[rx] patch: detect negative constants more accurately

DJ Delorie dj@redhat.com
Mon Apr 30 23:42:00 GMT 2012


Applied.

	* config/rx-parse.y (rx_intop): Add parameter for operation size.
	Check for large positive constants really being small negative
	ones.
	(BRA, BSR): Update calls to rx_intop.
	(immediate): Likewise.

Index: gas/config/rx-parse.y
===================================================================
RCS file: /cvs/src/src/gas/config/rx-parse.y,v
retrieving revision 1.7
diff -p -U5 -r1.7  gas/config/rx-parse.y
--- gas/config/rx-parse.y	3 Apr 2012 19:06:40 -0000	1.7
+++ gas/config/rx-parse.y	27 Apr 2012 18:23:23 -0000
@@ -102,11 +102,11 @@ static int sizemap[] = { BSIZE, WSIZE, L
 			   else rx_linkrelax_dsp (pos); \
 			   F (displacement (v, msz), pos, 2)
 
 #define id24(a,b2,b3)	   B3 (0xfb+a, b2, b3)
 
-static int         rx_intop (expressionS, int);
+static int         rx_intop (expressionS, int, int);
 static int         rx_uintop (expressionS, int);
 static int         rx_disp3op (expressionS);
 static int         rx_disp5op (expressionS *, int);
 static int         rx_disp5op0 (expressionS *, int);
 static int         exp_val (expressionS exp);
@@ -190,15 +190,15 @@ statement :
 /* ---------------------------------------------------------------------- */
 
 	| BRA EXPR
 	  { if (rx_disp3op ($2))
 	      { B1 (0x08); rx_disp3 ($2, 5); }
-	    else if (rx_intop ($2, 8))
+	    else if (rx_intop ($2, 8, 8))
 	      { B1 (0x2e); PC1 ($2); }
-	    else if (rx_intop ($2, 16))
+	    else if (rx_intop ($2, 16, 16))
 	      { B1 (0x38); PC2 ($2); }
-	    else if (rx_intop ($2, 24))
+	    else if (rx_intop ($2, 24, 24))
 	      { B1 (0x04); PC3 ($2); }
 	    else
 	      { rx_relax (RX_RELAX_BRANCH, 0);
 		rx_linkrelax_branch ();
 		/* We'll convert this to a longer one later if needed.  */
@@ -211,13 +211,13 @@ statement :
 	  { B1 (0x08); rx_disp3 ($3, 5); }
 
 /* ---------------------------------------------------------------------- */
 
 	| BSR EXPR
-	  { if (rx_intop ($2, 16))
+	  { if (rx_intop ($2, 16, 16))
 	      { B1 (0x39); PC2 ($2); }
-	    else if (rx_intop ($2, 24))
+	    else if (rx_intop ($2, 24, 24))
 	      { B1 (0x05); PC3 ($2); }
 	    else
 	      { rx_relax (RX_RELAX_BRANCH, 0);
 		rx_linkrelax_branch ();
 		B1 (0x39); PC2 ($2); } }
@@ -1306,20 +1306,27 @@ rx_error (const char * str)
   as_bad ("%*s^ %s", len, "", str);
   return 0;
 }
 
 static int
-rx_intop (expressionS exp, int nbits)
+rx_intop (expressionS exp, int nbits, int opbits)
 {
   long v;
+  long mask, msb;
 
   if (exp.X_op == O_big && nbits == 32)
       return 1;
   if (exp.X_op != O_constant)
     return 0;
   v = exp.X_add_number;
 
+  msb = 1UL << (opbits - 1);
+  mask = (1UL << opbits) - 1;
+
+  if ((v & msb) && ! (v & ~mask))
+    v -= 1UL << opbits;
+
   switch (nbits)
     {
     case 4:
       return -0x8 <= v && v <= 0x7;
     case 5:
@@ -1459,31 +1466,31 @@ immediate (expressionS exp, int type, in
 	exp.X_add_number = - exp.X_add_number - 1;
       else
 	rx_error (_("sbb cannot use symbolic immediates"));
     }
 
-  if (rx_intop (exp, 8))
+  if (rx_intop (exp, 8, bits))
     {
       rx_op (exp, 1, type);
       return 1;
     }
-  else if (rx_intop (exp, 16))
+  else if (rx_intop (exp, 16, bits))
     {
       rx_op (exp, 2, type);
       return 2;
     }
   else if (rx_uintop (exp, 16) && bits == 16)
     {
       rx_op (exp, 2, type);
       return 2;
     }
-  else if (rx_intop (exp, 24))
+  else if (rx_intop (exp, 24, bits))
     {
       rx_op (exp, 3, type);
       return 3;
     }
-  else if (rx_intop (exp, 32))
+  else if (rx_intop (exp, 32, bits))
     {
       rx_op (exp, 4, type);
       return 0;
     }
   else if (type == RXREL_SIGNED)



More information about the Binutils mailing list