From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 46390 invoked by alias); 1 May 2019 17:41:26 -0000 Mailing-List: contact binutils-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: binutils-owner@sourceware.org Received: (qmail 46381 invoked by uid 89); 1 May 2019 17:41:26 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-25.7 required=5.0 tests=AWL,BAYES_00,GIT_PATCH_0,GIT_PATCH_1,GIT_PATCH_2,GIT_PATCH_3 autolearn=ham version=3.3.1 spammy= X-HELO: foss.arm.com Received: from usa-sjc-mx-foss1.foss.arm.com (HELO foss.arm.com) (217.140.101.70) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Wed, 01 May 2019 17:41:24 +0000 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.72.51.249]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 4CA9C80D for ; Wed, 1 May 2019 10:41:23 -0700 (PDT) Received: from [10.2.207.62] (e107157-lin.cambridge.arm.com [10.2.207.62]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id EAAF83F719 for ; Wed, 1 May 2019 10:41:22 -0700 (PDT) Subject: [PATCH 42/57][Arm][OBJDUMP] Add support for MVE instructions: vldr[bhw] and vstr[bhw] To: binutils@sourceware.org References: <19569550-4d2e-0bb3-592a-d91050d490f6@arm.com> From: "Andre Vieira (lists)" Message-ID: Date: Wed, 01 May 2019 17:41:00 -0000 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Thunderbird/60.6.1 MIME-Version: 1.0 In-Reply-To: <19569550-4d2e-0bb3-592a-d91050d490f6@arm.com> Content-Type: multipart/mixed; boundary="------------280097F595D4BB0E53A90160" X-IsSubscribed: yes X-SW-Source: 2019-05/txt/msg00072.txt.bz2 This is a multi-part message in MIME format. --------------280097F595D4BB0E53A90160 Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: 7bit Content-length: 862 Hi, This patch adds support for all MVE VLDR[bhw] and VSTR[bhw] instructions. It adds an extra check to the 'print_insn_coprocessor_1' to skip a particular encoding that overlaps with VLDR and VSTR (system register). Is this OK for trunk? Cheers, Andre opcodes/ChangeLog: 2019-05-01 Andre Vieira Michael Collison * 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. --------------280097F595D4BB0E53A90160 Content-Type: text/x-patch; name="42.patch" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="42.patch" Content-length: 9407 diff --git a/opcodes/arm-dis.c b/opcodes/arm-dis.c index 9d821d92093216c48bc94c1e82da92dc5fdd4139..218c730b72926b8e0d6232243f192910d7385165 100644 --- a/opcodes/arm-dis.c +++ b/opcodes/arm-dis.c @@ -103,6 +103,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 }; @@ -127,6 +137,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. */ }; @@ -1839,6 +1851,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 @@ -2033,6 +2047,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, @@ -2057,6 +2101,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} @@ -4084,12 +4158,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. */ @@ -4122,6 +4293,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; } @@ -4253,6 +4460,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; } @@ -4269,10 +4499,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; } @@ -4395,6 +4633,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: @@ -4404,6 +4644,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 @@ -4657,6 +4899,15 @@ print_insn_coprocessor_1 (const struct sopcode32 *opcodes, && (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++) { @@ -5902,6 +6153,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); @@ -5913,6 +6168,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; --------------280097F595D4BB0E53A90160--