source: patches/gcc-4.0.3-mips_tls-1.patch @ 69cde8d

clfs-1.2clfs-2.1clfs-3.0.0-systemdclfs-3.0.0-sysvinitsystemdsysvinit
Last change on this file since 69cde8d was 69cde8d, checked in by Jim Gifford <clfs@…>, 18 years ago

Added: All patches needed for the book.

  • Property mode set to 100644
File size: 16.2 KB
  • gcc/config/mips/mips-protos.h

    Submitted By: Jim Gifford (patches at jg555 dot com)
    Date: 2005-09-12
    Initial Package Version: 4.0.1
    Origin: Daniel Jacobowitz
    Upstream Status: GCC Dev Mailling lists
    Description: Adds support for TLS on MIPS
     
    diff -Naur gcc-4.0.1.orig/gcc/config/mips/mips-protos.h gcc-4.0.1/gcc/config/mips/mips-protos.h
    old new  
    6161       An UNSPEC wrapper around a function's address.  It represents the
    6262       offset of _gp from the start of the function.
    6363
     64   SYMBOL_TLS
     65       A thread-local symbol.
     66
     67   SYMBOL_TLSGD
     68   SYMBOL_TLSLDM
     69   SYMBOL_DTPREL
     70   SYMBOL_GOTTPREL
     71   SYMBOL_TPREL
     72       UNSPEC wrappers around SYMBOL_TLS, corresponding to the
     73       thread-local storage relocation operators.
     74
    6475   SYMBOL_64_HIGH
    6576       For a 64-bit symbolic address X, this is the value of
    6677       (%highest(X) << 16) + %higher(X).
     
    8293  SYMBOL_GOTOFF_GLOBAL,
    8394  SYMBOL_GOTOFF_CALL,
    8495  SYMBOL_GOTOFF_LOADGP,
     96  SYMBOL_TLS,
     97  SYMBOL_TLSGD,
     98  SYMBOL_TLSLDM,
     99  SYMBOL_DTPREL,
     100  SYMBOL_GOTTPREL,
     101  SYMBOL_TPREL,
    85102  SYMBOL_64_HIGH,
    86103  SYMBOL_64_MID,
    87104  SYMBOL_64_LOW
  • gcc/config/mips/mips.c

    diff -Naur gcc-4.0.1.orig/gcc/config/mips/mips.c gcc-4.0.1/gcc/config/mips/mips.c
    old new  
    236236static bool mips_symbolic_address_p (enum mips_symbol_type, enum machine_mode);
    237237static bool mips_classify_address (struct mips_address_info *, rtx,
    238238                                   enum machine_mode, int);
     239static bool mips_cannot_force_const_mem (rtx);
    239240static int mips_symbol_insns (enum mips_symbol_type);
    240241static bool mips16_unextended_reference_p (enum machine_mode mode, rtx, rtx);
    241242static rtx mips_force_temporary (rtx, rtx);
     
    601602/* Map hard register number to register class */
    602603const enum reg_class mips_regno_to_class[] =
    603604{
    604   LEA_REGS,     LEA_REGS,       M16_NA_REGS,    M16_NA_REGS,
     605  LEA_REGS,     LEA_REGS,       M16_NA_REGS,    V1_REG,
    605606  M16_REGS,     M16_REGS,       M16_REGS,       M16_REGS,
    606607  LEA_REGS,     LEA_REGS,       LEA_REGS,       LEA_REGS,
    607608  LEA_REGS,     LEA_REGS,       LEA_REGS,       LEA_REGS,
     
    817818#undef TARGET_EXPAND_BUILTIN
    818819#define TARGET_EXPAND_BUILTIN mips_expand_builtin
    819820
     821#undef TARGET_HAVE_TLS
     822#define TARGET_HAVE_TLS HAVE_AS_TLS
     823
     824#undef TARGET_CANNOT_FORCE_CONST_MEM
     825#define TARGET_CANNOT_FORCE_CONST_MEM mips_cannot_force_const_mem
     826
    820827struct gcc_target targetm = TARGET_INITIALIZER;
    821828
    822829
  • gcc/config/mips/mips.h

     /* Classify symbol X, which must be a SYMBOL_REF or a LABEL_REF.  */
    @@ -835,6 +842,9 @@
     
       gcc_assert (GET_CODE (x) == SYMBOL_REF);
     
    +  if (SYMBOL_REF_TLS_MODEL (x))
    +    return SYMBOL_TLS;
    +
       if (CONSTANT_POOL_ADDRESS_P (x))
         {
           if (TARGET_MIPS16)
    @@ -943,7 +953,11 @@
       if (UNSPEC_ADDRESS_P (x))
         *symbol_type = UNSPEC_ADDRESS_TYPE (x);
       else if (GET_CODE (x) == SYMBOL_REF || GET_CODE (x) == LABEL_REF)
    -    *symbol_type = mips_classify_symbol (x);
    +    {
    +      *symbol_type = mips_classify_symbol (x);
    +      if (*symbol_type == SYMBOL_TLS)
    +	return false;
    +    }
       else
         return false;
     
    @@ -993,6 +1007,12 @@
         case SYMBOL_GOTOFF_GLOBAL:
         case SYMBOL_GOTOFF_CALL:
         case SYMBOL_GOTOFF_LOADGP:
    +    case SYMBOL_TLSGD:
    +    case SYMBOL_TLSLDM:
    +    case SYMBOL_DTPREL:
    +    case SYMBOL_TPREL:
    +    case SYMBOL_GOTTPREL:
    +    case SYMBOL_TLS:
           return false;
         }
       gcc_unreachable ();
    @@ -1090,6 +1110,14 @@
           /* The address will have to be loaded from the GOT first.  */
           return false;
     
    +    case SYMBOL_TLSGD:
    +    case SYMBOL_TLSLDM:
    +    case SYMBOL_DTPREL:
    +    case SYMBOL_TPREL:
    +    case SYMBOL_GOTTPREL:
    +    case SYMBOL_TLS:
    +      return false;
    +
         case SYMBOL_GOTOFF_PAGE:
         case SYMBOL_GOTOFF_GLOBAL:
         case SYMBOL_GOTOFF_CALL:
    @@ -1102,6 +1130,33 @@
       gcc_unreachable ();
     }
     
    +/* Return true if X is a thread-local symbol.  */
    +
    +static bool
    +mips_tls_operand_p (rtx x)
    +{
    +  return GET_CODE (x) == SYMBOL_REF && SYMBOL_REF_TLS_MODEL (x) != 0;
    +}
    +
    +/* Return true if X can not be forced into a constant pool.  */
    +
    +static int
    +mips_tls_symbol_ref_1 (rtx *x, void *data ATTRIBUTE_UNUSED)
    +{
    +  return mips_tls_operand_p (*x);
    +}
    +
    +/* Return true if X can not be forced into a constant pool.  */
    +
    +static bool
    +mips_cannot_force_const_mem (rtx x)
    +{
    +  if (! TARGET_HAVE_TLS)
    +    return false;
    +
    +  return for_each_rtx (&x, &mips_tls_symbol_ref_1, 0);
    +}
    +
     
     /* Return true if X is a valid address for machine mode MODE.  If it is,
        fill in INFO appropriately.  STRICT is true if we should only accept
    @@ -1223,8 +1278,19 @@
         case SYMBOL_64_HIGH:
         case SYMBOL_64_MID:
         case SYMBOL_64_LOW:
    +    case SYMBOL_TLSGD:
    +    case SYMBOL_TLSLDM:
    +    case SYMBOL_DTPREL:
    +    case SYMBOL_GOTTPREL:
    +    case SYMBOL_TPREL:
           /* Check whether the offset is a 16- or 32-bit value.  */
           return mips_split_p[type] ? 2 : 1;
    +
    +    case SYMBOL_TLS:
    +      /* We don't treat a bare TLS symbol as a constant.  */
    +      return 0;
    +
    +      return 1;
         }
       gcc_unreachable ();
     }
    @@ -1521,6 +1587,114 @@
       return plus_constant (reg, offset);
     }
     
    +/* Emit a call to __tls_get_addr.  SYM is the TLS symbol we are
    +   referencing, and TYPE is the symbol type to use (either global
    +   dynamic or local dynamic).  V0 is an RTX for the return value
    +   location.  The entire insn sequence is returned.  */
    +
    +static GTY(()) rtx mips_tls_symbol;
    +
    +static rtx
    +mips_call_tls_get_addr (rtx sym, enum mips_symbol_type type, rtx v0)
    +{
    +  rtx insn, loc, tga, a0;
    +
    +  a0 = gen_rtx_REG (Pmode, GP_ARG_FIRST);
    +
    +  if (!mips_tls_symbol)
    +    mips_tls_symbol = init_one_libfunc ("__tls_get_addr");
    +
    +  loc = mips_unspec_address (sym, type);
    +
    +  start_sequence ();
    +
    +  emit_insn (gen_rtx_SET (Pmode, a0,
    +			  gen_rtx_LO_SUM (Pmode, pic_offset_table_rtx, loc)));
    +  tga = gen_rtx_MEM (Pmode, mips_tls_symbol);
    +  insn = emit_call_insn (gen_call_value (v0, tga, const0_rtx, const0_rtx));
    +  CONST_OR_PURE_CALL_P (insn) = 1;
    +  use_reg (&CALL_INSN_FUNCTION_USAGE (insn), v0);
    +  use_reg (&CALL_INSN_FUNCTION_USAGE (insn), a0);
    +  insn = get_insns ();
    +
    +  end_sequence ();
    +
    +  return insn;
    +}
    +
    +/* Generate the code to access LOC, a thread local SYMBOL_REF.  The
    +   return value will be a valid address and move_operand (either a REG
    +   or a LO_SUM).  */
    +
    +static rtx
    +mips_legitimize_tls_address (rtx loc)
    +{
    +  rtx dest, insn, v0, v1, tmp1, tmp2, eqv;
    +  enum tls_model model;
    +
    +  v0 = gen_rtx_REG (Pmode, GP_RETURN);
    +  v1 = gen_rtx_REG (Pmode, GP_RETURN + 1);
    +
    +  model = SYMBOL_REF_TLS_MODEL (loc);
    +
    +  switch (model)
    +    {
    +    case TLS_MODEL_GLOBAL_DYNAMIC:
    +      insn = mips_call_tls_get_addr (loc, SYMBOL_TLSGD, v0);
    +      dest = gen_reg_rtx (Pmode);
    +      emit_libcall_block (insn, dest, v0, loc);
    +      break;
    +
    +    case TLS_MODEL_LOCAL_DYNAMIC:
    +      insn = mips_call_tls_get_addr (loc, SYMBOL_TLSLDM, v0);
    +      tmp1 = gen_reg_rtx (Pmode);
    +
    +      /* Attach a unique REG_EQUIV, to allow the RTL optimizers to
    +	 share the LDM result with other LD model accesses.  */
    +      eqv = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, const0_rtx),
    +			    UNSPEC_TLS_LDM);
    +      emit_libcall_block (insn, tmp1, v0, eqv);
    +
    +      tmp2 = mips_unspec_offset_high (NULL, tmp1, loc, SYMBOL_DTPREL);
    +      dest = gen_rtx_LO_SUM (Pmode, tmp2,
    +			     mips_unspec_address (loc, SYMBOL_DTPREL));
    +      break;
    +
    +    case TLS_MODEL_INITIAL_EXEC:
    +      tmp1 = gen_reg_rtx (Pmode);
    +      tmp2 = mips_unspec_address (loc, SYMBOL_GOTTPREL);
    +      if (Pmode == DImode)
    +	{
    +	  emit_insn (gen_tls_get_tp_di (v1));
    +	  emit_insn (gen_load_gotdi (tmp1, pic_offset_table_rtx, tmp2));
    +	}
    +      else
    +	{
    +	  emit_insn (gen_tls_get_tp_si (v1));
    +	  emit_insn (gen_load_gotsi (tmp1, pic_offset_table_rtx, tmp2));
    +	}
    +      dest = gen_reg_rtx (Pmode);
    +      emit_insn (gen_add3_insn (dest, tmp1, v1));
    +      break;
    +
    +    case TLS_MODEL_LOCAL_EXEC:
    +
    +      if (Pmode == DImode)
    +	emit_insn (gen_tls_get_tp_di (v1));
    +      else
    +	emit_insn (gen_tls_get_tp_si (v1));
    +
    +      tmp1 = mips_unspec_offset_high (NULL, v1, loc, SYMBOL_TPREL);
    +      dest = gen_rtx_LO_SUM (Pmode, tmp1,
    +			     mips_unspec_address (loc, SYMBOL_TPREL));
    +      break;
    +
    +    default:
    +      abort ();
    +    }
    +
    +  return dest;
    +}
     
     /* This function is used to implement LEGITIMIZE_ADDRESS.  If *XLOC can
        be legitimized in a way that the generic machinery might not expect,
    @@ -1532,6 +1706,12 @@
     {
       enum mips_symbol_type symbol_type;
     
    +  if (mips_tls_operand_p (*xloc))
    +    {
    +      *xloc = mips_legitimize_tls_address (*xloc);
    +      return true;
    +    }
    +
       /* See if the address can split into a high part and a LO_SUM.  */
       if (mips_symbolic_constant_p (*xloc, &symbol_type)
           && mips_symbolic_address_p (symbol_type, mode)
    @@ -1707,6 +1887,12 @@
           return;
         }
     
    +  if (mips_tls_operand_p (src))
    +    {
    +      emit_move_insn (dest, mips_legitimize_tls_address (src));
    +      return;
    +    }
    +
       /* See if the symbol can be split.  For mips16, this is often worse than
          forcing it in the constant pool since it needs the single-register form
          of addiu or daddiu.  */
    @@ -4321,6 +4507,7 @@
     			     GR_REGS);
       mips_char_to_class['e'] = LEA_REGS;
       mips_char_to_class['j'] = PIC_FN_ADDR_REG;
    +  mips_char_to_class['v'] = V1_REG;
       mips_char_to_class['y'] = GR_REGS;
       mips_char_to_class['z'] = ST_REGS;
       mips_char_to_class['B'] = COP0_REGS;
    @@ -4509,6 +4696,22 @@
           mips_lo_relocs[SYMBOL_GOTOFF_LOADGP] = "%lo(%neg(%gp_rel(";
         }
     
    +  /* Thread-local relocation operators.  */
    +  mips_lo_relocs[SYMBOL_TLSGD] = "%tlsgd(";
    +  mips_lo_relocs[SYMBOL_TLSLDM] = "%tlsldm(";
    +  mips_split_p[SYMBOL_DTPREL] = 1;
    +  mips_hi_relocs[SYMBOL_DTPREL] = "%dtprel_hi(";
    +  mips_lo_relocs[SYMBOL_DTPREL] = "%dtprel_lo(";
    +  mips_lo_relocs[SYMBOL_GOTTPREL] = "%gottprel(";
    +  mips_split_p[SYMBOL_TPREL] = 1;
    +  mips_hi_relocs[SYMBOL_TPREL] = "%tprel_hi(";
    +  mips_lo_relocs[SYMBOL_TPREL] = "%tprel_lo(";
    +
    +  /* We don't have a thread pointer access instruction on MIPS16, or
    +     appropriate TLS relocations.  */
    +  if (TARGET_MIPS16)
    +    targetm.have_tls = false;
    +
       /* Default to working around R4000 errata only if the processor
          was selected explicitly.  */
       if ((target_flags_explicit & MASK_FIX_R4000) == 0
    diff -Naur gcc-4.0.1.orig/gcc/config/mips/mips.h gcc-4.0.1/gcc/config/mips/mips.h
    old new  
    17141714  T_REG,                        /* mips16 T register ($24) */
    17151715  M16_T_REGS,                   /* mips16 registers plus T register */
    17161716  PIC_FN_ADDR_REG,              /* SVR4 PIC function address register */
     1717  V1_REG,                       /* Register $v1 ($3) used for TLS access.  */
    17171718  LEA_REGS,                     /* Every GPR except $25 */
    17181719  GR_REGS,                      /* integer registers */
    17191720  FP_REGS,                      /* floating point registers */
     
    17521753  "T_REG",                                                              \
    17531754  "M16_T_REGS",                                                         \
    17541755  "PIC_FN_ADDR_REG",                                                    \
     1756  "V1_REG",                                                             \
    17551757  "LEA_REGS",                                                           \
    17561758  "GR_REGS",                                                            \
    17571759  "FP_REGS",                                                            \
     
    17931795  { 0x01000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },   /* mips16 T register */ \
    17941796  { 0x010300fc, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },   /* mips16 and T regs */ \
    17951797  { 0x02000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },   /* SVR4 PIC function address register */ \
    1796   { 0xfdffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },   /* Every other GPR */   \
     1798  { 0x00000008, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },   /* only $v1 */ \
     1799  { 0xfdffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },   /* Every other GPR except $25 */   \
    17971800  { 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },   /* integer registers */ \
    17981801  { 0x00000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },   /* floating registers*/ \
    17991802  { 0x00000000, 0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000000 },   /* hi register */       \
     
    18491852#define GR_REG_CLASS_P(CLASS)                                           \
    18501853  ((CLASS) == GR_REGS || (CLASS) == M16_REGS || (CLASS) == T_REG        \
    18511854   || (CLASS) == M16_T_REGS || (CLASS) == M16_NA_REGS                   \
     1855   || (CLASS) == V1_REG                                                 \
    18521856   || (CLASS) == PIC_FN_ADDR_REG || (CLASS) == LEA_REGS)
    18531857
    18541858/* This macro is also used later on in the file.  */
     
    18961900   'f'  Floating point registers
    18971901   'h'  Hi register
    18981902   'l'  Lo register
     1903   'v'  $v1 only
    18991904   'x'  Multiply/divide registers
    19001905   'z'  FP Status register
    19011906   'B'  Cop0 register
     
    30173022        " TEXT_SECTION_ASM_OP);
    30183023#endif
    30193024#endif
     3025
     3026#ifndef HAVE_AS_TLS
     3027#define HAVE_AS_TLS 0
     3028#endif
  • gcc/config/mips/mips.md

    diff -Naur gcc-4.0.1.orig/gcc/config/mips/mips.md gcc-4.0.1/gcc/config/mips/mips.md
    old new  
    4545   (UNSPEC_LOAD_GOT             24)
    4646   (UNSPEC_GP                   25)
    4747   (UNSPEC_MFHILO               26)
     48   (UNSPEC_TLS_LDM              27)
     49   (UNSPEC_TLS_GET_TP           28)
    4850
    4951   (UNSPEC_ADDRESS_FIRST        100)
    5052
     
    30273029;; We could use MEMs, but an unspec gives more optimization
    30283030;; opportunities.
    30293031
    3030 (define_insn "*load_got<mode>"
     3032(define_insn "load_got<mode>"
    30313033  [(set (match_operand:P 0 "register_operand" "=d")
    30323034        (unspec:P [(match_operand:P 1 "register_operand" "d")
    30333035                   (match_operand:P 2 "immediate_operand" "")]
    30343036                  UNSPEC_LOAD_GOT))]
    3035   "TARGET_ABICALLS"
     3037  ""
    30363038  "<load>\t%0,%R2(%1)"
    30373039  [(set_attr "type" "load")
    30383040   (set_attr "mode" "<MODE>")
     
    52965298  [(match_dup 0)]
    52975299  { operands[0] = mips_rewrite_small_data (operands[0]); })
    52985300
    52995301
     5302; Thread-Local Storage
     5303
     5304; The TLS base pointer is acessed via "rdhwr $v1, $29".  No current
     5305; MIPS architecture defines this register, and no current
     5306; implementation provides it; instead, any OS which supports TLS is
     5307; expected to trap and emulate this instruction.  rdhwr is part of the
     5308; MIPS 32r2 specification, but we use it on any architecture because
     5309; we expect it to be emulated.  Use .set to force the assembler to
     5310; accept it.
     5311
     5312(define_insn "tls_get_tp_<mode>"
     5313  [(set (match_operand:P 0 "register_operand" "=v")
     5314        (unspec:P [(const_int 0)]
     5315                  UNSPEC_TLS_GET_TP))]
     5316  "HAVE_AS_TLS && !TARGET_MIPS16"
     5317  ".set\tpush\;.set\tmips32r2\t\;rdhwr\t%0,$29\;.set\tpop"
     5318  [(set_attr "type" "unknown")
     5319   (set_attr "mode" "<MODE>")])
     5320
    53005321
    53015322; The MIPS Paired-Single Floating Point and MIPS-3D Instructions.
  • gcc/configure

     
     (include "mips-ps-3d.md")
    diff -Naur gcc-4.0.1.orig/gcc/configure gcc-4.0.1/gcc/configure
    old new  
    1377913779        tls_first_minor=13
    1378013780        tls_as_opt=--fatal-warnings
    1378113781        ;;
     13782  mips*-*-*)
     13783    conftest_s='
     13784        .section .tdata,"awT",@progbits
     13785x:
     13786        .word 2
     13787        .text
     13788        addiu $4, $28, %tlsgd(x)
     13789        addiu $4, $28, %tlsldm(x)
     13790        lui $4, %dtprel_hi(x)
     13791        addiu $4, $4, %dtprel_lo(x)
     13792        lw $4, %gottprel(x)($28)
     13793        lui $4, %tprel_hi(x)
     13794        addiu $4, $4, %tprel_lo(x)'
     13795        tls_first_major=2
     13796        tls_first_minor=16
     13797        tls_as_opt='-32 --fatal-warnings'
     13798        ;;
    1378213799  powerpc-*-*)
    1378313800    conftest_s='
    1378413801        .section ".tdata","awT",@progbits
  • gcc/configure.ac

    diff -Naur gcc-4.0.1.orig/gcc/configure.ac gcc-4.0.1/gcc/configure.ac
    old new  
    23492349        tls_first_minor=13
    23502350        tls_as_opt=--fatal-warnings
    23512351        ;;
     2352  mips*-*-*)
     2353    conftest_s='
     2354        .section .tdata,"awT",@progbits
     2355x:
     2356        .word 2
     2357        .text
     2358        addiu $4, $28, %tlsgd(x)
     2359        addiu $4, $28, %tlsldm(x)
     2360        lui $4, %dtprel_hi(x)
     2361        addiu $4, $4, %dtprel_lo(x)
     2362        lw $4, %gottprel(x)($28)
     2363        lui $4, %tprel_hi(x)
     2364        addiu $4, $4, %tprel_lo(x)'
     2365        tls_first_major=2
     2366        tls_first_minor=16
     2367        tls_as_opt='-32 --fatal-warnings'
     2368        ;;
    23522369  powerpc-*-*)
    23532370    conftest_s='
    23542371        .section ".tdata","awT",@progbits
  • gcc/testsuite/gcc.dg/tls/offset-1.c

    diff -Naur gcc-4.0.1.orig/gcc/testsuite/gcc.dg/tls/offset-1.c gcc-4.0.1/gcc/testsuite/gcc.dg/tls/offset-1.c
    old new  
     1/* { dg-do link } */
     2/* Test that we do not emit a TLS reference into a constant pool.  */
     3
     4__thread int x[2];
     5
     6int * __attribute__((noinline))
     7foo (void)
     8{
     9  return &x[1];
     10}
     11
     12int main (void)
     13{
     14  return *foo ();
     15}
Note: See TracBrowser for help on using the repository browser.