configure.in (HAVE_AS_TLS): Add alpha tests.
authorRichard Henderson <rth@redhat.com>
Sat, 1 Jun 2002 00:19:10 +0000 (17:19 -0700)
committerRichard Henderson <rth@gcc.gnu.org>
Sat, 1 Jun 2002 00:19:10 +0000 (17:19 -0700)
* configure.in (HAVE_AS_TLS): Add alpha tests.
* configure: Rebuild.
* config/alpha/alpha.c (TARGET_AS_TLS): New.
(alpha_tls_size, alpha_tls_size_string): New.
(overide_options): Set it.  Always install machine_status hooks.
(input_operand): Accept got tls predicates.
(local_symbol_p): Merge into ...
(local_symbolic_operand): ... here.  Reject tls symbols.
(global_symbolic_operand): Likewise.
(tls_symbolic_operand_1, dtp16_symbolic_operand): New.
(dtp32_symbolic_operand, gotdtp_symbolic_operand): New.
(tp16_symbolic_operand, tp32_symbolic_operand): New.
(gottp_symbolic_operand, tls_symbolic_operand_type): New.
(alpha_encode_section_info): Handle TLS symbols.
(alpha_strip_name_encoding): Likewise.
(alpha_legitimate_address_p): Likewise.
(alpha_legitimize_address): Likewise.
(alpha_expand_mov): Early exit to avoid nop moves.
(struct machine_function): Move from unicosmk.h.  Add some_ld_name.
(alpha_init_machine_status, alpha_mark_machine_status,
alpha_free_machine_status): Always define.
(get_some_local_dynamic_name, get_some_local_dynamic_name_1): New.
(print_operand, print_operand_address): Add TLS relocs.
* config/alpha/alpha.h (HAVE_AS_TLS): Default 0.
(MASK_TLS_KERNEL, TARGET_TLS_KERNEL): New.
(TARGET_SWITCHES): Add -mtls-kernel.
(alpha_tls_size, alpha_tls_size_string): New.
(TARGET_OPTIONS): Add -mtls-size=.
(reg_class, REG_CLASS_NAMES, REG_CLASS_CONTENTS,
REGNO_REG_CLASS, REG_CLASS_FROM_LETTER): Add R0_REG.
(ASM_OUTPUT_LABELREF): Skip %.
(PRINT_OPERAND_PUNCT_VALID_P): Add &.
(PREDICATE_CODES): Update.
* config/alpha/alpha.md (UNSPEC_TLSGD_CALL, UNSPEC_TLSLDM_CALL,
UNSPEC_TLSGD, UNSPEC_TLSLDM, UNSPEC_DTPREL, UNSPEC_TPREL,
UNSPEC_TP, UNSPECV_SET_TP): New.
(adddi_er_lo16_dtp, adddi_er_hi32_dtp, adddi_er_lo32_dtp,
adddi_er_lo16_tp, adddi_er_hi32_tp, adddi_er_lo32_tp, load_tp,
set_tp, movdi_er_tlsgd, movdi_er_tlsldm, movdi_er_gotdtp,
movdi_er_gottp, call_value_osf_tlsgd, call_value_osf_tlsldm): New.
(call_value_osf_2_er): Accept anything as op4.
* config/alpha/alpha-protos.h: Update.
* config/alpha/unicosmk.h (struct machine_function): Move to alpha.c.

From-SVN: r54125

gcc/ChangeLog
gcc/config/alpha/alpha-protos.h
gcc/config/alpha/alpha.c
gcc/config/alpha/alpha.h
gcc/config/alpha/alpha.md
gcc/config/alpha/unicosmk.h
gcc/configure
gcc/configure.in

index 7e5103ee9e1a09b6d4ce3186d3135e059e1f1092..efd25dd41262da3541fc35a523b3155f11d4b1ee 100644 (file)
@@ -1,3 +1,49 @@
+2002-05-31  Richard Henderson  <rth@redhat.com>
+
+       * configure.in (HAVE_AS_TLS): Add alpha tests.
+       * configure: Rebuild.
+       * config/alpha/alpha.c (TARGET_AS_TLS): New.
+       (alpha_tls_size, alpha_tls_size_string): New.
+       (overide_options): Set it.  Always install machine_status hooks.
+       (input_operand): Accept got tls predicates.
+       (local_symbol_p): Merge into ...
+       (local_symbolic_operand): ... here.  Reject tls symbols.
+       (global_symbolic_operand): Likewise.
+       (tls_symbolic_operand_1, dtp16_symbolic_operand): New.
+       (dtp32_symbolic_operand, gotdtp_symbolic_operand): New.
+       (tp16_symbolic_operand, tp32_symbolic_operand): New.
+       (gottp_symbolic_operand, tls_symbolic_operand_type): New.
+       (alpha_encode_section_info): Handle TLS symbols.
+       (alpha_strip_name_encoding): Likewise.
+       (alpha_legitimate_address_p): Likewise.
+       (alpha_legitimize_address): Likewise.
+       (alpha_expand_mov): Early exit to avoid nop moves.
+       (struct machine_function): Move from unicosmk.h.  Add some_ld_name.
+       (alpha_init_machine_status, alpha_mark_machine_status,
+       alpha_free_machine_status): Always define.
+       (get_some_local_dynamic_name, get_some_local_dynamic_name_1): New.
+       (print_operand, print_operand_address): Add TLS relocs.
+       * config/alpha/alpha.h (HAVE_AS_TLS): Default 0.
+       (MASK_TLS_KERNEL, TARGET_TLS_KERNEL): New.
+       (TARGET_SWITCHES): Add -mtls-kernel.
+       (alpha_tls_size, alpha_tls_size_string): New.
+       (TARGET_OPTIONS): Add -mtls-size=.
+       (reg_class, REG_CLASS_NAMES, REG_CLASS_CONTENTS,
+       REGNO_REG_CLASS, REG_CLASS_FROM_LETTER): Add R0_REG.
+       (ASM_OUTPUT_LABELREF): Skip %.
+       (PRINT_OPERAND_PUNCT_VALID_P): Add &.
+       (PREDICATE_CODES): Update.
+       * config/alpha/alpha.md (UNSPEC_TLSGD_CALL, UNSPEC_TLSLDM_CALL,
+       UNSPEC_TLSGD, UNSPEC_TLSLDM, UNSPEC_DTPREL, UNSPEC_TPREL,
+       UNSPEC_TP, UNSPECV_SET_TP): New.
+       (adddi_er_lo16_dtp, adddi_er_hi32_dtp, adddi_er_lo32_dtp,
+       adddi_er_lo16_tp, adddi_er_hi32_tp, adddi_er_lo32_tp, load_tp,
+       set_tp, movdi_er_tlsgd, movdi_er_tlsldm, movdi_er_gotdtp,
+       movdi_er_gottp, call_value_osf_tlsgd, call_value_osf_tlsldm): New.
+       (call_value_osf_2_er): Accept anything as op4.
+       * config/alpha/alpha-protos.h: Update.
+       * config/alpha/unicosmk.h (struct machine_function): Move to alpha.c.
+
 2002-05-31  Zack Weinberg  <zack@codesourcery.com>
 
        * cppinit.c (append_include_chain): Always pay attention to
index 2eb195a503d19d6fc51f5ca6a2c85f1753de2596..cbe8e3437b075dec7e1bee7ccecba4c628f7c824 100644 (file)
@@ -61,6 +61,12 @@ extern int local_symbolic_operand PARAMS ((rtx, enum machine_mode));
 extern int small_symbolic_operand PARAMS ((rtx, enum machine_mode));
 extern int some_small_symbolic_operand PARAMS ((rtx, enum machine_mode));
 extern int global_symbolic_operand PARAMS ((rtx, enum machine_mode));
+extern int dtp16_symbolic_operand PARAMS ((rtx, enum machine_mode));
+extern int dtp32_symbolic_operand PARAMS ((rtx, enum machine_mode));
+extern int gotdtp_symbolic_operand PARAMS ((rtx, enum machine_mode));
+extern int tp16_symbolic_operand PARAMS ((rtx, enum machine_mode));
+extern int tp32_symbolic_operand PARAMS ((rtx, enum machine_mode));
+extern int gottp_symbolic_operand PARAMS ((rtx, enum machine_mode));
 extern int call_operand PARAMS ((rtx, enum machine_mode));
 extern int symbolic_operand PARAMS ((rtx, enum machine_mode));
 extern int alpha_comparison_operator PARAMS ((rtx, enum machine_mode));
