From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 38859 invoked by alias); 25 Aug 2016 15:07:53 -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 38845 invoked by uid 89); 25 Aug 2016 15:07:52 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.1 required=5.0 tests=BAYES_00,RP_MATCHES_RCVD,SPF_PASS autolearn=ham version=3.3.2 spammy=ROR, 4856, 2997, applicable 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; Thu, 25 Aug 2016 15:07:50 +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 EFF14451; Thu, 25 Aug 2016 08:09:29 -0700 (PDT) Received: from e105689-lin.cambridge.arm.com (e105689-lin.cambridge.arm.com [10.2.207.32]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id C124F3F252; Thu, 25 Aug 2016 08:07:48 -0700 (PDT) Subject: Re: [AArch64][SVE 30/32] Add SVE instruction classes To: binutils@sourceware.org, richard.sandiford@arm.com References: <874m6b6ekq.fsf@e105548-lin.cambridge.arm.com> <87inurzviy.fsf@e105548-lin.cambridge.arm.com> From: "Richard Earnshaw (lists)" Message-ID: Date: Thu, 25 Aug 2016 15:07:00 -0000 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Thunderbird/45.2.0 MIME-Version: 1.0 In-Reply-To: <87inurzviy.fsf@e105548-lin.cambridge.arm.com> Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit X-SW-Source: 2016-08/txt/msg00276.txt.bz2 On 23/08/16 10:25, Richard Sandiford wrote: > The main purpose of the SVE aarch64_insn_classes is to describe how > an index into an aarch64_opnd_qualifier_seq_t is represented in the > instruction encoding. Other instructions usually use flags for this > information, but (a) we're running out of those and (b) the iclass > would otherwise be unused for SVE. > > OK to install? > > Thanks, > Richard > > > include/opcode/ > * aarch64.h (sve_cpy, sve_index, sve_limm, sve_misc, sve_movprfx) > (sve_pred_zm, sve_shift_pred, sve_shift_unpred, sve_size_bhs) > (sve_size_bhsd, sve_size_hsd, sve_size_sd): New aarch64_insn_classes. > > opcodes/ > * aarch64-opc.h (FLD_SVE_M_4, FLD_SVE_M_14, FLD_SVE_M_16) > (FLD_SVE_sz, FLD_SVE_tsz, FLD_SVE_tszl_8, FLD_SVE_tszl_19): New > aarch64_field_kinds. > * aarch64-opc.c (fields): Add corresponding entries. > * aarch64-asm.c (aarch64_get_variant): New function. > (aarch64_encode_variant_using_iclass): Likewise. > (aarch64_opcode_encode): Call it. > * aarch64-dis.c (aarch64_decode_variant_using_iclass): New function. > (aarch64_opcode_decode): Call it. > OK R. > diff --git a/include/opcode/aarch64.h b/include/opcode/aarch64.h > index 8d3fb21..01e6b2c 100644 > --- a/include/opcode/aarch64.h > +++ b/include/opcode/aarch64.h > @@ -485,6 +485,18 @@ enum aarch64_insn_class > movewide, > pcreladdr, > ic_system, > + sve_cpy, > + sve_index, > + sve_limm, > + sve_misc, > + sve_movprfx, > + sve_pred_zm, > + sve_shift_pred, > + sve_shift_unpred, > + sve_size_bhs, > + sve_size_bhsd, > + sve_size_hsd, > + sve_size_sd, > testbranch, > }; > > diff --git a/opcodes/aarch64-asm.c b/opcodes/aarch64-asm.c > index fd356f4..78fd272 100644 > --- a/opcodes/aarch64-asm.c > +++ b/opcodes/aarch64-asm.c > @@ -1140,6 +1140,27 @@ encode_fcvt (aarch64_inst *inst) > return; > } > > +/* Return the index in qualifiers_list that INST is using. Should only > + be called once the qualifiers are known to be valid. */ > + > +static int > +aarch64_get_variant (struct aarch64_inst *inst) > +{ > + int i, nops, variant; > + > + nops = aarch64_num_of_operands (inst->opcode); > + for (variant = 0; variant < AARCH64_MAX_QLF_SEQ_NUM; ++variant) > + { > + for (i = 0; i < nops; ++i) > + if (inst->opcode->qualifiers_list[variant][i] > + != inst->operands[i].qualifier) > + break; > + if (i == nops) > + return variant; > + } > + abort (); > +} > + > /* Do miscellaneous encodings that are not common enough to be driven by > flags. */ > > @@ -1318,6 +1339,65 @@ do_special_encoding (struct aarch64_inst *inst) > DEBUG_TRACE ("exit with coding 0x%x", (uint32_t) inst->value); > } > > +/* Some instructions (including all SVE ones) use the instruction class > + to describe how a qualifiers_list index is represented in the instruction > + encoding. If INST is such an instruction, encode the chosen qualifier > + variant. */ > + > +static void > +aarch64_encode_variant_using_iclass (struct aarch64_inst *inst) > +{ > + switch (inst->opcode->iclass) > + { > + case sve_cpy: > + insert_fields (&inst->value, aarch64_get_variant (inst), > + 0, 2, FLD_SVE_M_14, FLD_size); > + break; > + > + case sve_index: > + case sve_shift_pred: > + case sve_shift_unpred: > + /* For indices and shift amounts, the variant is encoded as > + part of the immediate. */ > + break; > + > + case sve_limm: > + /* For sve_limm, the .B, .H, and .S forms are just a convenience > + and depend on the immediate. They don't have a separate > + encoding. */ > + break; > + > + case sve_misc: > + /* sve_misc instructions have only a single variant. */ > + break; > + > + case sve_movprfx: > + insert_fields (&inst->value, aarch64_get_variant (inst), > + 0, 2, FLD_SVE_M_16, FLD_size); > + break; > + > + case sve_pred_zm: > + insert_field (FLD_SVE_M_4, &inst->value, aarch64_get_variant (inst), 0); > + break; > + > + case sve_size_bhs: > + case sve_size_bhsd: > + insert_field (FLD_size, &inst->value, aarch64_get_variant (inst), 0); > + break; > + > + case sve_size_hsd: > + insert_field (FLD_size, &inst->value, aarch64_get_variant (inst) + 1, 0); > + break; > + > + case sve_size_sd: > + insert_field (FLD_SVE_sz, &inst->value, aarch64_get_variant (inst), 0); > + break; > + > + default: > + break; > + } > +} > + > /* Converters converting an alias opcode instruction to its real form. */ > > /* ROR , , # > @@ -1686,6 +1766,10 @@ aarch64_opcode_encode (const aarch64_opcode *opcode, > if (opcode_has_special_coder (opcode)) > do_special_encoding (inst); > > + /* Possibly use the instruction class to encode the chosen qualifier > + variant. */ > + aarch64_encode_variant_using_iclass (inst); > + > encoding_exit: > DEBUG_TRACE ("exit with %s", opcode->name); > > diff --git a/opcodes/aarch64-dis.c b/opcodes/aarch64-dis.c > index 385286c..f84f216 100644 > --- a/opcodes/aarch64-dis.c > +++ b/opcodes/aarch64-dis.c > @@ -2444,6 +2444,105 @@ determine_disassembling_preference (struct aarch64_inst *inst) > } > } > > +/* Some instructions (including all SVE ones) use the instruction class > + to describe how a qualifiers_list index is represented in the instruction > + encoding. If INST is such an instruction, decode the appropriate fields > + and fill in the operand qualifiers accordingly. Return true if no > + problems are found. */ > + > +static bfd_boolean > +aarch64_decode_variant_using_iclass (aarch64_inst *inst) > +{ > + int i, variant; > + > + variant = 0; > + switch (inst->opcode->iclass) > + { > + case sve_cpy: > + variant = extract_fields (inst->value, 0, 2, FLD_size, FLD_SVE_M_14); > + break; > + > + case sve_index: > + i = extract_field (FLD_SVE_tsz, inst->value, 0); > + if (i == 0) > + return FALSE; > + while ((i & 1) == 0) > + { > + i >>= 1; > + variant += 1; > + } > + break; > + > + case sve_limm: > + /* Pick the smallest applicable element size. */ > + if ((inst->value & 0x20600) == 0x600) > + variant = 0; > + else if ((inst->value & 0x20400) == 0x400) > + variant = 1; > + else if ((inst->value & 0x20000) == 0) > + variant = 2; > + else > + variant = 3; > + break; > + > + case sve_misc: > + /* sve_misc instructions have only a single variant. */ > + break; > + > + case sve_movprfx: > + variant = extract_fields (inst->value, 0, 2, FLD_size, FLD_SVE_M_16); > + break; > + > + case sve_pred_zm: > + variant = extract_field (FLD_SVE_M_4, inst->value, 0); > + break; > + > + case sve_shift_pred: > + i = extract_fields (inst->value, 0, 2, FLD_SVE_tszh, FLD_SVE_tszl_8); > + sve_shift: > + if (i == 0) > + return FALSE; > + while (i != 1) > + { > + i >>= 1; > + variant += 1; > + } > + break; > + > + case sve_shift_unpred: > + i = extract_fields (inst->value, 0, 2, FLD_SVE_tszh, FLD_SVE_tszl_19); > + goto sve_shift; > + > + case sve_size_bhs: > + variant = extract_field (FLD_size, inst->value, 0); > + if (variant >= 3) > + return FALSE; > + break; > + > + case sve_size_bhsd: > + variant = extract_field (FLD_size, inst->value, 0); > + break; > + > + case sve_size_hsd: > + i = extract_field (FLD_size, inst->value, 0); > + if (i < 1) > + return FALSE; > + variant = i - 1; > + break; > + > + case sve_size_sd: > + variant = extract_field (FLD_SVE_sz, inst->value, 0); > + break; > + > + default: > + /* No mapping between instruction class and qualifiers. */ > + return TRUE; > + } > + > + for (i = 0; i < AARCH64_MAX_OPND_NUM; ++i) > + inst->operands[i].qualifier = inst->opcode->qualifiers_list[variant][i]; > + return TRUE; > +} > /* Decode the CODE according to OPCODE; fill INST. Return 0 if the decoding > fails, which meanes that CODE is not an instruction of OPCODE; otherwise > return 1. > @@ -2491,6 +2590,14 @@ aarch64_opcode_decode (const aarch64_opcode *opcode, const aarch64_insn code, > goto decode_fail; > } > > + /* Possibly use the instruction class to determine the correct > + qualifier. */ > + if (!aarch64_decode_variant_using_iclass (inst)) > + { > + DEBUG_TRACE ("iclass-based decoder FAIL"); > + goto decode_fail; > + } > + > /* Call operand decoders. */ > for (i = 0; i < AARCH64_MAX_OPND_NUM; ++i) > { > diff --git a/opcodes/aarch64-opc.c b/opcodes/aarch64-opc.c > index 1ad4ccf..2eb2a81 100644 > --- a/opcodes/aarch64-opc.c > +++ b/opcodes/aarch64-opc.c > @@ -264,6 +264,9 @@ const aarch64_field fields[] = > { 31, 1 }, /* b5: in the test bit and branch instructions. */ > { 19, 5 }, /* b40: in the test bit and branch instructions. */ > { 10, 6 }, /* scale: in the fixed-point scalar to fp converting inst. */ > + { 4, 1 }, /* SVE_M_4: Merge/zero select, bit 4. */ > + { 14, 1 }, /* SVE_M_14: Merge/zero select, bit 14. */ > + { 16, 1 }, /* SVE_M_16: Merge/zero select, bit 16. */ > { 17, 1 }, /* SVE_N: SVE equivalent of N. */ > { 0, 4 }, /* SVE_Pd: p0-p15, bits [3,0]. */ > { 10, 3 }, /* SVE_Pg3: p0-p7, bits [12,10]. */ > @@ -299,7 +302,11 @@ const aarch64_field fields[] = > { 10, 2 }, /* SVE_msz: 2-bit shift amount for ADR. */ > { 5, 5 }, /* SVE_pattern: vector pattern enumeration. */ > { 0, 4 }, /* SVE_prfop: prefetch operation for SVE PRF[BHWD]. */ > + { 22, 1 }, /* SVE_sz: 1-bit element size select. */ > + { 16, 4 }, /* SVE_tsz: triangular size select. */ > { 22, 2 }, /* SVE_tszh: triangular size select high, bits [23,22]. */ > + { 8, 2 }, /* SVE_tszl_8: triangular size select low, bits [9,8]. */ > + { 19, 2 }, /* SVE_tszl_19: triangular size select low, bits [20,19]. */ > { 14, 1 }, /* SVE_xs_14: UXTW/SXTW select (bit 14). */ > { 22, 1 } /* SVE_xs_22: UXTW/SXTW select (bit 22). */ > }; > diff --git a/opcodes/aarch64-opc.h b/opcodes/aarch64-opc.h > index a7654d0..0c3d90e 100644 > --- a/opcodes/aarch64-opc.h > +++ b/opcodes/aarch64-opc.h > @@ -91,6 +91,9 @@ enum aarch64_field_kind > FLD_b5, > FLD_b40, > FLD_scale, > + FLD_SVE_M_4, > + FLD_SVE_M_14, > + FLD_SVE_M_16, > FLD_SVE_N, > FLD_SVE_Pd, > FLD_SVE_Pg3, > @@ -126,7 +129,11 @@ enum aarch64_field_kind > FLD_SVE_msz, > FLD_SVE_pattern, > FLD_SVE_prfop, > + FLD_SVE_sz, > + FLD_SVE_tsz, > FLD_SVE_tszh, > + FLD_SVE_tszl_8, > + FLD_SVE_tszl_19, > FLD_SVE_xs_14, > FLD_SVE_xs_22, > }; >