sparc.c (struct machine_function): New type.
* config/sparc/sparc.c (struct machine_function): New type. (TARGET_HAVE_TLS, TARGET_CANNOT_FORCE_CONST_MEM): Define. (sparc_override_options): Initialize init_machine_status. (tls_symbolic_operand, tgd_symbolic_operand, tld_symbolic_operand, tie_symbolic_operand, tle_symbolic_operand): New functions. (symbolic_operand): Disallow tls_symbolic_operand. (symbolic_memory_operand): Likewise. (tls_call_delay, sparc_cannot_force_const_mem, legitimate_constant_p, constant_address_p, legitimate_pic_operand_p, legitimate_address_p): New functions. (sparc_tls_symbol): New variable. (sparc_tls_get_addr, sparc_tls_got, legitimize_tls_address, legitimize_address): New functions. (print_operand): Handle %&. (sparc_init_machine_status, get_some_local_dynamic_name, get_some_local_dynamic_name_1): New functions. (sparc_output_dwarf_dtprel): New function. * config/sparc/sparc.h (CONSTANT_ADDRESS_P): Moved into constant_address_p. (LEGITIMATE_PIC_OPERAND_P): Moved into legitimate_pic_operand_p. (LEGITIMATE_CONSTANT_P): Moved into legitimate_constant_p. (GO_IF_LEGITIMATE_ADDRESS): Moved into legitimate_address_p. (LEGITIMIZE_ADDRESS): Moved into legitimize_address. (PRINT_OPERAND_PUNCT_VALID_P): Add '&'. (TARGET_TLS, TARGET_SUN_TLS, TARGET_GNU_TLS): Define. (ASM_OUTPUT_DWARF_DTPREL): Define. (PREDICATE_CODES): Add tgd_symbolic_operand, tld_symbolic_operand, tie_symbolic_operand, tle_symbolic_operand. * config/sparc/sparc.md (UNSPEC_TLSGD, UNSPEC_TLSLDM, UNSPEC_TLSLDO, UNSPEC_TLSIE, UNSPEC_TLSLE, UNSPEC_TLSLD_BASE): New constants. (tls_call_delay): New attribute. (in_call_delay): Use it. (movqi, movhi, movsi, movdi): Call legitimize_tls_address if needed. (tgd_hi22, tgd_lo10, tgd_add32, tgd_add64, tgd_call32, tgd_call64, tldm_hi22, tldm_lo10, tldm_add32, tldm_add64, tldm_call32, tldm_call64, tldo_hix22, tldo_lox10, tldo_add32, tldo_add64, tie_hi22, tie_lo10, tie_ld32, tie_ld64, tie_add32, tie_add64, tle_hix22_sp32, tle_lox10_sp32, tle_hix22_sp64, tle_lox10_sp64): New insns. (tldo_ldub_sp32, tldo_ldub1_sp32, tldo_ldub2_sp32, tldo_ldsb1_sp32, tldo_ldsb2_sp32, tldo_ldub_sp64, tldo_ldub1_sp64, tldo_ldub2_sp64, tldo_ldub3_sp64, tldo_ldsb1_sp64, tldo_ldsb2_sp64, tldo_ldsb3_sp64, tldo_lduh_sp32, tldo_lduh1_sp32, tldo_ldsh1_sp32, tldo_lduh_sp64, tldo_lduh1_sp64, tldo_lduh2_sp64, tldo_ldsh1_sp64, tldo_ldsh2_sp64, tldo_lduw_sp32, tldo_lduw_sp64, tldo_lduw1_sp64, tldo_ldsw1_sp64, tldo_ldx_sp64, tldo_stb_sp32, tldo_stb_sp64, tldo_sth_sp32, tldo_sth_sp64, tldo_stw_sp32, tldo_stw_sp64, tldo_stx_sp64): New insns. * config/sparc/sparc-protos.h (legitimate_constant_p, constant_address_p, legitimate_pic_operand_p, legitimate_address_p, legitimize_tls_address, legitimize_address, tls_symbolic_operand, tls_call_delay, sparc_output_dwarf_dtprel): New prototypes. * config/sparc/linux.h (TARGET_GNU_TLS, TARGET_SUN_TLS): Define. * config/sparc/linux64.h (TARGET_GNU_TLS, TARGET_SUN_TLS): Likewise. * configure.in (sparc*-*-*): Add TLS check. * configure: Rebuilt. From-SVN: r71202
This commit is contained in:
parent
7b65ed5448
commit
5751a10b97
|
@ -1,3 +1,61 @@
|
||||||
|
2003-09-08 Jakub Jelinek <jakub@redhat.com>
|
||||||
|
|
||||||
|
* config/sparc/sparc.c (struct machine_function): New type.
|
||||||
|
(TARGET_HAVE_TLS, TARGET_CANNOT_FORCE_CONST_MEM): Define.
|
||||||
|
(sparc_override_options): Initialize init_machine_status.
|
||||||
|
(tls_symbolic_operand, tgd_symbolic_operand, tld_symbolic_operand,
|
||||||
|
tie_symbolic_operand, tle_symbolic_operand): New functions.
|
||||||
|
(symbolic_operand): Disallow tls_symbolic_operand.
|
||||||
|
(symbolic_memory_operand): Likewise.
|
||||||
|
(tls_call_delay, sparc_cannot_force_const_mem, legitimate_constant_p,
|
||||||
|
constant_address_p, legitimate_pic_operand_p, legitimate_address_p):
|
||||||
|
New functions.
|
||||||
|
(sparc_tls_symbol): New variable.
|
||||||
|
(sparc_tls_get_addr, sparc_tls_got, legitimize_tls_address,
|
||||||
|
legitimize_address): New functions.
|
||||||
|
(print_operand): Handle %&.
|
||||||
|
(sparc_init_machine_status, get_some_local_dynamic_name,
|
||||||
|
get_some_local_dynamic_name_1): New functions.
|
||||||
|
(sparc_output_dwarf_dtprel): New function.
|
||||||
|
* config/sparc/sparc.h (CONSTANT_ADDRESS_P): Moved into
|
||||||
|
constant_address_p.
|
||||||
|
(LEGITIMATE_PIC_OPERAND_P): Moved into legitimate_pic_operand_p.
|
||||||
|
(LEGITIMATE_CONSTANT_P): Moved into legitimate_constant_p.
|
||||||
|
(GO_IF_LEGITIMATE_ADDRESS): Moved into legitimate_address_p.
|
||||||
|
(LEGITIMIZE_ADDRESS): Moved into legitimize_address.
|
||||||
|
(PRINT_OPERAND_PUNCT_VALID_P): Add '&'.
|
||||||
|
(TARGET_TLS, TARGET_SUN_TLS, TARGET_GNU_TLS): Define.
|
||||||
|
(ASM_OUTPUT_DWARF_DTPREL): Define.
|
||||||
|
(PREDICATE_CODES): Add tgd_symbolic_operand, tld_symbolic_operand,
|
||||||
|
tie_symbolic_operand, tle_symbolic_operand.
|
||||||
|
* config/sparc/sparc.md (UNSPEC_TLSGD, UNSPEC_TLSLDM, UNSPEC_TLSLDO,
|
||||||
|
UNSPEC_TLSIE, UNSPEC_TLSLE, UNSPEC_TLSLD_BASE): New constants.
|
||||||
|
(tls_call_delay): New attribute.
|
||||||
|
(in_call_delay): Use it.
|
||||||
|
(movqi, movhi, movsi, movdi): Call legitimize_tls_address if needed.
|
||||||
|
(tgd_hi22, tgd_lo10, tgd_add32, tgd_add64, tgd_call32, tgd_call64,
|
||||||
|
tldm_hi22, tldm_lo10, tldm_add32, tldm_add64, tldm_call32, tldm_call64,
|
||||||
|
tldo_hix22, tldo_lox10, tldo_add32, tldo_add64, tie_hi22, tie_lo10,
|
||||||
|
tie_ld32, tie_ld64, tie_add32, tie_add64, tle_hix22_sp32,
|
||||||
|
tle_lox10_sp32, tle_hix22_sp64, tle_lox10_sp64): New insns.
|
||||||
|
(tldo_ldub_sp32, tldo_ldub1_sp32, tldo_ldub2_sp32, tldo_ldsb1_sp32,
|
||||||
|
tldo_ldsb2_sp32, tldo_ldub_sp64, tldo_ldub1_sp64, tldo_ldub2_sp64,
|
||||||
|
tldo_ldub3_sp64, tldo_ldsb1_sp64, tldo_ldsb2_sp64, tldo_ldsb3_sp64,
|
||||||
|
tldo_lduh_sp32, tldo_lduh1_sp32, tldo_ldsh1_sp32, tldo_lduh_sp64,
|
||||||
|
tldo_lduh1_sp64, tldo_lduh2_sp64, tldo_ldsh1_sp64, tldo_ldsh2_sp64,
|
||||||
|
tldo_lduw_sp32, tldo_lduw_sp64, tldo_lduw1_sp64, tldo_ldsw1_sp64,
|
||||||
|
tldo_ldx_sp64, tldo_stb_sp32, tldo_stb_sp64, tldo_sth_sp32,
|
||||||
|
tldo_sth_sp64, tldo_stw_sp32, tldo_stw_sp64, tldo_stx_sp64): New
|
||||||
|
insns.
|
||||||
|
* config/sparc/sparc-protos.h (legitimate_constant_p,
|
||||||
|
constant_address_p, legitimate_pic_operand_p, legitimate_address_p,
|
||||||
|
legitimize_tls_address, legitimize_address, tls_symbolic_operand,
|
||||||
|
tls_call_delay, sparc_output_dwarf_dtprel): New prototypes.
|
||||||
|
* config/sparc/linux.h (TARGET_GNU_TLS, TARGET_SUN_TLS): Define.
|
||||||
|
* config/sparc/linux64.h (TARGET_GNU_TLS, TARGET_SUN_TLS): Likewise.
|
||||||
|
* configure.in (sparc*-*-*): Add TLS check.
|
||||||
|
* configure: Rebuilt.
|
||||||
|
|
||||||
2003-09-07 Eric Botcazou <ebotcazou@libertysurf.fr>
|
2003-09-07 Eric Botcazou <ebotcazou@libertysurf.fr>
|
||||||
|
|
||||||
PR target/11689
|
PR target/11689
|
||||||
|
|
|
@ -232,6 +232,13 @@ do { \
|
||||||
#define LINK_EH_SPEC "%{!static:--eh-frame-hdr} "
|
#define LINK_EH_SPEC "%{!static:--eh-frame-hdr} "
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_AS_TLS
|
||||||
|
#undef TARGET_SUN_TLS
|
||||||
|
#undef TARGET_GNU_TLS
|
||||||
|
#define TARGET_SUN_TLS 0
|
||||||
|
#define TARGET_GNU_TLS 1
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Don't be different from other Linux platforms in this regard. */
|
/* Don't be different from other Linux platforms in this regard. */
|
||||||
#define HANDLE_PRAGMA_PACK_PUSH_POP
|
#define HANDLE_PRAGMA_PACK_PUSH_POP
|
||||||
|
|
||||||
|
|
|
@ -315,6 +315,13 @@ do { \
|
||||||
#define LINK_EH_SPEC "%{!static:--eh-frame-hdr} "
|
#define LINK_EH_SPEC "%{!static:--eh-frame-hdr} "
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_AS_TLS
|
||||||
|
#undef TARGET_SUN_TLS
|
||||||
|
#undef TARGET_GNU_TLS
|
||||||
|
#define TARGET_SUN_TLS 0
|
||||||
|
#define TARGET_GNU_TLS 1
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Don't be different from other Linux platforms in this regard. */
|
/* Don't be different from other Linux platforms in this regard. */
|
||||||
#define HANDLE_PRAGMA_PACK_PUSH_POP
|
#define HANDLE_PRAGMA_PACK_PUSH_POP
|
||||||
|
|
||||||
|
|
|
@ -78,7 +78,13 @@ extern void emit_tfmode_cvt (enum rtx_code, rtx *);
|
||||||
extern int gen_v9_scc (enum rtx_code, rtx *);
|
extern int gen_v9_scc (enum rtx_code, rtx *);
|
||||||
extern void sparc_initialize_trampoline (rtx, rtx, rtx);
|
extern void sparc_initialize_trampoline (rtx, rtx, rtx);
|
||||||
extern void sparc64_initialize_trampoline (rtx, rtx, rtx);
|
extern void sparc64_initialize_trampoline (rtx, rtx, rtx);
|
||||||
|
extern bool legitimate_constant_p (rtx);
|
||||||
|
extern bool constant_address_p (rtx);
|
||||||
|
extern bool legitimate_pic_operand_p (rtx);
|
||||||
|
extern int legitimate_address_p (enum machine_mode, rtx, int);
|
||||||
extern rtx legitimize_pic_address (rtx, enum machine_mode, rtx);
|
extern rtx legitimize_pic_address (rtx, enum machine_mode, rtx);
|
||||||
|
extern rtx legitimize_tls_address (rtx);
|
||||||
|
extern rtx legitimize_address (rtx, rtx, enum machine_mode);
|
||||||
extern void sparc_defer_case_vector (rtx, rtx, int);
|
extern void sparc_defer_case_vector (rtx, rtx, int);
|
||||||
extern void sparc_emit_set_const32 (rtx, rtx);
|
extern void sparc_emit_set_const32 (rtx, rtx);
|
||||||
extern void sparc_emit_set_const64 (rtx, rtx);
|
extern void sparc_emit_set_const64 (rtx, rtx);
|
||||||
|
@ -96,9 +102,11 @@ extern int arith_4096_operand (rtx, enum machine_mode);
|
||||||
extern int zero_operand (rtx, enum machine_mode);
|
extern int zero_operand (rtx, enum machine_mode);
|
||||||
extern int fp_zero_operand (rtx, enum machine_mode);
|
extern int fp_zero_operand (rtx, enum machine_mode);
|
||||||
extern int reg_or_0_operand (rtx, enum machine_mode);
|
extern int reg_or_0_operand (rtx, enum machine_mode);
|
||||||
|
extern int tls_symbolic_operand (rtx);
|
||||||
extern int empty_delay_slot (rtx);
|
extern int empty_delay_slot (rtx);
|
||||||
extern int eligible_for_epilogue_delay (rtx, int);
|
extern int eligible_for_epilogue_delay (rtx, int);
|
||||||
extern int eligible_for_sibcall_delay (rtx);
|
extern int eligible_for_sibcall_delay (rtx);
|
||||||
|
extern int tls_call_delay (rtx);
|
||||||
extern int emit_move_sequence (rtx, enum machine_mode);
|
extern int emit_move_sequence (rtx, enum machine_mode);
|
||||||
extern int fp_sethi_p (rtx);
|
extern int fp_sethi_p (rtx);
|
||||||
extern int fp_mov_p (rtx);
|
extern int fp_mov_p (rtx);
|
||||||
|
@ -116,6 +124,7 @@ extern char *sparc_v8plus_shift (rtx *, rtx, const char *);
|
||||||
extern int sparc_check_64 (rtx, rtx);
|
extern int sparc_check_64 (rtx, rtx);
|
||||||
extern rtx gen_df_reg (rtx, int);
|
extern rtx gen_df_reg (rtx, int);
|
||||||
extern int sparc_extra_constraint_check (rtx, int, int);
|
extern int sparc_extra_constraint_check (rtx, int, int);
|
||||||
|
extern void sparc_output_dwarf_dtprel (FILE*, int, rtx);
|
||||||
#endif /* RTX_CODE */
|
#endif /* RTX_CODE */
|
||||||
|
|
||||||
#endif /* __SPARC_PROTOS_H__ */
|
#endif /* __SPARC_PROTOS_H__ */
|
||||||
|
|
|
@ -120,6 +120,12 @@ char sparc_leaf_regs[] =
|
||||||
1, 1, 1, 1, 1, 1, 1, 1,
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
1, 1, 1, 1, 1};
|
1, 1, 1, 1, 1};
|
||||||
|
|
||||||
|
struct machine_function GTY(())
|
||||||
|
{
|
||||||
|
/* Some local-dynamic TLS symbol name. */
|
||||||
|
const char *some_ld_name;
|
||||||
|
};
|
||||||
|
|
||||||
/* Name of where we pretend to think the frame pointer points.
|
/* Name of where we pretend to think the frame pointer points.
|
||||||
Normally, this is "%fp", but if we are in a leaf procedure,
|
Normally, this is "%fp", but if we are in a leaf procedure,
|
||||||
this is "%sp+something". We record "something" separately as it may be
|
this is "%sp+something". We record "something" separately as it may be
|
||||||
|
@ -176,6 +182,12 @@ static void emit_hard_tfmode_operation (enum rtx_code, rtx *);
|
||||||
static bool sparc_function_ok_for_sibcall (tree, tree);
|
static bool sparc_function_ok_for_sibcall (tree, tree);
|
||||||
static void sparc_output_mi_thunk (FILE *, tree, HOST_WIDE_INT,
|
static void sparc_output_mi_thunk (FILE *, tree, HOST_WIDE_INT,
|
||||||
HOST_WIDE_INT, tree);
|
HOST_WIDE_INT, tree);
|
||||||
|
static struct machine_function * sparc_init_machine_status (void);
|
||||||
|
static bool sparc_cannot_force_const_mem (rtx);
|
||||||
|
static rtx sparc_tls_get_addr (void);
|
||||||
|
static rtx sparc_tls_got (void);
|
||||||
|
static const char *get_some_local_dynamic_name (void);
|
||||||
|
static int get_some_local_dynamic_name_1 (rtx *, void *);
|
||||||
static bool sparc_rtx_costs (rtx, int, int, int *);
|
static bool sparc_rtx_costs (rtx, int, int, int *);
|
||||||
|
|
||||||
/* Option handling. */
|
/* Option handling. */
|
||||||
|
@ -240,6 +252,13 @@ enum processor_type sparc_cpu;
|
||||||
#undef TARGET_FUNCTION_OK_FOR_SIBCALL
|
#undef TARGET_FUNCTION_OK_FOR_SIBCALL
|
||||||
#define TARGET_FUNCTION_OK_FOR_SIBCALL sparc_function_ok_for_sibcall
|
#define TARGET_FUNCTION_OK_FOR_SIBCALL sparc_function_ok_for_sibcall
|
||||||
|
|
||||||
|
#ifdef HAVE_AS_TLS
|
||||||
|
#undef TARGET_HAVE_TLS
|
||||||
|
#define TARGET_HAVE_TLS true
|
||||||
|
#endif
|
||||||
|
#undef TARGET_CANNOT_FORCE_CONST_MEM
|
||||||
|
#define TARGET_CANNOT_FORCE_CONST_MEM sparc_cannot_force_const_mem
|
||||||
|
|
||||||
#undef TARGET_ASM_OUTPUT_MI_THUNK
|
#undef TARGET_ASM_OUTPUT_MI_THUNK
|
||||||
#define TARGET_ASM_OUTPUT_MI_THUNK sparc_output_mi_thunk
|
#define TARGET_ASM_OUTPUT_MI_THUNK sparc_output_mi_thunk
|
||||||
#undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
|
#undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
|
||||||
|
@ -448,6 +467,9 @@ sparc_override_options (void)
|
||||||
|
|
||||||
/* Do various machine dependent initializations. */
|
/* Do various machine dependent initializations. */
|
||||||
sparc_init_modes ();
|
sparc_init_modes ();
|
||||||
|
|
||||||
|
/* Set up function hooks. */
|
||||||
|
init_machine_status = sparc_init_machine_status;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Miscellaneous utilities. */
|
/* Miscellaneous utilities. */
|
||||||
|
@ -687,6 +709,41 @@ call_operand_address (rtx op, enum machine_mode mode)
|
||||||
return (symbolic_operand (op, mode) || memory_address_p (Pmode, op));
|
return (symbolic_operand (op, mode) || memory_address_p (Pmode, op));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* If OP is a SYMBOL_REF of a thread-local symbol, return its TLS mode,
|
||||||
|
otherwise return 0. */
|
||||||
|
|
||||||
|
int
|
||||||
|
tls_symbolic_operand (rtx op)
|
||||||
|
{
|
||||||
|
if (GET_CODE (op) != SYMBOL_REF)
|
||||||
|
return 0;
|
||||||
|
return SYMBOL_REF_TLS_MODEL (op);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
tgd_symbolic_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
|
||||||
|
{
|
||||||
|
return tls_symbolic_operand (op) == TLS_MODEL_GLOBAL_DYNAMIC;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
tld_symbolic_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
|
||||||
|
{
|
||||||
|
return tls_symbolic_operand (op) == TLS_MODEL_LOCAL_DYNAMIC;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
tie_symbolic_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
|
||||||
|
{
|
||||||
|
return tls_symbolic_operand (op) == TLS_MODEL_INITIAL_EXEC;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
tle_symbolic_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
|
||||||
|
{
|
||||||
|
return tls_symbolic_operand (op) == TLS_MODEL_LOCAL_EXEC;
|
||||||
|
}
|
||||||
|
|
||||||
/* Returns 1 if OP is either a symbol reference or a sum of a symbol
|
/* Returns 1 if OP is either a symbol reference or a sum of a symbol
|
||||||
reference and a constant. */
|
reference and a constant. */
|
||||||
|
|
||||||
|
@ -701,12 +758,15 @@ symbolic_operand (register rtx op, enum machine_mode mode)
|
||||||
switch (GET_CODE (op))
|
switch (GET_CODE (op))
|
||||||
{
|
{
|
||||||
case SYMBOL_REF:
|
case SYMBOL_REF:
|
||||||
|
return !SYMBOL_REF_TLS_MODEL (op);
|
||||||
|
|
||||||
case LABEL_REF:
|
case LABEL_REF:
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
case CONST:
|
case CONST:
|
||||||
op = XEXP (op, 0);
|
op = XEXP (op, 0);
|
||||||
return ((GET_CODE (XEXP (op, 0)) == SYMBOL_REF
|
return (((GET_CODE (XEXP (op, 0)) == SYMBOL_REF
|
||||||
|
&& !SYMBOL_REF_TLS_MODEL (XEXP (op, 0)))
|
||||||
|| GET_CODE (XEXP (op, 0)) == LABEL_REF)
|
|| GET_CODE (XEXP (op, 0)) == LABEL_REF)
|
||||||
&& GET_CODE (XEXP (op, 1)) == CONST_INT);
|
&& GET_CODE (XEXP (op, 1)) == CONST_INT);
|
||||||
|
|
||||||
|
@ -726,8 +786,9 @@ symbolic_memory_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
|
||||||
if (GET_CODE (op) != MEM)
|
if (GET_CODE (op) != MEM)
|
||||||
return 0;
|
return 0;
|
||||||
op = XEXP (op, 0);
|
op = XEXP (op, 0);
|
||||||
return (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == CONST
|
return ((GET_CODE (op) == SYMBOL_REF && !SYMBOL_REF_TLS_MODEL (op))
|
||||||
|| GET_CODE (op) == HIGH || GET_CODE (op) == LABEL_REF);
|
|| GET_CODE (op) == CONST || GET_CODE (op) == HIGH
|
||||||
|
|| GET_CODE (op) == LABEL_REF);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return truth value of statement that OP is a LABEL_REF of mode MODE. */
|
/* Return truth value of statement that OP is a LABEL_REF of mode MODE. */
|
||||||
|
@ -2793,6 +2854,32 @@ eligible_for_epilogue_delay (rtx trial, int slot)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Return nonzero if TRIAL can go into the call delay slot. */
|
||||||
|
int
|
||||||
|
tls_call_delay (rtx trial)
|
||||||
|
{
|
||||||
|
rtx pat, unspec;
|
||||||
|
|
||||||
|
/* Binutils allows
|
||||||
|
call __tls_get_addr, %tgd_call (foo)
|
||||||
|
add %l7, %o0, %o0, %tgd_add (foo)
|
||||||
|
while Sun as/ld does not. */
|
||||||
|
if (TARGET_GNU_TLS || !TARGET_TLS)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
pat = PATTERN (trial);
|
||||||
|
if (GET_CODE (pat) != SET || GET_CODE (SET_DEST (pat)) != PLUS)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
unspec = XEXP (SET_DEST (pat), 1);
|
||||||
|
if (GET_CODE (unspec) != UNSPEC
|
||||||
|
|| (XINT (unspec, 1) != UNSPEC_TLSGD
|
||||||
|
&& XINT (unspec, 1) != UNSPEC_TLSLDM))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* Return nonzero if TRIAL can go into the sibling call
|
/* Return nonzero if TRIAL can go into the sibling call
|
||||||
delay slot. */
|
delay slot. */
|
||||||
|
|
||||||
|
@ -2965,6 +3052,45 @@ reg_unused_after (rtx reg, rtx insn)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Determine if it's legal to put X into the constant pool. This
|
||||||
|
is not possible if X contains the address of a symbol that is
|
||||||
|
not constant (TLS) or not known at final link time (PIC). */
|
||||||
|
|
||||||
|
static bool
|
||||||
|
sparc_cannot_force_const_mem (rtx x)
|
||||||
|
{
|
||||||
|
switch (GET_CODE (x))
|
||||||
|
{
|
||||||
|
case CONST_INT:
|
||||||
|
case CONST_DOUBLE:
|
||||||
|
/* Accept all non-symbolic constants. */
|
||||||
|
return false;
|
||||||
|
|
||||||
|
case LABEL_REF:
|
||||||
|
/* Labels are OK iff we are non-PIC. */
|
||||||
|
return flag_pic != 0;
|
||||||
|
|
||||||
|
case SYMBOL_REF:
|
||||||
|
/* 'Naked' TLS symbol references are never OK,
|
||||||
|
non-TLS symbols are OK iff we are non-PIC. */
|
||||||
|
if (SYMBOL_REF_TLS_MODEL (x))
|
||||||
|
return true;
|
||||||
|
else
|
||||||
|
return flag_pic != 0;
|
||||||
|
|
||||||
|
case CONST:
|
||||||
|
return sparc_cannot_force_const_mem (XEXP (x, 0));
|
||||||
|
case PLUS:
|
||||||
|
case MINUS:
|
||||||
|
return sparc_cannot_force_const_mem (XEXP (x, 0))
|
||||||
|
|| sparc_cannot_force_const_mem (XEXP (x, 1));
|
||||||
|
case UNSPEC:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
abort ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* The table we use to reference PIC data. */
|
/* The table we use to reference PIC data. */
|
||||||
static GTY(()) rtx global_offset_table;
|
static GTY(()) rtx global_offset_table;
|
||||||
|
|
||||||
|
@ -3010,6 +3136,391 @@ pic_address_needs_scratch (rtx x)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Determine if a given RTX is a valid constant. We already know this
|
||||||
|
satisfies CONSTANT_P. */
|
||||||
|
|
||||||
|
bool
|
||||||
|
legitimate_constant_p (rtx x)
|
||||||
|
{
|
||||||
|
rtx inner;
|
||||||
|
|
||||||
|
switch (GET_CODE (x))
|
||||||
|
{
|
||||||
|
case SYMBOL_REF:
|
||||||
|
/* TLS symbols are not constant. */
|
||||||
|
if (SYMBOL_REF_TLS_MODEL (x))
|
||||||
|
return false;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CONST:
|
||||||
|
inner = XEXP (x, 0);
|
||||||
|
|
||||||
|
/* Offsets of TLS symbols are never valid.
|
||||||
|
Discourage CSE from creating them. */
|
||||||
|
if (GET_CODE (inner) == PLUS
|
||||||
|
&& tls_symbolic_operand (XEXP (inner, 0)))
|
||||||
|
return false;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CONST_DOUBLE:
|
||||||
|
if (GET_MODE (x) == VOIDmode)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
/* Floating point constants are generally not ok.
|
||||||
|
The only exception is 0.0 in VIS. */
|
||||||
|
if (TARGET_VIS
|
||||||
|
&& (GET_MODE (x) == SFmode
|
||||||
|
|| GET_MODE (x) == DFmode
|
||||||
|
|| GET_MODE (x) == TFmode)
|
||||||
|
&& fp_zero_operand (x, GET_MODE (x)))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Determine if a given RTX is a valid constant address. */
|
||||||
|
|
||||||
|
bool
|
||||||
|
constant_address_p (rtx x)
|
||||||
|
{
|
||||||
|
switch (GET_CODE (x))
|
||||||
|
{
|
||||||
|
case LABEL_REF:
|
||||||
|
case CONST_INT:
|
||||||
|
case HIGH:
|
||||||
|
return true;
|
||||||
|
|
||||||
|
case CONST:
|
||||||
|
if (flag_pic && pic_address_needs_scratch (x))
|
||||||
|
return false;
|
||||||
|
return legitimate_constant_p (x);
|
||||||
|
|
||||||
|
case SYMBOL_REF:
|
||||||
|
return !flag_pic && legitimate_constant_p (x);
|
||||||
|
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Nonzero if the constant value X is a legitimate general operand
|
||||||
|
when generating PIC code. It is given that flag_pic is on and
|
||||||
|
that X satisfies CONSTANT_P or is a CONST_DOUBLE. */
|
||||||
|
|
||||||
|
bool
|
||||||
|
legitimate_pic_operand_p (rtx x)
|
||||||
|
{
|
||||||
|
if (pic_address_needs_scratch (x))
|
||||||
|
return false;
|
||||||
|
if (tls_symbolic_operand (x)
|
||||||
|
|| (GET_CODE (x) == CONST
|
||||||
|
&& GET_CODE (XEXP (x, 0)) == PLUS
|
||||||
|
&& tls_symbolic_operand (XEXP (XEXP (x, 0), 0))))
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return nonzero if ADDR is a valid memory address.
|
||||||
|
STRICT specifies whether strict register checking applies. */
|
||||||
|
|
||||||
|
int
|
||||||
|
legitimate_address_p (enum machine_mode mode, rtx addr, int strict)
|
||||||
|
{
|
||||||
|
rtx rs1 = NULL, rs2 = NULL, imm1 = NULL, imm2;
|
||||||
|
|
||||||
|
if (REG_P (addr) || GET_CODE (addr) == SUBREG)
|
||||||
|
rs1 = addr;
|
||||||
|
else if (GET_CODE (addr) == PLUS)
|
||||||
|
{
|
||||||
|
rs1 = XEXP (addr, 0);
|
||||||
|
rs2 = XEXP (addr, 1);
|
||||||
|
|
||||||
|
/* Canonicalize. REG comes first, if there are no regs,
|
||||||
|
LO_SUM comes first. */
|
||||||
|
if (!REG_P (rs1)
|
||||||
|
&& GET_CODE (rs1) != SUBREG
|
||||||
|
&& (REG_P (rs2)
|
||||||
|
|| GET_CODE (rs2) == SUBREG
|
||||||
|
|| (GET_CODE (rs2) == LO_SUM && GET_CODE (rs1) != LO_SUM)))
|
||||||
|
{
|
||||||
|
rs1 = XEXP (addr, 1);
|
||||||
|
rs2 = XEXP (addr, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((flag_pic == 1
|
||||||
|
&& rs1 == pic_offset_table_rtx
|
||||||
|
&& !REG_P (rs2)
|
||||||
|
&& GET_CODE (rs2) != SUBREG
|
||||||
|
&& GET_CODE (rs2) != LO_SUM
|
||||||
|
&& GET_CODE (rs2) != MEM
|
||||||
|
&& !tls_symbolic_operand (rs2)
|
||||||
|
&& (! symbolic_operand (rs2, VOIDmode) || mode == Pmode)
|
||||||
|
&& (GET_CODE (rs2) != CONST_INT || SMALL_INT (rs2)))
|
||||||
|
|| ((REG_P (rs1)
|
||||||
|
|| GET_CODE (rs1) == SUBREG)
|
||||||
|
&& RTX_OK_FOR_OFFSET_P (rs2)))
|
||||||
|
{
|
||||||
|
imm1 = rs2;
|
||||||
|
rs2 = NULL;
|
||||||
|
}
|
||||||
|
else if ((REG_P (rs1) || GET_CODE (rs1) == SUBREG)
|
||||||
|
&& (REG_P (rs2) || GET_CODE (rs2) == SUBREG))
|
||||||
|
{
|
||||||
|
/* We prohibit REG + REG for TFmode when there are no instructions
|
||||||
|
which accept REG+REG instructions. We do this because REG+REG
|
||||||
|
is not an offsetable address. If we get the situation in reload
|
||||||
|
where source and destination of a movtf pattern are both MEMs with
|
||||||
|
REG+REG address, then only one of them gets converted to an
|
||||||
|
offsetable address. */
|
||||||
|
if (mode == TFmode
|
||||||
|
&& !(TARGET_FPU && TARGET_ARCH64 && TARGET_V9
|
||||||
|
&& TARGET_HARD_QUAD))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* We prohibit REG + REG on ARCH32 if not optimizing for
|
||||||
|
DFmode/DImode because then mem_min_alignment is likely to be zero
|
||||||
|
after reload and the forced split would lack a matching splitter
|
||||||
|
pattern. */
|
||||||
|
if (TARGET_ARCH32 && !optimize
|
||||||
|
&& (mode == DFmode || mode == DImode))
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else if (USE_AS_OFFSETABLE_LO10
|
||||||
|
&& GET_CODE (rs1) == LO_SUM
|
||||||
|
&& TARGET_ARCH64
|
||||||
|
&& ! TARGET_CM_MEDMID
|
||||||
|
&& RTX_OK_FOR_OLO10_P (rs2))
|
||||||
|
{
|
||||||
|
imm2 = rs2;
|
||||||
|
rs2 = NULL;
|
||||||
|
imm1 = XEXP (rs1, 1);
|
||||||
|
rs1 = XEXP (rs1, 0);
|
||||||
|
if (! CONSTANT_P (imm1) || tls_symbolic_operand (rs1))
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (GET_CODE (addr) == LO_SUM)
|
||||||
|
{
|
||||||
|
rs1 = XEXP (addr, 0);
|
||||||
|
imm1 = XEXP (addr, 1);
|
||||||
|
|
||||||
|
if (! CONSTANT_P (imm1) || tls_symbolic_operand (rs1))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* We can't allow TFmode, because an offset greater than or equal to the
|
||||||
|
alignment (8) may cause the LO_SUM to overflow if !v9. */
|
||||||
|
if (mode == TFmode && !TARGET_V9)
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else if (GET_CODE (addr) == CONST_INT && SMALL_INT (addr))
|
||||||
|
return 1;
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (GET_CODE (rs1) == SUBREG)
|
||||||
|
rs1 = SUBREG_REG (rs1);
|
||||||
|
if (!REG_P (rs1))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (rs2)
|
||||||
|
{
|
||||||
|
if (GET_CODE (rs2) == SUBREG)
|
||||||
|
rs2 = SUBREG_REG (rs2);
|
||||||
|
if (!REG_P (rs2))
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strict)
|
||||||
|
{
|
||||||
|
if (!REGNO_OK_FOR_BASE_P (REGNO (rs1))
|
||||||
|
|| (rs2 && !REGNO_OK_FOR_BASE_P (REGNO (rs2))))
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ((REGNO (rs1) >= 32
|
||||||
|
&& REGNO (rs1) != FRAME_POINTER_REGNUM
|
||||||
|
&& REGNO (rs1) < FIRST_PSEUDO_REGISTER)
|
||||||
|
|| (rs2
|
||||||
|
&& (REGNO (rs2) >= 32
|
||||||
|
&& REGNO (rs2) != FRAME_POINTER_REGNUM
|
||||||
|
&& REGNO (rs2) < FIRST_PSEUDO_REGISTER)))
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Construct the SYMBOL_REF for the tls_get_offset function. */
|
||||||
|
|
||||||
|
static GTY(()) rtx sparc_tls_symbol;
|
||||||
|
static rtx
|
||||||
|
sparc_tls_get_addr (void)
|
||||||
|
{
|
||||||
|
if (!sparc_tls_symbol)
|
||||||
|
sparc_tls_symbol = gen_rtx_SYMBOL_REF (Pmode, "__tls_get_addr");
|
||||||
|
|
||||||
|
return sparc_tls_symbol;
|
||||||
|
}
|
||||||
|
|
||||||
|
static rtx
|
||||||
|
sparc_tls_got (void)
|
||||||
|
{
|
||||||
|
rtx temp;
|
||||||
|
if (flag_pic)
|
||||||
|
{
|
||||||
|
current_function_uses_pic_offset_table = 1;
|
||||||
|
return pic_offset_table_rtx;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!global_offset_table)
|
||||||
|
global_offset_table = gen_rtx_SYMBOL_REF (Pmode, "_GLOBAL_OFFSET_TABLE_");
|
||||||
|
temp = gen_reg_rtx (Pmode);
|
||||||
|
emit_move_insn (temp, global_offset_table);
|
||||||
|
return temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* ADDR contains a thread-local SYMBOL_REF. Generate code to compute
|
||||||
|
this (thread-local) address. */
|
||||||
|
|
||||||
|
rtx
|
||||||
|
legitimize_tls_address (rtx addr)
|
||||||
|
{
|
||||||
|
rtx temp1, temp2, temp3, ret, o0, got, insn;
|
||||||
|
|
||||||
|
if (no_new_pseudos)
|
||||||
|
abort ();
|
||||||
|
|
||||||
|
if (GET_CODE (addr) == SYMBOL_REF)
|
||||||
|
switch (SYMBOL_REF_TLS_MODEL (addr))
|
||||||
|
{
|
||||||
|
case TLS_MODEL_GLOBAL_DYNAMIC:
|
||||||
|
start_sequence ();
|
||||||
|
temp1 = gen_reg_rtx (SImode);
|
||||||
|
temp2 = gen_reg_rtx (SImode);
|
||||||
|
ret = gen_reg_rtx (Pmode);
|
||||||
|
o0 = gen_rtx_REG (Pmode, 8);
|
||||||
|
got = sparc_tls_got ();
|
||||||
|
emit_insn (gen_tgd_hi22 (temp1, addr));
|
||||||
|
emit_insn (gen_tgd_lo10 (temp2, temp1, addr));
|
||||||
|
if (TARGET_ARCH32)
|
||||||
|
{
|
||||||
|
emit_insn (gen_tgd_add32 (o0, got, temp2, addr));
|
||||||
|
insn = emit_call_insn (gen_tgd_call32 (o0, sparc_tls_get_addr (),
|
||||||
|
addr, const1_rtx));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
emit_insn (gen_tgd_add64 (o0, got, temp2, addr));
|
||||||
|
insn = emit_call_insn (gen_tgd_call64 (o0, sparc_tls_get_addr (),
|
||||||
|
addr, const1_rtx));
|
||||||
|
}
|
||||||
|
CALL_INSN_FUNCTION_USAGE (insn)
|
||||||
|
= gen_rtx_EXPR_LIST (VOIDmode, gen_rtx_USE (VOIDmode, o0),
|
||||||
|
CALL_INSN_FUNCTION_USAGE (insn));
|
||||||
|
insn = get_insns ();
|
||||||
|
end_sequence ();
|
||||||
|
emit_libcall_block (insn, ret, o0, addr);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TLS_MODEL_LOCAL_DYNAMIC:
|
||||||
|
start_sequence ();
|
||||||
|
temp1 = gen_reg_rtx (SImode);
|
||||||
|
temp2 = gen_reg_rtx (SImode);
|
||||||
|
temp3 = gen_reg_rtx (Pmode);
|
||||||
|
ret = gen_reg_rtx (Pmode);
|
||||||
|
o0 = gen_rtx_REG (Pmode, 8);
|
||||||
|
got = sparc_tls_got ();
|
||||||
|
emit_insn (gen_tldm_hi22 (temp1));
|
||||||
|
emit_insn (gen_tldm_lo10 (temp2, temp1));
|
||||||
|
if (TARGET_ARCH32)
|
||||||
|
{
|
||||||
|
emit_insn (gen_tldm_add32 (o0, got, temp2));
|
||||||
|
insn = emit_call_insn (gen_tldm_call32 (o0, sparc_tls_get_addr (),
|
||||||
|
const1_rtx));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
emit_insn (gen_tldm_add64 (o0, got, temp2));
|
||||||
|
insn = emit_call_insn (gen_tldm_call64 (o0, sparc_tls_get_addr (),
|
||||||
|
const1_rtx));
|
||||||
|
}
|
||||||
|
CALL_INSN_FUNCTION_USAGE (insn)
|
||||||
|
= gen_rtx_EXPR_LIST (VOIDmode, gen_rtx_USE (VOIDmode, o0),
|
||||||
|
CALL_INSN_FUNCTION_USAGE (insn));
|
||||||
|
insn = get_insns ();
|
||||||
|
end_sequence ();
|
||||||
|
emit_libcall_block (insn, temp3, o0,
|
||||||
|
gen_rtx_UNSPEC (Pmode, gen_rtvec (1, const0_rtx),
|
||||||
|
UNSPEC_TLSLD_BASE));
|
||||||
|
temp1 = gen_reg_rtx (SImode);
|
||||||
|
temp2 = gen_reg_rtx (SImode);
|
||||||
|
emit_insn (gen_tldo_hix22 (temp1, addr));
|
||||||
|
emit_insn (gen_tldo_lox10 (temp2, temp1, addr));
|
||||||
|
if (TARGET_ARCH32)
|
||||||
|
emit_insn (gen_tldo_add32 (ret, temp3, temp2, addr));
|
||||||
|
else
|
||||||
|
emit_insn (gen_tldo_add64 (ret, temp3, temp2, addr));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TLS_MODEL_INITIAL_EXEC:
|
||||||
|
temp1 = gen_reg_rtx (SImode);
|
||||||
|
temp2 = gen_reg_rtx (SImode);
|
||||||
|
temp3 = gen_reg_rtx (Pmode);
|
||||||
|
got = sparc_tls_got ();
|
||||||
|
emit_insn (gen_tie_hi22 (temp1, addr));
|
||||||
|
emit_insn (gen_tie_lo10 (temp2, temp1, addr));
|
||||||
|
if (TARGET_ARCH32)
|
||||||
|
emit_insn (gen_tie_ld32 (temp3, got, temp2, addr));
|
||||||
|
else
|
||||||
|
emit_insn (gen_tie_ld64 (temp3, got, temp2, addr));
|
||||||
|
if (TARGET_SUN_TLS)
|
||||||
|
{
|
||||||
|
ret = gen_reg_rtx (Pmode);
|
||||||
|
if (TARGET_ARCH32)
|
||||||
|
emit_insn (gen_tie_add32 (ret, gen_rtx_REG (Pmode, 7),
|
||||||
|
temp3, addr));
|
||||||
|
else
|
||||||
|
emit_insn (gen_tie_add64 (ret, gen_rtx_REG (Pmode, 7),
|
||||||
|
temp3, addr));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
ret = gen_rtx_PLUS (Pmode, gen_rtx_REG (Pmode, 7), temp3);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TLS_MODEL_LOCAL_EXEC:
|
||||||
|
temp1 = gen_reg_rtx (Pmode);
|
||||||
|
temp2 = gen_reg_rtx (Pmode);
|
||||||
|
if (TARGET_ARCH32)
|
||||||
|
{
|
||||||
|
emit_insn (gen_tle_hix22_sp32 (temp1, addr));
|
||||||
|
emit_insn (gen_tle_lox10_sp32 (temp2, temp1, addr));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
emit_insn (gen_tle_hix22_sp64 (temp1, addr));
|
||||||
|
emit_insn (gen_tle_lox10_sp64 (temp2, temp1, addr));
|
||||||
|
}
|
||||||
|
ret = gen_rtx_PLUS (Pmode, gen_rtx_REG (Pmode, 7), temp2);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
abort ();
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
abort (); /* for now ... */
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Legitimize PIC addresses. If the address is already position-independent,
|
/* Legitimize PIC addresses. If the address is already position-independent,
|
||||||
we return ORIG. Newly generated position-independent addresses go into a
|
we return ORIG. Newly generated position-independent addresses go into a
|
||||||
reg. This is REG if nonzero, otherwise we allocate register(s) as
|
reg. This is REG if nonzero, otherwise we allocate register(s) as
|
||||||
|
@ -3117,6 +3628,52 @@ legitimize_pic_address (rtx orig, enum machine_mode mode ATTRIBUTE_UNUSED,
|
||||||
return orig;
|
return orig;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Try machine-dependent ways of modifying an illegitimate address X
|
||||||
|
to be legitimate. If we find one, return the new, valid address.
|
||||||
|
|
||||||
|
OLDX is the address as it was before break_out_memory_refs was called.
|
||||||
|
In some cases it is useful to look at this to decide what needs to be done.
|
||||||
|
|
||||||
|
MODE is the mode of the operand pointed to by X. */
|
||||||
|
|
||||||
|
rtx
|
||||||
|
legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED, enum machine_mode mode)
|
||||||
|
{
|
||||||
|
rtx orig_x = x;
|
||||||
|
|
||||||
|
if (GET_CODE (x) == PLUS && GET_CODE (XEXP (x, 0)) == MULT)
|
||||||
|
x = gen_rtx_PLUS (Pmode, XEXP (x, 1),
|
||||||
|
force_operand (XEXP (x, 0), NULL_RTX));
|
||||||
|
if (GET_CODE (x) == PLUS && GET_CODE (XEXP (x, 1)) == MULT)
|
||||||
|
x = gen_rtx_PLUS (Pmode, XEXP (x, 0),
|
||||||
|
force_operand (XEXP (x, 1), NULL_RTX));
|
||||||
|
if (GET_CODE (x) == PLUS && GET_CODE (XEXP (x, 0)) == PLUS)
|
||||||
|
x = gen_rtx_PLUS (Pmode, force_operand (XEXP (x, 0), NULL_RTX),
|
||||||
|
XEXP (x, 1));
|
||||||
|
if (GET_CODE (x) == PLUS && GET_CODE (XEXP (x, 1)) == PLUS)
|
||||||
|
x = gen_rtx_PLUS (Pmode, XEXP (x, 0),
|
||||||
|
force_operand (XEXP (x, 1), NULL_RTX));
|
||||||
|
|
||||||
|
if (x != orig_x && legitimate_address_p (mode, x, FALSE))
|
||||||
|
return x;
|
||||||
|
|
||||||
|
if (tls_symbolic_operand (x))
|
||||||
|
x = legitimize_tls_address (x);
|
||||||
|
else if (flag_pic)
|
||||||
|
x = legitimize_pic_address (x, mode, 0);
|
||||||
|
else if (GET_CODE (x) == PLUS && CONSTANT_ADDRESS_P (XEXP (x, 1)))
|
||||||
|
x = gen_rtx_PLUS (Pmode, XEXP (x, 0),
|
||||||
|
copy_to_mode_reg (Pmode, XEXP (x, 1)));
|
||||||
|
else if (GET_CODE (x) == PLUS && CONSTANT_ADDRESS_P (XEXP (x, 0)))
|
||||||
|
x = gen_rtx_PLUS (Pmode, XEXP (x, 1),
|
||||||
|
copy_to_mode_reg (Pmode, XEXP (x, 0)));
|
||||||
|
else if (GET_CODE (x) == SYMBOL_REF
|
||||||
|
|| GET_CODE (x) == CONST
|
||||||
|
|| GET_CODE (x) == LABEL_REF)
|
||||||
|
x = copy_to_suggested_reg (x, NULL_RTX, Pmode);
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
/* Emit special PIC prologues. */
|
/* Emit special PIC prologues. */
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -6095,6 +6652,10 @@ print_operand (FILE *file, rtx x, int code)
|
||||||
/* ??? What if offset is too big? Perhaps the caller knows it isn't? */
|
/* ??? What if offset is too big? Perhaps the caller knows it isn't? */
|
||||||
fprintf (file, "%s+%d", frame_base_name, frame_base_offset);
|
fprintf (file, "%s+%d", frame_base_name, frame_base_offset);
|
||||||
return;
|
return;
|
||||||
|
case '&':
|
||||||
|
/* Print some local dynamic TLS name. */
|
||||||
|
assemble_name (file, get_some_local_dynamic_name ());
|
||||||
|
return;
|
||||||
case 'Y':
|
case 'Y':
|
||||||
/* Adjust the operand to take into account a RESTORE operation. */
|
/* Adjust the operand to take into account a RESTORE operation. */
|
||||||
if (GET_CODE (x) == CONST_INT)
|
if (GET_CODE (x) == CONST_INT)
|
||||||
|
@ -8350,4 +8911,68 @@ sparc_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED,
|
||||||
no_new_pseudos = 0;
|
no_new_pseudos = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* How to allocate a 'struct machine_function'. */
|
||||||
|
|
||||||
|
static struct machine_function *
|
||||||
|
sparc_init_machine_status (void)
|
||||||
|
{
|
||||||
|
return ggc_alloc_cleared (sizeof (struct machine_function));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Locate some local-dynamic symbol still in use by this function
|
||||||
|
so that we can print its name in local-dynamic base patterns. */
|
||||||
|
|
||||||
|
static const char *
|
||||||
|
get_some_local_dynamic_name (void)
|
||||||
|
{
|
||||||
|
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 (rtx *px, void *data ATTRIBUTE_UNUSED)
|
||||||
|
{
|
||||||
|
rtx x = *px;
|
||||||
|
|
||||||
|
if (x
|
||||||
|
&& GET_CODE (x) == SYMBOL_REF
|
||||||
|
&& SYMBOL_REF_TLS_MODEL (x) == TLS_MODEL_LOCAL_DYNAMIC)
|
||||||
|
{
|
||||||
|
cfun->machine->some_ld_name = XSTR (x, 0);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This is called from dwarf2out.c via ASM_OUTPUT_DWARF_DTPREL.
|
||||||
|
We need to emit DTP-relative relocations. */
|
||||||
|
|
||||||
|
void
|
||||||
|
sparc_output_dwarf_dtprel (FILE *file, int size, rtx x)
|
||||||
|
{
|
||||||
|
switch (size)
|
||||||
|
{
|
||||||
|
case 4:
|
||||||
|
fputs ("\t.word\t%r_tls_dtpoff32(", file);
|
||||||
|
break;
|
||||||
|
case 8:
|
||||||
|
fputs ("\t.xword\t%r_tls_dtpoff64(", file);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
abort ();
|
||||||
|
}
|
||||||
|
output_addr_const (file, x);
|
||||||
|
fputs (")", file);
|
||||||
|
}
|
||||||
|
|
||||||
#include "gt-sparc.h"
|
#include "gt-sparc.h"
|
||||||
|
|
|
@ -2099,27 +2099,18 @@ do { \
|
||||||
When PIC, we do not accept an address that would require a scratch reg
|
When PIC, we do not accept an address that would require a scratch reg
|
||||||
to load into a register. */
|
to load into a register. */
|
||||||
|
|
||||||
#define CONSTANT_ADDRESS_P(X) \
|
#define CONSTANT_ADDRESS_P(X) constant_address_p (X)
|
||||||
(GET_CODE (X) == LABEL_REF || GET_CODE (X) == SYMBOL_REF \
|
|
||||||
|| GET_CODE (X) == CONST_INT || GET_CODE (X) == HIGH \
|
|
||||||
|| (GET_CODE (X) == CONST \
|
|
||||||
&& ! (flag_pic && pic_address_needs_scratch (X))))
|
|
||||||
|
|
||||||
/* Define this, so that when PIC, reload won't try to reload invalid
|
/* Define this, so that when PIC, reload won't try to reload invalid
|
||||||
addresses which require two reload registers. */
|
addresses which require two reload registers. */
|
||||||
|
|
||||||
#define LEGITIMATE_PIC_OPERAND_P(X) (! pic_address_needs_scratch (X))
|
#define LEGITIMATE_PIC_OPERAND_P(X) legitimate_pic_operand_p (X)
|
||||||
|
|
||||||
/* Nonzero if the constant value X is a legitimate general operand.
|
/* Nonzero if the constant value X is a legitimate general operand.
|
||||||
Anything can be made to work except floating point constants.
|
Anything can be made to work except floating point constants.
|
||||||
If TARGET_VIS, 0.0 can be made to work as well. */
|
If TARGET_VIS, 0.0 can be made to work as well. */
|
||||||
|
|
||||||
#define LEGITIMATE_CONSTANT_P(X) \
|
#define LEGITIMATE_CONSTANT_P(X) legitimate_constant_p (X)
|
||||||
(GET_CODE (X) != CONST_DOUBLE || GET_MODE (X) == VOIDmode || \
|
|
||||||
(TARGET_VIS && \
|
|
||||||
(GET_MODE (X) == SFmode || GET_MODE (X) == DFmode || \
|
|
||||||
GET_MODE (X) == TFmode) && \
|
|
||||||
fp_zero_operand (X, GET_MODE (X))))
|
|
||||||
|
|
||||||
/* The macros REG_OK_FOR..._P assume that the arg is a REG rtx
|
/* The macros REG_OK_FOR..._P assume that the arg is a REG rtx
|
||||||
and check its validity for a certain class.
|
and check its validity for a certain class.
|
||||||
|
@ -2226,110 +2217,19 @@ do { \
|
||||||
#define RTX_OK_FOR_OLO10_P(X) \
|
#define RTX_OK_FOR_OLO10_P(X) \
|
||||||
(GET_CODE (X) == CONST_INT && INTVAL (X) >= -0x1000 && INTVAL (X) < 0xc00 - 8)
|
(GET_CODE (X) == CONST_INT && INTVAL (X) >= -0x1000 && INTVAL (X) < 0xc00 - 8)
|
||||||
|
|
||||||
|
#ifdef REG_OK_STRICT
|
||||||
#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \
|
#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \
|
||||||
{ if (RTX_OK_FOR_BASE_P (X)) \
|
{ \
|
||||||
goto ADDR; \
|
if (legitimate_address_p (MODE, X, 1)) \
|
||||||
else if (GET_CODE (X) == PLUS) \
|
|
||||||
{ \
|
|
||||||
register rtx op0 = XEXP (X, 0); \
|
|
||||||
register rtx op1 = XEXP (X, 1); \
|
|
||||||
if (flag_pic && op0 == pic_offset_table_rtx) \
|
|
||||||
{ \
|
|
||||||
if (RTX_OK_FOR_BASE_P (op1)) \
|
|
||||||
goto ADDR; \
|
|
||||||
else if (flag_pic == 1 \
|
|
||||||
&& GET_CODE (op1) != REG \
|
|
||||||
&& GET_CODE (op1) != LO_SUM \
|
|
||||||
&& GET_CODE (op1) != MEM \
|
|
||||||
&& (! SYMBOLIC_CONST (op1) \
|
|
||||||
|| MODE == Pmode) \
|
|
||||||
&& (GET_CODE (op1) != CONST_INT \
|
|
||||||
|| SMALL_INT (op1))) \
|
|
||||||
goto ADDR; \
|
|
||||||
} \
|
|
||||||
else if (RTX_OK_FOR_BASE_P (op0)) \
|
|
||||||
{ \
|
|
||||||
if ((RTX_OK_FOR_INDEX_P (op1) \
|
|
||||||
/* We prohibit REG + REG for TFmode when \
|
|
||||||
there are no instructions which accept \
|
|
||||||
REG+REG instructions. We do this \
|
|
||||||
because REG+REG is not an offsetable \
|
|
||||||
address. If we get the situation \
|
|
||||||
in reload where source and destination \
|
|
||||||
of a movtf pattern are both MEMs with \
|
|
||||||
REG+REG address, then only one of them \
|
|
||||||
gets converted to an offsetable \
|
|
||||||
address. */ \
|
|
||||||
&& (MODE != TFmode \
|
|
||||||
|| (TARGET_FPU && TARGET_ARCH64 \
|
|
||||||
&& TARGET_V9 \
|
|
||||||
&& TARGET_HARD_QUAD)) \
|
|
||||||
/* We prohibit REG + REG on ARCH32 if \
|
|
||||||
not optimizing for DFmode/DImode \
|
|
||||||
because then mem_min_alignment is \
|
|
||||||
likely to be zero after reload and the \
|
|
||||||
forced split would lack a matching \
|
|
||||||
splitter pattern. */ \
|
|
||||||
&& (TARGET_ARCH64 || optimize \
|
|
||||||
|| (MODE != DFmode \
|
|
||||||
&& MODE != DImode))) \
|
|
||||||
|| RTX_OK_FOR_OFFSET_P (op1)) \
|
|
||||||
goto ADDR; \
|
|
||||||
} \
|
|
||||||
else if (RTX_OK_FOR_BASE_P (op1)) \
|
|
||||||
{ \
|
|
||||||
if ((RTX_OK_FOR_INDEX_P (op0) \
|
|
||||||
/* See the previous comment. */ \
|
|
||||||
&& (MODE != TFmode \
|
|
||||||
|| (TARGET_FPU && TARGET_ARCH64 \
|
|
||||||
&& TARGET_V9 \
|
|
||||||
&& TARGET_HARD_QUAD)) \
|
|
||||||
&& (TARGET_ARCH64 || optimize \
|
|
||||||
|| (MODE != DFmode \
|
|
||||||
&& MODE != DImode))) \
|
|
||||||
|| RTX_OK_FOR_OFFSET_P (op0)) \
|
|
||||||
goto ADDR; \
|
|
||||||
} \
|
|
||||||
else if (USE_AS_OFFSETABLE_LO10 \
|
|
||||||
&& GET_CODE (op0) == LO_SUM \
|
|
||||||
&& TARGET_ARCH64 \
|
|
||||||
&& ! TARGET_CM_MEDMID \
|
|
||||||
&& RTX_OK_FOR_OLO10_P (op1)) \
|
|
||||||
{ \
|
|
||||||
register rtx op00 = XEXP (op0, 0); \
|
|
||||||
register rtx op01 = XEXP (op0, 1); \
|
|
||||||
if (RTX_OK_FOR_BASE_P (op00) \
|
|
||||||
&& CONSTANT_P (op01)) \
|
|
||||||
goto ADDR; \
|
|
||||||
} \
|
|
||||||
else if (USE_AS_OFFSETABLE_LO10 \
|
|
||||||
&& GET_CODE (op1) == LO_SUM \
|
|
||||||
&& TARGET_ARCH64 \
|
|
||||||
&& ! TARGET_CM_MEDMID \
|
|
||||||
&& RTX_OK_FOR_OLO10_P (op0)) \
|
|
||||||
{ \
|
|
||||||
register rtx op10 = XEXP (op1, 0); \
|
|
||||||
register rtx op11 = XEXP (op1, 1); \
|
|
||||||
if (RTX_OK_FOR_BASE_P (op10) \
|
|
||||||
&& CONSTANT_P (op11)) \
|
|
||||||
goto ADDR; \
|
|
||||||
} \
|
|
||||||
} \
|
|
||||||
else if (GET_CODE (X) == LO_SUM) \
|
|
||||||
{ \
|
|
||||||
register rtx op0 = XEXP (X, 0); \
|
|
||||||
register rtx op1 = XEXP (X, 1); \
|
|
||||||
if (RTX_OK_FOR_BASE_P (op0) \
|
|
||||||
&& CONSTANT_P (op1) \
|
|
||||||
/* We can't allow TFmode, because an offset \
|
|
||||||
greater than or equal to the alignment (8) \
|
|
||||||
may cause the LO_SUM to overflow if !v9. */\
|
|
||||||
&& (MODE != TFmode || TARGET_V9)) \
|
|
||||||
goto ADDR; \
|
|
||||||
} \
|
|
||||||
else if (GET_CODE (X) == CONST_INT && SMALL_INT (X)) \
|
|
||||||
goto ADDR; \
|
goto ADDR; \
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \
|
||||||
|
{ \
|
||||||
|
if (legitimate_address_p (MODE, X, 0)) \
|
||||||
|
goto ADDR; \
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Go to LABEL if ADDR (a legitimate address expression)
|
/* Go to LABEL if ADDR (a legitimate address expression)
|
||||||
has an effect that depends on the machine mode it is used for.
|
has an effect that depends on the machine mode it is used for.
|
||||||
|
@ -2374,33 +2274,11 @@ do { \
|
||||||
|
|
||||||
/* On SPARC, change REG+N into REG+REG, and REG+(X*Y) into REG+REG. */
|
/* On SPARC, change REG+N into REG+REG, and REG+(X*Y) into REG+REG. */
|
||||||
#define LEGITIMIZE_ADDRESS(X,OLDX,MODE,WIN) \
|
#define LEGITIMIZE_ADDRESS(X,OLDX,MODE,WIN) \
|
||||||
{ rtx sparc_x = (X); \
|
{ \
|
||||||
if (GET_CODE (X) == PLUS && GET_CODE (XEXP (X, 0)) == MULT) \
|
(X) = legitimize_address (X, OLDX, MODE); \
|
||||||
(X) = gen_rtx_PLUS (Pmode, XEXP (X, 1), \
|
if (memory_address_p (MODE, X)) \
|
||||||
force_operand (XEXP (X, 0), NULL_RTX)); \
|
goto WIN; \
|
||||||
if (GET_CODE (X) == PLUS && GET_CODE (XEXP (X, 1)) == MULT) \
|
}
|
||||||
(X) = gen_rtx_PLUS (Pmode, XEXP (X, 0), \
|
|
||||||
force_operand (XEXP (X, 1), NULL_RTX)); \
|
|
||||||
if (GET_CODE (X) == PLUS && GET_CODE (XEXP (X, 0)) == PLUS) \
|
|
||||||
(X) = gen_rtx_PLUS (Pmode, force_operand (XEXP (X, 0), NULL_RTX),\
|
|
||||||
XEXP (X, 1)); \
|
|
||||||
if (GET_CODE (X) == PLUS && GET_CODE (XEXP (X, 1)) == PLUS) \
|
|
||||||
(X) = gen_rtx_PLUS (Pmode, XEXP (X, 0), \
|
|
||||||
force_operand (XEXP (X, 1), NULL_RTX)); \
|
|
||||||
if (sparc_x != (X) && memory_address_p (MODE, X)) \
|
|
||||||
goto WIN; \
|
|
||||||
if (flag_pic) (X) = legitimize_pic_address (X, MODE, 0); \
|
|
||||||
else if (GET_CODE (X) == PLUS && CONSTANT_ADDRESS_P (XEXP (X, 1))) \
|
|
||||||
(X) = gen_rtx_PLUS (Pmode, XEXP (X, 0), \
|
|
||||||
copy_to_mode_reg (Pmode, XEXP (X, 1))); \
|
|
||||||
else if (GET_CODE (X) == PLUS && CONSTANT_ADDRESS_P (XEXP (X, 0))) \
|
|
||||||
(X) = gen_rtx_PLUS (Pmode, XEXP (X, 1), \
|
|
||||||
copy_to_mode_reg (Pmode, XEXP (X, 0))); \
|
|
||||||
else if (GET_CODE (X) == SYMBOL_REF || GET_CODE (X) == CONST \
|
|
||||||
|| GET_CODE (X) == LABEL_REF) \
|
|
||||||
(X) = copy_to_suggested_reg (X, NULL_RTX, Pmode); \
|
|
||||||
if (memory_address_p (MODE, X)) \
|
|
||||||
goto WIN; }
|
|
||||||
|
|
||||||
/* Try a machine-dependent way of reloading an illegitimate address
|
/* Try a machine-dependent way of reloading an illegitimate address
|
||||||
operand. If we find one, push the reload and jump to WIN. This
|
operand. If we find one, push the reload and jump to WIN. This
|
||||||
|
@ -2845,8 +2723,16 @@ do { \
|
||||||
#define ASM_OUTPUT_IDENT(FILE, NAME) \
|
#define ASM_OUTPUT_IDENT(FILE, NAME) \
|
||||||
fprintf (FILE, "%s\"%s\"\n", IDENT_ASM_OP, NAME);
|
fprintf (FILE, "%s\"%s\"\n", IDENT_ASM_OP, NAME);
|
||||||
|
|
||||||
|
/* Emit a dtp-relative reference to a TLS variable. */
|
||||||
|
|
||||||
|
#ifdef HAVE_AS_TLS
|
||||||
|
#define ASM_OUTPUT_DWARF_DTPREL(FILE, SIZE, X) \
|
||||||
|
sparc_output_dwarf_dtprel (FILE, SIZE, X)
|
||||||
|
#endif
|
||||||
|
|
||||||
#define PRINT_OPERAND_PUNCT_VALID_P(CHAR) \
|
#define PRINT_OPERAND_PUNCT_VALID_P(CHAR) \
|
||||||
((CHAR) == '#' || (CHAR) == '*' || (CHAR) == '^' || (CHAR) == '(' || (CHAR) == '_')
|
((CHAR) == '#' || (CHAR) == '*' || (CHAR) == '^' \
|
||||||
|
|| (CHAR) == '(' || (CHAR) == '_' || (CHAR) == '&')
|
||||||
|
|
||||||
/* Print operand X (an rtx) in assembler syntax to file FILE.
|
/* Print operand X (an rtx) in assembler syntax to file FILE.
|
||||||
CODE is a letter or dot (`z' in `%z0') or 0 if no letter was specified.
|
CODE is a letter or dot (`z' in `%z0') or 0 if no letter was specified.
|
||||||
|
@ -2933,6 +2819,14 @@ do { \
|
||||||
} \
|
} \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_AS_TLS
|
||||||
|
#define TARGET_TLS 1
|
||||||
|
#else
|
||||||
|
#define TARGET_TLS 0
|
||||||
|
#endif
|
||||||
|
#define TARGET_SUN_TLS TARGET_TLS
|
||||||
|
#define TARGET_GNU_TLS 0
|
||||||
|
|
||||||
/* Define the codes that are matched by predicates in sparc.c. */
|
/* Define the codes that are matched by predicates in sparc.c. */
|
||||||
|
|
||||||
#define PREDICATE_CODES \
|
#define PREDICATE_CODES \
|
||||||
|
@ -2980,7 +2874,11 @@ do { \
|
||||||
{"clobbered_register", {REG}}, \
|
{"clobbered_register", {REG}}, \
|
||||||
{"input_operand", {SUBREG, REG, CONST_INT, MEM, CONST}}, \
|
{"input_operand", {SUBREG, REG, CONST_INT, MEM, CONST}}, \
|
||||||
{"const64_operand", {CONST_INT, CONST_DOUBLE}}, \
|
{"const64_operand", {CONST_INT, CONST_DOUBLE}}, \
|
||||||
{"const64_high_operand", {CONST_INT, CONST_DOUBLE}},
|
{"const64_high_operand", {CONST_INT, CONST_DOUBLE}}, \
|
||||||
|
{"tgd_symbolic_operand", {SYMBOL_REF}}, \
|
||||||
|
{"tld_symbolic_operand", {SYMBOL_REF}}, \
|
||||||
|
{"tie_symbolic_operand", {SYMBOL_REF}}, \
|
||||||
|
{"tle_symbolic_operand", {SYMBOL_REF}},
|
||||||
|
|
||||||
/* The number of Pmode words for the setjmp buffer. */
|
/* The number of Pmode words for the setjmp buffer. */
|
||||||
#define JMP_BUF_SIZE 12
|
#define JMP_BUF_SIZE 12
|
||||||
|
|
|
@ -38,6 +38,13 @@
|
||||||
(UNSPEC_EMB_TEXTHI 14)
|
(UNSPEC_EMB_TEXTHI 14)
|
||||||
(UNSPEC_EMB_TEXTULO 15)
|
(UNSPEC_EMB_TEXTULO 15)
|
||||||
(UNSPEC_EMB_SETHM 18)
|
(UNSPEC_EMB_SETHM 18)
|
||||||
|
|
||||||
|
(UNSPEC_TLSGD 30)
|
||||||
|
(UNSPEC_TLSLDM 31)
|
||||||
|
(UNSPEC_TLSLDO 32)
|
||||||
|
(UNSPEC_TLSIE 33)
|
||||||
|
(UNSPEC_TLSLE 34)
|
||||||
|
(UNSPEC_TLSLD_BASE 35)
|
||||||
])
|
])
|
||||||
|
|
||||||
(define_constants
|
(define_constants
|
||||||
|
@ -195,6 +202,9 @@
|
||||||
|
|
||||||
;; Attributes for instruction and branch scheduling
|
;; Attributes for instruction and branch scheduling
|
||||||
|
|
||||||
|
(define_attr "tls_call_delay" "false,true"
|
||||||
|
(symbol_ref "tls_call_delay (insn)"))
|
||||||
|
|
||||||
(define_attr "in_call_delay" "false,true"
|
(define_attr "in_call_delay" "false,true"
|
||||||
(cond [(eq_attr "type" "uncond_branch,branch,call,sibcall,call_no_delay_slot,multi")
|
(cond [(eq_attr "type" "uncond_branch,branch,call,sibcall,call_no_delay_slot,multi")
|
||||||
(const_string "false")
|
(const_string "false")
|
||||||
|
@ -202,7 +212,8 @@
|
||||||
(if_then_else (eq_attr "length" "1")
|
(if_then_else (eq_attr "length" "1")
|
||||||
(const_string "true")
|
(const_string "true")
|
||||||
(const_string "false"))]
|
(const_string "false"))]
|
||||||
(if_then_else (eq_attr "length" "1")
|
(if_then_else (and (eq_attr "length" "1")
|
||||||
|
(eq_attr "tls_call_delay" "true"))
|
||||||
(const_string "true")
|
(const_string "true")
|
||||||
(const_string "false"))))
|
(const_string "false"))))
|
||||||
|
|
||||||
|
@ -1681,6 +1692,10 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Fixup TLS cases. */
|
||||||
|
if (tls_symbolic_operand (operands [1]))
|
||||||
|
operands[1] = legitimize_tls_address (operands[1]);
|
||||||
|
|
||||||
/* Fixup PIC cases. */
|
/* Fixup PIC cases. */
|
||||||
if (flag_pic)
|
if (flag_pic)
|
||||||
{
|
{
|
||||||
|
@ -1740,6 +1755,10 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Fixup TLS cases. */
|
||||||
|
if (tls_symbolic_operand (operands [1]))
|
||||||
|
operands[1] = legitimize_tls_address (operands[1]);
|
||||||
|
|
||||||
/* Fixup PIC cases. */
|
/* Fixup PIC cases. */
|
||||||
if (flag_pic)
|
if (flag_pic)
|
||||||
{
|
{
|
||||||
|
@ -1822,6 +1841,10 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Fixup TLS cases. */
|
||||||
|
if (tls_symbolic_operand (operands [1]))
|
||||||
|
operands[1] = legitimize_tls_address (operands[1]);
|
||||||
|
|
||||||
/* Fixup PIC cases. */
|
/* Fixup PIC cases. */
|
||||||
if (flag_pic)
|
if (flag_pic)
|
||||||
{
|
{
|
||||||
|
@ -1998,6 +2021,10 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Fixup TLS cases. */
|
||||||
|
if (tls_symbolic_operand (operands [1]))
|
||||||
|
operands[1] = legitimize_tls_address (operands[1]);
|
||||||
|
|
||||||
if (flag_pic)
|
if (flag_pic)
|
||||||
{
|
{
|
||||||
if (CONSTANT_P (operands[1])
|
if (CONSTANT_P (operands[1])
|
||||||
|
@ -8366,3 +8393,566 @@
|
||||||
"TARGET_V9"
|
"TARGET_V9"
|
||||||
"t%C0\t%%xcc, %1"
|
"t%C0\t%%xcc, %1"
|
||||||
[(set_attr "type" "trap")])
|
[(set_attr "type" "trap")])
|
||||||
|
|
||||||
|
;; TLS support
|
||||||
|
(define_insn "tgd_hi22"
|
||||||
|
[(set (match_operand:SI 0 "register_operand" "=r")
|
||||||
|
(high:SI (unspec:SI [(match_operand 1 "tgd_symbolic_operand" "")]
|
||||||
|
UNSPEC_TLSGD)))]
|
||||||
|
"TARGET_TLS"
|
||||||
|
"sethi\\t%%tgd_hi22(%a1), %0")
|
||||||
|
|
||||||
|
(define_insn "tgd_lo10"
|
||||||
|
[(set (match_operand:SI 0 "register_operand" "=r")
|
||||||
|
(lo_sum:SI (match_operand:SI 1 "register_operand" "r")
|
||||||
|
(unspec:SI [(match_operand 2 "tgd_symbolic_operand" "")]
|
||||||
|
UNSPEC_TLSGD)))]
|
||||||
|
"TARGET_TLS"
|
||||||
|
"add\\t%1, %%tgd_lo10(%a2), %0")
|
||||||
|
|
||||||
|
(define_insn "tgd_add32"
|
||||||
|
[(set (match_operand:SI 0 "register_operand" "=r")
|
||||||
|
(plus:SI (match_operand:SI 1 "register_operand" "r")
|
||||||
|
(unspec:SI [(match_operand:SI 2 "register_operand" "r")
|
||||||
|
(match_operand 3 "tgd_symbolic_operand" "")]
|
||||||
|
UNSPEC_TLSGD)))]
|
||||||
|
"TARGET_TLS && TARGET_ARCH32"
|
||||||
|
"add\\t%1, %2, %0, %%tgd_add(%a3)")
|
||||||
|
|
||||||
|
(define_insn "tgd_add64"
|
||||||
|
[(set (match_operand:DI 0 "register_operand" "=r")
|
||||||
|
(plus:DI (match_operand:DI 1 "register_operand" "r")
|
||||||
|
(unspec:DI [(match_operand:SI 2 "register_operand" "r")
|
||||||
|
(match_operand 3 "tgd_symbolic_operand" "")]
|
||||||
|
UNSPEC_TLSGD)))]
|
||||||
|
"TARGET_TLS && TARGET_ARCH64"
|
||||||
|
"add\\t%1, %2, %0, %%tgd_add(%a3)")
|
||||||
|
|
||||||
|
(define_insn "tgd_call32"
|
||||||
|
[(set (match_operand 0 "register_operand" "=r")
|
||||||
|
(call (mem:SI (unspec:SI [(match_operand:SI 1 "symbolic_operand" "s")
|
||||||
|
(match_operand 2 "tgd_symbolic_operand" "")]
|
||||||
|
UNSPEC_TLSGD))
|
||||||
|
(match_operand 3 "" "")))
|
||||||
|
(clobber (reg:SI 15))]
|
||||||
|
"TARGET_TLS && TARGET_ARCH32"
|
||||||
|
"call\t%a1, %%tgd_call(%a2)%#"
|
||||||
|
[(set_attr "type" "call")])
|
||||||
|
|
||||||
|
(define_insn "tgd_call64"
|
||||||
|
[(set (match_operand 0 "register_operand" "=r")
|
||||||
|
(call (mem:DI (unspec:DI [(match_operand:DI 1 "symbolic_operand" "s")
|
||||||
|
(match_operand 2 "tgd_symbolic_operand" "")]
|
||||||
|
UNSPEC_TLSGD))
|
||||||
|
(match_operand 3 "" "")))
|
||||||
|
(clobber (reg:DI 15))]
|
||||||
|
"TARGET_TLS && TARGET_ARCH64"
|
||||||
|
"call\t%a1, %%tgd_call(%a2)%#"
|
||||||
|
[(set_attr "type" "call")])
|
||||||
|
|
||||||
|
(define_insn "tldm_hi22"
|
||||||
|
[(set (match_operand:SI 0 "register_operand" "=r")
|
||||||
|
(high:SI (unspec:SI [(const_int 0)] UNSPEC_TLSLDM)))]
|
||||||
|
"TARGET_TLS"
|
||||||
|
"sethi\\t%%tldm_hi22(%&), %0")
|
||||||
|
|
||||||
|
(define_insn "tldm_lo10"
|
||||||
|
[(set (match_operand:SI 0 "register_operand" "=r")
|
||||||
|
(lo_sum:SI (match_operand:SI 1 "register_operand" "r")
|
||||||
|
(unspec:SI [(const_int 0)] UNSPEC_TLSLDM)))]
|
||||||
|
"TARGET_TLS"
|
||||||
|
"add\\t%1, %%tldm_lo10(%&), %0")
|
||||||
|
|
||||||
|
(define_insn "tldm_add32"
|
||||||
|
[(set (match_operand:SI 0 "register_operand" "=r")
|
||||||
|
(plus:SI (match_operand:SI 1 "register_operand" "r")
|
||||||
|
(unspec:SI [(match_operand:SI 2 "register_operand" "r")]
|
||||||
|
UNSPEC_TLSLDM)))]
|
||||||
|
"TARGET_TLS && TARGET_ARCH32"
|
||||||
|
"add\\t%1, %2, %0, %%tldm_add(%&)")
|
||||||
|
|
||||||
|
(define_insn "tldm_add64"
|
||||||
|
[(set (match_operand:DI 0 "register_operand" "=r")
|
||||||
|
(plus:DI (match_operand:DI 1 "register_operand" "r")
|
||||||
|
(unspec:DI [(match_operand:SI 2 "register_operand" "r")]
|
||||||
|
UNSPEC_TLSLDM)))]
|
||||||
|
"TARGET_TLS && TARGET_ARCH64"
|
||||||
|
"add\\t%1, %2, %0, %%tldm_add(%&)")
|
||||||
|
|
||||||
|
(define_insn "tldm_call32"
|
||||||
|
[(set (match_operand 0 "register_operand" "=r")
|
||||||
|
(call (mem:SI (unspec:SI [(match_operand:SI 1 "symbolic_operand" "s")]
|
||||||
|
UNSPEC_TLSLDM))
|
||||||
|
(match_operand 2 "" "")))
|
||||||
|
(clobber (reg:SI 15))]
|
||||||
|
"TARGET_TLS && TARGET_ARCH32"
|
||||||
|
"call\t%a1, %%tldm_call(%&)%#"
|
||||||
|
[(set_attr "type" "call")])
|
||||||
|
|
||||||
|
(define_insn "tldm_call64"
|
||||||
|
[(set (match_operand 0 "register_operand" "=r")
|
||||||
|
(call (mem:DI (unspec:DI [(match_operand:DI 1 "symbolic_operand" "s")]
|
||||||
|
UNSPEC_TLSLDM))
|
||||||
|
(match_operand 2 "" "")))
|
||||||
|
(clobber (reg:DI 15))]
|
||||||
|
"TARGET_TLS && TARGET_ARCH64"
|
||||||
|
"call\t%a1, %%tldm_call(%&)%#"
|
||||||
|
[(set_attr "type" "call")])
|
||||||
|
|
||||||
|
(define_insn "tldo_hix22"
|
||||||
|
[(set (match_operand:SI 0 "register_operand" "=r")
|
||||||
|
(high:SI (unspec:SI [(match_operand 1 "tld_symbolic_operand" "")]
|
||||||
|
UNSPEC_TLSLDO)))]
|
||||||
|
"TARGET_TLS"
|
||||||
|
"sethi\\t%%tldo_hix22(%a1), %0")
|
||||||
|
|
||||||
|
(define_insn "tldo_lox10"
|
||||||
|
[(set (match_operand:SI 0 "register_operand" "=r")
|
||||||
|
(lo_sum:SI (match_operand:SI 1 "register_operand" "r")
|
||||||
|
(unspec:SI [(match_operand 2 "tld_symbolic_operand" "")]
|
||||||
|
UNSPEC_TLSLDO)))]
|
||||||
|
"TARGET_TLS"
|
||||||
|
"xor\\t%1, %%tldo_lox10(%a2), %0")
|
||||||
|
|
||||||
|
(define_insn "tldo_add32"
|
||||||
|
[(set (match_operand:SI 0 "register_operand" "=r")
|
||||||
|
(plus:SI (match_operand:SI 1 "register_operand" "r")
|
||||||
|
(unspec:SI [(match_operand:SI 2 "register_operand" "r")
|
||||||
|
(match_operand 3 "tld_symbolic_operand" "")]
|
||||||
|
UNSPEC_TLSLDO)))]
|
||||||
|
"TARGET_TLS && TARGET_ARCH32"
|
||||||
|
"add\\t%1, %2, %0, %%tldo_add(%a3)")
|
||||||
|
|
||||||
|
(define_insn "tldo_add64"
|
||||||
|
[(set (match_operand:DI 0 "register_operand" "=r")
|
||||||
|
(plus:DI (match_operand:DI 1 "register_operand" "r")
|
||||||
|
(unspec:DI [(match_operand:SI 2 "register_operand" "r")
|
||||||
|
(match_operand 3 "tld_symbolic_operand" "")]
|
||||||
|
UNSPEC_TLSLDO)))]
|
||||||
|
"TARGET_TLS && TARGET_ARCH64"
|
||||||
|
"add\\t%1, %2, %0, %%tldo_add(%a3)")
|
||||||
|
|
||||||
|
(define_insn "tie_hi22"
|
||||||
|
[(set (match_operand:SI 0 "register_operand" "=r")
|
||||||
|
(high:SI (unspec:SI [(match_operand 1 "tie_symbolic_operand" "")]
|
||||||
|
UNSPEC_TLSIE)))]
|
||||||
|
"TARGET_TLS"
|
||||||
|
"sethi\\t%%tie_hi22(%a1), %0")
|
||||||
|
|
||||||
|
(define_insn "tie_lo10"
|
||||||
|
[(set (match_operand:SI 0 "register_operand" "=r")
|
||||||
|
(lo_sum:SI (match_operand:SI 1 "register_operand" "r")
|
||||||
|
(unspec:SI [(match_operand 2 "tie_symbolic_operand" "")]
|
||||||
|
UNSPEC_TLSIE)))]
|
||||||
|
"TARGET_TLS"
|
||||||
|
"add\\t%1, %%tie_lo10(%a2), %0")
|
||||||
|
|
||||||
|
(define_insn "tie_ld32"
|
||||||
|
[(set (match_operand:SI 0 "register_operand" "=r")
|
||||||
|
(unspec:SI [(match_operand:SI 1 "register_operand" "r")
|
||||||
|
(match_operand:SI 2 "register_operand" "r")
|
||||||
|
(match_operand 3 "tie_symbolic_operand" "")]
|
||||||
|
UNSPEC_TLSIE))]
|
||||||
|
"TARGET_TLS && TARGET_ARCH32"
|
||||||
|
"ld\\t[%1 + %2], %0, %%tie_ld(%a3)"
|
||||||
|
[(set_attr "type" "load")])
|
||||||
|
|
||||||
|
(define_insn "tie_ld64"
|
||||||
|
[(set (match_operand:DI 0 "register_operand" "=r")
|
||||||
|
(unspec:DI [(match_operand:DI 1 "register_operand" "r")
|
||||||
|
(match_operand:SI 2 "register_operand" "r")
|
||||||
|
(match_operand 3 "tie_symbolic_operand" "")]
|
||||||
|
UNSPEC_TLSIE))]
|
||||||
|
"TARGET_TLS && TARGET_ARCH64"
|
||||||
|
"ldx\\t[%1 + %2], %0, %%tie_ldx(%a3)"
|
||||||
|
[(set_attr "type" "load")])
|
||||||
|
|
||||||
|
(define_insn "tie_add32"
|
||||||
|
[(set (match_operand:SI 0 "register_operand" "=r")
|
||||||
|
(plus:SI (match_operand:SI 1 "register_operand" "r")
|
||||||
|
(unspec:SI [(match_operand:SI 2 "register_operand" "r")
|
||||||
|
(match_operand 3 "tld_symbolic_operand" "")]
|
||||||
|
UNSPEC_TLSIE)))]
|
||||||
|
"TARGET_SUN_TLS && TARGET_ARCH32"
|
||||||
|
"add\\t%1, %2, %0, %%tie_add(%a3)")
|
||||||
|
|
||||||
|
(define_insn "tie_add64"
|
||||||
|
[(set (match_operand:DI 0 "register_operand" "=r")
|
||||||
|
(plus:DI (match_operand:DI 1 "register_operand" "r")
|
||||||
|
(unspec:DI [(match_operand:DI 2 "register_operand" "r")
|
||||||
|
(match_operand 3 "tld_symbolic_operand" "")]
|
||||||
|
UNSPEC_TLSIE)))]
|
||||||
|
"TARGET_SUN_TLS && TARGET_ARCH64"
|
||||||
|
"add\\t%1, %2, %0, %%tie_add(%a3)")
|
||||||
|
|
||||||
|
(define_insn "tle_hix22_sp32"
|
||||||
|
[(set (match_operand:SI 0 "register_operand" "=r")
|
||||||
|
(high:SI (unspec:SI [(match_operand 1 "tle_symbolic_operand" "")]
|
||||||
|
UNSPEC_TLSLE)))]
|
||||||
|
"TARGET_TLS && TARGET_ARCH32"
|
||||||
|
"sethi\\t%%tle_hix22(%a1), %0")
|
||||||
|
|
||||||
|
(define_insn "tle_lox10_sp32"
|
||||||
|
[(set (match_operand:SI 0 "register_operand" "=r")
|
||||||
|
(lo_sum:SI (match_operand:SI 1 "register_operand" "r")
|
||||||
|
(unspec:SI [(match_operand 2 "tle_symbolic_operand" "")]
|
||||||
|
UNSPEC_TLSLE)))]
|
||||||
|
"TARGET_TLS && TARGET_ARCH32"
|
||||||
|
"xor\\t%1, %%tle_lox10(%a2), %0")
|
||||||
|
|
||||||
|
(define_insn "tle_hix22_sp64"
|
||||||
|
[(set (match_operand:DI 0 "register_operand" "=r")
|
||||||
|
(high:DI (unspec:DI [(match_operand 1 "tle_symbolic_operand" "")]
|
||||||
|
UNSPEC_TLSLE)))]
|
||||||
|
"TARGET_TLS && TARGET_ARCH64"
|
||||||
|
"sethi\\t%%tle_hix22(%a1), %0")
|
||||||
|
|
||||||
|
(define_insn "tle_lox10_sp64"
|
||||||
|
[(set (match_operand:DI 0 "register_operand" "=r")
|
||||||
|
(lo_sum:DI (match_operand:DI 1 "register_operand" "r")
|
||||||
|
(unspec:DI [(match_operand 2 "tle_symbolic_operand" "")]
|
||||||
|
UNSPEC_TLSLE)))]
|
||||||
|
"TARGET_TLS && TARGET_ARCH64"
|
||||||
|
"xor\\t%1, %%tle_lox10(%a2), %0")
|
||||||
|
|
||||||
|
;; Now patterns combinding tldo_add{32,64} with some integer loads or stores
|
||||||
|
(define_insn "*tldo_ldub_sp32"
|
||||||
|
[(set (match_operand:QI 0 "register_operand" "=r")
|
||||||
|
(mem:QI (plus:SI (unspec:SI [(match_operand:SI 2 "register_operand" "r")
|
||||||
|
(match_operand 3 "tld_symbolic_operand" "")]
|
||||||
|
UNSPEC_TLSLDO)
|
||||||
|
(match_operand:SI 1 "register_operand" "r"))))]
|
||||||
|
"TARGET_TLS && TARGET_ARCH32"
|
||||||
|
"ldub\t[%1 + %2], %0, %%tldo_add(%3)"
|
||||||
|
[(set_attr "type" "load")
|
||||||
|
(set_attr "us3load_type" "3cycle")])
|
||||||
|
|
||||||
|
(define_insn "*tldo_ldub1_sp32"
|
||||||
|
[(set (match_operand:HI 0 "register_operand" "=r")
|
||||||
|
(zero_extend:HI (mem:QI (plus:SI (unspec:SI [(match_operand:SI 2 "register_operand" "r")
|
||||||
|
(match_operand 3 "tld_symbolic_operand" "")]
|
||||||
|
UNSPEC_TLSLDO)
|
||||||
|
(match_operand:SI 1 "register_operand" "r")))))]
|
||||||
|
"TARGET_TLS && TARGET_ARCH32"
|
||||||
|
"ldub\t[%1 + %2], %0, %%tldo_add(%3)"
|
||||||
|
[(set_attr "type" "load")
|
||||||
|
(set_attr "us3load_type" "3cycle")])
|
||||||
|
|
||||||
|
(define_insn "*tldo_ldub2_sp32"
|
||||||
|
[(set (match_operand:SI 0 "register_operand" "=r")
|
||||||
|
(zero_extend:SI (mem:QI (plus:SI (unspec:SI [(match_operand:SI 2 "register_operand" "r")
|
||||||
|
(match_operand 3 "tld_symbolic_operand" "")]
|
||||||
|
UNSPEC_TLSLDO)
|
||||||
|
(match_operand:SI 1 "register_operand" "r")))))]
|
||||||
|
"TARGET_TLS && TARGET_ARCH32"
|
||||||
|
"ldub\t[%1 + %2], %0, %%tldo_add(%3)"
|
||||||
|
[(set_attr "type" "load")
|
||||||
|
(set_attr "us3load_type" "3cycle")])
|
||||||
|
|
||||||
|
(define_insn "*tldo_ldsb1_sp32"
|
||||||
|
[(set (match_operand:HI 0 "register_operand" "=r")
|
||||||
|
(sign_extend:HI (mem:QI (plus:SI (unspec:SI [(match_operand:SI 2 "register_operand" "r")
|
||||||
|
(match_operand 3 "tld_symbolic_operand" "")]
|
||||||
|
UNSPEC_TLSLDO)
|
||||||
|
(match_operand:SI 1 "register_operand" "r")))))]
|
||||||
|
"TARGET_TLS && TARGET_ARCH32"
|
||||||
|
"ldsb\t[%1 + %2], %0, %%tldo_add(%3)"
|
||||||
|
[(set_attr "type" "sload")
|
||||||
|
(set_attr "us3load_type" "3cycle")])
|
||||||
|
|
||||||
|
(define_insn "*tldo_ldsb2_sp32"
|
||||||
|
[(set (match_operand:SI 0 "register_operand" "=r")
|
||||||
|
(sign_extend:SI (mem:QI (plus:SI (unspec:SI [(match_operand:SI 2 "register_operand" "r")
|
||||||
|
(match_operand 3 "tld_symbolic_operand" "")]
|
||||||
|
UNSPEC_TLSLDO)
|
||||||
|
(match_operand:SI 1 "register_operand" "r")))))]
|
||||||
|
"TARGET_TLS && TARGET_ARCH32"
|
||||||
|
"ldsb\t[%1 + %2], %0, %%tldo_add(%3)"
|
||||||
|
[(set_attr "type" "sload")
|
||||||
|
(set_attr "us3load_type" "3cycle")])
|
||||||
|
|
||||||
|
(define_insn "*tldo_ldub_sp64"
|
||||||
|
[(set (match_operand:QI 0 "register_operand" "=r")
|
||||||
|
(mem:QI (plus:DI (unspec:DI [(match_operand:SI 2 "register_operand" "r")
|
||||||
|
(match_operand 3 "tld_symbolic_operand" "")]
|
||||||
|
UNSPEC_TLSLDO)
|
||||||
|
(match_operand:DI 1 "register_operand" "r"))))]
|
||||||
|
"TARGET_TLS && TARGET_ARCH64"
|
||||||
|
"ldub\t[%1 + %2], %0, %%tldo_add(%3)"
|
||||||
|
[(set_attr "type" "load")
|
||||||
|
(set_attr "us3load_type" "3cycle")])
|
||||||
|
|
||||||
|
(define_insn "*tldo_ldub1_sp64"
|
||||||
|
[(set (match_operand:HI 0 "register_operand" "=r")
|
||||||
|
(zero_extend:HI (mem:QI (plus:DI (unspec:DI [(match_operand:SI 2 "register_operand" "r")
|
||||||
|
(match_operand 3 "tld_symbolic_operand" "")]
|
||||||
|
UNSPEC_TLSLDO)
|
||||||
|
(match_operand:DI 1 "register_operand" "r")))))]
|
||||||
|
"TARGET_TLS && TARGET_ARCH64"
|
||||||
|
"ldub\t[%1 + %2], %0, %%tldo_add(%3)"
|
||||||
|
[(set_attr "type" "load")
|
||||||
|
(set_attr "us3load_type" "3cycle")])
|
||||||
|
|
||||||
|
(define_insn "*tldo_ldub2_sp64"
|
||||||
|
[(set (match_operand:SI 0 "register_operand" "=r")
|
||||||
|
(zero_extend:SI (mem:QI (plus:DI (unspec:DI [(match_operand:SI 2 "register_operand" "r")
|
||||||
|
(match_operand 3 "tld_symbolic_operand" "")]
|
||||||
|
UNSPEC_TLSLDO)
|
||||||
|
(match_operand:DI 1 "register_operand" "r")))))]
|
||||||
|
"TARGET_TLS && TARGET_ARCH64"
|
||||||
|
"ldub\t[%1 + %2], %0, %%tldo_add(%3)"
|
||||||
|
[(set_attr "type" "load")
|
||||||
|
(set_attr "us3load_type" "3cycle")])
|
||||||
|
|
||||||
|
(define_insn "*tldo_ldub3_sp64"
|
||||||
|
[(set (match_operand:DI 0 "register_operand" "=r")
|
||||||
|
(zero_extend:DI (mem:QI (plus:DI (unspec:DI [(match_operand:SI 2 "register_operand" "r")
|
||||||
|
(match_operand 3 "tld_symbolic_operand" "")]
|
||||||
|
UNSPEC_TLSLDO)
|
||||||
|
(match_operand:DI 1 "register_operand" "r")))))]
|
||||||
|
"TARGET_TLS && TARGET_ARCH64"
|
||||||
|
"ldub\t[%1 + %2], %0, %%tldo_add(%3)"
|
||||||
|
[(set_attr "type" "load")
|
||||||
|
(set_attr "us3load_type" "3cycle")])
|
||||||
|
|
||||||
|
(define_insn "*tldo_ldsb1_sp64"
|
||||||
|
[(set (match_operand:HI 0 "register_operand" "=r")
|
||||||
|
(sign_extend:HI (mem:QI (plus:DI (unspec:DI [(match_operand:SI 2 "register_operand" "r")
|
||||||
|
(match_operand 3 "tld_symbolic_operand" "")]
|
||||||
|
UNSPEC_TLSLDO)
|
||||||
|
(match_operand:DI 1 "register_operand" "r")))))]
|
||||||
|
"TARGET_TLS && TARGET_ARCH64"
|
||||||
|
"ldsb\t[%1 + %2], %0, %%tldo_add(%3)"
|
||||||
|
[(set_attr "type" "sload")
|
||||||
|
(set_attr "us3load_type" "3cycle")])
|
||||||
|
|
||||||
|
(define_insn "*tldo_ldsb2_sp64"
|
||||||
|
[(set (match_operand:SI 0 "register_operand" "=r")
|
||||||
|
(sign_extend:SI (mem:QI (plus:DI (unspec:DI [(match_operand:SI 2 "register_operand" "r")
|
||||||
|
(match_operand 3 "tld_symbolic_operand" "")]
|
||||||
|
UNSPEC_TLSLDO)
|
||||||
|
(match_operand:DI 1 "register_operand" "r")))))]
|
||||||
|
"TARGET_TLS && TARGET_ARCH64"
|
||||||
|
"ldsb\t[%1 + %2], %0, %%tldo_add(%3)"
|
||||||
|
[(set_attr "type" "sload")
|
||||||
|
(set_attr "us3load_type" "3cycle")])
|
||||||
|
|
||||||
|
(define_insn "*tldo_ldsb3_sp64"
|
||||||
|
[(set (match_operand:DI 0 "register_operand" "=r")
|
||||||
|
(sign_extend:DI (mem:QI (plus:DI (unspec:DI [(match_operand:SI 2 "register_operand" "r")
|
||||||
|
(match_operand 3 "tld_symbolic_operand" "")]
|
||||||
|
UNSPEC_TLSLDO)
|
||||||
|
(match_operand:DI 1 "register_operand" "r")))))]
|
||||||
|
"TARGET_TLS && TARGET_ARCH64"
|
||||||
|
"ldsb\t[%1 + %2], %0, %%tldo_add(%3)"
|
||||||
|
[(set_attr "type" "sload")
|
||||||
|
(set_attr "us3load_type" "3cycle")])
|
||||||
|
|
||||||
|
(define_insn "*tldo_lduh_sp32"
|
||||||
|
[(set (match_operand:HI 0 "register_operand" "=r")
|
||||||
|
(mem:HI (plus:SI (unspec:SI [(match_operand:SI 2 "register_operand" "r")
|
||||||
|
(match_operand 3 "tld_symbolic_operand" "")]
|
||||||
|
UNSPEC_TLSLDO)
|
||||||
|
(match_operand:SI 1 "register_operand" "r"))))]
|
||||||
|
"TARGET_TLS && TARGET_ARCH32"
|
||||||
|
"lduh\t[%1 + %2], %0, %%tldo_add(%3)"
|
||||||
|
[(set_attr "type" "load")
|
||||||
|
(set_attr "us3load_type" "3cycle")])
|
||||||
|
|
||||||
|
(define_insn "*tldo_lduh1_sp32"
|
||||||
|
[(set (match_operand:SI 0 "register_operand" "=r")
|
||||||
|
(zero_extend:SI (mem:HI (plus:SI (unspec:SI [(match_operand:SI 2 "register_operand" "r")
|
||||||
|
(match_operand 3 "tld_symbolic_operand" "")]
|
||||||
|
UNSPEC_TLSLDO)
|
||||||
|
(match_operand:SI 1 "register_operand" "r")))))]
|
||||||
|
"TARGET_TLS && TARGET_ARCH32"
|
||||||
|
"lduh\t[%1 + %2], %0, %%tldo_add(%3)"
|
||||||
|
[(set_attr "type" "load")
|
||||||
|
(set_attr "us3load_type" "3cycle")])
|
||||||
|
|
||||||
|
(define_insn "*tldo_ldsh1_sp32"
|
||||||
|
[(set (match_operand:SI 0 "register_operand" "=r")
|
||||||
|
(sign_extend:SI (mem:HI (plus:SI (unspec:SI [(match_operand:SI 2 "register_operand" "r")
|
||||||
|
(match_operand 3 "tld_symbolic_operand" "")]
|
||||||
|
UNSPEC_TLSLDO)
|
||||||
|
(match_operand:SI 1 "register_operand" "r")))))]
|
||||||
|
"TARGET_TLS && TARGET_ARCH32"
|
||||||
|
"ldsh\t[%1 + %2], %0, %%tldo_add(%3)"
|
||||||
|
[(set_attr "type" "sload")
|
||||||
|
(set_attr "us3load_type" "3cycle")])
|
||||||
|
|
||||||
|
(define_insn "*tldo_lduh_sp64"
|
||||||
|
[(set (match_operand:HI 0 "register_operand" "=r")
|
||||||
|
(mem:HI (plus:DI (unspec:DI [(match_operand:SI 2 "register_operand" "r")
|
||||||
|
(match_operand 3 "tld_symbolic_operand" "")]
|
||||||
|
UNSPEC_TLSLDO)
|
||||||
|
(match_operand:DI 1 "register_operand" "r"))))]
|
||||||
|
"TARGET_TLS && TARGET_ARCH64"
|
||||||
|
"lduh\t[%1 + %2], %0, %%tldo_add(%3)"
|
||||||
|
[(set_attr "type" "load")
|
||||||
|
(set_attr "us3load_type" "3cycle")])
|
||||||
|
|
||||||
|
(define_insn "*tldo_lduh1_sp64"
|
||||||
|
[(set (match_operand:SI 0 "register_operand" "=r")
|
||||||
|
(zero_extend:SI (mem:HI (plus:DI (unspec:DI [(match_operand:SI 2 "register_operand" "r")
|
||||||
|
(match_operand 3 "tld_symbolic_operand" "")]
|
||||||
|
UNSPEC_TLSLDO)
|
||||||
|
(match_operand:DI 1 "register_operand" "r")))))]
|
||||||
|
"TARGET_TLS && TARGET_ARCH64"
|
||||||
|
"lduh\t[%1 + %2], %0, %%tldo_add(%3)"
|
||||||
|
[(set_attr "type" "load")
|
||||||
|
(set_attr "us3load_type" "3cycle")])
|
||||||
|
|
||||||
|
(define_insn "*tldo_lduh2_sp64"
|
||||||
|
[(set (match_operand:DI 0 "register_operand" "=r")
|
||||||
|
(zero_extend:DI (mem:HI (plus:DI (unspec:DI [(match_operand:SI 2 "register_operand" "r")
|
||||||
|
(match_operand 3 "tld_symbolic_operand" "")]
|
||||||
|
UNSPEC_TLSLDO)
|
||||||
|
(match_operand:DI 1 "register_operand" "r")))))]
|
||||||
|
"TARGET_TLS && TARGET_ARCH64"
|
||||||
|
"lduh\t[%1 + %2], %0, %%tldo_add(%3)"
|
||||||
|
[(set_attr "type" "load")
|
||||||
|
(set_attr "us3load_type" "3cycle")])
|
||||||
|
|
||||||
|
(define_insn "*tldo_ldsh1_sp64"
|
||||||
|
[(set (match_operand:SI 0 "register_operand" "=r")
|
||||||
|
(sign_extend:SI (mem:HI (plus:DI (unspec:DI [(match_operand:SI 2 "register_operand" "r")
|
||||||
|
(match_operand 3 "tld_symbolic_operand" "")]
|
||||||
|
UNSPEC_TLSLDO)
|
||||||
|
(match_operand:DI 1 "register_operand" "r")))))]
|
||||||
|
"TARGET_TLS && TARGET_ARCH64"
|
||||||
|
"ldsh\t[%1 + %2], %0, %%tldo_add(%3)"
|
||||||
|
[(set_attr "type" "sload")
|
||||||
|
(set_attr "us3load_type" "3cycle")])
|
||||||
|
|
||||||
|
(define_insn "*tldo_ldsh2_sp64"
|
||||||
|
[(set (match_operand:DI 0 "register_operand" "=r")
|
||||||
|
(sign_extend:DI (mem:HI (plus:DI (unspec:DI [(match_operand:SI 2 "register_operand" "r")
|
||||||
|
(match_operand 3 "tld_symbolic_operand" "")]
|
||||||
|
UNSPEC_TLSLDO)
|
||||||
|
(match_operand:DI 1 "register_operand" "r")))))]
|
||||||
|
"TARGET_TLS && TARGET_ARCH64"
|
||||||
|
"ldsh\t[%1 + %2], %0, %%tldo_add(%3)"
|
||||||
|
[(set_attr "type" "sload")
|
||||||
|
(set_attr "us3load_type" "3cycle")])
|
||||||
|
|
||||||
|
(define_insn "*tldo_lduw_sp32"
|
||||||
|
[(set (match_operand:SI 0 "register_operand" "=r")
|
||||||
|
(mem:SI (plus:SI (unspec:SI [(match_operand:SI 2 "register_operand" "r")
|
||||||
|
(match_operand 3 "tld_symbolic_operand" "")]
|
||||||
|
UNSPEC_TLSLDO)
|
||||||
|
(match_operand:SI 1 "register_operand" "r"))))]
|
||||||
|
"TARGET_TLS && TARGET_ARCH32"
|
||||||
|
"ld\t[%1 + %2], %0, %%tldo_add(%3)"
|
||||||
|
[(set_attr "type" "load")])
|
||||||
|
|
||||||
|
(define_insn "*tldo_lduw_sp64"
|
||||||
|
[(set (match_operand:SI 0 "register_operand" "=r")
|
||||||
|
(mem:SI (plus:DI (unspec:DI [(match_operand:SI 2 "register_operand" "r")
|
||||||
|
(match_operand 3 "tld_symbolic_operand" "")]
|
||||||
|
UNSPEC_TLSLDO)
|
||||||
|
(match_operand:DI 1 "register_operand" "r"))))]
|
||||||
|
"TARGET_TLS && TARGET_ARCH64"
|
||||||
|
"lduw\t[%1 + %2], %0, %%tldo_add(%3)"
|
||||||
|
[(set_attr "type" "load")])
|
||||||
|
|
||||||
|
(define_insn "*tldo_lduw1_sp64"
|
||||||
|
[(set (match_operand:DI 0 "register_operand" "=r")
|
||||||
|
(zero_extend:DI (mem:SI (plus:DI (unspec:DI [(match_operand:SI 2 "register_operand" "r")
|
||||||
|
(match_operand 3 "tld_symbolic_operand" "")]
|
||||||
|
UNSPEC_TLSLDO)
|
||||||
|
(match_operand:DI 1 "register_operand" "r")))))]
|
||||||
|
"TARGET_TLS && TARGET_ARCH64"
|
||||||
|
"lduw\t[%1 + %2], %0, %%tldo_add(%3)"
|
||||||
|
[(set_attr "type" "load")])
|
||||||
|
|
||||||
|
(define_insn "*tldo_ldsw1_sp64"
|
||||||
|
[(set (match_operand:DI 0 "register_operand" "=r")
|
||||||
|
(sign_extend:DI (mem:SI (plus:DI (unspec:DI [(match_operand:SI 2 "register_operand" "r")
|
||||||
|
(match_operand 3 "tld_symbolic_operand" "")]
|
||||||
|
UNSPEC_TLSLDO)
|
||||||
|
(match_operand:DI 1 "register_operand" "r")))))]
|
||||||
|
"TARGET_TLS && TARGET_ARCH64"
|
||||||
|
"ldsw\t[%1 + %2], %0, %%tldo_add(%3)"
|
||||||
|
[(set_attr "type" "sload")
|
||||||
|
(set_attr "us3load_type" "3cycle")])
|
||||||
|
|
||||||
|
(define_insn "*tldo_ldx_sp64"
|
||||||
|
[(set (match_operand:DI 0 "register_operand" "=r")
|
||||||
|
(mem:DI (plus:DI (unspec:DI [(match_operand:SI 2 "register_operand" "r")
|
||||||
|
(match_operand 3 "tld_symbolic_operand" "")]
|
||||||
|
UNSPEC_TLSLDO)
|
||||||
|
(match_operand:DI 1 "register_operand" "r"))))]
|
||||||
|
"TARGET_TLS && TARGET_ARCH64"
|
||||||
|
"ldx\t[%1 + %2], %0, %%tldo_add(%3)"
|
||||||
|
[(set_attr "type" "load")])
|
||||||
|
|
||||||
|
(define_insn "*tldo_stb_sp32"
|
||||||
|
[(set (mem:QI (plus:SI (unspec:SI [(match_operand:SI 2 "register_operand" "r")
|
||||||
|
(match_operand 3 "tld_symbolic_operand" "")]
|
||||||
|
UNSPEC_TLSLDO)
|
||||||
|
(match_operand:SI 1 "register_operand" "r")))
|
||||||
|
(match_operand:QI 0 "register_operand" "=r"))]
|
||||||
|
"TARGET_TLS && TARGET_ARCH32"
|
||||||
|
"stb\t%0, [%1 + %2], %%tldo_add(%3)"
|
||||||
|
[(set_attr "type" "store")])
|
||||||
|
|
||||||
|
(define_insn "*tldo_stb_sp64"
|
||||||
|
[(set (mem:QI (plus:DI (unspec:DI [(match_operand:SI 2 "register_operand" "r")
|
||||||
|
(match_operand 3 "tld_symbolic_operand" "")]
|
||||||
|
UNSPEC_TLSLDO)
|
||||||
|
(match_operand:DI 1 "register_operand" "r")))
|
||||||
|
(match_operand:QI 0 "register_operand" "=r"))]
|
||||||
|
"TARGET_TLS && TARGET_ARCH64"
|
||||||
|
"stb\t%0, [%1 + %2], %%tldo_add(%3)"
|
||||||
|
[(set_attr "type" "store")])
|
||||||
|
|
||||||
|
(define_insn "*tldo_sth_sp32"
|
||||||
|
[(set (mem:HI (plus:SI (unspec:SI [(match_operand:SI 2 "register_operand" "r")
|
||||||
|
(match_operand 3 "tld_symbolic_operand" "")]
|
||||||
|
UNSPEC_TLSLDO)
|
||||||
|
(match_operand:SI 1 "register_operand" "r")))
|
||||||
|
(match_operand:HI 0 "register_operand" "=r"))]
|
||||||
|
"TARGET_TLS && TARGET_ARCH32"
|
||||||
|
"sth\t%0, [%1 + %2], %%tldo_add(%3)"
|
||||||
|
[(set_attr "type" "store")])
|
||||||
|
|
||||||
|
(define_insn "*tldo_sth_sp64"
|
||||||
|
[(set (mem:HI (plus:DI (unspec:DI [(match_operand:SI 2 "register_operand" "r")
|
||||||
|
(match_operand 3 "tld_symbolic_operand" "")]
|
||||||
|
UNSPEC_TLSLDO)
|
||||||
|
(match_operand:DI 1 "register_operand" "r")))
|
||||||
|
(match_operand:HI 0 "register_operand" "=r"))]
|
||||||
|
"TARGET_TLS && TARGET_ARCH64"
|
||||||
|
"sth\t%0, [%1 + %2], %%tldo_add(%3)"
|
||||||
|
[(set_attr "type" "store")])
|
||||||
|
|
||||||
|
(define_insn "*tldo_stw_sp32"
|
||||||
|
[(set (mem:SI (plus:SI (unspec:SI [(match_operand:SI 2 "register_operand" "r")
|
||||||
|
(match_operand 3 "tld_symbolic_operand" "")]
|
||||||
|
UNSPEC_TLSLDO)
|
||||||
|
(match_operand:SI 1 "register_operand" "r")))
|
||||||
|
(match_operand:SI 0 "register_operand" "=r"))]
|
||||||
|
"TARGET_TLS && TARGET_ARCH32"
|
||||||
|
"st\t%0, [%1 + %2], %%tldo_add(%3)"
|
||||||
|
[(set_attr "type" "store")])
|
||||||
|
|
||||||
|
(define_insn "*tldo_stw_sp64"
|
||||||
|
[(set (mem:SI (plus:DI (unspec:DI [(match_operand:SI 2 "register_operand" "r")
|
||||||
|
(match_operand 3 "tld_symbolic_operand" "")]
|
||||||
|
UNSPEC_TLSLDO)
|
||||||
|
(match_operand:DI 1 "register_operand" "r")))
|
||||||
|
(match_operand:SI 0 "register_operand" "=r"))]
|
||||||
|
"TARGET_TLS && TARGET_ARCH64"
|
||||||
|
"stw\t%0, [%1 + %2], %%tldo_add(%3)"
|
||||||
|
[(set_attr "type" "store")])
|
||||||
|
|
||||||
|
(define_insn "*tldo_stx_sp64"
|
||||||
|
[(set (mem:DI (plus:DI (unspec:DI [(match_operand:SI 2 "register_operand" "r")
|
||||||
|
(match_operand 3 "tld_symbolic_operand" "")]
|
||||||
|
UNSPEC_TLSLDO)
|
||||||
|
(match_operand:DI 1 "register_operand" "r")))
|
||||||
|
(match_operand:DI 0 "register_operand" "=r"))]
|
||||||
|
"TARGET_TLS && TARGET_ARCH64"
|
||||||
|
"stx\t%0, [%1 + %2], %%tldo_add(%3)"
|
||||||
|
[(set_attr "type" "store")])
|
||||||
|
|
|
@ -6661,6 +6661,33 @@ foo: .long 25
|
||||||
tls_first_minor=14
|
tls_first_minor=14
|
||||||
tls_as_opt="-m64 -Aesame"
|
tls_as_opt="-m64 -Aesame"
|
||||||
;;
|
;;
|
||||||
|
sparc*-*-*)
|
||||||
|
conftest_s='
|
||||||
|
.section ".tdata","awT",@progbits
|
||||||
|
foo: .long 25
|
||||||
|
.text
|
||||||
|
sethi %tgd_hi22(foo), %o0
|
||||||
|
add %o0, %tgd_lo10(foo), %o1
|
||||||
|
add %l7, %o1, %o0, %tgd_add(foo)
|
||||||
|
call __tls_get_addr, %tgd_call(foo)
|
||||||
|
sethi %tldm_hi22(foo), %l1
|
||||||
|
add %l1, %tldm_lo10(foo), %l2
|
||||||
|
add %l7, %l2, %o0, %tldm_add(foo)
|
||||||
|
call __tls_get_addr, %tldm_call(foo)
|
||||||
|
sethi %tldo_hix22(foo), %l3
|
||||||
|
xor %l3, %tldo_lox10(foo), %l4
|
||||||
|
add %o0, %l4, %l5, %tldo_add(foo)
|
||||||
|
sethi %tie_hi22(foo), %o3
|
||||||
|
add %o3, %tie_lo10(foo), %o3
|
||||||
|
ld [%l7 + %o3], %o2, %tie_ld(foo)
|
||||||
|
add %g7, %o2, %o4, %tie_add(foo)
|
||||||
|
sethi %tle_hix22(foo), %l1
|
||||||
|
xor %l1, %tle_lox10(foo), %o5
|
||||||
|
ld [%g7 + %o5], %o1'
|
||||||
|
tls_first_major=2
|
||||||
|
tls_first_minor=14
|
||||||
|
tls_as_opt=-32
|
||||||
|
;;
|
||||||
esac
|
esac
|
||||||
if test -z "$tls_first_major"; then
|
if test -z "$tls_first_major"; then
|
||||||
: # If we don't have a check, assume no support.
|
: # If we don't have a check, assume no support.
|
||||||
|
|
|
@ -2000,7 +2000,6 @@ foo: .long 25
|
||||||
tls_first_minor=13
|
tls_first_minor=13
|
||||||
;;
|
;;
|
||||||
i[34567]86-*-*)
|
i[34567]86-*-*)
|
||||||
changequote([,])dnl
|
|
||||||
conftest_s='
|
conftest_s='
|
||||||
.section ".tdata","awT",@progbits
|
.section ".tdata","awT",@progbits
|
||||||
foo: .long 25
|
foo: .long 25
|
||||||
|
@ -2147,6 +2146,34 @@ foo: .long 25
|
||||||
tls_first_minor=14
|
tls_first_minor=14
|
||||||
tls_as_opt="-m64 -Aesame"
|
tls_as_opt="-m64 -Aesame"
|
||||||
;;
|
;;
|
||||||
|
sparc*-*-*)
|
||||||
|
conftest_s='
|
||||||
|
.section ".tdata","awT",@progbits
|
||||||
|
foo: .long 25
|
||||||
|
.text
|
||||||
|
sethi %tgd_hi22(foo), %o0
|
||||||
|
add %o0, %tgd_lo10(foo), %o1
|
||||||
|
add %l7, %o1, %o0, %tgd_add(foo)
|
||||||
|
call __tls_get_addr, %tgd_call(foo)
|
||||||
|
sethi %tldm_hi22(foo), %l1
|
||||||
|
add %l1, %tldm_lo10(foo), %l2
|
||||||
|
add %l7, %l2, %o0, %tldm_add(foo)
|
||||||
|
call __tls_get_addr, %tldm_call(foo)
|
||||||
|
sethi %tldo_hix22(foo), %l3
|
||||||
|
xor %l3, %tldo_lox10(foo), %l4
|
||||||
|
add %o0, %l4, %l5, %tldo_add(foo)
|
||||||
|
sethi %tie_hi22(foo), %o3
|
||||||
|
add %o3, %tie_lo10(foo), %o3
|
||||||
|
ld [%l7 + %o3], %o2, %tie_ld(foo)
|
||||||
|
add %g7, %o2, %o4, %tie_add(foo)
|
||||||
|
sethi %tle_hix22(foo), %l1
|
||||||
|
xor %l1, %tle_lox10(foo), %o5
|
||||||
|
ld [%g7 + %o5], %o1'
|
||||||
|
tls_first_major=2
|
||||||
|
tls_first_minor=14
|
||||||
|
tls_as_opt=-32
|
||||||
|
;;
|
||||||
|
changequote([,])dnl
|
||||||
esac
|
esac
|
||||||
if test -z "$tls_first_major"; then
|
if test -z "$tls_first_major"; then
|
||||||
: # If we don't have a check, assume no support.
|
: # If we don't have a check, assume no support.
|
||||||
|
|
Loading…
Reference in New Issue