[PATCH 41/57][Arm][OBJDUMP] Add support for MVE instructions: vld[24] and vst[24]
authorAndre Vieira <andre.simoesdiasvieira@arm.com>
Thu, 16 May 2019 13:04:35 +0000 (14:04 +0100)
committerAndre Vieira <andre.simoesdiasvieira@arm.com>
Thu, 16 May 2019 15:37:17 +0000 (16:37 +0100)
opcodes/ChangeLog:
2019-05-16  Andre Vieira  <andre.simoesdiasvieira@arm.com>
    Michael Collison <michael.collison@arm.com>

* arm-dis.c (enum mve_instructions): Add new instructions.
(enum mve_unpredictable): Add new reasons.
(is_mve_encoding_conflict): Handle new instructions.
(is_mve_unpredictable): Likewise.
(mve_opcodes): Add new instructions.
(print_mve_unpredictable): Handle new reasons.
(print_mve_register_blocks): New print function.
(print_mve_size): Handle new instructions.
(print_insn_mve): Likewise.

opcodes/ChangeLog
opcodes/arm-dis.c

index ef6d3e8..25a86e2 100644 (file)
@@ -3,6 +3,19 @@
 
        * arm-dis.c (enum mve_instructions): Add new instructions.
        (enum mve_unpredictable): Add new reasons.
 
        * arm-dis.c (enum mve_instructions): Add new instructions.
        (enum mve_unpredictable): Add new reasons.
+       (is_mve_encoding_conflict): Handle new instructions.
+       (is_mve_unpredictable): Likewise.
+       (mve_opcodes): Add new instructions.
+       (print_mve_unpredictable): Handle new reasons.
+       (print_mve_register_blocks): New print function.
+       (print_mve_size): Handle new instructions.
+       (print_insn_mve): Likewise.
+
+2019-05-16  Andre Vieira  <andre.simoesdiasvieira@arm.com>
+           Michael Collison <michael.collison@arm.com>
+
+       * arm-dis.c (enum mve_instructions): Add new instructions.
+       (enum mve_unpredictable): Add new reasons.
        (enum mve_undefined): Likewise.
        (is_mve_encoding_conflict): Handle new instructions.
        (is_mve_undefined): Likewise.
        (enum mve_undefined): Likewise.
        (is_mve_encoding_conflict): Handle new instructions.
        (is_mve_undefined): Likewise.
index 75cc27b..8ebf227 100644 (file)
@@ -98,6 +98,10 @@ enum mve_instructions
   MVE_VHSUB_T1,
   MVE_VHSUB_T2,
   MVE_VRHADD,
   MVE_VHSUB_T1,
   MVE_VHSUB_T2,
   MVE_VRHADD,
+  MVE_VLD2,
+  MVE_VLD4,
+  MVE_VST2,
+  MVE_VST4,
   MVE_NONE
 };
 
   MVE_NONE
 };
 
@@ -110,6 +114,12 @@ enum mve_unpredictable
   UNPRED_R13,                  /* Unpredictable because r13 (sp) or
                                   r15 (sp) used.  */
   UNPRED_R15,                  /* Unpredictable because r15 (pc) is used.  */
   UNPRED_R13,                  /* Unpredictable because r13 (sp) or
                                   r15 (sp) used.  */
   UNPRED_R15,                  /* Unpredictable because r15 (pc) is used.  */
+  UNPRED_Q_GT_4,               /* Unpredictable because
+                                  vec reg start > 4 (vld4/st4).  */
+  UNPRED_Q_GT_6,               /* Unpredictable because
+                                  vec reg start > 6 (vld2/st2).  */
+  UNPRED_R13_AND_WB,           /* Unpredictable becase gp reg = r13
+                                  and WB bit = 1.  */
   UNPRED_NONE                  /* No unpredictable behavior.  */
 };
 
   UNPRED_NONE                  /* No unpredictable behavior.  */
 };
 
@@ -1823,7 +1833,11 @@ static const struct opcode32 neon_opcodes[] =
    %n                  print vector comparison code for predicated instruction
    %v                  print vector predicate for instruction in predicated
                        block
    %n                  print vector comparison code for predicated instruction
    %v                  print vector predicate for instruction in predicated
                        block
+   %w                  print writeback mode for MVE v{st,ld}[24]
+   %B                  print v{st,ld}[24] any one operands
+
    %<bitfield>r                print as an ARM register
    %<bitfield>r                print as an ARM register
+   %<bitfield>d                print the bitfield in decimal
    %<bitfield>Q                print as a MVE Q register
    %<bitfield>Z                as %<>r but r15 is ZR instead of PC and r13 is
                        UNPREDICTABLE
    %<bitfield>Q                print as a MVE Q register
    %<bitfield>Z                as %<>r but r15 is ZR instead of PC and r13 is
                        UNPREDICTABLE