index 9681d929e4e655eec7ff6a9b59edd9b7c908c777..bee3dc1d5553db047f1d17674993a9925cbe12fe 100644 (file)
@@ -69,6 +69,10 @@ enum alpha_fp_rounding_mode alpha_fprm;
 
 enum alpha_fp_trap_mode alpha_fptm;
 
+/* Specify bit size of immediate TLS offsets.  */
+
+int alpha_tls_size = 32;
+
 /* Strings decoded into the above options.  */
 
 const char *alpha_cpu_string;  /* -mcpu= */
@@ -77,6 +81,7 @@ const char *alpha_tp_string;  /* -mtrap-precision=[p|s|i] */
 const char *alpha_fprm_string; /* -mfp-rounding-mode=[n|m|c|d] */
 const char *alpha_fptm_string; /* -mfp-trap-mode=[n|u|su|sui] */
 const char *alpha_mlat_string; /* -mmemory-latency= */
+const char *alpha_tls_size_string; /* -mtls-size=[16|32|64] */
 
 /* Save information from a "cmpxx" operation until the branch or scc is
    emitted.  */
@@ -113,6 +118,10 @@ int alpha_this_literal_sequence_number;
 int alpha_this_gpdisp_sequence_number;
 
 /* Declarations of static functions.  */
+static int tls_symbolic_operand_1
+  PARAMS ((rtx, enum machine_mode, int, int));
+static enum tls_model tls_symbolic_operand_type
+  PARAMS ((rtx));
 static bool decl_in_text_section
   PARAMS ((tree));
 static bool alpha_in_small_data_p
@@ -125,8 +134,6 @@ static int some_small_symbolic_operand_1
   PARAMS ((rtx *, void *));
 static int split_small_symbolic_operand_1
   PARAMS ((rtx *, void *));
-static bool local_symbol_p
-  PARAMS ((rtx));
 static void alpha_set_memflags_1
   PARAMS ((rtx, int, int, int));
 static rtx alpha_emit_set_const_1
@@ -147,6 +154,10 @@ static const char *get_trap_mode_suffix
   PARAMS ((void));
 static const char *get_round_mode_suffix
   PARAMS ((void));
+static const char *get_some_local_dynamic_name
+  PARAMS ((void));
+static int get_some_local_dynamic_name_1
+  PARAMS ((rtx *, void *));
 static rtx set_frame_related_p
   PARAMS ((void));
 static const char *alpha_lookup_xfloating_lib_func
@@ -173,14 +184,12 @@ static void alpha_elf_select_rtx_section
   PARAMS ((enum machine_mode, rtx, unsigned HOST_WIDE_INT));
 #endif
 
-#if TARGET_ABI_UNICOSMK
 static void alpha_init_machine_status
   PARAMS ((struct function *p));
 static void alpha_mark_machine_status
   PARAMS ((struct function *p));
 static void alpha_free_machine_status
   PARAMS ((struct function *p));
-#endif
 
 static void unicosmk_output_deferred_case_vectors PARAMS ((FILE *));
 static void unicosmk_gen_dsib PARAMS ((unsigned long *imaskP));
@@ -266,6 +275,9 @@ static void unicosmk_unique_section PARAMS ((tree, int));
 #define TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD \
   alpha_multipass_dfa_lookahead
 
+#undef TARGET_HAVE_TLS
+#define TARGET_HAVE_TLS HAVE_AS_TLS
+
 struct gcc_target targetm = TARGET_INITIALIZER;
 \f
 /* Parse target option strings.  */
@@ -385,6 +397,18 @@ override_options ()
        error ("bad value `%s' for -mfp-trap-mode switch", alpha_fptm_string);
     }
 
+  if (alpha_tls_size_string)
+    {
+      if (strcmp (alpha_tls_size_string, "16") == 0)
+       alpha_tls_size = 16;
+      else if (strcmp (alpha_tls_size_string, "32") == 0)
+       alpha_tls_size = 32;
+      else if (strcmp (alpha_tls_size_string, "64") == 0)
+       alpha_tls_size = 64;
+      else
+       error ("bad value `%s' for -mtls-size switch", alpha_tls_size_string);
+    }
+
   alpha_cpu
     = TARGET_CPU_DEFAULT & MASK_CPU_EV6 ? PROCESSOR_EV6
       : (TARGET_CPU_DEFAULT & MASK_CPU_EV5 ? PROCESSOR_EV5 : PROCESSOR_EV4);
@@ -527,12 +551,10 @@ override_options ()
 
   /* Register variables and functions with the garbage collector.  */
 
-#if TARGET_ABI_UNICOSMK
   /* Set up function hooks.  */
   init_machine_status = alpha_init_machine_status;
   mark_machine_status = alpha_mark_machine_status;
   free_machine_status = alpha_free_machine_status;
-#endif
 }
 \f
 /* Returns 1 if VALUE is a mask that contains full bytes of zero or ones.  */
@@ -857,7 +879,9 @@ input_operand (op, mode)
             symbolic operands to be reconstructed from their high/lo_sum
             form.  */
          return (small_symbolic_operand (op, mode)
-                 || global_symbolic_operand (op, mode));
+                 || global_symbolic_operand (op, mode)
+                 || gotdtp_symbolic_operand (op, mode)
+                 || gottp_symbolic_operand (op, mode));
        }
 
       /* This handles both the Windows/NT and OSF cases.  */
@@ -946,29 +970,13 @@ direct_call_operand (op, mode)
 /* Return true if OP is a LABEL_REF, or SYMBOL_REF or CONST referencing
    a variable known to be defined in this file.  */
 
-static bool
-local_symbol_p (op)
-     rtx op;
-{
-  const char *str = XSTR (op, 0);
-
-  /* ??? SYMBOL_REF_FLAG is set for local function symbols, but we
-     run into problems with the rtl inliner in that the symbol was
-     once external, but is local after inlining, which results in
-     unrecognizable insns.  */
-
-  return (CONSTANT_POOL_ADDRESS_P (op)
-         /* If @, then alpha_encode_section_info sez it's local.  */
-         || str[0] == '@'
-         /* If *$, then ASM_GENERATE_INTERNAL_LABEL sez it's local.  */
-         || (str[0] == '*' && str[1] == '$'));
-}
-
 int
 local_symbolic_operand (op, mode)
      rtx op;
      enum machine_mode mode;
 {
+  const char *str;
+
   if (mode != VOIDmode && GET_MODE (op) != VOIDmode && mode != GET_MODE (op))
     return 0;
 
@@ -983,7 +991,26 @@ local_symbolic_operand (op, mode)
   if (GET_CODE (op) != SYMBOL_REF)
     return 0;
 
-  return local_symbol_p (op);
+  /* Easy pickings.  */
+  if (CONSTANT_POOL_ADDRESS_P (op) || STRING_POOL_ADDRESS_P (op))
+    return 1;
+
+  /* ??? SYMBOL_REF_FLAG is set for local function symbols, but we
+     run into problems with the rtl inliner in that the symbol was
+     once external, but is local after inlining, which results in
+     unrecognizable insns.  */
+
+  str = XSTR (op, 0);
+
+  /* If @[VS], then alpha_encode_section_info sez it's local.  */
+  if (str[0] == '@' && (str[1] == 'L' || str[1] == 'S'))
+    return 1;
+
+  /* If *$, then ASM_GENERATE_INTERNAL_LABEL sez it's local.  */
+  if (str[0] == '*' && str[1] == '$')
+    return 1;
+
+  return 0;
 }
 
 /* Return true if OP is a SYMBOL_REF or CONST referencing a variable
@@ -1015,7 +1042,7 @@ small_symbolic_operand (op, mode)
   else
     {
       str = XSTR (op, 0);
-      return str[0] == '@' && str[1] == 's';
+      return str[0] == '@' && str[1] == 'S';
     }
 }
 
@@ -1027,6 +1054,8 @@ global_symbolic_operand (op, mode)
      rtx op;
      enum machine_mode mode;
 {
+  const char *str;
+
   if (mode != VOIDmode && GET_MODE (op) != VOIDmode && mode != GET_MODE (op))
     return 0;
 
@@ -1038,7 +1067,12 @@ global_symbolic_operand (op, mode)
   if (GET_CODE (op) != SYMBOL_REF)
     return 0;
 
-  return ! local_symbol_p (op);
+  if (local_symbolic_operand (op, mode))
+    return 0;
+
+  /* Also verify that it's not a TLS symbol.  */
+  str = XSTR (op, 0);
+  return str[0] != '%' && str[0] != '@';
 }
 
 /* Return 1 if OP is a valid operand for the MEM of a CALL insn.  */
@@ -1091,6 +1125,110 @@ symbolic_operand (op, mode)
   return 0;
 }
 
