From: Andrew Carlotti <andrew.carlotti@arm.com>
To: Saurabh Jha <saurabh.jha@arm.com>
Cc: binutils@sourceware.org, Richard Earnshaw <richard.earnshaw@arm.com>
Subject: Re: [PATCH v2 1/2] gas, aarch64: Add AdvSIMD lut extension
Date: Tue, 21 May 2024 14:57:44 +0100 [thread overview]
Message-ID: <7ad78811-fb9e-7518-72ec-d4d5885f756e@e124511.cambridge.arm.com> (raw)
In-Reply-To: <f38f4aa8-00d1-4917-b198-637d9844b6a3@arm.com>
On Thu, May 16, 2024 at 11:35:18AM +0100, Saurabh Jha wrote:
> Introduces instructions for the Advanced SIMD lut extension for AArch64.
> They are documented in the following links:
> * luti2: https://developer.arm.com/documentation/ddi0602/2024-03/SIMD-FP-Instructions/LUTI2--Lookup-table-read-with-2-bit-indices-?lang=en
> * luti4: https://developer.arm.com/documentation/ddi0602/2024-03/SIMD-FP-Instructions/LUTI4--Lookup-table-read-with-4-bit-indices-?lang=en
>
> These instructions needed definition of some new operands. We will first
> discuss operands for the third operand of the instructions and then
> discuss a vector register list operand needed for the second operand.
>
> The third operands are vectors with bit indices and without type
> qualifiers. They are called Em_INDEX1_14, Em_INDEX2_13, and Em_INDEX3_12
> and they have 1 bit, 2 bit, and 3 bit indices respectively. For these
> new operands, we defined new parsing case branch and a new instruction
> class. We also modified the existing reglane inserters and extractors
> to handle the new operands. The lsb and width of these operands are
> the same as many existing operands but the convention is to give
> different names to fields that serve different purpose so we
> introduced new fields in aarch64-opc.c and aarch64-opc.h for these
> operands.
>
> For the second operand of these instructions, we introduced a new
> operand called LVn_LUT. This represents a vector register list with
> stride 1. We defined new inserter and extractor for this new operand and
> it is encoded in FLD_Rn. We are enforcing the number of registers in the
> reglist using opcode flag rather than operand flag as this is what other
> SIMD vector register list operands are doing. The disassembly also uses
> opcode flag to print the correct number of registers.
> ---
> Hi,
>
> Regression tested for aarch64-none-elf and found no regressions.
>
> Ok for binutils-master? I don't have commit access so can someone please
> commit on my behalf?
>
> Regards,
> Saurabh
> diff --git a/gas/config/tc-aarch64.c b/gas/config/tc-aarch64.c
> index 6ad4fae8b0ece71e5ac448be889846369c657420..bfba6efc6417e15887b0349c671e074e2238adc0 100644
> --- a/gas/config/tc-aarch64.c
> +++ b/gas/config/tc-aarch64.c
> @@ -1513,6 +1513,54 @@ parse_vector_reg_list (char **ccp, aarch64_reg_type type,
> return error ? PARSE_FAIL : (ret_val << 2) | (nb_regs - 1);
> }
>
> +/* Parse a SIMD vector register with a bit index. The SIMD vectors with
> + bit indices don't have type qualifiers.
> +
> + Return null if the string pointed to by *CCP is not a valid AdvSIMD
> + vector register with a bit index.
> +
> + Otherwise return the register and the bit index information
> + in *typeinfo.
> +
> + The validity of the bit index itself is checked separately in encoding.
> + */
> +
> +static const reg_entry *
> +parse_simd_vector_with_bit_index (char **ccp, struct vector_type_el *typeinfo)
> +{
> + char *str = *ccp;
> + const reg_entry *reg = parse_reg (&str);
> + struct vector_type_el atype;
> +
> + // Setting it here as this is the convention followed in the
> + // rest of the code with indices.
> + atype.defined = NTA_HASINDEX;
> + // This will be set to correct value in parse_index_expressions.
> + atype.index = 0;
> + // The rest of the fields are not applicable for this operand.
> + atype.type = NT_invtype;
> + atype.width = -1;
> + atype.element_size = 0;
> +
> + if (reg == NULL)
> + return NULL;
> +
> + if (reg->type != REG_TYPE_V)
> + return NULL;
> +
> + // Parse the bit index.
> + if (!skip_past_char (&str, '['))
> + return NULL;
> + if (!parse_index_expression (&str, &atype.index))
> + return NULL;
> + if (!skip_past_char (&str, ']'))
> + return NULL;
> +
> + *typeinfo = atype;
> + *ccp = str;
> + return reg;
> +}
> +
> /* Directives: register aliases. */
>
> static reg_entry *
> @@ -6761,6 +6809,23 @@ parse_operands (char *str, const aarch64_opcode *opcode)
> reg_type = REG_TYPE_Z;
> goto vector_reg_index;
>
> + case AARCH64_OPND_Em_INDEX1_14:
> + case AARCH64_OPND_Em_INDEX2_13:
> + case AARCH64_OPND_Em_INDEX3_12:
> + // These are SIMD vector operands with bit indices. For example,
> + // 'V27[3]'. These operands don't have type qualifiers before
> + // indices.
> + reg = parse_simd_vector_with_bit_index(&str, &vectype);
> +
> + if (!reg)
> + goto failure;
> + gas_assert (vectype.defined & NTA_HASINDEX);
> +
> + info->qualifier = AARCH64_OPND_QLF_NIL;
> + info->reglane.regno = reg->number;
> + info->reglane.index = vectype.index;
> + break;
> +
Is the new function and separate handling necessary? There's already support
in the section below for indexed operands without qualifiers on SVE registers.
I tested removing the reg->type check from the below line, and nothing broke in
the testsuite, so maybe that's an option.
> if (reg->type == REG_TYPE_Z && vectype.type == NT_invtype)
If that's not an option, could you move this block of code so it isn't in the
middle of the vector_reg_index cases?
> case AARCH64_OPND_Ed:
> case AARCH64_OPND_En:
> case AARCH64_OPND_Em:
> @@ -6812,6 +6877,7 @@ parse_operands (char *str, const aarch64_opcode *opcode)
> goto vector_reg_list;
>
> case AARCH64_OPND_LVn:
> + case AARCH64_OPND_LVn_LUT:
> case AARCH64_OPND_LVt:
> case AARCH64_OPND_LVt_AL:
> case AARCH64_OPND_LEt:
> @@ -10477,6 +10543,7 @@ static const struct aarch64_option_cpu_value_table aarch64_features[] = {
> {"rcpc3", AARCH64_FEATURE (RCPC3), AARCH64_FEATURE (RCPC2)},
> {"cpa", AARCH64_FEATURE (CPA), AARCH64_NO_FEATURES},
> {"faminmax", AARCH64_FEATURE (FAMINMAX), AARCH64_FEATURE (SIMD)},
> + {"lut", AARCH64_FEATURE (LUT), AARCH64_FEATURE (SIMD)},
> {NULL, AARCH64_NO_FEATURES, AARCH64_NO_FEATURES},
> };
>
...
> diff --git a/include/opcode/aarch64.h b/include/opcode/aarch64.h
> index 2fca9528c2012be983c2414a30fa5930e57e5c92..63456021a1d167c747ca913a355dd02cf90fc726 100644
> --- a/include/opcode/aarch64.h
> +++ b/include/opcode/aarch64.h
> @@ -232,6 +232,8 @@ enum aarch64_feature_bit {
> AARCH64_FEATURE_CPA,
> /* FAMINMAX instructions. */
> AARCH64_FEATURE_FAMINMAX,
> + /* LUT instructions. */
> + AARCH64_FEATURE_LUT,
> AARCH64_NUM_FEATURES
> };
>
> @@ -518,10 +520,14 @@ enum aarch64_opnd
> AARCH64_OPND_Em, /* AdvSIMD Vector Element Vm. */
> AARCH64_OPND_Em16, /* AdvSIMD Vector Element Vm restricted to V0 - V15 when
> qualifier is S_H. */
> + AARCH64_OPND_Em_INDEX1_14, /* AdvSIMD 1-bit encoded index in Vm at [14] */
> + AARCH64_OPND_Em_INDEX2_13, /* AdvSIMD 2-bit encoded index in Vm at [14:13] */
> + AARCH64_OPND_Em_INDEX3_12, /* AdvSIMD 3-bit encoded index in Vm at [14:12] */
> AARCH64_OPND_LVn, /* AdvSIMD Vector register list used in e.g. TBL. */
> AARCH64_OPND_LVt, /* AdvSIMD Vector register list used in ld/st. */
> AARCH64_OPND_LVt_AL, /* AdvSIMD Vector register list for loading single
> structure to all lanes. */
> + AARCH64_OPND_LVn_LUT, /* AdvSIMD Vector register list used in lut. */
> AARCH64_OPND_LEt, /* AdvSIMD Vector Element list. */
>
> AARCH64_OPND_CRn, /* Co-processor register in CRn field. */
> @@ -1018,7 +1024,8 @@ enum aarch64_insn_class
> the,
> sve2_urqvs,
> sve_index1,
> - rcpc3
> + rcpc3,
> + lut
> };
>
> /* Opcode enumerators. */
> diff --git a/opcodes/aarch64-asm.h b/opcodes/aarch64-asm.h
> index 88e389bfebda001efbb578a6e144dd5e2513cf78..edeb6d8de7e2c3e117e0ad91a02b93c0e040a061 100644
> --- a/opcodes/aarch64-asm.h
> +++ b/opcodes/aarch64-asm.h
> @@ -47,6 +47,7 @@ AARCH64_DECL_OPD_INSERTER (ins_reglane);
> AARCH64_DECL_OPD_INSERTER (ins_reglist);
> AARCH64_DECL_OPD_INSERTER (ins_ldst_reglist);
> AARCH64_DECL_OPD_INSERTER (ins_ldst_reglist_r);
> +AARCH64_DECL_OPD_INSERTER (ins_lut_reglist);
> AARCH64_DECL_OPD_INSERTER (ins_ldst_elemlist);
> AARCH64_DECL_OPD_INSERTER (ins_advsimd_imm_shift);
> AARCH64_DECL_OPD_INSERTER (ins_imm);
> diff --git a/opcodes/aarch64-asm.c b/opcodes/aarch64-asm.c
> index 5a55ca2f86db2d45b6cb54b5ee22606ec27c51fd..338ed54165d26cec2f0634bc62c1d7355ca4956a 100644
> --- a/opcodes/aarch64-asm.c
> +++ b/opcodes/aarch64-asm.c
> @@ -168,6 +168,27 @@ aarch64_ins_reglane (const aarch64_operand *self, const aarch64_opnd_info *info,
> assert (reglane_index < 4);
> insert_field (FLD_SM3_imm2, code, reglane_index, 0);
> }
> + else if (inst->opcode->iclass == lut)
> + {
> + unsigned reglane_index = info->reglane.index;
> + switch (info->type)
> + {
> + case AARCH64_OPND_Em_INDEX1_14:
> + assert (reglane_index < 2);
> + insert_field (FLD_imm1_14, code, reglane_index, 0);
> + break;
> + case AARCH64_OPND_Em_INDEX2_13:
> + assert (reglane_index < 4);
> + insert_field (FLD_imm2_13, code, reglane_index, 0);
> + break;
> + case AARCH64_OPND_Em_INDEX3_12:
> + assert (reglane_index < 8);
> + insert_field (FLD_imm3_12, code, reglane_index, 0);
> + break;
> + default:
> + return false;
> + }
> + }
> else
> {
> /* index for e.g. SQDMLAL <Va><d>, <Vb><n>, <Vm>.<Ts>[<index>]
> @@ -286,6 +307,17 @@ aarch64_ins_ldst_reglist_r (const aarch64_operand *self ATTRIBUTE_UNUSED,
> return true;
> }
>
> +/* Insert regnos of register list operand for AdvSIMD lut instructions. */
> +bool
> +aarch64_ins_lut_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;
> +}
> +
> /* Insert Q, opcode<2:1>, S, size and Rt fields for a register element list
> operand e.g. Vt in AdvSIMD load/store single element instructions. */
> bool
> diff --git a/opcodes/aarch64-dis.h b/opcodes/aarch64-dis.h
> index 86494cc30937b1d7e4caf90630caec30c8b31d3e..9e8f7c214d70390a72f93e38655a5ac0f562d085 100644
> --- a/opcodes/aarch64-dis.h
> +++ b/opcodes/aarch64-dis.h
> @@ -70,6 +70,7 @@ AARCH64_DECL_OPD_EXTRACTOR (ext_reglane);
> AARCH64_DECL_OPD_EXTRACTOR (ext_reglist);
> AARCH64_DECL_OPD_EXTRACTOR (ext_ldst_reglist);
> AARCH64_DECL_OPD_EXTRACTOR (ext_ldst_reglist_r);
> +AARCH64_DECL_OPD_EXTRACTOR (ext_lut_reglist);
> AARCH64_DECL_OPD_EXTRACTOR (ext_ldst_elemlist);
> AARCH64_DECL_OPD_EXTRACTOR (ext_advsimd_imm_shift);
> AARCH64_DECL_OPD_EXTRACTOR (ext_shll_imm);
> diff --git a/opcodes/aarch64-dis.c b/opcodes/aarch64-dis.c
> index 96f42ae862a395bf3aa498c495fdcea9a3d12a41..130d2c1fae005c25a4615a88190b62ffd059cdb1 100644
> --- a/opcodes/aarch64-dis.c
> +++ b/opcodes/aarch64-dis.c
> @@ -398,6 +398,23 @@ aarch64_ext_reglane (const aarch64_operand *self, aarch64_opnd_info *info,
> /* index for e.g. SM3TT2A <Vd>.4S, <Vn>.4S, <Vm>S[<imm2>]. */
> info->reglane.index = extract_field (FLD_SM3_imm2, code, 0);
> }
> + else if (inst->opcode->iclass == lut)
> + {
> + switch (info->type)
> + {
> + case AARCH64_OPND_Em_INDEX1_14:
> + info->reglane.index = extract_field (FLD_imm1_14, code, 0);
> + break;
> + case AARCH64_OPND_Em_INDEX2_13:
> + info->reglane.index = extract_field (FLD_imm2_13, code, 0);
> + break;
> + case AARCH64_OPND_Em_INDEX3_12:
> + info->reglane.index = extract_field (FLD_imm3_12, code, 0);
> + break;
> + default:
> + return false;
> + }
> + }
> else
> {
> /* Index only for e.g. SQDMLAL <Va><d>, <Vb><n>, <Vm>.<Ts>[<index>]
> @@ -533,6 +550,21 @@ aarch64_ext_ldst_reglist_r (const aarch64_operand *self ATTRIBUTE_UNUSED,
> return true;
> }
>
> +/* Decode AdvSIMD vector register list for AdvSIMD lut instructions.
> + The number of of registers in the list is determined by the opcode
> + flag. */
> +bool
> +aarch64_ext_lut_reglist (const aarch64_operand *self, aarch64_opnd_info *info,
> + const aarch64_insn code,
> + const aarch64_inst *inst ATTRIBUTE_UNUSED,
> + aarch64_operand_error *errors ATTRIBUTE_UNUSED)
> +{
> + info->reglist.first_regno = extract_field (self->fields[0], code, 0);
> + info->reglist.num_regs = get_opcode_dependent_value (inst->opcode);
> + info->reglist.stride = 1;
> + return true;
> +}
> +
> /* Decode Q, opcode<2:1>, S, size and Rt fields of Vt in AdvSIMD
> load/store single element instructions. */
> bool
> diff --git a/opcodes/aarch64-opc.h b/opcodes/aarch64-opc.h
> index 4e781f000cc38c12058530e5851b08083d42af52..23e634f1250de579661bbeb14d611b868b76bc8d 100644
> --- a/opcodes/aarch64-opc.h
> +++ b/opcodes/aarch64-opc.h
> @@ -147,6 +147,7 @@ enum aarch64_field_kind
> FLD_imm1_2,
> FLD_imm1_8,
> FLD_imm1_10,
> + FLD_imm1_14,
> FLD_imm1_15,
> FLD_imm1_16,
> FLD_imm2_0,
> @@ -154,6 +155,7 @@ enum aarch64_field_kind
> FLD_imm2_8,
> FLD_imm2_10,
> FLD_imm2_12,
> + FLD_imm2_13,
> FLD_imm2_15,
> FLD_imm2_16,
> FLD_imm2_19,
> diff --git a/opcodes/aarch64-opc.c b/opcodes/aarch64-opc.c
> index e88c616f4a9f3657756b919dc1196c08831c3cc5..61ab4c14a6393150f29a3fa1679a30b642bf8844 100644
> --- a/opcodes/aarch64-opc.c
> +++ b/opcodes/aarch64-opc.c
> @@ -337,6 +337,7 @@ const aarch64_field fields[] =
> { 2, 1 }, /* imm1_2: general immediate in bits [2]. */
> { 8, 1 }, /* imm1_8: general immediate in bits [8]. */
> { 10, 1 }, /* imm1_10: general immediate in bits [10]. */
> + { 14, 1 }, /* imm1_14: general immediate in bits [14]. */
> { 15, 1 }, /* imm1_15: general immediate in bits [15]. */
> { 16, 1 }, /* imm1_16: general immediate in bits [16]. */
> { 0, 2 }, /* imm2_0: general immediate in bits [1:0]. */
> @@ -344,6 +345,7 @@ const aarch64_field fields[] =
> { 8, 2 }, /* imm2_8: general immediate in bits [9:8]. */
> { 10, 2 }, /* imm2_10: 2-bit immediate, bits [11:10] */
> { 12, 2 }, /* imm2_12: 2-bit immediate, bits [13:12] */
> + { 13, 2 }, /* imm2_13: 2-bit immediate, bits [14:13] */
> { 15, 2 }, /* imm2_15: 2-bit immediate, bits [16:15] */
> { 16, 2 }, /* imm2_16: 2-bit immediate, bits [17:16] */
> { 19, 2 }, /* imm2_19: 2-bit immediate, bits [20:19] */
> @@ -2554,6 +2556,10 @@ operand_general_constraint_met_p (const aarch64_opnd_info *opnds, int idx,
> num = get_opcode_dependent_value (opcode);
> switch (type)
> {
> + case AARCH64_OPND_LVn_LUT:
> + if (!check_reglist (opnd, mismatch_detail, idx, num, 1))
> + return 0;
> + break;
> case AARCH64_OPND_LVt:
> assert (num >= 1 && num <= 4);
> /* Unless LD1/ST1, the number of registers should be equal to that
> @@ -3165,6 +3171,14 @@ operand_general_constraint_met_p (const aarch64_opnd_info *opnds, int idx,
> and is halfed because complex numbers take two elements. */
> num = aarch64_get_qualifier_nelem (opnds[0].qualifier)
> * aarch64_get_qualifier_esize (opnds[0].qualifier) / 2;
> + else if (opcode->iclass == lut)
> + {
> + size = get_operand_fields_width (get_operand_from_code (type)) - 5;
> + if (!check_reglane (opnd, mismatch_detail, idx, "v", 0, 31,
> + 0, (1 << size) - 1))
> + return 0;
> + break;
> + }
> else
> num = 16;
> num = num / aarch64_get_qualifier_esize (qualifier) - 1;
> @@ -4069,6 +4083,14 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
> style_imm (styler, "%" PRIi64, opnd->reglane.index));
> break;
>
> + case AARCH64_OPND_Em_INDEX1_14:
> + case AARCH64_OPND_Em_INDEX2_13:
> + case AARCH64_OPND_Em_INDEX3_12:
> + snprintf (buf, size, "%s[%s]",
> + style_reg (styler, "v%d", opnd->reglane.regno),
> + style_imm (styler, "%" PRIi64, opnd->reglane.index));
> + break;
> +
> case AARCH64_OPND_VdD1:
> case AARCH64_OPND_VnD1:
> snprintf (buf, size, "%s[%s]",
> @@ -4077,6 +4099,7 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
> break;
>
> case AARCH64_OPND_LVn:
> + case AARCH64_OPND_LVn_LUT:
> case AARCH64_OPND_LVt:
> case AARCH64_OPND_LVt_AL:
> case AARCH64_OPND_LEt:
> diff --git a/opcodes/aarch64-tbl.h b/opcodes/aarch64-tbl.h
> index 5b1c8561ac6147e64ba99b6e9fba85ed8ee712c4..6d7aa3d770ad34071bfe67f95d974eaa7b6cdbbd 100644
> --- a/opcodes/aarch64-tbl.h
> +++ b/opcodes/aarch64-tbl.h
> @@ -1004,6 +1004,24 @@
> QLF3(V_16B, V_16B, V_16B), \
> }
>
> +/* e.g. luti2 <Vd>.16B, { <Vn>.16B }, <Vm>[index]. */
> +/* The third operand is an AdvSIMD vector with a bit index
> + and without a type qualifier and is checked separately
> + based on operand enum. */
> +#define QL_VVUB \
> +{ \
> + QLF3(V_16B , V_16B , NIL), \
> +}
> +
> +/* e.g. luti2 <Vd>.8H, { <Vn>.8H }, <Vm>[index]. */
> +/* The third operand is an AdvSIMD vector with a bit index
> + and without a type qualifier and is checked separately
> + based on operand enum. */
> +#define QL_VVUH \
> +{ \
> + QLF3(V_8H , V_8H , NIL), \
> +}
> +
> /* e.g. EXT <Vd>.<T>, <Vn>.<T>, <Vm>.<T>, #<index>. */
> #define QL_VEXT \
> { \
> @@ -2669,6 +2687,8 @@ static const aarch64_feature_set aarch64_feature_faminmax_sve2 =
> AARCH64_FEATURES (2, FAMINMAX, SVE2);
> static const aarch64_feature_set aarch64_feature_faminmax_sme2 =
> AARCH64_FEATURES (3, SVE2, FAMINMAX, SME2);
> +static const aarch64_feature_set aarch64_feature_lut =
> + AARCH64_FEATURE (LUT);
>
> #define CORE &aarch64_feature_v8
> #define FP &aarch64_feature_fp
> @@ -2740,6 +2760,7 @@ static const aarch64_feature_set aarch64_feature_faminmax_sme2 =
> #define FAMINMAX &aarch64_feature_faminmax
> #define FAMINMAX_SVE2 &aarch64_feature_faminmax_sve2
> #define FAMINMAX_SME2 &aarch64_feature_faminmax_sme2
> +#define LUT &aarch64_feature_lut
>
> #define CORE_INSN(NAME,OPCODE,MASK,CLASS,OP,OPS,QUALS,FLAGS) \
> { NAME, OPCODE, MASK, CLASS, OP, CORE, OPS, QUALS, FLAGS, 0, 0, NULL }
> @@ -2925,6 +2946,8 @@ static const aarch64_feature_set aarch64_feature_faminmax_sme2 =
> #define FAMINMAX_SME2_INSN(NAME,OPCODE,MASK,OPS,QUALS) \
> { NAME, OPCODE, MASK, sme_size_22_hsd, 0, FAMINMAX_SME2, OPS, QUALS, \
> F_STRICT | 0, 0, 1, NULL }
> +#define LUT_INSN(NAME,OPCODE,MASK,OPS,QUALS,FLAGS) \
> + { NAME, OPCODE, MASK, lut, 0, LUT, OPS, QUALS, FLAGS, 0, 0, NULL }
>
> #define MOPS_CPY_OP1_OP2_PME_INSN(NAME, OPCODE, MASK, FLAGS, CONSTRAINTS) \
> MOPS_INSN (NAME, OPCODE, MASK, 0, \
> @@ -4275,6 +4298,11 @@ const struct aarch64_opcode aarch64_opcode_table[] =
> FAMINMAX_SME2_INSN ("famax", 0xc120b940, 0xff23ffe3, OP3 (SME_Zdnx4, SME_Zdnx4, SME_Zmx4), OP_SVE_VVV_HSD),
> FAMINMAX_SME2_INSN ("famin", 0xc120b141, 0xff21ffe1, OP3 (SME_Zdnx2, SME_Zdnx2, SME_Zmx2), OP_SVE_VVV_HSD),
> FAMINMAX_SME2_INSN ("famin", 0xc120b941, 0xff23ffe3, OP3 (SME_Zdnx4, SME_Zdnx4, SME_Zmx4), OP_SVE_VVV_HSD),
> + /* AdvSIMD lut. */
> + LUT_INSN ("luti2", 0x4e801000, 0xffe09c00, OP3 (Vd, LVn_LUT, Em_INDEX2_13), QL_VVUB, F_OD(1)),
> + LUT_INSN ("luti2", 0x4ec00000, 0xffe08c00, OP3 (Vd, LVn_LUT, Em_INDEX3_12), QL_VVUH, F_OD(1)),
> + LUT_INSN ("luti4", 0x4e402000, 0xffe0bc00, OP3 (Vd, LVn_LUT, Em_INDEX1_14), QL_VVUB, F_OD(1)),
> + LUT_INSN ("luti4", 0x4e401000, 0xffe09c00, OP3 (Vd, LVn_LUT, Em_INDEX2_13), QL_VVUH, F_OD(2)),
> /* Move wide (immediate). */
> CORE_INSN ("movn", 0x12800000, 0x7f800000, movewide, OP_MOVN, OP2 (Rd, HALF), QL_DST_R, F_SF | F_HAS_ALIAS),
> CORE_INSN ("mov", 0x12800000, 0x7f800000, movewide, OP_MOV_IMM_WIDEN, OP2 (Rd, IMM_MOV), QL_DST_R, F_SF | F_ALIAS | F_CONV),
> @@ -6531,12 +6559,20 @@ const struct aarch64_opcode aarch64_opcode_table[] =
> "a SIMD vector element") \
> Y(SIMD_ELEMENT, reglane, "Em16", 0, F(FLD_Rm), \
> "a SIMD vector element limited to V0-V15") \
> + Y(SIMD_ELEMENT, reglane, "Em_INDEX1_14", 0, F(FLD_Rm, FLD_imm1_14), \
> + "a SIMD vector without a type qualifier encoding a bit index") \
> + Y(SIMD_ELEMENT, reglane, "Em_INDEX2_13", 0, F(FLD_Rm, FLD_imm2_13), \
> + "a SIMD vector without a type qualifier encoding a bit index") \
> + Y(SIMD_ELEMENT, reglane, "Em_INDEX3_12", 0, F(FLD_Rm, FLD_imm3_12), \
> + "a SIMD vector without a type qualifier encoding a bit index") \
I think this is a better fit for simple_index (instead of reglane). See also
how the existing SME luti operands work. Unless I've missed something, using
simple_index would mean that you don't need to edit the inserter or extractor
functions.
> Y(SIMD_REGLIST, reglist, "LVn", 0, F(FLD_Rn), \
> "a SIMD vector register list") \
> Y(SIMD_REGLIST, ldst_reglist, "LVt", 0, F(), \
> "a SIMD vector register list") \
> Y(SIMD_REGLIST, ldst_reglist_r, "LVt_AL", 0, F(), \
> "a SIMD vector register list") \
> + Y(SIMD_REGLIST, lut_reglist, "LVn_LUT", 0, F(FLD_Rn), \
> + "a SIMD vector register list") \
> Y(SIMD_REGLIST, ldst_elemlist, "LEt", 0, F(), \
> "a SIMD vector element list") \
> Y(IMMEDIATE, imm, "CRn", 0, F(FLD_CRn), \
next prev parent reply other threads:[~2024-05-21 13:58 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-05-16 10:35 Saurabh Jha
2024-05-20 13:05 ` Richard Earnshaw (lists)
2024-05-21 12:58 ` Saurabh Jha
2024-05-21 13:57 ` Andrew Carlotti [this message]
2024-05-22 10:17 ` Saurabh Jha
2024-05-23 15:58 ` Andrew Carlotti
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=7ad78811-fb9e-7518-72ec-d4d5885f756e@e124511.cambridge.arm.com \
--to=andrew.carlotti@arm.com \
--cc=binutils@sourceware.org \
--cc=richard.earnshaw@arm.com \
--cc=saurabh.jha@arm.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).