This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
alpha tls support
- From: Richard Henderson <rth at redhat dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Fri, 31 May 2002 17:20:33 -0700
- Subject: alpha tls support
* 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.
Index: gcc/configure.in
===================================================================
RCS file: /cvs/gcc/gcc/gcc/configure.in,v
retrieving revision 1.595
diff -c -p -d -r1.595 configure.in
*** gcc/configure.in 31 May 2002 20:11:46 -0000 1.595
--- gcc/configure.in 1 Jun 2002 00:11:16 -0000
*************** tls_first_major=
*** 1725,1730 ****
--- 1725,1752 ----
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='
Index: gcc/config/alpha/alpha-protos.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/alpha/alpha-protos.h,v
retrieving revision 1.33
diff -c -p -d -r1.33 alpha-protos.h
*** gcc/config/alpha/alpha-protos.h 19 May 2002 05:22:58 -0000 1.33
--- gcc/config/alpha/alpha-protos.h 1 Jun 2002 00:11:16 -0000
*************** extern int local_symbolic_operand PARAMS
*** 61,66 ****
--- 61,72 ----
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: gcc/config/alpha/alpha.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/alpha/alpha.c,v
retrieving revision 1.255
diff -c -p -d -r1.255 alpha.c
*** gcc/config/alpha/alpha.c 28 May 2002 08:42:20 -0000 1.255
--- gcc/config/alpha/alpha.c 1 Jun 2002 00:11:16 -0000
*************** enum alpha_fp_rounding_mode alpha_fprm;
*** 69,74 ****
--- 69,78 ----
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= */
*************** const char *alpha_tp_string; /* -mtrap-p
*** 77,82 ****
--- 81,87 ----
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. */
*************** int alpha_this_literal_sequence_number;
*** 113,118 ****
--- 118,127 ----
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
*************** static int some_small_symbolic_operand_1
*** 125,132 ****
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
--- 134,139 ----
*************** static const char *get_trap_mode_suffix
*** 147,152 ****
--- 154,163 ----
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
*************** static void alpha_elf_select_rtx_section
*** 173,186 ****
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));
--- 184,195 ----
*************** static void unicosmk_unique_section PARA
*** 266,271 ****
--- 275,283 ----
#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. */
*************** override_options ()
*** 385,390 ****
--- 397,414 ----
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);
*************** override_options ()
*** 527,538 ****
/* 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. */
--- 551,560 ----
*************** input_operand (op, mode)
*** 857,863 ****
symbolic operands to be reconstructed from their high/lo_sum
form. */
return (small_symbolic_operand (op, mode)
! || global_symbolic_operand (op, mode));
}
/* This handles both the Windows/NT and OSF cases. */
--- 879,887 ----
symbolic operands to be reconstructed from their high/lo_sum
form. */
return (small_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. */
*************** direct_call_operand (op, mode)
*** 946,974 ****
/* 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;
{
if (mode != VOIDmode && GET_MODE (op) != VOIDmode && mode != GET_MODE (op))
return 0;
--- 970,982 ----
/* Return true if OP is a LABEL_REF, or SYMBOL_REF or CONST referencing
a variable known to be defined in this file. */
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;
*************** local_symbolic_operand (op, mode)
*** 983,989 ****
if (GET_CODE (op) != SYMBOL_REF)
return 0;
! return local_symbol_p (op);
}
/* Return true if OP is a SYMBOL_REF or CONST referencing a variable
--- 991,1016 ----
if (GET_CODE (op) != SYMBOL_REF)
return 0;
! /* 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
*************** small_symbolic_operand (op, mode)
*** 1015,1021 ****
else
{
str = XSTR (op, 0);
! return str[0] == '@' && str[1] == 's';
}
}
--- 1042,1048 ----
else
{
str = XSTR (op, 0);
! return str[0] == '@' && str[1] == 'S';
}
}
*************** global_symbolic_operand (op, mode)
*** 1027,1032 ****
--- 1054,1061 ----
rtx op;
enum machine_mode mode;
{
+ const char *str;
+
if (mode != VOIDmode && GET_MODE (op) != VOIDmode && mode != GET_MODE (op))
return 0;
*************** global_symbolic_operand (op, mode)
*** 1038,1044 ****
if (GET_CODE (op) != SYMBOL_REF)
return 0;
! return ! local_symbol_p (op);
}
/* Return 1 if OP is a valid operand for the MEM of a CALL insn. */
--- 1067,1078 ----
if (GET_CODE (op) != SYMBOL_REF)
return 0;
! 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. */
*************** symbolic_operand (op, mode)
*** 1091,1096 ****
--- 1125,1234 ----
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. */
*************** alpha_tablejump_best_label (insn)
*** 1561,1566 ****
--- 1699,1752 ----
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. */
*************** alpha_encode_section_info (decl, first)
*** 1622,1628 ****
int first ATTRIBUTE_UNUSED;
{
const char *symbol_str;
! bool is_local, is_small;
rtx rtl, symbol;
rtl = DECL_P (decl) ? DECL_RTL (decl) : TREE_CST_RTL (decl);
--- 1808,1815 ----
int first ATTRIBUTE_UNUSED;
{
const char *symbol_str;
! bool is_local;
! char encoding = 0;
rtx rtl, symbol;
rtl = DECL_P (decl) ? DECL_RTL (decl) : TREE_CST_RTL (decl);
*************** alpha_encode_section_info (decl, first)
*** 1659,1676 ****
/* 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);
/* Finally, encode this into the symbol string. */
! if (is_local)
{
char *newstr;
size_t len;
! if (symbol_str[0] == '@')
{
! if (symbol_str[1] == (is_small ? 's' : 'v'))
return;
symbol_str += 2;
}
--- 1846,1901 ----
/* A variable is considered "local" if it is defined in this module. */
is_local = (*targetm.binds_local_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 (encoding)
{
char *newstr;
size_t len;
! if (symbol_str[0] == (is_local ? '@' : '%'))
{
! if (symbol_str[1] == encoding)
return;
symbol_str += 2;
}
*************** alpha_encode_section_info (decl, first)
*** 1678,1695 ****
len = strlen (symbol_str) + 1;
newstr = alloca (len + 2);
! newstr[0] = '@';
! newstr[1] = (is_small ? 's' : 'v');
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. */
--- 1903,1914 ----
len = strlen (symbol_str) + 1;
newstr = alloca (len + 2);
! newstr[0] = (is_local ? '@' : '%');
! newstr[1] = encoding;
memcpy (newstr + 2, symbol_str, len);
XSTR (symbol, 0) = ggc_alloc_string (newstr, len + 2 - 1);
}
}
/* Undo the effects of the above. */
*************** static const char *
*** 1698,1704 ****
alpha_strip_name_encoding (str)
const char *str;
{
! if (str[0] == '@')
str += 2;
if (str[0] == '*')
str++;
--- 1917,1923 ----
alpha_strip_name_encoding (str)
const char *str;
{
! if (str[0] == '@' || str[0] == '%')
str += 2;
if (str[0] == '*')
str++;
*************** alpha_legitimate_address_p (mode, x, str
*** 1799,1805 ****
return false;
/* The symbol must be local. */
! if (local_symbolic_operand (ofs, Pmode))
return true;
}
}
--- 2018,2026 ----
return false;
/* The symbol must be local. */
! if (local_symbolic_operand (ofs, Pmode)
! || dtp32_symbolic_operand (ofs, Pmode)
! || tp32_symbolic_operand (ofs, Pmode))
return true;
}
}
*************** alpha_legitimize_address (x, scratch, mo
*** 1865,1870 ****
--- 2086,2185 ----
/* 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))
*************** alpha_expand_mov (mode, operands)
*** 2589,2594 ****
--- 2904,2911 ----
tmp = alpha_legitimize_address (operands[1], operands[0], mode);
if (tmp)
{
+ if (tmp == operands[0])
+ return true;
operands[1] = tmp;
return false;
}
*************** alpha_multipass_dfa_lookahead ()
*** 4906,4915 ****
return (alpha_cpu == PROCESSOR_EV6 ? 4 : 2);
}
/* 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;
--- 5223,5253 ----
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. */
static void
alpha_init_machine_status (p)
struct function *p;
*************** alpha_init_machine_status (p)
*** 4917,4926 ****
--- 5255,5269 ----
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
*************** alpha_mark_machine_status (p)
*** 4931,4938 ****
--- 5274,5283 ----
if (machine)
{
+ #if TARGET_ABI_UNICOSMK
ggc_mark_rtx (machine->first_ciw);
ggc_mark_rtx (machine->addr_list);
+ #endif
}
}
*************** alpha_free_machine_status (p)
*** 4943,4949 ****
free (p->machine);
p->machine = NULL;
}
- #endif /* TARGET_ABI_UNICOSMK */
/* Functions to save and restore alpha_return_addr_rtx. */
--- 5288,5293 ----
*************** get_round_mode_suffix ()
*** 5087,5092 ****
--- 5431,5475 ----
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
*************** print_operand (file, x, code)
*** 5104,5109 ****
--- 5487,5496 ----
assemble_name (file, alpha_fnname);
break;
+ case '&':
+ assemble_name (file, get_some_local_dynamic_name ());
+ break;
+
case '/':
{
const char *trap = get_trap_mode_suffix ();
*************** print_operand (file, x, code)
*** 5145,5157 ****
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");
break;
case 'r':
--- 5532,5561 ----
break;
case 'J':
! {
! 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':
*************** print_operand (file, x, code)
*** 5385,5390 ****
--- 5789,5807 ----
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;
*************** print_operand_address (file, addr)
*** 5414,5420 ****
if (GET_CODE (addr) == LO_SUM)
{
! output_addr_const (file, XEXP (addr, 1));
if (offset)
{
fputc ('+', file);
--- 5831,5866 ----
if (GET_CODE (addr) == LO_SUM)
{
! 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);
*************** print_operand_address (file, addr)
*** 5431,5437 ****
abort ();
fprintf (file, "($%d)\t\t!%s", basereg,
! (basereg == 29 ? "gprel" : "gprellow"));
return;
}
--- 5877,5883 ----
abort ();
fprintf (file, "($%d)\t\t!%s", basereg,
! (basereg == 29 ? reloc16 : reloclo));
return;
}
Index: gcc/config/alpha/alpha.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/alpha/alpha.h,v
retrieving revision 1.166
diff -c -p -d -r1.166 alpha.h
*** gcc/config/alpha/alpha.h 19 May 2002 21:53:53 -0000 1.166
--- gcc/config/alpha/alpha.h 1 Jun 2002 00:11:16 -0000
*************** extern int target_flags;
*** 137,142 ****
--- 137,143 ----
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. */
*************** extern enum alpha_fp_trap_mode alpha_fpt
*** 208,213 ****
--- 209,218 ----
#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)
*************** extern enum alpha_fp_trap_mode alpha_fpt
*** 251,256 ****
--- 256,264 ----
#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,
*************** extern enum alpha_fp_trap_mode alpha_fpt
*** 293,298 ****
--- 301,308 ----
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, ""} }
*************** extern const char *alpha_fprm_string; /*
*** 316,321 ****
--- 326,332 ----
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 \
{ \
*************** extern const char *alpha_mlat_string; /*
*** 331,336 ****
--- 342,349 ----
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
*************** extern const char *alpha_mlat_string; /*
*** 681,687 ****
class that represents their union. */
enum reg_class {
! NO_REGS, R24_REG, R25_REG, R27_REG,
GENERAL_REGS, FLOAT_REGS, ALL_REGS,
LIM_REG_CLASSES
};
--- 694,700 ----
class that represents their union. */
enum reg_class {
! NO_REGS, R0_REG, R24_REG, R25_REG, R27_REG,
GENERAL_REGS, FLOAT_REGS, ALL_REGS,
LIM_REG_CLASSES
};
*************** enum reg_class {
*** 690,697 ****
/* Give names of register classes as strings for dump file. */
! #define REG_CLASS_NAMES \
! {"NO_REGS", "R24_REG", "R25_REG", "R27_REG", \
"GENERAL_REGS", "FLOAT_REGS", "ALL_REGS" }
/* Define which registers fit in which classes.
--- 703,710 ----
/* Give names of register classes as strings for dump file. */
! #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.
*************** enum reg_class {
*** 700,705 ****
--- 713,719 ----
#define REG_CLASS_CONTENTS \
{ {0x00000000, 0x00000000}, /* NO_REGS */ \
+ {0x00000001, 0x00000000}, /* R0_REG */ \
{0x01000000, 0x00000000}, /* R24_REG */ \
{0x02000000, 0x00000000}, /* R25_REG */ \
{0x08000000, 0x00000000}, /* R27_REG */ \
*************** enum reg_class {
*** 713,719 ****
or could index an array. */
#define REGNO_REG_CLASS(REGNO) \
! ((REGNO) == 24 ? R24_REG \
: (REGNO) == 25 ? R25_REG \
: (REGNO) == 27 ? R27_REG \
: (REGNO) >= 32 && (REGNO) <= 62 ? FLOAT_REGS \
--- 727,734 ----
or could index an array. */
#define REGNO_REG_CLASS(REGNO) \
! ((REGNO) == 0 ? R0_REG \
! : (REGNO) == 24 ? R24_REG \
: (REGNO) == 25 ? R25_REG \
: (REGNO) == 27 ? R27_REG \
: (REGNO) >= 32 && (REGNO) <= 62 ? FLOAT_REGS \
*************** enum reg_class {
*** 730,735 ****
--- 745,751 ----
: (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. */
*************** do { \
*** 1710,1716 ****
#define ASM_OUTPUT_LABELREF(STREAM, NAME) \
do { \
const char *name_ = NAME; \
! if (*name_ == '@') \
name_ += 2; \
if (*name_ == '*') \
name_++; \
--- 1726,1732 ----
#define ASM_OUTPUT_LABELREF(STREAM, NAME) \
do { \
const char *name_ = NAME; \
! if (*name_ == '@' || *name == '%') \
name_ += 2; \
if (*name_ == '*') \
name_++; \
*************** do { \
*** 1893,1899 ****
#define PRINT_OPERAND_PUNCT_VALID_P(CODE) \
((CODE) == '/' || (CODE) == ',' || (CODE) == '-' || (CODE) == '~' \
! || (CODE) == '#' || (CODE) == '*')
/* Print a memory address as an operand to reference that memory location. */
--- 1909,1915 ----
#define PRINT_OPERAND_PUNCT_VALID_P(CODE) \
((CODE) == '/' || (CODE) == ',' || (CODE) == '-' || (CODE) == '~' \
! || (CODE) == '#' || (CODE) == '*' || (CODE) == '&')
/* Print a memory address as an operand to reference that memory location. */
*************** do { \
*** 1929,1934 ****
--- 1945,1956 ----
{"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: gcc/config/alpha/alpha.md
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/alpha/alpha.md,v
retrieving revision 1.187
diff -c -p -d -r1.187 alpha.md
*** gcc/config/alpha/alpha.md 5 May 2002 21:54:38 -0000 1.187
--- gcc/config/alpha/alpha.md 1 Jun 2002 00:11:16 -0000
***************
*** 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.
;; Contributed by Richard Kenner (kenner@vlsi1.ultra.nyu.edu)
;;
;; This file is part of GNU CC.
--- 1,6 ----
;; Machine description for DEC Alpha for GNU C compiler
;; Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
! ;; 2000, 2001, 2002 Free Software Foundation, Inc.
;; Contributed by Richard Kenner (kenner@vlsi1.ultra.nyu.edu)
;;
;; This file is part of GNU CC.
***************
*** 40,45 ****
--- 40,54 ----
(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,62 ****
--- 66,72 ----
(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
*************** fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi
*** 335,340 ****
--- 345,392 ----
""
"")
+ (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")
*************** fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi
*** 4805,4810 ****
--- 4857,4899 ----
"!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
*************** fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi
*** 5282,5287 ****
--- 5371,5445 ----
}
})
+ (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"))]
*************** fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi
*** 6720,6726 ****
(plus:DI (pc) (const_int 4)))
(unspec_volatile [(reg:DI 29)] UNSPECV_BLOCKAGE)
(use (match_operand 3 "" ""))
! (use (match_operand 4 "const_int_operand" ""))]
"TARGET_EXPLICIT_RELOCS && TARGET_ABI_OSF"
"jsr $26,(%1),%3%J4"
[(set_attr "type" "jsr")])
--- 6878,6884 ----
(plus:DI (pc) (const_int 4)))
(unspec_volatile [(reg:DI 29)] UNSPECV_BLOCKAGE)
(use (match_operand 3 "" ""))
! (use (match_operand 4 "" ""))]
"TARGET_EXPLICIT_RELOCS && TARGET_ABI_OSF"
"jsr $26,(%1),%3%J4"
[(set_attr "type" "jsr")])
*************** fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi
*** 6740,6745 ****
--- 6898,6967 ----
[(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"))
*************** fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi
*** 6815,6818 ****
"TARGET_ABI_UNICOSMK"
"jsr $26,(%1)"
[(set_attr "type" "jsr")])
-
--- 7037,7039 ----
Index: gcc/config/alpha/unicosmk.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/alpha/unicosmk.h,v
retrieving revision 1.12
diff -c -p -d -r1.12 unicosmk.h
*** gcc/config/alpha/unicosmk.h 18 May 2002 19:27:43 -0000 1.12
--- gcc/config/alpha/unicosmk.h 1 Jun 2002 00:11:16 -0000
*************** do { \
*** 293,311 ****
#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) \
--- 293,298 ----