Commit d3585b76 by Daniel Jacobowitz Committed by Daniel Jacobowitz

configure.ac: Add test for ARM TLS support.

	* configure.ac: Add test for ARM TLS support.
	* configure: Regenerated.
	* config/arm/arm-protos.h (legitimize_tls_address)
	(arm_tls_referenced_p, tls_mentioned_p)
	(arm_output_addr_const_extra): New prototypes.
	(thumb_legitimize_pic_address): Delete.
	* config/arm/arm.c: Include "gt-arm.h".
	(enum tls_reloc): New.
	(arm_cannot_copy_insn_p, arm_tls_symbol_p, load_tls_operand)
	(pcrel_constant_p, get_tls_get_addr, arm_load_tp)
	(arm_call_tls_get_addr, legitimize_tls_address)
	(arm_tls_referenced_p, arm_tls_operand_p_1, tls_mentioned_p)
	(arm_init_tls_builtins, arm_emit_tls_decoration)
	(arm_output_addr_const_extra): New functions.
	(TARGET_CANNOT_COPY_INSN_P, TARGET_CANNOT_FORCE_CONST_MEM)
	(TARGET_HAVE_TLS): Define.
	(target_thread_pointer): New.
	(arm_override_options): Handle -mtp=.
	(legitimize_pic_address): Ignore UNSPECs.
	(arm_legitimate_address_p, thumb_legitimate_address_p): Handle PC
	relative symbols.
	(arm_legitimize_address, thumb_legitimize_address): Handle TLS.
	(tls_get_addr_libfunc): New variable.
	(symbol_mentioned_p, label_mentioned_p): Ignore UNSPEC_TLS.
	(arm_init_builtins): Call arm_init_tls_builtins.
	(arm_expand_builtin): Handle ARM_BUILTIN_THREAD_POINTER.
	(arm_encode_section_info): Call default_encode_section_info.
	* config/arm/arm.h (TARGET_HARD_TP, TARGET_SOFT_TP): Define.
	(enum arm_tp_type): New.
	(target_thread_pointer): Add declaration.
	(LEGITIMATE_CONSTANT_P): Handle TLS.
	(LEGITIMATE_PIC_OPERAND_P): Handle TLS.
	(OUTPUT_ADDR_CONST_EXTRA): Call arm_output_addr_const_extra.
	(enum arm_builtins): Add ARM_BUILTIN_THREAD_POINTER.
	* config/arm/arm.md: Add UNSPEC_TLS.
	(movsi): Handle TLS.
	(pic_add_dot_plus_four, pic_add_dot_plus_eight): Allow for
	non-PIC.
	(tls_load_dot_plus_eight): New insn and a peephole to create it.
	(load_tp_hard, load_tp_soft): New insns.
	* arm.opt: Add -mtp=.
	* doc/invoke.texi (ARM Options): Document -mtp.

Co-Authored-By: Paul Brook <paul@codesourcery.com>
Co-Authored-By: Phil Blundell <pb@reciva.com>

