* Fix for PR 18665, from sky branch.
[deliverable/binutils-gdb.git] / opcodes / fr30-asm.c
index 32b47a3109c627432eeb885f938ed9116fd7d8b1..8094201310a10cba525a1f2a8f6145cc430f7cb1 100644 (file)
@@ -59,33 +59,110 @@ static const char * insert_insn_normal
 /* -- asm.c */
 /* Handle register lists for LDMx and STMx  */
 
+static int
+parse_register_number (strp)
+     const char **strp;
+{
+  int regno;
+  if (**strp < '0' || **strp > '9')
+    return -1; /* error */
+  regno = **strp - '0';
+  ++*strp;
+
+  if (**strp >= '0' && **strp <= '9')
+    {
+      regno = regno * 10 + (**strp - '0');
+      ++*strp;
+    }
+
+  return regno;
+}
+
 static const char *
-parse_low_register_list (od, strp, opindex, valuep)
+parse_register_list (od, strp, opindex, valuep, high_low, load_store)
      CGEN_OPCODE_DESC od;
      const char **strp;
      int opindex;
      unsigned long *valuep;
+     int high_low;   /* 0 == high, 1 == low */
+     int load_store; /* 0 == load, 1 == store */
 {
+  int regno;
   *valuep = 0;
   while (**strp && **strp != ')')
     {
+      if (**strp != 'R' && **strp != 'r')
+       break;
       ++*strp;
+
+      regno = parse_register_number (strp);
+      if (regno == -1)
+       return "Register number is not valid";
+      if (regno > 7 && !high_low)
+       return "Register must be between r0 and r7";
+      if (regno < 8 && high_low)
+       return "Register must be between r8 and r15";
+
+      if (high_low)
+       regno -= 8;
+
+      if (load_store) /* mask is reversed for store */
+       *valuep |= 0x80 >> regno;
+      else
+       *valuep |= 1 << regno;
+
+      if (**strp == ',')
+       {
+         if (*(*strp + 1) == ')')
+           break;
+         ++*strp;
+       }
     }
 
-  if (!*strp)
+  if (!*strp || **strp != ')')
     return "Register list is not valid";
 
   return NULL;
 }
 
 static const char *
-parse_hi_register_list (od, strp, opindex, valuep)
+parse_low_register_list_ld (od, strp, opindex, valuep)
+     CGEN_OPCODE_DESC od;
+     const char **strp;
+     int opindex;
+     unsigned long *valuep;
+{
+  return parse_register_list (od, strp, opindex, valuep, 0/*low*/, 0/*load*/);
+}
+
+static const char *
+parse_hi_register_list_ld (od, strp, opindex, valuep)
+     CGEN_OPCODE_DESC od;
+     const char **strp;
+     int opindex;
+     unsigned long *valuep;
+{
+  return parse_register_list (od, strp, opindex, valuep, 1/*high*/, 0/*load*/);
+}
+
+static const char *
+parse_low_register_list_st (od, strp, opindex, valuep)
+     CGEN_OPCODE_DESC od;
+     const char **strp;
+     int opindex;
+     unsigned long *valuep;
+{
+  return parse_register_list (od, strp, opindex, valuep, 0/*low*/, 1/*store*/);
+}
+
+static const char *
+parse_hi_register_list_st (od, strp, opindex, valuep)
      CGEN_OPCODE_DESC od;
      const char **strp;
      int opindex;
      unsigned long *valuep;
 {
-  return parse_low_register_list (od, strp, opindex, valuep);
+  return parse_register_list (od, strp, opindex, valuep, 1/*high*/, 1/*store*/);
 }
 
 /* -- */
@@ -157,9 +234,6 @@ fr30_cgen_parse_operand (od, opindex, strp, fields)
     case FR30_OPERAND_U4C :
       errmsg = cgen_parse_unsigned_integer (od, strp, FR30_OPERAND_U4C, &fields->f_u4c);
       break;
-    case FR30_OPERAND_M4 :
-      errmsg = cgen_parse_unsigned_integer (od, strp, FR30_OPERAND_M4, &fields->f_m4);
-      break;
     case FR30_OPERAND_U8 :
       errmsg = cgen_parse_unsigned_integer (od, strp, FR30_OPERAND_U8, &fields->f_u8);
       break;
@@ -187,16 +261,12 @@ fr30_cgen_parse_operand (od, opindex, strp, fields)
     case FR30_OPERAND_I32 :
       errmsg = cgen_parse_unsigned_integer (od, strp, FR30_OPERAND_I32, &fields->f_i32);
       break;
+    case FR30_OPERAND_M4 :
+      errmsg = cgen_parse_signed_integer (od, strp, FR30_OPERAND_M4, &fields->f_m4);
+      break;
     case FR30_OPERAND_I20 :
       errmsg = cgen_parse_unsigned_integer (od, strp, FR30_OPERAND_I20, &fields->f_i20);
       break;
