mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-06-29 16:38:05 +08:00
gas/
* config/tc-mips.h (TC_FORCE_RELOCATION): Remove comment. * config/tc-mips.c (calculate_reloc): New function. (append_insn): Use it. Do not resolve compound relocations here. (mips16_macro_build, mips16_ip): Use calculate_reloc. (mips16_immed_extend): New function, split out from... (mips16_immed): ...here. (mips_frob_file): Handle null symbols. (mips_force_relocation): Remove NEWABI handling. (read_reloc_insn, write_reloc_insn): New functions. (md_apply_fix): Report TLS relocations against constants. Use read_reloc_insn, calculate_reloc and write_reloc_insn. Report relocations against constants that can't be resolved at assembly time. gas/testsuite/ * gas/mips/elf-rel22.s, gas/mips/elf-rel22.d: Add more tests. * gas/mips/elf-rel29.s, gas/mips/elf-rel29.d, gas/mips/micromips@elf-rel29.d, gas/mips/elf-rel30.s, gas/mips/elf-rel30.l: New tests. * gas/mips/mips.exp: Run them.
This commit is contained in:
@ -1,3 +1,19 @@
|
|||||||
|
2012-09-23 Richard Sandiford <rdsandiford@googlemail.com>
|
||||||
|
|
||||||
|
* config/tc-mips.h (TC_FORCE_RELOCATION): Remove comment.
|
||||||
|
* config/tc-mips.c (calculate_reloc): New function.
|
||||||
|
(append_insn): Use it. Do not resolve compound relocations here.
|
||||||
|
(mips16_macro_build, mips16_ip): Use calculate_reloc.
|
||||||
|
(mips16_immed_extend): New function, split out from...
|
||||||
|
(mips16_immed): ...here.
|
||||||
|
(mips_frob_file): Handle null symbols.
|
||||||
|
(mips_force_relocation): Remove NEWABI handling.
|
||||||
|
(read_reloc_insn, write_reloc_insn): New functions.
|
||||||
|
(md_apply_fix): Report TLS relocations against constants.
|
||||||
|
Use read_reloc_insn, calculate_reloc and write_reloc_insn.
|
||||||
|
Report relocations against constants that can't be resolved
|
||||||
|
at assembly time.
|
||||||
|
|
||||||
2012-09-23 Maciej W. Rozycki <macro@codesourcery.com>
|
2012-09-23 Maciej W. Rozycki <macro@codesourcery.com>
|
||||||
|
|
||||||
* config/tc-mips.c (append_insn) <BFD_RELOC_MIPS_JMP>: Don't
|
* config/tc-mips.c (append_insn) <BFD_RELOC_MIPS_JMP>: Don't
|
||||||
|
@ -4022,6 +4022,52 @@ micromips_map_reloc (bfd_reloc_code_real_type reloc)
|
|||||||
return reloc;
|
return reloc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Try to resolve relocation RELOC against constant OPERAND at assembly time.
|
||||||
|
Return true on success, storing the resolved value in RESULT. */
|
||||||
|
|
||||||
|
static bfd_boolean
|
||||||
|
calculate_reloc (bfd_reloc_code_real_type reloc, offsetT operand,
|
||||||
|
offsetT *result)
|
||||||
|
{
|
||||||
|
switch (reloc)
|
||||||
|
{
|
||||||
|
case BFD_RELOC_MIPS_HIGHEST:
|
||||||
|
case BFD_RELOC_MICROMIPS_HIGHEST:
|
||||||
|
*result = ((operand + 0x800080008000ull) >> 48) & 0xffff;
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
case BFD_RELOC_MIPS_HIGHER:
|
||||||
|
case BFD_RELOC_MICROMIPS_HIGHER:
|
||||||
|
*result = ((operand + 0x80008000ull) >> 32) & 0xffff;
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
case BFD_RELOC_HI16_S:
|
||||||
|
case BFD_RELOC_MICROMIPS_HI16_S:
|
||||||
|
case BFD_RELOC_MIPS16_HI16_S:
|
||||||
|
*result = ((operand + 0x8000) >> 16) & 0xffff;
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
case BFD_RELOC_HI16:
|
||||||
|
case BFD_RELOC_MICROMIPS_HI16:
|
||||||
|
case BFD_RELOC_MIPS16_HI16:
|
||||||
|
*result = (operand >> 16) & 0xffff;
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
case BFD_RELOC_LO16:
|
||||||
|
case BFD_RELOC_MICROMIPS_LO16:
|
||||||
|
case BFD_RELOC_MIPS16_LO16:
|
||||||
|
*result = operand & 0xffff;
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
case BFD_RELOC_UNUSED:
|
||||||
|
*result = operand;
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Output an instruction. IP is the instruction information.
|
/* Output an instruction. IP is the instruction information.
|
||||||
ADDRESS_EXPR is an operand of the instruction to be used with
|
ADDRESS_EXPR is an operand of the instruction to be used with
|
||||||
RELOC_TYPE. EXPANSIONP is true if the instruction is part of
|
RELOC_TYPE. EXPANSIONP is true if the instruction is part of
|
||||||
@ -4057,43 +4103,13 @@ append_insn (struct mips_cl_insn *ip, expressionS *address_expr,
|
|||||||
|
|
||||||
if (address_expr == NULL)
|
if (address_expr == NULL)
|
||||||
ip->complete_p = 1;
|
ip->complete_p = 1;
|
||||||
else if (*reloc_type <= BFD_RELOC_UNUSED
|
else if (reloc_type[0] <= BFD_RELOC_UNUSED
|
||||||
|
&& reloc_type[1] == BFD_RELOC_UNUSED
|
||||||
|
&& reloc_type[2] == BFD_RELOC_UNUSED
|
||||||
&& address_expr->X_op == O_constant)
|
&& address_expr->X_op == O_constant)
|
||||||
{
|
{
|
||||||
unsigned int tmp;
|
|
||||||
|
|
||||||
ip->complete_p = 1;
|
|
||||||
switch (*reloc_type)
|
switch (*reloc_type)
|
||||||
{
|
{
|
||||||
case BFD_RELOC_32:
|
|
||||||
ip->insn_opcode |= address_expr->X_add_number;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case BFD_RELOC_MIPS_HIGHEST:
|
|
||||||
tmp = (address_expr->X_add_number + 0x800080008000ull) >> 48;
|
|
||||||
ip->insn_opcode |= tmp & 0xffff;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case BFD_RELOC_MIPS_HIGHER:
|
|
||||||
tmp = (address_expr->X_add_number + 0x80008000ull) >> 32;
|
|
||||||
ip->insn_opcode |= tmp & 0xffff;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case BFD_RELOC_HI16_S:
|
|
||||||
tmp = (address_expr->X_add_number + 0x8000) >> 16;
|
|
||||||
ip->insn_opcode |= tmp & 0xffff;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case BFD_RELOC_HI16:
|
|
||||||
ip->insn_opcode |= (address_expr->X_add_number >> 16) & 0xffff;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case BFD_RELOC_UNUSED:
|
|
||||||
case BFD_RELOC_LO16:
|
|
||||||
case BFD_RELOC_MIPS_GOT_DISP:
|
|
||||||
ip->insn_opcode |= address_expr->X_add_number & 0xffff;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case BFD_RELOC_MIPS_JMP:
|
case BFD_RELOC_MIPS_JMP:
|
||||||
{
|
{
|
||||||
int shift;
|
int shift;
|
||||||
@ -4136,13 +4152,22 @@ append_insn (struct mips_cl_insn *ip, expressionS *address_expr,
|
|||||||
ip->insn_opcode |= ((address_expr->X_add_number >> shift)
|
ip->insn_opcode |= ((address_expr->X_add_number >> shift)
|
||||||
& 0xffff);
|
& 0xffff);
|
||||||
}
|
}
|
||||||
ip->complete_p = 0;
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
internalError ();
|
{
|
||||||
}
|
offsetT value;
|
||||||
|
|
||||||
|
if (calculate_reloc (*reloc_type, address_expr->X_add_number,
|
||||||
|
&value))
|
||||||
|
{
|
||||||
|
ip->insn_opcode |= value & 0xffff;
|
||||||
|
ip->complete_p = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mips_relax.sequence != 2 && !mips_opts.noreorder)
|
if (mips_relax.sequence != 2 && !mips_opts.noreorder)
|
||||||
@ -5227,14 +5252,15 @@ mips16_macro_build (expressionS *ep, const char *name, const char *fmt,
|
|||||||
case 'p':
|
case 'p':
|
||||||
case 'q':
|
case 'q':
|
||||||
{
|
{
|
||||||
|
offsetT value;
|
||||||
|
|
||||||
gas_assert (ep != NULL);
|
gas_assert (ep != NULL);
|
||||||
|
|
||||||
if (ep->X_op != O_constant)
|
if (ep->X_op != O_constant)
|
||||||
*r = (int) BFD_RELOC_UNUSED + c;
|
*r = (int) BFD_RELOC_UNUSED + c;
|
||||||
else
|
else if (calculate_reloc (*r, ep->X_add_number, &value))
|
||||||
{
|
{
|
||||||
mips16_immed (NULL, 0, c, *r, ep->X_add_number,
|
mips16_immed (NULL, 0, c, *r, value, 0, &insn.insn_opcode);
|
||||||
0, &insn.insn_opcode);
|
|
||||||
ep = NULL;
|
ep = NULL;
|
||||||
*r = BFD_RELOC_UNUSED;
|
*r = BFD_RELOC_UNUSED;
|
||||||
}
|
}
|
||||||
@ -13376,40 +13402,17 @@ mips16_ip (char *str, struct mips_cl_insn *ip)
|
|||||||
case '\0':
|
case '\0':
|
||||||
if (*s == '\0')
|
if (*s == '\0')
|
||||||
{
|
{
|
||||||
|
offsetT value;
|
||||||
|
|
||||||
/* Stuff the immediate value in now, if we can. */
|
/* Stuff the immediate value in now, if we can. */
|
||||||
if (imm_expr.X_op == O_constant
|
if (imm_expr.X_op == O_constant
|
||||||
&& *imm_reloc > BFD_RELOC_UNUSED
|
&& *imm_reloc > BFD_RELOC_UNUSED
|
||||||
&& *imm_reloc != BFD_RELOC_MIPS16_GOT16
|
&& insn->pinfo != INSN_MACRO
|
||||||
&& *imm_reloc != BFD_RELOC_MIPS16_CALL16
|
&& calculate_reloc (*offset_reloc,
|
||||||
&& insn->pinfo != INSN_MACRO)
|
imm_expr.X_add_number, &value))
|
||||||
{
|
{
|
||||||
valueT tmp;
|
|
||||||
|
|
||||||
switch (*offset_reloc)
|
|
||||||
{
|
|
||||||
case BFD_RELOC_MIPS16_HI16_S:
|
|
||||||
tmp = (imm_expr.X_add_number + 0x8000) >> 16;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case BFD_RELOC_MIPS16_HI16:
|
|
||||||
tmp = imm_expr.X_add_number >> 16;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case BFD_RELOC_MIPS16_LO16:
|
|
||||||
tmp = ((imm_expr.X_add_number + 0x8000) & 0xffff)
|
|
||||||
- 0x8000;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case BFD_RELOC_UNUSED:
|
|
||||||
tmp = imm_expr.X_add_number;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
internalError ();
|
|
||||||
}
|
|
||||||
|
|
||||||
mips16_immed (NULL, 0, *imm_reloc - BFD_RELOC_UNUSED,
|
mips16_immed (NULL, 0, *imm_reloc - BFD_RELOC_UNUSED,
|
||||||
*offset_reloc, tmp, forced_insn_length,
|
*offset_reloc, value, forced_insn_length,
|
||||||
&ip->insn_opcode);
|
&ip->insn_opcode);
|
||||||
imm_expr.X_op = O_absent;
|
imm_expr.X_op = O_absent;
|
||||||
*imm_reloc = BFD_RELOC_UNUSED;
|
*imm_reloc = BFD_RELOC_UNUSED;
|
||||||
@ -13995,6 +13998,31 @@ static const struct mips16_immed_operand mips16_immed_operands[] =
|
|||||||
#define MIPS16_NUM_IMMED \
|
#define MIPS16_NUM_IMMED \
|
||||||
(sizeof mips16_immed_operands / sizeof mips16_immed_operands[0])
|
(sizeof mips16_immed_operands / sizeof mips16_immed_operands[0])
|
||||||
|
|
||||||
|
/* Marshal immediate value VAL for an extended MIPS16 instruction.
|
||||||
|
NBITS is the number of significant bits in VAL. */
|
||||||
|
|
||||||
|
static unsigned long
|
||||||
|
mips16_immed_extend (offsetT val, unsigned int nbits)
|
||||||
|
{
|
||||||
|
int extval;
|
||||||
|
if (nbits == 16)
|
||||||
|
{
|
||||||
|
extval = ((val >> 11) & 0x1f) | (val & 0x7e0);
|
||||||
|
val &= 0x1f;
|
||||||
|
}
|
||||||
|
else if (nbits == 15)
|
||||||
|
{
|
||||||
|
extval = ((val >> 11) & 0xf) | (val & 0x7f0);
|
||||||
|
val &= 0xf;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
extval = ((val & 0x1f) << 6) | (val & 0x20);
|
||||||
|
val = 0;
|
||||||
|
}
|
||||||
|
return (extval << 16) | val;
|
||||||
|
}
|
||||||
|
|
||||||
/* Install immediate value VAL into MIPS16 instruction *INSN,
|
/* Install immediate value VAL into MIPS16 instruction *INSN,
|
||||||
extending it if necessary. The instruction in *INSN may
|
extending it if necessary. The instruction in *INSN may
|
||||||
already be extended.
|
already be extended.
|
||||||
@ -14078,7 +14106,6 @@ mips16_immed (char *file, unsigned int line, int type,
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
long minext, maxext;
|
long minext, maxext;
|
||||||
int extval;
|
|
||||||
|
|
||||||
if (reloc == BFD_RELOC_UNUSED)
|
if (reloc == BFD_RELOC_UNUSED)
|
||||||
{
|
{
|
||||||
@ -14097,23 +14124,7 @@ mips16_immed (char *file, unsigned int line, int type,
|
|||||||
_("operand value out of range for instruction"));
|
_("operand value out of range for instruction"));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (op->extbits == 16)
|
*insn |= mips16_immed_extend (val, op->extbits);
|
||||||
{
|
|
||||||
extval = ((val >> 11) & 0x1f) | (val & 0x7e0);
|
|
||||||
val &= 0x1f;
|
|
||||||
}
|
|
||||||
else if (op->extbits == 15)
|
|
||||||
{
|
|
||||||
extval = ((val >> 11) & 0xf) | (val & 0x7f0);
|
|
||||||
val &= 0xf;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
extval = ((val & 0x1f) << 6) | (val & 0x20);
|
|
||||||
val = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
*insn |= (extval << 16) | val;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -15357,9 +15368,11 @@ mips_frob_file (void)
|
|||||||
gas_assert (reloc_needs_lo_p (l->fixp->fx_r_type));
|
gas_assert (reloc_needs_lo_p (l->fixp->fx_r_type));
|
||||||
|
|
||||||
/* If a GOT16 relocation turns out to be against a global symbol,
|
/* If a GOT16 relocation turns out to be against a global symbol,
|
||||||
there isn't supposed to be a matching LO. */
|
there isn't supposed to be a matching LO. Ignore %gots against
|
||||||
|
constants; we'll report an error for those later. */
|
||||||
if (got16_reloc_p (l->fixp->fx_r_type)
|
if (got16_reloc_p (l->fixp->fx_r_type)
|
||||||
&& !pic_need_relax (l->fixp->fx_addsy, l->seg))
|
&& !(l->fixp->fx_addsy
|
||||||
|
&& pic_need_relax (l->fixp->fx_addsy, l->seg)))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* Check quickly whether the next fixup happens to be a matching %lo. */
|
/* Check quickly whether the next fixup happens to be a matching %lo. */
|
||||||
@ -15417,9 +15430,6 @@ mips_frob_file (void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We may have combined relocations without symbols in the N32/N64 ABI.
|
|
||||||
We have to prevent gas from dropping them. */
|
|
||||||
|
|
||||||
int
|
int
|
||||||
mips_force_relocation (fixS *fixp)
|
mips_force_relocation (fixS *fixp)
|
||||||
{
|
{
|
||||||
@ -15433,23 +15443,40 @@ mips_force_relocation (fixS *fixp)
|
|||||||
|| fixp->fx_r_type == BFD_RELOC_MICROMIPS_16_PCREL_S1)
|
|| fixp->fx_r_type == BFD_RELOC_MICROMIPS_16_PCREL_S1)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
if (HAVE_NEWABI
|
|
||||||
&& S_GET_SEGMENT (fixp->fx_addsy) == bfd_abs_section_ptr
|
|
||||||
&& (fixp->fx_r_type == BFD_RELOC_MIPS_SUB
|
|
||||||
|| hi16_reloc_p (fixp->fx_r_type)
|
|
||||||
|| lo16_reloc_p (fixp->fx_r_type)))
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Read the instruction associated with RELOC from BUF. */
|
||||||
|
|
||||||
|
static unsigned int
|
||||||
|
read_reloc_insn (char *buf, bfd_reloc_code_real_type reloc)
|
||||||
|
{
|
||||||
|
if (mips16_reloc_p (reloc) || micromips_reloc_p (reloc))
|
||||||
|
return read_compressed_insn (buf, 4);
|
||||||
|
else
|
||||||
|
return read_insn (buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Write instruction INSN to BUF, given that it has been relocated
|
||||||
|
by RELOC. */
|
||||||
|
|
||||||
|
static void
|
||||||
|
write_reloc_insn (char *buf, bfd_reloc_code_real_type reloc,
|
||||||
|
unsigned long insn)
|
||||||
|
{
|
||||||
|
if (mips16_reloc_p (reloc) || micromips_reloc_p (reloc))
|
||||||
|
write_compressed_insn (buf, insn, 4);
|
||||||
|
else
|
||||||
|
write_insn (buf, insn);
|
||||||
|
}
|
||||||
|
|
||||||
/* Apply a fixup to the object file. */
|
/* Apply a fixup to the object file. */
|
||||||
|
|
||||||
void
|
void
|
||||||
md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
|
md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
|
||||||
{
|
{
|
||||||
char *buf;
|
char *buf;
|
||||||
long insn;
|
unsigned long insn;
|
||||||
reloc_howto_type *howto;
|
reloc_howto_type *howto;
|
||||||
|
|
||||||
/* We ignore generic BFD relocations we don't know about. */
|
/* We ignore generic BFD relocations we don't know about. */
|
||||||
@ -15515,6 +15542,12 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
|
|||||||
case BFD_RELOC_MIPS16_TLS_GOTTPREL:
|
case BFD_RELOC_MIPS16_TLS_GOTTPREL:
|
||||||
case BFD_RELOC_MIPS16_TLS_TPREL_HI16:
|
case BFD_RELOC_MIPS16_TLS_TPREL_HI16:
|
||||||
case BFD_RELOC_MIPS16_TLS_TPREL_LO16:
|
case BFD_RELOC_MIPS16_TLS_TPREL_LO16:
|
||||||
|
if (!fixP->fx_addsy)
|
||||||
|
{
|
||||||
|
as_bad_where (fixP->fx_file, fixP->fx_line,
|
||||||
|
_("TLS relocation against a constant"));
|
||||||
|
break;
|
||||||
|
}
|
||||||
S_SET_THREAD_LOCAL (fixP->fx_addsy);
|
S_SET_THREAD_LOCAL (fixP->fx_addsy);
|
||||||
/* fall through */
|
/* fall through */
|
||||||
|
|
||||||
@ -15536,6 +15569,7 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
|
|||||||
case BFD_RELOC_MIPS_JALR:
|
case BFD_RELOC_MIPS_JALR:
|
||||||
case BFD_RELOC_HI16:
|
case BFD_RELOC_HI16:
|
||||||
case BFD_RELOC_HI16_S:
|
case BFD_RELOC_HI16_S:
|
||||||
|
case BFD_RELOC_LO16:
|
||||||
case BFD_RELOC_GPREL16:
|
case BFD_RELOC_GPREL16:
|
||||||
case BFD_RELOC_MIPS_LITERAL:
|
case BFD_RELOC_MIPS_LITERAL:
|
||||||
case BFD_RELOC_MIPS_CALL16:
|
case BFD_RELOC_MIPS_CALL16:
|
||||||
@ -15550,6 +15584,7 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
|
|||||||
case BFD_RELOC_MIPS16_CALL16:
|
case BFD_RELOC_MIPS16_CALL16:
|
||||||
case BFD_RELOC_MIPS16_HI16:
|
case BFD_RELOC_MIPS16_HI16:
|
||||||
case BFD_RELOC_MIPS16_HI16_S:
|
case BFD_RELOC_MIPS16_HI16_S:
|
||||||
|
case BFD_RELOC_MIPS16_LO16:
|
||||||
case BFD_RELOC_MIPS16_JMP:
|
case BFD_RELOC_MIPS16_JMP:
|
||||||
case BFD_RELOC_MICROMIPS_JMP:
|
case BFD_RELOC_MICROMIPS_JMP:
|
||||||
case BFD_RELOC_MICROMIPS_GOT_DISP:
|
case BFD_RELOC_MICROMIPS_GOT_DISP:
|
||||||
@ -15562,6 +15597,7 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
|
|||||||
case BFD_RELOC_MICROMIPS_JALR:
|
case BFD_RELOC_MICROMIPS_JALR:
|
||||||
case BFD_RELOC_MICROMIPS_HI16:
|
case BFD_RELOC_MICROMIPS_HI16:
|
||||||
case BFD_RELOC_MICROMIPS_HI16_S:
|
case BFD_RELOC_MICROMIPS_HI16_S:
|
||||||
|
case BFD_RELOC_MICROMIPS_LO16:
|
||||||
case BFD_RELOC_MICROMIPS_GPREL16:
|
case BFD_RELOC_MICROMIPS_GPREL16:
|
||||||
case BFD_RELOC_MICROMIPS_LITERAL:
|
case BFD_RELOC_MICROMIPS_LITERAL:
|
||||||
case BFD_RELOC_MICROMIPS_CALL16:
|
case BFD_RELOC_MICROMIPS_CALL16:
|
||||||
@ -15570,7 +15606,23 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
|
|||||||
case BFD_RELOC_MICROMIPS_GOT_LO16:
|
case BFD_RELOC_MICROMIPS_GOT_LO16:
|
||||||
case BFD_RELOC_MICROMIPS_CALL_HI16:
|
case BFD_RELOC_MICROMIPS_CALL_HI16:
|
||||||
case BFD_RELOC_MICROMIPS_CALL_LO16:
|
case BFD_RELOC_MICROMIPS_CALL_LO16:
|
||||||
/* Nothing needed to do. The value comes from the reloc entry. */
|
if (fixP->fx_done)
|
||||||
|
{
|
||||||
|
offsetT value;
|
||||||
|
|
||||||
|
if (calculate_reloc (fixP->fx_r_type, *valP, &value))
|
||||||
|
{
|
||||||
|
insn = read_reloc_insn (buf, fixP->fx_r_type);
|
||||||
|
if (mips16_reloc_p (fixP->fx_r_type))
|
||||||
|
insn |= mips16_immed_extend (value, 16);
|
||||||
|
else
|
||||||
|
insn |= (value & 0xffff);
|
||||||
|
write_reloc_insn (buf, fixP->fx_r_type, insn);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
as_bad_where (fixP->fx_file, fixP->fx_line,
|
||||||
|
_("Unsupported constant in relocation"));
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case BFD_RELOC_64:
|
case BFD_RELOC_64:
|
||||||
@ -15604,27 +15656,6 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
|
|||||||
md_number_to_chars (buf, *valP, fixP->fx_size);
|
md_number_to_chars (buf, *valP, fixP->fx_size);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case BFD_RELOC_LO16:
|
|
||||||
case BFD_RELOC_MIPS16_LO16:
|
|
||||||
case BFD_RELOC_MICROMIPS_LO16:
|
|
||||||
/* FIXME: Now that embedded-PIC is gone, some of this code/comment
|
|
||||||
may be safe to remove, but if so it's not obvious. */
|
|
||||||
/* When handling an embedded PIC switch statement, we can wind
|
|
||||||
up deleting a LO16 reloc. See the 'o' case in mips_ip. */
|
|
||||||
if (fixP->fx_done)
|
|
||||||
{
|
|
||||||
if (*valP + 0x8000 > 0xffff)
|
|
||||||
as_bad_where (fixP->fx_file, fixP->fx_line,
|
|
||||||
_("relocation overflow"));
|
|
||||||
/* 32-bit microMIPS instructions are divided into two halfwords.
|
|
||||||
Relocations always refer to the second halfword, regardless
|
|
||||||
of endianness. */
|
|
||||||
if (target_big_endian || fixP->fx_r_type == BFD_RELOC_MICROMIPS_LO16)
|
|
||||||
buf += 2;
|
|
||||||
md_number_to_chars (buf, *valP, 2);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case BFD_RELOC_16_PCREL_S2:
|
case BFD_RELOC_16_PCREL_S2:
|
||||||
if ((*valP & 0x3) != 0)
|
if ((*valP & 0x3) != 0)
|
||||||
as_bad_where (fixP->fx_file, fixP->fx_line,
|
as_bad_where (fixP->fx_file, fixP->fx_line,
|
||||||
|
@ -137,8 +137,6 @@ extern int mips_fix_adjustable (struct fix *);
|
|||||||
#define EXTERN_FORCE_RELOC \
|
#define EXTERN_FORCE_RELOC \
|
||||||
(OUTPUT_FLAVOR == bfd_target_elf_flavour)
|
(OUTPUT_FLAVOR == bfd_target_elf_flavour)
|
||||||
|
|
||||||
/* When generating NEWABI code, we may need to have to keep combined
|
|
||||||
relocations which don't have symbols. */
|
|
||||||
#define TC_FORCE_RELOCATION(FIX) mips_force_relocation (FIX)
|
#define TC_FORCE_RELOCATION(FIX) mips_force_relocation (FIX)
|
||||||
extern int mips_force_relocation (struct fix *);
|
extern int mips_force_relocation (struct fix *);
|
||||||
|
|
||||||
|
@ -1,3 +1,11 @@
|
|||||||
|
2012-09-23 Richard Sandiford <rdsandiford@googlemail.com>
|
||||||
|
|
||||||
|
* gas/mips/elf-rel22.s, gas/mips/elf-rel22.d: Add more tests.
|
||||||
|
* gas/mips/elf-rel29.s, gas/mips/elf-rel29.d,
|
||||||
|
gas/mips/micromips@elf-rel29.d, gas/mips/elf-rel30.s,
|
||||||
|
gas/mips/elf-rel30.l: New tests.
|
||||||
|
* gas/mips/mips.exp: Run them.
|
||||||
|
|
||||||
2012-09-23 Richard Sandiford <rdsandiford@googlemail.com>
|
2012-09-23 Richard Sandiford <rdsandiford@googlemail.com>
|
||||||
|
|
||||||
* gas/mips/dot-1.s, gas/mips/dot-1.d, gas/mips/micromips@dot-1.d,
|
* gas/mips/dot-1.s, gas/mips/dot-1.d, gas/mips/micromips@dot-1.d,
|
||||||
|
@ -7,3 +7,12 @@ Relocation section '\.rela\.text' .*:
|
|||||||
.* R_MIPS_LO16 * 4
|
.* R_MIPS_LO16 * 4
|
||||||
* Type2: R_MIPS_SUB *
|
* Type2: R_MIPS_SUB *
|
||||||
* Type3: R_MIPS_LO16 *
|
* Type3: R_MIPS_LO16 *
|
||||||
|
.* R_MIPS_LO16 * 4
|
||||||
|
* Type2: R_MIPS_SUB *
|
||||||
|
* Type3: R_MIPS_LO16 *
|
||||||
|
.* R_MIPS_GPREL16 * 123456
|
||||||
|
* Type2: R_MIPS_HI16 *
|
||||||
|
* Type3: R_MIPS_NONE *
|
||||||
|
.* R_MIPS_GPREL16 * 234567
|
||||||
|
* Type2: R_MIPS_SUB *
|
||||||
|
* Type3: R_MIPS_LO16 *
|
||||||
|
@ -1,4 +1,9 @@
|
|||||||
|
.eqv early_const,0x123456
|
||||||
lui $4,%lo(%neg(%lo(bar-foo)))
|
lui $4,%lo(%neg(%lo(bar-foo)))
|
||||||
foo:
|
foo:
|
||||||
nop
|
nop
|
||||||
bar:
|
bar:
|
||||||
|
lui $4,%lo(%neg(%lo(bar-foo)))
|
||||||
|
lui $4,%hi(%gp_rel(early_const))
|
||||||
|
lui $4,%lo(%neg(%gp_rel(late_const)))
|
||||||
|
.eqv late_const,0x234567
|
||||||
|
18
gas/testsuite/gas/mips/elf-rel29.d
Normal file
18
gas/testsuite/gas/mips/elf-rel29.d
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
#objdump: -dr --show-raw-insn
|
||||||
|
#as: -64
|
||||||
|
#name: MIPS ELF reloc 29
|
||||||
|
#source: elf-rel29.s
|
||||||
|
|
||||||
|
.*file format.*
|
||||||
|
|
||||||
|
Disassembly .*
|
||||||
|
|
||||||
|
0+0 <foo>:
|
||||||
|
.*: 3c041234 lui a0,0x1234
|
||||||
|
.*: 00042438 dsll a0,a0,0x10
|
||||||
|
.*: 64845679 daddiu a0,a0,22137
|
||||||
|
.*: 00042438 dsll a0,a0,0x10
|
||||||
|
.*: 64849abd daddiu a0,a0,-25923
|
||||||
|
.*: 00042438 dsll a0,a0,0x10
|
||||||
|
.*: 8c84def0 lw a0,-8464\(a0\)
|
||||||
|
#pass
|
12
gas/testsuite/gas/mips/elf-rel29.s
Normal file
12
gas/testsuite/gas/mips/elf-rel29.s
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
.set nomips16
|
||||||
|
.ent foo
|
||||||
|
foo:
|
||||||
|
lui $4,%highest(bar)
|
||||||
|
dsll $4,$4,16
|
||||||
|
daddiu $4,$4,%higher(bar)
|
||||||
|
dsll $4,$4,16
|
||||||
|
daddiu $4,$4,%hi(bar)
|
||||||
|
dsll $4,$4,16
|
||||||
|
lw $4,%lo(bar)($4)
|
||||||
|
.end foo
|
||||||
|
.eqv bar,0x123456789abcdef0
|
37
gas/testsuite/gas/mips/elf-rel30.l
Normal file
37
gas/testsuite/gas/mips/elf-rel30.l
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
.*:
|
||||||
|
.*: Unsupported constant in relocation
|
||||||
|
.*: Unsupported constant in relocation
|
||||||
|
.*: Unsupported constant in relocation
|
||||||
|
.*: Unsupported constant in relocation
|
||||||
|
.*: Unsupported constant in relocation
|
||||||
|
.*: Unsupported constant in relocation
|
||||||
|
.*: Unsupported constant in relocation
|
||||||
|
.*: Unsupported constant in relocation
|
||||||
|
.*: Unsupported constant in relocation
|
||||||
|
.*: Unsupported constant in relocation
|
||||||
|
.*: Unsupported constant in relocation
|
||||||
|
.*: Unsupported constant in relocation
|
||||||
|
.*: Unsupported constant in relocation
|
||||||
|
.*: Unsupported constant in relocation
|
||||||
|
.*: Unsupported constant in relocation
|
||||||
|
.*: Unsupported constant in relocation
|
||||||
|
.*: Unsupported constant in relocation
|
||||||
|
.*: Unsupported constant in relocation
|
||||||
|
.*: Unsupported constant in relocation
|
||||||
|
.*: Unsupported constant in relocation
|
||||||
|
.*: Unsupported constant in relocation
|
||||||
|
.*: Unsupported constant in relocation
|
||||||
|
.*: TLS relocation against a constant
|
||||||
|
.*: TLS relocation against a constant
|
||||||
|
.*: TLS relocation against a constant
|
||||||
|
.*: TLS relocation against a constant
|
||||||
|
.*: TLS relocation against a constant
|
||||||
|
.*: TLS relocation against a constant
|
||||||
|
.*: TLS relocation against a constant
|
||||||
|
.*: TLS relocation against a constant
|
||||||
|
.*: TLS relocation against a constant
|
||||||
|
.*: TLS relocation against a constant
|
||||||
|
.*: TLS relocation against a constant
|
||||||
|
.*: TLS relocation against a constant
|
||||||
|
.*: TLS relocation against a constant
|
||||||
|
.*: TLS relocation against a constant
|
42
gas/testsuite/gas/mips/elf-rel30.s
Normal file
42
gas/testsuite/gas/mips/elf-rel30.s
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
.set nomips16
|
||||||
|
.eqv c1,0x12345678
|
||||||
|
.ent foo
|
||||||
|
foo:
|
||||||
|
lui $4,%call_hi(c1)
|
||||||
|
lui $4,%call_hi(c2)
|
||||||
|
lui $4,%call_lo(c1)
|
||||||
|
lui $4,%call_lo(c2)
|
||||||
|
lui $4,%call16(c1)
|
||||||
|
lui $4,%call16(c2)
|
||||||
|
lui $4,%got_page(c1)
|
||||||
|
lui $4,%got_page(c2)
|
||||||
|
lui $4,%got_disp(c1)
|
||||||
|
lui $4,%got_disp(c2)
|
||||||
|
lui $4,%got_ofst(c1)
|
||||||
|
lui $4,%got_ofst(c2)
|
||||||
|
lui $4,%got_hi(c1)
|
||||||
|
lui $4,%got_hi(c2)
|
||||||
|
lui $4,%got_lo(c1)
|
||||||
|
lui $4,%got_lo(c2)
|
||||||
|
lui $4,%got(c1)
|
||||||
|
lui $4,%got(c2)
|
||||||
|
lui $4,%gp_rel(c1)
|
||||||
|
lui $4,%gp_rel(c2)
|
||||||
|
lui $4,%got(c1)
|
||||||
|
lui $4,%got(c2)
|
||||||
|
lui $4,%tlsgd(c1)
|
||||||
|
lui $4,%tlsgd(c2)
|
||||||
|
lui $4,%tlsldm(c1)
|
||||||
|
lui $4,%tlsldm(c2)
|
||||||
|
lui $4,%dtprel_hi(c1)
|
||||||
|
lui $4,%dtprel_hi(c2)
|
||||||
|
lui $4,%dtprel_lo(c1)
|
||||||
|
lui $4,%dtprel_lo(c2)
|
||||||
|
lui $4,%tprel_hi(c1)
|
||||||
|
lui $4,%tprel_hi(c2)
|
||||||
|
lui $4,%tprel_lo(c1)
|
||||||
|
lui $4,%tprel_lo(c2)
|
||||||
|
lui $4,%gottprel(c1)
|
||||||
|
lui $4,%gottprel(c2)
|
||||||
|
.end foo
|
||||||
|
.eqv c2,0x12345678
|
18
gas/testsuite/gas/mips/micromips@elf-rel29.d
Normal file
18
gas/testsuite/gas/mips/micromips@elf-rel29.d
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
#objdump: -dr --show-raw-insn
|
||||||
|
#as: -64
|
||||||
|
#name: MIPS ELF reloc 29
|
||||||
|
#source: elf-rel29.s
|
||||||
|
|
||||||
|
.*file format.*
|
||||||
|
|
||||||
|
Disassembly .*
|
||||||
|
|
||||||
|
0+0 <foo>:
|
||||||
|
.*: 41a4 1234 lui a0,0x1234
|
||||||
|
.*: 5884 8000 dsll a0,a0,0x10
|
||||||
|
.*: 5c84 5679 daddiu a0,a0,22137
|
||||||
|
.*: 5884 8000 dsll a0,a0,0x10
|
||||||
|
.*: 5c84 9abd daddiu a0,a0,-25923
|
||||||
|
.*: 5884 8000 dsll a0,a0,0x10
|
||||||
|
.*: fc84 def0 lw a0,-8464\(a0\)
|
||||||
|
#pass
|
@ -917,7 +917,9 @@ if { [istarget mips*-*-vxworks*] } {
|
|||||||
if $has_newabi {
|
if $has_newabi {
|
||||||
run_dump_test "elf-rel28-n32"
|
run_dump_test "elf-rel28-n32"
|
||||||
run_dump_test "elf-rel28-n64"
|
run_dump_test "elf-rel28-n64"
|
||||||
|
run_dump_test_arches "elf-rel29" [mips_arch_list_matching mips3]
|
||||||
}
|
}
|
||||||
|
run_list_test_arches "elf-rel30" "-32" [mips_arch_list_all]
|
||||||
|
|
||||||
if { !$no_mips16 } {
|
if { !$no_mips16 } {
|
||||||
run_dump_test "${tmips}mips${el}16-e"
|
run_dump_test "${tmips}mips${el}16-e"
|
||||||
|
Reference in New Issue
Block a user