aboutsummaryrefslogtreecommitdiff
path: root/opcodes/arm-dis.c
diff options
context:
space:
mode:
authorAndre Vieira <andre.simoesdiasvieira@arm.com>2019-05-16 14:06:46 +0100
committerAndre Vieira <andre.simoesdiasvieira@arm.com>2019-05-16 16:37:31 +0100
commitef1576a1b5f14276b44ee4c0fc259832ca0dfd99 (patch)
treea197906ad72905df3a65e2d1df778f0b42d8b8ef /opcodes/arm-dis.c
parentaef6d006581cab8a858e7abd36c57e73ea6e97a2 (diff)
downloadgdb-ef1576a1b5f14276b44ee4c0fc259832ca0dfd99.zip
gdb-ef1576a1b5f14276b44ee4c0fc259832ca0dfd99.tar.gz
gdb-ef1576a1b5f14276b44ee4c0fc259832ca0dfd99.tar.bz2
[PATCH 43/57][Arm][OBJDUMP] Add support for MVE instructions: scatter stores and gather loads
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. (enum mve_undefined): Likewise. (is_mve_undefined): Handle new instructions. (is_mve_unpredictable): Likewise. (print_mve_undefined): Likewise. (print_mve_unpredictable): Likewise. (print_mve_size): Likewise. (print_insn_mve): Likewise.
Diffstat (limited to 'opcodes/arm-dis.c')
-rw-r--r--opcodes/arm-dis.c356
1 files changed, 355 insertions, 1 deletions
diff --git a/opcodes/arm-dis.c b/opcodes/arm-dis.c
index 6d167ae..2a89937 100644
--- a/opcodes/arm-dis.c
+++ b/opcodes/arm-dis.c
@@ -112,6 +112,18 @@ enum mve_instructions
MVE_VSTRB_T5,
MVE_VSTRH_T6,
MVE_VSTRW_T7,
+ MVE_VLDRB_GATHER_T1,
+ MVE_VLDRH_GATHER_T2,
+ MVE_VLDRW_GATHER_T3,
+ MVE_VLDRD_GATHER_T4,
+ MVE_VLDRW_GATHER_T5,
+ MVE_VLDRD_GATHER_T6,
+ MVE_VSTRB_SCATTER_T1,
+ MVE_VSTRH_SCATTER_T2,
+ MVE_VSTRW_SCATTER_T3,
+ MVE_VSTRD_SCATTER_T4,
+ MVE_VSTRW_SCATTER_T5,
+ MVE_VSTRD_SCATTER_T6,
MVE_NONE
};
@@ -130,6 +142,9 @@ enum mve_unpredictable
vec reg start > 6 (vld2/st2). */
UNPRED_R13_AND_WB, /* Unpredictable becase gp reg = r13
and WB bit = 1. */
+ UNPRED_Q_REGS_EQUAL, /* Unpredictable because vector registers are
+ equal. */
+ UNPRED_OS, /* Unpredictable because offset scaled == 1. */
UNPRED_NONE /* No unpredictable behavior. */
};
@@ -138,6 +153,13 @@ 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_SIZE_NOT_2, /* undefined because size != 2. */
+ UNDEF_SIZE_NOT_3, /* undefined because size != 3. */
+ UNDEF_NOT_UNS_SIZE_0, /* undefined because U == 0 and
+ size == 0. */
+ UNDEF_NOT_UNS_SIZE_1, /* undefined because U == 0 and
+ size == 1. */
+ UNDEF_NOT_UNSIGNED, /* undefined because U == 0. */
UNDEF_NONE /* no undefined behavior. */
};
@@ -1840,6 +1862,8 @@ static const struct opcode32 neon_opcodes[] =
%% %
+ %a print '+' or '-' or imm offset in vldr[bhwd] and
+ vstr[bhwd]
%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
@@ -1847,6 +1871,7 @@ static const struct opcode32 neon_opcodes[] =
%n print vector comparison code for predicated instruction
%v print vector predicate for instruction in predicated
block
+ %o print offset scaled for vldr[hwd] and vstr[hwd]
%w print writeback mode for MVE v{st,ld}[24]
%B print v{st,ld}[24] any one operands
@@ -1856,7 +1881,8 @@ static const struct opcode32 neon_opcodes[] =
%<bitfield>Z as %<>r but r15 is ZR instead of PC and r13 is
UNPREDICTABLE
%<bitfield>s print size for vector predicate & non VMOV instructions
-*/
+ %<bitfield>i print immediate for vstr/vldr reg +/- imm
+ */
static const struct mopcode32 mve_opcodes[] =
{
@@ -2037,6 +2063,42 @@ static const struct mopcode32 mve_opcodes[] =
0xfc901e01, 0xff901e1f,
"vld4%5-6d.%7-8s\t%B, [%16-19r]%w"},
+ /* Vector VLDRB gather load. */
+ {ARM_FEATURE_COPROC (FPU_MVE),
+ MVE_VLDRB_GATHER_T1,
+ 0xec900e00, 0xefb01e50,
+ "vldrb%v.%u%7-8s\t%13-15,22Q, [%16-19r, %1-3,5Q]"},
+
+ /* Vector VLDRH gather load. */
+ {ARM_FEATURE_COPROC (FPU_MVE),
+ MVE_VLDRH_GATHER_T2,
+ 0xec900e10, 0xefb01e50,
+ "vldrh%v.%u%7-8s\t%13-15,22Q, [%16-19r, %1-3,5Q%o]"},
+
+ /* Vector VLDRW gather load. */
+ {ARM_FEATURE_COPROC (FPU_MVE),
+ MVE_VLDRW_GATHER_T3,
+ 0xfc900f40, 0xffb01fd0,
+ "vldrw%v.u32\t%13-15,22Q, [%16-19r, %1-3,5Q%o]"},
+
+ /* Vector VLDRD gather load. */
+ {ARM_FEATURE_COPROC (FPU_MVE),
+ MVE_VLDRD_GATHER_T4,
+ 0xec900fd0, 0xefb01fd0,
+ "vldrd%v.u64\t%13-15,22Q, [%16-19r, %1-3,5Q%o]"},
+
+ /* Vector VLDRW gather load. */
+ {ARM_FEATURE_COPROC (FPU_MVE),
+ MVE_VLDRW_GATHER_T5,
+ 0xfd101e00, 0xff111f00,
+ "vldrw%v.u32\t%13-15,22Q, [%17-19,7Q, #%a%0-6i]%w"},
+
+ /* Vector VLDRD gather load, variant T6. */
+ {ARM_FEATURE_COPROC (FPU_MVE),
+ MVE_VLDRD_GATHER_T6,
+ 0xfd101f00, 0xff111f00,
+ "vldrd%v.u64\t%13-15,22Q, [%17-19,7Q, #%a%0-6i]%w"},
+
/* Vector VLDRB. */
{ARM_FEATURE_COPROC (FPU_MVE),
MVE_VLDRB_T1,
@@ -2091,6 +2153,42 @@ static const struct mopcode32 mve_opcodes[] =
0xfca01e01, 0xffb01e1f,
"vst4%5-6d.%7-8s\t%B, [%16-19r]!"},
+ /* Vector VSTRB scatter store, T1 variant. */
+ {ARM_FEATURE_COPROC (FPU_MVE),
+ MVE_VSTRB_SCATTER_T1,
+ 0xec800e00, 0xffb01e50,
+ "vstrb%v.%7-8s\t%13-15,22Q, [%16-19r, %1-3,5Q]"},
+
+ /* Vector VSTRH scatter store, T2 variant. */
+ {ARM_FEATURE_COPROC (FPU_MVE),
+ MVE_VSTRH_SCATTER_T2,
+ 0xec800e10, 0xffb01e50,
+ "vstrh%v.%7-8s\t%13-15,22Q, [%16-19r, %1-3,5Q%o]"},
+
+ /* Vector VSTRW scatter store, T3 variant. */
+ {ARM_FEATURE_COPROC (FPU_MVE),
+ MVE_VSTRW_SCATTER_T3,
+ 0xec800e40, 0xffb01e50,
+ "vstrw%v.%7-8s\t%13-15,22Q, [%16-19r, %1-3,5Q%o]"},
+
+ /* Vector VSTRD scatter store, T4 variant. */
+ {ARM_FEATURE_COPROC (FPU_MVE),
+ MVE_VSTRD_SCATTER_T4,
+ 0xec800fd0, 0xffb01fd0,
+ "vstrd%v.64\t%13-15,22Q, [%16-19r, %1-3,5Q%o]"},
+
+ /* Vector VSTRW scatter store, T5 variant. */
+ {ARM_FEATURE_COPROC (FPU_MVE),
+ MVE_VSTRW_SCATTER_T5,
+ 0xfd001e00, 0xff111f00,
+ "vstrw%v.32\t%13-15,22Q, [%17-19,7Q, #%a%0-6i]%w"},
+
+ /* Vector VSTRD scatter store, T6 variant. */
+ {ARM_FEATURE_COPROC (FPU_MVE),
+ MVE_VSTRD_SCATTER_T6,
+ 0xfd001f00, 0xff111f00,
+ "vstrd%v.64\t%13-15,22Q, [%17-19,7Q, #%a%0-6i]%w"},
+
/* Vector VSTRB. */
{ARM_FEATURE_COPROC (FPU_MVE),
MVE_VSTRB_T1,
@@ -4319,6 +4417,113 @@ is_mve_undefined (unsigned long given, enum mve_instructions matched_insn,
else
return FALSE;
+ case MVE_VLDRB_GATHER_T1:
+ if (arm_decode_field (given, 7, 8) == 3)
+ {
+ *undefined_code = UNDEF_SIZE_3;
+ return TRUE;
+ }
+ else if ((arm_decode_field (given, 28, 28) == 0)
+ && (arm_decode_field (given, 7, 8) == 0))
+ {
+ *undefined_code = UNDEF_NOT_UNS_SIZE_0;
+ return TRUE;
+ }
+ else
+ return FALSE;
+
+ case MVE_VLDRH_GATHER_T2:
+ if (arm_decode_field (given, 7, 8) == 3)
+ {
+ *undefined_code = UNDEF_SIZE_3;
+ return TRUE;
+ }
+ else if ((arm_decode_field (given, 28, 28) == 0)
+ && (arm_decode_field (given, 7, 8) == 1))
+ {
+ *undefined_code = UNDEF_NOT_UNS_SIZE_1;
+ return TRUE;
+ }
+ else if (arm_decode_field (given, 7, 8) == 0)
+ {
+ *undefined_code = UNDEF_SIZE_0;
+ return TRUE;
+ }
+ else
+ return FALSE;
+
+ case MVE_VLDRW_GATHER_T3:
+ if (arm_decode_field (given, 7, 8) != 2)
+ {
+ *undefined_code = UNDEF_SIZE_NOT_2;
+ return TRUE;
+ }
+ else if (arm_decode_field (given, 28, 28) == 0)
+ {
+ *undefined_code = UNDEF_NOT_UNSIGNED;
+ return TRUE;
+ }
+ else
+ return FALSE;
+
+ case MVE_VLDRD_GATHER_T4:
+ if (arm_decode_field (given, 7, 8) != 3)
+ {
+ *undefined_code = UNDEF_SIZE_NOT_3;
+ return TRUE;
+ }
+ else if (arm_decode_field (given, 28, 28) == 0)
+ {
+ *undefined_code = UNDEF_NOT_UNSIGNED;
+ return TRUE;
+ }
+ else
+ return FALSE;
+
+ case MVE_VSTRB_SCATTER_T1:
+ if (arm_decode_field (given, 7, 8) == 3)
+ {
+ *undefined_code = UNDEF_SIZE_3;
+ return TRUE;
+ }
+ else
+ return FALSE;
+
+ case MVE_VSTRH_SCATTER_T2:
+ {
+ unsigned long size = arm_decode_field (given, 7, 8);
+ if (size == 3)
+ {
+ *undefined_code = UNDEF_SIZE_3;
+ return TRUE;
+ }
+ else if (size == 0)
+ {
+ *undefined_code = UNDEF_SIZE_0;
+ return TRUE;
+ }
+ else
+ return FALSE;
+ }
+
+ case MVE_VSTRW_SCATTER_T3:
+ if (arm_decode_field (given, 7, 8) != 2)
+ {
+ *undefined_code = UNDEF_SIZE_NOT_2;
+ return TRUE;
+ }
+ else
+ return FALSE;
+
+ case MVE_VSTRD_SCATTER_T4:
+ if (arm_decode_field (given, 7, 8) != 3)
+ {
+ *undefined_code = UNDEF_SIZE_NOT_3;
+ return TRUE;
+ }
+ else
+ return FALSE;
+
default:
return FALSE;
}
@@ -4473,6 +4678,77 @@ is_mve_unpredictable (unsigned long given, enum mve_instructions matched_insn,
return FALSE;
}
+ case MVE_VLDRB_GATHER_T1:
+ if (arm_decode_field (given, 0, 0) == 1)
+ {
+ *unpredictable_code = UNPRED_OS;
+ return TRUE;
+ }
+
+ /* fall through. */
+ /* To handle common code with T2-T4 variants. */
+ case MVE_VLDRH_GATHER_T2:
+ case MVE_VLDRW_GATHER_T3:
+ case MVE_VLDRD_GATHER_T4:
+ {
+ unsigned long qd = arm_decode_field_multiple (given, 13, 15, 22, 22);
+ unsigned long qm = arm_decode_field_multiple (given, 1, 3, 5, 5);
+
+ if (qd == qm)
+ {
+ *unpredictable_code = UNPRED_Q_REGS_EQUAL;
+ return TRUE;
+ }
+
+ if (arm_decode_field (given, 16, 19) == 0xf)
+ {
+ *unpredictable_code = UNPRED_R15;
+ return TRUE;
+ }
+
+ return FALSE;
+ }
+
+ case MVE_VLDRW_GATHER_T5:
+ case MVE_VLDRD_GATHER_T6:
+ {
+ unsigned long qd = arm_decode_field_multiple (given, 13, 15, 22, 22);
+ unsigned long qm = arm_decode_field_multiple (given, 17, 19, 7, 7);
+
+ if (qd == qm)
+ {
+ *unpredictable_code = UNPRED_Q_REGS_EQUAL;
+ return TRUE;
+ }
+ else
+ return FALSE;
+ }
+
+ case MVE_VSTRB_SCATTER_T1:
+ if (arm_decode_field (given, 16, 19) == 0xf)
+ {
+ *unpredictable_code = UNPRED_R15;
+ return TRUE;
+ }
+ else if (arm_decode_field (given, 0, 0) == 1)
+ {
+ *unpredictable_code = UNPRED_OS;
+ return TRUE;
+ }
+ else
+ return FALSE;
+
+ case MVE_VSTRH_SCATTER_T2:
+ case MVE_VSTRW_SCATTER_T3:
+ case MVE_VSTRD_SCATTER_T4:
+ if (arm_decode_field (given, 16, 19) == 0xf)
+ {
+ *unpredictable_code = UNPRED_R15;
+ return TRUE;
+ }
+ else
+ return FALSE;
+
default:
return FALSE;
}
@@ -4501,6 +4777,26 @@ print_mve_undefined (struct disassemble_info *info,
func (stream, "size <= 1");
break;
+ case UNDEF_SIZE_NOT_2:
+ func (stream, "size not equal to 2");
+ break;
+
+ case UNDEF_SIZE_NOT_3:
+ func (stream, "size not equal to 3");
+ break;
+
+ case UNDEF_NOT_UNS_SIZE_0:
+ func (stream, "not unsigned and size = zero");
+ break;
+
+ case UNDEF_NOT_UNS_SIZE_1:
+ func (stream, "not unsigned and size = one");
+ break;
+
+ case UNDEF_NOT_UNSIGNED:
+ func (stream, "not unsigned");
+ break;
+
case UNDEF_NONE:
break;
}
@@ -4546,6 +4842,15 @@ print_mve_unpredictable (struct disassemble_info *info,
func (stream, "use of r13 and write back");
break;
+ case UNPRED_Q_REGS_EQUAL:
+ func (stream,
+ "same vector register used for destination and other operand");
+ break;
+
+ case UNPRED_OS:
+ func (stream, "use of offset scaled");
+ break;
+
case UNPRED_NONE:
break;
}
@@ -4623,6 +4928,10 @@ print_mve_size (struct disassemble_info *info,
case MVE_VHSUB_T2:
case MVE_VLD2:
case MVE_VLD4:
+ case MVE_VLDRB_GATHER_T1:
+ case MVE_VLDRH_GATHER_T2:
+ case MVE_VLDRW_GATHER_T3:
+ case MVE_VLDRD_GATHER_T4:
case MVE_VLDRB_T1:
case MVE_VLDRH_T2:
case MVE_VPT_VEC_T1:
@@ -4634,6 +4943,9 @@ print_mve_size (struct disassemble_info *info,
case MVE_VRHADD:
case MVE_VST2:
case MVE_VST4:
+ case MVE_VSTRB_SCATTER_T1:
+ case MVE_VSTRH_SCATTER_T2:
+ case MVE_VSTRW_SCATTER_T3:
case MVE_VSTRB_T1:
case MVE_VSTRH_T2:
if (size <= 3)
@@ -6117,6 +6429,12 @@ print_insn_mve (struct disassemble_info *info, long given)
func (stream, "%%");
break;
+ case 'a':
+ /* Don't print anything for '+' as it is implied. */
+ if (arm_decode_field (given, 23, 23) == 0)
+ func (stream, "-");
+ break;
+
case 'c':
if (ifthen_state)
func (stream, "%s", arm_conditional[IFTHEN_COND]);
@@ -6137,6 +6455,17 @@ print_insn_mve (struct disassemble_info *info, long given)
print_vec_condition (info, given, insn->mve_op);
break;
+ case 'o':
+ if (arm_decode_field (given, 0, 0) == 1)
+ {
+ unsigned long size
+ = arm_decode_field (given, 4, 4)
+ | (arm_decode_field (given, 6, 6) << 1);
+
+ func (stream, ", uxtw #%lu", size);
+ }
+ break;
+
case 'u':
{
if (arm_decode_field (given, 28, 28) == 0)
@@ -6144,6 +6473,7 @@ print_insn_mve (struct disassemble_info *info, long given)
else
func (stream, "u");
}
+ break;
case 'v':
print_instruction_predicate (info);
@@ -6181,6 +6511,30 @@ print_insn_mve (struct disassemble_info *info, long given)
value,
insn->mve_op);
break;
+ case 'i':
+ {
+ unsigned long imm
+ = arm_decode_field (given, 0, 6);
+ unsigned long mod_imm = imm;
+
+ switch (insn->mve_op)
+ {
+ case MVE_VLDRW_GATHER_T5:
+ case MVE_VSTRW_SCATTER_T5:
+ mod_imm = mod_imm << 2;
+ break;
+ case MVE_VSTRD_SCATTER_T6:
+ case MVE_VLDRD_GATHER_T6:
+ mod_imm = mod_imm << 3;
+ break;
+
+ default:
+ break;
+ }
+
+ func (stream, "%lu", mod_imm);
+ }
+ break;
case 'r':
func (stream, "%s", arm_regnames[value]);
break;