From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 106060 invoked by alias); 25 Aug 2016 14:51:48 -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 106004 invoked by uid 89); 25 Aug 2016 14:51:47 -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=cpy, Top, Immediate 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 14:51:41 +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 78DBF28; Thu, 25 Aug 2016 07:53:20 -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 6FBBA3F252; Thu, 25 Aug 2016 07:51:39 -0700 (PDT) Subject: Re: [AArch64][SVE 27/32] Add SVE integer immediate operands To: binutils@sourceware.org, richard.sandiford@arm.com References: <874m6b6ekq.fsf@e105548-lin.cambridge.arm.com> <87vayrzvm2.fsf@e105548-lin.cambridge.arm.com> From: "Richard Earnshaw (lists)" Message-ID: Date: Thu, 25 Aug 2016 14:51: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: <87vayrzvm2.fsf@e105548-lin.cambridge.arm.com> Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit X-SW-Source: 2016-08/txt/msg00271.txt.bz2 On 23/08/16 10:24, Richard Sandiford wrote: > This patch adds the new SVE integer immediate operands. There are > three kinds: > > - simple signed and unsigned ranges, but with new widths and positions. > > - 13-bit logical immediates. These have the same form as in base AArch64, > but at a different bit position. > > In the case of the "MOV Zn., #" alias of DUPM, the logical > immediate is not allowed to be a valid DUP immediate, since DUP > is preferred over DUPM for constants that both instructions can handle. > > - a new 9-bit arithmetic immediate, of the form "{, LSL #8}". > In some contexts the operand is signed and in others it's unsigned. > As an extension, we allow shifted immediates to be written as a single > integer, e.g. "#256" is equivalent to "#1, LSL #8". We also use the > shiftless form as the preferred disassembly, except for the special > case of "#0, LSL #8" (a redundant encoding of 0). > > OK to install? > > Thanks, > Richard > > > include/opcode/ > * aarch64.h (AARCH64_OPND_SIMM5): New aarch64_opnd. > (AARCH64_OPND_SVE_AIMM, AARCH64_OPND_SVE_ASIMM) > (AARCH64_OPND_SVE_INV_LIMM, AARCH64_OPND_SVE_LIMM) > (AARCH64_OPND_SVE_LIMM_MOV, AARCH64_OPND_SVE_SHLIMM_PRED) > (AARCH64_OPND_SVE_SHLIMM_UNPRED, AARCH64_OPND_SVE_SHRIMM_PRED) > (AARCH64_OPND_SVE_SHRIMM_UNPRED, AARCH64_OPND_SVE_SIMM5) > (AARCH64_OPND_SVE_SIMM5B, AARCH64_OPND_SVE_SIMM6) > (AARCH64_OPND_SVE_SIMM8, AARCH64_OPND_SVE_UIMM3) > (AARCH64_OPND_SVE_UIMM7, AARCH64_OPND_SVE_UIMM8) > (AARCH64_OPND_SVE_UIMM8_53): Likewise. > (aarch64_sve_dupm_mov_immediate_p): Declare. > > opcodes/ > * aarch64-tbl.h (AARCH64_OPERANDS): Add entries for the new SVE > integer immediate operands. > * aarch64-opc.h (FLD_SVE_immN, FLD_SVE_imm3, FLD_SVE_imm5) > (FLD_SVE_imm5b, FLD_SVE_imm7, FLD_SVE_imm8, FLD_SVE_imm9) > (FLD_SVE_immr, FLD_SVE_imms, FLD_SVE_tszh): New aarch64_field_kinds. > * aarch64-opc.c (fields): Add corresponding entries. > (operand_general_constraint_met_p): Handle the new SVE integer > immediate operands. > (aarch64_print_operand): Likewise. > (aarch64_sve_dupm_mov_immediate_p): New function. > * aarch64-opc-2.c: Regenerate. > * aarch64-asm.h (ins_inv_limm, ins_sve_aimm, ins_sve_asimm) > (ins_sve_limm_mov, ins_sve_shlimm, ins_sve_shrimm): New inserters. > * aarch64-asm.c (aarch64_ins_limm_1): New function, split out from... > (aarch64_ins_limm): ...here. > (aarch64_ins_inv_limm): New function. > (aarch64_ins_sve_aimm): Likewise. > (aarch64_ins_sve_asimm): Likewise. > (aarch64_ins_sve_limm_mov): Likewise. > (aarch64_ins_sve_shlimm): Likewise. > (aarch64_ins_sve_shrimm): Likewise. > * aarch64-asm-2.c: Regenerate. > * aarch64-dis.h (ext_inv_limm, ext_sve_aimm, ext_sve_asimm) > (ext_sve_limm_mov, ext_sve_shlimm, ext_sve_shrimm): New extractors. > * aarch64-dis.c (decode_limm): New function, split out from... > (aarch64_ext_limm): ...here. > (aarch64_ext_inv_limm): New function. > (decode_sve_aimm): Likewise. > (aarch64_ext_sve_aimm): Likewise. > (aarch64_ext_sve_asimm): Likewise. > (aarch64_ext_sve_limm_mov): Likewise. > (aarch64_top_bit): Likewise. > (aarch64_ext_sve_shlimm): Likewise. > (aarch64_ext_sve_shrimm): Likewise. > * aarch64-dis-2.c: Regenerate. > > gas/ > * config/tc-aarch64.c (parse_operands): Handle the new SVE integer > immediate operands. + set_other_error (mismatch_detail, idx, + _("shift amount should be 0 or 8")); I think the error message should use 'must' rather than 'should'. 'Should' implies a degree of optionality that just doesn't apply here. OK with that change. R. > > diff --git a/gas/config/tc-aarch64.c b/gas/config/tc-aarch64.c > index 37fce5b..cb39cf8 100644 > --- a/gas/config/tc-aarch64.c > +++ b/gas/config/tc-aarch64.c > @@ -5553,6 +5553,7 @@ parse_operands (char *str, const aarch64_opcode *opcode) > break; > > case AARCH64_OPND_CCMP_IMM: > + case AARCH64_OPND_SIMM5: > case AARCH64_OPND_FBITS: > case AARCH64_OPND_UIMM4: > case AARCH64_OPND_UIMM3_OP1: > @@ -5560,10 +5561,36 @@ parse_operands (char *str, const aarch64_opcode *opcode) > case AARCH64_OPND_IMM_VLSL: > case AARCH64_OPND_IMM: > case AARCH64_OPND_WIDTH: > + case AARCH64_OPND_SVE_INV_LIMM: > + case AARCH64_OPND_SVE_LIMM: > + case AARCH64_OPND_SVE_LIMM_MOV: > + case AARCH64_OPND_SVE_SHLIMM_PRED: > + case AARCH64_OPND_SVE_SHLIMM_UNPRED: > + case AARCH64_OPND_SVE_SHRIMM_PRED: > + case AARCH64_OPND_SVE_SHRIMM_UNPRED: > + case AARCH64_OPND_SVE_SIMM5: > + case AARCH64_OPND_SVE_SIMM5B: > + case AARCH64_OPND_SVE_SIMM6: > + case AARCH64_OPND_SVE_SIMM8: > + case AARCH64_OPND_SVE_UIMM3: > + case AARCH64_OPND_SVE_UIMM7: > + case AARCH64_OPND_SVE_UIMM8: > + case AARCH64_OPND_SVE_UIMM8_53: > po_imm_nc_or_fail (); > info->imm.value = val; > break; > > + case AARCH64_OPND_SVE_AIMM: > + case AARCH64_OPND_SVE_ASIMM: > + po_imm_nc_or_fail (); > + info->imm.value = val; > + skip_whitespace (str); > + if (skip_past_comma (&str)) > + po_misc_or_fail (parse_shift (&str, info, SHIFTED_LSL)); > + else > + inst.base.operands[i].shifter.kind = AARCH64_MOD_LSL; > + break; > + > case AARCH64_OPND_SVE_PATTERN: > po_enum_or_fail (aarch64_sve_pattern_array); > info->imm.value = val; > diff --git a/include/opcode/aarch64.h b/include/opcode/aarch64.h > index 837d6bd..36e95b4 100644 > --- a/include/opcode/aarch64.h > +++ b/include/opcode/aarch64.h > @@ -200,6 +200,7 @@ enum aarch64_opnd > AARCH64_OPND_BIT_NUM, /* Immediate. */ > AARCH64_OPND_EXCEPTION,/* imm16 operand in exception instructions. */ > AARCH64_OPND_CCMP_IMM,/* Immediate in conditional compare instructions. */ > + AARCH64_OPND_SIMM5, /* 5-bit signed immediate in the imm5 field. */ > AARCH64_OPND_NZCV, /* Flag bit specifier giving an alternative value for > each condition flag. */ > > @@ -289,6 +290,11 @@ enum aarch64_opnd > AARCH64_OPND_SVE_ADDR_ZZ_LSL, /* SVE [Zn., Zm,, LSL #]. */ > AARCH64_OPND_SVE_ADDR_ZZ_SXTW, /* SVE [Zn., Zm,, SXTW #]. */ > AARCH64_OPND_SVE_ADDR_ZZ_UXTW, /* SVE [Zn., Zm,, UXTW #]. */ > + AARCH64_OPND_SVE_AIMM, /* SVE unsigned arithmetic immediate. */ > + AARCH64_OPND_SVE_ASIMM, /* SVE signed arithmetic immediate. */ > + AARCH64_OPND_SVE_INV_LIMM, /* SVE inverted logical immediate. */ > + AARCH64_OPND_SVE_LIMM, /* SVE logical immediate. */ > + AARCH64_OPND_SVE_LIMM_MOV, /* SVE logical immediate for MOV. */ > AARCH64_OPND_SVE_PATTERN, /* SVE vector pattern enumeration. */ > AARCH64_OPND_SVE_PATTERN_SCALED, /* Likewise, with additional MUL factor. */ > AARCH64_OPND_SVE_PRFOP, /* SVE prefetch operation. */ > @@ -300,6 +306,18 @@ enum aarch64_opnd > AARCH64_OPND_SVE_Pm, /* SVE p0-p15 in Pm. */ > AARCH64_OPND_SVE_Pn, /* SVE p0-p15 in Pn. */ > AARCH64_OPND_SVE_Pt, /* SVE p0-p15 in Pt. */ > + AARCH64_OPND_SVE_SHLIMM_PRED, /* SVE shift left amount (predicated). */ > + AARCH64_OPND_SVE_SHLIMM_UNPRED, /* SVE shift left amount (unpredicated). */ > + AARCH64_OPND_SVE_SHRIMM_PRED, /* SVE shift right amount (predicated). */ > + AARCH64_OPND_SVE_SHRIMM_UNPRED, /* SVE shift right amount (unpredicated). */ > + AARCH64_OPND_SVE_SIMM5, /* SVE signed 5-bit immediate. */ > + AARCH64_OPND_SVE_SIMM5B, /* SVE secondary signed 5-bit immediate. */ > + AARCH64_OPND_SVE_SIMM6, /* SVE signed 6-bit immediate. */ > + AARCH64_OPND_SVE_SIMM8, /* SVE signed 8-bit immediate. */ > + AARCH64_OPND_SVE_UIMM3, /* SVE unsigned 3-bit immediate. */ > + AARCH64_OPND_SVE_UIMM7, /* SVE unsigned 7-bit immediate. */ > + AARCH64_OPND_SVE_UIMM8, /* SVE unsigned 8-bit immediate. */ > + AARCH64_OPND_SVE_UIMM8_53, /* SVE split unsigned 8-bit immediate. */ > AARCH64_OPND_SVE_Za_5, /* SVE vector register in Za, bits [9,5]. */ > AARCH64_OPND_SVE_Za_16, /* SVE vector register in Za, bits [20,16]. */ > AARCH64_OPND_SVE_Zd, /* SVE vector register in Zd. */ > @@ -1065,6 +1083,9 @@ aarch64_get_operand_name (enum aarch64_opnd); > extern const char * > aarch64_get_operand_desc (enum aarch64_opnd); > > +extern bfd_boolean > +aarch64_sve_dupm_mov_immediate_p (uint64_t, int); > + > #ifdef DEBUG_AARCH64 > extern int debug_dump; > > diff --git a/opcodes/aarch64-asm-2.c b/opcodes/aarch64-asm-2.c > index da590ca..491ea53 100644 > --- a/opcodes/aarch64-asm-2.c > +++ b/opcodes/aarch64-asm-2.c > @@ -480,12 +480,6 @@ aarch64_insert_operand (const aarch64_operand *self, > case 27: > case 35: > case 36: > - case 129: > - case 130: > - case 131: > - case 132: > - case 133: > - case 134: > case 135: > case 136: > case 137: > @@ -494,7 +488,13 @@ aarch64_insert_operand (const aarch64_operand *self, > case 140: > case 141: > case 142: > - case 145: > + case 155: > + case 156: > + case 157: > + case 158: > + case 159: > + case 160: > + case 163: > return aarch64_ins_regno (self, info, code, inst); > case 12: > return aarch64_ins_reg_extended (self, info, code, inst); > @@ -527,12 +527,21 @@ aarch64_insert_operand (const aarch64_operand *self, > case 56: > case 57: > case 58: > - case 67: > + case 59: > case 68: > case 69: > case 70: > - case 126: > - case 128: > + case 71: > + case 132: > + case 134: > + case 147: > + case 148: > + case 149: > + case 150: > + case 151: > + case 152: > + case 153: > + case 154: > return aarch64_ins_imm (self, info, code, inst); > case 38: > case 39: > @@ -543,61 +552,61 @@ aarch64_insert_operand (const aarch64_operand *self, > return aarch64_ins_advsimd_imm_modified (self, info, code, inst); > case 46: > return aarch64_ins_fpimm (self, info, code, inst); > - case 59: > - return aarch64_ins_limm (self, info, code, inst); > case 60: > - return aarch64_ins_aimm (self, info, code, inst); > + case 130: > + return aarch64_ins_limm (self, info, code, inst); > case 61: > - return aarch64_ins_imm_half (self, info, code, inst); > + return aarch64_ins_aimm (self, info, code, inst); > case 62: > + return aarch64_ins_imm_half (self, info, code, inst); > + case 63: > return aarch64_ins_fbits (self, info, code, inst); > - case 64: > case 65: > + case 66: > return aarch64_ins_cond (self, info, code, inst); > - case 71: > - case 77: > - return aarch64_ins_addr_simple (self, info, code, inst); > case 72: > - return aarch64_ins_addr_regoff (self, info, code, inst); > + case 78: > + return aarch64_ins_addr_simple (self, info, code, inst); > case 73: > + return aarch64_ins_addr_regoff (self, info, code, inst); > case 74: > case 75: > - return aarch64_ins_addr_simm (self, info, code, inst); > case 76: > + return aarch64_ins_addr_simm (self, info, code, inst); > + case 77: > return aarch64_ins_addr_uimm12 (self, info, code, inst); > - case 78: > - return aarch64_ins_simd_addr_post (self, info, code, inst); > case 79: > - return aarch64_ins_sysreg (self, info, code, inst); > + return aarch64_ins_simd_addr_post (self, info, code, inst); > case 80: > - return aarch64_ins_pstatefield (self, info, code, inst); > + return aarch64_ins_sysreg (self, info, code, inst); > case 81: > + return aarch64_ins_pstatefield (self, info, code, inst); > case 82: > case 83: > case 84: > - return aarch64_ins_sysins_op (self, info, code, inst); > case 85: > + return aarch64_ins_sysins_op (self, info, code, inst); > case 86: > - return aarch64_ins_barrier (self, info, code, inst); > case 87: > - return aarch64_ins_prfop (self, info, code, inst); > + return aarch64_ins_barrier (self, info, code, inst); > case 88: > - return aarch64_ins_hint (self, info, code, inst); > + return aarch64_ins_prfop (self, info, code, inst); > case 89: > + return aarch64_ins_hint (self, info, code, inst); > case 90: > case 91: > case 92: > - return aarch64_ins_sve_addr_ri_s4xvl (self, info, code, inst); > case 93: > - return aarch64_ins_sve_addr_ri_s6xvl (self, info, code, inst); > + return aarch64_ins_sve_addr_ri_s4xvl (self, info, code, inst); > case 94: > - return aarch64_ins_sve_addr_ri_s9xvl (self, info, code, inst); > + return aarch64_ins_sve_addr_ri_s6xvl (self, info, code, inst); > case 95: > + return aarch64_ins_sve_addr_ri_s9xvl (self, info, code, inst); > case 96: > case 97: > case 98: > - return aarch64_ins_sve_addr_ri_u6 (self, info, code, inst); > case 99: > + return aarch64_ins_sve_addr_ri_u6 (self, info, code, inst); > case 100: > case 101: > case 102: > @@ -609,8 +618,8 @@ aarch64_insert_operand (const aarch64_operand *self, > case 108: > case 109: > case 110: > - return aarch64_ins_sve_addr_rr_lsl (self, info, code, inst); > case 111: > + return aarch64_ins_sve_addr_rr_lsl (self, info, code, inst); > case 112: > case 113: > case 114: > @@ -618,24 +627,39 @@ aarch64_insert_operand (const aarch64_operand *self, > case 116: > case 117: > case 118: > - return aarch64_ins_sve_addr_rz_xtw (self, info, code, inst); > case 119: > + return aarch64_ins_sve_addr_rz_xtw (self, info, code, inst); > case 120: > case 121: > case 122: > - return aarch64_ins_sve_addr_zi_u5 (self, info, code, inst); > case 123: > - return aarch64_ins_sve_addr_zz_lsl (self, info, code, inst); > + return aarch64_ins_sve_addr_zi_u5 (self, info, code, inst); > case 124: > - return aarch64_ins_sve_addr_zz_sxtw (self, info, code, inst); > + return aarch64_ins_sve_addr_zz_lsl (self, info, code, inst); > case 125: > + return aarch64_ins_sve_addr_zz_sxtw (self, info, code, inst); > + case 126: > return aarch64_ins_sve_addr_zz_uxtw (self, info, code, inst); > case 127: > + return aarch64_ins_sve_aimm (self, info, code, inst); > + case 128: > + return aarch64_ins_sve_asimm (self, info, code, inst); > + case 129: > + return aarch64_ins_inv_limm (self, info, code, inst); > + case 131: > + return aarch64_ins_sve_limm_mov (self, info, code, inst); > + case 133: > return aarch64_ins_sve_scale (self, info, code, inst); > case 143: > - return aarch64_ins_sve_index (self, info, code, inst); > case 144: > + return aarch64_ins_sve_shlimm (self, info, code, inst); > + case 145: > case 146: > + return aarch64_ins_sve_shrimm (self, info, code, inst); > + case 161: > + return aarch64_ins_sve_index (self, info, code, inst); > + case 162: > + case 164: > return aarch64_ins_sve_reglist (self, info, code, inst); > default: assert (0); abort (); > } > diff --git a/opcodes/aarch64-asm.c b/opcodes/aarch64-asm.c > index 944a9eb..61d0d95 100644 > --- a/opcodes/aarch64-asm.c > +++ b/opcodes/aarch64-asm.c > @@ -452,17 +452,18 @@ aarch64_ins_aimm (const aarch64_operand *self, const aarch64_opnd_info *info, > return NULL; > } > > -/* Insert logical/bitmask immediate for e.g. the last operand in > - ORR , , #. */ > -const char * > -aarch64_ins_limm (const aarch64_operand *self, const aarch64_opnd_info *info, > - aarch64_insn *code, const aarch64_inst *inst ATTRIBUTE_UNUSED) > +/* Common routine shared by aarch64_ins{,_inv}_limm. INVERT_P says whether > + the operand should be inverted before encoding. */ > +static const char * > +aarch64_ins_limm_1 (const aarch64_operand *self, > + const aarch64_opnd_info *info, aarch64_insn *code, > + const aarch64_inst *inst, bfd_boolean invert_p) > { > aarch64_insn value; > uint64_t imm = info->imm.value; > int esize = aarch64_get_qualifier_esize (inst->operands[0].qualifier); > > - if (inst->opcode->op == OP_BIC) > + if (invert_p) > imm = ~imm; > if (aarch64_logical_immediate_p (imm, esize, &value) == FALSE) > /* The constraint check should have guaranteed this wouldn't happen. */ > @@ -473,6 +474,25 @@ aarch64_ins_limm (const aarch64_operand *self, const aarch64_opnd_info *info, > return NULL; > } > > +/* Insert logical/bitmask immediate for e.g. the last operand in > + ORR , , #. */ > +const char * > +aarch64_ins_limm (const aarch64_operand *self, const aarch64_opnd_info *info, > + aarch64_insn *code, const aarch64_inst *inst) > +{ > + return aarch64_ins_limm_1 (self, info, code, inst, > + inst->opcode->op == OP_BIC); > +} > + > +/* Insert a logical/bitmask immediate for the BIC alias of AND (etc.). */ > +const char * > +aarch64_ins_inv_limm (const aarch64_operand *self, > + const aarch64_opnd_info *info, aarch64_insn *code, > + const aarch64_inst *inst) > +{ > + return aarch64_ins_limm_1 (self, info, code, inst, TRUE); > +} > + > /* Encode Ft for e.g. STR , [, {, {}}] > or LDP , , [], #. */ > const char * > @@ -903,6 +923,30 @@ aarch64_ins_sve_addr_zz_uxtw (const aarch64_operand *self, > return aarch64_ext_sve_addr_zz (self, info, code); > } > > +/* Encode an SVE ADD/SUB immediate. */ > +const char * > +aarch64_ins_sve_aimm (const aarch64_operand *self, > + const aarch64_opnd_info *info, aarch64_insn *code, > + const aarch64_inst *inst ATTRIBUTE_UNUSED) > +{ > + if (info->shifter.amount == 8) > + insert_all_fields (self, code, (info->imm.value & 0xff) | 256); > + else if (info->imm.value != 0 && (info->imm.value & 0xff) == 0) > + insert_all_fields (self, code, ((info->imm.value / 256) & 0xff) | 256); > + else > + insert_all_fields (self, code, info->imm.value & 0xff); > + return NULL; > +} > + > +/* Encode an SVE CPY/DUP immediate. */ > +const char * > +aarch64_ins_sve_asimm (const aarch64_operand *self, > + const aarch64_opnd_info *info, aarch64_insn *code, > + const aarch64_inst *inst) > +{ > + return aarch64_ins_sve_aimm (self, info, code, inst); > +} > + > /* Encode Zn[MM], where MM has a 7-bit triangular encoding. The fields > array specifies which field to use for Zn. MM is encoded in the > concatenation of imm5 and SVE_tszh, with imm5 being the less > @@ -919,6 +963,15 @@ aarch64_ins_sve_index (const aarch64_operand *self, > return NULL; > } > > +/* Encode a logical/bitmask immediate for the MOV alias of SVE DUPM. */ > +const char * > +aarch64_ins_sve_limm_mov (const aarch64_operand *self, > + const aarch64_opnd_info *info, aarch64_insn *code, > + const aarch64_inst *inst) > +{ > + return aarch64_ins_limm (self, info, code, inst); > +} > + > /* Encode {Zn. - Zm.}. The fields array specifies which field > to use for Zn. */ > const char * > @@ -943,6 +996,38 @@ aarch64_ins_sve_scale (const aarch64_operand *self, > return NULL; > } > > +/* Encode an SVE shift left immediate. */ > +const char * > +aarch64_ins_sve_shlimm (const aarch64_operand *self, > + const aarch64_opnd_info *info, aarch64_insn *code, > + const aarch64_inst *inst) > +{ > + const aarch64_opnd_info *prev_operand; > + unsigned int esize; > + > + assert (info->idx > 0); > + prev_operand = &inst->operands[info->idx - 1]; > + esize = aarch64_get_qualifier_esize (prev_operand->qualifier); > + insert_all_fields (self, code, 8 * esize + info->imm.value); > + return NULL; > +} > + > +/* Encode an SVE shift right immediate. */ > +const char * > +aarch64_ins_sve_shrimm (const aarch64_operand *self, > + const aarch64_opnd_info *info, aarch64_insn *code, > + const aarch64_inst *inst) > +{ > + const aarch64_opnd_info *prev_operand; > + unsigned int esize; > + > + assert (info->idx > 0); > + prev_operand = &inst->operands[info->idx - 1]; > + esize = aarch64_get_qualifier_esize (prev_operand->qualifier); > + insert_all_fields (self, code, 16 * esize - info->imm.value); > + return NULL; > +} > + > /* Miscellaneous encoding functions. */ > > /* Encode size[0], i.e. bit 22, for > diff --git a/opcodes/aarch64-asm.h b/opcodes/aarch64-asm.h > index 5e13de0..bbd320e 100644 > --- a/opcodes/aarch64-asm.h > +++ b/opcodes/aarch64-asm.h > @@ -54,6 +54,7 @@ AARCH64_DECL_OPD_INSERTER (ins_fpimm); > AARCH64_DECL_OPD_INSERTER (ins_fbits); > AARCH64_DECL_OPD_INSERTER (ins_aimm); > AARCH64_DECL_OPD_INSERTER (ins_limm); > +AARCH64_DECL_OPD_INSERTER (ins_inv_limm); > AARCH64_DECL_OPD_INSERTER (ins_ft); > AARCH64_DECL_OPD_INSERTER (ins_addr_simple); > AARCH64_DECL_OPD_INSERTER (ins_addr_regoff); > @@ -79,9 +80,14 @@ AARCH64_DECL_OPD_INSERTER (ins_sve_addr_zi_u5); > AARCH64_DECL_OPD_INSERTER (ins_sve_addr_zz_lsl); > AARCH64_DECL_OPD_INSERTER (ins_sve_addr_zz_sxtw); > AARCH64_DECL_OPD_INSERTER (ins_sve_addr_zz_uxtw); > +AARCH64_DECL_OPD_INSERTER (ins_sve_aimm); > +AARCH64_DECL_OPD_INSERTER (ins_sve_asimm); > AARCH64_DECL_OPD_INSERTER (ins_sve_index); > +AARCH64_DECL_OPD_INSERTER (ins_sve_limm_mov); > AARCH64_DECL_OPD_INSERTER (ins_sve_reglist); > AARCH64_DECL_OPD_INSERTER (ins_sve_scale); > +AARCH64_DECL_OPD_INSERTER (ins_sve_shlimm); > +AARCH64_DECL_OPD_INSERTER (ins_sve_shrimm); > > #undef AARCH64_DECL_OPD_INSERTER > > diff --git a/opcodes/aarch64-dis-2.c b/opcodes/aarch64-dis-2.c > index 48d6ce7..4527456 100644 > --- a/opcodes/aarch64-dis-2.c > +++ b/opcodes/aarch64-dis-2.c > @@ -10426,12 +10426,6 @@ aarch64_extract_operand (const aarch64_operand *self, > case 27: > case 35: > case 36: > - case 129: > - case 130: > - case 131: > - case 132: > - case 133: > - case 134: > case 135: > case 136: > case 137: > @@ -10440,7 +10434,13 @@ aarch64_extract_operand (const aarch64_operand *self, > case 140: > case 141: > case 142: > - case 145: > + case 155: > + case 156: > + case 157: > + case 158: > + case 159: > + case 160: > + case 163: > return aarch64_ext_regno (self, info, code, inst); > case 8: > return aarch64_ext_regrt_sysins (self, info, code, inst); > @@ -10477,13 +10477,22 @@ aarch64_extract_operand (const aarch64_operand *self, > case 56: > case 57: > case 58: > - case 66: > + case 59: > case 67: > case 68: > case 69: > case 70: > - case 126: > - case 128: > + case 71: > + case 132: > + case 134: > + case 147: > + case 148: > + case 149: > + case 150: > + case 151: > + case 152: > + case 153: > + case 154: > return aarch64_ext_imm (self, info, code, inst); > case 38: > case 39: > @@ -10496,61 +10505,61 @@ aarch64_extract_operand (const aarch64_operand *self, > return aarch64_ext_shll_imm (self, info, code, inst); > case 46: > return aarch64_ext_fpimm (self, info, code, inst); > - case 59: > - return aarch64_ext_limm (self, info, code, inst); > case 60: > - return aarch64_ext_aimm (self, info, code, inst); > + case 130: > + return aarch64_ext_limm (self, info, code, inst); > case 61: > - return aarch64_ext_imm_half (self, info, code, inst); > + return aarch64_ext_aimm (self, info, code, inst); > case 62: > + return aarch64_ext_imm_half (self, info, code, inst); > + case 63: > return aarch64_ext_fbits (self, info, code, inst); > - case 64: > case 65: > + case 66: > return aarch64_ext_cond (self, info, code, inst); > - case 71: > - case 77: > - return aarch64_ext_addr_simple (self, info, code, inst); > case 72: > - return aarch64_ext_addr_regoff (self, info, code, inst); > + case 78: > + return aarch64_ext_addr_simple (self, info, code, inst); > case 73: > + return aarch64_ext_addr_regoff (self, info, code, inst); > case 74: > case 75: > - return aarch64_ext_addr_simm (self, info, code, inst); > case 76: > + return aarch64_ext_addr_simm (self, info, code, inst); > + case 77: > return aarch64_ext_addr_uimm12 (self, info, code, inst); > - case 78: > - return aarch64_ext_simd_addr_post (self, info, code, inst); > case 79: > - return aarch64_ext_sysreg (self, info, code, inst); > + return aarch64_ext_simd_addr_post (self, info, code, inst); > case 80: > - return aarch64_ext_pstatefield (self, info, code, inst); > + return aarch64_ext_sysreg (self, info, code, inst); > case 81: > + return aarch64_ext_pstatefield (self, info, code, inst); > case 82: > case 83: > case 84: > - return aarch64_ext_sysins_op (self, info, code, inst); > case 85: > + return aarch64_ext_sysins_op (self, info, code, inst); > case 86: > - return aarch64_ext_barrier (self, info, code, inst); > case 87: > - return aarch64_ext_prfop (self, info, code, inst); > + return aarch64_ext_barrier (self, info, code, inst); > case 88: > - return aarch64_ext_hint (self, info, code, inst); > + return aarch64_ext_prfop (self, info, code, inst); > case 89: > + return aarch64_ext_hint (self, info, code, inst); > case 90: > case 91: > case 92: > - return aarch64_ext_sve_addr_ri_s4xvl (self, info, code, inst); > case 93: > - return aarch64_ext_sve_addr_ri_s6xvl (self, info, code, inst); > + return aarch64_ext_sve_addr_ri_s4xvl (self, info, code, inst); > case 94: > - return aarch64_ext_sve_addr_ri_s9xvl (self, info, code, inst); > + return aarch64_ext_sve_addr_ri_s6xvl (self, info, code, inst); > case 95: > + return aarch64_ext_sve_addr_ri_s9xvl (self, info, code, inst); > case 96: > case 97: > case 98: > - return aarch64_ext_sve_addr_ri_u6 (self, info, code, inst); > case 99: > + return aarch64_ext_sve_addr_ri_u6 (self, info, code, inst); > case 100: > case 101: > case 102: > @@ -10562,8 +10571,8 @@ aarch64_extract_operand (const aarch64_operand *self, > case 108: > case 109: > case 110: > - return aarch64_ext_sve_addr_rr_lsl (self, info, code, inst); > case 111: > + return aarch64_ext_sve_addr_rr_lsl (self, info, code, inst); > case 112: > case 113: > case 114: > @@ -10571,24 +10580,39 @@ aarch64_extract_operand (const aarch64_operand *self, > case 116: > case 117: > case 118: > - return aarch64_ext_sve_addr_rz_xtw (self, info, code, inst); > case 119: > + return aarch64_ext_sve_addr_rz_xtw (self, info, code, inst); > case 120: > case 121: > case 122: > - return aarch64_ext_sve_addr_zi_u5 (self, info, code, inst); > case 123: > - return aarch64_ext_sve_addr_zz_lsl (self, info, code, inst); > + return aarch64_ext_sve_addr_zi_u5 (self, info, code, inst); > case 124: > - return aarch64_ext_sve_addr_zz_sxtw (self, info, code, inst); > + return aarch64_ext_sve_addr_zz_lsl (self, info, code, inst); > case 125: > + return aarch64_ext_sve_addr_zz_sxtw (self, info, code, inst); > + case 126: > return aarch64_ext_sve_addr_zz_uxtw (self, info, code, inst); > case 127: > + return aarch64_ext_sve_aimm (self, info, code, inst); > + case 128: > + return aarch64_ext_sve_asimm (self, info, code, inst); > + case 129: > + return aarch64_ext_inv_limm (self, info, code, inst); > + case 131: > + return aarch64_ext_sve_limm_mov (self, info, code, inst); > + case 133: > return aarch64_ext_sve_scale (self, info, code, inst); > case 143: > - return aarch64_ext_sve_index (self, info, code, inst); > case 144: > + return aarch64_ext_sve_shlimm (self, info, code, inst); > + case 145: > case 146: > + return aarch64_ext_sve_shrimm (self, info, code, inst); > + case 161: > + return aarch64_ext_sve_index (self, info, code, inst); > + case 162: > + case 164: > return aarch64_ext_sve_reglist (self, info, code, inst); > default: assert (0); abort (); > } > diff --git a/opcodes/aarch64-dis.c b/opcodes/aarch64-dis.c > index ba6befd..ed050cd 100644 > --- a/opcodes/aarch64-dis.c > +++ b/opcodes/aarch64-dis.c > @@ -734,32 +734,21 @@ aarch64_ext_aimm (const aarch64_operand *self ATTRIBUTE_UNUSED, > return 1; > } > > -/* Decode logical immediate for e.g. ORR , , #. */ > - > -int > -aarch64_ext_limm (const aarch64_operand *self ATTRIBUTE_UNUSED, > - aarch64_opnd_info *info, const aarch64_insn code, > - const aarch64_inst *inst ATTRIBUTE_UNUSED) > +/* Return true if VALUE is a valid logical immediate encoding, storing the > + decoded value in *RESULT if so. ESIZE is the number of bytes in the > + decoded immediate. */ > +static int > +decode_limm (uint32_t esize, aarch64_insn value, int64_t *result) > { > uint64_t imm, mask; > - uint32_t sf; > uint32_t N, R, S; > unsigned simd_size; > - aarch64_insn value; > - > - value = extract_fields (code, 0, 3, FLD_N, FLD_immr, FLD_imms); > - assert (inst->operands[0].qualifier == AARCH64_OPND_QLF_W > - || inst->operands[0].qualifier == AARCH64_OPND_QLF_X); > - sf = aarch64_get_qualifier_esize (inst->operands[0].qualifier) != 4; > > /* value is N:immr:imms. */ > S = value & 0x3f; > R = (value >> 6) & 0x3f; > N = (value >> 12) & 0x1; > > - if (sf == 0 && N == 1) > - return 0; > - > /* The immediate value is S+1 bits to 1, left rotated by SIMDsize - R > (in other words, right rotated by R), then replicated. */ > if (N != 0) > @@ -782,6 +771,10 @@ aarch64_ext_limm (const aarch64_operand *self ATTRIBUTE_UNUSED, > /* Top bits are IGNORED. */ > R &= simd_size - 1; > } > + > + if (simd_size > esize * 8) > + return 0; > + > /* NOTE: if S = simd_size - 1 we get 0xf..f which is rejected. */ > if (S == simd_size - 1) > return 0; > @@ -803,8 +796,35 @@ aarch64_ext_limm (const aarch64_operand *self ATTRIBUTE_UNUSED, > default: assert (0); return 0; > } > > - info->imm.value = sf ? imm : imm & 0xffffffff; > + *result = imm & ~((uint64_t) -1 << (esize * 4) << (esize * 4)); > + > + return 1; > +} > + > +/* Decode a logical immediate for e.g. ORR , , #. */ > +int > +aarch64_ext_limm (const aarch64_operand *self, > + aarch64_opnd_info *info, const aarch64_insn code, > + const aarch64_inst *inst) > +{ > + uint32_t esize; > + aarch64_insn value; > + > + value = extract_fields (code, 0, 3, self->fields[0], self->fields[1], > + self->fields[2]); > + esize = aarch64_get_qualifier_esize (inst->operands[0].qualifier); > + return decode_limm (esize, value, &info->imm.value); > +} > > +/* Decode a logical immediate for the BIC alias of AND (etc.). */ > +int > +aarch64_ext_inv_limm (const aarch64_operand *self, > + aarch64_opnd_info *info, const aarch64_insn code, > + const aarch64_inst *inst) > +{ > + if (!aarch64_ext_limm (self, info, code, inst)) > + return 0; > + info->imm.value = ~info->imm.value; > return 1; > } > > @@ -1404,6 +1424,47 @@ aarch64_ext_sve_addr_zz_uxtw (const aarch64_operand *self, > return aarch64_ext_sve_addr_zz (self, info, code, AARCH64_MOD_UXTW); > } > > +/* Finish decoding an SVE arithmetic immediate, given that INFO already > + has the raw field value and that the low 8 bits decode to VALUE. */ > +static int > +decode_sve_aimm (aarch64_opnd_info *info, int64_t value) > +{ > + info->shifter.kind = AARCH64_MOD_LSL; > + info->shifter.amount = 0; > + if (info->imm.value & 0x100) > + { > + if (value == 0) > + /* Decode 0x100 as #0, LSL #8. */ > + info->shifter.amount = 8; > + else > + value *= 256; > + } > + info->shifter.operator_present = (info->shifter.amount != 0); > + info->shifter.amount_present = (info->shifter.amount != 0); > + info->imm.value = value; > + return 1; > +} > + > +/* Decode an SVE ADD/SUB immediate. */ > +int > +aarch64_ext_sve_aimm (const aarch64_operand *self, > + aarch64_opnd_info *info, const aarch64_insn code, > + const aarch64_inst *inst) > +{ > + return (aarch64_ext_imm (self, info, code, inst) > + && decode_sve_aimm (info, (uint8_t) info->imm.value)); > +} > + > +/* Decode an SVE CPY/DUP immediate. */ > +int > +aarch64_ext_sve_asimm (const aarch64_operand *self, > + aarch64_opnd_info *info, const aarch64_insn code, > + const aarch64_inst *inst) > +{ > + return (aarch64_ext_imm (self, info, code, inst) > + && decode_sve_aimm (info, (int8_t) info->imm.value)); > +} > + > /* Decode Zn[MM], where MM has a 7-bit triangular encoding. The fields > array specifies which field to use for Zn. MM is encoded in the > concatenation of imm5 and SVE_tszh, with imm5 being the less > @@ -1425,6 +1486,17 @@ aarch64_ext_sve_index (const aarch64_operand *self, > return 1; > } > > +/* Decode a logical immediate for the MOV alias of SVE DUPM. */ > +int > +aarch64_ext_sve_limm_mov (const aarch64_operand *self, > + aarch64_opnd_info *info, const aarch64_insn code, > + const aarch64_inst *inst) > +{ > + int esize = aarch64_get_qualifier_esize (inst->operands[0].qualifier); > + return (aarch64_ext_limm (self, info, code, inst) > + && aarch64_sve_dupm_mov_immediate_p (info->imm.value, esize)); > +} > + > /* Decode {Zn. - Zm.}. The fields array specifies which field > to use for Zn. The opcode-dependent value specifies the number > of registers in the list. */ > @@ -1457,6 +1529,44 @@ aarch64_ext_sve_scale (const aarch64_operand *self, > info->shifter.amount_present = (val != 0); > return 1; > } > + > +/* Return the top set bit in VALUE, which is expected to be relatively > + small. */ > +static uint64_t > +get_top_bit (uint64_t value) > +{ > + while ((value & -value) != value) > + value -= value & -value; > + return value; > +} > + > +/* Decode an SVE shift-left immediate. */ > +int > +aarch64_ext_sve_shlimm (const aarch64_operand *self, > + aarch64_opnd_info *info, const aarch64_insn code, > + const aarch64_inst *inst) > +{ > + if (!aarch64_ext_imm (self, info, code, inst) > + || info->imm.value == 0) > + return 0; > + > + info->imm.value -= get_top_bit (info->imm.value); > + return 1; > +} > + > +/* Decode an SVE shift-right immediate. */ > +int > +aarch64_ext_sve_shrimm (const aarch64_operand *self, > + aarch64_opnd_info *info, const aarch64_insn code, > + const aarch64_inst *inst) > +{ > + if (!aarch64_ext_imm (self, info, code, inst) > + || info->imm.value == 0) > + return 0; > + > + info->imm.value = get_top_bit (info->imm.value) * 2 - info->imm.value; > + return 1; > +} > > /* Bitfields that are commonly used to encode certain operands' information > may be partially used as part of the base opcode in some instructions. > diff --git a/opcodes/aarch64-dis.h b/opcodes/aarch64-dis.h > index 5619877..10983d1 100644 > --- a/opcodes/aarch64-dis.h > +++ b/opcodes/aarch64-dis.h > @@ -76,6 +76,7 @@ AARCH64_DECL_OPD_EXTRACTOR (ext_fpimm); > AARCH64_DECL_OPD_EXTRACTOR (ext_fbits); > AARCH64_DECL_OPD_EXTRACTOR (ext_aimm); > AARCH64_DECL_OPD_EXTRACTOR (ext_limm); > +AARCH64_DECL_OPD_EXTRACTOR (ext_inv_limm); > AARCH64_DECL_OPD_EXTRACTOR (ext_ft); > AARCH64_DECL_OPD_EXTRACTOR (ext_addr_simple); > AARCH64_DECL_OPD_EXTRACTOR (ext_addr_regoff); > @@ -101,9 +102,14 @@ AARCH64_DECL_OPD_EXTRACTOR (ext_sve_addr_zi_u5); > AARCH64_DECL_OPD_EXTRACTOR (ext_sve_addr_zz_lsl); > AARCH64_DECL_OPD_EXTRACTOR (ext_sve_addr_zz_sxtw); > AARCH64_DECL_OPD_EXTRACTOR (ext_sve_addr_zz_uxtw); > +AARCH64_DECL_OPD_EXTRACTOR (ext_sve_aimm); > +AARCH64_DECL_OPD_EXTRACTOR (ext_sve_asimm); > AARCH64_DECL_OPD_EXTRACTOR (ext_sve_index); > +AARCH64_DECL_OPD_EXTRACTOR (ext_sve_limm_mov); > AARCH64_DECL_OPD_EXTRACTOR (ext_sve_reglist); > AARCH64_DECL_OPD_EXTRACTOR (ext_sve_scale); > +AARCH64_DECL_OPD_EXTRACTOR (ext_sve_shlimm); > +AARCH64_DECL_OPD_EXTRACTOR (ext_sve_shrimm); > > #undef AARCH64_DECL_OPD_EXTRACTOR > > diff --git a/opcodes/aarch64-opc-2.c b/opcodes/aarch64-opc-2.c > index a72f577..d86e7dc 100644 > --- a/opcodes/aarch64-opc-2.c > +++ b/opcodes/aarch64-opc-2.c > @@ -82,6 +82,7 @@ const struct aarch64_operand aarch64_operands[] = > {AARCH64_OPND_CLASS_IMMEDIATE, "BIT_NUM", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_b5, FLD_b40}, "the bit number to be tested"}, > {AARCH64_OPND_CLASS_IMMEDIATE, "EXCEPTION", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_imm16}, "a 16-bit unsigned immediate"}, > {AARCH64_OPND_CLASS_IMMEDIATE, "CCMP_IMM", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_imm5}, "a 5-bit unsigned immediate"}, > + {AARCH64_OPND_CLASS_IMMEDIATE, "SIMM5", OPD_F_SEXT | OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_imm5}, "a 5-bit signed immediate"}, > {AARCH64_OPND_CLASS_IMMEDIATE, "NZCV", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_nzcv}, "a flag bit specifier giving an alternative value for each flag"}, > {AARCH64_OPND_CLASS_IMMEDIATE, "LIMM", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_N,FLD_immr,FLD_imms}, "Logical immediate"}, > {AARCH64_OPND_CLASS_IMMEDIATE, "AIMM", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_shift,FLD_imm12}, "a 12-bit unsigned immediate with optional left shift of 12 bits"}, > @@ -150,6 +151,11 @@ const struct aarch64_operand aarch64_operands[] = > {AARCH64_OPND_CLASS_ADDRESS, "SVE_ADDR_ZZ_LSL", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_SVE_Zn,FLD_SVE_Zm_16}, "an address with a vector register offset"}, > {AARCH64_OPND_CLASS_ADDRESS, "SVE_ADDR_ZZ_SXTW", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_SVE_Zn,FLD_SVE_Zm_16}, "an address with a vector register offset"}, > {AARCH64_OPND_CLASS_ADDRESS, "SVE_ADDR_ZZ_UXTW", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_SVE_Zn,FLD_SVE_Zm_16}, "an address with a vector register offset"}, > + {AARCH64_OPND_CLASS_IMMEDIATE, "SVE_AIMM", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_SVE_imm9}, "a 9-bit unsigned arithmetic operand"}, > + {AARCH64_OPND_CLASS_IMMEDIATE, "SVE_ASIMM", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_SVE_imm9}, "a 9-bit signed arithmetic operand"}, > + {AARCH64_OPND_CLASS_IMMEDIATE, "SVE_INV_LIMM", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_SVE_N,FLD_SVE_immr,FLD_SVE_imms}, "an inverted 13-bit logical immediate"}, > + {AARCH64_OPND_CLASS_IMMEDIATE, "SVE_LIMM", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_SVE_N,FLD_SVE_immr,FLD_SVE_imms}, "a 13-bit logical immediate"}, > + {AARCH64_OPND_CLASS_IMMEDIATE, "SVE_LIMM_MOV", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_SVE_N,FLD_SVE_immr,FLD_SVE_imms}, "a 13-bit logical move immediate"}, > {AARCH64_OPND_CLASS_IMMEDIATE, "SVE_PATTERN", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_SVE_pattern}, "an enumeration value such as POW2"}, > {AARCH64_OPND_CLASS_IMMEDIATE, "SVE_PATTERN_SCALED", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_SVE_pattern}, "an enumeration value such as POW2"}, > {AARCH64_OPND_CLASS_IMMEDIATE, "SVE_PRFOP", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_SVE_prfop}, "an enumeration value such as PLDL1KEEP"}, > @@ -161,6 +167,18 @@ const struct aarch64_operand aarch64_operands[] = > {AARCH64_OPND_CLASS_PRED_REG, "SVE_Pm", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_SVE_Pm}, "an SVE predicate register"}, > {AARCH64_OPND_CLASS_PRED_REG, "SVE_Pn", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_SVE_Pn}, "an SVE predicate register"}, > {AARCH64_OPND_CLASS_PRED_REG, "SVE_Pt", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_SVE_Pt}, "an SVE predicate register"}, > + {AARCH64_OPND_CLASS_IMMEDIATE, "SVE_SHLIMM_PRED", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_SVE_tszh,FLD_SVE_imm5}, "a shift-left immediate operand"}, > + {AARCH64_OPND_CLASS_IMMEDIATE, "SVE_SHLIMM_UNPRED", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_SVE_tszh,FLD_imm5}, "a shift-left immediate operand"}, > + {AARCH64_OPND_CLASS_IMMEDIATE, "SVE_SHRIMM_PRED", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_SVE_tszh,FLD_SVE_imm5}, "a shift-right immediate operand"}, > + {AARCH64_OPND_CLASS_IMMEDIATE, "SVE_SHRIMM_UNPRED", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_SVE_tszh,FLD_imm5}, "a shift-right immediate operand"}, > + {AARCH64_OPND_CLASS_IMMEDIATE, "SVE_SIMM5", OPD_F_SEXT | OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_SVE_imm5}, "a 5-bit signed immediate"}, > + {AARCH64_OPND_CLASS_IMMEDIATE, "SVE_SIMM5B", OPD_F_SEXT | OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_SVE_imm5b}, "a 5-bit signed immediate"}, > + {AARCH64_OPND_CLASS_IMMEDIATE, "SVE_SIMM6", OPD_F_SEXT | OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_SVE_imms}, "a 6-bit signed immediate"}, > + {AARCH64_OPND_CLASS_IMMEDIATE, "SVE_SIMM8", OPD_F_SEXT | OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_SVE_imm8}, "an 8-bit signed immediate"}, > + {AARCH64_OPND_CLASS_IMMEDIATE, "SVE_UIMM3", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_SVE_imm3}, "a 3-bit unsigned immediate"}, > + {AARCH64_OPND_CLASS_IMMEDIATE, "SVE_UIMM7", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_SVE_imm7}, "a 7-bit unsigned immediate"}, > + {AARCH64_OPND_CLASS_IMMEDIATE, "SVE_UIMM8", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_SVE_imm8}, "an 8-bit unsigned immediate"}, > + {AARCH64_OPND_CLASS_IMMEDIATE, "SVE_UIMM8_53", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_imm5,FLD_imm3}, "an 8-bit unsigned immediate"}, > {AARCH64_OPND_CLASS_SVE_REG, "SVE_Za_5", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_SVE_Za_5}, "an SVE vector register"}, > {AARCH64_OPND_CLASS_SVE_REG, "SVE_Za_16", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_SVE_Za_16}, "an SVE vector register"}, > {AARCH64_OPND_CLASS_SVE_REG, "SVE_Zd", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_SVE_Zd}, "an SVE vector register"}, > diff --git a/opcodes/aarch64-opc.c b/opcodes/aarch64-opc.c > index d0959b5..dec7e06 100644 > --- a/opcodes/aarch64-opc.c > +++ b/opcodes/aarch64-opc.c > @@ -264,6 +264,7 @@ 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. */ > + { 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]. */ > { 5, 4 }, /* SVE_Pg4_5: p0-p15, bits [8,5]. */ > @@ -279,8 +280,16 @@ const aarch64_field fields[] = > { 16, 5 }, /* SVE_Zm_16: SVE vector register, bits [20,16]. */ > { 5, 5 }, /* SVE_Zn: SVE vector register, bits [9,5]. */ > { 0, 5 }, /* SVE_Zt: SVE vector register, bits [4,0]. */ > + { 16, 3 }, /* SVE_imm3: 3-bit immediate field. */ > { 16, 4 }, /* SVE_imm4: 4-bit immediate field. */ > + { 5, 5 }, /* SVE_imm5: 5-bit immediate field. */ > + { 16, 5 }, /* SVE_imm5b: secondary 5-bit immediate field. */ > { 16, 6 }, /* SVE_imm6: 6-bit immediate field. */ > + { 14, 7 }, /* SVE_imm7: 7-bit immediate field. */ > + { 5, 8 }, /* SVE_imm8: 8-bit immediate field. */ > + { 5, 9 }, /* SVE_imm9: 9-bit immediate field. */ > + { 11, 6 }, /* SVE_immr: SVE equivalent of immr. */ > + { 5, 6 }, /* SVE_imms: SVE equivalent of imms. */ > { 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]. */ > @@ -1374,9 +1383,10 @@ operand_general_constraint_met_p (const aarch64_opnd_info *opnds, int idx, > const aarch64_opcode *opcode, > aarch64_operand_error *mismatch_detail) > { > - unsigned num, modifiers; > + unsigned num, modifiers, shift; > unsigned char size; > int64_t imm, min_value, max_value; > + uint64_t uvalue, mask; > const aarch64_opnd_info *opnd = opnds + idx; > aarch64_opnd_qualifier_t qualifier = opnd->qualifier; > > @@ -1977,6 +1987,10 @@ operand_general_constraint_met_p (const aarch64_opnd_info *opnds, int idx, > case AARCH64_OPND_UIMM7: > case AARCH64_OPND_UIMM3_OP1: > case AARCH64_OPND_UIMM3_OP2: > + case AARCH64_OPND_SVE_UIMM3: > + case AARCH64_OPND_SVE_UIMM7: > + case AARCH64_OPND_SVE_UIMM8: > + case AARCH64_OPND_SVE_UIMM8_53: > size = get_operand_fields_width (get_operand_from_code (type)); > assert (size < 32); > if (!value_fit_unsigned_field_p (opnd->imm.value, size)) > @@ -1987,6 +2001,22 @@ operand_general_constraint_met_p (const aarch64_opnd_info *opnds, int idx, > } > break; > > + case AARCH64_OPND_SIMM5: > + case AARCH64_OPND_SVE_SIMM5: > + case AARCH64_OPND_SVE_SIMM5B: > + case AARCH64_OPND_SVE_SIMM6: > + case AARCH64_OPND_SVE_SIMM8: > + size = get_operand_fields_width (get_operand_from_code (type)); > + assert (size < 32); > + if (!value_fit_signed_field_p (opnd->imm.value, size)) > + { > + set_imm_out_of_range_error (mismatch_detail, idx, > + -(1 << (size - 1)), > + (1 << (size - 1)) - 1); > + return 0; > + } > + break; > + > case AARCH64_OPND_WIDTH: > assert (idx > 1 && opnds[idx-1].type == AARCH64_OPND_IMM > && opnds[0].type == AARCH64_OPND_Rd); > @@ -2001,6 +2031,7 @@ operand_general_constraint_met_p (const aarch64_opnd_info *opnds, int idx, > break; > > case AARCH64_OPND_LIMM: > + case AARCH64_OPND_SVE_LIMM: > { > int esize = aarch64_get_qualifier_esize (opnds[0].qualifier); > uint64_t uimm = opnd->imm.value; > @@ -2171,6 +2202,90 @@ operand_general_constraint_met_p (const aarch64_opnd_info *opnds, int idx, > } > break; > > + case AARCH64_OPND_SVE_AIMM: > + min_value = 0; > + sve_aimm: > + assert (opnd->shifter.kind == AARCH64_MOD_LSL); > + size = aarch64_get_qualifier_esize (opnds[0].qualifier); > + mask = ~((uint64_t) -1 << (size * 4) << (size * 4)); > + uvalue = opnd->imm.value; > + shift = opnd->shifter.amount; > + if (size == 1) > + { > + if (shift != 0) > + { > + set_other_error (mismatch_detail, idx, > + _("no shift amount allowed for" > + " 8-bit constants")); > + return 0; > + } > + } > + else > + { > + if (shift != 0 && shift != 8) > + { > + set_other_error (mismatch_detail, idx, > + _("shift amount should be 0 or 8")); > + return 0; > + } > + if (shift == 0 && (uvalue & 0xff) == 0) > + { > + shift = 8; > + uvalue = (int64_t) uvalue / 256; > + } > + } > + mask >>= shift; > + if ((uvalue & mask) != uvalue && (uvalue | ~mask) != uvalue) > + { > + set_other_error (mismatch_detail, idx, > + _("immediate too big for element size")); > + return 0; > + } > + uvalue = (uvalue - min_value) & mask; > + if (uvalue > 0xff) > + { > + set_other_error (mismatch_detail, idx, > + _("invalid arithmetic immediate")); > + return 0; > + } > + break; > + > + case AARCH64_OPND_SVE_ASIMM: > + min_value = -128; > + goto sve_aimm; > + > + case AARCH64_OPND_SVE_INV_LIMM: > + { > + int esize = aarch64_get_qualifier_esize (opnds[0].qualifier); > + uint64_t uimm = ~opnd->imm.value; > + if (!aarch64_logical_immediate_p (uimm, esize, NULL)) > + { > + set_other_error (mismatch_detail, idx, > + _("immediate out of range")); > + return 0; > + } > + } > + break; > + > + case AARCH64_OPND_SVE_LIMM_MOV: > + { > + int esize = aarch64_get_qualifier_esize (opnds[0].qualifier); > + uint64_t uimm = opnd->imm.value; > + if (!aarch64_logical_immediate_p (uimm, esize, NULL)) > + { > + set_other_error (mismatch_detail, idx, > + _("immediate out of range")); > + return 0; > + } > + if (!aarch64_sve_dupm_mov_immediate_p (uimm, esize)) > + { > + set_other_error (mismatch_detail, idx, > + _("invalid replicated MOV immediate")); > + return 0; > + } > + } > + break; > + > case AARCH64_OPND_SVE_PATTERN_SCALED: > assert (opnd->shifter.kind == AARCH64_MOD_MUL); > if (!value_in_range_p (opnd->shifter.amount, 1, 16)) > @@ -2180,6 +2295,27 @@ operand_general_constraint_met_p (const aarch64_opnd_info *opnds, int idx, > } > break; > > + case AARCH64_OPND_SVE_SHLIMM_PRED: > + case AARCH64_OPND_SVE_SHLIMM_UNPRED: > + size = aarch64_get_qualifier_esize (opnds[idx - 1].qualifier); > + if (!value_in_range_p (opnd->imm.value, 0, 8 * size - 1)) > + { > + set_imm_out_of_range_error (mismatch_detail, idx, > + 0, 8 * size - 1); > + return 0; > + } > + break; > + > + case AARCH64_OPND_SVE_SHRIMM_PRED: > + case AARCH64_OPND_SVE_SHRIMM_UNPRED: > + size = aarch64_get_qualifier_esize (opnds[idx - 1].qualifier); > + if (!value_in_range_p (opnd->imm.value, 1, 8 * size)) > + { > + set_imm_out_of_range_error (mismatch_detail, idx, 1, 8 * size); > + return 0; > + } > + break; > + > default: > break; > } > @@ -2953,6 +3089,19 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc, > case AARCH64_OPND_IMMR: > case AARCH64_OPND_IMMS: > case AARCH64_OPND_FBITS: > + case AARCH64_OPND_SIMM5: > + case AARCH64_OPND_SVE_SHLIMM_PRED: > + case AARCH64_OPND_SVE_SHLIMM_UNPRED: > + case AARCH64_OPND_SVE_SHRIMM_PRED: > + case AARCH64_OPND_SVE_SHRIMM_UNPRED: > + case AARCH64_OPND_SVE_SIMM5: > + case AARCH64_OPND_SVE_SIMM5B: > + case AARCH64_OPND_SVE_SIMM6: > + case AARCH64_OPND_SVE_SIMM8: > + case AARCH64_OPND_SVE_UIMM3: > + case AARCH64_OPND_SVE_UIMM7: > + case AARCH64_OPND_SVE_UIMM8: > + case AARCH64_OPND_SVE_UIMM8_53: > snprintf (buf, size, "#%" PRIi64, opnd->imm.value); > break; > > @@ -3021,6 +3170,9 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc, > case AARCH64_OPND_LIMM: > case AARCH64_OPND_AIMM: > case AARCH64_OPND_HALF: > + case AARCH64_OPND_SVE_INV_LIMM: > + case AARCH64_OPND_SVE_LIMM: > + case AARCH64_OPND_SVE_LIMM_MOV: > if (opnd->shifter.amount) > snprintf (buf, size, "#0x%" PRIx64 ", lsl #%" PRIi64, opnd->imm.value, > opnd->shifter.amount); > @@ -3039,6 +3191,15 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc, > opnd->shifter.amount); > break; > > + case AARCH64_OPND_SVE_AIMM: > + case AARCH64_OPND_SVE_ASIMM: > + if (opnd->shifter.amount) > + snprintf (buf, size, "#%" PRIi64 ", lsl #%" PRIi64, opnd->imm.value, > + opnd->shifter.amount); > + else > + snprintf (buf, size, "#%" PRIi64, opnd->imm.value); > + break; > + > case AARCH64_OPND_FPIMM: > case AARCH64_OPND_SIMD_FPIMM: > switch (aarch64_get_qualifier_esize (opnds[0].qualifier)) > @@ -3967,6 +4128,33 @@ verify_ldpsw (const struct aarch64_opcode * opcode ATTRIBUTE_UNUSED, > return TRUE; > } > > +/* Return true if VALUE cannot be moved into an SVE register using DUP > + (with any element size, not just ESIZE) and if using DUPM would > + therefore be OK. ESIZE is the number of bytes in the immediate. */ > + > +bfd_boolean > +aarch64_sve_dupm_mov_immediate_p (uint64_t uvalue, int esize) > +{ > + int64_t svalue = uvalue; > + uint64_t upper = (uint64_t) -1 << (esize * 4) << (esize * 4); > + > + if ((uvalue & ~upper) != uvalue && (uvalue | upper) != uvalue) > + return FALSE; > + if (esize <= 4 || (uint32_t) uvalue == (uint32_t) (uvalue >> 32)) > + { > + svalue = (int32_t) uvalue; > + if (esize <= 2 || (uint16_t) uvalue == (uint16_t) (uvalue >> 16)) > + { > + svalue = (int16_t) uvalue; > + if (esize == 1 || (uint8_t) uvalue == (uint8_t) (uvalue >> 8)) > + return FALSE; > + } > + } > + if ((svalue & 0xff) == 0) > + svalue /= 256; > + return svalue < -128 || svalue >= 128; > +} > + > /* Include the opcode description table as well as the operand description > table. */ > #define VERIFIER(x) verify_##x > diff --git a/opcodes/aarch64-opc.h b/opcodes/aarch64-opc.h > index e823146..087376e 100644 > --- a/opcodes/aarch64-opc.h > +++ b/opcodes/aarch64-opc.h > @@ -91,6 +91,7 @@ enum aarch64_field_kind > FLD_b5, > FLD_b40, > FLD_scale, > + FLD_SVE_N, > FLD_SVE_Pd, > FLD_SVE_Pg3, > FLD_SVE_Pg4_5, > @@ -106,8 +107,16 @@ enum aarch64_field_kind > FLD_SVE_Zm_16, > FLD_SVE_Zn, > FLD_SVE_Zt, > + FLD_SVE_imm3, > FLD_SVE_imm4, > + FLD_SVE_imm5, > + FLD_SVE_imm5b, > FLD_SVE_imm6, > + FLD_SVE_imm7, > + FLD_SVE_imm8, > + FLD_SVE_imm9, > + FLD_SVE_immr, > + FLD_SVE_imms, > FLD_SVE_msz, > FLD_SVE_pattern, > FLD_SVE_prfop, > diff --git a/opcodes/aarch64-tbl.h b/opcodes/aarch64-tbl.h > index ac7ccf0..d743e3b 100644 > --- a/opcodes/aarch64-tbl.h > +++ b/opcodes/aarch64-tbl.h > @@ -2761,6 +2761,8 @@ struct aarch64_opcode aarch64_opcode_table[] = > "a 16-bit unsigned immediate") \ > Y(IMMEDIATE, imm, "CCMP_IMM", 0, F(FLD_imm5), \ > "a 5-bit unsigned immediate") \ > + Y(IMMEDIATE, imm, "SIMM5", OPD_F_SEXT, F(FLD_imm5), \ > + "a 5-bit signed immediate") \ > Y(IMMEDIATE, imm, "NZCV", 0, F(FLD_nzcv), \ > "a flag bit specifier giving an alternative value for each flag") \ > Y(IMMEDIATE, limm, "LIMM", 0, F(FLD_N,FLD_immr,FLD_imms), \ > @@ -2925,6 +2927,19 @@ struct aarch64_opcode aarch64_opcode_table[] = > Y(ADDRESS, sve_addr_zz_uxtw, "SVE_ADDR_ZZ_UXTW", 0, \ > F(FLD_SVE_Zn,FLD_SVE_Zm_16), \ > "an address with a vector register offset") \ > + Y(IMMEDIATE, sve_aimm, "SVE_AIMM", 0, F(FLD_SVE_imm9), \ > + "a 9-bit unsigned arithmetic operand") \ > + Y(IMMEDIATE, sve_asimm, "SVE_ASIMM", 0, F(FLD_SVE_imm9), \ > + "a 9-bit signed arithmetic operand") \ > + Y(IMMEDIATE, inv_limm, "SVE_INV_LIMM", 0, \ > + F(FLD_SVE_N,FLD_SVE_immr,FLD_SVE_imms), \ > + "an inverted 13-bit logical immediate") \ > + Y(IMMEDIATE, limm, "SVE_LIMM", 0, \ > + F(FLD_SVE_N,FLD_SVE_immr,FLD_SVE_imms), \ > + "a 13-bit logical immediate") \ > + Y(IMMEDIATE, sve_limm_mov, "SVE_LIMM_MOV", 0, \ > + F(FLD_SVE_N,FLD_SVE_immr,FLD_SVE_imms), \ > + "a 13-bit logical move immediate") \ > Y(IMMEDIATE, imm, "SVE_PATTERN", 0, F(FLD_SVE_pattern), \ > "an enumeration value such as POW2") \ > Y(IMMEDIATE, sve_scale, "SVE_PATTERN_SCALED", 0, \ > @@ -2947,6 +2962,30 @@ struct aarch64_opcode aarch64_opcode_table[] = > "an SVE predicate register") \ > Y(PRED_REG, regno, "SVE_Pt", 0, F(FLD_SVE_Pt), \ > "an SVE predicate register") \ > + Y(IMMEDIATE, sve_shlimm, "SVE_SHLIMM_PRED", 0, \ > + F(FLD_SVE_tszh,FLD_SVE_imm5), "a shift-left immediate operand") \ > + Y(IMMEDIATE, sve_shlimm, "SVE_SHLIMM_UNPRED", 0, \ > + F(FLD_SVE_tszh,FLD_imm5), "a shift-left immediate operand") \ > + Y(IMMEDIATE, sve_shrimm, "SVE_SHRIMM_PRED", 0, \ > + F(FLD_SVE_tszh,FLD_SVE_imm5), "a shift-right immediate operand") \ > + Y(IMMEDIATE, sve_shrimm, "SVE_SHRIMM_UNPRED", 0, \ > + F(FLD_SVE_tszh,FLD_imm5), "a shift-right immediate operand") \ > + Y(IMMEDIATE, imm, "SVE_SIMM5", OPD_F_SEXT, F(FLD_SVE_imm5), \ > + "a 5-bit signed immediate") \ > + Y(IMMEDIATE, imm, "SVE_SIMM5B", OPD_F_SEXT, F(FLD_SVE_imm5b), \ > + "a 5-bit signed immediate") \ > + Y(IMMEDIATE, imm, "SVE_SIMM6", OPD_F_SEXT, F(FLD_SVE_imms), \ > + "a 6-bit signed immediate") \ > + Y(IMMEDIATE, imm, "SVE_SIMM8", OPD_F_SEXT, F(FLD_SVE_imm8), \ > + "an 8-bit signed immediate") \ > + Y(IMMEDIATE, imm, "SVE_UIMM3", 0, F(FLD_SVE_imm3), \ > + "a 3-bit unsigned immediate") \ > + Y(IMMEDIATE, imm, "SVE_UIMM7", 0, F(FLD_SVE_imm7), \ > + "a 7-bit unsigned immediate") \ > + Y(IMMEDIATE, imm, "SVE_UIMM8", 0, F(FLD_SVE_imm8), \ > + "an 8-bit unsigned immediate") \ > + Y(IMMEDIATE, imm, "SVE_UIMM8_53", 0, F(FLD_imm5,FLD_imm3), \ > + "an 8-bit unsigned immediate") \ > Y(SVE_REG, regno, "SVE_Za_5", 0, F(FLD_SVE_Za_5), \ > "an SVE vector register") \ > Y(SVE_REG, regno, "SVE_Za_16", 0, F(FLD_SVE_Za_16), \ >