This is the mail archive of the
binutils@sources.redhat.com
mailing list for the binutils project.
[PATCH] MIPS gas: irix relocation tweaks
- From: Stan Cox <scox at redhat dot com>
- To: binutils at sources dot redhat dot com
- Date: 09 Sep 2002 23:52:03 -0400
- Subject: [PATCH] MIPS gas: irix relocation tweaks
- Organization: Red Hat, RDU, NC
This patch changes gas so it creates relocations that are more like those of
Irix for the Newabi. The primary differences are:
1. use R_MIPS_GOT_DISP for internal and external symbols
2. use R_MIPS_GOT_PAGE/R_MIPS_GOT_OFFSET for internal function symbols
3. make -xgot optional and not the default
Tested on Irix and mips-elf.
* 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.
Index: config/tc-mips.c
===================================================================
RCS file: /cvs/uberbaum/gas/config/tc-mips.c,v
retrieving revision 1.162
diff -u -2 -p -r1.162 tc-mips.c
--- config/tc-mips.c 5 Sep 2002 00:01:18 -0000 1.162
+++ config/tc-mips.c 10 Sep 2002 03:15:11 -0000
@@ -1835,4 +1835,5 @@ append_insn (place, ip, address_expr, re
case BFD_RELOC_LO16:
+ case BFD_RELOC_MIPS_GOT_DISP:
ip->insn_opcode |= address_expr->X_add_number & 0xffff;
break;
@@ -3586,18 +3587,30 @@ load_address (counter, reg, ep, used_at)
nop
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. */
ex.X_add_number = ep->X_add_number;
ep->X_add_number = 0;
frag_grow (20);
- macro_build ((char *) NULL, counter, ep,
- HAVE_32BIT_ADDRESSES ? "lw" : "ld", "t,o(b)",
- reg, (int) BFD_RELOC_MIPS_GOT16, mips_gp_register);
- macro_build ((char *) NULL, counter, (expressionS *) NULL, "nop", "");
- p = frag_var (rs_machine_dependent, 4, 0,
- RELAX_ENCODE (0, 4, -8, 0, 0, mips_opts.warn_about_macros),
- ep->X_add_symbol, (offsetT) 0, (char *) NULL);
- macro_build (p, counter, ep,
- HAVE_32BIT_ADDRESSES ? "addiu" : "daddiu",
- "t,r,j", reg, reg, (int) BFD_RELOC_LO16);
+ 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,
+ HAVE_32BIT_ADDRESSES ? "lw" : "ld", "t,o(b)",
+ reg, (int) BFD_RELOC_MIPS_GOT16, mips_gp_register);
+ macro_build ((char *) NULL, counter, (expressionS *) NULL, "nop", "");
+ p = frag_var (rs_machine_dependent, 4, 0,
+ RELAX_ENCODE (0, 4, -8, 0, 0, mips_opts.warn_about_macros),
+ ep->X_add_symbol, (offsetT) 0, (char *) NULL);
+ macro_build (p, counter, ep,
+ HAVE_32BIT_ADDRESSES ? "addiu" : "daddiu",
+ "t,r,j", reg, reg, (int) BFD_RELOC_LO16);
+ }
+
if (ex.X_add_number != 0)
{
@@ -4631,5 +4644,14 @@ macro (ip)
For a local symbol, we want the same instruction
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;
offset_expr.X_add_number = 0;
@@ -4637,4 +4659,6 @@ macro (ip)
if (expr1.X_add_number == 0 && tempreg == PIC_CALL_REG)
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,
HAVE_32BIT_ADDRESSES ? "lw" : "ld",
@@ -4736,4 +4760,5 @@ macro (ip)
int lui_reloc_type = (int) BFD_RELOC_MIPS_GOT_HI16;
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
@@ -4777,29 +4802,8 @@ macro (ip)
addu $tempreg,$tempreg,$at
- For NewABI, we want for data addresses
- 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)
+ For NewABI, we want for local data addresses
+ lw $tempreg,<sym>($gp) (BFD_RELOC_MIPS_GOT_DISP)
*/
- 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;
offset_expr.X_add_number = 0;
@@ -4814,4 +4818,5 @@ macro (ip)
lw_reloc_type = (int) BFD_RELOC_MIPS_CALL_LO16;
}
+
macro_build ((char *) NULL, &icnt, &offset_expr, "lui", "t,u",
tempreg, lui_reloc_type);
@@ -4922,10 +4927,19 @@ macro (ip)
p += 4;
}
+
+ if (HAVE_NEWABI)
+ local_reloc_type = (int) BFD_RELOC_MIPS_GOT_DISP;
macro_build (p, &icnt, &offset_expr,
HAVE_32BIT_ADDRESSES ? "lw" : "ld",
- "t,o(b)", tempreg, (int) BFD_RELOC_MIPS_GOT16,
+ "t,o(b)", tempreg,
+ local_reloc_type,
mips_gp_register);
p += 4;
- if (expr1.X_add_number >= -0x8000
+ if (expr1.X_add_number == 0 && HAVE_NEWABI)
+ {
+ /* BFD_RELOC_MIPS_GOT_DISP is sufficient for newabi */
+ }
+ else
+ if (expr1.X_add_number >= -0x8000
&& expr1.X_add_number < 0x8000)
{
@@ -5598,4 +5612,5 @@ macro (ip)
{
char *p;
+ int lw_reloc_type = (int) BFD_RELOC_MIPS_GOT16;
/* If this is a reference to an external symbol, we want
@@ -5603,9 +5618,6 @@ macro (ip)
nop
<op> $treg,0($tempreg)
- Otherwise we want
- lw $tempreg,<sym>($gp) (BFD_RELOC_MIPS_GOT16)
- nop
- addiu $tempreg,$tempreg,<sym> (BFD_RELOC_LO16)
- <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
the <op>. If there is a constant, we stick it in the
@@ -5617,4 +5629,6 @@ macro (ip)
expr1.X_add_number = offset_expr.X_add_number;
offset_expr.X_add_number = 0;
+ if (HAVE_NEWABI)
+ lw_reloc_type = (int) BFD_RELOC_MIPS_GOT_DISP;
if (expr1.X_add_number < -0x8000
|| expr1.X_add_number >= 0x8000)
@@ -5623,5 +5637,5 @@ macro (ip)
macro_build ((char *) NULL, &icnt, &offset_expr,
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", "");
p = frag_var (rs_machine_dependent, 4, 0,
@@ -5668,4 +5682,5 @@ macro (ip)
expr1.X_add_number = offset_expr.X_add_number;
offset_expr.X_add_number = 0;
+
if (expr1.X_add_number < -0x8000
|| expr1.X_add_number >= 0x8000)
@@ -5715,4 +5730,5 @@ macro (ip)
p += 4;
}
+
macro_build (p, &icnt, &offset_expr,
HAVE_32BIT_ADDRESSES ? "lw" : "ld",
@@ -10419,7 +10435,4 @@ mips_after_parse_args ()
mips_opts.fp32 = file_mips_fp32;
- if (HAVE_NEWABI)
- mips_big_got = 1;
-
if (mips_flag_mdebug < 0)
{
@@ -10643,4 +10656,5 @@ md_apply_fix3 (fixP, valP, seg)
long insn;
valueT value;
+ static int previous_fx_r_type = 0;
assert (fixP->fx_size == 4
@@ -10742,6 +10756,12 @@ md_apply_fix3 (fixP, valP, seg)
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;
+ previous_fx_r_type = fixP->fx_r_type;
switch (fixP->fx_r_type)
@@ -12636,5 +12656,6 @@ tc_gen_reloc (section, fixp)
reloc and generate a new one. */
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_CALL16
@@ -12643,5 +12664,5 @@ tc_gen_reloc (section, fixp)
|| fixp->fx_r_type == BFD_RELOC_MIPS_CALL_HI16
|| fixp->fx_r_type == BFD_RELOC_MIPS_CALL_LO16)
- && ! HAVE_NEWABI)
+ )
{
arelent *reloc2;
@@ -12704,13 +12735,30 @@ tc_gen_reloc (section, fixp)
case BFD_RELOC_MIPS_GOT16:
break;
- case BFD_RELOC_MIPS_CALL16:
case BFD_RELOC_MIPS_GOT_LO16:
case BFD_RELOC_MIPS_CALL_LO16:
fixp->fx_r_type = BFD_RELOC_MIPS_GOT16;
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
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;
+ }
}