mips-tdep.c: Sign-extend pointers for n32

Maciej W. Rozycki macro@mips.com
Thu Dec 20 16:41:00 GMT 2007

On Wed, 19 Dec 2007, Daniel Jacobowitz wrote:

> I happen to know otherwise.  I once wasted several days tracking down
> a bug in the Linux kernel's IP checksumming implementation which
> resulted in incorrectly extended values in registers; there are MIPS
> parts which really do behave unpredictably when you use 32-bit
> arithmetic operations on them (specifically the Broadcom SB1).

 I recall the issue and the problem was broken inline assembly, which used 
64-bit operations to produce results associated with 32-bit integer types 
and register constraints.  This is a different issue and is doomed to fail 

> And I believe a compiler would be justified in using such instructions
> on a signed char argument.

 Yes, of course -- it is actually meant to and thus will never produce 
results outside the sign-extended 32-bit range (remember that before 
extending, bits 31:16 or 31:8 as appropriate are zeroes, so after a 
zero-extension the values still fall within the signed 32-bit range).  
And most ALU operations do not care about the signedness, but there are 
two exceptions that came to my mind after I sent you the previous letter, 
specifically signed "div/mult", and GCC indeed uses signed/unsigned load 
operations for 16/8-bit types as appropriate, so even though chasing the 
relevant document that would state it explicitly seems a non-trivial task, 
I think sign-extension of such small signed integers is implied.

 Also n32 builds on compatibility with o32 and the most definite o32 
Processor Supplement, 3rd Edition" says:

"All integer-valued arguments are passed as 32-bit words, with signed or 
unsigned bytes and halfwords expanded (promoted) as necessary."

 Thus I have taken your suggestion into account and modified the change 
further as follows and regression tested it as previously, successfully.  
Well, I guess it actually means we do not really have a terribly good 
coverage here -- I suppose a set of test cases that would check that 
promotion is performed correctly with manual calls would be useful.

2007-12-19  David Ung  <davidu@mips.com>
            Maciej W. Rozycki  <macro@mips.com>

	* mips-tdep.c (mips_n32n64_push_dummy_call): Sign-extend
	integers and 32-bit pointers as required by the ABI.

 OK to apply?


Index: binutils-quilt/src/gdb/mips-tdep.c
--- binutils-quilt.orig/src/gdb/mips-tdep.c	2007-12-19 15:15:45.000000000 +0000
+++ binutils-quilt/src/gdb/mips-tdep.c	2007-12-20 16:13:31.000000000 +0000
@@ -3184,8 +3184,21 @@
 	         purpose register.  */
 	      if (argreg <= MIPS_LAST_ARG_REGNUM)
-		  LONGEST regval =
-		    extract_unsigned_integer (val, partial_len);
+		  LONGEST regval;
+		  /* Sign extend pointers, 32-bit integers and signed
+		     16-bit and 8-bit integers; everything else is taken
+		     as is.  */
+		  if ((partial_len == 4
+		       && (typecode == TYPE_CODE_PTR
+			   || typecode == TYPE_CODE_INT))
+		      || (partial_len < 4
+			  && typecode == TYPE_CODE_INT
+			  && !TYPE_UNSIGNED (arg_type)))
+		    regval = extract_signed_integer (val, partial_len);
+		  else
+		    regval = extract_unsigned_integer (val, partial_len);
 		  /* A non-floating-point argument being passed in a
 		     general register.  If a struct or union, and if

More information about the Gdb-patches mailing list