OSDN Git Service

* configure.ac: Add HAVE_AS_TLS check for Xtensa.
authorbwilson <bwilson@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 19 Sep 2008 00:18:42 +0000 (00:18 +0000)
committerbwilson <bwilson@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 19 Sep 2008 00:18:42 +0000 (00:18 +0000)
* config/xtensa/predicates.md (tls_symbol_operand): New.
* config/xtensa/xtensa.c (TARGET_HAVE_TLS): Define.
(TARGET_CANNOT_FORCE_MEM): Define.
(xtensa_tls_symbol_p): New.
(xtensa_emit_move_sequence): Check for and legitimize TLS addresses.
(xtensa_legitimate_address_p): Disallow constant pool TLS references.
(xtensa_tls_module_base): New.
(xtensa_call_tls_desc): New.
(xtensa_legitimize_tls_address): New.
(xtensa_legitimize_address): Handle TLS symbols.
(xtensa_tls_referenced_p_1): New.
(xtensa_tls_referenced_p): New.
(xtensa_output_addr_const_extra): Handle UNSPEC_TPOFF and UNSPEC_DTPOFF.
(XTENSA_BUILTIN_THREAD_POINTER): New.
(XTENSA_BUILTIN_SET_THREAD_POINTER): New.
(xtensa_init_builtins): Set NOTHROW and READONLY for umulsidi3 builtin.
Add declarations for __builtin_thread_pointer and
__builtin_set_thread_pointer.
(xtensa_fold_builtin): Recognize new builtins.
(xtensa_expand_builtin): Expand new builtins.
* config/xtensa/xtensa.h (XCHAL_HAVE_THREADPTR): Define default value.
(TARGET_THREADPTR): Define.
(HAVE_AS_TLS): Define default value.
(LEGITIMATE_CONSTANT_P): Disallow TLS references.
* config/xtensa/xtensa.md (UNSPEC_TPOFF, UNSPEC_DTPOFF): New.
(UNSPEC_TLS_FUNC, UNSPEC_TLS_ARG, UNSPEC_TLS_CALL, UNSPEC_TP): New.
(UNSPECV_SET_TP): New.
(sym_TPOFF, sym_DTPOFF): New.
(load_tp, set_tp, tls_func, tls_arg, tls_call): New.
* config/xtensa/xtensa-protos.h (xtensa_tls_referenced_p): Declare.
* configure: Regenerated.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@140482 138bc75d-0d04-0410-961f-82ee72b054a4

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

index 37170cc..ac95774 100644 (file)
@@ -1,3 +1,38 @@
+2008-09-18  Bob Wilson  <bob.wilson@acm.org>
+
+       * configure.ac: Add HAVE_AS_TLS check for Xtensa.
+       * config/xtensa/predicates.md (tls_symbol_operand): New.
+       * config/xtensa/xtensa.c (TARGET_HAVE_TLS): Define.
+       (TARGET_CANNOT_FORCE_MEM): Define.
+       (xtensa_tls_symbol_p): New.
+       (xtensa_emit_move_sequence): Check for and legitimize TLS addresses.
+       (xtensa_legitimate_address_p): Disallow constant pool TLS references.
+       (xtensa_tls_module_base): New.
+       (xtensa_call_tls_desc): New.
+       (xtensa_legitimize_tls_address): New.
+       (xtensa_legitimize_address): Handle TLS symbols.
+       (xtensa_tls_referenced_p_1): New.
+       (xtensa_tls_referenced_p): New.
+       (xtensa_output_addr_const_extra): Handle UNSPEC_TPOFF and UNSPEC_DTPOFF.
+       (XTENSA_BUILTIN_THREAD_POINTER): New.
+       (XTENSA_BUILTIN_SET_THREAD_POINTER): New.
+       (xtensa_init_builtins): Set NOTHROW and READONLY for umulsidi3 builtin.
+       Add declarations for __builtin_thread_pointer and
+       __builtin_set_thread_pointer.
+       (xtensa_fold_builtin): Recognize new builtins.
+       (xtensa_expand_builtin): Expand new builtins.
+       * config/xtensa/xtensa.h (XCHAL_HAVE_THREADPTR): Define default value.
+       (TARGET_THREADPTR): Define.
+       (HAVE_AS_TLS): Define default value.
+       (LEGITIMATE_CONSTANT_P): Disallow TLS references.
+       * config/xtensa/xtensa.md (UNSPEC_TPOFF, UNSPEC_DTPOFF): New.
+       (UNSPEC_TLS_FUNC, UNSPEC_TLS_ARG, UNSPEC_TLS_CALL, UNSPEC_TP): New.
+       (UNSPECV_SET_TP): New.
+       (sym_TPOFF, sym_DTPOFF): New.
+       (load_tp, set_tp, tls_func, tls_arg, tls_call): New.
+       * config/xtensa/xtensa-protos.h (xtensa_tls_referenced_p): Declare.
+       * configure: Regenerated.
+       
 2008-09-18  H.J. Lu  <hongjiu.lu@intel.com>
 
        PR target/37394