+/* Return true if OP is valid for a particular TLS relocation.  */
+
+static int
+tls_symbolic_operand_1 (op, mode, size, unspec)
+     rtx op;
+     enum machine_mode mode;
+     int size, unspec;
+{
+  const char *str;
+  int letter;
+
+  if (mode != VOIDmode && GET_MODE (op) != VOIDmode && mode != GET_MODE (op))
+    return 0;
+
+  if (GET_CODE (op) != CONST)
+    return 0;
+  op = XEXP (op, 0);
+
+  if (GET_CODE (op) != UNSPEC || XINT (op, 1) != unspec)
+    return 0;
+  op = XVECEXP (op, 0, 0);
+
+  if (GET_CODE (op) != SYMBOL_REF)
+    return 0;
+  str = XSTR (op, 0);
+
+  if (str[0] == '%')
+    {
+      if (size != 64)
+       return 0;
+    }
+  else if (str[0] == '@')
+    {
+      if (alpha_tls_size > size)
+       return 0;
+    }
+  else
+    return 0;
+
+  letter = (unspec == UNSPEC_DTPREL ? 'D' : 'T');
+
+  return str[1] == letter;
+}
+
+/* Return true if OP is valid for 16-bit DTP relative relocations.  */
+
+int
+dtp16_symbolic_operand (op, mode)
+      rtx op;
+      enum machine_mode mode;
+{
+  return tls_symbolic_operand_1 (op, mode, 16, UNSPEC_DTPREL);
+}
+
+/* Return true if OP is valid for 32-bit DTP relative relocations.  */
+
+int
+dtp32_symbolic_operand (op, mode)
+      rtx op;
+      enum machine_mode mode;
+{
+  return tls_symbolic_operand_1 (op, mode, 32, UNSPEC_DTPREL);
+}
+
+/* Return true if OP is valid for 64-bit DTP relative relocations.  */
+
+int
+gotdtp_symbolic_operand (op, mode)
+      rtx op;
+      enum machine_mode mode;
+{
+  return tls_symbolic_operand_1 (op, mode, 64, UNSPEC_DTPREL);
+}
+
+/* Return true if OP is valid for 16-bit TP relative relocations.  */
+
+int
+tp16_symbolic_operand (op, mode)
+      rtx op;
+      enum machine_mode mode;
+{
+  return tls_symbolic_operand_1 (op, mode, 16, UNSPEC_TPREL);
+}
+
+/* Return true if OP is valid for 32-bit TP relative relocations.  */
+
+int
+tp32_symbolic_operand (op, mode)
+      rtx op;
+      enum machine_mode mode;
+{
+  return tls_symbolic_operand_1 (op, mode, 32, UNSPEC_TPREL);
+}
+
+/* Return true if OP is valid for 64-bit TP relative relocations.  */
+
+int
+gottp_symbolic_operand (op, mode)
+      rtx op;
+      enum machine_mode mode;
+{
+  return tls_symbolic_operand_1 (op, mode, 64, UNSPEC_TPREL);
+}
+
 /* Return 1 if OP is a valid Alpha comparison operator.  Here we know which
    comparisons are valid in which insn.  */
 
@@ -1561,6 +1699,54 @@ alpha_tablejump_best_label (insn)
 
   return best_label ? best_label : const0_rtx;
 }
+
+/* Return the TLS model to use for SYMBOL.  */
+
+static enum tls_model
+tls_symbolic_operand_type (symbol)
+     rtx symbol;
+{
+  const char *str;
+
+  if (GET_CODE (symbol) != SYMBOL_REF)
+    return 0;
+  str = XSTR (symbol, 0);
+
+  if (str[0] == '%')
+    {
+      /* ??? Be prepared for -ftls-model=local-dynamic.  Perhaps we shouldn't
+        have separately encoded local-ness.  On well, maybe the user will use
+        attribute visibility next time.  At least we don't crash...  */
+      if (str[1] == 'G' || str[1] == 'D')
+       return TLS_MODEL_GLOBAL_DYNAMIC;
+      if (str[1] == 'T')
+       return TLS_MODEL_INITIAL_EXEC;
+    }
+  else if (str[0] == '@')
+    {
+      if (str[1] == 'D')
+       {
+         /* Local dynamic is a waste if we're not going to combine
+            the __tls_get_addr calls.  So avoid it if not optimizing.  */
+         if (optimize)
+           return TLS_MODEL_LOCAL_DYNAMIC;
+         else
+           return TLS_MODEL_GLOBAL_DYNAMIC;
+       }
+      if (str[1] == 'T')
+       {
+         /* 64-bit local exec is the same as initial exec except without
+            the dynamic relocation.  In either case we use a got entry.  */
+         if (alpha_tls_size == 64)
+           return TLS_MODEL_INITIAL_EXEC;
+         else
+           return TLS_MODEL_LOCAL_EXEC;
+       }
+    }
+
+  return 0;
+}
+
 \f
 /* Return true if the function DECL will be placed in the default text
    section.  */
@@ -1622,7 +1808,8 @@ alpha_encode_section_info (decl, first)
      int first ATTRIBUTE_UNUSED;
 {
   const char *symbol_str;
-  bool is_local, is_small;
+  bool is_local;
+  char encoding = 0;
   rtx rtl, symbol;
 
   rtl = DECL_P (decl) ? DECL_RTL (decl) : TREE_CST_RTL (decl);
@@ -1659,18 +1846,56 @@ alpha_encode_section_info (decl, first)
   /* A variable is considered "local" if it is defined in this module.  */
   is_local = (*targetm.binds_local_p) (decl);
 
-  /* Determine if DECL will wind up in .sdata/.sbss.  */
-  is_small = alpha_in_small_data_p (decl);
+  /* Care for TLS variables.  */
+  if (TREE_CODE (decl) == VAR_DECL && DECL_THREAD_LOCAL (decl))
+    {
+      enum tls_model kind;
+      if (!flag_pic)
+       {
+         if (is_local)
+           kind = TLS_MODEL_LOCAL_EXEC;
+         else
+           kind = TLS_MODEL_INITIAL_EXEC;
+       }
+      else if (is_local)
+       kind = TLS_MODEL_LOCAL_DYNAMIC;
+      else
+       kind = TLS_MODEL_GLOBAL_DYNAMIC;
+      if (kind < flag_tls_default)
+       kind = flag_tls_default;
+
+      switch (kind)
+       {
+       case TLS_MODEL_GLOBAL_DYNAMIC:
+         encoding = 'G';
+         break;
+       case TLS_MODEL_LOCAL_DYNAMIC:
+         encoding = 'D';
+         break;
+       case TLS_MODEL_INITIAL_EXEC:
+       case TLS_MODEL_LOCAL_EXEC:
+         encoding = 'T';
+         break;
+       }
+    }
+  else if (is_local)
+    {
+      /* Determine if DECL will wind up in .sdata/.sbss.  */
+      if (alpha_in_small_data_p (decl))
+       encoding = 'S';
+      else
+       encoding = 'L';
+    }
 
   /* Finally, encode this into the symbol string.  */
-  if (is_local)
+  if (encoding)
     {
       char *newstr;
       size_t len;
 
-      if (symbol_str[0] == '@')
+      if (symbol_str[0] == (is_local ? '@' : '%'))
        {
-         if (symbol_str[1] == (is_small ? 's' : 'v'))
+         if (symbol_str[1] == encoding)
            return;
          symbol_str += 2;
        }
@@ -1678,18 +1903,12 @@ alpha_encode_section_info (decl, first)
       len = strlen (symbol_str) + 1;
       newstr = alloca (len + 2);
 
-      newstr[0] = '@';
-      newstr[1] = (is_small ? 's' : 'v');
+      newstr[0] = (is_local ? '@' : '%');
+      newstr[1] = encoding;
       memcpy (newstr + 2, symbol_str, len);
          
       XSTR (symbol, 0) = ggc_alloc_string (newstr, len + 2 - 1);
     }
-  else if (symbol_str[0] == '@')
-    {
-      /* We're hosed.  This can happen when the user adds a weak
-        attribute after rtl generation.  They should have gotten
-        a warning about unspecified behaviour from varasm.c.  */
-    }
 }
 
 /* Undo the effects of the above.  */
@@ -1698,7 +1917,7 @@ static const char *
 alpha_strip_name_encoding (str)
      const char *str;
 {
-  if (str[0] == '@')
+  if (str[0] == '@' || str[0] == '%')
     str += 2;
   if (str[0] == '*')
     str++;
@@ -1799,7 +2018,9 @@ alpha_legitimate_address_p (mode, x, strict)
            return false;
 
          /* The symbol must be local.  */
-         if (local_symbolic_operand (ofs, Pmode))
+         if (local_symbolic_operand (ofs, Pmode)
+             || dtp32_symbolic_operand (ofs, Pmode)
+             || tp32_symbolic_operand (ofs, Pmode))
            return true;
        }
     }
