OSDN Git Service

* configure.ac (hppa*-*-linux*: Check for a TLS capable gas.
authordanglin <danglin@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 6 Jul 2005 02:18:21 +0000 (02:18 +0000)
committerdanglin <danglin@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 6 Jul 2005 02:18:21 +0000 (02:18 +0000)
* 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

gcc/ChangeLog
gcc/config/pa/pa-protos.h
gcc/config/pa/pa.c
gcc/config/pa/pa.h
gcc/config/pa/pa.md
gcc/config/pa/predicates.md
gcc/configure
gcc/configure.ac

index b7d8723..d398a7f 100644 (file)
@@ -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.
index 031087b..3bc4c30 100644 (file)
@@ -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);
index 969da83..7eb1956 100644 (file)
@@ -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;
 \f
 /* 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;
index b20a1b7..b9a5394 100644 (file)
@@ -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
index f724209..83fdec6 100644 (file)
   [(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")])
index 7fd1ee6..b383569 100644 (file)
   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:
   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
index 79ed496..3611276 100755 (executable)
@@ -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
index 0a66cdf..f2d631b 100644 (file)
@@ -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