From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 40304 invoked by alias); 1 May 2019 17:39:35 -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 40295 invoked by uid 89); 1 May 2019 17:39:35 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-25.6 required=5.0 tests=AWL,BAYES_00,GIT_PATCH_0,GIT_PATCH_1,GIT_PATCH_2,GIT_PATCH_3,KAM_LOTSOFHASH autolearn=ham version=3.3.1 spammy=ete X-HELO: foss.arm.com Received: from 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:39:32 +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 C523780D for ; Wed, 1 May 2019 10:39:30 -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 4A2A73F719 for ; Wed, 1 May 2019 10:39:30 -0700 (PDT) Subject: [PATCH 39/57][Arm][OBJDUMP] Add support for MVE instructions: vpt, vpst and vcmp To: binutils@sourceware.org References: <19569550-4d2e-0bb3-592a-d91050d490f6@arm.com> From: "Andre Vieira (lists)" Message-ID: <77de8189-7f9f-b9f7-314a-ad94df6f645c@arm.com> Date: Wed, 01 May 2019 17:39: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="------------3AD6DAF84A9D4ECEB058BFFC" X-IsSubscribed: yes X-SW-Source: 2019-05/txt/msg00069.txt.bz2 This is a multi-part message in MIME format. --------------3AD6DAF84A9D4ECEB058BFFC Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: 7bit Content-length: 1453 Hi, This patch adds support for MVE instructions VPT, VPST, and VCMP. This patch also adds a framework to parse VPT/VPST blocks and instructions therein. opcodes/ChangeLog: 2019-05-01 Andre Vieira Michael Collison * arm-dis.c (enum mve_instructions): Add new instructions. (enum mve_unpredictable): Add new values. (mve_opcodes): Add new instructions. (vec_condnames): New array with vector conditions. (mve_predicatenames): New array with predicate suffixes. (mve_vec_sizename): New array with vector sizes. (enum vpt_pred_state): New enum with vector predication states. (struct vpt_block): New struct type for vpt blocks. (vpt_block_state): Global struct to keep track of state. (mve_extract_pred_mask): New helper function. (num_instructions_vpt_block): Likewise. (mark_outside_vpt_block): Likewise. (mark_inside_vpt_block): Likewise. (invert_next_predicate_state): Likewise. (update_next_predicate_state): Likewise. (update_vpt_block_state): Likewise. (is_vpt_instruction): Likewise. (is_mve_encoding_conflict): Add entries for new instructions. (is_mve_unpredictable): Likewise. (print_mve_unpredictable): Handle new cases. (print_instruction_predicate): Likewise. (print_mve_size): New function. (print_vec_condition): New function. (print_insn_mve): Handle vpt blocks and new print operands. --------------3AD6DAF84A9D4ECEB058BFFC Content-Type: text/x-patch; name="39.patch" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="39.patch" Content-length: 20230 diff --git a/gas/testsuite/gas/arm/mve-vpst-bad.l b/gas/testsuite/gas/arm/mve-vpst-bad.l index 35a56890c85fd44ac22e47ea97b3bddd6811f14e..9a396ae6459db53939d0cfc9f58358c965712697 100644 --- a/gas/testsuite/gas/arm/mve-vpst-bad.l +++ b/gas/testsuite/gas/arm/mve-vpst-bad.l @@ -16,4 +16,4 @@ [^:]*:55: Warning: instruction is UNPREDICTABLE in an IT block [^:]*:62: Error: incorrect condition in VPT/VPST block -- `vaddt.i32 q0,q1,q2' [^:]*:65: Error: syntax error -- `vaddeq.i32 q0,q1,q2' -[^:]*:68: Warning: section '.text' finished with an open VPT/VPST block. +[^:]*:68: Warning: .* finished with an open VPT/VPST block. diff --git a/gas/testsuite/gas/arm/mve-vpt-bad-1.l b/gas/testsuite/gas/arm/mve-vpt-bad-1.l index 28bd9d6047de0fc0592b7b75ee48f3b086f1f879..99036d29120aede14cd66217bf0564da42817bc3 100644 --- a/gas/testsuite/gas/arm/mve-vpt-bad-1.l +++ b/gas/testsuite/gas/arm/mve-vpt-bad-1.l @@ -20,4 +20,4 @@ [^:]*:23: Error: syntax error -- `vpteq.i8 eq,q0,q1' [^:]*:26: Warning: instruction is UNPREDICTABLE in a VPT block [^:]*:27: Warning: instruction is UNPREDICTABLE in a VPT block -[^:]*:30: Warning: section '.text' finished with an open VPT/VPST block. +[^:]*:30: Warning: .* finished with an open VPT/VPST block. diff --git a/gas/testsuite/gas/arm/mve-vpt-bad-2.l b/gas/testsuite/gas/arm/mve-vpt-bad-2.l index 678a824eef64d15a7a1add12d84157f80f1555f7..9f11fe890fa00e60ae2f9d1712cd0e7f8b49dcb4 100644 --- a/gas/testsuite/gas/arm/mve-vpt-bad-2.l +++ b/gas/testsuite/gas/arm/mve-vpt-bad-2.l @@ -17,5 +17,5 @@ [^:]*:20: Error: syntax error -- `vpteq.f32 eq,q0,q1' [^:]*:23: Warning: instruction is UNPREDICTABLE in a VPT block [^:]*:24: Warning: instruction is UNPREDICTABLE in a VPT block -[^:]*:27: Warning: section '.text' finished with an open VPT/VPST block. +[^:]*:27: Warning: .* finished with an open VPT/VPST block. diff --git a/opcodes/arm-dis.c b/opcodes/arm-dis.c index ddf707d6b1f90e46b6e144c84cbf404ead00c806..84ee48d1f5005d16b097a4628d4d9ad252dc7ad5 100644 --- a/opcodes/arm-dis.c +++ b/opcodes/arm-dis.c @@ -21,6 +21,7 @@ MA 02110-1301, USA. */ #include "sysdep.h" +#include #include "disassemble.h" #include "opcode/arm.h" @@ -69,6 +70,23 @@ struct arm_private_data enum mve_instructions { + MVE_VPST, + MVE_VPT_FP_T1, + MVE_VPT_FP_T2, + MVE_VPT_VEC_T1, + MVE_VPT_VEC_T2, + MVE_VPT_VEC_T3, + MVE_VPT_VEC_T4, + MVE_VPT_VEC_T5, + MVE_VPT_VEC_T6, + MVE_VCMP_FP_T1, + MVE_VCMP_FP_T2, + MVE_VCMP_VEC_T1, + MVE_VCMP_VEC_T2, + MVE_VCMP_VEC_T3, + MVE_VCMP_VEC_T4, + MVE_VCMP_VEC_T5, + MVE_VCMP_VEC_T6, MVE_NONE }; @@ -76,6 +94,10 @@ enum mve_unpredictable { UNPRED_IT_BLOCK, /* Unpredictable because mve insn in it block. */ + UNPRED_FCA_0_FCB_1, /* Unpredictable because fcA = 0 and + fcB = 1 (vpt). */ + UNPRED_R13, /* Unpredictable because r13 (sp) or + r15 (sp) used. */ UNPRED_NONE /* No unpredictable behavior. */ }; @@ -1781,10 +1803,114 @@ static const struct opcode32 neon_opcodes[] = %% % - */ + %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 + block + %Q print as a MVE Q register + %Z as %<>r but r15 is ZR instead of PC and r13 is + UNPREDICTABLE + %s print size for vector predicate & non VMOV instructions +*/ static const struct mopcode32 mve_opcodes[] = { + /* MVE. */ + + {ARM_FEATURE_COPROC (FPU_MVE), + MVE_VPST, + 0xfe310f4d, 0xffbf1fff, + "vpst%i" + }, + + /* Floating point VPT T1. */ + {ARM_FEATURE_COPROC (FPU_MVE_FP), + MVE_VPT_FP_T1, + 0xee310f00, 0xefb10f50, + "vpt%i.f%28s\t%n, %17-19Q, %1-3,5Q"}, + /* Floating point VPT T2. */ + {ARM_FEATURE_COPROC (FPU_MVE_FP), + MVE_VPT_FP_T2, + 0xee310f40, 0xefb10f50, + "vpt%i.f%28s\t%n, %17-19Q, %0-3Z"}, + + /* Vector VPT T1. */ + {ARM_FEATURE_COPROC (FPU_MVE), + MVE_VPT_VEC_T1, + 0xfe010f00, 0xff811f51, + "vpt%i.i%20-21s\t%n, %17-19Q, %1-3,5Q"}, + /* Vector VPT T2. */ + {ARM_FEATURE_COPROC (FPU_MVE), + MVE_VPT_VEC_T2, + 0xfe010f01, 0xff811f51, + "vpt%i.u%20-21s\t%n, %17-19Q, %1-3,5Q"}, + /* Vector VPT T3. */ + {ARM_FEATURE_COPROC (FPU_MVE), + MVE_VPT_VEC_T3, + 0xfe011f00, 0xff811f50, + "vpt%i.s%20-21s\t%n, %17-19Q, %1-3,5Q"}, + /* Vector VPT T4. */ + {ARM_FEATURE_COPROC (FPU_MVE), + MVE_VPT_VEC_T4, + 0xfe010f40, 0xff811f70, + "vpt%i.i%20-21s\t%n, %17-19Q, %0-3Z"}, + /* Vector VPT T5. */ + {ARM_FEATURE_COPROC (FPU_MVE), + MVE_VPT_VEC_T5, + 0xfe010f60, 0xff811f70, + "vpt%i.u%20-21s\t%n, %17-19Q, %0-3Z"}, + /* Vector VPT T6. */ + {ARM_FEATURE_COPROC (FPU_MVE), + MVE_VPT_VEC_T6, + 0xfe011f40, 0xff811f50, + "vpt%i.s%20-21s\t%n, %17-19Q, %0-3Z"}, + + /* Vector VCMP floating point T1. */ + {ARM_FEATURE_COPROC (FPU_MVE_FP), + MVE_VCMP_FP_T1, + 0xee310f00, 0xeff1ef50, + "vcmp%v.f%28s\t%n, %17-19Q, %1-3,5Q"}, + + /* Vector VCMP floating point T2. */ + {ARM_FEATURE_COPROC (FPU_MVE_FP), + MVE_VCMP_FP_T2, + 0xee310f40, 0xeff1ef50, + "vcmp%v.f%28s\t%n, %17-19Q, %0-3Z"}, + + /* Vector VCMP T1. */ + {ARM_FEATURE_COPROC (FPU_MVE), + MVE_VCMP_VEC_T1, + 0xfe010f00, 0xffc1ff51, + "vcmp%v.i%20-21s\t%n, %17-19Q, %1-3,5Q"}, + /* Vector VCMP T2. */ + {ARM_FEATURE_COPROC (FPU_MVE), + MVE_VCMP_VEC_T2, + 0xfe010f01, 0xffc1ff51, + "vcmp%v.u%20-21s\t%n, %17-19Q, %1-3,5Q"}, + /* Vector VCMP T3. */ + {ARM_FEATURE_COPROC (FPU_MVE), + MVE_VCMP_VEC_T3, + 0xfe011f00, 0xffc1ff50, + "vcmp%v.s%20-21s\t%n, %17-19Q, %1-3,5Q"}, + /* Vector VCMP T4. */ + {ARM_FEATURE_COPROC (FPU_MVE), + MVE_VCMP_VEC_T4, + 0xfe010f40, 0xffc1ff70, + "vcmp%v.i%20-21s\t%n, %17-19Q, %0-3Z"}, + /* Vector VCMP T5. */ + {ARM_FEATURE_COPROC (FPU_MVE), + MVE_VCMP_VEC_T5, + 0xfe010f60, 0xffc1ff70, + "vcmp%v.u%20-21s\t%n, %17-19Q, %0-3Z"}, + /* Vector VCMP T6. */ + {ARM_FEATURE_COPROC (FPU_MVE), + MVE_VCMP_VEC_T6, + 0xfe011f40, 0xffc1ff50, + "vcmp%v.s%20-21s\t%n, %17-19Q, %0-3Z"}, + + {ARM_FEATURE_CORE_LOW (0), + MVE_NONE, + 0x00000000, 0x00000000, 0} }; /* Opcode tables: ARM, 16-bit Thumb, 32-bit Thumb. All three are partially @@ -3379,6 +3505,56 @@ static const char *const iwmmxt_cregnames[] = "wcgr0", "wcgr1", "wcgr2", "wcgr3", "reserved", "reserved", "reserved", "reserved" }; +static const char *const vec_condnames[] = +{ "eq", "ne", "cs", "hi", "ge", "lt", "gt", "le" +}; + +static const char *const mve_predicatenames[] = +{ "", "ttt", "tt", "tte", "t", "tee", "te", "tet", "", + "eee", "ee", "eet", "e", "ett", "et", "ete" +}; + +/* Names for 2-bit size field for mve vector isntructions. */ +static const char *const mve_vec_sizename[] = + { "8", "16", "32", "64"}; + +/* Indicates whether we are processing a then predicate, + else predicate or none at all. */ +enum vpt_pred_state +{ + PRED_NONE, + PRED_THEN, + PRED_ELSE +}; + +/* Information used to process a vpt block and subsequent instructions. */ +struct vpt_block +{ + /* Are we in a vpt block. */ + bfd_boolean in_vpt_block; + + /* Next predicate state if in vpt block. */ + enum vpt_pred_state next_pred_state; + + /* Mask from vpt/vpst instruction. */ + long predicate_mask; + + /* Instruction number in vpt block. */ + long current_insn_num; + + /* Number of instructions in vpt block.. */ + long num_pred_insn; +}; + +static struct vpt_block vpt_block_state = +{ + FALSE, + PRED_NONE, + 0, + 0, + 0 +}; + /* Default to GCC register name set. */ static unsigned int regname_selected = 1; @@ -3401,6 +3577,113 @@ static bfd_vma ifthen_address; /* Functions. */ +/* Extract the predicate mask for a VPT or VPST instruction. + The mask is composed of bits 13-15 (Mkl) and bit 22 (Mkh). */ + +static long +mve_extract_pred_mask (long given) +{ + return ((given & 0x00400000) >> 19) | ((given & 0xe000) >> 13); +} + +/* Return the number of instructions in a MVE predicate block. */ +static long +num_instructions_vpt_block (long given) +{ + long mask = mve_extract_pred_mask (given); + if (mask == 0) + return 0; + + if (mask == 8) + return 1; + + if ((mask & 7) == 4) + return 2; + + if ((mask & 3) == 2) + return 3; + + if ((mask & 1) == 1) + return 4; + + return 0; +} + +static void +mark_outside_vpt_block (void) +{ + vpt_block_state.in_vpt_block = FALSE; + vpt_block_state.next_pred_state = PRED_NONE; + vpt_block_state.predicate_mask = 0; + vpt_block_state.current_insn_num = 0; + vpt_block_state.num_pred_insn = 0; +} + +static void +mark_inside_vpt_block (long given) +{ + vpt_block_state.in_vpt_block = TRUE; + vpt_block_state.next_pred_state = PRED_THEN; + vpt_block_state.predicate_mask = mve_extract_pred_mask (given); + vpt_block_state.current_insn_num = 0; + vpt_block_state.num_pred_insn = num_instructions_vpt_block (given); + assert (vpt_block_state.num_pred_insn >= 1); +} + +static enum vpt_pred_state +invert_next_predicate_state (enum vpt_pred_state astate) +{ + if (astate == PRED_THEN) + return PRED_ELSE; + else if (astate == PRED_ELSE) + return PRED_THEN; + else + return PRED_NONE; +} + +static enum vpt_pred_state +update_next_predicate_state (void) +{ + long pred_mask = vpt_block_state.predicate_mask; + long mask_for_insn = 0; + + switch (vpt_block_state.current_insn_num) + { + case 1: + mask_for_insn = 8; + break; + + case 2: + mask_for_insn = 4; + break; + + case 3: + mask_for_insn = 2; + break; + + case 4: + return PRED_NONE; + } + + if (pred_mask & mask_for_insn) + return invert_next_predicate_state (vpt_block_state.next_pred_state); + else + return vpt_block_state.next_pred_state; +} + +static void +update_vpt_block_state (void) +{ + vpt_block_state.current_insn_num++; + if (vpt_block_state.current_insn_num == vpt_block_state.num_pred_insn) + { + /* No more instructions to process in vpt block. */ + mark_outside_vpt_block (); + return; + } + + vpt_block_state.next_pred_state = update_next_predicate_state (); +} /* Decode a bitfield of the form matching regexp (N(-N)?,)*N(-N)?. Returns pointer to following character of the format string and @@ -3504,6 +3787,38 @@ is_mve_architecture (struct disassemble_info *info) return FALSE; } +static bfd_boolean +is_vpt_instruction (long given) +{ + + /* If mkh:mkl is '0000' then its not a vpt/vpst instruction. */ + if ((given & 0x0040e000) == 0) + return FALSE; + + /* VPT floating point T1 variant. */ + if (((given & 0xefb10f50) == 0xee310f00 && ((given & 0x1001) != 0x1)) + /* VPT floating point T2 variant. */ + || ((given & 0xefb10f50) == 0xee310f40) + /* VPT vector T1 variant. */ + || ((given & 0xff811f51) == 0xfe010f00) + /* VPT vector T2 variant. */ + || ((given & 0xff811f51) == 0xfe010f01 + && ((given & 0x300000) != 0x300000)) + /* VPT vector T3 variant. */ + || ((given & 0xff811f50) == 0xfe011f00) + /* VPT vector T4 variant. */ + || ((given & 0xff811f70) == 0xfe010f40) + /* VPT vector T5 variant. */ + || ((given & 0xff811f70) == 0xfe010f60) + /* VPT vector T6 variant. */ + || ((given & 0xff811f50) == 0xfe011f40) + /* VPST vector T variant. */ + || ((given & 0xffbf1fff) == 0xfe310f4d)) + return TRUE; + else + return FALSE; +} + /* Decode a bitfield from opcode GIVEN, with starting bitfield = START and ending bitfield = END. END must be greater than START. */ @@ -3550,7 +3865,69 @@ static bfd_boolean is_mve_encoding_conflict (unsigned long given, enum mve_instructions matched_insn) { - return FALSE; + switch (matched_insn) + { + case MVE_VPST: + if (arm_decode_field_multiple (given, 13, 15, 22, 22) == 0) + return TRUE; + else + return FALSE; + + case MVE_VPT_FP_T1: + if (arm_decode_field_multiple (given, 13, 15, 22, 22) == 0) + return TRUE; + if ((arm_decode_field (given, 12, 12) == 0) + && (arm_decode_field (given, 0, 0) == 1)) + return TRUE; + return FALSE; + + case MVE_VPT_FP_T2: + if (arm_decode_field_multiple (given, 13, 15, 22, 22) == 0) + return TRUE; + if (arm_decode_field (given, 0, 3) == 0xd) + return TRUE; + return FALSE; + + case MVE_VPT_VEC_T1: + case MVE_VPT_VEC_T2: + case MVE_VPT_VEC_T3: + case MVE_VPT_VEC_T4: + case MVE_VPT_VEC_T5: + case MVE_VPT_VEC_T6: + if (arm_decode_field_multiple (given, 13, 15, 22, 22) == 0) + return TRUE; + if (arm_decode_field (given, 20, 21) == 3) + return TRUE; + return FALSE; + + case MVE_VCMP_FP_T1: + if ((arm_decode_field (given, 12, 12) == 0) + && (arm_decode_field (given, 0, 0) == 1)) + return TRUE; + else + return FALSE; + + case MVE_VCMP_FP_T2: + if (arm_decode_field (given, 0, 3) == 0xd) + return TRUE; + else + return FALSE; + + case MVE_VCMP_VEC_T1: + case MVE_VCMP_VEC_T2: + case MVE_VCMP_VEC_T3: + case MVE_VCMP_VEC_T4: + case MVE_VCMP_VEC_T5: + case MVE_VCMP_VEC_T6: + if (arm_decode_field (given, 20, 21) == 3) + return TRUE; + else + return FALSE; + + default: + return FALSE; + + } } /* Return FALSE if GIVEN is not an undefined encoding for MATCHED_INSN. @@ -3576,18 +3953,37 @@ is_mve_unpredictable (unsigned long given, enum mve_instructions matched_insn, { *unpredictable_code = UNPRED_NONE; - return FALSE; -} + switch (matched_insn) + { + case MVE_VCMP_FP_T2: + case MVE_VPT_FP_T2: + if ((arm_decode_field (given, 12, 12) == 0) + && (arm_decode_field (given, 5, 5) == 1)) + { + *unpredictable_code = UNPRED_FCA_0_FCB_1; + return TRUE; + } + else + return FALSE; -#define W_BIT 21 -#define I_BIT 22 -#define U_BIT 23 -#define P_BIT 24 + case MVE_VPT_VEC_T4: + case MVE_VPT_VEC_T5: + case MVE_VPT_VEC_T6: + case MVE_VCMP_VEC_T4: + case MVE_VCMP_VEC_T5: + case MVE_VCMP_VEC_T6: + if (arm_decode_field (given, 0, 3) == 0xd) + { + *unpredictable_code = UNPRED_R13; + return TRUE; + } + else + return FALSE; -#define WRITEBACK_BIT_SET (given & (1 << W_BIT)) -#define IMMEDIATE_BIT_SET (given & (1 << I_BIT)) -#define NEGATIVE_BIT_SET ((given & (1 << U_BIT)) == 0) -#define PRE_BIT_SET (given & (1 << P_BIT)) + default: + return FALSE; + } +} static void print_mve_undefined (struct disassemble_info *info, @@ -3621,11 +4017,154 @@ print_mve_unpredictable (struct disassemble_info *info, func (stream, "mve instruction in it block"); break; + case UNPRED_FCA_0_FCB_1: + func (stream, "condition bits, fca = 0 and fcb = 1"); + break; + + case UNPRED_R13: + func (stream, "use of r13 (sp)"); + break; + case UNPRED_NONE: break; } } +static void +print_instruction_predicate (struct disassemble_info *info) +{ + void *stream = info->stream; + fprintf_ftype func = info->fprintf_func; + + if (vpt_block_state.next_pred_state == PRED_THEN) + func (stream, "t"); + else if (vpt_block_state.next_pred_state == PRED_ELSE) + func (stream, "e"); +} + +static void +print_mve_size (struct disassemble_info *info, + unsigned long size, + enum mve_instructions matched_insn) +{ + void *stream = info->stream; + fprintf_ftype func = info->fprintf_func; + + switch (matched_insn) + { + case MVE_VCMP_VEC_T1: + case MVE_VCMP_VEC_T2: + case MVE_VCMP_VEC_T3: + case MVE_VCMP_VEC_T4: + case MVE_VCMP_VEC_T5: + case MVE_VCMP_VEC_T6: + case MVE_VPT_VEC_T1: + case MVE_VPT_VEC_T2: + case MVE_VPT_VEC_T3: + case MVE_VPT_VEC_T4: + case MVE_VPT_VEC_T5: + case MVE_VPT_VEC_T6: + if (size <= 3) + func (stream, "%s", mve_vec_sizename[size]); + else + func (stream, ""); + break; + + case MVE_VCMP_FP_T1: + case MVE_VCMP_FP_T2: + case MVE_VPT_FP_T1: + case MVE_VPT_FP_T2: + if (size == 0) + func (stream, "32"); + else if (size == 1) + func (stream, "16"); + break; + + default: + break; + } +} + +static void +print_vec_condition (struct disassemble_info *info, long given, + enum mve_instructions matched_insn) +{ + void *stream = info->stream; + fprintf_ftype func = info->fprintf_func; + long vec_cond = 0; + + switch (matched_insn) + { + case MVE_VPT_FP_T1: + case MVE_VCMP_FP_T1: + vec_cond = (((given & 0x1000) >> 10) + | ((given & 1) << 1) + | ((given & 0x0080) >> 7)); + func (stream, "%s",vec_condnames[vec_cond]); + break; + + case MVE_VPT_FP_T2: + case MVE_VCMP_FP_T2: + vec_cond = (((given & 0x1000) >> 10) + | ((given & 0x0020) >> 4) + | ((given & 0x0080) >> 7)); + func (stream, "%s",vec_condnames[vec_cond]); + break; + + case MVE_VPT_VEC_T1: + case MVE_VCMP_VEC_T1: + vec_cond = (given & 0x0080) >> 7; + func (stream, "%s",vec_condnames[vec_cond]); + break; + + case MVE_VPT_VEC_T2: + case MVE_VCMP_VEC_T2: + vec_cond = 2 | ((given & 0x0080) >> 7); + func (stream, "%s",vec_condnames[vec_cond]); + break; + + case MVE_VPT_VEC_T3: + case MVE_VCMP_VEC_T3: + vec_cond = 4 | ((given & 1) << 1) | ((given & 0x0080) >> 7); + func (stream, "%s",vec_condnames[vec_cond]); + break; + + case MVE_VPT_VEC_T4: + case MVE_VCMP_VEC_T4: + vec_cond = (given & 0x0080) >> 7; + func (stream, "%s",vec_condnames[vec_cond]); + break; + + case MVE_VPT_VEC_T5: + case MVE_VCMP_VEC_T5: + vec_cond = 2 | ((given & 0x0080) >> 7); + func (stream, "%s",vec_condnames[vec_cond]); + break; + + case MVE_VPT_VEC_T6: + case MVE_VCMP_VEC_T6: + vec_cond = 4 | ((given & 0x0020) >> 4) | ((given & 0x0080) >> 7); + func (stream, "%s",vec_condnames[vec_cond]); + break; + + case MVE_NONE: + case MVE_VPST: + default: + break; + } +} + +#define W_BIT 21 +#define I_BIT 22 +#define U_BIT 23 +#define P_BIT 24 + +#define WRITEBACK_BIT_SET (given & (1 << W_BIT)) +#define IMMEDIATE_BIT_SET (given & (1 << I_BIT)) +#define NEGATIVE_BIT_SET ((given & (1 << U_BIT)) == 0) +#define PRE_BIT_SET (given & (1 << P_BIT)) + + /* Print one coprocessor instruction on INFO->STREAM. Return TRUE if the instuction matched, FALSE if this is not a recognised coprocessor instruction. */ @@ -4975,6 +5514,62 @@ print_insn_mve (struct disassemble_info *info, long given) func (stream, "%%"); break; + case 'c': + if (ifthen_state) + func (stream, "%s", arm_conditional[IFTHEN_COND]); + break; + + case 'i': + { + long mve_mask = mve_extract_pred_mask (given); + func (stream, "%s", mve_predicatenames[mve_mask]); + } + break; + + case 'n': + print_vec_condition (info, given, insn->mve_op); + break; + + case 'v': + print_instruction_predicate (info); + break; + + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + { + int width; + unsigned long value; + + c = arm_decode_bitfield (c, given, &value, &width); + + switch (*c) + { + case 'Z': + if (value == 13) + is_unpredictable = TRUE; + else if (value == 15) + func (stream, "zr"); + else + func (stream, "%s", arm_regnames[value]); + break; + case 's': + print_mve_size (info, + value, + insn->mve_op); + break; + case 'Q': + if (value & 0x8) + func (stream, "", value); + else + func (stream, "q%ld", value); + break; + default: + abort (); + } + break; + default: + abort (); + } } } else @@ -4990,6 +5585,13 @@ print_insn_mve (struct disassemble_info *info, long given) if (is_undefined) print_mve_undefined (info, undefined_cond); + if ((vpt_block_state.in_vpt_block == FALSE) + && !ifthen_state + && (is_vpt_instruction (given) == TRUE)) + mark_inside_vpt_block (given); + else if (vpt_block_state.in_vpt_block == TRUE) + update_vpt_block_state (); + return TRUE; } } --------------3AD6DAF84A9D4ECEB058BFFC--