Tidy up decoding of shift based addressing modes.
authorNick Clifton <nickc@redhat.com>
Wed, 16 Aug 2000 19:02:00 +0000 (19:02 +0000)
committerNick Clifton <nickc@redhat.com>
Wed, 16 Aug 2000 19:02:00 +0000 (19:02 +0000)
Add extra tests for these addressing modes

gas/ChangeLog
gas/config/tc-arm.c
gas/testsuite/ChangeLog
gas/testsuite/gas/arm/inst.d
gas/testsuite/gas/arm/inst.s

index 49bce914e97fe577218beb288df67499c0be8540..f494672e58baf130054bf7a3cf833cfb7fda5d85 100644 (file)
@@ -1,3 +1,20 @@
+2000-08-16  Nick Clifton  <nickc@redhat.com>
+
+       * config/tc-arm.c (struct asm_shift): Delete.
+       (shift[]): Delete.
+       (enum asm_shift_index): New.
+       (struct asm_shift_properties): New.
+       (struct asm_shift_name): New.
+       (shift_properties[]); New.
+       (shift_names[]); New.
+
+       (decode_shift): Use new structures.
+       Issue a warning is "ROR #0" is used.
+       Issue a warning if "ASR #0" or "LSR #0" is used.
+
+       (md_begin): Initialise arm_shift_hsh table from new
+       asm_shift_name array.
+
 2000-08-16  Jakub Jelinek  <jakub@redhat.com>
 
        * config/tc-sparc.c: Kill all warnings.
index 5ca0815288f6f1943c17e8609719636bc6eda413..a2ae26f8c55bfaab5d7d3dc585c9e8ea61e0eeb0 100644 (file)
@@ -166,28 +166,54 @@ struct arm_it
 
 struct arm_it inst;
 
-struct asm_shift
+enum asm_shift_index
 {
-  CONST char *  template;
-  unsigned long value;
+  SHIFT_LSL = 0,
+  SHIFT_LSR,
+  SHIFT_ASR,
+  SHIFT_ROR,
+  SHIFT_RRX
+};
+
+struct asm_shift_properties
+{
+  enum asm_shift_index index;
+  unsigned long        bit_field;
+  unsigned int         allows_0  : 1;
+  unsigned int         allows_32 : 1;
 };
 
