diff options
author | danglin <danglin@138bc75d-0d04-0410-961f-82ee72b054a4> | 2005-07-06 02:18:21 +0000 |
---|---|---|
committer | danglin <danglin@138bc75d-0d04-0410-961f-82ee72b054a4> | 2005-07-06 02:18:21 +0000 |
commit | 716b2c5a2b6f76743107e21661ece492f54505fb (patch) | |
tree | b033984f316da7a67bfe1fa08ed4aedef89780e8 | |
parent | 11e66330dc317e0b2db05c43677ae3ac98a8c677 (diff) | |
download | gcc-716b2c5a2b6f76743107e21661ece492f54505fb.tar.gz |
* configure.ac (hppa*-*-linux*: Check for a TLS capable gas.
* configure: Regenerate.
* config/pa/pa-protos.h (tls_symbolic_operand): Declare.
(pa_tls_referenced_p): Declare.
* config/pa/pa.c (legitimize_pic_address): Reject TLS operands.
(gen_tls_tga, gen_tls_get_addr, hppa_tls_call): New.
(legitimize_tls_address): New.
(hppa_legitimize_address): Handle TLS addresses.
(pa_tls_symbol_ref_1, pa_tls_referenced_p): New.
(TARGET_CANNOT_FORCE_CONST_MEM): Define.
(emit_move_sequence): Handle TLS addresses.
(pa_encode_section_info): Call default handler to handle common
sections.
* config/pa/pa.h (PA_SYMBOL_REF_TLS_P): New.
(CONSTANT_ADDRESS_P): Reject TLS operands.
(TARGET_HAVE_TLS) [HAVE_AS_TLS]: Define.
* config/pa/pa.md (UNSPEC_TP, UNSPEC_TLSGD, UNSPEC_TLSLDM)
(UNSPEC_TLSLDO, UNSPEC_TLSLDBASE, UNSPEC_TLSIE)
(UNSPEC_TLSLE): Define new constants.
(tgd_load, tld_load, tld_offset_load, tp_load, tie_load, tle_load): New.
* config/pa/predicates.md (symbolic_operand): Reject TLS operands.
(tls_symbolic_operand, tgd_symbolic_operand, tld_symbolic_operand)
(tie_symbolic_operand, tle_symbolic_operand): New
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@101648 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r-- | gcc/ChangeLog | 26 | ||||
-rw-r--r-- | gcc/config/pa/pa-protos.h | 2 | ||||
-rw-r--r-- | gcc/config/pa/pa.c | 125 | ||||
-rw-r--r-- | gcc/config/pa/pa.h | 12 | ||||
-rw-r--r-- | gcc/config/pa/pa.md | 87 | ||||
-rw-r--r-- | gcc/config/pa/predicates.md | 30 | ||||
-rwxr-xr-x | gcc/configure | 29 | ||||
-rw-r--r-- | gcc/configure.ac | 29 |
8 files changed, 335 insertions, 5 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index b7d872370e6..d398a7fdde4 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,29 @@ +2005-07-05 Randolph Chung <tausq@debian.org> + + * configure.ac (hppa*-*-linux*: Check for a TLS capable gas. + * configure: Regenerate. + * config/pa/pa-protos.h (tls_symbolic_operand): Declare. + (pa_tls_referenced_p): Declare. + * config/pa/pa.c (legitimize_pic_address): Reject TLS operands. + (gen_tls_tga, gen_tls_get_addr, hppa_tls_call): New. + (legitimize_tls_address): New. + (hppa_legitimize_address): Handle TLS addresses. + (pa_tls_symbol_ref_1, pa_tls_referenced_p): New. + (TARGET_CANNOT_FORCE_CONST_MEM): Define. + (emit_move_sequence): Handle TLS addresses. + (pa_encode_section_info): Call default handler to handle common + sections. + * config/pa/pa.h (PA_SYMBOL_REF_TLS_P): New. + (CONSTANT_ADDRESS_P): Reject TLS operands. + (TARGET_HAVE_TLS) [HAVE_AS_TLS]: Define. + * config/pa/pa.md (UNSPEC_TP, UNSPEC_TLSGD, UNSPEC_TLSLDM) + (UNSPEC_TLSLDO, UNSPEC_TLSLDBASE, UNSPEC_TLSIE) + (UNSPEC_TLSLE): Define new constants. + (tgd_load, tld_load, tld_offset_load, tp_load, tie_load, tle_load): New. + * config/pa/predicates.md (symbolic_operand): Reject TLS operands. + (tls_symbolic_operand, tgd_symbolic_operand, tld_symbolic_operand) + (tie_symbolic_operand, tle_symbolic_operand): New + 2005-07-06 Kelley Cook <kcook@gcc.gnu.org> * aclocal.m4: Update macros for autoconf 2.59 style. diff --git a/gcc/config/pa/pa-protos.h b/gcc/config/pa/pa-protos.h index 031087ba718..3bc4c309585 100644 --- a/gcc/config/pa/pa-protos.h +++ b/gcc/config/pa/pa-protos.h @@ -22,6 +22,7 @@ Boston, MA 02110-1301, USA. */ #ifdef RTX_CODE /* Prototype function used in various macros. */ extern int symbolic_operand (rtx, enum machine_mode); +extern int tls_symbolic_operand (rtx); /* Used in insn-*.c. */ extern int following_call (rtx); @@ -67,6 +68,7 @@ extern int adddi3_operand (rtx, enum machine_mode); extern int indexed_memory_operand (rtx, enum machine_mode); extern int symbolic_expression_p (rtx); extern int symbolic_memory_operand (rtx, enum machine_mode); +extern bool pa_tls_referenced_p (rtx); extern int pa_adjust_insn_length (rtx, int); extern int int11_operand (rtx, enum machine_mode); extern int reg_or_cint_move_operand (rtx, enum machine_mode); diff --git a/gcc/config/pa/pa.c b/gcc/config/pa/pa.c index 969da837a01..7eb19569055 100644 --- a/gcc/config/pa/pa.c +++ b/gcc/config/pa/pa.c @@ -292,6 +292,9 @@ static size_t n_deferred_plabels = 0; #undef TARGET_SCALAR_MODE_SUPPORTED_P #define TARGET_SCALAR_MODE_SUPPORTED_P pa_scalar_mode_supported_p +#undef TARGET_CANNOT_FORCE_CONST_MEM +#define TARGET_CANNOT_FORCE_CONST_MEM pa_tls_referenced_p + struct gcc_target targetm = TARGET_INITIALIZER; /* Parse the -mfixed-range= option string. */ @@ -595,6 +598,9 @@ legitimize_pic_address (rtx orig, enum machine_mode mode, rtx reg) { rtx pic_ref = orig; + if (PA_SYMBOL_REF_TLS_P (orig)) + abort(); + /* Labels need special handling. */ if (pic_label_operand (orig, mode)) { @@ -671,6 +677,80 @@ legitimize_pic_address (rtx orig, enum machine_mode mode, rtx reg) return pic_ref; } +static GTY(()) rtx gen_tls_tga; + +static rtx +gen_tls_get_addr (void) +{ + if (!gen_tls_tga) + gen_tls_tga = init_one_libfunc ("__tls_get_addr"); + return gen_tls_tga; +} + +static rtx +hppa_tls_call (rtx arg) +{ + rtx ret; + + ret = gen_reg_rtx (Pmode); + emit_library_call_value (gen_tls_get_addr (), ret, + LCT_CONST, Pmode, 1, arg, Pmode); + + return ret; +} + +static rtx +legitimize_tls_address (rtx addr) +{ + rtx ret, insn, tmp, t1, t2, tp; + enum tls_model model = SYMBOL_REF_TLS_MODEL (addr); + + switch (model) + { + case TLS_MODEL_GLOBAL_DYNAMIC: + tmp = gen_reg_rtx (Pmode); + emit_insn (gen_tgd_load (tmp, addr)); + ret = hppa_tls_call (tmp); + break; + + case TLS_MODEL_LOCAL_DYNAMIC: + ret = gen_reg_rtx (Pmode); + tmp = gen_reg_rtx (Pmode); + start_sequence (); + emit_insn (gen_tld_load (tmp, addr)); + t1 = hppa_tls_call (tmp); + insn = get_insns (); + end_sequence (); + t2 = gen_reg_rtx (Pmode); + emit_libcall_block (insn, t2, t1, + gen_rtx_UNSPEC (Pmode, gen_rtvec (1, const0_rtx), + UNSPEC_TLSLDBASE)); + emit_insn (gen_tld_offset_load (ret, addr, t2)); + break; + + case TLS_MODEL_INITIAL_EXEC: + tp = gen_reg_rtx (Pmode); + tmp = gen_reg_rtx (Pmode); + ret = gen_reg_rtx (Pmode); + emit_insn (gen_tp_load (tp)); + emit_insn (gen_tie_load (tmp, addr)); + emit_move_insn (ret, gen_rtx_PLUS (Pmode, tp, tmp)); + break; + + case TLS_MODEL_LOCAL_EXEC: + tp = gen_reg_rtx (Pmode); + ret = gen_reg_rtx (Pmode); + emit_insn (gen_tp_load (tp)); + emit_insn (gen_tle_load (ret, addr, tp)); + break; + + default: + abort(); + } + + return ret; +} + /* Try machine-dependent ways of modifying an illegitimate address to be legitimate. If we find one, return the new, valid address. This macro is used in only one place: `memory_address' in explow.c. @@ -740,7 +820,9 @@ hppa_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED, && !REG_POINTER (XEXP (x, 1))) return gen_rtx_PLUS (Pmode, XEXP (x, 1), XEXP (x, 0)); - if (flag_pic) + if (PA_SYMBOL_REF_TLS_P (x)) + return legitimize_tls_address (x); + else if (flag_pic) return legitimize_pic_address (x, mode, gen_reg_rtx (Pmode)); /* Strip off CONST. */ @@ -1190,6 +1272,25 @@ force_mode (enum machine_mode mode, rtx orig) return gen_rtx_REG (mode, REGNO (orig)); } +/* Return 1 if *X is a thread-local symbol. */ + +static int +pa_tls_symbol_ref_1 (rtx *x, void *data ATTRIBUTE_UNUSED) +{ + return PA_SYMBOL_REF_TLS_P (*x); +} + +/* Return 1 if X contains a thread-local symbol. */ + +bool +pa_tls_referenced_p (rtx x) +{ + if (!TARGET_HAVE_TLS) + return false; + + return for_each_rtx (&x, &pa_tls_symbol_ref_1, 0); +} + /* Emit insns to move operands[1] into operands[0]. Return 1 if we have written out everything that needs to be done to @@ -1707,6 +1808,26 @@ emit_move_sequence (rtx *operands, enum machine_mode mode, rtx scratch_reg) } return 1; } + else if (pa_tls_referenced_p (operand1)) + { + rtx tmp = operand1; + rtx addend = NULL; + + if (GET_CODE (tmp) == CONST && GET_CODE (XEXP (tmp, 0)) == PLUS) + { + addend = XEXP (XEXP (tmp, 0), 1); + tmp = XEXP (XEXP (tmp, 0), 0); + } + + gcc_assert (GET_CODE (tmp) == SYMBOL_REF); + tmp = legitimize_tls_address (tmp); + if (addend) + { + tmp = gen_rtx_PLUS (mode, tmp, addend); + tmp = force_operand (tmp, operands[0]); + } + operands[1] = tmp; + } else if (GET_CODE (operand1) != CONST_INT || !cint_ok_for_move (INTVAL (operand1))) { @@ -7371,6 +7492,8 @@ hppa_encode_label (rtx sym) static void pa_encode_section_info (tree decl, rtx rtl, int first) { + default_encode_section_info (decl, rtl, first); + if (first && TEXT_SPACE_P (decl)) { SYMBOL_REF_FLAG (XEXP (rtl, 0)) = 1; diff --git a/gcc/config/pa/pa.h b/gcc/config/pa/pa.h index b20a1b7bcaa..b9a5394af0f 100644 --- a/gcc/config/pa/pa.h +++ b/gcc/config/pa/pa.h @@ -1003,13 +1003,18 @@ extern int may_call_alloca; #define MAX_REGS_PER_ADDRESS 2 +/* Non-TLS symbolic references. */ +#define PA_SYMBOL_REF_TLS_P(RTX) \ + (GET_CODE (RTX) == SYMBOL_REF && SYMBOL_REF_TLS_MODEL (RTX) != 0) + /* Recognize any constant value that is a valid address except for symbolic addresses. We get better CSE by rejecting them here and allowing hppa_legitimize_address to break them up. We use most of the constants accepted by CONSTANT_P, except CONST_DOUBLE. */ #define CONSTANT_ADDRESS_P(X) \ - ((GET_CODE (X) == LABEL_REF || GET_CODE (X) == SYMBOL_REF \ + ((GET_CODE (X) == LABEL_REF \ + || (GET_CODE (X) == SYMBOL_REF && !SYMBOL_REF_TLS_MODEL (X)) \ || GET_CODE (X) == CONST_INT || GET_CODE (X) == CONST \ || GET_CODE (X) == HIGH) \ && (reload_in_progress || reload_completed || ! symbolic_expression_p (X))) @@ -1919,3 +1924,8 @@ forget_section (void) \ /* We need a libcall to canonicalize function pointers on TARGET_ELF32. */ #define CANONICALIZE_FUNCPTR_FOR_COMPARE_LIBCALL \ "__canonicalize_funcptr_for_compare" + +#ifdef HAVE_AS_TLS +#undef TARGET_HAVE_TLS +#define TARGET_HAVE_TLS true +#endif diff --git a/gcc/config/pa/pa.md b/gcc/config/pa/pa.md index f724209c1e9..83fdec6066a 100644 --- a/gcc/config/pa/pa.md +++ b/gcc/config/pa/pa.md @@ -32,6 +32,13 @@ [(UNSPEC_CFFC 0) ; canonicalize_funcptr_for_compare (UNSPEC_GOTO 1) ; indirect_goto (UNSPEC_DLTIND14R 2) ; + (UNSPEC_TP 3) + (UNSPEC_TLSGD 4) + (UNSPEC_TLSLDM 5) + (UNSPEC_TLSLDO 6) + (UNSPEC_TLSLDBASE 7) + (UNSPEC_TLSIE 8) + (UNSPEC_TLSLE 9) ]) ;; UNSPEC_VOLATILE: @@ -9347,3 +9354,83 @@ add,l %2,%3,%3\;bv,n %%r0(%3)" } [(set_attr "type" "load") (set_attr "length" "4")]) + + +;; TLS Support +(define_insn "tgd_load" + [(set (match_operand:SI 0 "register_operand" "=r") + (unspec:SI [(match_operand 1 "tgd_symbolic_operand" "")] UNSPEC_TLSGD)) + (clobber (reg:SI 1))] + "" + "* +{ + if (flag_pic) + return \"addil LT'%1-$tls_gdidx$,%%r19\;ldo RT'%1-$tls_gdidx$(%%r1),%0\"; + else + return \"addil LR'%1-$tls_gdidx$,%%r27\;ldo RR'%1-$tls_gdidx$(%%r1),%0\"; +}" + [(set_attr "type" "multi") + (set_attr "length" "8")]) + +(define_insn "tld_load" + [(set (match_operand:SI 0 "register_operand" "=r") + (unspec:SI [(match_operand 1 "tld_symbolic_operand" "")] UNSPEC_TLSLDM)) + (clobber (reg:SI 1))] + "" + "* +{ + if (flag_pic) + return \"addil LT'%1-$tls_ldidx$,%%r19\;ldo RT'%1-$tls_ldidx$(%%r1),%0\"; + else + return \"addil LR'%1-$tls_ldidx$,%%r27\;ldo RR'%1-$tls_ldidx$(%%r1),%0\"; +}" + [(set_attr "type" "multi") + (set_attr "length" "8")]) + +(define_insn "tld_offset_load" + [(set (match_operand:SI 0 "register_operand" "=r") + (plus:SI (unspec:SI [(match_operand 1 "tld_symbolic_operand" "")] + UNSPEC_TLSLDO) + (match_operand:SI 2 "register_operand" "r"))) + (clobber (reg:SI 1))] + "" + "* +{ + return \"addil LR'%1-$tls_dtpoff$,%2\;ldo RR'%1-$tls_dtpoff$(%%r1),%0\"; +}" + [(set_attr "type" "multi") + (set_attr "length" "8")]) + +(define_insn "tp_load" + [(set (match_operand:SI 0 "register_operand" "=r") + (unspec:SI [(const_int 0)] UNSPEC_TP))] + "" + "{mfctl|mfctl,w} %%cr27,%0" + [(set_attr "type" "multi") + (set_attr "length" "4")]) + +(define_insn "tie_load" + [(set (match_operand:SI 0 "register_operand" "=r") + (unspec:SI [(match_operand 1 "tie_symbolic_operand" "")] UNSPEC_TLSIE)) + (clobber (reg:SI 1))] + "" + "* +{ + if (flag_pic) + return \"addil LT'%1-$tls_ieoff$,%%r19\;ldw RT'%1-$tls_ieoff$(%%r1),%0\"; + else + return \"addil LR'%1-$tls_ieoff$,%%r27\;ldw RR'%1-$tls_ieoff$(%%r1),%0\"; +}" + [(set_attr "type" "multi") + (set_attr "length" "8")]) + +(define_insn "tle_load" + [(set (match_operand:SI 0 "register_operand" "=r") + (plus:SI (unspec:SI [(match_operand 1 "tle_symbolic_operand" "")] + UNSPEC_TLSLE) + (match_operand:SI 2 "register_operand" "r"))) + (clobber (reg:SI 1))] + "" + "addil LR'%1-$tls_leoff$,%2\;ldo RR'%1-$tls_leoff$(%%r1),%0" + [(set_attr "type" "multi") + (set_attr "length" "8")]) diff --git a/gcc/config/pa/predicates.md b/gcc/config/pa/predicates.md index 7fd1ee615e1..b3835699a8e 100644 --- a/gcc/config/pa/predicates.md +++ b/gcc/config/pa/predicates.md @@ -68,11 +68,13 @@ switch (GET_CODE (op)) { case SYMBOL_REF: + return !SYMBOL_REF_TLS_MODEL (op); case LABEL_REF: return 1; case CONST: op = XEXP (op, 0); - return ((GET_CODE (XEXP (op, 0)) == SYMBOL_REF + return (((GET_CODE (XEXP (op, 0)) == SYMBOL_REF + && !SYMBOL_REF_TLS_MODEL (XEXP (op, 0))) || GET_CODE (XEXP (op, 0)) == LABEL_REF) && GET_CODE (XEXP (op, 1)) == CONST_INT); default: @@ -91,10 +93,32 @@ if (GET_CODE (op) != MEM) return 0; op = XEXP (op, 0); - return (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == CONST - || GET_CODE (op) == HIGH || GET_CODE (op) == LABEL_REF); + return ((GET_CODE (op) == SYMBOL_REF && !SYMBOL_REF_TLS_MODEL (op)) + || GET_CODE (op) == CONST || GET_CODE (op) == HIGH + || GET_CODE (op) == LABEL_REF); }) +;; Return true if OP is a symbolic operand for the TLS Global Dynamic model. +(define_predicate "tgd_symbolic_operand" + (and (match_code "symbol_ref") + (match_test "SYMBOL_REF_TLS_MODEL (op) == TLS_MODEL_GLOBAL_DYNAMIC"))) + +;; Return true if OP is a symbolic operand for the TLS Local Dynamic model. +(define_predicate "tld_symbolic_operand" + (and (match_code "symbol_ref") + (match_test "SYMBOL_REF_TLS_MODEL (op) == TLS_MODEL_LOCAL_DYNAMIC"))) + +;; Return true if OP is a symbolic operand for the TLS Initial Exec model. +(define_predicate "tie_symbolic_operand" + (and (match_code "symbol_ref") + (match_test "SYMBOL_REF_TLS_MODEL (op) == TLS_MODEL_INITIAL_EXEC"))) + +;; Return true if OP is a symbolic operand for the TLS Local Exec model. +(define_predicate "tle_symbolic_operand" + (and (match_code "symbol_ref") + (match_test "SYMBOL_REF_TLS_MODEL (op) == TLS_MODEL_LOCAL_EXEC"))) + + ;; Return 1 if the operand is a register operand or a non-symbolic ;; memory operand after reload. This predicate is used for branch ;; patterns that internally handle register reloading. We need to diff --git a/gcc/configure b/gcc/configure index 79ed496b99d..36112760c9b 100755 --- a/gcc/configure +++ b/gcc/configure @@ -14015,6 +14015,35 @@ x: .long 25 tls_first_major=2 tls_first_minor=14 ;; + hppa*-*-linux*) + conftest_s=' +t1: .reg %r20 +t2: .reg %r21 +gp: .reg %r19 + .section ".tdata","awT",@progbits +foo: .long 25 + .text + .align 4 + addil LT%foo-$tls_gdidx$,gp + ldo RT%foo-$tls_gdidx$(%r1),%arg0 + b __tls_get_addr + nop + addil LT%foo-$tls_ldidx$,gp + b __tls_get_addr + ldo RT%foo-$tls_ldidx$(%r1),%arg0 + addil LR%foo-$tls_dtpoff$,%ret0 + ldo RR%foo-$tls_dtpoff$(%r1),%t1 + mfctl %cr27,%t1 + addil LT%foo-$tls_ieoff$,gp + ldw RT%foo-$tls_ieoff$(%r1),%t2 + add %t1,%t2,%t3 + mfctl %cr27,%t1 + addil LR%foo-$tls_leoff$,%t1 + ldo RR%foo-$tls_leoff$(%r1),%t2' + tls_first_major=2 + tls_first_minor=15 + tls_as_opt=--fatal-warnings + ;; i[34567]86-*-*) conftest_s=' .section ".tdata","awT",@progbits diff --git a/gcc/configure.ac b/gcc/configure.ac index 0a66cdf8949..f2d631b4c7c 100644 --- a/gcc/configure.ac +++ b/gcc/configure.ac @@ -2189,6 +2189,35 @@ x: .long 25 tls_first_major=2 tls_first_minor=14 ;; + hppa*-*-linux*) + conftest_s=' +t1: .reg %r20 +t2: .reg %r21 +gp: .reg %r19 + .section ".tdata","awT",@progbits +foo: .long 25 + .text + .align 4 + addil LT%foo-$tls_gdidx$,gp + ldo RT%foo-$tls_gdidx$(%r1),%arg0 + b __tls_get_addr + nop + addil LT%foo-$tls_ldidx$,gp + b __tls_get_addr + ldo RT%foo-$tls_ldidx$(%r1),%arg0 + addil LR%foo-$tls_dtpoff$,%ret0 + ldo RR%foo-$tls_dtpoff$(%r1),%t1 + mfctl %cr27,%t1 + addil LT%foo-$tls_ieoff$,gp + ldw RT%foo-$tls_ieoff$(%r1),%t2 + add %t1,%t2,%t3 + mfctl %cr27,%t1 + addil LR%foo-$tls_leoff$,%t1 + ldo RR%foo-$tls_leoff$(%r1),%t2' + tls_first_major=2 + tls_first_minor=15 + tls_as_opt=--fatal-warnings + ;; i[34567]86-*-*) conftest_s=' .section ".tdata","awT",@progbits |