-    case FR30_OPERAND_LABEL9 :
-      {
-        bfd_vma value;
-        errmsg = cgen_parse_address (od, strp, FR30_OPERAND_LABEL9, 0, NULL,  & value);
-        fields->f_rel9 = value;
-      }
-      break;
     case FR30_OPERAND_DIR8 :
       errmsg = cgen_parse_unsigned_integer (od, strp, FR30_OPERAND_DIR8, &fields->f_dir8);
       break;
@@ -206,6 +276,13 @@ fr30_cgen_parse_operand (od, opindex, strp, fields)
     case FR30_OPERAND_DIR10 :
       errmsg = cgen_parse_unsigned_integer (od, strp, FR30_OPERAND_DIR10, &fields->f_dir10);
       break;
+    case FR30_OPERAND_LABEL9 :
+      {
+        bfd_vma value;
+        errmsg = cgen_parse_address (od, strp, FR30_OPERAND_LABEL9, 0, NULL,  & value);
+        fields->f_rel9 = value;
+      }
+      break;
     case FR30_OPERAND_LABEL12 :
       {
         bfd_vma value;
@@ -213,11 +290,17 @@ fr30_cgen_parse_operand (od, opindex, strp, fields)
         fields->f_rel12 = value;
       }
       break;
-    case FR30_OPERAND_REGLIST_LOW :
-      errmsg = parse_low_register_list (od, strp, FR30_OPERAND_REGLIST_LOW, &fields->f_reglist_low);
+    case FR30_OPERAND_REGLIST_LOW_LD :
+      errmsg = parse_low_register_list_ld (od, strp, FR30_OPERAND_REGLIST_LOW_LD, &fields->f_reglist_low_ld);
       break;
-    case FR30_OPERAND_REGLIST_HI :
-      errmsg = parse_hi_register_list (od, strp, FR30_OPERAND_REGLIST_HI, &fields->f_reglist_hi);
+    case FR30_OPERAND_REGLIST_HI_LD :
+      errmsg = parse_hi_register_list_ld (od, strp, FR30_OPERAND_REGLIST_HI_LD, &fields->f_reglist_hi_ld);
+      break;
+    case FR30_OPERAND_REGLIST_LOW_ST :
+      errmsg = parse_low_register_list_st (od, strp, FR30_OPERAND_REGLIST_LOW_ST, &fields->f_reglist_low_st);
+      break;
+    case FR30_OPERAND_REGLIST_HI_ST :
+      errmsg = parse_hi_register_list_st (od, strp, FR30_OPERAND_REGLIST_HI_ST, &fields->f_reglist_hi_st);
       break;
     case FR30_OPERAND_CC :
       errmsg = cgen_parse_unsigned_integer (od, strp, FR30_OPERAND_CC, &fields->f_cc);
@@ -305,13 +388,6 @@ fr30_cgen_insert_operand (od, opindex, fields, buffer, pc)
     case FR30_OPERAND_U4C :
       errmsg = insert_normal (od, fields->f_u4c, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED), 0, 12, 4, 16, total_length, buffer);
       break;
-    case FR30_OPERAND_M4 :
-      {
-        long value = fields->f_m4;
-        value = ((value) & (15));
-        errmsg = insert_normal (od, value, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED), 0, 8, 4, 16, total_length, buffer);
-      }
-      break;
     case FR30_OPERAND_U8 :
       errmsg = insert_normal (od, fields->f_u8, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED), 0, 8, 8, 16, total_length, buffer);
       break;
@@ -326,27 +402,27 @@ fr30_cgen_insert_operand (od, opindex, fields, buffer, pc)
       }
       break;
     case FR30_OPERAND_DISP8 :
-      errmsg = insert_normal (od, fields->f_disp8, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_SIGNED), 0, 4, 8, 16, total_length, buffer);
+      errmsg = insert_normal (od, fields->f_disp8, 0|(1<<CGEN_OPERAND_HASH_PREFIX), 0, 4, 8, 16, total_length, buffer);
       break;
     case FR30_OPERAND_DISP9 :
       {
         long value = fields->f_disp9;
         value = ((int) (value) >> (1));
-        errmsg = insert_normal (od, value, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_SIGNED), 0, 4, 8, 16, total_length, buffer);
+        errmsg = insert_normal (od, value, 0|(1<<CGEN_OPERAND_HASH_PREFIX), 0, 4, 8, 16, total_length, buffer);
       }
       break;
     case FR30_OPERAND_DISP10 :
       {
         long value = fields->f_disp10;
         value = ((int) (value) >> (2));
-        errmsg = insert_normal (od, value, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_SIGNED), 0, 4, 8, 16, total_length, buffer);
+        errmsg = insert_normal (od, value, 0|(1<<CGEN_OPERAND_HASH_PREFIX), 0, 4, 8, 16, total_length, buffer);
       }
       break;
     case FR30_OPERAND_S10 :
       {
         long value = fields->f_s10;
         value = ((int) (value) >> (2));
-        errmsg = insert_normal (od, value, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_SIGNED), 0, 8, 8, 16, total_length, buffer);
+        errmsg = insert_normal (od, value, 0|(1<<CGEN_OPERAND_HASH_PREFIX), 0, 8, 8, 16, total_length, buffer);
       }
       break;
     case FR30_OPERAND_U10 :