@@ -1865,6 +2086,100 @@ alpha_legitimize_address (x, scratch, mode)
   /* If this is a local symbol, split the address into HIGH/LO_SUM parts.  */
   if (TARGET_EXPLICIT_RELOCS && symbolic_operand (x, Pmode))
     {
+      rtx r0, r16, eqv, tga, tp, insn, dest, seq;
+
+      switch (tls_symbolic_operand_type (x))
+       {
+       case TLS_MODEL_GLOBAL_DYNAMIC:
+         start_sequence ();
+
+         r0 = gen_rtx_REG (Pmode, 0);
+         r16 = gen_rtx_REG (Pmode, 16);
+         tga = gen_rtx_SYMBOL_REF (Pmode, "__tls_get_addr");
+         dest = gen_reg_rtx (Pmode);
+         seq = GEN_INT (alpha_next_sequence_number++);
+         
+         emit_insn (gen_movdi_er_tlsgd (r16, pic_offset_table_rtx, x, seq));
+         insn = gen_call_value_osf_tlsgd (r0, tga, seq);
+         insn = emit_call_insn (insn);
+         CONST_OR_PURE_CALL_P (insn) = 1;
+         use_reg (&CALL_INSN_FUNCTION_USAGE (insn), r16);
+
+          insn = get_insns ();
+         end_sequence ();
+
+         emit_libcall_block (insn, dest, r0, x);
+         return dest;
+
+       case TLS_MODEL_LOCAL_DYNAMIC:
+         start_sequence ();
+
+         r0 = gen_rtx_REG (Pmode, 0);
+         r16 = gen_rtx_REG (Pmode, 16);
+         tga = gen_rtx_SYMBOL_REF (Pmode, "__tls_get_addr");
+         scratch = gen_reg_rtx (Pmode);
+         seq = GEN_INT (alpha_next_sequence_number++);
+
+         emit_insn (gen_movdi_er_tlsldm (r16, pic_offset_table_rtx, seq));
+         insn = gen_call_value_osf_tlsldm (r0, tga, seq);
+         insn = emit_call_insn (insn);
+         CONST_OR_PURE_CALL_P (insn) = 1;
+         use_reg (&CALL_INSN_FUNCTION_USAGE (insn), r16);
+
+          insn = get_insns ();
+         end_sequence ();
+
+         eqv = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, const0_rtx),
+                               UNSPEC_TLSLDM_CALL);
+         emit_libcall_block (insn, scratch, r0, eqv);
+
+         eqv = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, x), UNSPEC_DTPREL);
+         eqv = gen_rtx_CONST (Pmode, eqv);
+
+         if (alpha_tls_size == 64)
+           {
+             dest = gen_reg_rtx (Pmode);
+             emit_insn (gen_rtx_SET (VOIDmode, dest, eqv));
+             emit_insn (gen_adddi3 (dest, dest, scratch));
+             return dest;
+           }
+         if (alpha_tls_size == 32)
+           {
+             insn = gen_rtx_HIGH (Pmode, eqv);
+             insn = gen_rtx_PLUS (Pmode, scratch, insn);
+             scratch = gen_reg_rtx (Pmode);
+             emit_insn (gen_rtx_SET (VOIDmode, scratch, insn));
+           }
+         return gen_rtx_LO_SUM (Pmode, scratch, eqv);
+
+       case TLS_MODEL_INITIAL_EXEC:
+         eqv = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, x), UNSPEC_TPREL);
+         eqv = gen_rtx_CONST (Pmode, eqv);
+         tp = gen_reg_rtx (Pmode);
+         scratch = gen_reg_rtx (Pmode);
+         dest = gen_reg_rtx (Pmode);
+
+         emit_insn (gen_load_tp (tp));
+         emit_insn (gen_rtx_SET (VOIDmode, scratch, eqv));
+         emit_insn (gen_adddi3 (dest, tp, scratch));
+         return dest;
+
+       case TLS_MODEL_LOCAL_EXEC:
+         eqv = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, x), UNSPEC_TPREL);
+         eqv = gen_rtx_CONST (Pmode, eqv);
+         tp = gen_reg_rtx (Pmode);
+
+         emit_insn (gen_load_tp (tp));
+         if (alpha_tls_size == 32)
+           {
+             insn = gen_rtx_HIGH (Pmode, eqv);
+             insn = gen_rtx_PLUS (Pmode, tp, insn);
+             tp = gen_reg_rtx (Pmode);
+             emit_insn (gen_rtx_SET (VOIDmode, tp, insn));
+           }
+         return gen_rtx_LO_SUM (Pmode, tp, eqv);
+       }
+
       if (local_symbolic_operand (x, Pmode))
        {
          if (small_symbolic_operand (x, Pmode))
@@ -2589,6 +2904,8 @@ alpha_expand_mov (mode, operands)
       tmp = alpha_legitimize_address (operands[1], operands[0], mode);
       if (tmp)
        {
+         if (tmp == operands[0])
+           return true;
          operands[1] = tmp;
          return false;
        }
@@ -4906,10 +5223,31 @@ alpha_multipass_dfa_lookahead ()
   return (alpha_cpu == PROCESSOR_EV6 ? 4 : 2);
 }
 \f
+/* Machine-specific function data.  */
+
+struct machine_function
+{
+#if TARGET_ABI_UNICOSMK
+  /* List of call information words for calls from this function.  */
+  struct rtx_def *first_ciw;
+  struct rtx_def *last_ciw;
+  int ciw_count;
+
+  /* List of deferred case vectors.  */
+  struct rtx_def *addr_list;
+#else
+#if TARGET_ABI_OSF
+  const char *some_ld_name;
+#else
+  /* Non-empty struct.  */
+  char dummy;
+#endif
+#endif
+};
+
 /* Register global variables and machine-specific functions with the
    garbage collector.  */
 
-#if TARGET_ABI_UNICOSMK
 static void
 alpha_init_machine_status (p)
      struct function *p;
@@ -4917,10 +5255,15 @@ alpha_init_machine_status (p)
   p->machine =
     (struct machine_function *) xcalloc (1, sizeof (struct machine_function));
 
+#if TARGET_ABI_UNICOSMK
   p->machine->first_ciw = NULL_RTX;
   p->machine->last_ciw = NULL_RTX;
   p->machine->ciw_count = 0;
   p->machine->addr_list = NULL_RTX;
+#endif
+#if TARGET_ABI_OSF
+  p->machine->some_ld_name = NULL;
+#endif
 }
 
 static void
@@ -4931,8 +5274,10 @@ alpha_mark_machine_status (p)
 
   if (machine)
     {
+#if TARGET_ABI_UNICOSMK
       ggc_mark_rtx (machine->first_ciw);
       ggc_mark_rtx (machine->addr_list);
+#endif
     }
 }
 
@@ -4943,7 +5288,6 @@ alpha_free_machine_status (p)
   free (p->machine);
   p->machine = NULL;
 }
-#endif /* TARGET_ABI_UNICOSMK */
 
 /* Functions to save and restore alpha_return_addr_rtx.  */
 
@@ -5087,6 +5431,45 @@ get_round_mode_suffix ()
   abort ();
 }
 
+/* Locate some local-dynamic symbol still in use by this function
+   so that we can print its name in some movdi_er_tlsldm pattern.  */
+
+static const char *
+get_some_local_dynamic_name ()
+{
+  rtx insn;
+
+  if (cfun->machine->some_ld_name)
+    return cfun->machine->some_ld_name;
+
+  for (insn = get_insns (); insn ; insn = NEXT_INSN (insn))
+    if (INSN_P (insn)
+       && for_each_rtx (&PATTERN (insn), get_some_local_dynamic_name_1, 0))
+      return cfun->machine->some_ld_name;
+
+  abort ();
+}
+
+static int
+get_some_local_dynamic_name_1 (px, data)
+     rtx *px;
+     void *data ATTRIBUTE_UNUSED;
+{
+  rtx x = *px;
+
+  if (GET_CODE (x) == SYMBOL_REF)
+    {
+      const char *str = XSTR (x, 0);
+      if (str[0] == '@' && str[1] == 'D')
+       {
+          cfun->machine->some_ld_name = str;
+          return 1;
+       }
+    }
+
+  return 0;
+}
+
 /* Print an operand.  Recognize special options, documented below.  */
 
 void
@@ -5104,6 +5487,10 @@ print_operand (file, x, code)
       assemble_name (file, alpha_fnname);
       break;
 
