[PATCH 45/57][Arm][OBJDUMP] Add support for MVE instructions: vmov, vmvn, vorr, vorn, vmovx and vbic
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_okay_in_it): Handle new isntructions. (is_mve_encoding_conflict): Likewise. (is_mve_undefined): Likewise. (is_mve_unpredictable): Likewise. (print_mve_vmov_index): Likewise. (print_simd_imm8): Likewise. (print_mve_undefined): Likewise. (print_mve_unpredictable): Likewise. (print_mve_size): Likewise. (print_insn_mve): Likewise.
This commit is contained in:
parent
bf0b396de7
commit
c507f10b07
2 changed files with 621 additions and 5 deletions
|
@ -1,3 +1,20 @@
|
||||||
|
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_okay_in_it): Handle new isntructions.
|
||||||
|
(is_mve_encoding_conflict): Likewise.
|
||||||
|
(is_mve_undefined): Likewise.
|
||||||
|
(is_mve_unpredictable): Likewise.
|
||||||
|
(print_mve_vmov_index): Likewise.
|
||||||
|
(print_simd_imm8): Likewise.
|
||||||
|
(print_mve_undefined): Likewise.
|
||||||
|
(print_mve_unpredictable): Likewise.
|
||||||
|
(print_mve_size): Likewise.
|
||||||
|
(print_insn_mve): Likewise.
|
||||||
|
|
||||||
2019-05-16 Andre Vieira <andre.simoesdiasvieira@arm.com>
|
2019-05-16 Andre Vieira <andre.simoesdiasvieira@arm.com>
|
||||||
Michael Collison <michael.collison@arm.com>
|
Michael Collison <michael.collison@arm.com>
|
||||||
|
|
||||||
|
|
|
@ -129,6 +129,21 @@ enum mve_instructions
|
||||||
MVE_VCVT_FP_HALF_FP,
|
MVE_VCVT_FP_HALF_FP,
|
||||||
MVE_VCVT_FROM_FP_TO_INT,
|
MVE_VCVT_FROM_FP_TO_INT,
|
||||||
MVE_VRINT_FP,
|
MVE_VRINT_FP,
|
||||||
|
MVE_VMOV_HFP_TO_GP,
|
||||||
|
MVE_VMOV_GP_TO_VEC_LANE,
|
||||||
|
MVE_VMOV_IMM_TO_VEC,
|
||||||
|
MVE_VMOV_VEC_TO_VEC,
|
||||||
|
MVE_VMOV2_VEC_LANE_TO_GP,
|
||||||
|
MVE_VMOV2_GP_TO_VEC_LANE,
|
||||||
|
MVE_VMOV_VEC_LANE_TO_GP,
|
||||||
|
MVE_VMVN_IMM,
|
||||||
|
MVE_VMVN_REG,
|
||||||
|
MVE_VORR_IMM,
|
||||||
|
MVE_VORR_REG,
|
||||||
|
MVE_VORN,
|
||||||
|
MVE_VBIC_IMM,
|
||||||
|
MVE_VBIC_REG,
|
||||||
|
MVE_VMOVX,
|
||||||
MVE_NONE
|
MVE_NONE
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -152,12 +167,17 @@ enum mve_unpredictable
|
||||||
UNPRED_OS, /* Unpredictable because offset scaled == 1. */
|
UNPRED_OS, /* Unpredictable because offset scaled == 1. */
|
||||||
UNPRED_GP_REGS_EQUAL, /* Unpredictable because gp registers are the
|
UNPRED_GP_REGS_EQUAL, /* Unpredictable because gp registers are the
|
||||||
same. */
|
same. */
|
||||||
|
UNPRED_Q_REGS_EQ_AND_SIZE_1, /* Unpredictable because q regs equal and
|
||||||
|
size = 1. */
|
||||||
|
UNPRED_Q_REGS_EQ_AND_SIZE_2, /* Unpredictable because q regs equal and
|
||||||
|
size = 2. */
|
||||||
UNPRED_NONE /* No unpredictable behavior. */
|
UNPRED_NONE /* No unpredictable behavior. */
|
||||||
};
|
};
|
||||||
|
|
||||||
enum mve_undefined
|
enum mve_undefined
|
||||||
{
|
{
|
||||||
UNDEF_SIZE_0, /* undefined because size == 0. */
|
UNDEF_SIZE_0, /* undefined because size == 0. */
|
||||||
|
UNDEF_SIZE_2, /* undefined because size == 2. */
|
||||||
UNDEF_SIZE_3, /* undefined because size == 3. */
|
UNDEF_SIZE_3, /* undefined because size == 3. */
|
||||||
UNDEF_SIZE_LE_1, /* undefined because size <= 1. */
|
UNDEF_SIZE_LE_1, /* undefined because size <= 1. */
|
||||||
UNDEF_SIZE_NOT_2, /* undefined because size != 2. */
|
UNDEF_SIZE_NOT_2, /* undefined because size != 2. */
|
||||||
|
@ -169,6 +189,12 @@ enum mve_undefined
|
||||||
UNDEF_NOT_UNSIGNED, /* undefined because U == 0. */
|
UNDEF_NOT_UNSIGNED, /* undefined because U == 0. */
|
||||||
UNDEF_VCVT_IMM6, /* imm6 < 32. */
|
UNDEF_VCVT_IMM6, /* imm6 < 32. */
|
||||||
UNDEF_VCVT_FSI_IMM6, /* fsi = 0 and 32 >= imm6 <= 47. */
|
UNDEF_VCVT_FSI_IMM6, /* fsi = 0 and 32 >= imm6 <= 47. */
|
||||||
|
UNDEF_BAD_OP1_OP2, /* undefined with op2 = 2 and
|
||||||
|
op1 == (0 or 1). */
|
||||||
|
UNDEF_BAD_U_OP1_OP2, /* undefined with U = 1 and
|
||||||
|
op2 == 0 and op1 == (0 or 1). */
|
||||||
|
UNDEF_OP_0_BAD_CMODE, /* undefined because op == 0 and cmode
|
||||||
|
in {0xx1, x0x1}. */
|
||||||
UNDEF_NONE /* no undefined behavior. */
|
UNDEF_NONE /* no undefined behavior. */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1885,15 +1911,19 @@ static const struct opcode32 neon_opcodes[] =
|
||||||
%o print offset scaled for vldr[hwd] and vstr[hwd]
|
%o print offset scaled for vldr[hwd] and vstr[hwd]
|
||||||
%w print writeback mode for MVE v{st,ld}[24]
|
%w print writeback mode for MVE v{st,ld}[24]
|
||||||
%B print v{st,ld}[24] any one operands
|
%B print v{st,ld}[24] any one operands
|
||||||
|
%E print vmov, vmvn, vorr, vbic encoded constant
|
||||||
|
%N print generic index for vmov
|
||||||
|
|
||||||
%<bitfield>r print as an ARM register
|
%<bitfield>r print as an ARM register
|
||||||
%<bitfield>d print the bitfield in decimal
|
%<bitfield>d print the bitfield in decimal
|
||||||
%<bitfield>Q print as a MVE Q register
|
%<bitfield>Q print as a MVE Q register
|
||||||
|
%<bitfield>F print as a MVE S register
|
||||||
%<bitfield>Z as %<>r but r15 is ZR instead of PC and r13 is
|
%<bitfield>Z as %<>r but r15 is ZR instead of PC and r13 is
|
||||||
UNPREDICTABLE
|
UNPREDICTABLE
|
||||||
%<bitfield>s print size for vector predicate & non VMOV instructions
|
%<bitfield>s print size for vector predicate & non VMOV instructions
|
||||||
%<bitfield>i print immediate for vstr/vldr reg +/- imm
|
%<bitfield>i print immediate for vstr/vldr reg +/- imm
|
||||||
%<bitfield>k print immediate for vector conversion instruction
|
%<bitfield>k print immediate for vector conversion instruction
|
||||||
|
%<bitfield>x print the bitfield in hex.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static const struct mopcode32 mve_opcodes[] =
|
static const struct mopcode32 mve_opcodes[] =
|
||||||
|
@ -1948,6 +1978,18 @@ static const struct mopcode32 mve_opcodes[] =
|
||||||
0xfe011f40, 0xff811f50,
|
0xfe011f40, 0xff811f50,
|
||||||
"vpt%i.s%20-21s\t%n, %17-19Q, %0-3Z"},
|
"vpt%i.s%20-21s\t%n, %17-19Q, %0-3Z"},
|
||||||
|
|
||||||
|
/* Vector VBIC immediate. */
|
||||||
|
{ARM_FEATURE_COPROC (FPU_MVE),
|
||||||
|
MVE_VBIC_IMM,
|
||||||
|
0xef800070, 0xefb81070,
|
||||||
|
"vbic%v.i%8-11s\t%13-15,22Q, %E"},
|
||||||
|
|
||||||
|
/* Vector VBIC register. */
|
||||||
|
{ARM_FEATURE_COPROC (FPU_MVE),
|
||||||
|
MVE_VBIC_REG,
|
||||||
|
0xef100150, 0xffb11f51,
|
||||||
|
"vbic%v\t%13-15,22Q, %17-19,7Q, %1-3,5Q"},
|
||||||
|
|
||||||
/* Vector VCMP floating point T1. */
|
/* Vector VCMP floating point T1. */
|
||||||
{ARM_FEATURE_COPROC (FPU_MVE_FP),
|
{ARM_FEATURE_COPROC (FPU_MVE_FP),
|
||||||
MVE_VCMP_FP_T1,
|
MVE_VCMP_FP_T1,
|
||||||
|
@ -2171,6 +2213,103 @@ static const struct mopcode32 mve_opcodes[] =
|
||||||
0xec101f00, 0xfe101f80,
|
0xec101f00, 0xfe101f80,
|
||||||
"vldrw%v.u32\t%13-15,22Q, %d"},
|
"vldrw%v.u32\t%13-15,22Q, %d"},
|
||||||
|
|
||||||
|
/* Vector VMOV between gpr and half precision register, op == 0. */
|
||||||
|
{ARM_FEATURE_COPROC (FPU_MVE_FP),
|
||||||
|
MVE_VMOV_HFP_TO_GP,
|
||||||
|
0xee000910, 0xfff00f7f,
|
||||||
|
"vmov.f16\t%7,16-19F, %12-15r"},
|
||||||
|
|
||||||
|
/* Vector VMOV between gpr and half precision register, op == 1. */
|
||||||
|
{ARM_FEATURE_COPROC (FPU_MVE_FP),
|
||||||
|
MVE_VMOV_HFP_TO_GP,
|
||||||
|
0xee100910, 0xfff00f7f,
|
||||||
|
"vmov.f16\t%12-15r, %7,16-19F"},
|
||||||
|
|
||||||
|
{ARM_FEATURE_COPROC (FPU_MVE_FP),
|
||||||
|
MVE_VMOV_GP_TO_VEC_LANE,
|
||||||
|
0xee000b10, 0xff900f1f,
|
||||||
|
"vmov%c.%5-6,21-22s\t%17-19,7Q[%N], %12-15r"},
|
||||||
|
|
||||||
|
/* Vector VORR immediate to vector.
|
||||||
|
NOTE: MVE_VORR_IMM must appear in the table
|
||||||
|
before MVE_VMOV_IMM_TO_VEC due to opcode aliasing. */
|
||||||
|
{ARM_FEATURE_COPROC (FPU_MVE),
|
||||||
|
MVE_VORR_IMM,
|
||||||
|
0xef800050, 0xefb810f0,
|
||||||
|
"vorr%v.i%8-11s\t%13-15,22Q, %E"},
|
||||||
|
|
||||||
|
/* Vector VMOV immediate to vector,
|
||||||
|
cmode == 11x1 -> VMVN which is UNDEFINED
|
||||||
|
for such a cmode. */
|
||||||
|
{ARM_FEATURE_COPROC (FPU_MVE),
|
||||||
|
MVE_VMVN_IMM, 0xef800d50, 0xefb81dd0, UNDEFINED_INSTRUCTION},
|
||||||
|
|
||||||
|
/* Vector VMOV immediate to vector. */
|
||||||
|
{ARM_FEATURE_COPROC (FPU_MVE),
|
||||||
|
MVE_VMOV_IMM_TO_VEC,
|
||||||
|
0xef800050, 0xefb810d0,
|
||||||
|
"vmov%v.%5,8-11s\t%13-15,22Q, %E"},
|
||||||
|
|
||||||
|
/* Vector VMOV two 32-bit lanes to two gprs, idx = 0. */
|
||||||
|
{ARM_FEATURE_COPROC (FPU_MVE),
|
||||||
|
MVE_VMOV2_VEC_LANE_TO_GP,
|
||||||
|
0xec000f00, 0xffb01ff0,
|
||||||
|
"vmov%c\t%0-3r, %16-19r, %13-15,22Q[2], %13-15,22Q[0]"},
|
||||||
|
|
||||||
|
/* Vector VMOV two 32-bit lanes to two gprs, idx = 1. */
|
||||||
|
{ARM_FEATURE_COPROC (FPU_MVE),
|
||||||
|
MVE_VMOV2_VEC_LANE_TO_GP,
|
||||||
|
0xec000f10, 0xffb01ff0,
|
||||||
|
"vmov%c\t%0-3r, %16-19r, %13-15,22Q[3], %13-15,22Q[1]"},
|
||||||
|
|
||||||
|
/* Vector VMOV Two gprs to two 32-bit lanes, idx = 0. */
|
||||||
|
{ARM_FEATURE_COPROC (FPU_MVE),
|
||||||
|
MVE_VMOV2_GP_TO_VEC_LANE,
|
||||||
|
0xec100f00, 0xffb01ff0,
|
||||||
|
"vmov%c\t%13-15,22Q[2], %13-15,22Q[0], %0-3r, %16-19r"},
|
||||||
|
|
||||||
|
/* Vector VMOV Two gprs to two 32-bit lanes, idx = 1. */
|
||||||
|
{ARM_FEATURE_COPROC (FPU_MVE),
|
||||||
|
MVE_VMOV2_GP_TO_VEC_LANE,
|
||||||
|
0xec100f10, 0xffb01ff0,
|
||||||
|
"vmov%c\t%13-15,22Q[2], %13-15,22Q[0], %0-3r, %16-19r"},
|
||||||
|
|
||||||
|
/* Vector VMOV Vector lane to gpr. */
|
||||||
|
{ARM_FEATURE_COPROC (FPU_MVE_FP),
|
||||||
|
MVE_VMOV_VEC_LANE_TO_GP,
|
||||||
|
0xee100b10, 0xff100f1f,
|
||||||
|
"vmov%c.%u%5-6,21-22s\t%12-15r, %17-19,7Q[%N]"},
|
||||||
|
|
||||||
|
/* Floating point move extract. */
|
||||||
|
{ARM_FEATURE_COPROC (FPU_MVE_FP),
|
||||||
|
MVE_VMOVX,
|
||||||
|
0xfeb00a40, 0xffbf0fd0,
|
||||||
|
"vmovx.f16\t%22,12-15F, %5,0-3F"},
|
||||||
|
|
||||||
|
/* Vector VMVN immediate to vector. */
|
||||||
|
{ARM_FEATURE_COPROC (FPU_MVE),
|
||||||
|
MVE_VMVN_IMM,
|
||||||
|
0xef800070, 0xefb810f0,
|
||||||
|
"vmvn%v.i%8-11s\t%13-15,22Q, %E"},
|
||||||
|
|
||||||
|
/* Vector VMVN register. */
|
||||||
|
{ARM_FEATURE_COPROC (FPU_MVE),
|
||||||
|
MVE_VMVN_REG,
|
||||||
|
0xffb005c0, 0xffbf1fd1,
|
||||||
|
"vmvn%v\t%13-15,22Q, %1-3,5Q"},
|
||||||
|
|
||||||
|
/* Vector VORN, vector bitwise or not. */
|
||||||
|
{ARM_FEATURE_COPROC (FPU_MVE),
|
||||||
|
MVE_VORN,
|
||||||
|
0xef300150, 0xffb11f51,
|
||||||
|
"vorn%v\t%13-15,22Q, %17-19,7Q, %1-3,5Q"},
|
||||||
|
|
||||||
|
/* Vector VORR register. */
|
||||||
|
{ARM_FEATURE_COPROC (FPU_MVE),
|
||||||
|
MVE_VORR_REG,
|
||||||
|
0xef200150, 0xffb11f51,
|
||||||
|
"vorr%v\t%13-15,22Q, %17-19,7Q, %1-3,5Q"},
|
||||||
|
|
||||||
/* Vector VRINT floating point. */
|
/* Vector VRINT floating point. */
|
||||||
{ARM_FEATURE_COPROC (FPU_MVE_FP),
|
{ARM_FEATURE_COPROC (FPU_MVE_FP),
|
||||||
MVE_VRINT_FP,
|
MVE_VRINT_FP,
|
||||||
|
@ -4127,8 +4266,17 @@ arm_decode_shift (long given, fprintf_ftype func, void *stream,
|
||||||
static bfd_boolean
|
static bfd_boolean
|
||||||
is_mve_okay_in_it (enum mve_instructions matched_insn)
|
is_mve_okay_in_it (enum mve_instructions matched_insn)
|
||||||
{
|
{
|
||||||
|
switch (matched_insn)
|
||||||
|
{
|
||||||
|
case MVE_VMOV_GP_TO_VEC_LANE:
|
||||||
|
case MVE_VMOV2_VEC_LANE_TO_GP:
|
||||||
|
case MVE_VMOV2_GP_TO_VEC_LANE:
|
||||||
|
case MVE_VMOV_VEC_LANE_TO_GP:
|
||||||
|
return TRUE;
|
||||||
|
default:
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static bfd_boolean
|
static bfd_boolean
|
||||||
is_mve_architecture (struct disassemble_info *info)
|
is_mve_architecture (struct disassemble_info *info)
|
||||||
|
@ -4320,6 +4468,40 @@ is_mve_encoding_conflict (unsigned long given,
|
||||||
case MVE_VCVT_FP_FIX_VEC:
|
case MVE_VCVT_FP_FIX_VEC:
|
||||||
return (arm_decode_field (given, 16, 21) & 0x38) == 0;
|
return (arm_decode_field (given, 16, 21) & 0x38) == 0;
|
||||||
|
|
||||||
|
case MVE_VBIC_IMM:
|
||||||
|
case MVE_VORR_IMM:
|
||||||
|
{
|
||||||
|
unsigned long cmode = arm_decode_field (given, 8, 11);
|
||||||
|
|
||||||
|
if ((cmode & 1) == 0)
|
||||||
|
return TRUE;
|
||||||
|
else if ((cmode & 0xc) == 0xc)
|
||||||
|
return TRUE;
|
||||||
|
else
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
case MVE_VMVN_IMM:
|
||||||
|
{
|
||||||
|
unsigned long cmode = arm_decode_field (given, 8, 11);
|
||||||
|
|
||||||
|
if ((cmode & 9) == 1)
|
||||||
|
return TRUE;
|
||||||
|
else if ((cmode & 5) == 1)
|
||||||
|
return TRUE;
|
||||||
|
else if ((cmode & 0xe) == 0xe)
|
||||||
|
return TRUE;
|
||||||
|
else
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
case MVE_VMOV_IMM_TO_VEC:
|
||||||
|
if ((arm_decode_field (given, 5, 5) == 1)
|
||||||
|
&& (arm_decode_field (given, 8, 11) != 0xe))
|
||||||
|
return TRUE;
|
||||||
|
else
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
|
@ -4612,6 +4794,67 @@ is_mve_undefined (unsigned long given, enum mve_instructions matched_insn,
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case MVE_VMOV_VEC_LANE_TO_GP:
|
||||||
|
{
|
||||||
|
unsigned long op1 = arm_decode_field (given, 21, 22);
|
||||||
|
unsigned long op2 = arm_decode_field (given, 5, 6);
|
||||||
|
unsigned long u = arm_decode_field (given, 23, 23);
|
||||||
|
|
||||||
|
if ((op2 == 0) && (u == 1))
|
||||||
|
{
|
||||||
|
if ((op1 == 0) || (op1 == 1))
|
||||||
|
{
|
||||||
|
*undefined_code = UNDEF_BAD_U_OP1_OP2;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
else if (op2 == 2)
|
||||||
|
{
|
||||||
|
if ((op1 == 0) || (op1 == 1))
|
||||||
|
{
|
||||||
|
*undefined_code = UNDEF_BAD_OP1_OP2;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
case MVE_VMOV_GP_TO_VEC_LANE:
|
||||||
|
if (arm_decode_field (given, 5, 6) == 2)
|
||||||
|
{
|
||||||
|
unsigned long op1 = arm_decode_field (given, 21, 22);
|
||||||
|
if ((op1 == 0) || (op1 == 1))
|
||||||
|
{
|
||||||
|
*undefined_code = UNDEF_BAD_OP1_OP2;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
case MVE_VMOV_IMM_TO_VEC:
|
||||||
|
if (arm_decode_field (given, 5, 5) == 0)
|
||||||
|
{
|
||||||
|
unsigned long cmode = arm_decode_field (given, 8, 11);
|
||||||
|
|
||||||
|
if (((cmode & 9) == 1) || ((cmode & 5) == 1))
|
||||||
|
{
|
||||||
|
*undefined_code = UNDEF_OP_0_BAD_CMODE;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
@ -4837,6 +5080,8 @@ is_mve_unpredictable (unsigned long given, enum mve_instructions matched_insn,
|
||||||
else
|
else
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
|
case MVE_VMOV2_VEC_LANE_TO_GP:
|
||||||
|
case MVE_VMOV2_GP_TO_VEC_LANE:
|
||||||
case MVE_VCVT_BETWEEN_FP_INT:
|
case MVE_VCVT_BETWEEN_FP_INT:
|
||||||
case MVE_VCVT_FROM_FP_TO_INT:
|
case MVE_VCVT_FROM_FP_TO_INT:
|
||||||
{
|
{
|
||||||
|
@ -4862,11 +5107,224 @@ is_mve_unpredictable (unsigned long given, enum mve_instructions matched_insn,
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case MVE_VMOV_HFP_TO_GP:
|
||||||
|
case MVE_VMOV_GP_TO_VEC_LANE:
|
||||||
|
case MVE_VMOV_VEC_LANE_TO_GP:
|
||||||
|
{
|
||||||
|
unsigned long rda = arm_decode_field (given, 12, 15);
|
||||||
|
if (rda == 0xd)
|
||||||
|
{
|
||||||
|
*unpredictable_code = UNPRED_R13;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
else if (rda == 0xf)
|
||||||
|
{
|
||||||
|
*unpredictable_code = UNPRED_R15;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
print_mve_vmov_index (struct disassemble_info *info, unsigned long given)
|
||||||
|
{
|
||||||
|
unsigned long op1 = arm_decode_field (given, 21, 22);
|
||||||
|
unsigned long op2 = arm_decode_field (given, 5, 6);
|
||||||
|
unsigned long h = arm_decode_field (given, 16, 16);
|
||||||
|
unsigned long index, esize, targetBeat, idx;
|
||||||
|
void *stream = info->stream;
|
||||||
|
fprintf_ftype func = info->fprintf_func;
|
||||||
|
|
||||||
|
if ((op1 & 0x2) == 0x2)
|
||||||
|
{
|
||||||
|
index = op2;
|
||||||
|
esize = 8;
|
||||||
|
}
|
||||||
|
else if (((op1 & 0x2) == 0x0) && ((op2 & 0x1) == 0x1))
|
||||||
|
{
|
||||||
|
index = op2 >> 1;
|
||||||
|
esize = 16;
|
||||||
|
}
|
||||||
|
else if (((op1 & 0x2) == 0) && ((op2 & 0x3) == 0))
|
||||||
|
{
|
||||||
|
index = 0;
|
||||||
|
esize = 32;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
func (stream, "<undefined index>");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
targetBeat = (op1 & 0x1) | (h << 1);
|
||||||
|
idx = index + targetBeat * (32/esize);
|
||||||
|
|
||||||
|
func (stream, "%lu", idx);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Print neon and mve 8-bit immediate that can be a 8, 16, 32, or 64-bits
|
||||||
|
in length and integer of floating-point type. */
|
||||||
|
static void
|
||||||
|
print_simd_imm8 (struct disassemble_info *info, unsigned long given,
|
||||||
|
unsigned int ibit_loc, const struct mopcode32 *insn)
|
||||||
|
{
|
||||||
|
int bits = 0;
|
||||||
|
int cmode = (given >> 8) & 0xf;
|
||||||
|
int op = (given >> 5) & 0x1;
|
||||||
|
unsigned long value = 0, hival = 0;
|
||||||
|
unsigned shift;
|
||||||
|
int size = 0;
|
||||||
|
int isfloat = 0;
|
||||||
|
void *stream = info->stream;
|
||||||
|
fprintf_ftype func = info->fprintf_func;
|
||||||
|
|
||||||
|
/* On Neon the 'i' bit is at bit 24, on mve it is
|
||||||
|
at bit 28. */
|
||||||
|
bits |= ((given >> ibit_loc) & 1) << 7;
|
||||||
|
bits |= ((given >> 16) & 7) << 4;
|
||||||
|
bits |= ((given >> 0) & 15) << 0;
|
||||||
|
|
||||||
|
if (cmode < 8)
|
||||||
|
{
|
||||||
|
shift = (cmode >> 1) & 3;
|
||||||
|
value = (unsigned long) bits << (8 * shift);
|
||||||
|
size = 32;
|
||||||
|
}
|
||||||
|
else if (cmode < 12)
|
||||||
|
{
|
||||||
|
shift = (cmode >> 1) & 1;
|
||||||
|
value = (unsigned long) bits << (8 * shift);
|
||||||
|
size = 16;
|
||||||
|
}
|
||||||
|
else if (cmode < 14)
|
||||||
|
{
|
||||||
|
shift = (cmode & 1) + 1;
|
||||||
|
value = (unsigned long) bits << (8 * shift);
|
||||||
|
value |= (1ul << (8 * shift)) - 1;
|
||||||
|
size = 32;
|
||||||
|
}
|
||||||
|
else if (cmode == 14)
|
||||||
|
{
|
||||||
|
if (op)
|
||||||
|
{
|
||||||
|
/* Bit replication into bytes. */
|
||||||
|
int ix;
|
||||||
|
unsigned long mask;
|
||||||
|
|
||||||
|
value = 0;
|
||||||
|
hival = 0;
|
||||||
|
for (ix = 7; ix >= 0; ix--)
|
||||||
|
{
|
||||||
|
mask = ((bits >> ix) & 1) ? 0xff : 0;
|
||||||
|
if (ix <= 3)
|
||||||
|
value = (value << 8) | mask;
|
||||||
|
else
|
||||||
|
hival = (hival << 8) | mask;
|
||||||
|
}
|
||||||
|
size = 64;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Byte replication. */
|
||||||
|
value = (unsigned long) bits;
|
||||||
|
size = 8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (!op)
|
||||||
|
{
|
||||||
|
/* Floating point encoding. */
|
||||||
|
int tmp;
|
||||||
|
|
||||||
|
value = (unsigned long) (bits & 0x7f) << 19;
|
||||||
|
value |= (unsigned long) (bits & 0x80) << 24;
|
||||||
|
tmp = bits & 0x40 ? 0x3c : 0x40;
|
||||||
|
value |= (unsigned long) tmp << 24;
|
||||||
|
size = 32;
|
||||||
|
isfloat = 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
func (stream, "<illegal constant %.8x:%x:%x>",
|
||||||
|
bits, cmode, op);
|
||||||
|
size = 32;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// printU determines whether the immediate value should be printed as
|
||||||
|
// unsigned.
|
||||||
|
unsigned printU = 0;
|
||||||
|
switch (insn->mve_op)
|
||||||
|
{
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
// We want this for instructions that don't have a 'signed' type
|
||||||
|
case MVE_VBIC_IMM:
|
||||||
|
case MVE_VORR_IMM:
|
||||||
|
case MVE_VMVN_IMM:
|
||||||
|
case MVE_VMOV_IMM_TO_VEC:
|
||||||
|
printU = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
switch (size)
|
||||||
|
{
|
||||||
|
case 8:
|
||||||
|
func (stream, "#%ld\t; 0x%.2lx", value, value);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 16:
|
||||||
|
func (stream,
|
||||||
|
printU
|
||||||
|
? "#%lu\t; 0x%.4lx"
|
||||||
|
: "#%ld\t; 0x%.4lx", value, value);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 32:
|
||||||
|
if (isfloat)
|
||||||
|
{
|
||||||
|
unsigned char valbytes[4];
|
||||||
|
double fvalue;
|
||||||
|
|
||||||
|
/* Do this a byte at a time so we don't have to
|
||||||
|
worry about the host's endianness. */
|
||||||
|
valbytes[0] = value & 0xff;
|
||||||
|
valbytes[1] = (value >> 8) & 0xff;
|
||||||
|
valbytes[2] = (value >> 16) & 0xff;
|
||||||
|
valbytes[3] = (value >> 24) & 0xff;
|
||||||
|
|
||||||
|
floatformat_to_double
|
||||||
|
(& floatformat_ieee_single_little, valbytes,
|
||||||
|
& fvalue);
|
||||||
|
|
||||||
|
func (stream, "#%.7g\t; 0x%.8lx", fvalue,
|
||||||
|
value);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
func (stream,
|
||||||
|
printU
|
||||||
|
? "#%lu\t; 0x%.8lx"
|
||||||
|
: "#%ld\t; 0x%.8lx",
|
||||||
|
(long) (((value & 0x80000000L) != 0)
|
||||||
|
&& !printU
|
||||||
|
? value | ~0xffffffffL : value),
|
||||||
|
value);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 64:
|
||||||
|
func (stream, "#0x%.8lx%.8lx", hival, value);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
abort ();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
print_mve_undefined (struct disassemble_info *info,
|
print_mve_undefined (struct disassemble_info *info,
|
||||||
enum mve_undefined undefined_code)
|
enum mve_undefined undefined_code)
|
||||||
|
@ -4882,6 +5340,10 @@ print_mve_undefined (struct disassemble_info *info,
|
||||||
func (stream, "size equals zero");
|
func (stream, "size equals zero");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case UNDEF_SIZE_2:
|
||||||
|
func (stream, "size equals two");
|
||||||
|
break;
|
||||||
|
|
||||||
case UNDEF_SIZE_3:
|
case UNDEF_SIZE_3:
|
||||||
func (stream, "size equals three");
|
func (stream, "size equals three");
|
||||||
break;
|
break;
|
||||||
|
@ -4918,6 +5380,18 @@ print_mve_undefined (struct disassemble_info *info,
|
||||||
func (stream, "fsi = 0 and invalid imm6");
|
func (stream, "fsi = 0 and invalid imm6");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case UNDEF_BAD_OP1_OP2:
|
||||||
|
func (stream, "bad size with op2 = 2 and op1 = 0 or 1");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case UNDEF_BAD_U_OP1_OP2:
|
||||||
|
func (stream, "unsigned with op2 = 0 and op1 = 0 or 1");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case UNDEF_OP_0_BAD_CMODE:
|
||||||
|
func (stream, "op field equal 0 and bad cmode");
|
||||||
|
break;
|
||||||
|
|
||||||
case UNDEF_NONE:
|
case UNDEF_NONE:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -4976,6 +5450,14 @@ print_mve_unpredictable (struct disassemble_info *info,
|
||||||
func (stream, "same general-purpose register used for both operands");
|
func (stream, "same general-purpose register used for both operands");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case UNPRED_Q_REGS_EQ_AND_SIZE_1:
|
||||||
|
func (stream, "use of identical q registers and size = 1");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case UNPRED_Q_REGS_EQ_AND_SIZE_2:
|
||||||
|
func (stream, "use of identical q registers and size = 1");
|
||||||
|
break;
|
||||||
|
|
||||||
case UNPRED_NONE:
|
case UNPRED_NONE:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -5339,6 +5821,88 @@ print_mve_size (struct disassemble_info *info,
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case MVE_VMOV_GP_TO_VEC_LANE:
|
||||||
|
case MVE_VMOV_VEC_LANE_TO_GP:
|
||||||
|
switch (size)
|
||||||
|
{
|
||||||
|
case 0: case 4:
|
||||||
|
func (stream, "32");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 1: case 3:
|
||||||
|
case 5: case 7:
|
||||||
|
func (stream, "16");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 8: case 9: case 10: case 11:
|
||||||
|
case 12: case 13: case 14: case 15:
|
||||||
|
func (stream, "8");
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MVE_VMOV_IMM_TO_VEC:
|
||||||
|
switch (size)
|
||||||
|
{
|
||||||
|
case 0: case 4: case 8:
|
||||||
|
case 12: case 24: case 26:
|
||||||
|
func (stream, "i32");
|
||||||
|
break;
|
||||||
|
case 16: case 20:
|
||||||
|
func (stream, "i16");
|
||||||
|
break;
|
||||||
|
case 28:
|
||||||
|
func (stream, "i8");
|
||||||
|
break;
|
||||||
|
case 29:
|
||||||
|
func (stream, "i64");
|
||||||
|
break;
|
||||||
|
case 30:
|
||||||
|
func (stream, "f32");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MVE_VMVN_IMM:
|
||||||
|
switch (size)
|
||||||
|
{
|
||||||
|
case 0: case 2: case 4:
|
||||||
|
case 6: case 12: case 13:
|
||||||
|
func (stream, "32");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 8: case 10:
|
||||||
|
func (stream, "16");
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MVE_VBIC_IMM:
|
||||||
|
case MVE_VORR_IMM:
|
||||||
|
switch (size)
|
||||||
|
{
|
||||||
|
case 1: case 3:
|
||||||
|
case 5: case 7:
|
||||||
|
func (stream, "32");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 9: case 11:
|
||||||
|
func (stream, "16");
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -5563,7 +6127,6 @@ print_insn_coprocessor (bfd_vma pc,
|
||||||
don't let it match here. */
|
don't let it match here. */
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
|
||||||
for (c = insn->assembler; *c; c++)
|
for (c = insn->assembler; *c; c++)
|
||||||
{
|
{
|
||||||
if (*c == '%')
|
if (*c == '%')
|
||||||
|
@ -6829,12 +7392,32 @@ print_insn_mve (struct disassemble_info *info, long given)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'u':
|
case 'u':
|
||||||
|
{
|
||||||
|
unsigned long op1 = arm_decode_field (given, 21, 22);
|
||||||
|
|
||||||
|
if ((insn->mve_op == MVE_VMOV_VEC_LANE_TO_GP))
|
||||||
|
{
|
||||||
|
/* Check for signed. */
|
||||||
|
if (arm_decode_field (given, 23, 23) == 0)
|
||||||
|
{
|
||||||
|
/* We don't print 's' for S32. */
|
||||||
|
if ((arm_decode_field (given, 5, 6) == 0)
|
||||||
|
&& ((op1 == 0) || (op1 == 1)))
|
||||||
|
;
|
||||||
|
else
|
||||||
|
func (stream, "s");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
func (stream, "u");
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
if (arm_decode_field (given, 28, 28) == 0)
|
if (arm_decode_field (given, 28, 28) == 0)
|
||||||
func (stream, "s");
|
func (stream, "s");
|
||||||
else
|
else
|
||||||
func (stream, "u");
|
func (stream, "u");
|
||||||
}
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'v':
|
case 'v':
|
||||||
|
@ -6850,6 +7433,16 @@ print_insn_mve (struct disassemble_info *info, long given)
|
||||||
print_mve_register_blocks (info, given, insn->mve_op);
|
print_mve_register_blocks (info, given, insn->mve_op);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'E':
|
||||||
|
/* SIMD encoded constant for mov, mvn, vorr, vbic. */
|
||||||
|
|
||||||
|
print_simd_imm8 (info, given, 28, insn);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'N':
|
||||||
|
print_mve_vmov_index (info, given);
|
||||||
|
break;
|
||||||
|
|
||||||
case '0': case '1': case '2': case '3': case '4':
|
case '0': case '1': case '2': case '3': case '4':
|
||||||
case '5': case '6': case '7': case '8': case '9':
|
case '5': case '6': case '7': case '8': case '9':
|
||||||
{
|
{
|
||||||
|
@ -6907,12 +7500,18 @@ print_insn_mve (struct disassemble_info *info, long given)
|
||||||
func (stream, "%ld", value);
|
func (stream, "%ld", value);
|
||||||
value_in_comment = value;
|
value_in_comment = value;
|
||||||
break;
|
break;
|
||||||
|
case 'F':
|
||||||
|
func (stream, "s%ld", value);
|
||||||
|
break;
|
||||||
case 'Q':
|
case 'Q':
|
||||||
if (value & 0x8)
|
if (value & 0x8)
|
||||||
func (stream, "<illegal reg q%ld.5>", value);
|
func (stream, "<illegal reg q%ld.5>", value);
|
||||||
else
|
else
|
||||||
func (stream, "q%ld", value);
|
func (stream, "q%ld", value);
|
||||||
break;
|
break;
|
||||||
|
case 'x':
|
||||||
|
func (stream, "0x%08lx", value);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
abort ();
|
abort ();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue