This is the mail archive of the
binutils@sources.redhat.com
mailing list for the binutils project.
[patch] MIPS/gas: load/store address overflow on binutils 2.14
- From: "Maciej W. Rozycki" <macro at ds2 dot pg dot gda dot pl>
- To: binutils at sources dot redhat dot com
- Cc: Atsushi Nemoto <anemo at mba dot ocn dot ne dot jp>, Thiemo Seufer <ica2_ts at csv dot ica dot uni-stuttgart dot de>
- Date: Mon, 8 Sep 2003 23:09:39 +0200 (MET DST)
- Subject: [patch] MIPS/gas: load/store address overflow on binutils 2.14
- Organization: Technical University of Gdansk
Hello,
There is a problem with gas in binutils 2.14 -- when building for a
32-bit ABI it does not accept constant addresses with bit 31 set which are
valid. The reason is a new check introduced in tc-mips.c:macro() and a
shortcoming of the generic expr.c:operand() -- when building with BFD64
such addresses are not sign-extended and end up as unsigned 32-bit
constants -- there is no way to tell operand() to treat expressions
selectively as 32-bit and sign-extend them.
The original bug report follows.
Here is a fix that works for me. It makes gas accept unsigned
(zero-extended) 32-bit constants as addresses for a 32-bit ABI. Also
negated constants are accepted, to make constructs similar to both "lw
$2,0x80000000" and "lw $2,-0x80000000".
I defined a new macro to cover the extended range and found it suitable
to use instead of a similar check in tc-mips.c:load_register(). And while
doing that, I removed some seemingly useless nearby checks, both for
32-bit and 16-bit constants -- can anyone please elaborate what are they
for? I fail to see any use for them.
2003-09-08 Maciej W. Rozycki <macro@ds2.pg.gda.pl>
* config/tc-mips.c (IS_ZEXT_32BIT_NUM): New macro to determine if
a number is a zero-extended 32-bit number or a negation of one.
(load_register): Simplify range checks for 16-bit and 32-bit
constants.
(macro): Permit 32-bit addresses for load/store as qualified by
IS_ZEXT_32BIT_NUM.
I think it's worth to have a test case for these addresses -- I'll
prepare one soon.
OK to apply?
Maciej
--
+ Maciej W. Rozycki, Technical University of Gdansk, Poland +
+--------------------------------------------------------------+
+ e-mail: macro@ds2.pg.gda.pl, PGP key available +
---------- Forwarded message ----------
Message-ID: <20030807.190330.26271096.nemoto@toshiba-tops.co.jp>
Date: Thu, 07 Aug 2003 19:03:30 +0900 (JST)
From: Atsushi Nemoto <anemo@mba.ocn.ne.jp>
To: linux-mips@linux-mips.org
Subject: load/store address overflow on binutils 2.14
I'm trying binutils 2.14 (and binutils 2.14.90.0.5). These versions
can not compile this inctruction.
lw $2, 0x80000000
$ mips-linux-gcc -c foo.s
b.S: Assembler messages:
foo.S:1: Error: load/store address overflow (max 32 bits)
Using such an immediate address for load instructions is legal? I
found the error message in tc-mips.c and it looks like something
related to 64bit ABIs, but I just want to compile 32bit (standalone)
program.
Is this code really needed for 32bit ABI?
binutils-2.14/gas/config/tc-mips.c:6297
else if (offset_expr.X_op == O_constant
&& !HAVE_64BIT_ADDRESS_CONSTANTS
&& !IS_SEXT_32BIT_NUM (offset_expr.X_add_number))
as_bad (_("load/store address overflow (max 32 bits)"));
---
Atsushi Nemoto
---------- Forwarded message ----------
binutils-2.14-mips-gas-u32_const.patch
diff -up --recursive --new-file binutils-2.14.macro/gas/config/tc-mips.c binutils-2.14/gas/config/tc-mips.c
--- binutils-2.14.macro/gas/config/tc-mips.c 2003-06-02 20:35:25.000000000 +0000
+++ binutils-2.14/gas/config/tc-mips.c 2003-09-08 17:03:03.000000000 +0000
@@ -796,6 +796,12 @@ static int mips_relax_branch;
(((x) &~ (offsetT) 0x7fff) == 0 \
|| (((x) &~ (offsetT) 0x7fff) == ~ (offsetT) 0x7fff))
+/* Is the given value a zero-extended 32-bit value?
+ Or a negated zero-extended 32-bit value? */
+#define IS_ZEXT_32BIT_NUM(x) \
+ (((x) &~ (offsetT) 0xffffffff) == 0 \
+ || (((x) &~ (offsetT) 0xffffffff) == ~ (offsetT) 0xffffffff))
+
/* Prototypes for static functions. */
@@ -3561,12 +3567,7 @@ load_register (counter, reg, ep, dbl)
if (ep->X_op != O_big)
{
assert (ep->X_op == O_constant);
- if (ep->X_add_number < 0x8000
- && (ep->X_add_number >= 0
- || (ep->X_add_number >= -0x8000
- && (! dbl
- || ! ep->X_unsigned
- || sizeof (ep->X_add_number) > 4))))
+ if (IS_SEXT_16BIT_NUM(ep->X_add_number))
{
/* We can handle 16 bit signed values with an addiu to
$zero. No need to ever use daddiu here, since $zero and
@@ -3583,17 +3584,9 @@ load_register (counter, reg, ep, dbl)
(int) BFD_RELOC_LO16);
return;
}
- else if ((IS_SEXT_32BIT_NUM (ep->X_add_number)
- && (! dbl
- || ! ep->X_unsigned
- || sizeof (ep->X_add_number) > 4
- || (ep->X_add_number & 0x80000000) == 0))
- || ((HAVE_32BIT_GPRS || ! dbl)
- && (ep->X_add_number &~ (offsetT) 0xffffffff) == 0)
- || (HAVE_32BIT_GPRS
- && ! dbl
- && ((ep->X_add_number &~ (offsetT) 0xffffffff)
- == ~ (offsetT) 0xffffffff)))
+ else if (IS_SEXT_32BIT_NUM (ep->X_add_number)
+ || ((! dbl || HAVE_32BIT_GPRS)
+ && IS_ZEXT_32BIT_NUM (ep->X_add_number)))
{
/* 32 bit values require an lui. */
macro_build ((char *) NULL, counter, ep, "lui", "t,u", reg,
@@ -6296,7 +6289,7 @@ macro (ip)
}
else if (offset_expr.X_op == O_constant
&& !HAVE_64BIT_ADDRESS_CONSTANTS
- && !IS_SEXT_32BIT_NUM (offset_expr.X_add_number))
+ && !IS_ZEXT_32BIT_NUM (offset_expr.X_add_number))
as_bad (_("load/store address overflow (max 32 bits)"));
if (breg == 0)