aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorRandolph Chung <tausq@debian.org>2005-07-06 02:18:21 +0000
committerJohn David Anglin <danglin@gcc.gnu.org>2005-07-06 02:18:21 +0000
commit51076f9604483f4f1b4dc16a90871384c1fd15cc (patch)
treeb033984f316da7a67bfe1fa08ed4aedef89780e8 /gcc
parentf04f1d2c6305eea31102357d0b2aa7ab95ece2fb (diff)
downloadgcc-51076f9604483f4f1b4dc16a90871384c1fd15cc.zip
gcc-51076f9604483f4f1b4dc16a90871384c1fd15cc.tar.gz
gcc-51076f9604483f4f1b4dc16a90871384c1fd15cc.tar.bz2
configure.ac (hppa*-*-linux*): Check for a TLS capable gas.
* 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 From-SVN: r101648
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog26
-rw-r--r--gcc/config/pa/pa-protos.h2
-rw-r--r--gcc/config/pa/pa.c125
-rw-r--r--gcc/config/pa/pa.h12
-rw-r--r--gcc/config/pa/pa.md87
-rw-r--r--gcc/config/pa/predicates.md30
-rwxr-xr-xgcc/configure29
-rw-r--r--gcc/configure.ac29
8 files changed, 335 insertions, 5 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index b7d8723..d398a7f 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 031087b..3bc4c30 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 969da83..7eb1956 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 b20a1b7..b9a5394 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 f724209..83fdec6 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 7fd1ee6..b383569 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 79ed496b..3611276 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 0a66cdf..f2d631b 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