+    case '&':
+      assemble_name (file, get_some_local_dynamic_name ());
+      break;
+
     case '/':
       {
        const char *trap = get_trap_mode_suffix ();
@@ -5145,13 +5532,30 @@ print_operand (file, x, code)
       break;
 
     case 'J':
-      if (GET_CODE (x) == CONST_INT)
-       {
-         if (INTVAL (x) != 0)
-           fprintf (file, "\t\t!lituse_jsr!%d", (int) INTVAL (x));
-       }
-      else
-       output_operand_lossage ("invalid %%J value");
+      {
+       const char *lituse;
+
+        if (GET_CODE (x) == UNSPEC && XINT (x, 1) == UNSPEC_TLSGD_CALL)
+         {
+           x = XVECEXP (x, 0, 0);
+           lituse = "lituse_tlsgd";
+         }
+       else if (GET_CODE (x) == UNSPEC && XINT (x, 1) == UNSPEC_TLSLDM_CALL)
+         {
+           x = XVECEXP (x, 0, 0);
+           lituse = "lituse_tlsldm";
+         }
+       else if (GET_CODE (x) == CONST_INT)
+         lituse = "lituse_jsr";
+       else
+         {
+           output_operand_lossage ("invalid %%J value");
+           break;
+         }
+
+       if (x != const0_rtx)
+         fprintf (file, "\t\t!%s!%d", lituse, (int) INTVAL (x));
+      }
       break;
 
     case 'r':
@@ -5385,6 +5789,19 @@ print_operand (file, x, code)
        fprintf (file, "%s", reg_names[REGNO (x)]);
       else if (GET_CODE (x) == MEM)
        output_address (XEXP (x, 0));
+      else if (GET_CODE (x) == CONST && GET_CODE (XEXP (x, 0)) == UNSPEC)
+       {
+         switch (XINT (XEXP (x, 0), 1))
+           {
+           case UNSPEC_DTPREL:
+           case UNSPEC_TPREL:
+             output_addr_const (file, XVECEXP (XEXP (x, 0), 0, 0));
+             break;
+           default:
+             output_operand_lossage ("unknown relocation unspec");
+             break;
+           }
+       }
       else
        output_addr_const (file, x);
       break;
@@ -5414,7 +5831,36 @@ print_operand_address (file, addr)
 
   if (GET_CODE (addr) == LO_SUM)
     {
-      output_addr_const (file, XEXP (addr, 1));
+      const char *reloc16, *reloclo;
+      rtx op1 = XEXP (addr, 1);
+
+      if (GET_CODE (op1) == CONST && GET_CODE (XEXP (op1, 0)) == UNSPEC)
+       {
+         op1 = XEXP (op1, 0);
+         switch (XINT (op1, 1))
+           {
+           case UNSPEC_DTPREL:
+             reloc16 = NULL;
+             reloclo = (alpha_tls_size == 16 ? "dtprel" : "dtprello");
+             break;
+           case UNSPEC_TPREL:
+             reloc16 = NULL;
+             reloclo = (alpha_tls_size == 16 ? "tprel" : "tprello");
+             break;
+           default:
+             output_operand_lossage ("unknown relocation unspec");
+             return;
+           }
+
+         output_addr_const (file, XVECEXP (op1, 0, 0));
+       }
+      else
+       {
+         reloc16 = "gprel";
+         reloclo = "gprellow";
+         output_addr_const (file, op1);
+       }
+
       if (offset)
        {
          fputc ('+', file);
@@ -5431,7 +5877,7 @@ print_operand_address (file, addr)
        abort ();
 
       fprintf (file, "($%d)\t\t!%s", basereg,
-              (basereg == 29 ? "gprel" : "gprellow"));
+              (basereg == 29 ? reloc16 : reloclo));
       return;
     }
 
index fc9ba92aacadfe7dd6eb95d0ba39a32de1ae2442..94e773295b93440a1e820f942e5feb2a0039a94f 100644 (file)
@@ -137,6 +137,7 @@ extern int target_flags;
 extern enum alpha_trap_precision alpha_tp;
 extern enum alpha_fp_rounding_mode alpha_fprm;
 extern enum alpha_fp_trap_mode alpha_fptm;
+extern int alpha_tls_size;
 
 /* This means that floating-point support exists in the target implementation
    of the Alpha architecture.  This is usually the default.  */
@@ -208,6 +209,10 @@ extern enum alpha_fp_trap_mode alpha_fptm;
 #define MASK_SMALL_DATA (1 << 13)
 #define TARGET_SMALL_DATA (target_flags & MASK_SMALL_DATA)
 
+/* This means emit thread pointer loads for kernel not user.  */
+#define MASK_TLS_KERNEL        (1 << 14)
+#define TARGET_TLS_KERNEL (target_flags & MASK_TLS_KERNEL)
+
 /* This means that the processor is an EV5, EV56, or PCA56.
    Unlike alpha_cpu this is not affected by -mtune= setting.  */
 #define MASK_CPU_EV5   (1 << 28)
@@ -251,6 +256,9 @@ extern enum alpha_fp_trap_mode alpha_fptm;
 #ifndef TARGET_FIXUP_EV5_PREFETCH
 #define TARGET_FIXUP_EV5_PREFETCH 0
 #endif
+#ifndef HAVE_AS_TLS
+#define HAVE_AS_TLS 0
+#endif
 
 /* Macro to define tables used to set the flags.
    This is a list in braces of pairs in braces,
@@ -293,6 +301,8 @@ extern enum alpha_fp_trap_mode alpha_fptm;
      N_("Emit 16-bit relocations to the small data areas")},           \
     {"large-data", -MASK_SMALL_DATA,                                   \
      N_("Emit 32-bit relocations to the small data areas")},           \
+    {"tls-kernel", MASK_TLS_KERNEL,                                    \
+     N_("Emit rdval instead of rduniq for thread pointer")},           \
     {"", TARGET_DEFAULT | TARGET_CPU_DEFAULT                           \
         | TARGET_DEFAULT_EXPLICIT_RELOCS, ""} }
 
@@ -316,6 +326,7 @@ extern const char *alpha_fprm_string;       /* For -mfp-rounding-mode=[n|m|c|d] */
 extern const char *alpha_fptm_string;  /* For -mfp-trap-mode=[n|u|su|sui]  */
 extern const char *alpha_tp_string;    /* For -mtrap-precision=[p|f|i] */
 extern const char *alpha_mlat_string;  /* For -mmemory-latency= */
+extern const char *alpha_tls_size_string; /* For -mtls-size= */
 
 #define TARGET_OPTIONS                                 \
 {                                                      \
@@ -331,6 +342,8 @@ extern const char *alpha_mlat_string;       /* For -mmemory-latency= */
    N_("Control the precision given to fp exceptions")},        \
   {"memory-latency=",  &alpha_mlat_string,             \
    N_("Tune expected memory latency")},                        \
+  {"tls-size=",                &alpha_tls_size_string,         \
+   N_("Specify bit size of immediate TLS offsets")},   \
 }
 
 /* This macro defines names of additional specifications to put in the
@@ -681,7 +694,7 @@ extern const char *alpha_mlat_string;       /* For -mmemory-latency= */
    class that represents their union.  */
    
 enum reg_class {
-  NO_REGS, R24_REG, R25_REG, R27_REG,
+  NO_REGS, R0_REG, R24_REG, R25_REG, R27_REG,
   GENERAL_REGS, FLOAT_REGS, ALL_REGS,
   LIM_REG_CLASSES
 };
