This is the mail archive of the binutils-cvs@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[binutils-gdb] [PATCH 42/57][Arm][OBJDUMP] Add support for MVE instructions: vldr[bhw] and vstr[bhw]


https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=aef6d006581cab8a858e7abd36c57e73ea6e97a2

commit aef6d006581cab8a858e7abd36c57e73ea6e97a2
Author: Andre Vieira <andre.simoesdiasvieira@arm.com>
Date:   Thu May 16 14:05:38 2019 +0100

    [PATCH 42/57][Arm][OBJDUMP] Add support for MVE instructions: vldr[bhw] and vstr[bhw]
    
    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_undefined): Add new reasons.
    	(insns): Add new instructions.
    	(is_mve_encoding_conflict):
    	(print_mve_vld_str_addr): New print function.
    	(is_mve_undefined): Handle new instructions.
    	(is_mve_unpredictable): Likewise.
    	(print_mve_undefined): Likewise.
    	(print_mve_size): Likewise.
    	(print_insn_coprocessor_1): Handle MVE VLDR, VSTR instructions.
    	(print_insn_mve):  Handle new operands.

Diff:
---
 opcodes/ChangeLog |  15 ++++
 opcodes/arm-dis.c | 263 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 278 insertions(+)

diff --git a/opcodes/ChangeLog b/opcodes/ChangeLog
index 25a86e2..3fd0227 100644
--- a/opcodes/ChangeLog
+++ b/opcodes/ChangeLog
@@ -2,6 +2,21 @@
 	    Michael Collison <michael.collison@arm.com>
 
 	* arm-dis.c (enum mve_instructions): Add new instructions.
+	(enum mve_undefined): Add new reasons.
+	(insns): Add new instructions.
+	(is_mve_encoding_conflict):
+	(print_mve_vld_str_addr): New print function.
+	(is_mve_undefined): Handle new instructions.
+	(is_mve_unpredictable): Likewise.
+	(print_mve_undefined): Likewise.
+	(print_mve_size): Likewise.
+	(print_insn_coprocessor_1): Handle MVE VLDR, VSTR instructions.
+	(print_insn_mve):  Handle new operands.
+
+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.
diff --git a/opcodes/arm-dis.c b/opcodes/arm-dis.c
index 8ebf227..6d167ae 100644
--- a/opcodes/arm-dis.c
+++ b/opcodes/arm-dis.c
@@ -102,6 +102,16 @@ enum mve_instructions
   MVE_VLD4,
   MVE_VST2,
   MVE_VST4,
+  MVE_VLDRB_T1,
+  MVE_VLDRH_T2,
+  MVE_VLDRB_T5,
+  MVE_VLDRH_T6,
+  MVE_VLDRW_T7,
+  MVE_VSTRB_T1,
+  MVE_VSTRH_T2,
+  MVE_VSTRB_T5,
+  MVE_VSTRH_T6,
+  MVE_VSTRW_T7,
   MVE_NONE
 };
 
@@ -126,6 +136,8 @@ enum mve_unpredictable
 enum mve_undefined
 {
   UNDEF_SIZE_3,			/* undefined because size == 3.  */
+  UNDEF_SIZE_3,			/* undefined because size == 3.  */
+  UNDEF_SIZE_LE_1,		/* undefined because size <= 1.  */
   UNDEF_NONE			/* no undefined behavior.  */
 };
 
@@ -1829,6 +1841,8 @@ static const struct opcode32 neon_opcodes[] =
    %%			%
 
    %c			print condition code
+   %d			print addr mode of MVE vldr[bhw] and vstr[bhw]
+   %u			print 'U' (unsigned) or 'S' for various mve instructions
    %i			print MVE predicate(s) for vpt and vpst
    %n			print vector comparison code for predicated instruction
    %v			print vector predicate for instruction in predicated
@@ -2023,6 +2037,36 @@ static const struct mopcode32 mve_opcodes[] =
    0xfc901e01, 0xff901e1f,
    "vld4%5-6d.%7-8s\t%B, [%16-19r]%w"},
 
+  /* Vector VLDRB.  */
+  {ARM_FEATURE_COPROC (FPU_MVE),
+   MVE_VLDRB_T1,
+   0xec100e00, 0xee581e00,
+   "vldrb%v.%u%7-8s\t%13-15Q, %d"},
+
+  /* Vector VLDRH.  */
+  {ARM_FEATURE_COPROC (FPU_MVE),
+   MVE_VLDRH_T2,
+   0xec180e00, 0xee581e00,
+   "vldrh%v.%u%7-8s\t%13-15Q, %d"},
+
+  /* Vector VLDRB unsigned, variant T5.  */
+  {ARM_FEATURE_COPROC (FPU_MVE),
+   MVE_VLDRB_T5,
+   0xec101e00, 0xfe101f80,
+   "vldrb%v.u8\t%13-15,22Q, %d"},
+
+  /* Vector VLDRH unsigned, variant T6.  */
+  {ARM_FEATURE_COPROC (FPU_MVE),
+   MVE_VLDRH_T6,
+   0xec101e80, 0xfe101f80,
+   "vldrh%v.u16\t%13-15,22Q, %d"},
+
+  /* Vector VLDRW unsigned, variant T7.  */
+  {ARM_FEATURE_COPROC (FPU_MVE),
+   MVE_VLDRW_T7,
+   0xec101f00, 0xfe101f80,
+   "vldrw%v.u32\t%13-15,22Q, %d"},
+
   /* Vector VST2 no writeback.  */
   {ARM_FEATURE_COPROC (FPU_MVE),
    MVE_VST2,
@@ -2047,6 +2091,36 @@ static const struct mopcode32 mve_opcodes[] =
    0xfca01e01, 0xffb01e1f,
    "vst4%5-6d.%7-8s\t%B, [%16-19r]!"},
 
+  /* Vector VSTRB.  */
+  {ARM_FEATURE_COPROC (FPU_MVE),
+   MVE_VSTRB_T1,
+   0xec000e00, 0xfe581e00,
+   "vstrb%v.%7-8s\t%13-15Q, %d"},
+
+  /* Vector VSTRH.  */
+  {ARM_FEATURE_COPROC (FPU_MVE),
+   MVE_VSTRH_T2,
+   0xec080e00, 0xfe581e00,
+   "vstrh%v.%7-8s\t%13-15Q, %d"},
+
+  /* Vector VSTRB variant T5.  */
+  {ARM_FEATURE_COPROC (FPU_MVE),
+   MVE_VSTRB_T5,
+   0xec001e00, 0xfe101f80,
+   "vstrb%v.8\t%13-15,22Q, %d"},
+
+  /* Vector VSTRH variant T6.  */
+  {ARM_FEATURE_COPROC (FPU_MVE),
+   MVE_VSTRH_T6,
+   0xec001e80, 0xfe101f80,
+   "vstrh%v.16\t%13-15,22Q, %d"},
+
+  /* Vector VSTRW variant T7.  */
+  {ARM_FEATURE_COPROC (FPU_MVE),
+   MVE_VSTRW_T7,
+   0xec001f00, 0xfe101f80,
+   "vstrw%v.32\t%13-15,22Q, %d"},
+
   {ARM_FEATURE_CORE_LOW (0),
    MVE_NONE,
    0x00000000, 0x00000000, 0}
