Commit 69229b81 by Daniel Jacobowitz Committed by Daniel Jacobowitz

configure.ac: Check for MIPS TLS.

	* configure.ac: Check for MIPS TLS.
	* configure: Regenerated.
	* config/mips/mips-protos.h (enum mips_symbol_type): Add
	SYMBOL_TLS, SYMBOL_TLSGD, SYMBOL_TLSLDM, SYMBOL_DTPREL,
	SYMBOL_GOTTPREL, and SYMBOL_TPREL.
	* config/mips/mips.c (mips_regno_to_class): Handle V1_REG.
	(TARGET_HAVE_TLS, TARGET_CANNOT_FORCE_CONST_MEM): Define.
	(mips_classify_symbol, mips_symbolic_constant_p)
	(mips_symbolic_address_p, mips_symbol_insns): Handle TLS symbols.
	(mips_tls_operand_p, mips_call_tls_get_addr)
	(mips_legitimize_tls_address, mips_cannot_force_const_mem)
	(mips_tls_symbol_ref_1): New functions.
	(mips_legitimize_address, mips_legitimize_const_move): Call
	mips_legitimize_tls_address.
	(override_options): Handle V1_REG and TLS symbols.  Disable TLS
	for MIPS16.
	* config/mips/mips.h (enum reg_class, REG_CLASS_NAMES)
	(REG_CLASS_CONTENTS, GR_REG_CLASS_P): Include V1_REG.
	(mips_char_to_class): Document V1_REG.
	(HAVE_AS_TLS): Provide default.
	* config/mips/mips.md (UNSPEC_TLS_LDM, UNSPEC_TLS_GET_TP): New
	constants.
	(load_got<mode>): Renamed from *load_got<mode>.  Allow when
	!TARGET_ABICALLS.
	(tls_get_tp_<mode>): New instruction.

Co-Authored-By: Joseph Myers <joseph@codesourcery.com>