@@ -1997,6 +2011,42 @@ static const struct mopcode32 mve_opcodes[] =
    0xef000140, 0xef811f51,
    "vrhadd%v.%u%20-21s\t%13-15,22Q, %17-19,7Q, %1-3,5Q"},
 
    0xef000140, 0xef811f51,
    "vrhadd%v.%u%20-21s\t%13-15,22Q, %17-19,7Q, %1-3,5Q"},
 
+  /* Vector VLD2.  */
+  {ARM_FEATURE_COPROC (FPU_MVE),
+   MVE_VLD2,
+   0xfc901e00, 0xff901e5f,
+   "vld2%5d.%7-8s\t%B, [%16-19r]%w"},
+
+  /* Vector VLD4.  */
+  {ARM_FEATURE_COPROC (FPU_MVE),
+   MVE_VLD4,
+   0xfc901e01, 0xff901e1f,
+   "vld4%5-6d.%7-8s\t%B, [%16-19r]%w"},
+
+  /* Vector VST2 no writeback.  */
+  {ARM_FEATURE_COPROC (FPU_MVE),
+   MVE_VST2,
+   0xfc801e00, 0xffb01e5f,
+   "vst2%5d.%7-8s\t%B, [%16-19r]"},
+
+  /* Vector VST2 writeback.  */
+  {ARM_FEATURE_COPROC (FPU_MVE),
+   MVE_VST2,
+   0xfca01e00, 0xffb01e5f,
+   "vst2%5d.%7-8s\t%B, [%16-19r]!"},
+
+  /* Vector VST4 no writeback.  */
+  {ARM_FEATURE_COPROC (FPU_MVE),
+   MVE_VST4,
+   0xfc801e01, 0xffb01e1f,
+   "vst4%5-6d.%7-8s\t%B, [%16-19r]"},
+
+  /* Vector VST4 writeback.  */
+  {ARM_FEATURE_COPROC (FPU_MVE),
+   MVE_VST4,
+   0xfca01e01, 0xffb01e1f,
+   "vst4%5-6d.%7-8s\t%B, [%16-19r]!"},
+
   {ARM_FEATURE_CORE_LOW (0),
    MVE_NONE,
    0x00000000, 0x00000000, 0}
   {ARM_FEATURE_CORE_LOW (0),
    MVE_NONE,
    0x00000000, 0x00000000, 0}
@@ -4015,6 +4065,15 @@ is_mve_encoding_conflict (unsigned long given,
       else
        return FALSE;
 
       else
        return FALSE;
 
+    case MVE_VLD2:
+    case MVE_VLD4:
+    case MVE_VST2:
+    case MVE_VST4:
+      if (arm_decode_field (given, 7, 8) == 3)
+       return TRUE;
+      else
+       return FALSE;
+
     default:
       return FALSE;
 
     default:
       return FALSE;
 
@@ -4132,6 +4191,58 @@ is_mve_unpredictable (unsigned long given, enum mve_instructions matched_insn,
        return FALSE;
       }
 
        return FALSE;
       }
 
+    case MVE_VLD2:
+    case MVE_VST2:
+      {
+       unsigned long rn = arm_decode_field (given, 16, 19);
+
+       if ((rn == 0xd) && (arm_decode_field (given, 21, 21) == 1))
+         {
+           *unpredictable_code = UNPRED_R13_AND_WB;
+           return TRUE;
+         }
+
+       if (rn == 0xf)
+         {
+           *unpredictable_code = UNPRED_R15;
+           return TRUE;
+         }
+
+       if (arm_decode_field_multiple (given, 13, 15, 22, 22) > 6)
+         {
+           *unpredictable_code = UNPRED_Q_GT_6;
+           return TRUE;
+         }
+       else
+         return FALSE;
+      }
+
+    case MVE_VLD4:
+    case MVE_VST4:
+      {
+       unsigned long rn = arm_decode_field (given, 16, 19);
+
+       if ((rn == 0xd) && (arm_decode_field (given, 21, 21) == 1))
+         {
+           *unpredictable_code = UNPRED_R13_AND_WB;
+           return TRUE;
+         }
+
+       if (rn == 0xf)
+         {
+           *unpredictable_code = UNPRED_R15;
+           return TRUE;
+         }
+
+       if (arm_decode_field_multiple (given, 13, 15, 22, 22) > 4)
+         {
+           *unpredictable_code = UNPRED_Q_GT_4;
+           return TRUE;
+         }
+       else
+         return FALSE;
+      }
+
     default:
       return FALSE;
     }
     default:
       return FALSE;
     }