@@ -690,8 +703,8 @@ enum reg_class {
 
 /* Give names of register classes as strings for dump file.  */
 
-#define REG_CLASS_NAMES                                \
- {"NO_REGS", "R24_REG", "R25_REG", "R27_REG",  \
+#define REG_CLASS_NAMES                                        \
+ {"NO_REGS", "R0_REG", "R24_REG", "R25_REG", "R27_REG",        \
   "GENERAL_REGS", "FLOAT_REGS", "ALL_REGS" }
 
 /* Define which registers fit in which classes.
@@ -700,6 +713,7 @@ enum reg_class {
 
 #define REG_CLASS_CONTENTS                             \
 { {0x00000000, 0x00000000},    /* NO_REGS */           \
+  {0x00000001, 0x00000000},    /* R0_REG */            \
   {0x01000000, 0x00000000},    /* R24_REG */           \
   {0x02000000, 0x00000000},    /* R25_REG */           \
   {0x08000000, 0x00000000},    /* R27_REG */           \
@@ -713,7 +727,8 @@ enum reg_class {
    or could index an array.  */
 
 #define REGNO_REG_CLASS(REGNO)                 \
- ((REGNO) == 24 ? R24_REG                      \
+ ((REGNO) == 0 ? R0_REG                                \
+  : (REGNO) == 24 ? R24_REG                    \
   : (REGNO) == 25 ? R25_REG                    \
   : (REGNO) == 27 ? R27_REG                    \
   : (REGNO) >= 32 && (REGNO) <= 62 ? FLOAT_REGS        \
@@ -730,6 +745,7 @@ enum reg_class {
   : (C) == 'b' ? R25_REG               \
   : (C) == 'c' ? R27_REG               \
   : (C) == 'f' ? FLOAT_REGS            \
+  : (C) == 'v' ? R0_REG                        \
   : NO_REGS)
 
 /* Define this macro to change register usage conditional on target flags.  */
@@ -1710,7 +1726,7 @@ do {                                                                           \
 #define ASM_OUTPUT_LABELREF(STREAM, NAME)      \
 do {                                           \
   const char *name_ = NAME;                    \
-  if (*name_ == '@')                           \
+  if (*name_ == '@' || *name == '%')           \
     name_ += 2;                                        \
   if (*name_ == '*')                           \
     name_++;                                   \
@@ -1893,7 +1909,7 @@ do {                                              \
 
 #define PRINT_OPERAND_PUNCT_VALID_P(CODE) \
   ((CODE) == '/' || (CODE) == ',' || (CODE) == '-' || (CODE) == '~' \
-   || (CODE) == '#' || (CODE) == '*')
+   || (CODE) == '#' || (CODE) == '*' || (CODE) == '&')
 \f
 /* Print a memory address as an operand to reference that memory location.  */
 
@@ -1929,6 +1945,12 @@ do {                                             \
   {"local_symbolic_operand", {SYMBOL_REF, CONST, LABEL_REF}},          \
   {"small_symbolic_operand", {SYMBOL_REF, CONST}},                     \
   {"global_symbolic_operand", {SYMBOL_REF, CONST}},                    \
+  {"dtp16_symbolic_operand", {CONST}},                                 \
+  {"dtp32_symbolic_operand", {CONST}},                                 \
+  {"gotdtp_symbolic_operand", {CONST}},                                        \
+  {"tp16_symbolic_operand", {CONST}},                                  \
+  {"tp32_symbolic_operand", {CONST}},                                  \
+  {"gottp_symbolic_operand", {CONST}},                                 \
   {"call_operand", {REG, SYMBOL_REF}},                                 \
   {"input_operand", {SUBREG, REG, MEM, CONST_INT, CONST_DOUBLE,                \
                     SYMBOL_REF, CONST, LABEL_REF, HIGH}},              \
index 1df715ad0c27e78bc04422484cf4832e1aba30ad..85e5f4cfcc5a08d3073bbe69799ac77a80611eac 100644 (file)
@@ -1,6 +1,6 @@
 ;; Machine description for DEC Alpha for GNU C compiler
 ;; Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
-;; 2000, 2001 Free Software Foundation, Inc.
+;; 2000, 2001, 2002 Free Software Foundation, Inc.
 ;; Contributed by Richard Kenner (kenner@vlsi1.ultra.nyu.edu)
 ;;
 ;; This file is part of GNU CC.
    (UNSPEC_LITUSE      12)
    (UNSPEC_SIBCALL     13)
    (UNSPEC_SYMBOL      14)
+
+   ;; TLS Support
+   (UNSPEC_TLSGD_CALL  15)
+   (UNSPEC_TLSLDM_CALL 16)
+   (UNSPEC_TLSGD       17)
+   (UNSPEC_TLSLDM      18)
+   (UNSPEC_DTPREL      19)
+   (UNSPEC_TPREL       20)
+   (UNSPEC_TP          21)
   ])
 
 ;; UNSPEC_VOLATILE:
@@ -57,6 +66,7 @@
    (UNSPECV_FORCE_MOV  9)
    (UNSPECV_LDGP1      10)
    (UNSPECV_PLDGP2     11)     ; prologue ldgp
+   (UNSPECV_SET_TP     12)
   ])
 
 ;; Where necessary, the suffixes _le and _be are used to distinguish between
@@ -335,6 +345,48 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi,none"
   ""
   "")
 
+(define_insn "*adddi_er_lo16_dtp"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+       (lo_sum:DI (match_operand:DI 1 "register_operand" "r")
+                  (match_operand:DI 2 "dtp16_symbolic_operand" "")))]
+  "HAVE_AS_TLS"
+  "lda %0,%2(%1)\t\t!dtprel")
+
+(define_insn "*adddi_er_hi32_dtp"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+       (plus:DI (match_operand:DI 1 "register_operand" "r")
+                (high:DI (match_operand:DI 2 "dtp32_symbolic_operand" ""))))]
+  "HAVE_AS_TLS"
+  "ldah %0,%2(%1)\t\t!dtprelhi")
+
+(define_insn "*adddi_er_lo32_dtp"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+       (lo_sum:DI (match_operand:DI 1 "register_operand" "r")
+                  (match_operand:DI 2 "dtp32_symbolic_operand" "")))]
+  "HAVE_AS_TLS"
+  "lda %0,%2(%1)\t\t!dtprello")
+
+(define_insn "*adddi_er_lo16_tp"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+       (lo_sum:DI (match_operand:DI 1 "register_operand" "r")
+                  (match_operand:DI 2 "tp16_symbolic_operand" "")))]
+  "HAVE_AS_TLS"
+  "lda %0,%2(%1)\t\t!tprel")
+
+(define_insn "*adddi_er_hi32_tp"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+       (plus:DI (match_operand:DI 1 "register_operand" "r")
+                (high:DI (match_operand:DI 2 "tp32_symbolic_operand" ""))))]
+  "HAVE_AS_TLS"
+  "ldah %0,%2(%1)\t\t!tprelhi")
+
+(define_insn "*adddi_er_lo32_tp"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+       (lo_sum:DI (match_operand:DI 1 "register_operand" "r")
+                  (match_operand:DI 2 "tp32_symbolic_operand" "")))]
+  "HAVE_AS_TLS"
+  "lda %0,%2(%1)\t\t!tprello")
+
 (define_insn "*adddi_er_high_l"
   [(set (match_operand:DI 0 "register_operand" "=r")
        (plus:DI (match_operand:DI 1 "register_operand" "r")
@@ -4805,6 +4857,43 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi,none"
   "!TARGET_ABI_WINDOWS_NT"
   "call_pal 0x81"
   [(set_attr "type" "ibr")])
+
+;; For userland, we load the thread pointer from the TCB.
+;; For the kernel, we load the per-cpu private value.
+
+(define_insn "load_tp"
+  [(set (match_operand:DI 0 "register_operand" "=v")
+       (unspec:DI [(const_int 0)] UNSPEC_TP))]
+  "TARGET_ABI_OSF"
+{
+  if (TARGET_TLS_KERNEL)
+    return "call_pal 0x32";
+  else
+    return "call_pal 0x9e";
+}
+  [(set_attr "type" "ibr")])
+
+;; For completeness, and possibly a __builtin function, here's how to
+;; set the thread pointer.  Since we don't describe enough of this
+;; quantity for CSE, we have to use a volatile unspec, and then there's
+;; not much point in creating an R16_REG register class.
+
+(define_expand "set_tp"
+  [(set (reg:DI 16) (match_operand:DI 0 "input_operand" ""))
+   (unspec_volatile [(reg:DI 16)] UNSPECV_SET_TP)]
+  "TARGET_ABI_OSF"
+  "")
+
+(define_insn "*set_tp"
+  [(unspec_volatile [(reg:DI 16)] UNSPECV_SET_TP)]
+  "TARGET_ABI_OSF"
+{
+  if (TARGET_TLS_KERNEL)
+    return "call_pal 0x31";
+  else
+    return "call_pal 0x9f";
+}
+  [(set_attr "type" "ibr")])
 \f
 ;; Finally, we have the basic data motion insns.  The byte and word insns
 ;; are done via define_expand.  Start with the floating-point insns, since
@@ -5282,6 +5371,75 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi,none"
     }
 })
 
