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 - hppa] add compile time check for immediate values of shift/deposit/extract functions


On the parisc linux port I faces some time back the problem
that we generated an assembly statement like this one:
	extrw,u r8,9,11,r5
which has undefined runtime behavior since the length value (11)
extends beyond the leftmost bit (9):   (11-1 > 9)

Interestingly my PA2.0 processor didn't seemed to care and just
zero-extend the value at runtime, while my PA1.1 processors didn't
and just filled in random values into %r5 which led to crashes.

The patch below adds compile time checks to gas which (where possible)
will check the constant immediate values of the shift/deposit/extract
functions and warn the user if he coded a dangerous combination.

Compiling the testsuite by hand produces the expected additional warnings:
[deller@halden gas]$ ./as-new /mnt/sda6/home/cvs/LINUX/binutils/gas/testsuite/gas/hppa/basic/deposit.s
/mnt/sda6/home/cvs/LINUX/binutils/gas/testsuite/gas/hppa/basic/deposit.s: Assembler messages:
/mnt/sda6/home/cvs/LINUX/binutils/gas/testsuite/gas/hppa/basic/deposit.s:8: Warning: Immediates 5 and 10 will give undefined behavior.
/mnt/sda6/home/cvs/LINUX/binutils/gas/testsuite/gas/hppa/basic/deposit.s:9: Warning: Immediates 5 and 10 will give undefined behavior.
(and so on)


2009-02-22  Helge Deller <deller@gmx.de>

        * gas/config/tc-hppa.c: Add check of immediate values.



Index: gas/config/tc-hppa.c
===================================================================
RCS file: /cvs/src/src/gas/config/tc-hppa.c,v
retrieving revision 1.142
diff -u -p -r1.142 tc-hppa.c
--- gas/config/tc-hppa.c	9 Sep 2008 00:53:35 -0000	1.142
+++ gas/config/tc-hppa.c	22 Feb 2009 17:15:32 -0000
@@ -995,6 +995,16 @@ static struct default_space_dict pa_def_
 #define IS_R_SELECT(S)   (*(S) == 'R' || *(S) == 'r')
 #define IS_L_SELECT(S)   (*(S) == 'L' || *(S) == 'l')
 
+/* Store immediate values of shift/deposit/extract functions.  */
+
+#define INSERT_IMMEDIATE(VALUE) \
+  { \
+    if (immediate_check) \
+	{ if (sv1 == -1) sv1 = VALUE; \
+	  else if (sv2 == -1) sv2 = VALUE; \
+	} \
+  }
+
 /* Insert FIELD into OPCODE starting at bit START.  Continue pa_ip
    main loop after insertion.  */
 
@@ -3191,6 +3201,7 @@ pa_ip (char *str)
   int match = FALSE;
   int comma = 0;
   int cmpltr, nullif, flag, cond, num;
+  int immediate_check = 0, sv1 = -1, sv2 = -1;
   unsigned long opcode;
   struct pa_opcode *insn;
 
@@ -3351,6 +3362,7 @@ pa_ip (char *str)
 		break;
 	      s = expr_end;
 	      CHECK_FIELD (num, 32, 1, 0);
+	      INSERT_IMMEDIATE(num);
 	      INSERT_FIELD_AND_CONTINUE (opcode, 32 - num, 0);
 
 	    /* Handle a 5 bit immediate at 15.  */
@@ -4333,6 +4345,9 @@ pa_ip (char *str)
 		  case 'x':
 		  case 'y':
 		    cmpltr = 0;
+		    /* Check immediate values in shift/extract/deposit
+		     * instructions if they will give undefined behaviour.  */
+		    immediate_check = 1;
 		    if (*s == ',')
 		      {
 			save_s = s++;
@@ -5125,6 +5140,7 @@ pa_ip (char *str)
 		break;
 	      s = expr_end;
 	      CHECK_FIELD (num, 31, 0, strict);
+	      INSERT_IMMEDIATE(num);
 	      INSERT_FIELD_AND_CONTINUE (opcode, 31 - num, 5);
 
 	    /* Handle a 6 bit shift count at 20,22:26.  */
@@ -5134,6 +5150,7 @@ pa_ip (char *str)
 		break;
 	      s = expr_end;
 	      CHECK_FIELD (num, 63, 0, strict);
+	      INSERT_IMMEDIATE(num);
 	      num = 63 - num;
 	      opcode |= (num & 0x20) << 6;
 	      INSERT_FIELD_AND_CONTINUE (opcode, num & 0x1f, 5);
@@ -5146,6 +5163,7 @@ pa_ip (char *str)
 		break;
 	      s = expr_end;
 	      CHECK_FIELD (num, 64, 1, strict);
+	      INSERT_IMMEDIATE(num);
 	      num--;
 	      opcode |= (num & 0x20) << 3;
 	      num = 31 - (num & 0x1f);
@@ -5158,6 +5176,7 @@ pa_ip (char *str)
 		break;
 	      s = expr_end;
 	      CHECK_FIELD (num, 64, 1, strict);
+	      INSERT_IMMEDIATE(num);
 	      num--;
 	      opcode |= (num & 0x20) << 7;
 	      num = 31 - (num & 0x1f);
@@ -5170,6 +5189,7 @@ pa_ip (char *str)
 		break;
 	      s = expr_end;
 	      CHECK_FIELD (num, 31, 0, strict);
+	      INSERT_IMMEDIATE(num);
 	      INSERT_FIELD_AND_CONTINUE (opcode, num, 5);
 
 	    /* Handle a 6 bit bit position at 20,22:26.  */
@@ -5179,6 +5199,7 @@ pa_ip (char *str)
 		break;
 	      s = expr_end;
 	      CHECK_FIELD (num, 63, 0, strict);
+	      INSERT_IMMEDIATE(num);
 	      opcode |= (num & 0x20) << 6;
 	      INSERT_FIELD_AND_CONTINUE (opcode, num & 0x1f, 5);
 
@@ -5686,6 +5707,12 @@ pa_ip (char *str)
       break;
     }
 
+  if (immediate_check) {
+    if (sv1 != -1 && sv2 != -1 && (sv2-1) > sv1)
+      as_warn (_("Immediates %d and %d will give undefined behavior."),
+			sv1, sv2);
+  }
+
   the_insn.opcode = opcode;
 }
 


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