summaryrefslogtreecommitdiff
path: root/gas/config/rx-parse.y
diff options
context:
space:
mode:
authorDJ Delorie <dj@delorie.com>2012-04-30 22:09:08 +0000
committerDJ Delorie <dj@delorie.com>2012-04-30 22:09:08 +0000
commita47b601179e22a88df08b7558edceab6c1658594 (patch)
tree357ea55c0b924402222e4771e4775c42a7c6e130 /gas/config/rx-parse.y
parent3ad96e3fedb023e1b5ed0bede0b3c130bbe308be (diff)
downloadbinutils-redhat-a47b601179e22a88df08b7558edceab6c1658594.tar.gz
* 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.
Diffstat (limited to 'gas/config/rx-parse.y')
-rw-r--r--gas/config/rx-parse.y29
1 files changed, 18 insertions, 11 deletions
diff --git a/gas/config/rx-parse.y b/gas/config/rx-parse.y
index f223dc7e4f..756637bd4d 100644
--- a/gas/config/rx-parse.y
+++ b/gas/config/rx-parse.y
@@ -104,7 +104,7 @@ static int sizemap[] = { BSIZE, WSIZE, LSIZE, WSIZE };
#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);
@@ -192,11 +192,11 @@ 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);
@@ -213,9 +213,9 @@ statement :
/* ---------------------------------------------------------------------- */
| 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);
@@ -1308,9 +1308,10 @@ rx_error (const char * str)
}
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;
@@ -1318,6 +1319,12 @@ rx_intop (expressionS exp, int nbits)
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:
@@ -1461,12 +1468,12 @@ immediate (expressionS exp, int type, int pos, int bits)
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;
@@ -1476,12 +1483,12 @@ immediate (expressionS exp, int type, int pos, int bits)
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;