@@ -4074,12 +4148,109 @@ is_mve_encoding_conflict (unsigned long given,
       else
 	return FALSE;
 
+    case MVE_VSTRB_T1:
+    case MVE_VSTRH_T2:
+      if ((arm_decode_field (given, 24, 24) == 0)
+	  && (arm_decode_field (given, 21, 21) == 0))
+	{
+	    return TRUE;
+	}
+      else if ((arm_decode_field (given, 7, 8) == 3))
+	return TRUE;
+      else
+	return FALSE;
+
+    case MVE_VSTRB_T5:
+    case MVE_VSTRH_T6:
+    case MVE_VSTRW_T7:
+      if ((arm_decode_field (given, 24, 24) == 0)
+	  && (arm_decode_field (given, 21, 21) == 0))
+	{
+	    return TRUE;
+	}
+      else
+	return FALSE;
+
     default:
       return FALSE;
 
     }
 }
 
+static void
+print_mve_vld_str_addr (struct disassemble_info *info,
+			unsigned long given,
+			enum mve_instructions matched_insn)
+{
+  void *stream = info->stream;
+  fprintf_ftype func = info->fprintf_func;
+
+  unsigned long p, w, gpr, imm, add, mod_imm;
+
+  imm = arm_decode_field (given, 0, 6);
+  mod_imm = imm;
+
+  switch (matched_insn)
+    {
+    case MVE_VLDRB_T1:
+    case MVE_VSTRB_T1:
+      gpr = arm_decode_field (given, 16, 18);
+      break;
+
+    case MVE_VLDRH_T2:
+    case MVE_VSTRH_T2:
+      gpr = arm_decode_field (given, 16, 18);
+      mod_imm = imm << 1;
+      break;
+
+    case MVE_VLDRH_T6:
+    case MVE_VSTRH_T6:
+      gpr = arm_decode_field (given, 16, 19);
+      mod_imm = imm << 1;
+      break;
+
+    case MVE_VLDRW_T7:
+    case MVE_VSTRW_T7:
+      gpr = arm_decode_field (given, 16, 19);
+      mod_imm = imm << 2;
+      break;
+
+    case MVE_VLDRB_T5:
+    case MVE_VSTRB_T5:
+      gpr = arm_decode_field (given, 16, 19);
+      break;
+
+    default:
+      return;
+    }
+
+  p = arm_decode_field (given, 24, 24);
+  w = arm_decode_field (given, 21, 21);
+
+  add = arm_decode_field (given, 23, 23);
+
+  char * add_sub;
+
+  /* Don't print anything for '+' as it is implied.  */
+  if (add == 1)
+    add_sub = "";
+  else
+    add_sub = "-";
+
+  if (p == 1)
+    {
+      /* Offset mode.  */
+      if (w == 0)
+	func (stream, "[%s, #%s%lu]", arm_regnames[gpr], add_sub, mod_imm);
+      /* Pre-indexed mode.  */
+      else
+	func (stream, "[%s, #%s%lu]!", arm_regnames[gpr], add_sub, mod_imm);
+    }
+  else if ((p == 0) && (w == 1))
+    /* Post-index mode.  */
+    func (stream, "[%s], #%s%lu", arm_regnames[gpr], add_sub, mod_imm);
+}
+
 /* Return FALSE if GIVEN is not an undefined encoding for MATCHED_INSN.
    Otherwise, return TRUE and set UNDEFINED_CODE to give a reason as to why
    this encoding is undefined.  */
@@ -4112,6 +4283,42 @@ is_mve_undefined (unsigned long given, enum mve_instructions matched_insn,
       else
 	return FALSE;
 
+    case MVE_VLDRB_T1:
+      if (arm_decode_field (given, 7, 8) == 3)
+	{
+	  *undefined_code = UNDEF_SIZE_3;
+	  return TRUE;
+	}
+      else
+	return FALSE;
+
+    case MVE_VLDRH_T2:
+      if (arm_decode_field (given, 7, 8) <= 1)
+	{
+	  *undefined_code = UNDEF_SIZE_LE_1;
+	  return TRUE;
+	}
+      else
+	return FALSE;
+
+    case MVE_VSTRB_T1:
+      if ((arm_decode_field (given, 7, 8) == 0))
+	{
+	  *undefined_code = UNDEF_SIZE_0;
+	  return TRUE;
+	}
+      else
+	return FALSE;
+
+    case MVE_VSTRH_T2:
+      if ((arm_decode_field (given, 7, 8) <= 1))
+	{
+	  *undefined_code = UNDEF_SIZE_LE_1;
+	  return TRUE;
+	}
+      else
+	return FALSE;
+
     default:
       return FALSE;
     }
