From 04d54ace12e77deb8b1d26541de0f2cbc11880f5 Mon Sep 17 00:00:00 2001 From: Andre Vieira Date: Thu, 16 May 2019 14:04:35 +0100 Subject: [PATCH] [PATCH 41/57][Arm][OBJDUMP] Add support for MVE instructions: vld[24] and vst[24] opcodes/ChangeLog: 2019-05-16 Andre Vieira Michael Collison * 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 | 13 ++++ opcodes/arm-dis.c | 178 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 191 insertions(+) diff --git a/opcodes/ChangeLog b/opcodes/ChangeLog index ef6d3e8..25a86e2 100644 --- a/opcodes/ChangeLog +++ b/opcodes/ChangeLog @@ -3,6 +3,19 @@ * 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 + Michael Collison + + * 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. diff --git a/opcodes/arm-dis.c b/opcodes/arm-dis.c index 75cc27b..8ebf227 100644 --- a/opcodes/arm-dis.c +++ b/opcodes/arm-dis.c @@ -98,6 +98,10 @@ enum mve_instructions MVE_VHSUB_T1, MVE_VHSUB_T2, MVE_VRHADD, + MVE_VLD2, + MVE_VLD4, + MVE_VST2, + MVE_VST4, 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_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. */ }; @@ -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 + %w print writeback mode for MVE v{st,ld}[24] + %B print v{st,ld}[24] any one operands + %r print as an ARM register + %d print the bitfield in decimal %Q print as a MVE Q register %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"}, + /* 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} @@ -4015,6 +4065,15 @@ is_mve_encoding_conflict (unsigned long given, 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; @@ -4132,6 +4191,58 @@ is_mve_unpredictable (unsigned long given, enum mve_instructions matched_insn, 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; } @@ -4185,11 +4296,61 @@ print_mve_unpredictable (struct disassemble_info *info, 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; } } +/* 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, "", 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, "", q_reg_start); + break; + + default: + break; + } +} + 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_VLD2: + case MVE_VLD4: 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_VST2: + case MVE_VST4: 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; + 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': { @@ -5747,6 +5921,10 @@ print_insn_mve (struct disassemble_info *info, long given) 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, "", value); -- 2.7.4