@@ -4185,11 +4296,61 @@ print_mve_unpredictable (struct disassemble_info *info,
       func (stream, "use of r15 (pc)");
       break;
 
       func (stream, "use of r15 (pc)");
       break;
 
+    case UNPRED_Q_GT_4:
+      func (stream, "start register block > r4");
+      break;
+
+    case UNPRED_Q_GT_6:
+      func (stream, "start register block > r6");
+      break;
+
+    case UNPRED_R13_AND_WB:
+      func (stream, "use of r13 and write back");
+      break;
+
     case UNPRED_NONE:
       break;
     }
 }
 
     case UNPRED_NONE:
       break;
     }
 }
 
+/* Print register block operand for mve vld2/vld4/vst2/vld4.  */
+
+static void
+print_mve_register_blocks (struct disassemble_info *info,
+                          unsigned long given,
+                          enum mve_instructions matched_insn)
+{
+  void *stream = info->stream;
+  fprintf_ftype func = info->fprintf_func;
+
+  unsigned long q_reg_start = arm_decode_field_multiple (given,
+                                                        13, 15,
+                                                        22, 22);
+  switch (matched_insn)
+    {
+    case MVE_VLD2:
+    case MVE_VST2:
+      if (q_reg_start <= 6)
+       func (stream, "{q%ld, q%ld}", q_reg_start, q_reg_start + 1);
+      else
+       func (stream, "<illegal reg q%ld>", q_reg_start);
+      break;
+
+    case MVE_VLD4:
+    case MVE_VST4:
+      if (q_reg_start <= 4)
+       func (stream, "{q%ld, q%ld, q%ld, q%ld}", q_reg_start,
+             q_reg_start + 1, q_reg_start + 2,
+             q_reg_start + 3);
+      else
+       func (stream, "<illegal reg q%ld>", q_reg_start);
+      break;
+
+    default:
+      break;
+    }
+}
+
 static void
 print_instruction_predicate (struct disassemble_info *info)
 {
 static void
 print_instruction_predicate (struct disassemble_info *info)
 {
@@ -4222,6 +4383,8 @@ print_mve_size (struct disassemble_info *info,
     case MVE_VHADD_T2:
     case MVE_VHSUB_T1:
     case MVE_VHSUB_T2:
     case MVE_VHADD_T2:
     case MVE_VHSUB_T1:
     case MVE_VHSUB_T2:
+    case MVE_VLD2:
+    case MVE_VLD4:
     case MVE_VPT_VEC_T1:
     case MVE_VPT_VEC_T2:
     case MVE_VPT_VEC_T3:
     case MVE_VPT_VEC_T1:
     case MVE_VPT_VEC_T2:
     case MVE_VPT_VEC_T3:
@@ -4229,6 +4392,8 @@ print_mve_size (struct disassemble_info *info,
     case MVE_VPT_VEC_T5:
     case MVE_VPT_VEC_T6:
     case MVE_VRHADD:
     case MVE_VPT_VEC_T5:
     case MVE_VPT_VEC_T6:
     case MVE_VRHADD:
+    case MVE_VST2:
+    case MVE_VST4:
       if (size <= 3)
        func (stream, "%s", mve_vec_sizename[size]);
       else
       if (size <= 3)
        func (stream, "%s", mve_vec_sizename[size]);
       else
@@ -5721,6 +5886,15 @@ print_insn_mve (struct disassemble_info *info, long given)
                      print_instruction_predicate (info);
                      break;
 
                      print_instruction_predicate (info);
                      break;
 
+                   case 'w':
+                     if (arm_decode_field (given, 21, 21) == 1)
+                       func (stream, "!");
+                     break;
+
+                   case 'B':
+                     print_mve_register_blocks (info, given, insn->mve_op);
+                     break;
+
                    case '0': case '1': case '2': case '3': case '4':
                    case '5': case '6': case '7': case '8': case '9':
                      {
                    case '0': case '1': case '2': case '3': case '4':
                    case '5': case '6': case '7': case '8': case '9':
                      {
@@ -5747,6 +5921,10 @@ print_insn_mve (struct disassemble_info *info, long given)
                          case 'r':
                            func (stream, "%s", arm_regnames[value]);
                            break;
                          case 'r':
                            func (stream, "%s", arm_regnames[value]);
                            break;
+                         case 'd':
+                           func (stream, "%ld", value);
+                           value_in_comment = value;
+                           break;
                          case 'Q':
                            if (value & 0x8)
                              func (stream, "<illegal reg q%ld.5>", value);
                          case 'Q':
                            if (value & 0x8)
                              func (stream, "<illegal reg q%ld.5>", value);