* tc-mips.c (load_address): Use BFD_RELOC_MIPS_GOT_DISP for newabi.
(macro): Likewise for la. Likewise for ld. (mips_after_parse_args): Make -xgot optional, not the default. (md_apply_fix3): Allow composite relocation to set up gp. (tc_gen_reloc): Allow relaxing for newabi. Relax R_MIPS_CALL16 to R_MIPS_GOT_PAGE/R_MIPS_GOT_OFST if local. Relax R_MIPS_GOT16/R_MIPS_LO16 to R_MIPS_GOT_DISP if local.
This commit is contained in:
parent
dd2e090509
commit
ed6fb7bdf5
|
@ -1,3 +1,13 @@
|
||||||
|
2002-09-17 Stan Cox <scox@redhat.com>
|
||||||
|
|
||||||
|
* tc-mips.c (load_address): Use BFD_RELOC_MIPS_GOT_DISP for newabi.
|
||||||
|
(macro): Likewise for la. Likewise for ld.
|
||||||
|
(mips_after_parse_args): Make -xgot optional, not the default.
|
||||||
|
(md_apply_fix3): Allow composite relocation to set up gp.
|
||||||
|
(tc_gen_reloc): Allow relaxing for newabi.
|
||||||
|
Relax R_MIPS_CALL16 to R_MIPS_GOT_PAGE/R_MIPS_GOT_OFST if local.
|
||||||
|
Relax R_MIPS_GOT16/R_MIPS_LO16 to R_MIPS_GOT_DISP if local.
|
||||||
|
|
||||||
2002-09-17 Nick Clifton <nickc@redhat.com>
|
2002-09-17 Nick Clifton <nickc@redhat.com>
|
||||||
|
|
||||||
* config/tc-arm.c (md_apply_fix3): Note that an implemented
|
* config/tc-arm.c (md_apply_fix3): Note that an implemented
|
||||||
|
|
|
@ -1836,6 +1836,7 @@ append_insn (place, ip, address_expr, reloc_type, unmatched_hi)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case BFD_RELOC_LO16:
|
case BFD_RELOC_LO16:
|
||||||
|
case BFD_RELOC_MIPS_GOT_DISP:
|
||||||
ip->insn_opcode |= address_expr->X_add_number & 0xffff;
|
ip->insn_opcode |= address_expr->X_add_number & 0xffff;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -3587,10 +3588,20 @@ load_address (counter, reg, ep, used_at)
|
||||||
lw $reg,<sym>($gp) (BFD_RELOC_MIPS_GOT16)
|
lw $reg,<sym>($gp) (BFD_RELOC_MIPS_GOT16)
|
||||||
nop
|
nop
|
||||||
addiu $reg,$reg,<sym> (BFD_RELOC_LO16)
|
addiu $reg,$reg,<sym> (BFD_RELOC_LO16)
|
||||||
|
If we have NewABI, we want
|
||||||
|
lw $reg,<sym>($gp) (BFD_RELOC_MIPS_GOT_DISP)
|
||||||
If there is a constant, it must be added in after. */
|
If there is a constant, it must be added in after. */
|
||||||
ex.X_add_number = ep->X_add_number;
|
ex.X_add_number = ep->X_add_number;
|
||||||
ep->X_add_number = 0;
|
ep->X_add_number = 0;
|
||||||
frag_grow (20);
|
frag_grow (20);
|
||||||
|
if (HAVE_NEWABI)
|
||||||
|
{
|
||||||
|
macro_build ((char *) NULL, counter, ep,
|
||||||
|
HAVE_32BIT_ADDRESSES ? "lw" : "ld", "t,o(b)", reg,
|
||||||
|
(int) BFD_RELOC_MIPS_GOT_DISP, mips_gp_register);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
macro_build ((char *) NULL, counter, ep,
|
macro_build ((char *) NULL, counter, ep,
|
||||||
HAVE_32BIT_ADDRESSES ? "lw" : "ld", "t,o(b)",
|
HAVE_32BIT_ADDRESSES ? "lw" : "ld", "t,o(b)",
|
||||||
reg, (int) BFD_RELOC_MIPS_GOT16, mips_gp_register);
|
reg, (int) BFD_RELOC_MIPS_GOT16, mips_gp_register);
|
||||||
|
@ -3601,6 +3612,8 @@ load_address (counter, reg, ep, used_at)
|
||||||
macro_build (p, counter, ep,
|
macro_build (p, counter, ep,
|
||||||
HAVE_32BIT_ADDRESSES ? "addiu" : "daddiu",
|
HAVE_32BIT_ADDRESSES ? "addiu" : "daddiu",
|
||||||
"t,r,j", reg, reg, (int) BFD_RELOC_LO16);
|
"t,r,j", reg, reg, (int) BFD_RELOC_LO16);
|
||||||
|
}
|
||||||
|
|
||||||
if (ex.X_add_number != 0)
|
if (ex.X_add_number != 0)
|
||||||
{
|
{
|
||||||
if (ex.X_add_number < -0x8000 || ex.X_add_number >= 0x8000)
|
if (ex.X_add_number < -0x8000 || ex.X_add_number >= 0x8000)
|
||||||
|
@ -4632,12 +4645,23 @@ macro (ip)
|
||||||
addu $tempreg,$tempreg,$at
|
addu $tempreg,$tempreg,$at
|
||||||
For a local symbol, we want the same instruction
|
For a local symbol, we want the same instruction
|
||||||
sequence, but we output a BFD_RELOC_LO16 reloc on the
|
sequence, but we output a BFD_RELOC_LO16 reloc on the
|
||||||
addiu instruction. */
|
addiu instruction.
|
||||||
|
|
||||||
|
For NewABI, we want for local or external data addresses
|
||||||
|
lw $tempreg,<sym>($gp) (BFD_RELOC_MIPS_GOT_DISP)
|
||||||
|
For a local function symbol, we want
|
||||||
|
lw $tempreg,<sym>($gp) (BFD_RELOC_MIPS_GOT_PAGE)
|
||||||
|
nop
|
||||||
|
addiu $tempreg,$tempreg,<sym> (BFD_RELOC_MIPS_GOT_OFST)
|
||||||
|
*/
|
||||||
|
|
||||||
expr1.X_add_number = offset_expr.X_add_number;
|
expr1.X_add_number = offset_expr.X_add_number;
|
||||||
offset_expr.X_add_number = 0;
|
offset_expr.X_add_number = 0;
|
||||||
frag_grow (32);
|
frag_grow (32);
|
||||||
if (expr1.X_add_number == 0 && tempreg == PIC_CALL_REG)
|
if (expr1.X_add_number == 0 && tempreg == PIC_CALL_REG)
|
||||||
lw_reloc_type = (int) BFD_RELOC_MIPS_CALL16;
|
lw_reloc_type = (int) BFD_RELOC_MIPS_CALL16;
|
||||||
|
else if (HAVE_NEWABI)
|
||||||
|
lw_reloc_type = (int) BFD_RELOC_MIPS_GOT_DISP;
|
||||||
macro_build ((char *) NULL, &icnt, &offset_expr,
|
macro_build ((char *) NULL, &icnt, &offset_expr,
|
||||||
HAVE_32BIT_ADDRESSES ? "lw" : "ld",
|
HAVE_32BIT_ADDRESSES ? "lw" : "ld",
|
||||||
"t,o(b)", tempreg, lw_reloc_type, mips_gp_register);
|
"t,o(b)", tempreg, lw_reloc_type, mips_gp_register);
|
||||||
|
@ -4737,6 +4761,7 @@ macro (ip)
|
||||||
char *p;
|
char *p;
|
||||||
int lui_reloc_type = (int) BFD_RELOC_MIPS_GOT_HI16;
|
int lui_reloc_type = (int) BFD_RELOC_MIPS_GOT_HI16;
|
||||||
int lw_reloc_type = (int) BFD_RELOC_MIPS_GOT_LO16;
|
int lw_reloc_type = (int) BFD_RELOC_MIPS_GOT_LO16;
|
||||||
|
int local_reloc_type = (int) BFD_RELOC_MIPS_GOT16;
|
||||||
|
|
||||||
/* This is the large GOT case. If this is a reference to an
|
/* This is the large GOT case. If this is a reference to an
|
||||||
external symbol, and there is no constant, we want
|
external symbol, and there is no constant, we want
|
||||||
|
@ -4778,31 +4803,10 @@ macro (ip)
|
||||||
addiu $at,$at,<loconstant> (BFD_RELOC_LO16)
|
addiu $at,$at,<loconstant> (BFD_RELOC_LO16)
|
||||||
addu $tempreg,$tempreg,$at
|
addu $tempreg,$tempreg,$at
|
||||||
|
|
||||||
For NewABI, we want for data addresses
|
For NewABI, we want for local data addresses
|
||||||
lw $tempreg,<sym>($gp) (BFD_RELOC_MIPS_GOT_DISP)
|
lw $tempreg,<sym>($gp) (BFD_RELOC_MIPS_GOT_DISP)
|
||||||
If tempreg is PIC_CALL_REG pointing to a external symbol, we want
|
|
||||||
lw $tempreg,<sym>($gp) (BFD_RELOC_MIPS_CALL16)
|
|
||||||
*/
|
*/
|
||||||
if (HAVE_NEWABI)
|
|
||||||
{
|
|
||||||
int reloc_type = (tempreg == PIC_CALL_REG
|
|
||||||
? BFD_RELOC_MIPS_CALL16
|
|
||||||
: BFD_RELOC_MIPS_GOT_DISP);
|
|
||||||
|
|
||||||
macro_build ((char *) NULL, &icnt, &offset_expr,
|
|
||||||
HAVE_32BIT_ADDRESSES ? "lw" : "ld",
|
|
||||||
"t,o(b)", tempreg, reloc_type, mips_gp_register);
|
|
||||||
|
|
||||||
if (breg != 0)
|
|
||||||
macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
|
|
||||||
HAVE_32BIT_ADDRESSES ? "addu" : "daddu",
|
|
||||||
"d,v,t", treg, tempreg, breg);
|
|
||||||
|
|
||||||
if (! used_at)
|
|
||||||
return;
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
expr1.X_add_number = offset_expr.X_add_number;
|
expr1.X_add_number = offset_expr.X_add_number;
|
||||||
offset_expr.X_add_number = 0;
|
offset_expr.X_add_number = 0;
|
||||||
frag_grow (52);
|
frag_grow (52);
|
||||||
|
@ -4923,11 +4927,20 @@ macro (ip)
|
||||||
macro_build (p, &icnt, (expressionS *) NULL, "nop", "");
|
macro_build (p, &icnt, (expressionS *) NULL, "nop", "");
|
||||||
p += 4;
|
p += 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (HAVE_NEWABI)
|
||||||
|
local_reloc_type = (int) BFD_RELOC_MIPS_GOT_DISP;
|
||||||
macro_build (p, &icnt, &offset_expr,
|
macro_build (p, &icnt, &offset_expr,
|
||||||
HAVE_32BIT_ADDRESSES ? "lw" : "ld",
|
HAVE_32BIT_ADDRESSES ? "lw" : "ld",
|
||||||
"t,o(b)", tempreg, (int) BFD_RELOC_MIPS_GOT16,
|
"t,o(b)", tempreg,
|
||||||
|
local_reloc_type,
|
||||||
mips_gp_register);
|
mips_gp_register);
|
||||||
p += 4;
|
p += 4;
|
||||||
|
if (expr1.X_add_number == 0 && HAVE_NEWABI)
|
||||||
|
{
|
||||||
|
/* BFD_RELOC_MIPS_GOT_DISP is sufficient for newabi */
|
||||||
|
}
|
||||||
|
else
|
||||||
if (expr1.X_add_number >= -0x8000
|
if (expr1.X_add_number >= -0x8000
|
||||||
&& expr1.X_add_number < 0x8000)
|
&& expr1.X_add_number < 0x8000)
|
||||||
{
|
{
|
||||||
|
@ -5599,6 +5612,7 @@ macro (ip)
|
||||||
else if (mips_pic == SVR4_PIC && ! mips_big_got)
|
else if (mips_pic == SVR4_PIC && ! mips_big_got)
|
||||||
{
|
{
|
||||||
char *p;
|
char *p;
|
||||||
|
int lw_reloc_type = (int) BFD_RELOC_MIPS_GOT16;
|
||||||
|
|
||||||
/* If this is a reference to an external symbol, we want
|
/* If this is a reference to an external symbol, we want
|
||||||
lw $tempreg,<sym>($gp) (BFD_RELOC_MIPS_GOT16)
|
lw $tempreg,<sym>($gp) (BFD_RELOC_MIPS_GOT16)
|
||||||
|
@ -5609,6 +5623,8 @@ macro (ip)
|
||||||
nop
|
nop
|
||||||
addiu $tempreg,$tempreg,<sym> (BFD_RELOC_LO16)
|
addiu $tempreg,$tempreg,<sym> (BFD_RELOC_LO16)
|
||||||
<op> $treg,0($tempreg)
|
<op> $treg,0($tempreg)
|
||||||
|
If we have NewABI, we want
|
||||||
|
lw $reg,<sym>($gp) (BFD_RELOC_MIPS_GOT_DISP)
|
||||||
If there is a base register, we add it to $tempreg before
|
If there is a base register, we add it to $tempreg before
|
||||||
the <op>. If there is a constant, we stick it in the
|
the <op>. If there is a constant, we stick it in the
|
||||||
<op> instruction. We don't handle constants larger than
|
<op> instruction. We don't handle constants larger than
|
||||||
|
@ -5618,13 +5634,15 @@ macro (ip)
|
||||||
assert (offset_expr.X_op == O_symbol);
|
assert (offset_expr.X_op == O_symbol);
|
||||||
expr1.X_add_number = offset_expr.X_add_number;
|
expr1.X_add_number = offset_expr.X_add_number;
|
||||||
offset_expr.X_add_number = 0;
|
offset_expr.X_add_number = 0;
|
||||||
|
if (HAVE_NEWABI)
|
||||||
|
lw_reloc_type = (int) BFD_RELOC_MIPS_GOT_DISP;
|
||||||
if (expr1.X_add_number < -0x8000
|
if (expr1.X_add_number < -0x8000
|
||||||
|| expr1.X_add_number >= 0x8000)
|
|| expr1.X_add_number >= 0x8000)
|
||||||
as_bad (_("PIC code offset overflow (max 16 signed bits)"));
|
as_bad (_("PIC code offset overflow (max 16 signed bits)"));
|
||||||
frag_grow (20);
|
frag_grow (20);
|
||||||
macro_build ((char *) NULL, &icnt, &offset_expr,
|
macro_build ((char *) NULL, &icnt, &offset_expr,
|
||||||
HAVE_32BIT_ADDRESSES ? "lw" : "ld", "t,o(b)", tempreg,
|
HAVE_32BIT_ADDRESSES ? "lw" : "ld", "t,o(b)", tempreg,
|
||||||
(int) BFD_RELOC_MIPS_GOT16, mips_gp_register);
|
(int) lw_reloc_type, mips_gp_register);
|
||||||
macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "nop", "");
|
macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "nop", "");
|
||||||
p = frag_var (rs_machine_dependent, 4, 0,
|
p = frag_var (rs_machine_dependent, 4, 0,
|
||||||
RELAX_ENCODE (0, 4, -8, 0, 0, 0),
|
RELAX_ENCODE (0, 4, -8, 0, 0, 0),
|
||||||
|
@ -10420,9 +10438,6 @@ mips_after_parse_args ()
|
||||||
mips_opts.gp32 = file_mips_gp32;
|
mips_opts.gp32 = file_mips_gp32;
|
||||||
mips_opts.fp32 = file_mips_fp32;
|
mips_opts.fp32 = file_mips_fp32;
|
||||||
|
|
||||||
if (HAVE_NEWABI)
|
|
||||||
mips_big_got = 1;
|
|
||||||
|
|
||||||
if (mips_flag_mdebug < 0)
|
if (mips_flag_mdebug < 0)
|
||||||
{
|
{
|
||||||
#ifdef OBJ_MAYBE_ECOFF
|
#ifdef OBJ_MAYBE_ECOFF
|
||||||
|
@ -10644,6 +10659,7 @@ md_apply_fix3 (fixP, valP, seg)
|
||||||
bfd_byte *buf;
|
bfd_byte *buf;
|
||||||
long insn;
|
long insn;
|
||||||
valueT value;
|
valueT value;
|
||||||
|
static int previous_fx_r_type = 0;
|
||||||
|
|
||||||
assert (fixP->fx_size == 4
|
assert (fixP->fx_size == 4
|
||||||
|| fixP->fx_r_type == BFD_RELOC_16
|
|| fixP->fx_r_type == BFD_RELOC_16
|
||||||
|
@ -10743,8 +10759,14 @@ md_apply_fix3 (fixP, valP, seg)
|
||||||
|
|
||||||
fixP->fx_addnumber = value; /* Remember value for tc_gen_reloc. */
|
fixP->fx_addnumber = value; /* Remember value for tc_gen_reloc. */
|
||||||
|
|
||||||
if (fixP->fx_addsy == NULL && ! fixP->fx_pcrel)
|
/* We are not done if this is a composite relocation to set up gp. */
|
||||||
|
if (fixP->fx_addsy == NULL && ! fixP->fx_pcrel
|
||||||
|
&& !(fixP->fx_r_type == BFD_RELOC_MIPS_SUB
|
||||||
|
|| (previous_fx_r_type == BFD_RELOC_MIPS_SUB
|
||||||
|
&& (fixP->fx_r_type == BFD_RELOC_HI16_S
|
||||||
|
|| fixP->fx_r_type == BFD_RELOC_LO16))))
|
||||||
fixP->fx_done = 1;
|
fixP->fx_done = 1;
|
||||||
|
previous_fx_r_type = fixP->fx_r_type;
|
||||||
|
|
||||||
switch (fixP->fx_r_type)
|
switch (fixP->fx_r_type)
|
||||||
{
|
{
|
||||||
|
@ -12638,14 +12660,15 @@ tc_gen_reloc (section, fixp)
|
||||||
/* If this is a variant frag, we may need to adjust the existing
|
/* If this is a variant frag, we may need to adjust the existing
|
||||||
reloc and generate a new one. */
|
reloc and generate a new one. */
|
||||||
if (fixp->fx_frag->fr_opcode != NULL
|
if (fixp->fx_frag->fr_opcode != NULL
|
||||||
&& (fixp->fx_r_type == BFD_RELOC_GPREL16
|
&& ((fixp->fx_r_type == BFD_RELOC_GPREL16
|
||||||
|
&& ! HAVE_NEWABI)
|
||||||
|| fixp->fx_r_type == BFD_RELOC_MIPS_GOT16
|
|| fixp->fx_r_type == BFD_RELOC_MIPS_GOT16
|
||||||
|| fixp->fx_r_type == BFD_RELOC_MIPS_CALL16
|
|| fixp->fx_r_type == BFD_RELOC_MIPS_CALL16
|
||||||
|| fixp->fx_r_type == BFD_RELOC_MIPS_GOT_HI16
|
|| fixp->fx_r_type == BFD_RELOC_MIPS_GOT_HI16
|
||||||
|| fixp->fx_r_type == BFD_RELOC_MIPS_GOT_LO16
|
|| fixp->fx_r_type == BFD_RELOC_MIPS_GOT_LO16
|
||||||
|| fixp->fx_r_type == BFD_RELOC_MIPS_CALL_HI16
|
|| fixp->fx_r_type == BFD_RELOC_MIPS_CALL_HI16
|
||||||
|| fixp->fx_r_type == BFD_RELOC_MIPS_CALL_LO16)
|
|| fixp->fx_r_type == BFD_RELOC_MIPS_CALL_LO16)
|
||||||
&& ! HAVE_NEWABI)
|
)
|
||||||
{
|
{
|
||||||
arelent *reloc2;
|
arelent *reloc2;
|
||||||
|
|
||||||
|
@ -12706,15 +12729,32 @@ tc_gen_reloc (section, fixp)
|
||||||
abort ();
|
abort ();
|
||||||
case BFD_RELOC_MIPS_GOT16:
|
case BFD_RELOC_MIPS_GOT16:
|
||||||
break;
|
break;
|
||||||
case BFD_RELOC_MIPS_CALL16:
|
|
||||||
case BFD_RELOC_MIPS_GOT_LO16:
|
case BFD_RELOC_MIPS_GOT_LO16:
|
||||||
case BFD_RELOC_MIPS_CALL_LO16:
|
case BFD_RELOC_MIPS_CALL_LO16:
|
||||||
fixp->fx_r_type = BFD_RELOC_MIPS_GOT16;
|
fixp->fx_r_type = BFD_RELOC_MIPS_GOT16;
|
||||||
break;
|
break;
|
||||||
|
case BFD_RELOC_MIPS_CALL16:
|
||||||
|
if (HAVE_NEWABI)
|
||||||
|
{
|
||||||
|
/* BFD_RELOC_MIPS_GOT16;*/
|
||||||
|
fixp->fx_r_type = BFD_RELOC_MIPS_GOT_PAGE;
|
||||||
|
reloc2->howto = bfd_reloc_type_lookup
|
||||||
|
(stdoutput, BFD_RELOC_MIPS_GOT_OFST);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
fixp->fx_r_type = BFD_RELOC_MIPS_GOT16;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
abort ();
|
abort ();
|
||||||
|
|
||||||
|
/* newabi uses R_MIPS_GOT_DISP for local symbols */
|
||||||
|
if (HAVE_NEWABI && BFD_RELOC_MIPS_GOT_LO16)
|
||||||
|
{
|
||||||
|
fixp->fx_r_type = BFD_RELOC_MIPS_GOT_DISP;
|
||||||
|
retval[1] = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Since the old MIPS ELF ABI uses Rel instead of Rela, encode the vtable
|
/* Since the old MIPS ELF ABI uses Rel instead of Rela, encode the vtable
|
||||||
|
|
Loading…
Reference in New Issue