This is the mail archive of the binutils@sources.redhat.com mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[patch] MIPS/gas: load/store address overflow on binutils 2.14


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)


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]