-static CONST struct asm_shift shift[] =
-{
-  {"asl", 0},
-  {"lsl", 0},
-  {"lsr", 0x00000020},
-  {"asr", 0x00000040},
-  {"ror", 0x00000060},
-  {"rrx", 0x00000060},
-  {"ASL", 0},
-  {"LSL", 0},
-  {"LSR", 0x00000020},
-  {"ASR", 0x00000040},
-  {"ROR", 0x00000060},
-  {"RRX", 0x00000060}
+static const struct asm_shift_properties shift_properties [] =
+{
+  { SHIFT_LSL, 0,    1, 0},
+  { SHIFT_LSR, 0x20, 0, 1},
+  { SHIFT_ASR, 0x40, 0, 1},
+  { SHIFT_ROR, 0x60, 0, 0},
+  { SHIFT_RRX, 0x60, 0, 0}
+};
+
+struct asm_shift_name
+{
+  const char *                        name;
+  const struct asm_shift_properties * properties;
 };
 
+static const struct asm_shift_name shift_names [] =
+{
+  { "asl", shift_properties + SHIFT_LSL },
+  { "lsl", shift_properties + SHIFT_LSL },
+  { "lsr", shift_properties + SHIFT_LSR },
+  { "asr", shift_properties + SHIFT_ASR },
+  { "ror", shift_properties + SHIFT_ROR },
+  { "rrx", shift_properties + SHIFT_RRX },
+  { "ASL", shift_properties + SHIFT_LSL },
+  { "LSL", shift_properties + SHIFT_LSL },
+  { "LSR", shift_properties + SHIFT_LSR },
+  { "ASR", shift_properties + SHIFT_ASR },
+  { "ROR", shift_properties + SHIFT_ROR },
+  { "RRX", shift_properties + SHIFT_RRX }
+};
+  
 #define NO_SHIFT_RESTRICT 1
 #define SHIFT_RESTRICT   0
 
@@ -2505,7 +2531,7 @@ decode_shift (str, unrestrict)
      char ** str;
      int     unrestrict;
 {
-  struct asm_shift * shft;
+  struct asm_shift_name * shift;
   char * p;
   char   c;
 
@@ -2522,83 +2548,87 @@ decode_shift (str, unrestrict)
 
   c = * p;
   * p = '\0';
-  shft = (struct asm_shift *) hash_find (arm_shift_hsh, * str);
+  shift = (struct asm_shift_name *) hash_find (arm_shift_hsh, * str);
   * p = c;
-  if (shft)
+  
+  if (shift == NULL)
     {
-      if (   ! strncmp (* str, "rrx", 3)
-          || ! strncmp (* str, "RRX", 3))
-       {
-         * str = p;
-         inst.instruction |= shft->value;
-         return SUCCESS;
-       }
+      inst.error = _("Shift expression expected");
+      return FAIL;
+    }
 
-      skip_whitespace (p);
+  assert (shift->properties->index == shift_properties[shift->properties->index].index);
+  
+  if (shift->properties->index == SHIFT_RRX)
+    {
+      * str = p;
+      inst.instruction |= shift->properties->bit_field;
+      return SUCCESS;
+    }
 
-      if (unrestrict && reg_required_here (& p, 8) != FAIL)
-       {
-         inst.instruction |= shft->value | SHIFT_BY_REG;
-         * str = p;
-         return SUCCESS;
-       }
-      else if (is_immediate_prefix (* p))
-       {
-         inst.error = NULL;
-         p ++;
+  skip_whitespace (p);
 
-         if (my_get_expression (& inst.reloc.exp, & p))
-           return FAIL;
+  if (unrestrict && reg_required_here (& p, 8) != FAIL)
+    {
+      inst.instruction |= shift->properties->bit_field | SHIFT_BY_REG;
+      * str = p;
+      return SUCCESS;
+    }
+  else if (! is_immediate_prefix (* p))
+    {
+      inst.error = (unrestrict
+                   ? _("shift requires register or #expression")
+                   : _("shift requires #expression"));
+      * str = p;
+      return FAIL;
+    }
+    
+  inst.error = NULL;
+  p ++;
+  
+  if (my_get_expression (& inst.reloc.exp, & p))
+    return FAIL;
+  
+  /* Validate some simple #expressions.  */
+  if (inst.reloc.exp.X_op == O_constant)
+    {
+      unsigned num = inst.reloc.exp.X_add_number;
 
-         /* Validate some simple #expressions.  */
-         if (inst.reloc.exp.X_op == O_constant)
+      /* Reject operations greater than 32.  */
+      if (num > 32
+         /* Reject a shift of 0 unless the mode allows it.  */
+         || (num == 0 && shift->properties->allows_0 == 0)
+         /* Reject a shift of 32 unless the mode allows it.  */
+         || (num == 32 && shift->properties->allows_32 == 0)
+         )
+       {
+         /* As a special case we allow ROR #0, but we issue a message
+            reminding the programmer that this is actually an RRX.  */
+         if (num == 0 && shift->properties->index == SHIFT_ROR)
+           as_tsktsk (_("ROR #0 is actually RRX"));
+         else
            {
-             unsigned num = inst.reloc.exp.X_add_number;
-
-             /* Reject operations greater than 32, or lsl #32.  */
-             if (num > 32 || (num == 32 && shft->value == 0))
-               {
-                 inst.error = _("Invalid immediate shift");
-                 return FAIL;
-               }
-
-             /* Shifts of zero should be converted to lsl
-                (which is zero).  */
-             if (num == 0)
-               {
-                 * str = p;
-                 return SUCCESS;
-               }
-
-             /* Shifts of 32 are encoded as 0, for those shifts that
-                support it.  */
-             if (num == 32)
-               num = 0;
-
-             inst.instruction |= (num << 7) | shft->value;
-             * str = p;
-             return SUCCESS;
+             inst.error = _("Invalid immediate shift");
+             return FAIL;
            }
-
-         inst.reloc.type   = BFD_RELOC_ARM_SHIFT_IMM;
-         inst.reloc.pc_rel = 0;
-         inst.instruction |= shft->value;
-
-         * str = p;
-         return SUCCESS;
-       }
-      else
-       {
-         inst.error = (unrestrict
-                       ? _("shift requires register or #expression")
-                       : _("shift requires #expression"));
-         * str = p;
-         return FAIL;
        }
-    }
 
-  inst.error = _("Shift expression expected");
-  return FAIL;
+      /* Shifts of 32 are encoded as 0, for those shifts that
+        support it.  */
+      if (num == 32)
+       num = 0;
+      
+      inst.instruction |= (num << 7) | shift->properties->bit_field;
+    }
+  else
+    {
+      inst.reloc.type   = BFD_RELOC_ARM_SHIFT_IMM;
+      inst.reloc.pc_rel = 0;
+      inst.instruction |= shift->properties->bit_field;
+    }
+  
+  * str = p;
+  return SUCCESS;
 }
 
 /* Do those data_ops which can take a negative immediate constant
@@ -5240,8 +5270,8 @@ md_begin ()
     hash_insert (arm_tops_hsh, tinsns[i].template, (PTR) (tinsns + i));
   for (i = 0; i < sizeof (conds) / sizeof (struct asm_cond); i++)
     hash_insert (arm_cond_hsh, conds[i].template, (PTR) (conds + i));
-  for (i = 0; i < sizeof (shift) / sizeof (struct asm_shift); i++)
-    hash_insert (arm_shift_hsh, shift[i].template, (PTR) (shift + i));
+  for (i = 0; i < sizeof (shift_names) / sizeof (struct asm_shift_name); i++)
+    hash_insert (arm_shift_hsh, shift_names[i].name, (PTR) (shift_names + i));
   for (i = 0; i < sizeof (psrs) / sizeof (struct asm_psr); i++)
     hash_insert (arm_psr_hsh, psrs[i].template, (PTR) (psrs + i));
 
@@ -7388,7 +7418,7 @@ arm_parse_reloc ()
   }
   reloc_map[] =
   {
-#define MAP(str,reloc) { str, sizeof (str)-1, reloc }
+#define MAP(str,reloc) { str, sizeof (str) - 1, reloc }
     MAP ("(got)",    BFD_RELOC_ARM_GOT32),
     MAP ("(gotoff)", BFD_RELOC_ARM_GOTOFF),
     /* ScottB: Jan 30, 1998 - Added support for parsing "var(PLT)"
index d815495219bc544253aca12242bb39c8cd464ff3..4cdeffbfca84a1e6fa3c9668cc26b66d9c9cdea5 100644 (file)
@@ -1,3 +1,10 @@
+2000-08-16  Nick Clifton  <nickc@redhat.com>
+
+       * gas/arm/inst.s: Add tests for edge cases of shift based
+        addressing modes.
+
+       * gas/arm/inst.d: Add expected results for new tests.
+
 2000-07-20  Hans-Peter Nilsson  <hp@axis.com>
 
        * gas/all/gas.exp: Don't run floating-point tests on CRIS.
index 041f65b788d95047136ecb44a466a127407bce76..70fff23805c06f8d532e894239dadae68838d5ec 100644 (file)
@@ -167,3 +167,35 @@ Disassembly of section .text:
 [              ]*268:.*_wibble.*
 0000026c <[^>]*> dafffffe ?    ble     0000026c <[^>]*>
 [              ]*26c:.*testerfunc.*
+00000270 <[^>]*> e1a01102 ?    mov     r1, r2, lsl #2
+00000274 <[^>]*> e1a01002 ?    mov     r1, r2
+00000278 <[^>]*> e1a01f82 ?    mov     r1, r2, lsl #31
+0000027c <[^>]*> e1a01312 ?    mov     r1, r2, lsl r3
+00000280 <[^>]*> e1a01122 ?    mov     r1, r2, lsr #2
+00000284 <[^>]*> e1a01fa2 ?    mov     r1, r2, lsr #31
+00000288 <[^>]*> e1a01022 ?    mov     r1, r2, lsr #32
+0000028c <[^>]*> e1a01332 ?    mov     r1, r2, lsr r3
+00000290 <[^>]*> e1a01142 ?    mov     r1, r2, asr #2
+00000294 <[^>]*> e1a01fc2 ?    mov     r1, r2, asr #31
+00000298 <[^>]*> e1a01042 ?    mov     r1, r2, asr #32
+0000029c <[^>]*> e1a01352 ?    mov     r1, r2, asr r3
+000002a0 <[^>]*> e1a01162 ?    mov     r1, r2, ror #2
+000002a4 <[^>]*> e1a01fe2 ?    mov     r1, r2, ror #31
+000002a8 <[^>]*> e1a01372 ?    mov     r1, r2, ror r3
+000002ac <[^>]*> e1a01062 ?    mov     r1, r2, rrx
+000002b0 <[^>]*> e1a01102 ?    mov     r1, r2, lsl #2
+000002b4 <[^>]*> e1a01002 ?    mov     r1, r2
+000002b8 <[^>]*> e1a01f82 ?    mov     r1, r2, lsl #31
+000002bc <[^>]*> e1a01312 ?    mov     r1, r2, lsl r3
+000002c0 <[^>]*> e1a01122 ?    mov     r1, r2, lsr #2
+000002c4 <[^>]*> e1a01fa2 ?    mov     r1, r2, lsr #31
+000002c8 <[^>]*> e1a01022 ?    mov     r1, r2, lsr #32
+000002cc <[^>]*> e1a01332 ?    mov     r1, r2, lsr r3
+000002d0 <[^>]*> e1a01142 ?    mov     r1, r2, asr #2
+000002d4 <[^>]*> e1a01fc2 ?    mov     r1, r2, asr #31
+000002d8 <[^>]*> e1a01042 ?    mov     r1, r2, asr #32
+000002dc <[^>]*> e1a01352 ?    mov     r1, r2, asr r3
+000002e0 <[^>]*> e1a01162 ?    mov     r1, r2, ror #2
+000002e4 <[^>]*> e1a01fe2 ?    mov     r1, r2, ror #31
+000002e8 <[^>]*> e1a01372 ?    mov     r1, r2, ror r3
+000002ec <[^>]*> e1a01062 ?    mov     r1, r2, rrx
index f76bac9e4b696b4ff4729b2bcabbc3604b6f6f73..b162cfceca0d2b90df56ca6486c3953f210148db 100644 (file)
@@ -187,3 +187,37 @@ bar:
        blpl    hohum
        b       _wibble
        ble     testerfunc
+
+       mov r1, r2, lsl #2
+       mov r1, r2, lsl #0 
+       mov r1, r2, lsl #31
+       mov r1, r2, lsl r3
+       mov r1, r2, lsr #2
+       mov r1, r2, lsr #31
+       mov r1, r2, lsr #32
+       mov r1, r2, lsr r3
+       mov r1, r2, asr #2
+       mov r1, r2, asr #31
+       mov r1, r2, asr #32
+       mov r1, r2, asr r3
+       mov r1, r2, ror #2
+       mov r1, r2, ror #31
+       mov r1, r2, ror r3
+       mov r1, r2, rrx
+       mov r1, r2, LSL #2
+       mov r1, r2, LSL #0 
+       mov r1, r2, LSL #31
+       mov r1, r2, LSL r3
+       mov r1, r2, LSR #2
+       mov r1, r2, LSR #31
+       mov r1, r2, LSR #32
+       mov r1, r2, LSR r3
+       mov r1, r2, ASR #2
+       mov r1, r2, ASR #31
+       mov r1, r2, ASR #32
+       mov r1, r2, ASR r3
+       mov r1, r2, ROR #2
+       mov r1, r2, ROR #31
+       mov r1, r2, ROR r3
+       mov r1, r2, RRX
+       
\ No newline at end of file