index c96f637..2cb2a7d 100644 (file)
 
 (define_predicate "boolean_operator"
   (match_code "eq,ne"))
+
+(define_predicate "tls_symbol_operand"
+  (and (match_code "symbol_ref")
+       (match_test "SYMBOL_REF_TLS_MODEL (op) != 0")))
index 7ecde9b..0447fae 100644 (file)
@@ -56,6 +56,7 @@ extern char *xtensa_emit_movcc (bool, bool, bool, rtx *);
 extern char *xtensa_emit_call (int, rtx *);
 extern bool xtensa_legitimate_address_p (enum machine_mode, rtx, bool);
 extern rtx xtensa_legitimize_address (rtx, rtx, enum machine_mode);
+extern bool xtensa_tls_referenced_p (rtx);
 
 #ifdef TREE_CODE
 extern void init_cumulative_args (CUMULATIVE_ARGS *, int);
index 1af9cba..4e7edef 100644 (file)
@@ -131,6 +131,7 @@ static rtx gen_float_relational (enum rtx_code, rtx, rtx);
 static rtx gen_conditional_move (rtx);
 static rtx fixup_subreg_mem (rtx);
 static struct machine_function * xtensa_init_machine_status (void);
+static rtx xtensa_legitimize_tls_address (rtx);
 static bool xtensa_return_in_msb (const_tree);
 static void printx (FILE *, signed int);
 static void xtensa_function_epilogue (FILE *, HOST_WIDE_INT);
@@ -219,6 +220,12 @@ static const int reg_nonleaf_alloc_order[FIRST_PSEUDO_REGISTER] =
 #undef TARGET_SECONDARY_RELOAD
 #define TARGET_SECONDARY_RELOAD xtensa_secondary_reload
 
+#undef TARGET_HAVE_TLS
+#define TARGET_HAVE_TLS (TARGET_THREADPTR && HAVE_AS_TLS)
+
+#undef TARGET_CANNOT_FORCE_CONST_MEM
+#define TARGET_CANNOT_FORCE_CONST_MEM xtensa_tls_referenced_p
+
 struct gcc_target targetm = TARGET_INITIALIZER;
 
 \f
@@ -469,6 +476,18 @@ constantpool_mem_p (rtx op)
 }
 
 