From-SVN: r106489
parent 802b3461
2005-11-04 Daniel Jacobowitz <dan@codesourcery.com> 2005-11-04 Daniel Jacobowitz <dan@codesourcery.com>
Paul Brook <paul@codesourcery.com>
Phil Blundell <pb@reciva.com>
* configure.ac: Add test for ARM TLS support.
* configure: Regenerated.
* config/arm/arm-protos.h (legitimize_tls_address)
(arm_tls_referenced_p, tls_mentioned_p)
(arm_output_addr_const_extra): New prototypes.
(thumb_legitimize_pic_address): Delete.
* config/arm/arm.c: Include "gt-arm.h".
(enum tls_reloc): New.
(arm_cannot_copy_insn_p, arm_tls_symbol_p, load_tls_operand)
(pcrel_constant_p, get_tls_get_addr, arm_load_tp)
(arm_call_tls_get_addr, legitimize_tls_address)
(arm_tls_referenced_p, arm_tls_operand_p_1, tls_mentioned_p)
(arm_init_tls_builtins, arm_emit_tls_decoration)
(arm_output_addr_const_extra): New functions.
(TARGET_CANNOT_COPY_INSN_P, TARGET_CANNOT_FORCE_CONST_MEM)
(TARGET_HAVE_TLS): Define.
(target_thread_pointer): New.
(arm_override_options): Handle -mtp=.
(legitimize_pic_address): Ignore UNSPECs.
(arm_legitimate_address_p, thumb_legitimate_address_p): Handle PC
relative symbols.
(arm_legitimize_address, thumb_legitimize_address): Handle TLS.
(tls_get_addr_libfunc): New variable.
(symbol_mentioned_p, label_mentioned_p): Ignore UNSPEC_TLS.
(arm_init_builtins): Call arm_init_tls_builtins.
(arm_expand_builtin): Handle ARM_BUILTIN_THREAD_POINTER.
(arm_encode_section_info): Call default_encode_section_info.
* config/arm/arm.h (TARGET_HARD_TP, TARGET_SOFT_TP): Define.
(enum arm_tp_type): New.
(target_thread_pointer): Add declaration.
(LEGITIMATE_CONSTANT_P): Handle TLS.
(LEGITIMATE_PIC_OPERAND_P): Handle TLS.
(OUTPUT_ADDR_CONST_EXTRA): Call arm_output_addr_const_extra.
(enum arm_builtins): Add ARM_BUILTIN_THREAD_POINTER.
* config/arm/arm.md: Add UNSPEC_TLS.
(movsi): Handle TLS.
(pic_add_dot_plus_four, pic_add_dot_plus_eight): Allow for
non-PIC.
(tls_load_dot_plus_eight): New insn and a peephole to create it.
(load_tp_hard, load_tp_soft): New insns.
* arm.opt: Add -mtp=.
* doc/invoke.texi (ARM Options): Document -mtp.
2005-11-04 Daniel Jacobowitz <dan@codesourcery.com>
* config/arm/lib1funcs.asm: Don't include "libunwind.S". * config/arm/lib1funcs.asm: Don't include "libunwind.S".
* config/arm/libunwind.S: Include "lib1funcs.asm". * config/arm/libunwind.S: Include "lib1funcs.asm".
......
...@@ -56,6 +56,7 @@ extern RTX_CODE arm_canonicalize_comparison (RTX_CODE, enum machine_mode, ...@@ -56,6 +56,7 @@ extern RTX_CODE arm_canonicalize_comparison (RTX_CODE, enum machine_mode,
rtx *); rtx *);
extern int legitimate_pic_operand_p (rtx); extern int legitimate_pic_operand_p (rtx);
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, rtx);
extern int arm_legitimate_address_p (enum machine_mode, rtx, RTX_CODE, int); extern int arm_legitimate_address_p (enum machine_mode, rtx, RTX_CODE, int);
extern int thumb_legitimate_address_p (enum machine_mode, rtx, int); extern int thumb_legitimate_address_p (enum machine_mode, rtx, int);
extern int thumb_legitimate_offset_p (enum machine_mode, HOST_WIDE_INT); extern int thumb_legitimate_offset_p (enum machine_mode, HOST_WIDE_INT);
...@@ -66,6 +67,7 @@ extern rtx thumb_legitimize_reload_address (rtx *, enum machine_mode, int, int, ...@@ -66,6 +67,7 @@ extern rtx thumb_legitimize_reload_address (rtx *, enum machine_mode, int, int,
extern int arm_const_double_rtx (rtx); extern int arm_const_double_rtx (rtx);
extern int neg_const_double_rtx_ok_for_fpa (rtx); extern int neg_const_double_rtx_ok_for_fpa (rtx);
extern enum reg_class vfp_secondary_reload_class (enum machine_mode, rtx); extern enum reg_class vfp_secondary_reload_class (enum machine_mode, rtx);
extern bool arm_tls_referenced_p (rtx);
extern int cirrus_memory_offset (rtx); extern int cirrus_memory_offset (rtx);
extern int arm_coproc_mem_operand (rtx, bool); extern int arm_coproc_mem_operand (rtx, bool);
...@@ -74,6 +76,7 @@ extern int arm_no_early_alu_shift_dep (rtx, rtx); ...@@ -74,6 +76,7 @@ extern int arm_no_early_alu_shift_dep (rtx, rtx);
extern int arm_no_early_alu_shift_value_dep (rtx, rtx); extern int arm_no_early_alu_shift_value_dep (rtx, rtx);
extern int arm_no_early_mul_dep (rtx, rtx); extern int arm_no_early_mul_dep (rtx, rtx);
extern int tls_mentioned_p (rtx);
extern int symbol_mentioned_p (rtx); extern int symbol_mentioned_p (rtx);
extern int label_mentioned_p (rtx); extern int label_mentioned_p (rtx);
extern RTX_CODE minmax_code (rtx); extern RTX_CODE minmax_code (rtx);
...@@ -122,6 +125,8 @@ extern const char *vfp_output_fstmx (rtx *); ...@@ -122,6 +125,8 @@ extern const char *vfp_output_fstmx (rtx *);
extern void arm_set_return_address (rtx, rtx); extern void arm_set_return_address (rtx, rtx);
extern int arm_eliminable_register (rtx); extern int arm_eliminable_register (rtx);
extern bool arm_output_addr_const_extra (FILE *, rtx);
#if defined TREE_CODE #if defined TREE_CODE
extern rtx arm_function_arg (CUMULATIVE_ARGS *, enum machine_mode, tree, int); extern rtx arm_function_arg (CUMULATIVE_ARGS *, enum machine_mode, tree, int);
extern void arm_init_cumulative_args (CUMULATIVE_ARGS *, tree, rtx, tree); extern void arm_init_cumulative_args (CUMULATIVE_ARGS *, tree, rtx, tree);
...@@ -161,7 +166,6 @@ extern const char *thumb_load_double_from_address (rtx *); ...@@ -161,7 +166,6 @@ extern const char *thumb_load_double_from_address (rtx *);
extern const char *thumb_output_move_mem_multiple (int, rtx *); extern const char *thumb_output_move_mem_multiple (int, rtx *);
extern const char *thumb_call_via_reg (rtx); extern const char *thumb_call_via_reg (rtx);
extern void thumb_expand_movmemqi (rtx *); extern void thumb_expand_movmemqi (rtx *);
extern rtx *thumb_legitimize_pic_address (rtx, enum machine_mode, rtx);
extern int thumb_go_if_legitimate_address (enum machine_mode, rtx); extern int thumb_go_if_legitimate_address (enum machine_mode, rtx);
extern rtx arm_return_addr (int, rtx); extern rtx arm_return_addr (int, rtx);
extern void thumb_reload_out_hi (rtx *); extern void thumb_reload_out_hi (rtx *);
......
...@@ -188,6 +188,9 @@ static bool arm_cxx_use_aeabi_atexit (void); ...@@ -188,6 +188,9 @@ static bool arm_cxx_use_aeabi_atexit (void);
static void arm_init_libfuncs (void); static void arm_init_libfuncs (void);
static bool arm_handle_option (size_t, const char *, int); static bool arm_handle_option (size_t, const char *, int);
static unsigned HOST_WIDE_INT arm_shift_truncation_mask (enum machine_mode); static unsigned HOST_WIDE_INT arm_shift_truncation_mask (enum machine_mode);
static bool arm_cannot_copy_insn_p (rtx);
static bool arm_tls_symbol_p (rtx x);
/* Initialize the GCC target structure. */ /* Initialize the GCC target structure. */
#if TARGET_DLLIMPORT_DECL_ATTRIBUTES #if TARGET_DLLIMPORT_DECL_ATTRIBUTES
...@@ -353,6 +356,17 @@ static unsigned HOST_WIDE_INT arm_shift_truncation_mask (enum machine_mode); ...@@ -353,6 +356,17 @@ static unsigned HOST_WIDE_INT arm_shift_truncation_mask (enum machine_mode);
#define TARGET_ARM_EABI_UNWINDER true #define TARGET_ARM_EABI_UNWINDER true
#endif /* TARGET_UNWIND_INFO */ #endif /* TARGET_UNWIND_INFO */
#undef TARGET_CANNOT_COPY_INSN_P
#define TARGET_CANNOT_COPY_INSN_P arm_cannot_copy_insn_p
#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 arm_tls_referenced_p
struct gcc_target targetm = TARGET_INITIALIZER; struct gcc_target targetm = TARGET_INITIALIZER;
/* Obstack for minipool constant handling. */ /* Obstack for minipool constant handling. */
...@@ -390,6 +404,9 @@ enum float_abi_type arm_float_abi; ...@@ -390,6 +404,9 @@ enum float_abi_type arm_float_abi;
/* Which ABI to use. */ /* Which ABI to use. */
enum arm_abi_type arm_abi; enum arm_abi_type arm_abi;
/* Which thread pointer model to use. */
enum arm_tp_type target_thread_pointer = TP_AUTO;
/* Used to parse -mstructure_size_boundary command line option. */ /* Used to parse -mstructure_size_boundary command line option. */
int arm_structure_size_boundary = DEFAULT_STRUCTURE_SIZE_BOUNDARY; int arm_structure_size_boundary = DEFAULT_STRUCTURE_SIZE_BOUNDARY;
...@@ -415,6 +432,7 @@ static int thumb_call_reg_needed; ...@@ -415,6 +432,7 @@ static int thumb_call_reg_needed;
#define FL_VFPV2 (1 << 13) /* Vector Floating Point V2. */ #define FL_VFPV2 (1 << 13) /* Vector Floating Point V2. */
#define FL_WBUF (1 << 14) /* Schedule for write buffer ops. #define FL_WBUF (1 << 14) /* Schedule for write buffer ops.
Note: ARM6 & 7 derivatives only. */ Note: ARM6 & 7 derivatives only. */
#define FL_ARCH6K (1 << 15) /* Architecture rel 6 K extensions. */
#define FL_IWMMXT (1 << 29) /* XScale v2 or "Intel Wireless MMX technology". */ #define FL_IWMMXT (1 << 29) /* XScale v2 or "Intel Wireless MMX technology". */
...@@ -430,9 +448,9 @@ static int thumb_call_reg_needed; ...@@ -430,9 +448,9 @@ static int thumb_call_reg_needed;
#define FL_FOR_ARCH5TEJ FL_FOR_ARCH5TE #define FL_FOR_ARCH5TEJ FL_FOR_ARCH5TE
#define FL_FOR_ARCH6 (FL_FOR_ARCH5TE | FL_ARCH6) #define FL_FOR_ARCH6 (FL_FOR_ARCH5TE | FL_ARCH6)
#define FL_FOR_ARCH6J FL_FOR_ARCH6 #define FL_FOR_ARCH6J FL_FOR_ARCH6
#define FL_FOR_ARCH6K FL_FOR_ARCH6 #define FL_FOR_ARCH6K (FL_FOR_ARCH6 | FL_ARCH6K)
#define FL_FOR_ARCH6Z FL_FOR_ARCH6 #define FL_FOR_ARCH6Z FL_FOR_ARCH6
#define FL_FOR_ARCH6ZK FL_FOR_ARCH6 #define FL_FOR_ARCH6ZK FL_FOR_ARCH6K
/* The bits in this mask specify which /* The bits in this mask specify which
instructions we are allowed to generate. */ instructions we are allowed to generate. */
...@@ -463,6 +481,9 @@ int arm_arch5e = 0; ...@@ -463,6 +481,9 @@ int arm_arch5e = 0;
/* Nonzero if this chip supports the ARM Architecture 6 extensions. */ /* Nonzero if this chip supports the ARM Architecture 6 extensions. */
int arm_arch6 = 0; int arm_arch6 = 0;
/* Nonzero if this chip supports the ARM 6K extensions. */
int arm_arch6k = 0;
/* Nonzero if this chip can benefit from load scheduling. */ /* Nonzero if this chip can benefit from load scheduling. */
int arm_ld_sched = 0; int arm_ld_sched = 0;
...@@ -677,6 +698,16 @@ static const struct abi_name arm_all_abis[] = ...@@ -677,6 +698,16 @@ static const struct abi_name arm_all_abis[] =
{"aapcs-linux", ARM_ABI_AAPCS_LINUX} {"aapcs-linux", ARM_ABI_AAPCS_LINUX}
}; };
/* Supported TLS relocations. */
enum tls_reloc {
TLS_GD32,
TLS_LDM32,
TLS_LDO32,
TLS_IE32,
TLS_LE32
};
/* Return the number of bits set in VALUE. */ /* Return the number of bits set in VALUE. */
static unsigned static unsigned
bit_count (unsigned long value) bit_count (unsigned long value)
...@@ -1065,6 +1096,7 @@ arm_override_options (void) ...@@ -1065,6 +1096,7 @@ arm_override_options (void)
arm_arch5 = (insn_flags & FL_ARCH5) != 0; arm_arch5 = (insn_flags & FL_ARCH5) != 0;
arm_arch5e = (insn_flags & FL_ARCH5E) != 0; arm_arch5e = (insn_flags & FL_ARCH5E) != 0;
arm_arch6 = (insn_flags & FL_ARCH6) != 0; arm_arch6 = (insn_flags & FL_ARCH6) != 0;
arm_arch6k = (insn_flags & FL_ARCH6K) != 0;
arm_arch_xscale = (insn_flags & FL_XSCALE) != 0; arm_arch_xscale = (insn_flags & FL_XSCALE) != 0;
arm_arch_cirrus = (insn_flags & FL_CIRRUS) != 0; arm_arch_cirrus = (insn_flags & FL_CIRRUS) != 0;
...@@ -1194,6 +1226,30 @@ arm_override_options (void) ...@@ -1194,6 +1226,30 @@ arm_override_options (void)
&& (tune_flags & FL_MODE32) == 0) && (tune_flags & FL_MODE32) == 0)
flag_schedule_insns = flag_schedule_insns_after_reload = 0; flag_schedule_insns = flag_schedule_insns_after_reload = 0;
if (target_thread_switch)
{
if (strcmp (target_thread_switch, "soft") == 0)
target_thread_pointer = TP_SOFT;
else if (strcmp (target_thread_switch, "auto") == 0)
target_thread_pointer = TP_AUTO;
else if (strcmp (target_thread_switch, "cp15") == 0)
target_thread_pointer = TP_CP15;
else
error ("invalid thread pointer option: -mtp=%s", target_thread_switch);
}
/* Use the cp15 method if it is available. */
if (target_thread_pointer == TP_AUTO)
{
if (arm_arch6k && !TARGET_THUMB)
target_thread_pointer = TP_CP15;
else
target_thread_pointer = TP_SOFT;
}
if (TARGET_HARD_TP && TARGET_THUMB)
error ("can not use -mtp=cp15 with -mthumb");
/* Override the default structure alignment for AAPCS ABI. */ /* Override the default structure alignment for AAPCS ABI. */
if (TARGET_AAPCS_BASED) if (TARGET_AAPCS_BASED)
arm_structure_size_boundary = 8; arm_structure_size_boundary = 8;
...@@ -3182,6 +3238,10 @@ legitimize_pic_address (rtx orig, enum machine_mode mode, rtx reg) ...@@ -3182,6 +3238,10 @@ legitimize_pic_address (rtx orig, enum machine_mode mode, rtx reg)
&& XEXP (XEXP (orig, 0), 0) == pic_offset_table_rtx) && XEXP (XEXP (orig, 0), 0) == pic_offset_table_rtx)
return orig; return orig;
if (GET_CODE (XEXP (orig, 0)) == UNSPEC
&& XINT (XEXP (orig, 0), 1) == UNSPEC_TLS)
return orig;
if (reg == 0) if (reg == 0)
{ {
gcc_assert (!no_new_pseudos); gcc_assert (!no_new_pseudos);
...@@ -3355,6 +3415,19 @@ arm_address_register_rtx_p (rtx x, int strict_p) ...@@ -3355,6 +3415,19 @@ arm_address_register_rtx_p (rtx x, int strict_p)
|| regno == ARG_POINTER_REGNUM); || regno == ARG_POINTER_REGNUM);
} }
/* Return TRUE if this rtx is the difference of a symbol and a label,
and will reduce to a PC-relative relocation in the object file.
Expressions like this can be left alone when generating PIC, rather
than forced through the GOT. */
static int
pcrel_constant_p (rtx x)
{
if (GET_CODE (x) == MINUS)
return symbol_mentioned_p (XEXP (x, 0)) && label_mentioned_p (XEXP (x, 1));
return FALSE;
}
/* Return nonzero if X is a valid ARM state address operand. */ /* Return nonzero if X is a valid ARM state address operand. */
int int
arm_legitimate_address_p (enum machine_mode mode, rtx x, RTX_CODE outer, arm_legitimate_address_p (enum machine_mode mode, rtx x, RTX_CODE outer,
...@@ -3433,7 +3506,8 @@ arm_legitimate_address_p (enum machine_mode mode, rtx x, RTX_CODE outer, ...@@ -3433,7 +3506,8 @@ arm_legitimate_address_p (enum machine_mode mode, rtx x, RTX_CODE outer,
&& code == SYMBOL_REF && code == SYMBOL_REF
&& CONSTANT_POOL_ADDRESS_P (x) && CONSTANT_POOL_ADDRESS_P (x)
&& ! (flag_pic && ! (flag_pic
&& symbol_mentioned_p (get_pool_constant (x)))) && symbol_mentioned_p (get_pool_constant (x))
&& ! pcrel_constant_p (get_pool_constant (x))))
return 1; return 1;
return 0; return 0;
...@@ -3658,8 +3732,9 @@ thumb_legitimate_address_p (enum machine_mode mode, rtx x, int strict_p) ...@@ -3658,8 +3732,9 @@ thumb_legitimate_address_p (enum machine_mode mode, rtx x, int strict_p)
&& GET_MODE_SIZE (mode) == 4 && GET_MODE_SIZE (mode) == 4
&& GET_CODE (x) == SYMBOL_REF && GET_CODE (x) == SYMBOL_REF
&& CONSTANT_POOL_ADDRESS_P (x) && CONSTANT_POOL_ADDRESS_P (x)
&& !(flag_pic && ! (flag_pic
&& symbol_mentioned_p (get_pool_constant (x)))) && symbol_mentioned_p (get_pool_constant (x))
&& ! pcrel_constant_p (get_pool_constant (x))))
return 1; return 1;
return 0; return 0;
...@@ -3685,11 +3760,163 @@ thumb_legitimate_offset_p (enum machine_mode mode, HOST_WIDE_INT val) ...@@ -3685,11 +3760,163 @@ thumb_legitimate_offset_p (enum machine_mode mode, HOST_WIDE_INT val)
} }
} }
/* Build the SYMBOL_REF for __tls_get_addr. */
static GTY(()) rtx tls_get_addr_libfunc;
static rtx
get_tls_get_addr (void)
{
if (!tls_get_addr_libfunc)
tls_get_addr_libfunc = init_one_libfunc ("__tls_get_addr");
return tls_get_addr_libfunc;
}
static rtx
arm_load_tp (rtx target)
{
if (!target)
target = gen_reg_rtx (SImode);
if (TARGET_HARD_TP)
{
/* Can return in any reg. */
emit_insn (gen_load_tp_hard (target));
}
else
{
/* Always returned in r0. Immediately copy the result into a pseudo,
otherwise other uses of r0 (e.g. setting up function arguments) may
clobber the value. */
rtx tmp;
emit_insn (gen_load_tp_soft ());
tmp = gen_rtx_REG (SImode, 0);
emit_move_insn (target, tmp);
}
return target;
}
static rtx
load_tls_operand (rtx x, rtx reg)
{
rtx tmp;
if (reg == NULL_RTX)
reg = gen_reg_rtx (SImode);
tmp = gen_rtx_CONST (SImode, x);
emit_move_insn (reg, tmp);
return reg;
}
static rtx
arm_call_tls_get_addr (rtx x, rtx reg, rtx *valuep, int reloc)
{
rtx insns, label, sum;
start_sequence ();
label = gen_label_rtx ();
sum = gen_rtx_UNSPEC (Pmode,
gen_rtvec (4, x, GEN_INT (reloc),
gen_rtx_LABEL_REF (Pmode, label),
GEN_INT (TARGET_ARM ? 8 : 4)),
UNSPEC_TLS);
reg = load_tls_operand (sum, reg);
if (TARGET_ARM)
emit_insn (gen_pic_add_dot_plus_eight (reg, label));
else
emit_insn (gen_pic_add_dot_plus_four (reg, label));
*valuep = emit_library_call_value (get_tls_get_addr (), NULL_RTX, LCT_PURE, /* LCT_CONST? */
Pmode, 1, reg, Pmode);
insns = get_insns ();
end_sequence ();
return insns;
}
rtx
legitimize_tls_address (rtx x, rtx reg)
{
rtx dest, tp, label, sum, insns, ret, eqv, addend;
unsigned int model = SYMBOL_REF_TLS_MODEL (x);
switch (model)
{
case TLS_MODEL_GLOBAL_DYNAMIC:
insns = arm_call_tls_get_addr (x, reg, &ret, TLS_GD32);
dest = gen_reg_rtx (Pmode);
emit_libcall_block (insns, dest, ret, x);
return dest;
case TLS_MODEL_LOCAL_DYNAMIC:
insns = arm_call_tls_get_addr (x, reg, &ret, TLS_LDM32);
/* Attach a unique REG_EQUIV, to allow the RTL optimizers to
share the LDM result with other LD model accesses. */
eqv = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, const1_rtx),
UNSPEC_TLS);
dest = gen_reg_rtx (Pmode);
emit_libcall_block (insns, dest, ret, x);
/* Load the addend. */
addend = gen_rtx_UNSPEC (Pmode, gen_rtvec (2, x, GEN_INT (TLS_LDO32)),
UNSPEC_TLS);
addend = force_reg (SImode, gen_rtx_CONST (SImode, addend));
return gen_rtx_PLUS (Pmode, dest, addend);
case TLS_MODEL_INITIAL_EXEC:
label = gen_label_rtx ();
sum = gen_rtx_UNSPEC (Pmode,
gen_rtvec (4, x, GEN_INT (TLS_IE32),
gen_rtx_LABEL_REF (Pmode, label),
GEN_INT (TARGET_ARM ? 8 : 4)),
UNSPEC_TLS);
reg = load_tls_operand (sum, reg);
if (TARGET_ARM)
emit_insn (gen_tls_load_dot_plus_eight (reg, reg, label));
else
{
emit_insn (gen_pic_add_dot_plus_four (reg, label));
emit_move_insn (reg, gen_const_mem (SImode, reg));
}
tp = arm_load_tp (NULL_RTX);
return gen_rtx_PLUS (Pmode, tp, reg);
case TLS_MODEL_LOCAL_EXEC:
tp = arm_load_tp (NULL_RTX);
reg = gen_rtx_UNSPEC (Pmode,
gen_rtvec (2, x, GEN_INT (TLS_LE32)),
UNSPEC_TLS);
reg = force_reg (SImode, gen_rtx_CONST (SImode, reg));
return gen_rtx_PLUS (Pmode, tp, reg);
default:
abort ();
}
}
/* Try machine-dependent ways of modifying an illegitimate address /* Try machine-dependent ways of modifying an illegitimate address
to be legitimate. If we find one, return the new, valid address. */ to be legitimate. If we find one, return the new, valid address. */
rtx rtx
arm_legitimize_address (rtx x, rtx orig_x, enum machine_mode mode) arm_legitimize_address (rtx x, rtx orig_x, enum machine_mode mode)
{ {
if (arm_tls_symbol_p (x))
return legitimize_tls_address (x, NULL_RTX);
if (GET_CODE (x) == PLUS) if (GET_CODE (x) == PLUS)
{ {
rtx xop0 = XEXP (x, 0); rtx xop0 = XEXP (x, 0);
...@@ -3803,6 +4030,9 @@ arm_legitimize_address (rtx x, rtx orig_x, enum machine_mode mode) ...@@ -3803,6 +4030,9 @@ arm_legitimize_address (rtx x, rtx orig_x, enum machine_mode mode)
rtx rtx
thumb_legitimize_address (rtx x, rtx orig_x, enum machine_mode mode) thumb_legitimize_address (rtx x, rtx orig_x, enum machine_mode mode)
{ {
if (arm_tls_symbol_p (x))
return legitimize_tls_address (x, NULL_RTX);
if (GET_CODE (x) == PLUS if (GET_CODE (x) == PLUS
&& GET_CODE (XEXP (x, 1)) == CONST_INT && GET_CODE (XEXP (x, 1)) == CONST_INT
&& (INTVAL (XEXP (x, 1)) >= 32 * GET_MODE_SIZE (mode) && (INTVAL (XEXP (x, 1)) >= 32 * GET_MODE_SIZE (mode)
...@@ -3908,6 +4138,50 @@ thumb_legitimize_reload_address (rtx *x_p, ...@@ -3908,6 +4138,50 @@ thumb_legitimize_reload_address (rtx *x_p,
return NULL; return NULL;
} }
/* Test for various thread-local symbols. */
/* Return TRUE if X is a thread-local symbol. */
static bool
arm_tls_symbol_p (rtx x)
{
if (! TARGET_HAVE_TLS)
return false;
if (GET_CODE (x) != SYMBOL_REF)
return false;
return SYMBOL_REF_TLS_MODEL (x) != 0;
}
/* Helper for arm_tls_referenced_p. */
static int
arm_tls_operand_p_1 (rtx *x, void *data ATTRIBUTE_UNUSED)
{
if (GET_CODE (*x) == SYMBOL_REF)
return SYMBOL_REF_TLS_MODEL (*x) != 0;
/* Don't recurse into UNSPEC_TLS looking for TLS symbols; these are
TLS offsets, not real symbol references. */
if (GET_CODE (*x) == UNSPEC
&& XINT (*x, 1) == UNSPEC_TLS)
return -1;
return 0;
}
/* Return TRUE if X contains any TLS symbol references. */
bool
arm_tls_referenced_p (rtx x)
{
if (! TARGET_HAVE_TLS)
return false;
return for_each_rtx (&x, arm_tls_operand_p_1, NULL);
}
#define REG_OR_SUBREG_REG(X) \ #define REG_OR_SUBREG_REG(X) \
(GET_CODE (X) == REG \ (GET_CODE (X) == REG \
|| (GET_CODE (X) == SUBREG && GET_CODE (SUBREG_REG (X)) == REG)) || (GET_CODE (X) == SUBREG && GET_CODE (SUBREG_REG (X)) == REG))
...@@ -5278,6 +5552,11 @@ symbol_mentioned_p (rtx x) ...@@ -5278,6 +5552,11 @@ symbol_mentioned_p (rtx x)
if (GET_CODE (x) == SYMBOL_REF) if (GET_CODE (x) == SYMBOL_REF)
return 1; return 1;
/* UNSPEC_TLS entries for a symbol include the SYMBOL_REF, but they
are constant offsets, not symbols. */
if (GET_CODE (x) == UNSPEC && XINT (x, 1) == UNSPEC_TLS)
return 0;
fmt = GET_RTX_FORMAT (GET_CODE (x)); fmt = GET_RTX_FORMAT (GET_CODE (x));
for (i = GET_RTX_LENGTH (GET_CODE (x)) - 1; i >= 0; i--) for (i = GET_RTX_LENGTH (GET_CODE (x)) - 1; i >= 0; i--)
...@@ -5307,6 +5586,11 @@ label_mentioned_p (rtx x) ...@@ -5307,6 +5586,11 @@ label_mentioned_p (rtx x)
if (GET_CODE (x) == LABEL_REF) if (GET_CODE (x) == LABEL_REF)
return 1; return 1;
/* UNSPEC_TLS entries for a symbol include a LABEL_REF for the referencing
instruction, but they are constant offsets, not symbols. */
if (GET_CODE (x) == UNSPEC && XINT (x, 1) == UNSPEC_TLS)
return 0;
fmt = GET_RTX_FORMAT (GET_CODE (x)); fmt = GET_RTX_FORMAT (GET_CODE (x));
for (i = GET_RTX_LENGTH (GET_CODE (x)) - 1; i >= 0; i--) for (i = GET_RTX_LENGTH (GET_CODE (x)) - 1; i >= 0; i--)
{ {
...@@ -5325,6 +5609,48 @@ label_mentioned_p (rtx x) ...@@ -5325,6 +5609,48 @@ label_mentioned_p (rtx x)
return 0; return 0;
} }
int
tls_mentioned_p (rtx x)
{
switch (GET_CODE (x))
{
case CONST:
return tls_mentioned_p (XEXP (x, 0));
case UNSPEC:
if (XINT (x, 1) == UNSPEC_TLS)
return 1;
default:
return 0;
}
}
/* Must not copy a SET whose source operand is PC-relative. */
static bool
arm_cannot_copy_insn_p (rtx insn)
{
rtx pat = PATTERN (insn);
if (GET_CODE (pat) == PARALLEL
&& GET_CODE (XVECEXP (pat, 0, 0)) == SET)
{
rtx rhs = SET_SRC (XVECEXP (pat, 0, 0));
if (GET_CODE (rhs) == UNSPEC
&& XINT (rhs, 1) == UNSPEC_PIC_BASE)
return TRUE;
if (GET_CODE (rhs) == MEM
&& GET_CODE (XEXP (rhs, 0)) == UNSPEC
&& XINT (XEXP (rhs, 0), 1) == UNSPEC_PIC_BASE)
return TRUE;
}
return FALSE;
}
enum rtx_code enum rtx_code
minmax_code (rtx x) minmax_code (rtx x)
{ {
...@@ -5812,7 +6138,6 @@ emit_stm_seq (rtx *operands, int nops) ...@@ -5812,7 +6138,6 @@ emit_stm_seq (rtx *operands, int nops)
return ""; return "";
} }
/* Routines for use in generating RTL. */ /* Routines for use in generating RTL. */
rtx rtx
...@@ -12119,8 +12444,23 @@ arm_init_iwmmxt_builtins (void) ...@@ -12119,8 +12444,23 @@ arm_init_iwmmxt_builtins (void)
} }
static void static void
arm_init_tls_builtins (void)
{
tree ftype;
tree nothrow = tree_cons (get_identifier ("nothrow"), NULL, NULL);
tree const_nothrow = tree_cons (get_identifier ("const"), NULL, nothrow);
ftype = build_function_type (ptr_type_node, void_list_node);
lang_hooks.builtin_function ("__builtin_thread_pointer", ftype,
ARM_BUILTIN_THREAD_POINTER, BUILT_IN_MD,
NULL, const_nothrow);
}
static void
arm_init_builtins (void) arm_init_builtins (void)
{ {
arm_init_tls_builtins ();
if (TARGET_REALLY_IWMMXT) if (TARGET_REALLY_IWMMXT)
arm_init_iwmmxt_builtins (); arm_init_iwmmxt_builtins ();
} }
...@@ -12425,6 +12765,9 @@ arm_expand_builtin (tree exp, ...@@ -12425,6 +12765,9 @@ arm_expand_builtin (tree exp,
emit_insn (gen_iwmmxt_clrdi (target)); emit_insn (gen_iwmmxt_clrdi (target));
return target; return target;
case ARM_BUILTIN_THREAD_POINTER:
return arm_load_tp (target);
default: default:
break; break;
} }
...@@ -14224,6 +14567,8 @@ arm_encode_section_info (tree decl, rtx rtl, int first) ...@@ -14224,6 +14567,8 @@ arm_encode_section_info (tree decl, rtx rtl, int first)
else if (! TREE_PUBLIC (decl)) else if (! TREE_PUBLIC (decl))
arm_encode_call_attribute (decl, SHORT_CALL_FLAG_CHAR); arm_encode_call_attribute (decl, SHORT_CALL_FLAG_CHAR);
} }
default_encode_section_info (decl, rtl, first);
} }
#endif /* !ARM_PE */ #endif /* !ARM_PE */
...@@ -15025,3 +15370,66 @@ arm_output_fn_unwind (FILE * f, bool prologue) ...@@ -15025,3 +15370,66 @@ arm_output_fn_unwind (FILE * f, bool prologue)
else else
fputs ("\t.fnend\n", f); fputs ("\t.fnend\n", f);
} }
static bool
arm_emit_tls_decoration (FILE *fp, rtx x)
{
enum tls_reloc reloc;
rtx val;
val = XVECEXP (x, 0, 0);
reloc = INTVAL (XVECEXP (x, 0, 1));
output_addr_const (fp, val);
switch (reloc)
{
case TLS_GD32:
fputs ("(tlsgd)", fp);
break;
case TLS_LDM32:
fputs ("(tlsldm)", fp);
break;
case TLS_LDO32:
fputs ("(tlsldo)", fp);
break;
case TLS_IE32:
fputs ("(gottpoff)", fp);
break;
case TLS_LE32:
fputs ("(tpoff)", fp);
break;
default:
gcc_unreachable ();
}
switch (reloc)
{
case TLS_GD32:
case TLS_LDM32:
case TLS_IE32:
fputs (" + (. - ", fp);
output_addr_const (fp, XVECEXP (x, 0, 2));
fputs (" - ", fp);
output_addr_const (fp, XVECEXP (x, 0, 3));
fputc (')', fp);
break;
default:
break;
}
return TRUE;
}
bool
arm_output_addr_const_extra (FILE *fp, rtx x)
{
if (GET_CODE (x) == UNSPEC && XINT (x, 1) == UNSPEC_TLS)
return arm_emit_tls_decoration (fp, x);
else if (GET_CODE (x) == CONST_VECTOR)
return arm_emit_vector_const (fp, x);
return FALSE;
}
#include "gt-arm.h"
...@@ -192,6 +192,9 @@ extern GTY(()) rtx aof_pic_label; ...@@ -192,6 +192,9 @@ extern GTY(()) rtx aof_pic_label;
#define TARGET_AAPCS_BASED \ #define TARGET_AAPCS_BASED \
(arm_abi != ARM_ABI_APCS && arm_abi != ARM_ABI_ATPCS) (arm_abi != ARM_ABI_APCS && arm_abi != ARM_ABI_ATPCS)
#define TARGET_HARD_TP (target_thread_pointer == TP_CP15)
#define TARGET_SOFT_TP (target_thread_pointer == TP_SOFT)
/* True iff the full BPABI is being used. If TARGET_BPABI is true, /* True iff the full BPABI is being used. If TARGET_BPABI is true,
then TARGET_AAPCS_BASED must be true -- but the converse does not then TARGET_AAPCS_BASED must be true -- but the converse does not
hold. TARGET_BPABI implies the use of the BPABI runtime library, hold. TARGET_BPABI implies the use of the BPABI runtime library,
...@@ -289,6 +292,15 @@ extern enum arm_abi_type arm_abi; ...@@ -289,6 +292,15 @@ extern enum arm_abi_type arm_abi;
#define ARM_DEFAULT_ABI ARM_ABI_APCS #define ARM_DEFAULT_ABI ARM_ABI_APCS
#endif #endif
/* Which thread pointer access sequence to use. */
enum arm_tp_type {
TP_AUTO,
TP_SOFT,
TP_CP15
};
extern enum arm_tp_type target_thread_pointer;
/* Nonzero if this chip supports the ARM Architecture 3M extensions. */ /* Nonzero if this chip supports the ARM Architecture 3M extensions. */
extern int arm_arch3m; extern int arm_arch3m;
...@@ -1883,7 +1895,9 @@ typedef struct ...@@ -1883,7 +1895,9 @@ typedef struct
|| flag_pic) || flag_pic)
#define LEGITIMATE_CONSTANT_P(X) \ #define LEGITIMATE_CONSTANT_P(X) \
(TARGET_ARM ? ARM_LEGITIMATE_CONSTANT_P (X) : THUMB_LEGITIMATE_CONSTANT_P (X)) (!arm_tls_referenced_p (X) \
&& (TARGET_ARM ? ARM_LEGITIMATE_CONSTANT_P (X) \
: THUMB_LEGITIMATE_CONSTANT_P (X)))
/* Special characters prefixed to function names /* Special characters prefixed to function names
in order to encode attribute like information. in order to encode attribute like information.
...@@ -2199,14 +2213,16 @@ extern int arm_pic_register; ...@@ -2199,14 +2213,16 @@ extern int arm_pic_register;
#define PIC_OFFSET_TABLE_REGNUM arm_pic_register #define PIC_OFFSET_TABLE_REGNUM arm_pic_register
/* We can't directly access anything that contains a symbol, /* We can't directly access anything that contains a symbol,
nor can we indirect via the constant pool. */ nor can we indirect via the constant pool. One exception is
UNSPEC_TLS, which is always PIC. */
#define LEGITIMATE_PIC_OPERAND_P(X) \ #define LEGITIMATE_PIC_OPERAND_P(X) \
(!(symbol_mentioned_p (X) \ (!(symbol_mentioned_p (X) \
|| label_mentioned_p (X) \ || label_mentioned_p (X) \
|| (GET_CODE (X) == SYMBOL_REF \ || (GET_CODE (X) == SYMBOL_REF \
&& CONSTANT_POOL_ADDRESS_P (X) \ && CONSTANT_POOL_ADDRESS_P (X) \
&& (symbol_mentioned_p (get_pool_constant (X)) \ && (symbol_mentioned_p (get_pool_constant (X)) \
|| label_mentioned_p (get_pool_constant (X)))))) || label_mentioned_p (get_pool_constant (X))))) \
|| tls_mentioned_p (X))
/* We need to know when we are making a constant pool; this determines /* We need to know when we are making a constant pool; this determines
whether data needs to be in the GOT or can be referenced via a GOT whether data needs to be in the GOT or can be referenced via a GOT
...@@ -2487,10 +2503,9 @@ extern int making_const_table; ...@@ -2487,10 +2503,9 @@ extern int making_const_table;
else \ else \
THUMB_PRINT_OPERAND_ADDRESS (STREAM, X) THUMB_PRINT_OPERAND_ADDRESS (STREAM, X)
#define OUTPUT_ADDR_CONST_EXTRA(FILE, X, FAIL) \ #define OUTPUT_ADDR_CONST_EXTRA(file, x, fail) \
if (GET_CODE (X) != CONST_VECTOR \ if (arm_output_addr_const_extra (file, x) == FALSE) \
|| ! arm_emit_vector_const (FILE, X)) \ goto fail
goto FAIL;
/* A C expression whose value is RTL representing the value of the return /* A C expression whose value is RTL representing the value of the return
address for the frame COUNT steps up from the current frame. */ address for the frame COUNT steps up from the current frame. */
...@@ -2682,6 +2697,8 @@ enum arm_builtins ...@@ -2682,6 +2697,8 @@ enum arm_builtins
ARM_BUILTIN_WUNPCKELUH, ARM_BUILTIN_WUNPCKELUH,
ARM_BUILTIN_WUNPCKELUW, ARM_BUILTIN_WUNPCKELUW,
ARM_BUILTIN_THREAD_POINTER,
ARM_BUILTIN_MAX ARM_BUILTIN_MAX
}; };
#endif /* ! GCC_ARM_H */ #endif /* ! GCC_ARM_H */
...@@ -90,6 +90,7 @@ ...@@ -90,6 +90,7 @@
(UNSPEC_CLRDI 17) ; Used by the intrinsic form of the iWMMXt CLRDI instruction. (UNSPEC_CLRDI 17) ; Used by the intrinsic form of the iWMMXt CLRDI instruction.
(UNSPEC_WMADDS 18) ; Used by the intrinsic form of the iWMMXt WMADDS instruction. (UNSPEC_WMADDS 18) ; Used by the intrinsic form of the iWMMXt WMADDS instruction.
(UNSPEC_WMADDU 19) ; Used by the intrinsic form of the iWMMXt WMADDU instruction. (UNSPEC_WMADDU 19) ; Used by the intrinsic form of the iWMMXt WMADDU instruction.
(UNSPEC_TLS 20) ; A symbol that has been treated properly for TLS usage.
] ]
) )
...@@ -4281,7 +4282,31 @@ ...@@ -4281,7 +4282,31 @@
} }
} }
if (flag_pic /* Recognize the case where operand[1] is a reference to thread-local
data and load its address to a register. */
if (arm_tls_referenced_p (operands[1]))
{
rtx tmp = operands[1];
rtx addend = NULL;
if (GET_CODE (tmp) == CONST && GET_CODE (XEXP (tmp, 0)) == PLUS)
{
addend = XEXP (XEXP (tmp, 0), 1);
tmp = XEXP (XEXP (tmp, 0), 0);
}
gcc_assert (GET_CODE (tmp) == SYMBOL_REF);
gcc_assert (SYMBOL_REF_TLS_MODEL (tmp) != 0);
tmp = legitimize_tls_address (tmp, no_new_pseudos ? operands[0] : 0);
if (addend)
{
tmp = gen_rtx_PLUS (SImode, tmp, addend);
tmp = force_operand (tmp, operands[0]);
}
operands[1] = tmp;
}
else if (flag_pic
&& (CONSTANT_P (operands[1]) && (CONSTANT_P (operands[1])
|| symbol_mentioned_p (operands[1]) || symbol_mentioned_p (operands[1])
|| label_mentioned_p (operands[1]))) || label_mentioned_p (operands[1])))
...@@ -4444,7 +4469,7 @@ ...@@ -4444,7 +4469,7 @@
(const (plus:SI (pc) (const_int 4))))] (const (plus:SI (pc) (const_int 4))))]
UNSPEC_PIC_BASE)) UNSPEC_PIC_BASE))
(use (label_ref (match_operand 1 "" "")))] (use (label_ref (match_operand 1 "" "")))]
"TARGET_THUMB && flag_pic" "TARGET_THUMB"
"* "*
(*targetm.asm_out.internal_label) (asm_out_file, \"L\", (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
CODE_LABEL_NUMBER (operands[1])); CODE_LABEL_NUMBER (operands[1]));
...@@ -4459,7 +4484,7 @@ ...@@ -4459,7 +4484,7 @@
(const (plus:SI (pc) (const_int 8))))] (const (plus:SI (pc) (const_int 8))))]
UNSPEC_PIC_BASE)) UNSPEC_PIC_BASE))
(use (label_ref (match_operand 1 "" "")))] (use (label_ref (match_operand 1 "" "")))]
"TARGET_ARM && flag_pic" "TARGET_ARM"
"* "*
(*targetm.asm_out.internal_label) (asm_out_file, \"L\", (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
CODE_LABEL_NUMBER (operands[1])); CODE_LABEL_NUMBER (operands[1]));
...@@ -4468,6 +4493,41 @@ ...@@ -4468,6 +4493,41 @@
[(set_attr "predicable" "yes")] [(set_attr "predicable" "yes")]
) )
(define_insn "tls_load_dot_plus_eight"
[(set (match_operand:SI 0 "register_operand" "+r")
(mem:SI (unspec:SI [(plus:SI (match_operand:SI 1 "register_operand" "r")
(const (plus:SI (pc) (const_int 8))))]
UNSPEC_PIC_BASE)))
(use (label_ref (match_operand 2 "" "")))]
"TARGET_ARM"
"*
(*targetm.asm_out.internal_label) (asm_out_file, \"L\",
CODE_LABEL_NUMBER (operands[2]));
return \"ldr%?\\t%0, [%|pc, %1]\t\t@ tls_load_dot_plus_eight\";
"
[(set_attr "predicable" "yes")]
)
;; PIC references to local variables can generate pic_add_dot_plus_eight
;; followed by a load. These sequences can be crunched down to
;; tls_load_dot_plus_eight by a peephole.
(define_peephole2
[(parallel [(set (match_operand:SI 0 "register_operand" "")
(unspec:SI [(plus:SI (match_dup 0)
(const (plus:SI (pc) (const_int 8))))]
UNSPEC_PIC_BASE))
(use (label_ref (match_operand 1 "" "")))])
(set (match_operand:SI 2 "register_operand" "") (mem:SI (match_dup 0)))]
"TARGET_ARM && peep2_reg_dead_p (2, operands[0])"
[(parallel [(set (match_operand:SI 2 "register_operand" "+r")
(mem:SI (unspec:SI [(plus:SI (match_dup 0)
(const (plus:SI (pc) (const_int 8))))]
UNSPEC_PIC_BASE)))
(use (label_ref (match_operand 1 "" "")))])]
""
)
(define_expand "builtin_setjmp_receiver" (define_expand "builtin_setjmp_receiver"
[(label_ref (match_operand 0 "" ""))] [(label_ref (match_operand 0 "" ""))]
"flag_pic" "flag_pic"
...@@ -10080,6 +10140,28 @@ ...@@ -10080,6 +10140,28 @@
}" }"
) )
;; TLS support
(define_insn "load_tp_hard"
[(set (match_operand:SI 0 "register_operand" "=r")
(unspec:SI [(const_int 0)] UNSPEC_TLS))]
"TARGET_HARD_TP"
"mrc%?\\tp15, 0, %0, c13, c0, 3\\t@ load_tp_hard"
[(set_attr "predicable" "yes")]
)
;; Doesn't clobber R1-R3. Must use r0 for the first operand.
(define_insn "load_tp_soft"
[(set (reg:SI 0) (unspec:SI [(const_int 0)] UNSPEC_TLS))
(clobber (reg:SI LR_REGNUM))
(clobber (reg:SI IP_REGNUM))
(clobber (reg:CC CC_REGNUM))]
"TARGET_SOFT_TP"
"bl\\t__aeabi_read_tp\\t@ load_tp_soft"
[(set_attr "conds" "clob")]
)
;; Load the FPA co-processor patterns ;; Load the FPA co-processor patterns
(include "fpa.md") (include "fpa.md")
;; Load the Maverick co-processor patterns ;; Load the Maverick co-processor patterns
......
...@@ -134,6 +134,10 @@ mthumb-interwork ...@@ -134,6 +134,10 @@ mthumb-interwork
Target Report Mask(INTERWORK) Target Report Mask(INTERWORK)
Support calls between Thumb and ARM instruction sets Support calls between Thumb and ARM instruction sets
mtp=
Target RejectNegative Joined Var(target_thread_switch)
Specify how to access the thread pointer
mtpcs-frame mtpcs-frame
Target Report Mask(TPCS_FRAME) Target Report Mask(TPCS_FRAME)
Thumb: Generate (non-leaf) stack frames even if not needed Thumb: Generate (non-leaf) stack frames even if not needed
......
...@@ -14523,6 +14523,19 @@ foo: .long 25 ...@@ -14523,6 +14523,19 @@ foo: .long 25
tls_first_minor=15 tls_first_minor=15
tls_as_opt=--fatal-warnings tls_as_opt=--fatal-warnings
;; ;;
arm*-*-*)
conftest_s='
.section ".tdata","awT",%progbits
foo: .long 25
.text
.word foo(gottpoff)
.word foo(tpoff)
.word foo(tlsgd)
.word foo(tlsldm)
.word foo(tlsldo)'
tls_first_major=2
tls_first_minor=17
;;
i[34567]86-*-*) i[34567]86-*-*)
conftest_s=' conftest_s='
.section ".tdata","awT",@progbits .section ".tdata","awT",@progbits
......
# configure.ac for GCC # configure.ac for GCC
# Process this file with autoconf to generate a configuration script. # Process this file with autoconf to generate a configuration script.
# Copyright 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004 # Copyright 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
# Free Software Foundation, Inc. # Free Software Foundation, Inc.
#This file is part of GCC. #This file is part of GCC.
...@@ -2236,6 +2236,19 @@ foo: .long 25 ...@@ -2236,6 +2236,19 @@ foo: .long 25
tls_first_minor=15 tls_first_minor=15
tls_as_opt=--fatal-warnings tls_as_opt=--fatal-warnings
;; ;;
arm*-*-*)
conftest_s='
.section ".tdata","awT",%progbits
foo: .long 25
.text
.word foo(gottpoff)
.word foo(tpoff)
.word foo(tlsgd)
.word foo(tlsldm)
.word foo(tlsldo)'
tls_first_major=2
tls_first_minor=17
;;
i[34567]86-*-*) i[34567]86-*-*)
conftest_s=' conftest_s='
.section ".tdata","awT",@progbits .section ".tdata","awT",@progbits
......
...@@ -412,7 +412,8 @@ Objective-C and Objective-C++ Dialects}. ...@@ -412,7 +412,8 @@ Objective-C and Objective-C++ Dialects}.
-mpoke-function-name @gol -mpoke-function-name @gol
-mthumb -marm @gol -mthumb -marm @gol
-mtpcs-frame -mtpcs-leaf-frame @gol -mtpcs-frame -mtpcs-leaf-frame @gol
-mcaller-super-interworking -mcallee-super-interworking} -mcaller-super-interworking -mcallee-super-interworking @gol
-mtp=@var{name}}
@emph{AVR Options} @emph{AVR Options}
@gccoptlist{-mmcu=@var{mcu} -msize -minit-stack=@var{n} -mno-interrupts @gol @gccoptlist{-mmcu=@var{mcu} -msize -minit-stack=@var{n} -mno-interrupts @gol
...@@ -7456,6 +7457,15 @@ execute correctly regardless of whether the target code has been ...@@ -7456,6 +7457,15 @@ execute correctly regardless of whether the target code has been
compiled for interworking or not. There is a small overhead in the cost compiled for interworking or not. There is a small overhead in the cost
of executing a function pointer if this option is enabled. of executing a function pointer if this option is enabled.
@item -mtp=@var{name}
@opindex mtp
Specify the access model for the thread local storage pointer. The valid
models are @option{soft}, which generates calls to @code{__aeabi_read_tp},
@option{cp15}, which fetches the thread pointer from @code{cp15} directly
(supported in the arm6k architecture), and @option{auto}, which uses the
best available method for the selected processor. The default setting is
@option{auto}.
@end table @end table
@node AVR Options @node AVR Options
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment