Allow symbols in MEMORY region specification
[deliverable/binutils-gdb.git] / gas / config / rx-parse.y
index 0bcafc81afe6962330987fb577d505c66408960e..645ec99f5383fa0de8a105d1c6824f9a02914f90 100644 (file)
@@ -1,6 +1,5 @@
 /* rx-parse.y  Renesas RX parser
-   Copyright 2008, 2009
-   Free Software Foundation, Inc.
+   Copyright (C) 2008-2015 Free Software Foundation, Inc.
 
    This file is part of GAS, the GNU Assembler.
 
@@ -72,14 +71,14 @@ static int sizemap[] = { BSIZE, WSIZE, LSIZE, WSIZE };
 #define F(val,pos,sz)      rx_field (val, pos, sz)
 #define FE(exp,pos,sz)    rx_field (exp_val (exp), pos, sz);
 
-#define O1(v)              rx_op (v, 1, RXREL_SIGNED)
-#define O2(v)              rx_op (v, 2, RXREL_SIGNED)
-#define O3(v)              rx_op (v, 3, RXREL_SIGNED)
+#define O1(v)              rx_op (v, 1, RXREL_SIGNED); rx_range (v, -128, 255)
+#define O2(v)              rx_op (v, 2, RXREL_SIGNED); rx_range (v, -32768, 65536)
+#define O3(v)              rx_op (v, 3, RXREL_SIGNED); rx_range (v, -8388608, 16777216)
 #define O4(v)              rx_op (v, 4, RXREL_SIGNED)
 
-#define UO1(v)             rx_op (v, 1, RXREL_UNSIGNED)
-#define UO2(v)             rx_op (v, 2, RXREL_UNSIGNED)
-#define UO3(v)             rx_op (v, 3, RXREL_UNSIGNED)
+#define UO1(v)             rx_op (v, 1, RXREL_UNSIGNED); rx_range (v, 0, 255)
+#define UO2(v)             rx_op (v, 2, RXREL_UNSIGNED); rx_range (v, 0, 65536)
+#define UO3(v)             rx_op (v, 3, RXREL_UNSIGNED); rx_range (v, 0, 16777216)
 #define UO4(v)             rx_op (v, 4, RXREL_UNSIGNED)
 
 #define NO1(v)             rx_op (v, 1, RXREL_NEGATIVE)
@@ -91,26 +90,31 @@ static int sizemap[] = { BSIZE, WSIZE, LSIZE, WSIZE };
 #define PC2(v)             rx_op (v, 2, RXREL_PCREL)
 #define PC3(v)             rx_op (v, 3, RXREL_PCREL)
 
-#define IMM(v,pos)        F (immediate (v, RXREL_SIGNED, pos), pos, 2); \
+#define IMM_(v,pos,size)   F (immediate (v, RXREL_SIGNED, pos, size), pos, 2); \
                           if (v.X_op != O_constant && v.X_op != O_big) rx_linkrelax_imm (pos)
-#define NIMM(v,pos)       F (immediate (v, RXREL_NEGATIVE, pos), pos, 2)
-#define NBIMM(v,pos)      F (immediate (v, RXREL_NEGATIVE_BORROW, pos), pos, 2)
+#define IMM(v,pos)        IMM_ (v, pos, 32)
+#define IMMW(v,pos)       IMM_ (v, pos, 16); rx_range (v, -32768, 65536)
+#define IMMB(v,pos)       IMM_ (v, pos, 8); rx_range (v, -128, 255)
+#define NIMM(v,pos)       F (immediate (v, RXREL_NEGATIVE, pos, 32), pos, 2)
+#define NBIMM(v,pos)      F (immediate (v, RXREL_NEGATIVE_BORROW, pos, 32), pos, 2)
 #define DSP(v,pos,msz)    if (!v.X_md) rx_relax (RX_RELAX_DISP, pos); \
                           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 void       rx_check_float_support (void);
+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);
 static expressionS zero_expr (void);
-static int         immediate (expressionS, int, int);
+static int         immediate (expressionS, int, int, int);
 static int         displacement (expressionS, int);
 static void        rtsd_immediate (expressionS);
+static void       rx_range (expressionS, int, int);
 
 static int    need_flag = 0;
 static int    rx_in_brackets = 0;
@@ -189,11 +193,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);
@@ -210,9 +214,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);
@@ -278,7 +282,7 @@ statement :
          { if ($8 <= 7 && rx_uintop ($4, 8) && rx_disp5op0 (&$6, WSIZE))
              { B2 (0x3d, 0); rx_field5s2 ($6); F ($8, 9, 3); O1 ($4); }
            else
-             { B2 (0xf8, 0x01); F ($8, 8, 4); DSP ($6, 6, WSIZE); IMM ($4, 12); } }
+             { B2 (0xf8, 0x01); F ($8, 8, 4); DSP ($6, 6, WSIZE); IMMW ($4, 12); } }
 
        | MOV DOT_L '#' EXPR ',' disp '[' REG ']'
          { if ($8 <= 7 && rx_uintop ($4, 8) && rx_disp5op0 (&$6, LSIZE))
@@ -331,7 +335,7 @@ statement :
              { B2 (0x60, 0); FE ($3, 8, 4); F ($5, 12, 4); }
            else
              /* This is really an add, but we negate the immediate.  */
-             { B2 (0x38, 0); F ($5, 8, 4); F ($5, 12, 4); NIMM ($3, 6); } } /* ? */
+             { B2 (0x70, 0); F ($5, 8, 4); F ($5, 12, 4); NIMM ($3, 6); } }
 
        | CMP '#' EXPR ',' REG
          { if (rx_uintop ($3, 4))
@@ -532,7 +536,7 @@ statement :
 /* ---------------------------------------------------------------------- */
 
        | MVTIPL '#' EXPR
-         { B2 (0x7f, 0x98); FE ($3, 13, 3); }
+         { B3 (0x75, 0x70, 0x00); FE ($3, 20, 4); }
 
 /* ---------------------------------------------------------------------- */
 
@@ -598,10 +602,10 @@ statement :
 
 /* ---------------------------------------------------------------------- */
 
-       | SBB   { sub_op = 0; } op_dp20_rm
-       | NEG   { sub_op = 1; sub_op2 = 1; } op_dp20_rms
-       | ADC   { sub_op = 2; } op_dp20_rim
-       | ABS   { sub_op = 3; sub_op2 = 2; } op_dp20_rms
+       | SBB   { sub_op = 0; } op_dp20_rm_l
+       | NEG   { sub_op = 1; sub_op2 = 1; } op_dp20_rr
+       | ADC   { sub_op = 2; } op_dp20_rim_l
+       | ABS   { sub_op = 3; sub_op2 = 2; } op_dp20_rr
        | MAX   { sub_op = 4; } op_dp20_rim
        | MIN   { sub_op = 5; } op_dp20_rim
        | EMUL  { sub_op = 6; } op_dp20_i
@@ -610,7 +614,7 @@ statement :
        | DIVU  { sub_op = 9; } op_dp20_rim
        | TST   { sub_op = 12; } op_dp20_rim
        | XOR   { sub_op = 13; } op_dp20_rim
-       | NOT   { sub_op = 14; sub_op2 = 0; } op_dp20_rms
+       | NOT   { sub_op = 14; sub_op2 = 0; } op_dp20_rr
        | STZ   { sub_op = 14; } op_dp20_i
        | STNZ  { sub_op = 15; } op_dp20_i
 
@@ -632,13 +636,13 @@ statement :
        | BNOT REG ',' REG
          { id24 (1, 0x6f, 0x00); F ($4, 16, 4); F ($2, 20, 4); }
 
-       | BSET REG ',' disp '[' REG ']' DOT_B
+       | BSET REG ',' disp '[' REG ']' opt_b
          { id24 (1, 0x60, 0x00); F ($6, 16, 4); F ($2, 20, 4); DSP ($4, 14, BSIZE); }
-       | BCLR REG ',' disp '[' REG ']' DOT_B
+       | BCLR REG ',' disp '[' REG ']' opt_b
          { id24 (1, 0x64, 0x00); F ($6, 16, 4); F ($2, 20, 4); DSP ($4, 14, BSIZE); }
-       | BTST REG ',' disp '[' REG ']' DOT_B
+       | BTST REG ',' disp '[' REG ']' opt_b
          { id24 (1, 0x68, 0x00); F ($6, 16, 4); F ($2, 20, 4); DSP ($4, 14, BSIZE); }
-       | BNOT REG ',' disp '[' REG ']' DOT_B
+       | BNOT REG ',' disp '[' REG ']' opt_b
          { id24 (1, 0x6c, 0x00); F ($6, 16, 4); F ($2, 20, 4); DSP ($4, 14, BSIZE); }
 
 /* ---------------------------------------------------------------------- */
@@ -660,13 +664,13 @@ statement :
 
 /* ---------------------------------------------------------------------- */
 
-       | BMCND '#' EXPR ',' disp '[' REG ']' DOT_B
+       | BMCND '#' EXPR ',' disp '[' REG ']' opt_b
          { id24 (1, 0xe0, 0x00); F ($1, 20, 4); FE ($3, 11, 3);
              F ($7, 16, 4); DSP ($5, 14, BSIZE); }
 
 /* ---------------------------------------------------------------------- */
 
-       | BNOT '#' EXPR ',' disp '[' REG ']' DOT_B
+       | BNOT '#' EXPR ',' disp '[' REG ']' opt_b
          { id24 (1, 0xe0, 0x0f); FE ($3, 11, 3); F ($7, 16, 4);
              DSP ($5, 14, BSIZE); }
 
@@ -810,6 +814,16 @@ op_subadd
 
 /* sbb, neg, adc, abs, max, min, div, divu, tst, not, xor, stz, stnz, emul, emulu */
 
+op_dp20_rm_l
+       : REG ',' REG
+         { id24 (1, 0x03 + (sub_op<<2), 0x00); F ($1, 16, 4); F ($3, 20, 4); }
+       | disp '[' REG ']' opt_l ',' REG
+         { B4 (MEMEX, 0xa0, 0x00 + sub_op, 0x00);
+         F ($3, 24, 4); F ($7, 28, 4); DSP ($1, 14, LSIZE); }
+       ;
+
+/* neg, adc, abs, max, min, div, divu, tst, not, xor, stz, stnz, emul, emulu */
+
 op_dp20_rm
        : REG ',' REG
          { id24 (1, 0x03 + (sub_op<<2), 0x00); F ($1, 16, 4); F ($3, 20, 4); }
@@ -830,8 +844,14 @@ op_dp20_rim
        | op_dp20_i
        ;
 
-op_dp20_rms
-       : op_dp20_rm
+op_dp20_rim_l
+       : op_dp20_rm_l
+       | op_dp20_i
+       ;
+
+op_dp20_rr
+       : REG ',' REG
+         { id24 (1, 0x03 + (sub_op<<2), 0x00); F ($1, 16, 4); F ($3, 20, 4); }
        | REG
          { B2 (0x7e, sub_op2 << 4); F ($1, 12, 4); }
        ;
@@ -861,17 +881,20 @@ op_shift
        ;
 
 
-
 float2_op
-       : '#' EXPR ',' REG
-         { id24 (2, 0x72, sub_op << 4); F ($4, 20, 4); O4 ($2); }
+       : { rx_check_float_support (); }
+         '#' EXPR ',' REG
+         { id24 (2, 0x72, sub_op << 4); F ($5, 20, 4); O4 ($3); }
        | float2_op_ni
        ;
+
 float2_op_ni
-       : REG ',' REG
-         { id24 (1, 0x83 + (sub_op << 2), 0); F ($1, 16, 4); F ($3, 20, 4); }
-       | disp '[' REG ']' opt_l ',' REG
-         { id24 (1, 0x80 + (sub_op << 2), 0); F ($3, 16, 4); F ($7, 20, 4); DSP ($1, 14, LSIZE); }
+       : { rx_check_float_support (); } 
+         REG ',' REG
+         { id24 (1, 0x83 + (sub_op << 2), 0); F ($2, 16, 4); F ($4, 20, 4); }
+       | { rx_check_float_support (); }
+         disp '[' REG ']' opt_l ',' REG
+         { id24 (1, 0x80 + (sub_op << 2), 0); F ($4, 16, 4); F ($8, 20, 4); DSP ($2, 14, LSIZE); }
        ;
 
 /* ====================================================================== */
@@ -907,6 +930,10 @@ opt_l      :       {}
        | DOT_L {}
        ;
 
+opt_b  :       {}
+       | DOT_B {}
+       ;
+
 %%
 /* ====================================================================== */
 
@@ -939,7 +966,7 @@ token_table[] =
   { "pc", CREG, 1 },
   { "usp", CREG, 2 },
   { "fpsw", CREG, 3 },
-  { "cpen", CREG, 4 },
+  /* reserved */
   /* reserved */
   /* reserved */
   { "wr", CREG, 7 },
@@ -1170,6 +1197,8 @@ rx_lex (void)
     return 0;
 
   if (ISALPHA (*rx_lex_start)
+      || (rx_pid_register != -1 && memcmp (rx_lex_start, "%pidreg", 7) == 0)
+      || (rx_gp_register != -1 && memcmp (rx_lex_start, "%gpreg", 6) == 0)
       || (*rx_lex_start == '.' && ISALPHA (rx_lex_start[1])))
     {
       unsigned int i;
@@ -1183,6 +1212,28 @@ rx_lex (void)
       save = *e;
       *e = 0;
 
+      if (strcmp (rx_lex_start, "%pidreg") == 0)
+       {
+         {
+           rx_lval.regno = rx_pid_register;
+           *e = save;
+           rx_lex_start = e;
+           rx_last_token = REG;
+           return REG;
+         }
+       }
+
+      if (strcmp (rx_lex_start, "%gpreg") == 0)
+       {
+         {
+           rx_lval.regno = rx_gp_register;
+           *e = save;
+           rx_lex_start = e;
+           rx_last_token = REG;
+           return REG;
+         }
+       }
+
       if (rx_last_token == 0)
        for (ci = 0; ci < NUM_CONDITION_OPCODES; ci ++)
          if (check_condition (condition_opcode_table[ci].string))
@@ -1253,7 +1304,7 @@ rx_lex (void)
 }
 
 int
-rx_error (char * str)
+rx_error (const char * str)
 {
   int len;
 
@@ -1265,9 +1316,10 @@ rx_error (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;
@@ -1275,6 +1327,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:
@@ -1405,7 +1463,7 @@ zero_expr (void)
 }
 
 static int
-immediate (expressionS exp, int type, int pos)
+immediate (expressionS exp, int type, int pos, int bits)
 {
   /* We will emit constants ourself here, so negate them.  */
   if (type == RXREL_NEGATIVE && exp.X_op == O_constant)
@@ -1418,22 +1476,27 @@ immediate (expressionS exp, int type, int pos)
        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_intop (exp, 24))
+  else if (rx_uintop (exp, 16) && bits == 16)
+    {
+      rx_op (exp, 2, type);
+      return 2;
+    }
+  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;
@@ -1482,6 +1545,13 @@ displacement (expressionS exp, int msize)
        }
     }
 
+  if (exp.X_op == O_subtract)
+    {
+      exp.X_md = BFD_RELOC_RX_DIFF;
+      O2 (exp);
+      return 2;
+    }
+
   if (exp.X_op != O_constant)
     {
       rx_error (_("displacements must be constants"));
@@ -1553,3 +1623,23 @@ rtsd_immediate (expressionS exp)
   exp.X_add_number = val;
   O1 (exp);
 }
+
+static void
+rx_range (expressionS exp, int minv, int maxv)
+{
+  int val;
+
+  if (exp.X_op != O_constant)
+    return;
+
+  val = exp.X_add_number;
+  if (val < minv || val > maxv)
+    as_warn (_("Value %d out of range %d..%d"), val, minv, maxv);
+}
+
+static void
+rx_check_float_support (void)
+{
+  if (rx_cpu == RX100 || rx_cpu == RX200)
+    rx_error (_("target CPU type does not support floating point instructions"));
+}
This page took 0.028542 seconds and 4 git commands to generate.