+(define_insn "movdi_er_tlsgd"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+       (unspec:DI [(match_operand:DI 1 "register_operand" "r")
+                   (match_operand:DI 2 "symbolic_operand" "")
+                   (match_operand 3 "const_int_operand" "")]
+                  UNSPEC_TLSGD))]
+  "HAVE_AS_TLS"
+{
+  if (INTVAL (operands[3]) == 0)
+    return "lda %0,%2(%1)\t\t!tlsgd";
+  else
+    return "lda %0,%2(%1)\t\t!tlsgd!%3";
+})
+
+(define_insn "movdi_er_tlsldm"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+       (unspec:DI [(match_operand:DI 1 "register_operand" "r")
+                   (match_operand 2 "const_int_operand" "")]
+                  UNSPEC_TLSLDM))]
+  "HAVE_AS_TLS"
+{
+  if (INTVAL (operands[2]) == 0)
+    return "lda %0,%&(%1)\t\t!tlsldm";
+  else
+    return "lda %0,%&(%1)\t\t!tlsldm!%2";
+})
+
+(define_insn "*movdi_er_gotdtp"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+       (unspec:DI [(match_operand:DI 1 "register_operand" "r")
+                   (match_operand:DI 2 "symbolic_operand" "")]
+                  UNSPEC_DTPREL))]
+  "HAVE_AS_TLS"
+  "ldq %0,%2(%1)\t\t!gotdtprel"
+  [(set_attr "type" "ild")])
+
+(define_split
+  [(set (match_operand:DI 0 "register_operand" "")
+       (match_operand:DI 1 "gotdtp_symbolic_operand" ""))]
+  "HAVE_AS_TLS && reload_completed"
+  [(set (match_dup 0)
+       (unspec:DI [(match_dup 2)
+                   (match_dup 1)] UNSPEC_DTPREL))]
+{
+  operands[1] = XVECEXP (XEXP (operands[1], 0), 0, 0);
+  operands[2] = pic_offset_table_rtx;
+})
+
+(define_insn "*movdi_er_gottp"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+       (unspec:DI [(match_operand:DI 1 "register_operand" "r")
+                   (match_operand:DI 2 "symbolic_operand" "")]
+                  UNSPEC_TPREL))]
+  "HAVE_AS_TLS"
+  "ldq %0,%2(%1)\t\t!gottprel"
+  [(set_attr "type" "ild")])
+
+(define_split
+  [(set (match_operand:DI 0 "register_operand" "")
+       (match_operand:DI 1 "gottp_symbolic_operand" ""))]
+  "HAVE_AS_TLS && reload_completed"
+  [(set (match_dup 0)
+       (unspec:DI [(match_dup 2)
+                   (match_dup 1)] UNSPEC_TPREL))]
+{
+  operands[1] = XVECEXP (XEXP (operands[1], 0), 0, 0);
+  operands[2] = pic_offset_table_rtx;
+})
+
 (define_insn "*movdi_er_nofix"
   [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,r,r,r,r,m,*f,*f,Q")
        (match_operand:DI 1 "input_operand" "rJ,K,L,T,s,m,rJ,*fJ,Q,*f"))]
@@ -6720,7 +6878,7 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi,none"
        (plus:DI (pc) (const_int 4)))
    (unspec_volatile [(reg:DI 29)] UNSPECV_BLOCKAGE)
    (use (match_operand 3 "" ""))
-   (use (match_operand 4 "const_int_operand" ""))]
+   (use (match_operand 4 "" ""))]
   "TARGET_EXPLICIT_RELOCS && TARGET_ABI_OSF"
   "jsr $26,(%1),%3%J4"
   [(set_attr "type" "jsr")])
@@ -6740,6 +6898,70 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi,none"
   [(set_attr "type" "jsr")
    (set_attr "length" "*,*,8")])
 
