[patch] MIPS gas problems with gcc's explicit relocs
Maciej W. Rozycki
macro@ds2.pg.gda.pl
Fri May 28 19:00:00 GMT 2004
Hello,
The recent addition of explicit relocation generation to gcc triggered
failures for inline assembly under certain conditions. Example: given the
following program:
$ cat dlac.c
extern void *foo;
void *bar(void)
{
void *result;
asm("dla\t%0,%1" : "=r" (result) : "m" (foo));
return result;
}
I get:
$ mips64el-linux-gcc -mno-abicalls -S -o dlac.s dlac.c
$ cat dlac.s
.file 1 "dlac.c"
.section .mdebug.abi64
.previous
.text
.align 2
.align 2
.globl bar
.ent bar
.type bar, @function
bar:
.frame $fp,32,$31 # vars= 16, regs= 1/0, args= 0, gp= 0
.mask 0x40000000,-16
.fmask 0x00000000,0
daddiu $sp,$sp,-32
sd $fp,16($sp)
move $fp,$sp
lui $2,%highest(foo)
daddiu $2,$2,%higher(foo)
dsll $2,$2,16
daddiu $2,$2,%hi(foo)
dsll $2,$2,16
#APP
dla $2,%lo(foo)($2)
#NO_APP
sd $2,0($fp)
ld $2,0($fp)
move $sp,$fp
ld $fp,16($sp)
daddiu $sp,$sp,32
j $31
.end bar
.ident "GCC: (GNU) 3.5.0 20040522 (experimental)"
which fails to be assembled by gas due to a reloc operator used in the
second operand of "dla":
$ mips64el-linux-gcc -mno-abicalls -c -o dlac.o dlac.s
dlac.s: Assembler messages:
dlac.s:23: Error: bad expression
dlac.s:23: Error: illegal operands `dla'
Here's a patch that adds handling of such reloc operators to "la" and
related macros, implementing the expected behavior. The above program
gets assembled to:
$ mips64el-linux-objdump -Sr dlac.o
dlac.o: file format elf64-tradlittlemips
Disassembly of section .text:
0000000000000000 <bar>:
0: 67bdffe0 daddiu sp,sp,-32
4: ffbe0010 sd s8,16(sp)
8: 03a0f02d move s8,sp
c: 3c020000 lui v0,0x0
c: R_MIPS_HIGHEST foo
c: R_MIPS_NONE *ABS*
c: R_MIPS_NONE *ABS*
10: 64420000 daddiu v0,v0,0
10: R_MIPS_HIGHER foo
10: R_MIPS_NONE *ABS*
10: R_MIPS_NONE *ABS*
14: 00021438 dsll v0,v0,0x10
18: 64420000 daddiu v0,v0,0
18: R_MIPS_HI16 foo
18: R_MIPS_NONE *ABS*
18: R_MIPS_NONE *ABS*
1c: 00021438 dsll v0,v0,0x10
20: 64420000 daddiu v0,v0,0
20: R_MIPS_LO16 foo
20: R_MIPS_NONE *ABS*
20: R_MIPS_NONE *ABS*
24: ffc20000 sd v0,0(s8)
28: dfc20000 ld v0,0(s8)
2c: 03c0e82d move sp,s8
30: dfbe0010 ld s8,16(sp)
34: 03e00008 jr ra
38: 67bd0020 daddiu sp,sp,32
3c: 00000000 nop
gas/ChangeLog:
2004-05-28 Maciej W. Rozycki <macro@ds2.pg.gda.pl>
* config/tc-mips.c (append_insn): Handle constant expressions with
no associated relocation.
(macro): Handle reloc operators in operands of load address
macros.
(mips_ip): Cancel the expression after use for the Q format
specifier.
(parse_relocation): Return no relocation for unsupported
operators.
(my_getSmallExpression): Return no relocation if no relocation
operators are used.
gas/testsuite/ChangeLog:
2004-05-28 Maciej W. Rozycki <macro@ds2.pg.gda.pl>
* gas/mips/elf-rel20.d: New test for reloc operators with "la".
* gas/mips/elf-rel20.s: Source for the new test.
* gas/mips/mips.exp: Run the new test.
opcodes/ChangeLog:
2004-05-28 Maciej W. Rozycki <macro@ds2.pg.gda.pl>
* mips-opc.c (mips_builtin_opcodes): Handle reloc operators in
operands of load address macros.
A few notes:
1. I handle "dla", "dlca", "la" and "lca" the same way for symmetry and
simplicity. The reloc used overrides the macro name for GOT vs CALL
relocations. I see no point in making it more complicated. Ditto about
reloc operators of a dubious use here -- they're all handled as with
load/store instructions.
2. I feel the changes to use BFD_RELOC_UNUSED when no relocation is to be
used are the Right Thing -- I see no point in pretending a BFD_RELOC_LO16
relocation was used. The change appears safe, except a small bug had to
be corrected in MDMX support code.
3. The change was tested for the mips64el-linux target -- no regressions
in the testsuite. A testcase is included.
OK to apply?
Maciej
--
+ Maciej W. Rozycki, Technical University of Gdansk, Poland +
+--------------------------------------------------------------+
+ e-mail: macro@ds2.pg.gda.pl, PGP key available +
binutils-2.15.91-20040527-mips-la-reloc.patch
diff -up --recursive --new-file binutils-2.15.91-20040527.macro/gas/config/tc-mips.c binutils-2.15.91-20040527/gas/config/tc-mips.c
--- binutils-2.15.91-20040527.macro/gas/config/tc-mips.c 2004-05-21 03:25:26.000000000 +0000
+++ binutils-2.15.91-20040527/gas/config/tc-mips.c 2004-05-28 14:38:52.000000000 +0000
@@ -2079,7 +2079,7 @@ append_insn (struct mips_cl_insn *ip, ex
}
fixp[0] = fixp[1] = fixp[2] = NULL;
- if (address_expr != NULL && *reloc_type < BFD_RELOC_UNUSED)
+ if (address_expr != NULL)
{
if (address_expr->X_op == O_constant)
{
@@ -2112,6 +2112,7 @@ append_insn (struct mips_cl_insn *ip, ex
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;
@@ -2147,7 +2148,7 @@ append_insn (struct mips_cl_insn *ip, ex
internalError ();
}
}
- else
+ else if (*reloc_type < BFD_RELOC_UNUSED)
need_reloc:
{
reloc_howto_type *howto;
@@ -4869,6 +4870,15 @@ macro (struct mips_cl_insn *ip)
return;
}
+ if (offset_expr.X_op == O_symbol
+ && *offset_reloc != BFD_RELOC_UNUSED)
+ {
+ macro_build (&offset_expr,
+ (dbl || HAVE_64BIT_ADDRESSES) ? "daddiu" : "addiu",
+ "t,r,j", treg, sreg, *offset_reloc);
+ return;
+ }
+
if (treg == breg)
{
tempreg = AT;
@@ -8596,6 +8606,7 @@ do_msbd:
ip->insn_opcode |= (imm_expr.X_add_number
<< (OP_SH_VSEL +
(is_qh ? 2 : 1)));
+ imm_expr.X_op = O_absent;
if (*s != ']')
as_warn(_("Expecting ']' found '%s'"), s);
else
@@ -9809,7 +9820,7 @@ parse_relocation (char **str, bfd_reloc_
{
as_bad ("relocation %s isn't supported by the current ABI",
percent_op[i].str);
- *reloc = BFD_RELOC_LO16;
+ *reloc = BFD_RELOC_UNUSED;
}
return TRUE;
}
@@ -9821,8 +9832,7 @@ parse_relocation (char **str, bfd_reloc_
expression in *EP and the relocations in the array starting
at RELOC. Return the number of relocation operators used.
- On exit, EXPR_END points to the first character after the expression.
- If no relocation operators are used, RELOC[0] is set to BFD_RELOC_LO16. */
+ On exit, EXPR_END points to the first character after the expression. */
static size_t
my_getSmallExpression (expressionS *ep, bfd_reloc_code_real_type *reloc,
@@ -9868,9 +9878,7 @@ my_getSmallExpression (expressionS *ep,
expr_end = str;
- if (reloc_index == 0)
- reloc[0] = BFD_RELOC_LO16;
- else
+ if (reloc_index != 0)
{
prev_reloc_op_frag = frag_now;
for (i = 0; i < reloc_index; i++)
diff -up --recursive --new-file binutils-2.15.91-20040527.macro/gas/testsuite/gas/mips/elf-rel20.d binutils-2.15.91-20040527/gas/testsuite/gas/mips/elf-rel20.d
--- binutils-2.15.91-20040527.macro/gas/testsuite/gas/mips/elf-rel20.d 1970-01-01 00:00:00.000000000 +0000
+++ binutils-2.15.91-20040527/gas/testsuite/gas/mips/elf-rel20.d 2004-05-28 15:48:29.000000000 +0000
@@ -0,0 +1,31 @@
+#objdump: -dr --prefix-addresses -mmips:3000
+#name: MIPS ELF reloc 20
+#as: -march=mips2 -mabi=32
+#source: elf-rel20.s
+
+# Test relocations on the la macro.
+
+.*: +file format .*mips.*
+
+Disassembly of section .text:
+[0-9a-f]+ <[^>]*> lui a0,0x0
+[ ]*[0-9a-f]+: R_MIPS_CALL_HI16 gfunc
+[0-9a-f]+ <[^>]*> addu a0,a0,gp
+[0-9a-f]+ <[^>]*> addiu t9,a0,0
+[ ]*[0-9a-f]+: R_MIPS_CALL_LO16 gfunc
+[0-9a-f]+ <[^>]*> lui a0,0x0
+[ ]*[0-9a-f]+: R_MIPS_GOT_HI16 gvar
+[0-9a-f]+ <[^>]*> addu a0,a0,gp
+[0-9a-f]+ <[^>]*> addiu a1,a0,0
+[ ]*[0-9a-f]+: R_MIPS_GOT_LO16 gvar
+[0-9a-f]+ <[^>]*> lw a0,0\(gp\)
+[ ]*[0-9a-f]+: R_MIPS_GOT16 .data
+[0-9a-f]+ <[^>]*> addiu a1,a0,0
+[ ]*[0-9a-f]+: R_MIPS_LO16 .data
+[0-9a-f]+ <[^>]*> addiu t9,gp,0
+[ ]*[0-9a-f]+: R_MIPS_CALL16 gfunc
+[0-9a-f]+ <[^>]*> addiu a0,gp,0
+[ ]*[0-9a-f]+: R_MIPS_GOT_DISP gvar
+[0-9a-f]+ <[^>]*> addiu a0,gp,0
+[ ]*[0-9a-f]+: R_MIPS_GPREL16 gvar
+ ...
diff -up --recursive --new-file binutils-2.15.91-20040527.macro/gas/testsuite/gas/mips/elf-rel20.s binutils-2.15.91-20040527/gas/testsuite/gas/mips/elf-rel20.s
--- binutils-2.15.91-20040527.macro/gas/testsuite/gas/mips/elf-rel20.s 1970-01-01 00:00:00.000000000 +0000
+++ binutils-2.15.91-20040527/gas/testsuite/gas/mips/elf-rel20.s 2004-05-28 15:35:20.000000000 +0000
@@ -0,0 +1,28 @@
+ .ent foo
+foo:
+ # Check various forms of paired relocations.
+
+ lui $4,%call_hi(gfunc)
+ addu $4,$4,$gp
+ la $25,%call_lo(gfunc)($4)
+
+ lui $4,%got_hi(gvar)
+ addu $4,$4,$gp
+ la $5,%got_lo(gvar)($4)
+
+ lw $4,%got(lvar)($28)
+ la $5,%lo(lvar)($4)
+
+ # Check individual relocations.
+
+ la $25,%call16(gfunc)($28)
+
+ la $4,%got_disp(gvar)($28)
+
+ la $4,%gp_rel(gvar)($28)
+
+ .space 64
+ .end foo
+
+ .data
+lvar: .word 1,2
diff -up --recursive --new-file binutils-2.15.91-20040527.macro/gas/testsuite/gas/mips/mips.exp binutils-2.15.91-20040527/gas/testsuite/gas/mips/mips.exp
--- binutils-2.15.91-20040527.macro/gas/testsuite/gas/mips/mips.exp 2004-05-12 03:25:38.000000000 +0000
+++ binutils-2.15.91-20040527/gas/testsuite/gas/mips/mips.exp 2004-05-28 15:52:39.000000000 +0000
@@ -660,6 +660,7 @@ if { [istarget mips*-*-*] } then {
run_dump_test "elf-rel18"
}
run_dump_test "elf-rel19"
+ run_dump_test "elf-rel20"
if { !$no_mips16 } {
run_dump_test "${tmips}mips${el}16-e"
diff -up --recursive --new-file binutils-2.15.91-20040527.macro/opcodes/mips-opc.c binutils-2.15.91-20040527/opcodes/mips-opc.c
--- binutils-2.15.91-20040527.macro/opcodes/mips-opc.c 2003-11-19 04:25:23.000000000 +0000
+++ binutils-2.15.91-20040527/opcodes/mips-opc.c 2004-05-28 10:35:19.000000000 +0000
@@ -516,7 +516,9 @@ const struct mips_opcode mips_builtin_op
{"divu", "z,t", 0x0000001b, 0xffe0ffff, RD_s|RD_t|WR_HILO, I1 },
{"divu", "d,v,t", 0, (int) M_DIVU_3, INSN_MACRO, I1 },
{"divu", "d,v,I", 0, (int) M_DIVU_3I, INSN_MACRO, I1 },
+{"dla", "t,o(b)", 0, (int) M_DLA_AB, INSN_MACRO, I3 },
{"dla", "t,A(b)", 0, (int) M_DLA_AB, INSN_MACRO, I3 },
+{"dlca", "t,o(b)", 0, (int) M_DLA_AB, INSN_MACRO, I3 },
{"dlca", "t,A(b)", 0, (int) M_DLCA_AB, INSN_MACRO, I3 },
{"dli", "t,j", 0x24000000, 0xffe00000, WR_t, I3 }, /* addiu */
{"dli", "t,i", 0x34000000, 0xffe00000, WR_t, I3 }, /* ori */
@@ -636,11 +638,13 @@ const struct mips_opcode mips_builtin_op
will match first). */
{"jal", "a", 0x0c000000, 0xfc000000, UBD|WR_31, I1 },
{"jalx", "a", 0x74000000, 0xfc000000, UBD|WR_31, I16 },
+{"la", "t,o(b)", 0, (int) M_LA_AB, INSN_MACRO, I1 },
{"la", "t,A(b)", 0, (int) M_LA_AB, INSN_MACRO, I1 },
{"lb", "t,o(b)", 0x80000000, 0xfc000000, LDD|RD_b|WR_t, I1 },
{"lb", "t,A(b)", 0, (int) M_LB_AB, INSN_MACRO, I1 },
{"lbu", "t,o(b)", 0x90000000, 0xfc000000, LDD|RD_b|WR_t, I1 },
{"lbu", "t,A(b)", 0, (int) M_LBU_AB, INSN_MACRO, I1 },
+{"lca", "t,o(b)", 0, (int) M_LA_AB, INSN_MACRO, I1 },
{"lca", "t,A(b)", 0, (int) M_LCA_AB, INSN_MACRO, I1 },
{"ld", "t,o(b)", 0xdc000000, 0xfc000000, WR_t|RD_b, I3 },
{"ld", "t,o(b)", 0, (int) M_LD_OB, INSN_MACRO, I1 },
More information about the Binutils
mailing list