@@ -359,6 +435,13 @@ fr30_cgen_insert_operand (od, opindex, fields, buffer, pc)
     case FR30_OPERAND_I32 :
       errmsg = insert_normal (od, fields->f_i32, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_SIGN_OPT)|(1<<CGEN_OPERAND_UNSIGNED), 16, 0, 32, 32, total_length, buffer);
       break;
+    case FR30_OPERAND_M4 :
+      {
+        long value = fields->f_m4;
+        value = ((value) & (15));
+        errmsg = insert_normal (od, value, 0|(1<<CGEN_OPERAND_UNSIGNED), 0, 8, 4, 16, total_length, buffer);
+      }
+      break;
     case FR30_OPERAND_I20 :
       {
 do {
@@ -373,13 +456,6 @@ do {
           break;
       }
       break;
-    case FR30_OPERAND_LABEL9 :
-      {
-        long value = fields->f_rel9;
-        value = ((int) (((value) - (((pc) + (2))))) >> (1));
-        errmsg = insert_normal (od, value, 0|(1<<CGEN_OPERAND_PCREL_ADDR)|(1<<CGEN_OPERAND_SIGNED), 0, 8, 8, 16, total_length, buffer);
-      }
-      break;
     case FR30_OPERAND_DIR8 :
       errmsg = insert_normal (od, fields->f_dir8, 0|(1<<CGEN_OPERAND_UNSIGNED), 0, 8, 8, 16, total_length, buffer);
       break;
@@ -397,18 +473,31 @@ do {
         errmsg = insert_normal (od, value, 0|(1<<CGEN_OPERAND_UNSIGNED), 0, 8, 8, 16, total_length, buffer);
       }
       break;
+    case FR30_OPERAND_LABEL9 :
+      {
+        long value = fields->f_rel9;
+        value = ((int) (((value) - (((pc) + (2))))) >> (1));
+        errmsg = insert_normal (od, value, 0|(1<<CGEN_OPERAND_PCREL_ADDR), 0, 8, 8, 16, total_length, buffer);
+      }
+      break;
     case FR30_OPERAND_LABEL12 :
       {
         long value = fields->f_rel12;
-        value = ((int) (((value) - (((pc) & (-2))))) >> (1));
-        errmsg = insert_normal (od, value, 0|(1<<CGEN_OPERAND_PCREL_ADDR)|(1<<CGEN_OPERAND_SIGNED), 0, 5, 11, 16, total_length, buffer);
+        value = ((int) (((value) - (((pc) + (2))))) >> (1));
+        errmsg = insert_normal (od, value, 0|(1<<CGEN_OPERAND_PCREL_ADDR), 0, 5, 11, 16, total_length, buffer);
       }
       break;
-    case FR30_OPERAND_REGLIST_LOW :
-      errmsg = insert_normal (od, fields->f_reglist_low, 0|(1<<CGEN_OPERAND_UNSIGNED), 0, 8, 8, 16, total_length, buffer);
+    case FR30_OPERAND_REGLIST_LOW_LD :
+      errmsg = insert_normal (od, fields->f_reglist_low_ld, 0|(1<<CGEN_OPERAND_UNSIGNED), 0, 8, 8, 16, total_length, buffer);
+      break;
+    case FR30_OPERAND_REGLIST_HI_LD :
+      errmsg = insert_normal (od, fields->f_reglist_hi_ld, 0|(1<<CGEN_OPERAND_UNSIGNED), 0, 8, 8, 16, total_length, buffer);
+      break;
+    case FR30_OPERAND_REGLIST_LOW_ST :
+      errmsg = insert_normal (od, fields->f_reglist_low_st, 0|(1<<CGEN_OPERAND_UNSIGNED), 0, 8, 8, 16, total_length, buffer);
       break;
-    case FR30_OPERAND_REGLIST_HI :
-      errmsg = insert_normal (od, fields->f_reglist_hi, 0|(1<<CGEN_OPERAND_UNSIGNED), 0, 8, 8, 16, total_length, buffer);
+    case FR30_OPERAND_REGLIST_HI_ST :
+      errmsg = insert_normal (od, fields->f_reglist_hi_st, 0|(1<<CGEN_OPERAND_UNSIGNED), 0, 8, 8, 16, total_length, buffer);
       break;
     case FR30_OPERAND_CC :
       errmsg = insert_normal (od, fields->f_cc, 0|(1<<CGEN_OPERAND_UNSIGNED), 0, 4, 4, 16, total_length, buffer);
@@ -585,7 +674,7 @@ insert_normal (od, value, attrs, word_offset, start, length, word_length,
 #endif
 
   /* Ensure VALUE will fit.  */
-  if ((attrs & CGEN_ATTR_MASK (CGEN_OPERAND_UNSIGNED)) != 0)
+  if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_UNSIGNED))
     {
       unsigned long maxval = mask;
       if ((unsigned long) value > maxval)
This page took 0.026759 seconds and 4 git commands to generate.