@@ -4243,6 +4450,29 @@ is_mve_unpredictable (unsigned long given, enum mve_instructions matched_insn,
 	  return FALSE;
       }
 
+    case MVE_VLDRB_T5:
+    case MVE_VLDRH_T6:
+    case MVE_VLDRW_T7:
+    case MVE_VSTRB_T5:
+    case MVE_VSTRH_T6:
+    case MVE_VSTRW_T7:
+      {
+	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;
+	  }
+	else if (rn == 0xf)
+	  {
+	    *unpredictable_code = UNPRED_R15;
+	    return TRUE;
+	  }
+	else
+	  return FALSE;
+      }
+
     default:
       return FALSE;
     }
@@ -4259,10 +4489,18 @@ print_mve_undefined (struct disassemble_info *info,
 
   switch (undefined_code)
     {
+    case UNDEF_SIZE_0:
+      func (stream, "size equals zero");
+      break;
+
     case UNDEF_SIZE_3:
       func (stream, "size equals three");
       break;
 
+    case UNDEF_SIZE_LE_1:
+      func (stream, "size <= 1");
+      break;
+
     case UNDEF_NONE:
       break;
     }
@@ -4385,6 +4623,8 @@ print_mve_size (struct disassemble_info *info,
     case MVE_VHSUB_T2:
     case MVE_VLD2:
     case MVE_VLD4:
+    case MVE_VLDRB_T1:
+    case MVE_VLDRH_T2:
     case MVE_VPT_VEC_T1:
     case MVE_VPT_VEC_T2:
     case MVE_VPT_VEC_T3:
@@ -4394,6 +4634,8 @@ print_mve_size (struct disassemble_info *info,
     case MVE_VRHADD:
     case MVE_VST2:
     case MVE_VST4:
+    case MVE_VSTRB_T1:
+    case MVE_VSTRH_T2:
       if (size <= 3)
 	func (stream, "%s", mve_vec_sizename[size]);
       else
@@ -4646,6 +4888,15 @@ print_insn_coprocessor (bfd_vma pc,
 	      && (cp_num == 8 || cp_num == 14 || cp_num == 15))
 	    continue;
 	}
+      else if ((insn->value == 0xec100f80      /* vldr (system register) */
+		|| insn->value == 0xec000f80)  /* vstr (system register) */
+	       && arm_decode_field (given, 24, 24) == 0
+	       && arm_decode_field (given, 21, 21) == 0)
+	/* If the P and W bits are both 0 then these encodings match the MVE
+	   VLDR and VSTR instructions, these are in a different table, so we
+	   don't let it match here.  */
+	continue;
+
 
       for (c = insn->assembler; *c; c++)
 	{
@@ -5871,6 +6122,10 @@ print_insn_mve (struct disassemble_info *info, long given)
 			func (stream, "%s", arm_conditional[IFTHEN_COND]);
 		      break;
 
+		    case 'd':
+		      print_mve_vld_str_addr (info, given, insn->mve_op);
+		      break;
+
 		    case 'i':
 		      {
 			long mve_mask = mve_extract_pred_mask (given);
@@ -5882,6 +6137,14 @@ print_insn_mve (struct disassemble_info *info, long given)
 		      print_vec_condition (info, given, insn->mve_op);
 		      break;
 
+		    case 'u':
+		      {
+			if (arm_decode_field (given, 28, 28) == 0)
+			  func (stream, "s");
+			else
+			  func (stream, "u");
+		      }
+
 		    case 'v':
 		      print_instruction_predicate (info);
 		      break;


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]