+ 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. */
+bfd_boolean
+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. */
+bfd_boolean
+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. */
+bfd_boolean
+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. */
+bfd_boolean
+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. */
+bfd_boolean
+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. */
+bfd_boolean
+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. */
+bfd_boolean
+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. */
+bfd_boolean
+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 bfd_boolean
+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. */
+bfd_boolean
+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. */
+bfd_boolean
+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. */
+bfd_boolean
+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. */
+bfd_boolean
+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. */
+bfd_boolean
+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. */
+bfd_boolean
+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. */
+bfd_boolean
+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. */
+bfd_boolean
+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. */
+bfd_boolean
+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. */
+bfd_boolean
+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. */
+bfd_boolean
+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. */
+bfd_boolean
+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. */
+bfd_boolean
+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. */
+bfd_boolean
+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. */
+bfd_boolean
+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;