aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorRichard Henderson <rth@redhat.com>2002-05-31 17:19:10 -0700
committerRichard Henderson <rth@gcc.gnu.org>2002-05-31 17:19:10 -0700
commit6f9b006de010523b6186de10c00b1f0c366cb6c0 (patch)
treea1943ec632b73b43e8c2df8b6aedeb318c0f7e90 /gcc
parent39e5db1a7c9714f7a6c3f5f24617c81e8f8d87b2 (diff)
downloadgcc-6f9b006de010523b6186de10c00b1f0c366cb6c0.zip
gcc-6f9b006de010523b6186de10c00b1f0c366cb6c0.tar.gz
gcc-6f9b006de010523b6186de10c00b1f0c366cb6c0.tar.bz2
configure.in (HAVE_AS_TLS): Add alpha tests.
* 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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog46
-rw-r--r--gcc/config/alpha/alpha-protos.h6
-rw-r--r--gcc/config/alpha/alpha.c556
-rw-r--r--gcc/config/alpha/alpha.h34
-rw-r--r--gcc/config/alpha/alpha.md227
-rw-r--r--gcc/config/alpha/unicosmk.h13
-rwxr-xr-xgcc/configure48
-rw-r--r--gcc/configure.in22
8 files changed, 862 insertions, 90 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 7e5103e..efd25dd 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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
diff --git a/gcc/config/alpha/alpha-protos.h b/gcc/config/alpha/alpha-protos.h
index 2eb195a..cbe8e34 100644
--- a/gcc/config/alpha/alpha-protos.h
+++ b/gcc/config/alpha/alpha-protos.h
@@ -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));
diff --git a/gcc/config/alpha/alpha.c b/gcc/config/alpha/alpha.c
index 9681d92..bee3dc1 100644
--- a/gcc/config/alpha/alpha.c
+++ b/gcc/config/alpha/alpha.c
@@ -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;
/* 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
}
/* 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;
+}
+
/* 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);
}
+/* 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;
}
diff --git a/gcc/config/alpha/alpha.h b/gcc/config/alpha/alpha.h
index fc9ba92..94e7732 100644
--- a/gcc/config/alpha/alpha.h
+++ b/gcc/config/alpha/alpha.h
@@ -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) == '&')
/* 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}}, \
diff --git a/gcc/config/alpha/alpha.md b/gcc/config/alpha/alpha.md
index 1df715a..85e5f4c 100644
--- a/gcc/config/alpha/alpha.md
+++ b/gcc/config/alpha/alpha.md
@@ -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.
@@ -40,6 +40,15 @@
(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")])
;; 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")])
-
diff --git a/gcc/config/alpha/unicosmk.h b/gcc/config/alpha/unicosmk.h
index a8c8915..d21ba88 100644
--- a/gcc/config/alpha/unicosmk.h
+++ b/gcc/config/alpha/unicosmk.h
@@ -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) \
diff --git a/gcc/configure b/gcc/configure
index 5defdaa..e9bdc23 100755
--- a/gcc/configure
+++ b/gcc/configure
@@ -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"
diff --git a/gcc/configure.in b/gcc/configure.in
index a76dac8..c28efa0 100644
--- a/gcc/configure.in
+++ b/gcc/configure.in
@@ -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='