source:
patches/gcc-4.0.3-mips_tls-1.patch@
4af05f3
Last change on this file since 4af05f3 was 69cde8d, checked in by , 19 years ago | |
---|---|
|
|
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 61 61 An UNSPEC wrapper around a function's address. It represents the 62 62 offset of _gp from the start of the function. 63 63 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 64 75 SYMBOL_64_HIGH 65 76 For a 64-bit symbolic address X, this is the value of 66 77 (%highest(X) << 16) + %higher(X). … … 82 93 SYMBOL_GOTOFF_GLOBAL, 83 94 SYMBOL_GOTOFF_CALL, 84 95 SYMBOL_GOTOFF_LOADGP, 96 SYMBOL_TLS, 97 SYMBOL_TLSGD, 98 SYMBOL_TLSLDM, 99 SYMBOL_DTPREL, 100 SYMBOL_GOTTPREL, 101 SYMBOL_TPREL, 85 102 SYMBOL_64_HIGH, 86 103 SYMBOL_64_MID, 87 104 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 236 236 static bool mips_symbolic_address_p (enum mips_symbol_type, enum machine_mode); 237 237 static bool mips_classify_address (struct mips_address_info *, rtx, 238 238 enum machine_mode, int); 239 static bool mips_cannot_force_const_mem (rtx); 239 240 static int mips_symbol_insns (enum mips_symbol_type); 240 241 static bool mips16_unextended_reference_p (enum machine_mode mode, rtx, rtx); 241 242 static rtx mips_force_temporary (rtx, rtx); … … 601 602 /* Map hard register number to register class */ 602 603 const enum reg_class mips_regno_to_class[] = 603 604 { 604 LEA_REGS, LEA_REGS, M16_NA_REGS, M16_NA_REGS,605 LEA_REGS, LEA_REGS, M16_NA_REGS, V1_REG, 605 606 M16_REGS, M16_REGS, M16_REGS, M16_REGS, 606 607 LEA_REGS, LEA_REGS, LEA_REGS, LEA_REGS, 607 608 LEA_REGS, LEA_REGS, LEA_REGS, LEA_REGS, … … 817 818 #undef TARGET_EXPAND_BUILTIN 818 819 #define TARGET_EXPAND_BUILTIN mips_expand_builtin 819 820 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 820 827 struct gcc_target targetm = TARGET_INITIALIZER; 821 828 822 829 -
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 1714 1714 T_REG, /* mips16 T register ($24) */ 1715 1715 M16_T_REGS, /* mips16 registers plus T register */ 1716 1716 PIC_FN_ADDR_REG, /* SVR4 PIC function address register */ 1717 V1_REG, /* Register $v1 ($3) used for TLS access. */ 1717 1718 LEA_REGS, /* Every GPR except $25 */ 1718 1719 GR_REGS, /* integer registers */ 1719 1720 FP_REGS, /* floating point registers */ … … 1752 1753 "T_REG", \ 1753 1754 "M16_T_REGS", \ 1754 1755 "PIC_FN_ADDR_REG", \ 1756 "V1_REG", \ 1755 1757 "LEA_REGS", \ 1756 1758 "GR_REGS", \ 1757 1759 "FP_REGS", \ … … 1793 1795 { 0x01000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* mips16 T register */ \ 1794 1796 { 0x010300fc, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* mips16 and T regs */ \ 1795 1797 { 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 */ \ 1797 1800 { 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* integer registers */ \ 1798 1801 { 0x00000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* floating registers*/ \ 1799 1802 { 0x00000000, 0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000000 }, /* hi register */ \ … … 1849 1852 #define GR_REG_CLASS_P(CLASS) \ 1850 1853 ((CLASS) == GR_REGS || (CLASS) == M16_REGS || (CLASS) == T_REG \ 1851 1854 || (CLASS) == M16_T_REGS || (CLASS) == M16_NA_REGS \ 1855 || (CLASS) == V1_REG \ 1852 1856 || (CLASS) == PIC_FN_ADDR_REG || (CLASS) == LEA_REGS) 1853 1857 1854 1858 /* This macro is also used later on in the file. */ … … 1896 1900 'f' Floating point registers 1897 1901 'h' Hi register 1898 1902 'l' Lo register 1903 'v' $v1 only 1899 1904 'x' Multiply/divide registers 1900 1905 'z' FP Status register 1901 1906 'B' Cop0 register … … 3017 3022 " TEXT_SECTION_ASM_OP); 3018 3023 #endif 3019 3024 #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 45 45 (UNSPEC_LOAD_GOT 24) 46 46 (UNSPEC_GP 25) 47 47 (UNSPEC_MFHILO 26) 48 (UNSPEC_TLS_LDM 27) 49 (UNSPEC_TLS_GET_TP 28) 48 50 49 51 (UNSPEC_ADDRESS_FIRST 100) 50 52 … … 3027 3029 ;; We could use MEMs, but an unspec gives more optimization 3028 3030 ;; opportunities. 3029 3031 3030 (define_insn " *load_got<mode>"3032 (define_insn "load_got<mode>" 3031 3033 [(set (match_operand:P 0 "register_operand" "=d") 3032 3034 (unspec:P [(match_operand:P 1 "register_operand" "d") 3033 3035 (match_operand:P 2 "immediate_operand" "")] 3034 3036 UNSPEC_LOAD_GOT))] 3035 " TARGET_ABICALLS"3037 "" 3036 3038 "<load>\t%0,%R2(%1)" 3037 3039 [(set_attr "type" "load") 3038 3040 (set_attr "mode" "<MODE>") … … 5296 5298 [(match_dup 0)] 5297 5299 { operands[0] = mips_rewrite_small_data (operands[0]); }) 5298 5300 5299 5301 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 5300 5321 5301 5322 ; 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 13779 13779 tls_first_minor=13 13780 13780 tls_as_opt=--fatal-warnings 13781 13781 ;; 13782 mips*-*-*) 13783 conftest_s=' 13784 .section .tdata,"awT",@progbits 13785 x: 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 ;; 13782 13799 powerpc-*-*) 13783 13800 conftest_s=' 13784 13801 .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 2349 2349 tls_first_minor=13 2350 2350 tls_as_opt=--fatal-warnings 2351 2351 ;; 2352 mips*-*-*) 2353 conftest_s=' 2354 .section .tdata,"awT",@progbits 2355 x: 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 ;; 2352 2369 powerpc-*-*) 2353 2370 conftest_s=' 2354 2371 .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 6 int * __attribute__((noinline)) 7 foo (void) 8 { 9 return &x[1]; 10 } 11 12 int main (void) 13 { 14 return *foo (); 15 }
Note:
See TracBrowser
for help on using the repository browser.