Add support for TLS in MicroBlaze
* configure.ac: Add MicroBlaze TLS support detection. * configure: Regenerate. * config/microblaze/microblaze-protos.h: (microblaze_cannot_force_const_mem, microblaze_tls_referenced_p, symbol_mentioned_p, label_mentioned_p): Add prototypes. * config/microblaze/microblaze.c (microblaze_address_type): Add ADDRESS_TLS and tls_reloc address types. (microblaze_address_info): Add tls_reloc. (TARGET_HAVE_TLS): Define. (get_tls_get_addr, microblaze_tls_symbol_p, microblaze_tls_operand_p_1, microblaze_tls_referenced_p, microblaze_cannot_force_const_mem, symbol_mentioned_p, label_mentioned_p, tls_mentioned_p, load_tls_operand, microblaze_call_tls_get_addr, microblaze_legitimize_tls_address): New functions. (microblaze_classify_unspec): Handle UNSPEC_TLS. (get_base_reg): Use microblaze_tls_symbol_p. (microblaze_classify_address): Handle TLS. (microblaze_legitimate_pic_operand): Use symbol_mentioned_p, label_mentioned_p and microblaze_tls_referenced_p. (microblaze_legitimize_address): Handle TLS. (microblaze_address_insns): Handle ADDRESS_TLS. (pic_address_needs_scratch): Handle TLS. (print_operand_address): Handle TLS. (microblaze_expand_prologue): Check TLS_NEEDS_GOT. (microblaze_expand_move): Handle TLS. (microblaze_legitimate_constant_p): Check microblaze_cannot_force_const_mem and microblaze_tls_symbol_p. (TARGET_CANNOT_FORCE_CONST_MEM): Define. * config/microblaze/microblaze.h (TLS_NEEDS_GOT): Define (PIC_OFFSET_TABLE_REGNUM): Set. * config/microblaze/linux.h (TLS_NEEDS_GOT): Define. * config/microblaze/microblaze.md (UNSPEC_TLS): Define. (addsi3, movsi_internal2, movdf_internal): Update constraints * config/microblaze/predicates.md (arith_plus_operand): Define (move_operand): Redefine as move_src_operand, check microblaze_tls_referenced_p. Co-Authored-By: David Holsgrove <david.holsgrove@xilinx.com> From-SVN: r196659
This commit is contained in:
parent
a7137ee176
commit
8cc9a5a584
@ -1,3 +1,41 @@
|
||||
2013-03-14 Edgar E. Iglesias <edgar.iglesias@xilinx.com>
|
||||
David Holsgrove <david.holsgrove@xilinx.com>
|
||||
|
||||
* configure.ac: Add MicroBlaze TLS support detection.
|
||||
* configure: Regenerate.
|
||||
* config/microblaze/microblaze-protos.h: (microblaze_cannot_force_const_mem,
|
||||
microblaze_tls_referenced_p, symbol_mentioned_p, label_mentioned_p):
|
||||
Add prototypes.
|
||||
* config/microblaze/microblaze.c (microblaze_address_type): Add ADDRESS_TLS
|
||||
and tls_reloc address types.
|
||||
(microblaze_address_info): Add tls_reloc.
|
||||
(TARGET_HAVE_TLS): Define.
|
||||
(get_tls_get_addr, microblaze_tls_symbol_p, microblaze_tls_operand_p_1,
|
||||
microblaze_tls_referenced_p, microblaze_cannot_force_const_mem,
|
||||
symbol_mentioned_p, label_mentioned_p, tls_mentioned_p, load_tls_operand,
|
||||
microblaze_call_tls_get_addr, microblaze_legitimize_tls_address): New functions.
|
||||
(microblaze_classify_unspec): Handle UNSPEC_TLS.
|
||||
(get_base_reg): Use microblaze_tls_symbol_p.
|
||||
(microblaze_classify_address): Handle TLS.
|
||||
(microblaze_legitimate_pic_operand): Use symbol_mentioned_p, label_mentioned_p
|
||||
and microblaze_tls_referenced_p.
|
||||
(microblaze_legitimize_address): Handle TLS.
|
||||
(microblaze_address_insns): Handle ADDRESS_TLS.
|
||||
(pic_address_needs_scratch): Handle TLS.
|
||||
(print_operand_address): Handle TLS.
|
||||
(microblaze_expand_prologue): Check TLS_NEEDS_GOT.
|
||||
(microblaze_expand_move): Handle TLS.
|
||||
(microblaze_legitimate_constant_p): Check microblaze_cannot_force_const_mem
|
||||
and microblaze_tls_symbol_p.
|
||||
(TARGET_CANNOT_FORCE_CONST_MEM): Define.
|
||||
* config/microblaze/microblaze.h (TLS_NEEDS_GOT): Define
|
||||
(PIC_OFFSET_TABLE_REGNUM): Set.
|
||||
* config/microblaze/linux.h (TLS_NEEDS_GOT): Define.
|
||||
* config/microblaze/microblaze.md (UNSPEC_TLS): Define.
|
||||
(addsi3, movsi_internal2, movdf_internal): Update constraints
|
||||
* config/microblaze/predicates.md (arith_plus_operand): Define
|
||||
(move_operand): Redefine as move_src_operand, check microblaze_tls_referenced_p.
|
||||
|
||||
2013-03-14 Ian Bolton <ian.bolton@arm.com>
|
||||
|
||||
* config/aarch64/aarch64.md: (*and<mode>3nr_compare0): Use CC_NZ.
|
||||
|
@ -22,6 +22,9 @@
|
||||
#undef TARGET_SUPPORTS_PIC
|
||||
#define TARGET_SUPPORTS_PIC 1
|
||||
|
||||
#undef TLS_NEEDS_GOT
|
||||
#define TLS_NEEDS_GOT 1
|
||||
|
||||
#define DYNAMIC_LINKER "/lib/ld.so.1"
|
||||
#undef SUBTARGET_EXTRA_SPECS
|
||||
#define SUBTARGET_EXTRA_SPECS \
|
||||
|
@ -50,6 +50,10 @@ extern void microblaze_declare_object (FILE *, const char *, const char *,
|
||||
const char *, int);
|
||||
extern void microblaze_asm_output_ident (const char *);
|
||||
extern int microblaze_legitimate_pic_operand (rtx);
|
||||
extern bool microblaze_tls_referenced_p (rtx);
|
||||
extern int symbol_mentioned_p (rtx);
|
||||
extern int label_mentioned_p (rtx);
|
||||
extern bool microblaze_cannot_force_const_mem (enum machine_mode, rtx);
|
||||
#endif /* RTX_CODE */
|
||||
|
||||
/* Declare functions in microblaze-c.c. */
|
||||
|
@ -84,7 +84,8 @@ enum microblaze_address_type
|
||||
ADDRESS_CONST_INT,
|
||||
ADDRESS_SYMBOLIC,
|
||||
ADDRESS_GOTOFF,
|
||||
ADDRESS_PLT
|
||||
ADDRESS_PLT,
|
||||
ADDRESS_TLS
|
||||
};
|
||||
|
||||
/* Classifies symbols
|
||||
@ -98,6 +99,15 @@ enum microblaze_symbol_type
|
||||
SYMBOL_TYPE_GENERAL
|
||||
};
|
||||
|
||||
/* TLS Address Type. */
|
||||
enum tls_reloc {
|
||||
TLS_GD,
|
||||
TLS_LDM,
|
||||
TLS_DTPREL,
|
||||
TLS_IE,
|
||||
TLS_LE
|
||||
};
|
||||
|
||||
/* Classification of a MicroBlaze address. */
|
||||
struct microblaze_address_info
|
||||
{
|
||||
@ -108,6 +118,7 @@ struct microblaze_address_info
|
||||
rtx offset; /* Contains valid values on ADDRESS_CONST_INT and ADDRESS_REG. */
|
||||
rtx symbol; /* Contains valid values on ADDRESS_SYMBOLIC. */
|
||||
enum microblaze_symbol_type symbol_type;
|
||||
enum tls_reloc tls_type;
|
||||
};
|
||||
|
||||
/* Structure to be filled in by compute_frame_size with register
|
||||
@ -215,6 +226,11 @@ static int microblaze_interrupt_function_p (tree);
|
||||
|
||||
section *sdata2_section;
|
||||
|
||||
#ifdef HAVE_AS_TLS
|
||||
#undef TARGET_HAVE_TLS
|
||||
#define TARGET_HAVE_TLS true
|
||||
#endif
|
||||
|
||||
/* Return truth value if a CONST_DOUBLE is ok to be a legitimate constant. */
|
||||
static bool
|
||||
microblaze_const_double_ok (rtx op, enum machine_mode mode)
|
||||
@ -287,6 +303,9 @@ simple_memory_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
|
||||
plus0 = XEXP (addr, 0);
|
||||
plus1 = XEXP (addr, 1);
|
||||
|
||||
if (GET_CODE (plus0) != REG)
|
||||
return 0;
|
||||
|
||||
if (GET_CODE (plus0) == REG && GET_CODE (plus1) == CONST_INT
|
||||
&& SMALL_INT (plus1))
|
||||
{
|
||||
@ -386,6 +405,225 @@ microblaze_valid_base_register_p (rtx x,
|
||||
&& microblaze_regno_ok_for_base_p (REGNO (x), strict));
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
/* Return TRUE if X is a thread-local symbol. */
|
||||
bool
|
||||
microblaze_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;
|
||||
}
|
||||
|
||||
static int
|
||||
microblaze_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
|
||||
microblaze_tls_referenced_p (rtx x)
|
||||
{
|
||||
if (!TARGET_HAVE_TLS)
|
||||
return false;
|
||||
|
||||
return for_each_rtx (&x, microblaze_tls_operand_p_1, NULL);
|
||||
}
|
||||
|
||||
bool
|
||||
microblaze_cannot_force_const_mem (enum machine_mode mode ATTRIBUTE_UNUSED, rtx x)
|
||||
{
|
||||
return microblaze_tls_referenced_p(x);
|
||||
}
|
||||
|
||||
/* Return TRUE if X references a SYMBOL_REF. */
|
||||
int
|
||||
symbol_mentioned_p (rtx x)
|
||||
{
|
||||
const char * fmt;
|
||||
int i;
|
||||
|
||||
if (GET_CODE (x) == SYMBOL_REF)
|
||||
return 1;
|
||||
|
||||
/* UNSPEC entries for a symbol include the SYMBOL_REF, but they
|
||||
are constant offsets, not symbols. */
|
||||
if (GET_CODE (x) == UNSPEC)
|
||||
return 0;
|
||||
|
||||
fmt = GET_RTX_FORMAT (GET_CODE (x));
|
||||
|
||||
for (i = GET_RTX_LENGTH (GET_CODE (x)) - 1; i >= 0; i--)
|
||||
{
|
||||
if (fmt[i] == 'E')
|
||||
{
|
||||
int j;
|
||||
|
||||
for (j = XVECLEN (x, i) - 1; j >= 0; j--)
|
||||
if (symbol_mentioned_p (XVECEXP (x, i, j)))
|
||||
return 1;
|
||||
}
|
||||
else if (fmt[i] == 'e' && symbol_mentioned_p (XEXP (x, i)))
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Return TRUE if X references a LABEL_REF. */
|
||||
int
|
||||
label_mentioned_p (rtx x)
|
||||
{
|
||||
const char * fmt;
|
||||
int i;
|
||||
|
||||
if (GET_CODE (x) == LABEL_REF)
|
||||
return 1;
|
||||
|
||||
/* UNSPEC entries for a symbol include a LABEL_REF for the referencing
|
||||
instruction, but they are constant offsets, not symbols. */
|
||||
if (GET_CODE (x) == UNSPEC)
|
||||
return 0;
|
||||
|
||||
fmt = GET_RTX_FORMAT (GET_CODE (x));
|
||||
for (i = GET_RTX_LENGTH (GET_CODE (x)) - 1; i >= 0; i--)
|
||||
{
|
||||
if (fmt[i] == 'E')
|
||||
{
|
||||
int j;
|
||||
|
||||
for (j = XVECLEN (x, i) - 1; j >= 0; j--)
|
||||
if (label_mentioned_p (XVECEXP (x, i, j)))
|
||||
return 1;
|
||||
}
|
||||
else if (fmt[i] == 'e' && label_mentioned_p (XEXP (x, i)))
|
||||
return 1;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
static rtx
|
||||
load_tls_operand (rtx x, rtx reg)
|
||||
{
|
||||
rtx tmp;
|
||||
|
||||
if (reg == NULL_RTX)
|
||||
reg = gen_reg_rtx (Pmode);
|
||||
|
||||
tmp = gen_rtx_CONST (Pmode, x);
|
||||
|
||||
emit_insn (gen_rtx_SET (VOIDmode, reg,
|
||||
gen_rtx_PLUS (Pmode, pic_offset_table_rtx, tmp)));
|
||||
|
||||
return reg;
|
||||
}
|
||||
|
||||
static rtx
|
||||
microblaze_call_tls_get_addr (rtx x, rtx reg, rtx *valuep, int reloc)
|
||||
{
|
||||
rtx insns, tls_entry;
|
||||
|
||||
df_set_regs_ever_live (PIC_OFFSET_TABLE_REGNUM, true);
|
||||
|
||||
start_sequence ();
|
||||
|
||||
tls_entry = gen_rtx_UNSPEC (Pmode, gen_rtvec (2, x, GEN_INT (reloc)),
|
||||
UNSPEC_TLS);
|
||||
|
||||
reg = load_tls_operand (tls_entry, reg);
|
||||
|
||||
*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
|
||||
microblaze_legitimize_tls_address(rtx x, rtx reg)
|
||||
{
|
||||
rtx dest, insns, ret, eqv, addend;
|
||||
enum tls_model model;
|
||||
model = SYMBOL_REF_TLS_MODEL (x);
|
||||
|
||||
switch (model)
|
||||
{
|
||||
case TLS_MODEL_LOCAL_DYNAMIC:
|
||||
case TLS_MODEL_GLOBAL_DYNAMIC:
|
||||
case TLS_MODEL_INITIAL_EXEC:
|
||||
insns = microblaze_call_tls_get_addr (x, reg, &ret, TLS_GD);
|
||||
dest = gen_reg_rtx (Pmode);
|
||||
emit_libcall_block (insns, dest, ret, x);
|
||||
break;
|
||||
|
||||
case TLS_MODEL_LOCAL_EXEC:
|
||||
insns = microblaze_call_tls_get_addr (x, reg, &ret, TLS_LDM);
|
||||
|
||||
/* 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, eqv);
|
||||
|
||||
/* Load the addend. */
|
||||
addend = gen_rtx_UNSPEC (Pmode, gen_rtvec (2, x, GEN_INT (TLS_DTPREL)),
|
||||
UNSPEC_TLS);
|
||||
addend = force_reg (SImode, gen_rtx_CONST (SImode, addend));
|
||||
dest = gen_rtx_PLUS (Pmode, dest, addend);
|
||||
break;
|
||||
|
||||
default:
|
||||
gcc_unreachable ();
|
||||
}
|
||||
return dest;
|
||||
}
|
||||
|
||||
static bool
|
||||
microblaze_classify_unspec (struct microblaze_address_info *info, rtx x)
|
||||
{
|
||||
@ -401,6 +639,11 @@ microblaze_classify_unspec (struct microblaze_address_info *info, rtx x)
|
||||
{
|
||||
info->type = ADDRESS_PLT;
|
||||
}
|
||||
else if (XINT (x, 1) == UNSPEC_TLS)
|
||||
{
|
||||
info->type = ADDRESS_TLS;
|
||||
info->tls_type = tls_reloc INTVAL(XVECEXP(x, 0, 1));
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
@ -431,7 +674,12 @@ static int
|
||||
get_base_reg (rtx x)
|
||||
{
|
||||
tree decl;
|
||||
int base_reg = (flag_pic ? MB_ABI_PIC_ADDR_REGNUM : MB_ABI_BASE_REGNUM);
|
||||
int base_reg;
|
||||
|
||||
if (!flag_pic || microblaze_tls_symbol_p(x))
|
||||
base_reg = MB_ABI_BASE_REGNUM;
|
||||
else if (flag_pic)
|
||||
base_reg = MB_ABI_PIC_ADDR_REGNUM;
|
||||
|
||||
if (TARGET_XLGPOPT
|
||||
&& GET_CODE (x) == SYMBOL_REF
|
||||
@ -509,28 +757,61 @@ microblaze_classify_address (struct microblaze_address_info *info, rtx x,
|
||||
}
|
||||
else if (GET_CODE (xplus1) == UNSPEC)
|
||||
{
|
||||
/* Need offsettable address. */
|
||||
if (GET_MODE_SIZE (mode) > UNITS_PER_WORD)
|
||||
return false;
|
||||
|
||||
return microblaze_classify_unspec (info, xplus1);
|
||||
}
|
||||
else if ((GET_CODE (xplus1) == SYMBOL_REF ||
|
||||
GET_CODE (xplus1) == LABEL_REF) && flag_pic == 2)
|
||||
GET_CODE (xplus1) == LABEL_REF))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else if (GET_CODE (xplus1) == SYMBOL_REF ||
|
||||
GET_CODE (xplus1) == LABEL_REF ||
|
||||
GET_CODE (xplus1) == CONST)
|
||||
{
|
||||
if (GET_CODE (XEXP (xplus1, 0)) == UNSPEC)
|
||||
return microblaze_classify_unspec (info, XEXP (xplus1, 0));
|
||||
else if (flag_pic == 2)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (flag_pic == 2 || microblaze_tls_symbol_p(xplus1))
|
||||
return false;
|
||||
info->type = ADDRESS_SYMBOLIC;
|
||||
info->symbol = xplus1;
|
||||
info->symbol_type = SYMBOL_TYPE_GENERAL;
|
||||
return true;
|
||||
}
|
||||
else if (GET_CODE (xplus1) == CONST)
|
||||
{
|
||||
rtx xconst0 = XEXP(xplus1, 0);
|
||||
|
||||
/* base + unspec. */
|
||||
if (GET_CODE (xconst0) == UNSPEC)
|
||||
{
|
||||
/* Need offsettable address. */
|
||||
if (GET_MODE_SIZE (mode) > UNITS_PER_WORD)
|
||||
return false;
|
||||
return microblaze_classify_unspec(info, xconst0);
|
||||
}
|
||||
|
||||
/* for (plus x const_int) just look at x. */
|
||||
if (GET_CODE (xconst0) == PLUS
|
||||
&& GET_CODE (XEXP (xconst0, 1)) == CONST_INT
|
||||
&& SMALL_INT (XEXP (xconst0, 1)))
|
||||
{
|
||||
/* This is ok as info->symbol is set to xplus1 the full
|
||||
const-expression below. */
|
||||
xconst0 = XEXP (xconst0, 0);
|
||||
}
|
||||
|
||||
if (GET_CODE (xconst0) == SYMBOL_REF
|
||||
|| GET_CODE (xconst0) == LABEL_REF)
|
||||
{
|
||||
if (flag_pic == 2 || microblaze_tls_symbol_p(xconst0))
|
||||
return false;
|
||||
|
||||
info->type = ADDRESS_SYMBOLIC;
|
||||
info->symbol = xplus1;
|
||||
info->symbol_type = SYMBOL_TYPE_GENERAL;
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Not base + symbol || base + UNSPEC. */
|
||||
return false;
|
||||
|
||||
}
|
||||
else if (GET_CODE (xplus1) == REG
|
||||
&& microblaze_valid_index_register_p (xplus1, mode,
|
||||
strict)
|
||||
@ -562,13 +843,20 @@ microblaze_classify_address (struct microblaze_address_info *info, rtx x,
|
||||
|
||||
if (GET_CODE (x) == CONST)
|
||||
{
|
||||
return !(flag_pic && pic_address_needs_scratch (x));
|
||||
}
|
||||
else if (flag_pic == 2)
|
||||
{
|
||||
return false;
|
||||
if (GET_CODE (XEXP (x, 0)) == UNSPEC)
|
||||
{
|
||||
info->regA = gen_rtx_raw_REG (mode,
|
||||
get_base_reg (XVECEXP (XEXP (x,0), 0, 0)));
|
||||
return microblaze_classify_unspec (info, XEXP (x, 0));
|
||||
}
|
||||
return !(flag_pic && pic_address_needs_scratch (x));
|
||||
}
|
||||
|
||||
if (flag_pic == 2)
|
||||
return false;
|
||||
else if (microblaze_tls_symbol_p(x))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -616,11 +904,10 @@ microblaze_valid_pic_const (rtx x)
|
||||
int
|
||||
microblaze_legitimate_pic_operand (rtx x)
|
||||
{
|
||||
struct microblaze_address_info addr;
|
||||
|
||||
if (pic_address_needs_scratch (x))
|
||||
if (flag_pic == 2 && (symbol_mentioned_p(x) || label_mentioned_p(x)))
|
||||
return 0;
|
||||
if (!microblaze_valid_pic_const(x))
|
||||
|
||||
if (microblaze_tls_referenced_p(x))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
@ -706,7 +993,7 @@ microblaze_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
|
||||
return result;
|
||||
}
|
||||
|
||||
if (code0 == REG && REG_OK_FOR_BASE_P (xplus0) && flag_pic == 2)
|
||||
if (code0 == REG && REG_OK_FOR_BASE_P (xplus0))
|
||||
{
|
||||
if (reload_in_progress)
|
||||
df_set_regs_ever_live (PIC_OFFSET_TABLE_REGNUM, true);
|
||||
@ -717,26 +1004,58 @@ microblaze_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
|
||||
}
|
||||
if (code1 == SYMBOL_REF)
|
||||
{
|
||||
result =
|
||||
gen_rtx_UNSPEC (Pmode, gen_rtvec (1, xplus1), UNSPEC_GOTOFF);
|
||||
result = gen_rtx_CONST (Pmode, result);
|
||||
result = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, result);
|
||||
result = gen_const_mem (Pmode, result);
|
||||
result = gen_rtx_PLUS (Pmode, xplus0, result);
|
||||
return result;
|
||||
if (microblaze_tls_symbol_p(xplus1))
|
||||
{
|
||||
rtx tls_ref, reg;
|
||||
reg = gen_reg_rtx (Pmode);
|
||||
|
||||
tls_ref = microblaze_legitimize_tls_address (xplus1,
|
||||
NULL_RTX);
|
||||
emit_move_insn (reg, tls_ref);
|
||||
|
||||
result = gen_rtx_PLUS (Pmode, xplus0, reg);
|
||||
|
||||
return result;
|
||||
}
|
||||
else if (flag_pic == 2)
|
||||
{
|
||||
rtx pic_ref, reg;
|
||||
reg = gen_reg_rtx (Pmode);
|
||||
|
||||
pic_ref = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, xplus1),
|
||||
UNSPEC_GOTOFF);
|
||||
pic_ref = gen_rtx_CONST (Pmode, pic_ref);
|
||||
pic_ref = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, pic_ref);
|
||||
pic_ref = gen_const_mem (Pmode, pic_ref);
|
||||
emit_move_insn (reg, pic_ref);
|
||||
result = gen_rtx_PLUS (Pmode, xplus0, reg);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (GET_CODE (xinsn) == SYMBOL_REF)
|
||||
{
|
||||
if (reload_in_progress)
|
||||
df_set_regs_ever_live (PIC_OFFSET_TABLE_REGNUM, true);
|
||||
result = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, xinsn), UNSPEC_GOTOFF);
|
||||
result = gen_rtx_CONST (Pmode, result);
|
||||
result = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, result);
|
||||
result = gen_const_mem (Pmode, result);
|
||||
return result;
|
||||
rtx reg;
|
||||
if (microblaze_tls_symbol_p(xinsn))
|
||||
{
|
||||
reg = microblaze_legitimize_tls_address (xinsn, NULL_RTX);
|
||||
}
|
||||
else
|
||||
{
|
||||
rtx pic_ref;
|
||||
|
||||
if (reload_in_progress)
|
||||
df_set_regs_ever_live (PIC_OFFSET_TABLE_REGNUM, true);
|
||||
|
||||
pic_ref = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, xinsn), UNSPEC_GOTOFF);
|
||||
pic_ref = gen_rtx_CONST (Pmode, pic_ref);
|
||||
pic_ref = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, pic_ref);
|
||||
pic_ref = gen_const_mem (Pmode, pic_ref);
|
||||
reg = pic_ref;
|
||||
}
|
||||
return reg;
|
||||
}
|
||||
|
||||
return x;
|
||||
@ -1061,10 +1380,22 @@ microblaze_address_insns (rtx x, enum machine_mode mode)
|
||||
else
|
||||
return 2;
|
||||
case ADDRESS_REG_INDEX:
|
||||
case ADDRESS_SYMBOLIC:
|
||||
return 1;
|
||||
case ADDRESS_SYMBOLIC:
|
||||
case ADDRESS_GOTOFF:
|
||||
return 2;
|
||||
case ADDRESS_TLS:
|
||||
switch (addr.tls_type)
|
||||
{
|
||||
case TLS_GD:
|
||||
return 2;
|
||||
case TLS_LDM:
|
||||
return 2;
|
||||
case TLS_DTPREL:
|
||||
return 1;
|
||||
default :
|
||||
abort();
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -1088,13 +1419,18 @@ microblaze_address_cost (rtx addr, enum machine_mode mode ATTRIBUTE_UNUSED,
|
||||
int
|
||||
pic_address_needs_scratch (rtx x)
|
||||
{
|
||||
/* An address which is a symbolic plus a non SMALL_INT needs a temp reg. */
|
||||
if (GET_CODE (x) == CONST && GET_CODE (XEXP (x, 0)) == PLUS
|
||||
&& GET_CODE (XEXP (XEXP (x, 0), 0)) == SYMBOL_REF
|
||||
&& GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT
|
||||
&& (flag_pic == 2 || !SMALL_INT (XEXP (XEXP (x, 0), 1))))
|
||||
return 1;
|
||||
if (GET_CODE (x) == CONST && GET_CODE (XEXP (x,0)) == PLUS)
|
||||
{
|
||||
rtx p0, p1;
|
||||
|
||||
p0 = XEXP (XEXP (x, 0), 0);
|
||||
p1 = XEXP (XEXP (x, 0), 1);
|
||||
|
||||
if ((GET_CODE (p0) == SYMBOL_REF || GET_CODE (p0) == LABEL_REF)
|
||||
&& (GET_CODE (p1) == CONST_INT)
|
||||
&& (flag_pic == 2 || microblaze_tls_symbol_p (p0) || !SMALL_INT (p1)))
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1918,6 +2254,7 @@ print_operand (FILE * file, rtx op, int letter)
|
||||
case ADDRESS_CONST_INT:
|
||||
case ADDRESS_SYMBOLIC:
|
||||
case ADDRESS_GOTOFF:
|
||||
case ADDRESS_TLS:
|
||||
fputs ("i", file);
|
||||
break;
|
||||
case ADDRESS_REG_INDEX:
|
||||
@ -2034,10 +2371,19 @@ print_operand (FILE * file, rtx op, int letter)
|
||||
else if (letter == 't')
|
||||
fputs (code == EQ ? "t" : "f", file);
|
||||
|
||||
else if (code == CONST && GET_CODE (XEXP (op, 0)) == REG)
|
||||
else if (code == CONST
|
||||
&& ((GET_CODE (XEXP (op, 0)) == REG)
|
||||
|| (GET_CODE (XEXP (op, 0)) == UNSPEC)))
|
||||
{
|
||||
print_operand (file, XEXP (op, 0), letter);
|
||||
}
|
||||
else if (code == CONST
|
||||
&& (GET_CODE (XEXP (op, 0)) == PLUS)
|
||||
&& (GET_CODE (XEXP (XEXP (op, 0), 0)) == REG)
|
||||
&& (GET_CODE (XEXP (XEXP (op, 0), 1)) == CONST))
|
||||
{
|
||||
print_operand_address (file, XEXP (op, 0));
|
||||
}
|
||||
else if (letter == 'm')
|
||||
fprintf (file, HOST_WIDE_INT_PRINT_DEC, (1L << INTVAL (op)));
|
||||
else
|
||||
@ -2098,6 +2444,7 @@ print_operand_address (FILE * file, rtx addr)
|
||||
case ADDRESS_SYMBOLIC:
|
||||
case ADDRESS_GOTOFF:
|
||||
case ADDRESS_PLT:
|
||||
case ADDRESS_TLS:
|
||||
if (info.regA)
|
||||
fprintf (file, "%s,", reg_names[REGNO (info.regA)]);
|
||||
output_addr_const (file, info.symbol);
|
||||
@ -2109,6 +2456,24 @@ print_operand_address (FILE * file, rtx addr)
|
||||
{
|
||||
fputs ("@PLT", file);
|
||||
}
|
||||
else if (type == ADDRESS_TLS)
|
||||
{
|
||||
switch (info.tls_type)
|
||||
{
|
||||
case TLS_GD:
|
||||
fputs ("@TLSGD", file);
|
||||
break;
|
||||
case TLS_LDM:
|
||||
fputs ("@TLSLDM", file);
|
||||
break;
|
||||
case TLS_DTPREL:
|
||||
fputs ("@TLSDTPREL", file);
|
||||
break;
|
||||
default :
|
||||
abort();
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ADDRESS_INVALID:
|
||||
fatal_insn ("invalid address", addr);
|
||||
@ -2471,7 +2836,8 @@ microblaze_expand_prologue (void)
|
||||
}
|
||||
}
|
||||
|
||||
if (flag_pic == 2 && df_regs_ever_live_p (MB_ABI_PIC_ADDR_REGNUM))
|
||||
if ((flag_pic == 2 || TLS_NEEDS_GOT )
|
||||
&& df_regs_ever_live_p (MB_ABI_PIC_ADDR_REGNUM))
|
||||
{
|
||||
SET_REGNO (pic_offset_table_rtx, MB_ABI_PIC_ADDR_REGNUM);
|
||||
emit_insn (gen_set_got (pic_offset_table_rtx)); /* setting GOT. */
|
||||
@ -2701,82 +3067,61 @@ expand_pic_symbol_ref (enum machine_mode mode ATTRIBUTE_UNUSED, rtx op)
|
||||
bool
|
||||
microblaze_expand_move (enum machine_mode mode, rtx operands[])
|
||||
{
|
||||
rtx op0, op1;
|
||||
|
||||
op0 = operands[0];
|
||||
op1 = operands[1];
|
||||
|
||||
if (!register_operand (op0, SImode)
|
||||
&& !register_operand (op1, SImode)
|
||||
&& (GET_CODE (op1) != CONST_INT || INTVAL (op1) != 0))
|
||||
{
|
||||
rtx temp = force_reg (SImode, op1);
|
||||
emit_move_insn (op0, temp);
|
||||
return true;
|
||||
}
|
||||
/* If operands[1] is a constant address invalid for pic, then we need to
|
||||
handle it just like LEGITIMIZE_ADDRESS does. */
|
||||
if (flag_pic)
|
||||
if (GET_CODE (op1) == SYMBOL_REF || GET_CODE (op1) == LABEL_REF)
|
||||
{
|
||||
if (GET_CODE (operands[0]) == MEM)
|
||||
rtx result;
|
||||
if (microblaze_tls_symbol_p(op1))
|
||||
{
|
||||
rtx addr = XEXP (operands[0], 0);
|
||||
if (GET_CODE (addr) == SYMBOL_REF)
|
||||
{
|
||||
rtx ptr_reg, result;
|
||||
|
||||
if (reload_in_progress)
|
||||
df_set_regs_ever_live (PIC_OFFSET_TABLE_REGNUM, true);
|
||||
|
||||
addr = expand_pic_symbol_ref (mode, addr);
|
||||
ptr_reg = gen_reg_rtx (Pmode);
|
||||
emit_move_insn (ptr_reg, addr);
|
||||
result = gen_rtx_MEM (mode, ptr_reg);
|
||||
operands[0] = result;
|
||||
}
|
||||
}
|
||||
if (GET_CODE (operands[1]) == SYMBOL_REF
|
||||
|| GET_CODE (operands[1]) == LABEL_REF)
|
||||
{
|
||||
rtx result;
|
||||
if (reload_in_progress)
|
||||
df_set_regs_ever_live (PIC_OFFSET_TABLE_REGNUM, true);
|
||||
result = expand_pic_symbol_ref (mode, operands[1]);
|
||||
if (GET_CODE (operands[0]) != REG)
|
||||
{
|
||||
rtx ptr_reg = gen_reg_rtx (Pmode);
|
||||
emit_move_insn (ptr_reg, result);
|
||||
emit_move_insn (operands[0], ptr_reg);
|
||||
}
|
||||
else
|
||||
{
|
||||
emit_move_insn (operands[0], result);
|
||||
}
|
||||
result = microblaze_legitimize_tls_address (op1, NULL_RTX);
|
||||
emit_move_insn (op0, result);
|
||||
return true;
|
||||
}
|
||||
else if (GET_CODE (operands[1]) == MEM &&
|
||||
GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF)
|
||||
else if (flag_pic)
|
||||
{
|
||||
rtx result;
|
||||
rtx ptr_reg;
|
||||
if (reload_in_progress)
|
||||
df_set_regs_ever_live (PIC_OFFSET_TABLE_REGNUM, true);
|
||||
result = expand_pic_symbol_ref (mode, XEXP (operands[1], 0));
|
||||
|
||||
ptr_reg = gen_reg_rtx (Pmode);
|
||||
|
||||
emit_move_insn (ptr_reg, result);
|
||||
result = gen_rtx_MEM (mode, ptr_reg);
|
||||
emit_move_insn (operands[0], result);
|
||||
return true;
|
||||
}
|
||||
else if (pic_address_needs_scratch (operands[1]))
|
||||
{
|
||||
rtx temp = force_reg (SImode, XEXP (XEXP (operands[1], 0), 0));
|
||||
rtx temp2 = XEXP (XEXP (operands[1], 0), 1);
|
||||
|
||||
if (reload_in_progress)
|
||||
df_set_regs_ever_live (PIC_OFFSET_TABLE_REGNUM, true);
|
||||
emit_move_insn (operands[0], gen_rtx_PLUS (SImode, temp, temp2));
|
||||
result = expand_pic_symbol_ref (mode, op1);
|
||||
emit_move_insn (op0, result);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if ((reload_in_progress | reload_completed) == 0
|
||||
&& !register_operand (operands[0], SImode)
|
||||
&& !register_operand (operands[1], SImode)
|
||||
&& (GET_CODE (operands[1]) != CONST_INT || INTVAL (operands[1]) != 0))
|
||||
/* Handle Case of (const (plus symbol const_int)). */
|
||||
if (GET_CODE (op1) == CONST && GET_CODE (XEXP (op1,0)) == PLUS)
|
||||
{
|
||||
rtx temp = force_reg (SImode, operands[1]);
|
||||
emit_move_insn (operands[0], temp);
|
||||
return true;
|
||||
rtx p0, p1;
|
||||
|
||||
p0 = XEXP (XEXP (op1, 0), 0);
|
||||
p1 = XEXP (XEXP (op1, 0), 1);
|
||||
|
||||
if ((GET_CODE (p1) == CONST_INT)
|
||||
&& ((GET_CODE (p0) == UNSPEC)
|
||||
|| ((GET_CODE (p0) == SYMBOL_REF || GET_CODE (p0) == LABEL_REF)
|
||||
&& (flag_pic == 2 || microblaze_tls_symbol_p (p0)
|
||||
|| !SMALL_INT (p1)))))
|
||||
{
|
||||
rtx temp = force_reg (SImode, p0);
|
||||
rtx temp2 = p1;
|
||||
|
||||
if (flag_pic && reload_in_progress)
|
||||
df_set_regs_ever_live (PIC_OFFSET_TABLE_REGNUM, true);
|
||||
emit_move_insn (op0, gen_rtx_PLUS (SImode, temp, temp2));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@ -3048,10 +3393,40 @@ microblaze_adjust_cost (rtx insn ATTRIBUTE_UNUSED, rtx link,
|
||||
At present, GAS doesn't understand li.[sd], so don't allow it
|
||||
to be generated at present. */
|
||||
static bool
|
||||
microblaze_legitimate_constant_p (enum machine_mode mode, rtx x)
|
||||
microblaze_legitimate_constant_p (enum machine_mode mode ATTRIBUTE_UNUSED, rtx x)
|
||||
{
|
||||
return GET_CODE (x) != CONST_DOUBLE || microblaze_const_double_ok (x, mode);
|
||||
|
||||
if (microblaze_cannot_force_const_mem(mode, x))
|
||||
return false;
|
||||
|
||||
if (GET_CODE (x) == CONST_DOUBLE)
|
||||
{
|
||||
return microblaze_const_double_ok (x, GET_MODE (x));
|
||||
}
|
||||
|
||||
/* Handle Case of (const (plus unspec const_int)). */
|
||||
if (GET_CODE (x) == CONST && GET_CODE (XEXP (x,0)) == PLUS)
|
||||
{
|
||||
rtx p0, p1;
|
||||
|
||||
p0 = XEXP (XEXP (x, 0), 0);
|
||||
p1 = XEXP (XEXP (x, 0), 1);
|
||||
|
||||
if (GET_CODE(p1) == CONST_INT)
|
||||
{
|
||||
/* Const offset from UNSPEC is not supported. */
|
||||
if ((GET_CODE (p0) == UNSPEC))
|
||||
return false;
|
||||
|
||||
if ((GET_CODE (p0) == SYMBOL_REF || GET_CODE (p0) == LABEL_REF)
|
||||
&& (microblaze_tls_symbol_p (p0) || !SMALL_INT (p1)))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
#undef TARGET_ENCODE_SECTION_INFO
|
||||
#define TARGET_ENCODE_SECTION_INFO microblaze_encode_section_info
|
||||
@ -3068,6 +3443,9 @@ microblaze_legitimate_constant_p (enum machine_mode mode, rtx x)
|
||||
#undef TARGET_RTX_COSTS
|
||||
#define TARGET_RTX_COSTS microblaze_rtx_costs
|
||||
|
||||
#undef TARGET_CANNOT_FORCE_CONST_MEM
|
||||
#define TARGET_CANNOT_FORCE_CONST_MEM microblaze_cannot_force_const_mem
|
||||
|
||||
#undef TARGET_ADDRESS_COST
|
||||
#define TARGET_ADDRESS_COST microblaze_address_cost
|
||||
|
||||
|
@ -65,6 +65,9 @@ extern enum pipeline_type microblaze_pipe;
|
||||
/* The default is to support PIC. */
|
||||
#define TARGET_SUPPORTS_PIC 1
|
||||
|
||||
/* The default is to not need GOT for TLS. */
|
||||
#define TLS_NEEDS_GOT 0
|
||||
|
||||
/* What is the default setting for -mcpu= . We set it to v4.00.a even though
|
||||
we are actually ahead. This is safest version that has generate code
|
||||
compatible for the original ISA */
|
||||
@ -326,9 +329,7 @@ extern char microblaze_hard_regno_mode_ok[][FIRST_PSEUDO_REGISTER];
|
||||
|
||||
#define NO_FUNCTION_CSE 1
|
||||
|
||||
#define PIC_OFFSET_TABLE_REGNUM \
|
||||
(flag_pic ? (GP_REG_FIRST + MB_ABI_PIC_ADDR_REGNUM) : \
|
||||
INVALID_REGNUM)
|
||||
#define PIC_OFFSET_TABLE_REGNUM (GP_REG_FIRST + MB_ABI_PIC_ADDR_REGNUM)
|
||||
|
||||
enum reg_class
|
||||
{
|
||||
|
@ -40,6 +40,7 @@
|
||||
(UNSPEC_PLT 103) ;; jump table
|
||||
(UNSPEC_CMP 104) ;; signed compare
|
||||
(UNSPEC_CMPU 105) ;; unsigned compare
|
||||
(UNSPEC_TLS 106) ;; jump table
|
||||
])
|
||||
|
||||
|
||||
@ -459,7 +460,7 @@
|
||||
(define_insn "addsi3"
|
||||
[(set (match_operand:SI 0 "register_operand" "=d,d,d")
|
||||
(plus:SI (match_operand:SI 1 "reg_or_0_operand" "%dJ,dJ,dJ")
|
||||
(match_operand:SI 2 "arith_operand" "d,I,i")))]
|
||||
(match_operand:SI 2 "arith_plus_operand" "d,I,i")))]
|
||||
""
|
||||
"@
|
||||
addk\t%0,%z1,%2
|
||||
@ -892,8 +893,8 @@
|
||||
|
||||
|
||||
(define_insn "*movdi_internal"
|
||||
[(set (match_operand:DI 0 "nonimmediate_operand" "=d,d,d,d,d,R,m")
|
||||
(match_operand:DI 1 "general_operand" " d,i,J,R,m,d,d"))]
|
||||
[(set (match_operand:DI 0 "nonimmediate_operand" "=d,d,d,d,d,R,o")
|
||||
(match_operand:DI 1 "general_operand" " d,i,J,R,o,d,d"))]
|
||||
""
|
||||
{
|
||||
switch (which_alternative)
|
||||
@ -999,13 +1000,9 @@
|
||||
(set_attr "length" "4")])
|
||||
|
||||
(define_insn "*movsi_internal2"
|
||||
[(set (match_operand:SI 0 "nonimmediate_operand" "=d,d,d, d,d,R, T")
|
||||
(match_operand:SI 1 "move_operand" " d,I,Mnis,R,m,dJ,dJ"))]
|
||||
"(register_operand (operands[0], SImode)
|
||||
|| register_operand (operands[1], SImode)
|
||||
|| (GET_CODE (operands[1]) == CONST_INT && INTVAL (operands[1]) == 0))
|
||||
&& (flag_pic != 2 || (GET_CODE (operands[1]) != SYMBOL_REF
|
||||
&& GET_CODE (operands[1]) != LABEL_REF))"
|
||||
[(set (match_operand:SI 0 "nonimmediate_operand" "=d,d,d, d,d,R,m")
|
||||
(match_operand:SI 1 "move_src_operand" " d,I,Mnis,R,m,dJ,dJ"))]
|
||||
""
|
||||
"@
|
||||
addk\t%0,%1,r0
|
||||
addik\t%0,r0,%1\t# %X1
|
||||
@ -1196,7 +1193,7 @@
|
||||
;; Applies to both TARGET_SOFT_FLOAT and TARGET_HARD_FLOAT
|
||||
;;
|
||||
(define_insn "*movdf_internal"
|
||||
[(set (match_operand:DF 0 "nonimmediate_operand" "=d,d,d,d,To")
|
||||
[(set (match_operand:DF 0 "nonimmediate_operand" "=d,d,d,d,o")
|
||||
(match_operand:DF 1 "general_operand" "dG,o,F,T,d"))]
|
||||
""
|
||||
{
|
||||
|
@ -30,6 +30,52 @@
|
||||
(and (match_code "const_int,const_double")
|
||||
(match_test "LARGE_INT (op)"))))
|
||||
|
||||
(define_predicate "arith_plus_operand"
|
||||
(match_operand 0 "general_operand")
|
||||
{
|
||||
switch (GET_CODE (op))
|
||||
{
|
||||
default:
|
||||
return 0;
|
||||
case CONST_INT:
|
||||
case REG:
|
||||
return 1;
|
||||
case SYMBOL_REF:
|
||||
case LABEL_REF:
|
||||
if (flag_pic || microblaze_tls_referenced_p(op))
|
||||
return 0;
|
||||
return 1;
|
||||
case CONST:
|
||||
{
|
||||
rtx const0;
|
||||
const0 = XEXP (op, 0);
|
||||
|
||||
switch (GET_CODE(const0))
|
||||
{
|
||||
default:
|
||||
return 0;
|
||||
case UNSPEC :
|
||||
return 1;
|
||||
|
||||
case PLUS :
|
||||
{
|
||||
rtx p0, p1;
|
||||
p0 = XEXP (const0, 0);
|
||||
p1 = XEXP (const0, 1);
|
||||
|
||||
if ((GET_CODE(p0) == SYMBOL_REF
|
||||
|| GET_CODE (p0) == LABEL_REF)
|
||||
&& GET_CODE(p1) == CONST_INT)
|
||||
{
|
||||
return arith_plus_operand (p0, GET_MODE(p0));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
})
|
||||
|
||||
(define_predicate "const_0_operand"
|
||||
(and (match_code "const_int,const_double")
|
||||
(match_test "op == CONST0_RTX (GET_MODE (op))")))
|
||||
@ -54,14 +100,21 @@
|
||||
(match_test "GET_CODE (op) == REG || GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == CONST_INT")))
|
||||
|
||||
;; Return if OPERAND is valid as a source operand for a move instruction.
|
||||
(define_predicate "move_operand"
|
||||
(define_predicate "move_src_operand"
|
||||
(and (
|
||||
not (
|
||||
and (match_code "plus")
|
||||
(not (match_test "(GET_CODE (XEXP (op, 0)) == REG) ^ (GET_CODE (XEXP (op,1)) == REG)"))
|
||||
)
|
||||
)
|
||||
(match_operand 0 "general_operand")))
|
||||
(match_operand 0 "general_operand"))
|
||||
{
|
||||
if (microblaze_tls_referenced_p(op)
|
||||
|| (flag_pic && (symbol_mentioned_p(op) || label_mentioned_p(op))))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
})
|
||||
|
||||
;; Test for valid PIC call operand
|
||||
(define_predicate "call_insn_plt_operand"
|
||||
|
12
gcc/configure
vendored
12
gcc/configure
vendored
@ -23205,6 +23205,18 @@ foo: data8 25
|
||||
tls_first_minor=13
|
||||
tls_as_opt=--fatal-warnings
|
||||
;;
|
||||
microblaze*-*-*)
|
||||
conftest_s='
|
||||
.section .tdata,"awT",@progbits
|
||||
x:
|
||||
.word 2
|
||||
.text
|
||||
addik r5,r20,x@TLSGD
|
||||
addik r5,r20,x@TLSLDM'
|
||||
tls_first_major=2
|
||||
tls_first_minor=20
|
||||
tls_as_opt='--fatal-warnings'
|
||||
;;
|
||||
mips*-*-*)
|
||||
conftest_s='
|
||||
.section .tdata,"awT",@progbits
|
||||
|
@ -2968,6 +2968,18 @@ foo: data8 25
|
||||
tls_first_minor=13
|
||||
tls_as_opt=--fatal-warnings
|
||||
;;
|
||||
microblaze*-*-*)
|
||||
conftest_s='
|
||||
.section .tdata,"awT",@progbits
|
||||
x:
|
||||
.word 2
|
||||
.text
|
||||
addik r5,r20,x@TLSGD
|
||||
addik r5,r20,x@TLSLDM'
|
||||
tls_first_major=2
|
||||
tls_first_minor=20
|
||||
tls_as_opt='--fatal-warnings'
|
||||
;;
|
||||
mips*-*-*)
|
||||
conftest_s='
|
||||
.section .tdata,"awT",@progbits
|
||||
|
Loading…
Reference in New Issue
Block a user