This is the mail archive of the binutils@sourceware.org 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] Fix sign-extended immediates for SH on 64-bit host


Hi,

it appears that the SH backend for gas has a bug in it that is exposed
when using a cross-compiled toolchain that is built on a 64-bit host. As
an example, the assembler does not interpret the immediate constant
0xfffffff0 as a negative value when run on a 64-bit machine, rather it
is zero-extended. The constant is correctly recognised as a negative
integer on a 32-bit machine.

The attached patches introduce two new macros, SEXT and TRUNC to
sign-extend and truncate a long, respectively. Using these macros allows
us to obtain the same result from using sign-extended immediates on both
32-bit and 64-bit hosts.

Comments?

2009-08-29  Matt Fleming  <matt@console-pimps.org>

	* config/tc-sh.c (TRUNC): Define.
	(SEXT): Define.
	(md_apply_fix): Use new SEXT macro.

2009-08-29  Matt Fleming  <matt@console-pimps.org>

	* gas/sh/sign-extension.d: New file.
	* gas/sh/sign-extension.s: New file.
	* gas/sh/basic.exp: Run new test.
Index: gas/config/tc-sh.c
===================================================================
RCS file: /cvs/src/src/gas/config/tc-sh.c,v
retrieving revision 1.132
diff -u -r1.132 tc-sh.c
--- gas/config/tc-sh.c	24 Jul 2009 11:45:00 -0000	1.132
+++ gas/config/tc-sh.c	27 Aug 2009 20:09:14 -0000
@@ -156,6 +156,11 @@
 #define ENCODE_RELAX(what,length) (((what) << 4) + (length))
 #define GET_WHAT(x) ((x>>4))
 
+/* Truncate and sign-extend at 32 bits, so that building on a 64-bit host
+   gives identical results to a 32-bit host.  */
+#define TRUNC(X)	((long) (X) & 0xffffffff)
+#define SEXT(X)		((TRUNC (X) ^ 0x80000000) - 0x80000000)
+
 /* These are the three types of relaxable instruction.  */
 /* These are the types of relaxable instructions; except for END which is
    a marker.  */
@@ -4183,7 +4188,7 @@
 	val = ((val >> shift)
 	       | ((long) -1 & ~ ((long) -1 >> shift)));
     }
-  if (max != 0 && (val < min || val > max))
+  if (max != 0 && (SEXT(val) < min || SEXT(val) > max))
     as_bad_where (fixP->fx_file, fixP->fx_line, _("offset out of range"));
   else if (max != 0)
     /* Stop the generic code from trying to overlow check the value as well.
Index: gas/testsuite/gas/sh/basic.exp
===================================================================
RCS file: /cvs/src/src/gas/testsuite/gas/sh/basic.exp,v
retrieving revision 1.24
diff -u -r1.24 basic.exp
--- gas/testsuite/gas/sh/basic.exp	3 Jul 2007 11:01:08 -0000	1.24
+++ gas/testsuite/gas/sh/basic.exp	28 Aug 2009 23:50:02 -0000
@@ -169,6 +169,8 @@
 	run_dump_test "reg-prefix"
 
 	run_dump_test "too_large"
+
+	run_dump_test "sign-extension"
     }
 }
 
--- /dev/null	2009-04-14 11:16:40.000000000 +0100
+++ gas/testsuite/gas/sh/sign-extension.d	2009-08-28 23:50:57.000000000 +0100
@@ -0,0 +1,11 @@
+#as: -little
+#objdump: -drj.text
+#name: Sign-extended immediate
+
+.*:     file format .*sh.*
+
+Disassembly of section \.text:
+
+00000000 <foo>:
+   0:	f0 e0       	mov	#-16,r0
+   2:	09 00       	nop	
--- /dev/null	2009-04-14 11:16:40.000000000 +0100
+++ gas/testsuite/gas/sh/sign-extension.s	2009-08-27 21:39:27.000000000 +0100
@@ -0,0 +1,3 @@
+	.align 2
+foo:
+	mov #0xfffffff0, r0

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