This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
[PATCH 02/15] MIPS: Make the LD/SD macro consistent on o32
- From: "Maciej W. Rozycki" <macro at linux-mips dot org>
- To: binutils at sourceware dot org
- Date: Sun, 3 Oct 2010 20:39:50 +0100 (BST)
- Subject: [PATCH 02/15] MIPS: Make the LD/SD macro consistent on o32
Hi,
While converting the LD test case to a multi-arch setup I have triggered
inconsistent behaviour of the LD/SD macro when assembled for the o32 ABI
with a 64-bit ISA. Considering the following program:
$ cat ld.s
ld $5,32767($4)
ld $5,32768($4)
we get the following output:
$ mips-linux-as -32 -mips3 -o ld.o ld.s
$ mips-linux-objdump -d ld.o
ld.o: file format elf32-tradbigmips
Disassembly of section .text:
00000000 <.text>:
0: dc857fff ld a1,32767(a0)
4: 3c010001 lui at,0x1
8: 00810821 addu at,a0,at
c: 8c258000 lw a1,-32768(at)
10: 8c268004 lw a2,-32764(at)
...
Oops!
This is because on MIPS III and above the M_LD_OB/M_SD_OB macro is
overridden by a hardware instruction, but no such thing happens for the
M_LD_AB/M_SD_AB macro. As the o32 ABI implies 32-bit registers, I think
the correct fix is to make LW/SW hardware instructions to be generated
from LD/SD in all cases. The following change implements it. For the
sake of odd corner cases such as sometimes needed by the Linux kernel or
suchlike the hardware LD/SD instructions are still available for o32 with
".set nomacro".
This change triggered a regression in a GAS test case which I discovered
was an n32 assembly output from GCC. Assembling n32 code may not be
supported on some targets, so rather than trying to figure out how to make
this piece of code fit, I have converted it to o32. This is meant to test
line numbers, so it shouldn't care about the ABI used and the choice of
n32 was a bit unfortunate.
2010-10-03 Maciej W. Rozycki <macro@linux-mips.org>
opcodes/
* mips-opc.c (mips_builtin_opcodes): Move M_LD_OB and M_SD_OB
macros before their corresponding MIPS III hardware instructions.
gas/
* config/tc-mips.c (macro)[M_LD_OB, M_SD_OB]: Handle 64-bit ABIs.
gas/testsuite/
* gas/mips/lineno.s: Convert to o32.
* gas/mips/lineno.d: Adjust patterns accordingly. Force the o32
ABI.
OK to apply?
Maciej
binutils-2.20.51-20100925-mips-gas-ldsd-o32.patch
Index: binutils-2.20.51/gas/config/tc-mips.c
===================================================================
--- binutils-2.20.51.orig/gas/config/tc-mips.c
+++ binutils-2.20.51/gas/config/tc-mips.c
@@ -7364,15 +7364,18 @@ macro (struct mips_cl_insn *ip)
break;
case M_LD_OB:
- s = "lw";
+ s = HAVE_64BIT_GPRS ? "ld" : "lw";
goto sd_ob;
case M_SD_OB:
- s = "sw";
+ s = HAVE_64BIT_GPRS ? "sd" : "sw";
sd_ob:
- gas_assert (HAVE_32BIT_ADDRESSES);
macro_build (&offset_expr, s, "t,o(b)", treg, BFD_RELOC_LO16, breg);
- offset_expr.X_add_number += 4;
- macro_build (&offset_expr, s, "t,o(b)", treg + 1, BFD_RELOC_LO16, breg);
+ if (!HAVE_64BIT_GPRS)
+ {
+ offset_expr.X_add_number += 4;
+ macro_build (&offset_expr, s, "t,o(b)", treg + 1,
+ BFD_RELOC_LO16, breg);
+ }
break;
/* New code added to support COPZ instructions.
Index: binutils-2.20.51/gas/testsuite/gas/mips/lineno.d
===================================================================
--- binutils-2.20.51.orig/gas/testsuite/gas/mips/lineno.d
+++ binutils-2.20.51/gas/testsuite/gas/mips/lineno.d
@@ -1,6 +1,6 @@
#objdump: -d -l -mmips:4000
#name: assembly line numbers
-#as: --gstabs -march=r4000
+#as: --gstabs -32 -march=r4000
.*: +file format .*mips.*
@@ -17,9 +17,9 @@ main\(\):
.*lineno.s:16
.*10:.*addiu.*
.*lineno.s:17
-.*14:.*sd.*
+.*14:.*sw.*
.*lineno.s:18
-.*18:.*sd.*
+.*18:.*sw.*
.*lineno.s:19
.*1c:.*move.*
.*lineno.s:20
@@ -59,9 +59,9 @@ main\(\):
.*lineno.s:34
.*60:.*move.*
.*lineno.s:35
-.*64:.*ld.*
+.*64:.*lw.*
.*lineno.s:36
-.*68:.*ld.*
+.*68:.*lw.*
.*lineno.s:37
.*6c:.*addiu.*
.*lineno.s:38
@@ -73,7 +73,7 @@ g\(\):
.*lineno.s:47
.*78:.*addiu.*
.*lineno.s:48
-.*7c:.*sd.*
+.*7c:.*sw.*
.*lineno.s:49
.*80:.*move.*
.*lineno.s:50
@@ -92,7 +92,7 @@ g\(\):
.*lineno.s:56
.*9c:.*move.*
.*lineno.s:57
-.*a0:.*ld.*
+.*a0:.*lw.*
.*lineno.s:58
.*a4:.*addiu.*
.*lineno.s:59
Index: binutils-2.20.51/opcodes/mips-opc.c
===================================================================
--- binutils-2.20.51.orig/opcodes/mips-opc.c
+++ binutils-2.20.51/opcodes/mips-opc.c
@@ -743,8 +743,9 @@ const struct mips_opcode mips_builtin_op
{"lbu", "t,o(b)", 0x90000000, 0xfc000000, LDD|RD_b|WR_t, 0, I1 },
{"lbu", "t,A(b)", 0, (int) M_LBU_AB, INSN_MACRO, 0, I1 },
{"lca", "t,A(b)", 0, (int) M_LCA_AB, INSN_MACRO, 0, I1 },
-{"ld", "t,o(b)", 0xdc000000, 0xfc000000, WR_t|RD_b, 0, I3 },
+/* The macro has to be first to handle o32 correctly. */
{"ld", "t,o(b)", 0, (int) M_LD_OB, INSN_MACRO, 0, I1 },
+{"ld", "t,o(b)", 0xdc000000, 0xfc000000, WR_t|RD_b, 0, I3 },
{"ld", "t,A(b)", 0, (int) M_LD_AB, INSN_MACRO, 0, I1 },
{"ldaddw", "t,b", 0x70000010, 0xfc00ffff, SM|RD_t|WR_t|RD_b, 0, XLR },
{"ldaddwu", "t,b", 0x70000011, 0xfc00ffff, SM|RD_t|WR_t|RD_b, 0, XLR },
@@ -1173,8 +1174,9 @@ const struct mips_opcode mips_builtin_op
{"sc", "t,A(b)", 0, (int) M_SC_AB, INSN_MACRO, 0, I2 },
{"scd", "t,o(b)", 0xf0000000, 0xfc000000, SM|RD_t|WR_t|RD_b, 0, I3 },
{"scd", "t,A(b)", 0, (int) M_SCD_AB, INSN_MACRO, 0, I3 },
-{"sd", "t,o(b)", 0xfc000000, 0xfc000000, SM|RD_t|RD_b, 0, I3 },
+/* The macro has to be first to handle o32 correctly. */
{"sd", "t,o(b)", 0, (int) M_SD_OB, INSN_MACRO, 0, I1 },
+{"sd", "t,o(b)", 0xfc000000, 0xfc000000, SM|RD_t|RD_b, 0, I3 },
{"sd", "t,A(b)", 0, (int) M_SD_AB, INSN_MACRO, 0, I1 },
{"sdbbp", "", 0x0000000e, 0xffffffff, TRAP, 0, G2 },
{"sdbbp", "c", 0x0000000e, 0xfc00ffff, TRAP, 0, G2 },
Index: binutils-2.20.51/gas/testsuite/gas/mips/lineno.s
===================================================================
--- binutils-2.20.51.orig/gas/testsuite/gas/mips/lineno.s
+++ binutils-2.20.51/gas/testsuite/gas/mips/lineno.s
@@ -7,15 +7,15 @@
.word 0xdeadbeef
# some real code, compiled from a toy C program
- .globl main
+ .globl main
.ent main
main:
- .frame $fp,32,$31 # vars= 16, regs= 2/0, args= 0, extra= 0
+ .frame $fp,24,$31 # vars= 16, regs= 2/0, args= 0, extra= 0
.mask 0xc0000000,-8
.fmask 0x00000000,0
- subu $sp,$sp,32
- sd $31,24($sp)
- sd $fp,16($sp)
+ subu $sp,$sp,24
+ sw $31,20($sp)
+ sw $fp,16($sp)
move $fp,$sp
jal __main
li $2,2 # 0x2
@@ -32,20 +32,20 @@ main:
b $L1
$L1:
move $sp,$fp
- ld $31,24($sp)
- ld $fp,16($sp)
- addu $sp,$sp,32
+ lw $31,20($sp)
+ lw $fp,16($sp)
+ addu $sp,$sp,24
j $31
.end main
.align 2
.globl g
.ent g
g:
- .frame $fp,32,$31 # vars= 16, regs= 1/0, args= 0, extra= 0
+ .frame $fp,24,$31 # vars= 16, regs= 1/0, args= 0, extra= 0
.mask 0x40000000,-16
.fmask 0x00000000,0
- subu $sp,$sp,32
- sd $fp,16($sp)
+ subu $sp,$sp,24
+ sw $fp,16($sp)
move $fp,$sp
sw $4,0($fp)
lw $2,0($fp)
@@ -54,7 +54,7 @@ g:
b $L2
$L2:
move $sp,$fp
- ld $fp,16($sp)
- addu $sp,$sp,32
+ lw $fp,16($sp)
+ addu $sp,$sp,24
j $31
.end g