+ return true;
+}
+
+/* Encode an SVE address [<base>, #<simm4>*<factor>, MUL VL],
+ where <simm4> is a 4-bit signed value and where <factor> is 1 plus
+ SELF's operand-dependent value. fields[0] specifies the field that
+ holds <base>. <simm4> is encoded in the SVE_imm4 field. */
+bool
+aarch64_ins_sve_addr_ri_s4xvl (const aarch64_operand *self,
+ const aarch64_opnd_info *info,
+ aarch64_insn *code,
+ const aarch64_inst *inst ATTRIBUTE_UNUSED,
+ aarch64_operand_error *errors ATTRIBUTE_UNUSED)
+{
+ int factor = 1 + get_operand_specific_data (self);
+ insert_field (self->fields[0], code, info->addr.base_regno, 0);
+ insert_field (FLD_SVE_imm4, code, info->addr.offset.imm / factor, 0);
+ return true;
+}
+
+/* Encode an SVE address [<base>, #<simm6>*<factor>, MUL VL],
+ where <simm6> is a 6-bit signed value and where <factor> is 1 plus
+ SELF's operand-dependent value. fields[0] specifies the field that
+ holds <base>. <simm6> is encoded in the SVE_imm6 field. */
+bool
+aarch64_ins_sve_addr_ri_s6xvl (const aarch64_operand *self,
+ const aarch64_opnd_info *info,
+ aarch64_insn *code,
+ const aarch64_inst *inst ATTRIBUTE_UNUSED,
+ aarch64_operand_error *errors ATTRIBUTE_UNUSED)
+{
+ int factor = 1 + get_operand_specific_data (self);
+ insert_field (self->fields[0], code, info->addr.base_regno, 0);
+ insert_field (FLD_SVE_imm6, code, info->addr.offset.imm / factor, 0);
+ return true;
+}
+
+/* Encode an SVE address [<base>, #<simm9>*<factor>, MUL VL],
+ where <simm9> is a 9-bit signed value and where <factor> is 1 plus
+ SELF's operand-dependent value. fields[0] specifies the field that
+ holds <base>. <simm9> is encoded in the concatenation of the SVE_imm6
+ and imm3 fields, with imm3 being the less-significant part. */
+bool
+aarch64_ins_sve_addr_ri_s9xvl (const aarch64_operand *self,
+ const aarch64_opnd_info *info,
+ aarch64_insn *code,
+ const aarch64_inst *inst ATTRIBUTE_UNUSED,
+ aarch64_operand_error *errors ATTRIBUTE_UNUSED)
+{
+ int factor = 1 + get_operand_specific_data (self);
+ insert_field (self->fields[0], code, info->addr.base_regno, 0);
+ insert_fields (code, info->addr.offset.imm / factor, 0,
+ 2, FLD_imm3, FLD_SVE_imm6);
+ return true;
+}
+
+/* Encode an SVE address [X<n>, #<SVE_imm4> << <shift>], where <SVE_imm4>
+ is a 4-bit signed number and where <shift> is SELF's operand-dependent
+ value. fields[0] specifies the base register field. */
+bool
+aarch64_ins_sve_addr_ri_s4 (const aarch64_operand *self,
+ const aarch64_opnd_info *info, aarch64_insn *code,
+ const aarch64_inst *inst ATTRIBUTE_UNUSED,
+ aarch64_operand_error *errors ATTRIBUTE_UNUSED)
+{
+ int factor = 1 << get_operand_specific_data (self);
+ insert_field (self->fields[0], code, info->addr.base_regno, 0);
+ insert_field (FLD_SVE_imm4, code, info->addr.offset.imm / factor, 0);
+ return true;
+}
+
+/* Encode an SVE address [X<n>, #<SVE_imm6> << <shift>], where <SVE_imm6>
+ is a 6-bit unsigned number and where <shift> is SELF's operand-dependent
+ value. fields[0] specifies the base register field. */
+bool
+aarch64_ins_sve_addr_ri_u6 (const aarch64_operand *self,
+ const aarch64_opnd_info *info, aarch64_insn *code,
+ const aarch64_inst *inst ATTRIBUTE_UNUSED,
+ aarch64_operand_error *errors ATTRIBUTE_UNUSED)
+{
+ int factor = 1 << get_operand_specific_data (self);
+ insert_field (self->fields[0], code, info->addr.base_regno, 0);
+ insert_field (FLD_SVE_imm6, code, info->addr.offset.imm / factor, 0);
+ return true;
+}
+
+/* Encode an SVE address [X<n>, X<m>{, LSL #<shift>}], where <shift>
+ is SELF's operand-dependent value. fields[0] specifies the base
+ register field and fields[1] specifies the offset register field. */
+bool
+aarch64_ins_sve_addr_rr_lsl (const aarch64_operand *self,
+ const aarch64_opnd_info *info, aarch64_insn *code,
+ const aarch64_inst *inst ATTRIBUTE_UNUSED,
+ aarch64_operand_error *errors ATTRIBUTE_UNUSED)
+{
+ insert_field (self->fields[0], code, info->addr.base_regno, 0);
+ insert_field (self->fields[1], code, info->addr.offset.regno, 0);
+ return true;
+}
+
+/* Encode an SVE address [X<n>, Z<m>.<T>, (S|U)XTW {#<shift>}], where
+ <shift> is SELF's operand-dependent value. fields[0] specifies the
+ base register field, fields[1] specifies the offset register field and
+ fields[2] is a single-bit field that selects SXTW over UXTW. */
+bool
+aarch64_ins_sve_addr_rz_xtw (const aarch64_operand *self,
+ const aarch64_opnd_info *info, aarch64_insn *code,
+ const aarch64_inst *inst ATTRIBUTE_UNUSED,
+ aarch64_operand_error *errors ATTRIBUTE_UNUSED)
+{
+ insert_field (self->fields[0], code, info->addr.base_regno, 0);
+ insert_field (self->fields[1], code, info->addr.offset.regno, 0);
+ if (info->shifter.kind == AARCH64_MOD_UXTW)
+ insert_field (self->fields[2], code, 0, 0);
+ else
+ insert_field (self->fields[2], code, 1, 0);
+ return true;
+}
+
+/* Encode an SVE address [Z<n>.<T>, #<imm5> << <shift>], where <imm5> is a
+ 5-bit unsigned number and where <shift> is SELF's operand-dependent value.
+ fields[0] specifies the base register field. */
+bool
+aarch64_ins_sve_addr_zi_u5 (const aarch64_operand *self,
+ const aarch64_opnd_info *info, aarch64_insn *code,
+ const aarch64_inst *inst ATTRIBUTE_UNUSED,
+ aarch64_operand_error *errors ATTRIBUTE_UNUSED)
+{
+ int factor = 1 << get_operand_specific_data (self);
+ insert_field (self->fields[0], code, info->addr.base_regno, 0);
+ insert_field (FLD_imm5, code, info->addr.offset.imm / factor, 0);
+ return true;
+}
+
+/* Encode an SVE address [Z<n>.<T>, Z<m>.<T>{, <modifier> {#<msz>}}],
+ where <modifier> is fixed by the instruction and where <msz> is a
+ 2-bit unsigned number. fields[0] specifies the base register field
+ and fields[1] specifies the offset register field. */
+static bool
+aarch64_ext_sve_addr_zz (const aarch64_operand *self,
+ const aarch64_opnd_info *info, aarch64_insn *code,
+ aarch64_operand_error *errors ATTRIBUTE_UNUSED)
+{
+ insert_field (self->fields[0], code, info->addr.base_regno, 0);
+ insert_field (self->fields[1], code, info->addr.offset.regno, 0);
+ insert_field (FLD_SVE_msz, code, info->shifter.amount, 0);
+ return true;
+}
+
+/* Encode an SVE address [Z<n>.<T>, Z<m>.<T>{, LSL #<msz>}], where
+ <msz> is a 2-bit unsigned number. fields[0] specifies the base register
+ field and fields[1] specifies the offset register field. */
+bool
+aarch64_ins_sve_addr_zz_lsl (const aarch64_operand *self,
+ const aarch64_opnd_info *info, aarch64_insn *code,
+ const aarch64_inst *inst ATTRIBUTE_UNUSED,
+ aarch64_operand_error *errors)
+{
+ return aarch64_ext_sve_addr_zz (self, info, code, errors);
+}
+
+/* Encode an SVE address [Z<n>.<T>, Z<m>.<T>, SXTW {#<msz>}], where
+ <msz> is a 2-bit unsigned number. fields[0] specifies the base register
+ field and fields[1] specifies the offset register field. */
+bool
+aarch64_ins_sve_addr_zz_sxtw (const aarch64_operand *self,
+ const aarch64_opnd_info *info,
+ aarch64_insn *code,
+ const aarch64_inst *inst ATTRIBUTE_UNUSED,
+ aarch64_operand_error *errors)
+{
+ return aarch64_ext_sve_addr_zz (self, info, code, errors);
+}
+
+/* Encode an SVE address [Z<n>.<T>, Z<m>.<T>, UXTW {#<msz>}], where
+ <msz> is a 2-bit unsigned number. fields[0] specifies the base register
+ field and fields[1] specifies the offset register field. */
+bool
+aarch64_ins_sve_addr_zz_uxtw (const aarch64_operand *self,
+ const aarch64_opnd_info *info,
+ aarch64_insn *code,
+ const aarch64_inst *inst ATTRIBUTE_UNUSED,
+ aarch64_operand_error *errors)
+{
+ return aarch64_ext_sve_addr_zz (self, info, code, errors);
+}
+
+/* Encode an SVE ADD/SUB immediate. */
+bool
+aarch64_ins_sve_aimm (const aarch64_operand *self,
+ const aarch64_opnd_info *info, aarch64_insn *code,
+ const aarch64_inst *inst ATTRIBUTE_UNUSED,
+ aarch64_operand_error *errors 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 true;
+}
+
+/* Encode an SVE CPY/DUP immediate. */
+bool
+aarch64_ins_sve_asimm (const aarch64_operand *self,
+ const aarch64_opnd_info *info, aarch64_insn *code,
+ const aarch64_inst *inst,
+ aarch64_operand_error *errors)
+{
+ return aarch64_ins_sve_aimm (self, info, code, inst, errors);
+}
+
+/* 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
+ significant part. */
+bool
+aarch64_ins_sve_index (const aarch64_operand *self,
+ const aarch64_opnd_info *info, aarch64_insn *code,
+ const aarch64_inst *inst ATTRIBUTE_UNUSED,
+ aarch64_operand_error *errors ATTRIBUTE_UNUSED)
+{
+ unsigned int esize = aarch64_get_qualifier_esize (info->qualifier);
+ insert_field (self->fields[0], code, info->reglane.regno, 0);
+ insert_fields (code, (info->reglane.index * 2 + 1) * esize, 0,
+ 2, FLD_imm5, FLD_SVE_tszh);
+ return true;
+}
+
+/* Encode a logical/bitmask immediate for the MOV alias of SVE DUPM. */
+bool
+aarch64_ins_sve_limm_mov (const aarch64_operand *self,
+ const aarch64_opnd_info *info, aarch64_insn *code,
+ const aarch64_inst *inst,
+ aarch64_operand_error *errors)
+{
+ return aarch64_ins_limm (self, info, code, inst, errors);
+}
+
+/* Encode Zn[MM], where Zn occupies the least-significant part of the field
+ and where MM occupies the most-significant part. The operand-dependent
+ value specifies the number of bits in Zn. */
+bool
+aarch64_ins_sve_quad_index (const aarch64_operand *self,
+ const aarch64_opnd_info *info, aarch64_insn *code,
+ const aarch64_inst *inst ATTRIBUTE_UNUSED,
+ aarch64_operand_error *errors ATTRIBUTE_UNUSED)
+{
+ unsigned int reg_bits = get_operand_specific_data (self);
+ assert (info->reglane.regno < (1U << reg_bits));
+ unsigned int val = (info->reglane.index << reg_bits) + info->reglane.regno;
+ insert_all_fields (self, code, val);
+ return true;
+}
+
+/* Encode {Zn.<T> - Zm.<T>}. The fields array specifies which field
+ to use for Zn. */
+bool
+aarch64_ins_sve_reglist (const aarch64_operand *self,
+ const aarch64_opnd_info *info, aarch64_insn *code,
+ const aarch64_inst *inst ATTRIBUTE_UNUSED,
+ aarch64_operand_error *errors ATTRIBUTE_UNUSED)
+{
+ insert_field (self->fields[0], code, info->reglist.first_regno, 0);
+ return true;
+}
+
+/* Encode <pattern>{, MUL #<amount>}. The fields array specifies which
+ fields to use for <pattern>. <amount> - 1 is encoded in the SVE_imm4
+ field. */
+bool
+aarch64_ins_sve_scale (const aarch64_operand *self,
+ const aarch64_opnd_info *info, aarch64_insn *code,
+ const aarch64_inst *inst ATTRIBUTE_UNUSED,
+ aarch64_operand_error *errors ATTRIBUTE_UNUSED)
+{
+ insert_all_fields (self, code, info->imm.value);
+ insert_field (FLD_SVE_imm4, code, info->shifter.amount - 1, 0);
+ return true;
+}
+
+/* Encode an SVE shift left immediate. */
+bool
+aarch64_ins_sve_shlimm (const aarch64_operand *self,
+ const aarch64_opnd_info *info, aarch64_insn *code,
+ const aarch64_inst *inst,
+ aarch64_operand_error *errors ATTRIBUTE_UNUSED)
+{
+ 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 true;
+}
+
+/* Encode an SVE shift right immediate. */
+bool
+aarch64_ins_sve_shrimm (const aarch64_operand *self,
+ const aarch64_opnd_info *info, aarch64_insn *code,
+ const aarch64_inst *inst,
+ aarch64_operand_error *errors ATTRIBUTE_UNUSED)
+{
+ const aarch64_opnd_info *prev_operand;
+ unsigned int esize;
+
+ unsigned int opnd_backshift = get_operand_specific_data (self);
+ assert (info->idx >= (int)opnd_backshift);
+ prev_operand = &inst->operands[info->idx - opnd_backshift];
+ esize = aarch64_get_qualifier_esize (prev_operand->qualifier);
+ insert_all_fields (self, code, 16 * esize - info->imm.value);
+ return true;
+}
+
+/* Encode a single-bit immediate that selects between #0.5 and #1.0.
+ The fields array specifies which field to use. */
+bool
+aarch64_ins_sve_float_half_one (const aarch64_operand *self,
+ const aarch64_opnd_info *info,
+ aarch64_insn *code,
+ const aarch64_inst *inst ATTRIBUTE_UNUSED,
+ aarch64_operand_error *errors ATTRIBUTE_UNUSED)
+{
+ if (info->imm.value == 0x3f000000)
+ insert_field (self->fields[0], code, 0, 0);
+ else
+ insert_field (self->fields[0], code, 1, 0);
+ return true;
+}
+
+/* Encode a single-bit immediate that selects between #0.5 and #2.0.
+ The fields array specifies which field to use. */
+bool
+aarch64_ins_sve_float_half_two (const aarch64_operand *self,
+ const aarch64_opnd_info *info,
+ aarch64_insn *code,
+ const aarch64_inst *inst ATTRIBUTE_UNUSED,
+ aarch64_operand_error *errors ATTRIBUTE_UNUSED)
+{
+ if (info->imm.value == 0x3f000000)
+ insert_field (self->fields[0], code, 0, 0);
+ else
+ insert_field (self->fields[0], code, 1, 0);
+ return true;
+}
+
+/* Encode a single-bit immediate that selects between #0.0 and #1.0.
+ The fields array specifies which field to use. */
+bool
+aarch64_ins_sve_float_zero_one (const aarch64_operand *self,
+ const aarch64_opnd_info *info,
+ aarch64_insn *code,
+ const aarch64_inst *inst ATTRIBUTE_UNUSED,
+ aarch64_operand_error *errors ATTRIBUTE_UNUSED)
+{
+ if (info->imm.value == 0)
+ insert_field (self->fields[0], code, 0, 0);
+ else
+ insert_field (self->fields[0], code, 1, 0);
+ return true;
+}
+
+/* Encode in SME instruction such as MOVA ZA tile vector register number,
+ vector indicator, vector selector and immediate. */
+bool
+aarch64_ins_sme_za_hv_tiles (const aarch64_operand *self,
+ const aarch64_opnd_info *info,
+ aarch64_insn *code,
+ const aarch64_inst *inst ATTRIBUTE_UNUSED,
+ aarch64_operand_error *errors ATTRIBUTE_UNUSED)
+{
+ int fld_size;
+ int fld_q;
+ int fld_v = info->za_tile_vector.v;
+ int fld_rv = info->za_tile_vector.index.regno - 12;
+ int fld_zan_imm = info->za_tile_vector.index.imm;
+ int regno = info->za_tile_vector.regno;
+
+ switch (info->qualifier)
+ {
+ case AARCH64_OPND_QLF_S_B:
+ fld_size = 0;
+ fld_q = 0;
+ break;
+ case AARCH64_OPND_QLF_S_H:
+ fld_size = 1;
+ fld_q = 0;
+ fld_zan_imm |= regno << 3;
+ break;
+ case AARCH64_OPND_QLF_S_S:
+ fld_size = 2;
+ fld_q = 0;
+ fld_zan_imm |= regno << 2;
+ break;
+ case AARCH64_OPND_QLF_S_D:
+ fld_size = 3;
+ fld_q = 0;
+ fld_zan_imm |= regno << 1;
+ break;
+ case AARCH64_OPND_QLF_S_Q:
+ fld_size = 3;
+ fld_q = 1;
+ fld_zan_imm = regno;
+ break;
+ default:
+ return false;
+ }
+
+ insert_field (self->fields[0], code, fld_size, 0);
+ insert_field (self->fields[1], code, fld_q, 0);
+ insert_field (self->fields[2], code, fld_v, 0);
+ insert_field (self->fields[3], code, fld_rv, 0);
+ insert_field (self->fields[4], code, fld_zan_imm, 0);
+
+ return true;
+}
+
+/* Encode in SME instruction ZERO list of up to eight 64-bit element tile names
+ separated by commas, encoded in the "imm8" field.
+
+ For programmer convenience an assembler must also accept the names of
+ 32-bit, 16-bit and 8-bit element tiles which are converted into the
+ corresponding set of 64-bit element tiles.
+*/
+bool
+aarch64_ins_sme_za_list (const aarch64_operand *self,
+ const aarch64_opnd_info *info,
+ aarch64_insn *code,
+ const aarch64_inst *inst ATTRIBUTE_UNUSED,
+ aarch64_operand_error *errors ATTRIBUTE_UNUSED)
+{
+ int fld_mask = info->imm.value;
+ insert_field (self->fields[0], code, fld_mask, 0);
+ return true;
+}
+
+bool
+aarch64_ins_sme_za_array (const aarch64_operand *self,
+ const aarch64_opnd_info *info,
+ aarch64_insn *code,
+ const aarch64_inst *inst ATTRIBUTE_UNUSED,
+ aarch64_operand_error *errors ATTRIBUTE_UNUSED)
+{
+ int regno = info->za_tile_vector.index.regno - 12;
+ int imm = info->za_tile_vector.index.imm;
+ insert_field (self->fields[0], code, regno, 0);
+ insert_field (self->fields[1], code, imm, 0);
+ return true;
+}
+
+bool
+aarch64_ins_sme_addr_ri_u4xvl (const aarch64_operand *self,
+ const aarch64_opnd_info *info,
+ aarch64_insn *code,
+ const aarch64_inst *inst ATTRIBUTE_UNUSED,
+ aarch64_operand_error *errors ATTRIBUTE_UNUSED)
+{
+ int regno = info->addr.base_regno;
+ int imm = info->addr.offset.imm;
+ insert_field (self->fields[0], code, regno, 0);
+ insert_field (self->fields[1], code, imm, 0);
+ return true;
+}
+
+/* Encode in SMSTART and SMSTOP {SM | ZA } mode. */
+bool
+aarch64_ins_sme_sm_za (const aarch64_operand *self,
+ const aarch64_opnd_info *info,
+ aarch64_insn *code,
+ const aarch64_inst *inst ATTRIBUTE_UNUSED,
+ aarch64_operand_error *errors ATTRIBUTE_UNUSED)
+{
+ aarch64_insn fld_crm;
+ /* Set CRm[3:1] bits. */
+ if (info->reg.regno == 's')
+ fld_crm = 0x02 ; /* SVCRSM. */
+ else if (info->reg.regno == 'z')
+ fld_crm = 0x04; /* SVCRZA. */
+ else
+ return false;
+
+ insert_field (self->fields[0], code, fld_crm, 0);
+ return true;
+}
+
+/* Encode source scalable predicate register (Pn), name of the index base
+ register W12-W15 (Rm), and optional element index, defaulting to 0, in the
+ range 0 to one less than the number of vector elements in a 128-bit vector
+ register, encoded in "i1:tszh:tszl".
+*/
+bool
+aarch64_ins_sme_pred_reg_with_index (const aarch64_operand *self,
+ const aarch64_opnd_info *info,
+ aarch64_insn *code,
+ const aarch64_inst *inst ATTRIBUTE_UNUSED,
+ aarch64_operand_error *errors ATTRIBUTE_UNUSED)
+{
+ int fld_pn = info->za_tile_vector.regno;
+ int fld_rm = info->za_tile_vector.index.regno - 12;
+ int imm = info->za_tile_vector.index.imm;
+ int fld_i1, fld_tszh, fld_tshl;
+
+ insert_field (self->fields[0], code, fld_rm, 0);
+ insert_field (self->fields[1], code, fld_pn, 0);
+
+ /* Optional element index, defaulting to 0, in the range 0 to one less than
+ the number of vector elements in a 128-bit vector register, encoded in
+ "i1:tszh:tszl".
+
+ i1 tszh tszl <T>
+ 0 0 000 RESERVED
+ x x xx1 B
+ x x x10 H
+ x x 100 S
+ x 1 000 D
+ */
+ switch (info->qualifier)
+ {
+ case AARCH64_OPND_QLF_S_B:
+ /* <imm> is 4 bit value. */
+ fld_i1 = (imm >> 3) & 0x1;
+ fld_tszh = (imm >> 2) & 0x1;
+ fld_tshl = ((imm << 1) | 0x1) & 0x7;
+ break;
+ case AARCH64_OPND_QLF_S_H:
+ /* <imm> is 3 bit value. */
+ fld_i1 = (imm >> 2) & 0x1;
+ fld_tszh = (imm >> 1) & 0x1;
+ fld_tshl = ((imm << 2) | 0x2) & 0x7;
+ break;
+ case AARCH64_OPND_QLF_S_S:
+ /* <imm> is 2 bit value. */
+ fld_i1 = (imm >> 1) & 0x1;
+ fld_tszh = imm & 0x1;
+ fld_tshl = 0x4;
+ break;
+ case AARCH64_OPND_QLF_S_D:
+ /* <imm> is 1 bit value. */
+ fld_i1 = imm & 0x1;
+ fld_tszh = 0x1;
+ fld_tshl = 0x0;
+ break;
+ default:
+ return false;
+ }
+
+ insert_field (self->fields[2], code, fld_i1, 0);
+ insert_field (self->fields[3], code, fld_tszh, 0);
+ insert_field (self->fields[4], code, fld_tshl, 0);
+ return true;