+(define_insn_and_split "call_value_osf_tlsgd"
+  [(set (match_operand 0 "" "")
+       (call (mem:DI (match_operand:DI 1 "symbolic_operand" ""))
+             (const_int 0)))
+   (unspec [(match_operand:DI 2 "const_int_operand" "")] UNSPEC_TLSGD_CALL)
+   (use (reg:DI 29))
+   (clobber (reg:DI 26))]
+  "HAVE_AS_TLS"
+  "#"
+  "&& reload_completed"
+  [(set (match_dup 3)
+       (unspec:DI [(match_dup 5)
+                   (match_dup 1)
+                   (match_dup 2)] UNSPEC_LITERAL))
+   (parallel [(set (match_dup 0)
+                  (call (mem:DI (match_dup 3))
+                        (const_int 0)))
+             (set (reg:DI 26) (plus:DI (pc) (const_int 4)))
+             (unspec_volatile [(match_dup 5)] UNSPECV_BLOCKAGE)
+             (use (match_dup 1))
+             (use (unspec [(match_dup 2)] UNSPEC_TLSGD_CALL))])
+   (set (match_dup 5)
+       (unspec_volatile:DI [(reg:DI 26) (match_dup 4)] UNSPECV_LDGP1))
+   (set (match_dup 5)
+       (unspec:DI [(match_dup 5) (match_dup 4)] UNSPEC_LDGP2))]
+{
+  operands[3] = gen_rtx_REG (Pmode, 27);
+  operands[4] = GEN_INT (alpha_next_sequence_number++);
+  operands[5] = pic_offset_table_rtx;
+}
+  [(set_attr "type" "multi")])
+
+(define_insn_and_split "call_value_osf_tlsldm"
+  [(set (match_operand 0 "" "")
+       (call (mem:DI (match_operand:DI 1 "symbolic_operand" ""))
+             (const_int 0)))
+   (unspec [(match_operand:DI 2 "const_int_operand" "")] UNSPEC_TLSLDM_CALL)
+   (use (reg:DI 29))
+   (clobber (reg:DI 26))]
+  "HAVE_AS_TLS"
+  "#"
+  "&& reload_completed"
+  [(set (match_dup 3)
+       (unspec:DI [(match_dup 5)
+                   (match_dup 1)
+                   (match_dup 2)] UNSPEC_LITERAL))
+   (parallel [(set (match_dup 0)
+                  (call (mem:DI (match_dup 3))
+                        (const_int 0)))
+             (set (reg:DI 26) (plus:DI (pc) (const_int 4)))
+             (unspec_volatile [(match_dup 5)] UNSPECV_BLOCKAGE)
+             (use (match_dup 1))
+             (use (unspec [(match_dup 2)] UNSPEC_TLSLDM_CALL))])
+   (set (reg:DI 29)
+       (unspec_volatile:DI [(reg:DI 26) (match_dup 4)] UNSPECV_LDGP1))
+   (set (reg:DI 29)
+       (unspec:DI [(reg:DI 29) (match_dup 4)] UNSPEC_LDGP2))]
+{
+  operands[3] = gen_rtx_REG (Pmode, 27);
+  operands[4] = GEN_INT (alpha_next_sequence_number++);
+  operands[5] = pic_offset_table_rtx;
+}
+  [(set_attr "type" "multi")])
+
 (define_insn "*call_value_osf_1"
   [(set (match_operand 0 "" "")
        (call (mem:DI (match_operand:DI 1 "call_operand" "c,R,s"))
@@ -6815,4 +7037,3 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi,none"
   "TARGET_ABI_UNICOSMK"
   "jsr $26,(%1)"
   [(set_attr "type" "jsr")])
-
index a8c8915d406f93aa53d0b791e080fa1cdebaf61e..d21ba8844c4d1eb5e43454f552261eaaa58a43d2 100644 (file)
@@ -293,19 +293,6 @@ do {                                                               \
 #undef EPILOGUE_USES
 #define EPILOGUE_USES(REGNO)  ((REGNO) == 26 || (REGNO) == 15)
 
-/* Machine-specific function data.  */
-
-struct machine_function
-{
-  /* List of call information words for calls from this function.  */
-  struct rtx_def *first_ciw;
-  struct rtx_def *last_ciw;
-  int ciw_count;
-
-  /* List of deferred case vectors.  */
-  struct rtx_def *addr_list;
-};
-
 /* Would have worked, only the stack doesn't seem to be executable
 #undef TRAMPOLINE_TEMPLATE
 #define TRAMPOLINE_TEMPLATE(FILE)                      \
index 5defdaa0a03eaee59fa94a5e6155aa3fda405ded..e9bdc235b51f7ade65a2b1fdfa567d82efb69479 100755 (executable)
@@ -7399,6 +7399,28 @@ conftest_s=
 tls_first_major=
 tls_first_minor=
 case "$target" in
+  alpha*-*-*)
+    conftest_s='
+       .section ".tdata","awT",@progbits
+foo:   .long   25
+       .text
+       ldq     $27,__tls_get_addr($29)         !literal!1
+       lda     $16,foo($29)                    !tlsgd!1
+       jsr     $26,($27),__tls_get_addr        !lituse_tlsgd!1
+       ldq     $27,__tls_get_addr($29)         !literal!2
+       lda     $16,foo($29)                    !tlsldm!2
+       jsr     $26,($27),__tls_get_addr        !lituse_tlsldm!2
+       ldq     $1,foo($29)                     !gotdtprel
+       ldah    $2,foo($29)                     !dtprelhi
+       lda     $3,foo($2)                      !dtprello
+       lda     $4,foo($29)                     !dtprel
+       ldq     $1,foo($29)                     !gottprel
+       ldah    $2,foo($29)                     !tprelhi
+       lda     $3,foo($2)                      !tprello
+       lda     $4,foo($29)                     !tprel'
+       tls_first_major=2
+       tls_first_minor=13
+       ;;
   i[34567]86-*-*)
     conftest_s='
        .section ".tdata","awT",@progbits
@@ -7463,7 +7485,7 @@ case "$target" in
   # All TARGET_ABI_OSF targets.
   alpha*-*-osf* | alpha*-*-linux* | alpha*-*-*bsd*)
     echo $ac_n "checking assembler supports explicit relocations""... $ac_c" 1>&6
-echo "configure:7467: checking assembler supports explicit relocations" >&5
+echo "configure:7489: checking assembler supports explicit relocations" >&5
 if eval "test \"`echo '$''{'gcc_cv_as_explicit_relocs'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -7513,7 +7535,7 @@ EOF
     ;;
   sparc*-*-*)
     echo $ac_n "checking assembler .register pseudo-op support""... $ac_c" 1>&6
-echo "configure:7517: checking assembler .register pseudo-op support" >&5
+echo "configure:7539: checking assembler .register pseudo-op support" >&5
 if eval "test \"`echo '$''{'gcc_cv_as_register_pseudo_op'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -7541,7 +7563,7 @@ EOF
     fi
 
     echo $ac_n "checking assembler supports -relax""... $ac_c" 1>&6
-echo "configure:7545: checking assembler supports -relax" >&5
+echo "configure:7567: checking assembler supports -relax" >&5
 if eval "test \"`echo '$''{'gcc_cv_as_relax_opt'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -7569,7 +7591,7 @@ EOF
     fi
 
     echo $ac_n "checking assembler and linker support unaligned pc related relocs""... $ac_c" 1>&6
-echo "configure:7573: checking assembler and linker support unaligned pc related relocs" >&5
+echo "configure:7595: checking assembler and linker support unaligned pc related relocs" >&5
 if eval "test \"`echo '$''{'gcc_cv_as_sparc_ua_pcrel'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -7596,7 +7618,7 @@ EOF
     fi
 
     echo $ac_n "checking assembler and linker support unaligned pc related relocs against hidden symbols""... $ac_c" 1>&6
-echo "configure:7600: checking assembler and linker support unaligned pc related relocs against hidden symbols" >&5
+echo "configure:7622: checking assembler and linker support unaligned pc related relocs against hidden symbols" >&5
 if eval "test \"`echo '$''{'gcc_cv_as_sparc_ua_pcrel_hidden'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -7637,7 +7659,7 @@ EOF
 
     if test "x$gcc_cv_as_flags64" != xno; then
        echo $ac_n "checking for assembler offsetable %lo() support""... $ac_c" 1>&6
-echo "configure:7641: checking for assembler offsetable %lo() support" >&5
+echo "configure:7663: checking for assembler offsetable %lo() support" >&5
 if eval "test \"`echo '$''{'gcc_cv_as_offsetable_lo10'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -7677,7 +7699,7 @@ EOF
 
   i[34567]86-*-* | x86_64-*-*)
     echo $ac_n "checking assembler instructions""... $ac_c" 1>&6
-echo "configure:7681: checking assembler instructions" >&5
+echo "configure:7703: checking assembler instructions" >&5
     gcc_cv_as_instructions=
     if test x$gcc_cv_gas_major_version != x -a x$gcc_cv_gas_minor_version != x; then
       if test "$gcc_cv_gas_major_version" -eq 2 -a "$gcc_cv_gas_minor_version" -ge 9 -o "$gcc_cv_gas_major_version" -gt 2; then
@@ -7704,7 +7726,7 @@ EOF
     echo "$ac_t""$gcc_cv_as_instructions" 1>&6
 
     echo $ac_n "checking assembler GOTOFF in data directives""... $ac_c" 1>&6
-echo "configure:7708: checking assembler GOTOFF in data directives" >&5
+echo "configure:7730: checking assembler GOTOFF in data directives" >&5
     gcc_cv_as_gotoff_in_data=no
     if test x$gcc_cv_gas_major_version != x -a x$gcc_cv_gas_minor_version != x
     then
@@ -7734,7 +7756,7 @@ EOF
 esac
 
 echo $ac_n "checking assembler dwarf2 debug_line support""... $ac_c" 1>&6
-echo "configure:7738: checking assembler dwarf2 debug_line support" >&5
+echo "configure:7760: checking assembler dwarf2 debug_line support" >&5
 gcc_cv_as_dwarf2_debug_line=no
 # ??? Not all targets support dwarf2 debug_line, even within a version
 # of gas.  Moreover, we need to emit a valid instruction to trigger any
@@ -7790,7 +7812,7 @@ fi
 echo "$ac_t""$gcc_cv_as_dwarf2_debug_line" 1>&6
 
 echo $ac_n "checking assembler --gdwarf2 support""... $ac_c" 1>&6
-echo "configure:7794: checking assembler --gdwarf2 support" >&5
+echo "configure:7816: checking assembler --gdwarf2 support" >&5
 gcc_cv_as_gdwarf2_flag=no
 if test x$gcc_cv_gas_major_version != x -a x$gcc_cv_gas_minor_version != x;
 then
@@ -7819,7 +7841,7 @@ fi
 echo "$ac_t""$gcc_cv_as_gdwarf2_flag" 1>&6
 
 echo $ac_n "checking assembler --gstabs support""... $ac_c" 1>&6
-echo "configure:7823: checking assembler --gstabs support" >&5
+echo "configure:7845: checking assembler --gstabs support" >&5
 gcc_cv_as_gstabs_flag=no
 if test x$gcc_cv_gas_major_version != x -a x$gcc_cv_gas_minor_version != x;
 then
@@ -7847,7 +7869,7 @@ fi
 echo "$ac_t""$gcc_cv_as_gstabs_flag" 1>&6
 
 echo $ac_n "checking linker PT_GNU_EH_FRAME support""... $ac_c" 1>&6
-echo "configure:7851: checking linker PT_GNU_EH_FRAME support" >&5
+echo "configure:7873: checking linker PT_GNU_EH_FRAME support" >&5
 gcc_cv_ld_eh_frame_hdr=no
 if test x$gcc_cv_gld_major_version != x -a x$gcc_cv_gld_minor_version != x; then
   if test "$gcc_cv_gld_major_version" -eq 2 -a "$gcc_cv_gld_minor_version" -ge 12 -o "$gcc_cv_gld_major_version" -gt 2 && grep 'EMUL = elf' ../ld/Makefile > /dev/null; then
@@ -8010,7 +8032,7 @@ fi
 
 
 echo $ac_n "checking whether to enable maintainer-specific portions of Makefiles""... $ac_c" 1>&6
-echo "configure:8014: checking whether to enable maintainer-specific portions of Makefiles" >&5
+echo "configure:8036: checking whether to enable maintainer-specific portions of Makefiles" >&5
     # Check whether --enable-maintainer-mode or --disable-maintainer-mode was given.
 if test "${enable_maintainer_mode+set}" = set; then
   enableval="$enable_maintainer_mode"
index a76dac824f00eaee962d0d84cca63a8b3b33f9c8..c28efa0e6201e0d7df69989e1e14af42f23910ac 100644 (file)
@@ -1725,6 +1725,28 @@ tls_first_major=
 tls_first_minor=
 case "$target" in
 changequote(,)dnl
+  alpha*-*-*)
+    conftest_s='
+       .section ".tdata","awT",@progbits
+foo:   .long   25
+       .text
+       ldq     $27,__tls_get_addr($29)         !literal!1
+       lda     $16,foo($29)                    !tlsgd!1
+       jsr     $26,($27),__tls_get_addr        !lituse_tlsgd!1
+       ldq     $27,__tls_get_addr($29)         !literal!2
+       lda     $16,foo($29)                    !tlsldm!2
+       jsr     $26,($27),__tls_get_addr        !lituse_tlsldm!2
+       ldq     $1,foo($29)                     !gotdtprel
+       ldah    $2,foo($29)                     !dtprelhi
+       lda     $3,foo($2)                      !dtprello
+       lda     $4,foo($29)                     !dtprel
+       ldq     $1,foo($29)                     !gottprel
+       ldah    $2,foo($29)                     !tprelhi
+       lda     $3,foo($2)                      !tprello
+       lda     $4,foo($29)                     !tprel'
+       tls_first_major=2
+       tls_first_minor=13
+       ;;
   i[34567]86-*-*)
 changequote([,])dnl
     conftest_s='