From-SVN: r96380
parent b095fe2c
2005-03-13 Daniel Jacobowitz <dan@codesourcery.com>
Joseph S. Myers <joseph@codesourcery.com>
* configure.ac: Check for MIPS TLS.
* configure: Regenerated.
* config/mips/mips-protos.h (enum mips_symbol_type): Add
SYMBOL_TLS, SYMBOL_TLSGD, SYMBOL_TLSLDM, SYMBOL_DTPREL,
SYMBOL_GOTTPREL, and SYMBOL_TPREL.
* config/mips/mips.c (mips_regno_to_class): Handle V1_REG.
(TARGET_HAVE_TLS, TARGET_CANNOT_FORCE_CONST_MEM): Define.
(mips_classify_symbol, mips_symbolic_constant_p)
(mips_symbolic_address_p, mips_symbol_insns): Handle TLS symbols.
(mips_tls_operand_p, mips_call_tls_get_addr)
(mips_legitimize_tls_address, mips_cannot_force_const_mem)
(mips_tls_symbol_ref_1): New functions.
(mips_legitimize_address, mips_legitimize_const_move): Call
mips_legitimize_tls_address.
(override_options): Handle V1_REG and TLS symbols. Disable TLS
for MIPS16.
* config/mips/mips.h (enum reg_class, REG_CLASS_NAMES)
(REG_CLASS_CONTENTS, GR_REG_CLASS_P): Include V1_REG.
(mips_char_to_class): Document V1_REG.
(HAVE_AS_TLS): Provide default.
* config/mips/mips.md (UNSPEC_TLS_LDM, UNSPEC_TLS_GET_TP): New
constants.
(load_got<mode>): Renamed from *load_got<mode>. Allow when
!TARGET_ABICALLS.
(tls_get_tp_<mode>): New instruction.
2005-03-13 Daniel Jacobowitz <dan@codesourcery.com>
* configure.ac: Update checks for target tools.
* configure: Regenerated.
......
......@@ -61,6 +61,17 @@ Boston, MA 02111-1307, USA. */
An UNSPEC wrapper around a function's address. It represents the
offset of _gp from the start of the function.
SYMBOL_TLS
A thread-local symbol.
SYMBOL_TLSGD
SYMBOL_TLSLDM
SYMBOL_DTPREL
SYMBOL_GOTTPREL
SYMBOL_TPREL
UNSPEC wrappers around SYMBOL_TLS, corresponding to the
thread-local storage relocation operators.
SYMBOL_64_HIGH
For a 64-bit symbolic address X, this is the value of
(%highest(X) << 16) + %higher(X).
......@@ -82,6 +93,12 @@ enum mips_symbol_type {
SYMBOL_GOTOFF_GLOBAL,
SYMBOL_GOTOFF_CALL,
SYMBOL_GOTOFF_LOADGP,
SYMBOL_TLS,
SYMBOL_TLSGD,
SYMBOL_TLSLDM,
SYMBOL_DTPREL,
SYMBOL_GOTTPREL,
SYMBOL_TPREL,
SYMBOL_64_HIGH,
SYMBOL_64_MID,
SYMBOL_64_LOW
......
......@@ -236,6 +236,7 @@ static bool mips_valid_base_register_p (rtx, enum machine_mode, int);
static bool mips_symbolic_address_p (enum mips_symbol_type, enum machine_mode);
static bool mips_classify_address (struct mips_address_info *, rtx,
enum machine_mode, int);
static bool mips_cannot_force_const_mem (rtx);
static int mips_symbol_insns (enum mips_symbol_type);
static bool mips16_unextended_reference_p (enum machine_mode mode, rtx, rtx);
static rtx mips_force_temporary (rtx, rtx);
......@@ -601,7 +602,7 @@ static const char *mips_hi_relocs[NUM_SYMBOL_TYPES];
/* Map hard register number to register class */
const enum reg_class mips_regno_to_class[] =
{
LEA_REGS, LEA_REGS, M16_NA_REGS, M16_NA_REGS,
LEA_REGS, LEA_REGS, M16_NA_REGS, V1_REG,
M16_REGS, M16_REGS, M16_REGS, M16_REGS,
LEA_REGS, LEA_REGS, LEA_REGS, LEA_REGS,
LEA_REGS, LEA_REGS, LEA_REGS, LEA_REGS,
......@@ -817,6 +818,12 @@ const struct mips_cpu_info mips_cpu_info_table[] = {
#undef TARGET_EXPAND_BUILTIN
#define TARGET_EXPAND_BUILTIN mips_expand_builtin
#undef TARGET_HAVE_TLS
#define TARGET_HAVE_TLS HAVE_AS_TLS
#undef TARGET_CANNOT_FORCE_CONST_MEM
#define TARGET_CANNOT_FORCE_CONST_MEM mips_cannot_force_const_mem
struct gcc_target targetm = TARGET_INITIALIZER;
/* Classify symbol X, which must be a SYMBOL_REF or a LABEL_REF. */
......@@ -835,6 +842,9 @@ mips_classify_symbol (rtx x)
gcc_assert (GET_CODE (x) == SYMBOL_REF);
if (SYMBOL_REF_TLS_MODEL (x))
return SYMBOL_TLS;
if (CONSTANT_POOL_ADDRESS_P (x))
{
if (TARGET_MIPS16)
......@@ -943,7 +953,11 @@ mips_symbolic_constant_p (rtx x, enum mips_symbol_type *symbol_type)
if (UNSPEC_ADDRESS_P (x))
*symbol_type = UNSPEC_ADDRESS_TYPE (x);
else if (GET_CODE (x) == SYMBOL_REF || GET_CODE (x) == LABEL_REF)
*symbol_type = mips_classify_symbol (x);
{
*symbol_type = mips_classify_symbol (x);
if (*symbol_type == SYMBOL_TLS)
return false;
}
else
return false;
......@@ -993,6 +1007,12 @@ mips_symbolic_constant_p (rtx x, enum mips_symbol_type *symbol_type)
case SYMBOL_GOTOFF_GLOBAL:
case SYMBOL_GOTOFF_CALL:
case SYMBOL_GOTOFF_LOADGP:
case SYMBOL_TLSGD:
case SYMBOL_TLSLDM:
case SYMBOL_DTPREL:
case SYMBOL_TPREL:
case SYMBOL_GOTTPREL:
case SYMBOL_TLS:
return false;
}
gcc_unreachable ();
......@@ -1090,6 +1110,14 @@ mips_symbolic_address_p (enum mips_symbol_type symbol_type,
/* The address will have to be loaded from the GOT first. */
return false;
case SYMBOL_TLSGD:
case SYMBOL_TLSLDM:
case SYMBOL_DTPREL:
case SYMBOL_TPREL:
case SYMBOL_GOTTPREL:
case SYMBOL_TLS:
return false;
case SYMBOL_GOTOFF_PAGE:
case SYMBOL_GOTOFF_GLOBAL:
case SYMBOL_GOTOFF_CALL:
......@@ -1154,6 +1182,33 @@ mips_classify_address (struct mips_address_info *info, rtx x,
return false;
}
}
/* Return true if X is a thread-local symbol. */
static bool
mips_tls_operand_p (rtx x)
{
return GET_CODE (x) == SYMBOL_REF && SYMBOL_REF_TLS_MODEL (x) != 0;
}
/* Return true if X can not be forced into a constant pool. */
static int
mips_tls_symbol_ref_1 (rtx *x, void *data ATTRIBUTE_UNUSED)
{
return mips_tls_operand_p (*x);
}
/* Return true if X can not be forced into a constant pool. */
static bool
mips_cannot_force_const_mem (rtx x)
{
if (! TARGET_HAVE_TLS)
return false;
return for_each_rtx (&x, &mips_tls_symbol_ref_1, 0);
}
/* Return the number of instructions needed to load a symbol of the
given type into a register. If valid in an address, the same number
......@@ -1223,8 +1278,17 @@ mips_symbol_insns (enum mips_symbol_type type)
case SYMBOL_64_HIGH:
case SYMBOL_64_MID:
case SYMBOL_64_LOW:
case SYMBOL_TLSGD:
case SYMBOL_TLSLDM:
case SYMBOL_DTPREL:
case SYMBOL_GOTTPREL:
case SYMBOL_TPREL:
/* Check whether the offset is a 16- or 32-bit value. */
return mips_split_p[type] ? 2 : 1;
case SYMBOL_TLS:
/* We don't treat a bare TLS symbol as a constant. */
return 0;
}
gcc_unreachable ();
}
......@@ -1521,6 +1585,114 @@ mips_add_offset (rtx temp, rtx reg, HOST_WIDE_INT offset)
return plus_constant (reg, offset);
}
/* Emit a call to __tls_get_addr. SYM is the TLS symbol we are
referencing, and TYPE is the symbol type to use (either global
dynamic or local dynamic). V0 is an RTX for the return value
location. The entire insn sequence is returned. */
static GTY(()) rtx mips_tls_symbol;
static rtx
mips_call_tls_get_addr (rtx sym, enum mips_symbol_type type, rtx v0)
{
rtx insn, loc, tga, a0;
a0 = gen_rtx_REG (Pmode, GP_ARG_FIRST);
if (!mips_tls_symbol)
mips_tls_symbol = init_one_libfunc ("__tls_get_addr");
loc = mips_unspec_address (sym, type);
start_sequence ();
emit_insn (gen_rtx_SET (Pmode, a0,
gen_rtx_LO_SUM (Pmode, pic_offset_table_rtx, loc)));
tga = gen_rtx_MEM (Pmode, mips_tls_symbol);
insn = emit_call_insn (gen_call_value (v0, tga, const0_rtx, const0_rtx));
CONST_OR_PURE_CALL_P (insn) = 1;
use_reg (&CALL_INSN_FUNCTION_USAGE (insn), v0);
use_reg (&CALL_INSN_FUNCTION_USAGE (insn), a0);
insn = get_insns ();
end_sequence ();
return insn;
}
/* Generate the code to access LOC, a thread local SYMBOL_REF. The
return value will be a valid address and move_operand (either a REG
or a LO_SUM). */
static rtx
mips_legitimize_tls_address (rtx loc)
{
rtx dest, insn, v0, v1, tmp1, tmp2, eqv;
enum tls_model model;
v0 = gen_rtx_REG (Pmode, GP_RETURN);
v1 = gen_rtx_REG (Pmode, GP_RETURN + 1);
model = SYMBOL_REF_TLS_MODEL (loc);
switch (model)
{
case TLS_MODEL_GLOBAL_DYNAMIC:
insn = mips_call_tls_get_addr (loc, SYMBOL_TLSGD, v0);
dest = gen_reg_rtx (Pmode);
emit_libcall_block (insn, dest, v0, loc);
break;
case TLS_MODEL_LOCAL_DYNAMIC:
insn = mips_call_tls_get_addr (loc, SYMBOL_TLSLDM, v0);
tmp1 = gen_reg_rtx (Pmode);
/* 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, const0_rtx),
UNSPEC_TLS_LDM);
emit_libcall_block (insn, tmp1, v0, eqv);
tmp2 = mips_unspec_offset_high (NULL, tmp1, loc, SYMBOL_DTPREL);
dest = gen_rtx_LO_SUM (Pmode, tmp2,
mips_unspec_address (loc, SYMBOL_DTPREL));
break;
case TLS_MODEL_INITIAL_EXEC:
tmp1 = gen_reg_rtx (Pmode);
tmp2 = mips_unspec_address (loc, SYMBOL_GOTTPREL);
if (Pmode == DImode)
{
emit_insn (gen_tls_get_tp_di (v1));
emit_insn (gen_load_gotdi (tmp1, pic_offset_table_rtx, tmp2));
}
else
{
emit_insn (gen_tls_get_tp_si (v1));
emit_insn (gen_load_gotsi (tmp1, pic_offset_table_rtx, tmp2));
}
dest = gen_reg_rtx (Pmode);
emit_insn (gen_add3_insn (dest, tmp1, v1));
break;
case TLS_MODEL_LOCAL_EXEC:
if (Pmode == DImode)
emit_insn (gen_tls_get_tp_di (v1));
else
emit_insn (gen_tls_get_tp_si (v1));
tmp1 = mips_unspec_offset_high (NULL, v1, loc, SYMBOL_TPREL);
dest = gen_rtx_LO_SUM (Pmode, tmp1,
mips_unspec_address (loc, SYMBOL_TPREL));
break;
default:
abort ();
}
return dest;
}
/* This function is used to implement LEGITIMIZE_ADDRESS. If *XLOC can
be legitimized in a way that the generic machinery might not expect,
......@@ -1532,6 +1704,12 @@ mips_legitimize_address (rtx *xloc, enum machine_mode mode)
{
enum mips_symbol_type symbol_type;
if (mips_tls_operand_p (*xloc))
{
*xloc = mips_legitimize_tls_address (*xloc);
return true;
}
/* See if the address can split into a high part and a LO_SUM. */
if (mips_symbolic_constant_p (*xloc, &symbol_type)
&& mips_symbolic_address_p (symbol_type, mode)
......@@ -1707,6 +1885,12 @@ mips_legitimize_const_move (enum machine_mode mode, rtx dest, rtx src)
return;
}
if (mips_tls_operand_p (src))
{
emit_move_insn (dest, mips_legitimize_tls_address (src));
return;
}
/* See if the symbol can be split. For mips16, this is often worse than
forcing it in the constant pool since it needs the single-register form
of addiu or daddiu. */
......@@ -4323,6 +4507,7 @@ override_options (void)
GR_REGS);
mips_char_to_class['e'] = LEA_REGS;
mips_char_to_class['j'] = PIC_FN_ADDR_REG;
mips_char_to_class['v'] = V1_REG;
mips_char_to_class['y'] = GR_REGS;
mips_char_to_class['z'] = ST_REGS;
mips_char_to_class['B'] = COP0_REGS;
......@@ -4511,6 +4696,22 @@ override_options (void)
mips_lo_relocs[SYMBOL_GOTOFF_LOADGP] = "%lo(%neg(%gp_rel(";
}
/* Thread-local relocation operators. */
mips_lo_relocs[SYMBOL_TLSGD] = "%tlsgd(";
mips_lo_relocs[SYMBOL_TLSLDM] = "%tlsldm(";
mips_split_p[SYMBOL_DTPREL] = 1;
mips_hi_relocs[SYMBOL_DTPREL] = "%dtprel_hi(";
mips_lo_relocs[SYMBOL_DTPREL] = "%dtprel_lo(";
mips_lo_relocs[SYMBOL_GOTTPREL] = "%gottprel(";
mips_split_p[SYMBOL_TPREL] = 1;
mips_hi_relocs[SYMBOL_TPREL] = "%tprel_hi(";
mips_lo_relocs[SYMBOL_TPREL] = "%tprel_lo(";
/* We don't have a thread pointer access instruction on MIPS16, or
appropriate TLS relocations. */
if (TARGET_MIPS16)
targetm.have_tls = false;
/* Default to working around R4000 errata only if the processor
was selected explicitly. */
if ((target_flags_explicit & MASK_FIX_R4000) == 0
......
......@@ -1714,6 +1714,7 @@ enum reg_class
T_REG, /* mips16 T register ($24) */
M16_T_REGS, /* mips16 registers plus T register */
PIC_FN_ADDR_REG, /* SVR4 PIC function address register */
V1_REG, /* Register $v1 ($3) used for TLS access. */
LEA_REGS, /* Every GPR except $25 */
GR_REGS, /* integer registers */
FP_REGS, /* floating point registers */
......@@ -1752,6 +1753,7 @@ enum reg_class
"T_REG", \
"M16_T_REGS", \
"PIC_FN_ADDR_REG", \
"V1_REG", \
"LEA_REGS", \
"GR_REGS", \
"FP_REGS", \
......@@ -1793,7 +1795,8 @@ enum reg_class
{ 0x01000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* mips16 T register */ \
{ 0x010300fc, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* mips16 and T regs */ \
{ 0x02000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* SVR4 PIC function address register */ \
{ 0xfdffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* Every other GPR */ \
{ 0x00000008, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* only $v1 */ \
{ 0xfdffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* Every other GPR except $25 */ \
{ 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* integer registers */ \
{ 0x00000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* floating registers*/ \
{ 0x00000000, 0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000000 }, /* hi register */ \
......@@ -1849,6 +1852,7 @@ extern const enum reg_class mips_regno_to_class[];
#define GR_REG_CLASS_P(CLASS) \
((CLASS) == GR_REGS || (CLASS) == M16_REGS || (CLASS) == T_REG \
|| (CLASS) == M16_T_REGS || (CLASS) == M16_NA_REGS \
|| (CLASS) == V1_REG \
|| (CLASS) == PIC_FN_ADDR_REG || (CLASS) == LEA_REGS)
/* This macro is also used later on in the file. */
......@@ -1896,6 +1900,7 @@ extern const enum reg_class mips_regno_to_class[];
'f' Floating point registers
'h' Hi register
'l' Lo register
'v' $v1 only
'x' Multiply/divide registers
'z' FP Status register
'B' Cop0 register
......@@ -3031,3 +3036,7 @@ while (0)
" TEXT_SECTION_ASM_OP);
#endif
#endif
#ifndef HAVE_AS_TLS
#define HAVE_AS_TLS 0
#endif
......@@ -45,6 +45,8 @@
(UNSPEC_LOAD_GOT 24)
(UNSPEC_GP 25)
(UNSPEC_MFHILO 26)
(UNSPEC_TLS_LDM 27)
(UNSPEC_TLS_GET_TP 28)
(UNSPEC_ADDRESS_FIRST 100)
......@@ -3017,12 +3019,12 @@ beq\t%2,%.,1b\;\
;; We could use MEMs, but an unspec gives more optimization
;; opportunities.
(define_insn "*load_got<mode>"
(define_insn "load_got<mode>"
[(set (match_operand:P 0 "register_operand" "=d")
(unspec:P [(match_operand:P 1 "register_operand" "d")
(match_operand:P 2 "immediate_operand" "")]
UNSPEC_LOAD_GOT))]
"TARGET_ABICALLS"
""
"<load>\t%0,%R2(%1)"
[(set_attr "type" "load")
(set_attr "mode" "<MODE>")
......@@ -5295,6 +5297,25 @@ beq\t%2,%.,1b\;\
[(match_dup 0)]
{ operands[0] = mips_rewrite_small_data (operands[0]); })
; Thread-Local Storage
; The TLS base pointer is acessed via "rdhwr $v1, $29". No current
; MIPS architecture defines this register, and no current
; implementation provides it; instead, any OS which supports TLS is
; expected to trap and emulate this instruction. rdhwr is part of the
; MIPS 32r2 specification, but we use it on any architecture because
; we expect it to be emulated. Use .set to force the assembler to
; accept it.
(define_insn "tls_get_tp_<mode>"
[(set (match_operand:P 0 "register_operand" "=v")
(unspec:P [(const_int 0)]
UNSPEC_TLS_GET_TP))]
"HAVE_AS_TLS && !TARGET_MIPS16"
".set\tpush\;.set\tmips32r2\t\;rdhwr\t%0,$29\;.set\tpop"
[(set_attr "type" "unknown")
(set_attr "mode" "<MODE>")])
; The MIPS Paired-Single Floating Point and MIPS-3D Instructions.
(include "mips-ps-3d.md")
......@@ -13670,6 +13670,23 @@ foo: data8 25
tls_first_minor=13
tls_as_opt=--fatal-warnings
;;
mips*-*-*)
conftest_s='
.section .tdata,"awT",@progbits
x:
.word 2
.text
addiu $4, $28, %tlsgd(x)
addiu $4, $28, %tlsldm(x)
lui $4, %dtprel_hi(x)
addiu $4, $4, %dtprel_lo(x)
lw $4, %gottprel(x)($28)
lui $4, %tprel_hi(x)
addiu $4, $4, %tprel_lo(x)'
tls_first_major=2
tls_first_minor=16
tls_as_opt='-32 --fatal-warnings'
;;
powerpc-*-*)
conftest_s='
.section ".tdata","awT",@progbits
......
......@@ -2353,6 +2353,23 @@ foo: data8 25
tls_first_minor=13
tls_as_opt=--fatal-warnings
;;
mips*-*-*)
conftest_s='
.section .tdata,"awT",@progbits
x:
.word 2
.text
addiu $4, $28, %tlsgd(x)
addiu $4, $28, %tlsldm(x)
lui $4, %dtprel_hi(x)
addiu $4, $4, %dtprel_lo(x)
lw $4, %gottprel(x)($28)
lui $4, %tprel_hi(x)
addiu $4, $4, %tprel_lo(x)'
tls_first_major=2
tls_first_minor=16
tls_as_opt='-32 --fatal-warnings'
;;
powerpc-*-*)
conftest_s='
.section ".tdata","awT",@progbits
......
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