+/* Return TRUE if X is a thread-local symbol.  */
+
+static bool
+xtensa_tls_symbol_p (rtx x)
+{
+  if (! TARGET_HAVE_TLS)
+    return false;
+
+  return GET_CODE (x) == SYMBOL_REF && SYMBOL_REF_TLS_MODEL (x) != 0;
+}
+
+
 void
 xtensa_extend_reg (rtx dst, rtx src)
 {
@@ -910,12 +929,38 @@ xtensa_split_operand_pair (rtx operands[4], enum machine_mode mode)
 int
 xtensa_emit_move_sequence (rtx *operands, enum machine_mode mode)
 {
-  if (CONSTANT_P (operands[1])
-      && (GET_CODE (operands[1]) != CONST_INT
-         || !xtensa_simm12b (INTVAL (operands[1]))))
+  rtx src = operands[1];
+
+  if (CONSTANT_P (src)
+      && (GET_CODE (src) != CONST_INT || ! xtensa_simm12b (INTVAL (src))))
     {
-      if (!TARGET_CONST16)
-       operands[1] = force_const_mem (SImode, operands[1]);
+      rtx dst = operands[0];
+
+      if (xtensa_tls_referenced_p (src))
+       {
+         rtx addend = NULL;
+
+         if (GET_CODE (src) == CONST && GET_CODE (XEXP (src, 0)) == PLUS)
+           {
+             addend = XEXP (XEXP (src, 0), 1);
+             src = XEXP (XEXP (src, 0), 0);
+           }
+
+         src = xtensa_legitimize_tls_address (src);
+         if (addend)
+           {
+             src = gen_rtx_PLUS (mode, src, addend);
+             src = force_operand (src, dst);
+           }
+         emit_move_insn (dst, src);
+         return 1;
+       }
+
+      if (! TARGET_CONST16)
+       {
+         src = force_const_mem (SImode, src);
+         operands[1] = src;
+       }
 
       /* PC-relative loads are always SImode, and CONST16 is only
         supported in the movsi pattern, so add a SUBREG for any other
@@ -923,16 +968,16 @@ xtensa_emit_move_sequence (rtx *operands, enum machine_mode mode)
 
       if (mode != SImode)
        {
-         if (register_operand (operands[0], mode))
+         if (register_operand (dst, mode))
            {
-             operands[0] = simplify_gen_subreg (SImode, operands[0], mode, 0);
-             emit_move_insn (operands[0], operands[1]);
+             emit_move_insn (simplify_gen_subreg (SImode, dst, mode, 0), src);
              return 1;
            }
          else
            {
-             operands[1] = force_reg (SImode, operands[1]);
-             operands[1] = gen_lowpart_SUBREG (mode, operands[1]);
+             src = force_reg (SImode, src);
+             src = gen_lowpart_SUBREG (mode, src);
+             operands[1] = src;
            }
        }
     }
@@ -1664,7 +1709,8 @@ xtensa_legitimate_address_p (enum machine_mode mode, rtx addr, bool strict)
 {
   /* Allow constant pool addresses.  */
   if (mode != BLKmode && GET_MODE_SIZE (mode) >= UNITS_PER_WORD
-      && ! TARGET_CONST16 && constantpool_address_p (addr))
+      && ! TARGET_CONST16 && constantpool_address_p (addr)
+      && ! xtensa_tls_referenced_p (addr))
     return true;
 
   while (GET_CODE (addr) == SUBREG)
@@ -1709,11 +1755,97 @@ xtensa_legitimate_address_p (enum machine_mode mode, rtx addr, bool strict)
 }
 
 
+/* Construct the SYMBOL_REF for the _TLS_MODULE_BASE_ symbol.  */
+
+static GTY(()) rtx xtensa_tls_module_base_symbol;
+
+static rtx
+xtensa_tls_module_base (void)
+{
+  if (! xtensa_tls_module_base_symbol)
+    {
+      xtensa_tls_module_base_symbol =
+       gen_rtx_SYMBOL_REF (Pmode, "_TLS_MODULE_BASE_");
+      SYMBOL_REF_FLAGS (xtensa_tls_module_base_symbol)
+        |= TLS_MODEL_GLOBAL_DYNAMIC << SYMBOL_FLAG_TLS_SHIFT;
+    }
+
+  return xtensa_tls_module_base_symbol;
+}
+
+
+static rtx
+xtensa_call_tls_desc (rtx sym, rtx *retp)
+{
+  rtx fn, arg, a10, call_insn, insns;
+
+  start_sequence ();
+  fn = gen_reg_rtx (Pmode);
+  arg = gen_reg_rtx (Pmode);
+  a10 = gen_rtx_REG (Pmode, 10);
+
+  emit_insn (gen_tls_func (fn, sym));
+  emit_insn (gen_tls_arg (arg, sym));
+  emit_move_insn (a10, arg);
+  call_insn = emit_call_insn (gen_tls_call (a10, fn, sym, const1_rtx));
+  CALL_INSN_FUNCTION_USAGE (call_insn)
+    = gen_rtx_EXPR_LIST (VOIDmode, gen_rtx_USE (VOIDmode, a10),
+                        CALL_INSN_FUNCTION_USAGE (call_insn));
+  insns = get_insns ();
+  end_sequence ();
+
+  *retp = a10;
+  return insns;
+}
+
+
+static rtx
+xtensa_legitimize_tls_address (rtx x)
+{
+  unsigned int model = SYMBOL_REF_TLS_MODEL (x);
+  rtx dest, tp, ret, modbase, base, addend, insns;
+
+  dest = gen_reg_rtx (Pmode);
+  switch (model)
+    {
+    case TLS_MODEL_GLOBAL_DYNAMIC:
+      insns = xtensa_call_tls_desc (x, &ret);
+      emit_libcall_block (insns, dest, ret, x);
+      break;
+
+    case TLS_MODEL_LOCAL_DYNAMIC:
+      base = gen_reg_rtx (Pmode);
+      modbase = xtensa_tls_module_base ();
+      insns = xtensa_call_tls_desc (modbase, &ret);
+      emit_libcall_block (insns, base, ret, modbase);
+      addend = force_reg (SImode, gen_sym_DTPOFF (x));
+      emit_insn (gen_addsi3 (dest, base, addend));
+      break;
+
+    case TLS_MODEL_INITIAL_EXEC:
+    case TLS_MODEL_LOCAL_EXEC:
+      tp = gen_reg_rtx (SImode);
+      emit_insn (gen_load_tp (tp));
+      addend = force_reg (SImode, gen_sym_TPOFF (x));
+      emit_insn (gen_addsi3 (dest, tp, addend));
+      break;
+
+    default:
+      gcc_unreachable ();
+    }
+
+  return dest;
+}
+
+
 rtx
 xtensa_legitimize_address (rtx x,
                           rtx oldx ATTRIBUTE_UNUSED,
                           enum machine_mode mode)
 {
+  if (xtensa_tls_symbol_p (x))
+    return xtensa_legitimize_tls_address (x);
+
   if (GET_CODE (x) == PLUS)
     {
       rtx plus0 = XEXP (x, 0);
@@ -1745,6 +1877,46 @@ xtensa_legitimize_address (rtx x,
 }
 
 
+/* Helper for xtensa_tls_referenced_p.  */
+
+static int
+xtensa_tls_referenced_p_1 (rtx *x, void *data ATTRIBUTE_UNUSED)
+{
+  if (GET_CODE (*x) == SYMBOL_REF)
+    return SYMBOL_REF_TLS_MODEL (*x) != 0;
+
+  /* Ignore TLS references that have already been legitimized.  */
+  if (GET_CODE (*x) == UNSPEC)
+    {
+      switch (XINT (*x, 1))
+       {
+       case UNSPEC_TPOFF:
+       case UNSPEC_DTPOFF:
+       case UNSPEC_TLS_FUNC:
+       case UNSPEC_TLS_ARG:
+       case UNSPEC_TLS_CALL:
+         return -1;
+       default:
+         break;
+       }
+    }
+
+  return 0;
+}
+
+
+/* Return TRUE if X contains any TLS symbol references.  */
+
+bool
+xtensa_tls_referenced_p (rtx x)
+{
+  if (! TARGET_HAVE_TLS)
+    return false;
+
+  return for_each_rtx (&x, xtensa_tls_referenced_p_1, NULL);
+}
+
+
 /* Return the debugger register number to use for 'regno'.  */
 
 int
@@ -2204,6 +2376,14 @@ xtensa_output_addr_const_extra (FILE *fp, rtx x)
     {
       switch (XINT (x, 1))
        {
+       case UNSPEC_TPOFF:
+         output_addr_const (fp, XVECEXP (x, 0, 0));
+         fputs ("@TPOFF", fp);
+         return true;
+       case UNSPEC_DTPOFF:
+         output_addr_const (fp, XVECEXP (x, 0, 0));
+         fputs ("@DTPOFF", fp);
+         return true;
        case UNSPEC_PLT:
          if (flag_pic)
            {
@@ -2760,6 +2940,8 @@ xtensa_gimplify_va_arg_expr (tree valist, tree type, gimple_seq *pre_p,
 enum xtensa_builtin
 {
   XTENSA_BUILTIN_UMULSIDI3,
+  XTENSA_BUILTIN_THREAD_POINTER,
+  XTENSA_BUILTIN_SET_THREAD_POINTER,
   XTENSA_BUILTIN_max
 };
 
@@ -2767,15 +2949,34 @@ enum xtensa_builtin
 static void
 xtensa_init_builtins (void)
 {
-  tree ftype;
+  tree ftype, decl;
 
   ftype = build_function_type_list (unsigned_intDI_type_node,
                                    unsigned_intSI_type_node,
                                    unsigned_intSI_type_node, NULL_TREE);
 
-  add_builtin_function ("__builtin_umulsidi3", ftype,
-                       XTENSA_BUILTIN_UMULSIDI3, BUILT_IN_MD,
-                       "__umulsidi3", NULL_TREE);
+  decl = add_builtin_function ("__builtin_umulsidi3", ftype,
+                              XTENSA_BUILTIN_UMULSIDI3, BUILT_IN_MD,
+                              "__umulsidi3", NULL_TREE);
+  TREE_NOTHROW (decl) = 1;
+  TREE_READONLY (decl) = 1;
+
+  if (TARGET_THREADPTR)
+    {
+      ftype = build_function_type (ptr_type_node, void_list_node);
+      decl = add_builtin_function ("__builtin_thread_pointer", ftype,
+                                  XTENSA_BUILTIN_THREAD_POINTER, BUILT_IN_MD,
+                                  NULL, NULL_TREE);
+      TREE_READONLY (decl) = 1;
+      TREE_NOTHROW (decl) = 1;
+
+      ftype = build_function_type_list (void_type_node, ptr_type_node,
+                                       NULL_TREE);
+      decl = add_builtin_function ("__builtin_set_thread_pointer", ftype,
+                                  XTENSA_BUILTIN_SET_THREAD_POINTER,
+                                  BUILT_IN_MD, NULL, NULL_TREE);
+      TREE_NOTHROW (decl) = 1;
+    }
 }
 
 
@@ -2785,8 +2986,9 @@ xtensa_fold_builtin (tree fndecl, tree arglist, bool ignore ATTRIBUTE_UNUSED)
   unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
   tree arg0, arg1;
 
-  if (fcode == XTENSA_BUILTIN_UMULSIDI3)
+  switch (fcode)
     {
+    case XTENSA_BUILTIN_UMULSIDI3:
       arg0 = TREE_VALUE (arglist);
       arg1 = TREE_VALUE (TREE_CHAIN (arglist));
       if ((TREE_CODE (arg0) == INTEGER_CST && TREE_CODE (arg1) == INTEGER_CST)
@@ -2794,11 +2996,17 @@ xtensa_fold_builtin (tree fndecl, tree arglist, bool ignore ATTRIBUTE_UNUSED)
        return fold_build2 (MULT_EXPR, unsigned_intDI_type_node,
                            fold_convert (unsigned_intDI_type_node, arg0),
                            fold_convert (unsigned_intDI_type_node, arg1));
-      else
-       return NULL;
+      break;
+
+    case XTENSA_BUILTIN_THREAD_POINTER:
+    case XTENSA_BUILTIN_SET_THREAD_POINTER:
+      break;
+
+    default:
+      internal_error ("bad builtin code");
+      break;
     }
 
-  internal_error ("bad builtin code");
   return NULL;
 }
 
@@ -2811,14 +3019,32 @@ xtensa_expand_builtin (tree exp, rtx target,
 {
   tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
   unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
+  rtx arg;
+
+  switch (fcode)
+    {
+    case XTENSA_BUILTIN_UMULSIDI3:
+      /* The umulsidi3 builtin is just a mechanism to avoid calling the real
+        __umulsidi3 function when the Xtensa configuration can directly
+        implement it.  If not, just call the function.  */
+      return expand_call (exp, target, ignore);
 
-  /* The umulsidi3 builtin is just a mechanism to avoid calling the real
-     __umulsidi3 function when the Xtensa configuration can directly
-     implement it.  If not, just call the function.  */
-  if (fcode == XTENSA_BUILTIN_UMULSIDI3)
-    return expand_call (exp, target, ignore);
+    case XTENSA_BUILTIN_THREAD_POINTER:
+      if (!target || !register_operand (target, Pmode))
+       target = gen_reg_rtx (Pmode);
+      emit_insn (gen_load_tp (target));
+      return target;
 
-  internal_error ("bad builtin code");
+    case XTENSA_BUILTIN_SET_THREAD_POINTER:
+      arg = expand_normal (CALL_EXPR_ARG (exp, 0));
+      if (!register_operand (arg, Pmode))
+       arg = copy_to_mode_reg (Pmode, arg);
+      emit_insn (gen_set_tp (arg));
+      return const0_rtx;
+
+    default:
+      internal_error ("bad builtin code");
+    }
   return NULL_RTX;
 }
 
index ab3b648..1427fd0 100644 (file)
@@ -51,6 +51,9 @@ extern unsigned xtensa_current_frame_size;
 #ifndef XCHAL_HAVE_S32C1I
 #define XCHAL_HAVE_S32C1I 0
 #endif
+#ifndef XCHAL_HAVE_THREADPTR
+#define XCHAL_HAVE_THREADPTR 0
+#endif
 #define TARGET_BIG_ENDIAN      XCHAL_HAVE_BE
 #define TARGET_DENSITY         XCHAL_HAVE_DENSITY
 #define TARGET_MAC16           XCHAL_HAVE_MAC16
@@ -72,11 +75,16 @@ extern unsigned xtensa_current_frame_size;
 #define TARGET_RELEASE_SYNC    XCHAL_HAVE_RELEASE_SYNC
 #define TARGET_S32C1I          XCHAL_HAVE_S32C1I
 #define TARGET_ABSOLUTE_LITERALS XSHAL_USE_ABSOLUTE_LITERALS
+#define TARGET_THREADPTR       XCHAL_HAVE_THREADPTR
 
 #define TARGET_DEFAULT \
   ((XCHAL_HAVE_L32R    ? 0 : MASK_CONST16) |                           \
    MASK_SERIALIZE_VOLATILE)
 
+#ifndef HAVE_AS_TLS
+#define HAVE_AS_TLS 0
+#endif
+
 #define OVERRIDE_OPTIONS override_options ()
 
 /* Reordering blocks for Xtensa is not a good idea unless the compiler
@@ -791,7 +799,7 @@ typedef struct xtensa_args
 
 /* Nonzero if the constant value X is a legitimate general operand.
    It is given that X satisfies CONSTANT_P or is a CONST_DOUBLE.  */
-#define LEGITIMATE_CONSTANT_P(X) 1
+#define LEGITIMATE_CONSTANT_P(X) (! xtensa_tls_referenced_p (X))
 
 /* A C expression that is nonzero if X is a legitimate immediate
    operand on the target machine when generating position independent
index 4f831d3..29119ed 100644 (file)
   (UNSPEC_NOP          2)
   (UNSPEC_PLT          3)
   (UNSPEC_RET_ADDR     4)
+  (UNSPEC_TPOFF                5)
+  (UNSPEC_DTPOFF       6)
+  (UNSPEC_TLS_FUNC     7)
+  (UNSPEC_TLS_ARG      8)
+  (UNSPEC_TLS_CALL     9)
+  (UNSPEC_TP           10)
 
   (UNSPECV_SET_FP      1)
   (UNSPECV_ENTRY       2)
@@ -36,6 +42,7 @@
   (UNSPECV_S32RI       4)
   (UNSPECV_S32C1I      5)
   (UNSPECV_EH_RETURN   6)
+  (UNSPECV_SET_TP      7)
 ])
 
 ;; This code iterator allows signed and unsigned widening multiplications
 })
 
 (define_insn "call_value_internal"
-   [(set (match_operand 0 "register_operand" "=a")
-         (call (mem (match_operand:SI 1 "call_insn_operand" "nir"))
-               (match_operand 2 "" "i")))]
+  [(set (match_operand 0 "register_operand" "=a")
+        (call (mem (match_operand:SI 1 "call_insn_operand" "nir"))
+              (match_operand 2 "" "i")))]
   ""
 {
   return xtensa_emit_call (1, operands);
    (set_attr "length"  "0")])
 
 \f
+;; TLS support
+
+(define_expand "sym_TPOFF"
+  [(const (unspec [(match_operand:SI 0 "" "")] UNSPEC_TPOFF))]
+  ""
+  "")
+
+(define_expand "sym_DTPOFF"
+  [(const (unspec [(match_operand:SI 0 "" "")] UNSPEC_DTPOFF))]
+  ""
+  "")
+
+(define_insn "load_tp"
+  [(set (match_operand:SI 0 "register_operand" "=a")
+       (unspec:SI [(const_int 0)] UNSPEC_TP))]
+  "TARGET_THREADPTR"
+  "rur\t%0, THREADPTR"
+  [(set_attr "type"    "rsr")
+   (set_attr "mode"    "SI")
+   (set_attr "length"  "3")])
+
+(define_insn "set_tp"
+  [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")]
+                   UNSPECV_SET_TP)]
+  "TARGET_THREADPTR"
+  "wur\t%0, THREADPTR"
+  [(set_attr "type"    "wsr")
+   (set_attr "mode"    "SI")
+   (set_attr "length"  "3")])
+
+(define_insn "tls_func"
+  [(set (match_operand:SI 0 "register_operand" "=a")
+       (unspec:SI [(match_operand:SI 1 "tls_symbol_operand" "")]
+                  UNSPEC_TLS_FUNC))]
+  "TARGET_THREADPTR && HAVE_AS_TLS"
+  "movi\t%0, %1@TLSFUNC"
+  [(set_attr "type"    "load")
+   (set_attr "mode"    "SI")
+   (set_attr "length"  "3")])
+
+(define_insn "tls_arg"
+  [(set (match_operand:SI 0 "register_operand" "=a")
+       (unspec:SI [(match_operand:SI 1 "tls_symbol_operand" "")]
+                  UNSPEC_TLS_ARG))]
+  "TARGET_THREADPTR && HAVE_AS_TLS"
+  "movi\t%0, %1@TLSARG"
+  [(set_attr "type"    "load")
+   (set_attr "mode"    "SI")
+   (set_attr "length"  "3")])
+
+(define_insn "tls_call"
+  [(set (match_operand:SI 0 "register_operand" "=a")
+       (call (mem:SI (unspec:SI [(match_operand:SI 1 "register_operand" "r")
+                                 (match_operand:SI 2 "tls_symbol_operand" "")]
+                                 UNSPEC_TLS_CALL))
+             (match_operand 3 "" "i")))]
+  "TARGET_THREADPTR && HAVE_AS_TLS"
+  "callx8.tls %1, %2@TLSCALL"
+  [(set_attr "type"    "call")
+   (set_attr "mode"    "none")
+   (set_attr "length"  "3")])
+
+\f
 ;; Instructions for the Xtensa "boolean" option.
 
 (define_insn "*booltrue"
index e6535fb..0dbf86a 100755 (executable)
@@ -21194,7 +21194,7 @@ cat >>confdefs.h <<_ACEOF
 _ACEOF
 
 
-# Thread-local storage - the check is heavily parametrized.
+# Thread-local storage - the check is heavily parameterized.
 conftest_s=
 tls_first_major=
 tls_first_minor=
@@ -21526,6 +21526,17 @@ foo:   .long   25
        tls_as_opt="-32 --fatal-warnings"
       fi
        ;;
+  xtensa*-*-*)
+    conftest_s='
+       .section ".tdata","awT",@progbits
+foo:   .long   25
+       .text
+       movi    a8, foo@TLSFUNC
+       movi    a10, foo@TLSARG
+       callx8.tls a8, foo@TLSCALL'
+       tls_first_major=2
+       tls_first_minor=19
+       ;;
 esac
 set_have_as_tls=no
 if test "x$enable_tls" = xno ; then
index e81b203..b6bc311 100644 (file)
@@ -2322,7 +2322,7 @@ AC_DEFINE_UNQUOTED(HAVE_COMDAT_GROUP,
   [`if test $gcc_cv_as_comdat_group = yes || test $gcc_cv_as_comdat_group_percent = yes; then echo 1; else echo 0; fi`],
 [Define 0/1 if your assembler and linker support COMDAT groups.])
 
-# Thread-local storage - the check is heavily parametrized.
+# Thread-local storage - the check is heavily parameterized.
 conftest_s=
 tls_first_major=
 tls_first_minor=
@@ -2655,6 +2655,17 @@ foo:     .long   25
        tls_as_opt="-32 --fatal-warnings"
       fi
        ;;
+  xtensa*-*-*)
+    conftest_s='
+       .section ".tdata","awT",@progbits
+foo:   .long   25
+       .text
+       movi    a8, foo@TLSFUNC
+       movi    a10, foo@TLSARG
+       callx8.tls a8, foo@TLSCALL'
+       tls_first_major=2
+       tls_first_minor=19
+       ;;
 changequote([,])dnl
 esac
 set_have_as_tls=no