[PATCH v6 3/4] gas, aarch64: Add SVE2 lut extension

Saurabh Jha saurabh.jha@arm.com
Tue May 28 14:57:17 GMT 2024



On 5/23/2024 5:34 PM, Andrew Carlotti wrote:
> On Thu, May 23, 2024 at 02:50:18PM +0100, Saurabh Jha wrote:
>>
>> Introduces instructions for the SVE2 lut extension for AArch64. They are documented in the following links:
>> * luti2: https://developer.arm.com/documentation/ddi0602/2024-03/SVE-Instructions/LUTI2--Lookup-table-read-with-2-bit-indices-?lang=en
>> * luti4: https://developer.arm.com/documentation/ddi0602/2024-03/SVE-Instructions/LUTI4--Lookup-table-read-with-4-bit-indices-?lang=en
>>
>> These instructions use new SVE2 vector operands. They are called
>> SVE_Zm1_23_INDEX, SVE_Zm2_22_INDEX, and Zm3_12_INDEX and they have
>> 1 bit, 2 bit, and 3 bit indices respectively.
>>
>> For these new operands, we defined a new inserter and a new extractor.
>>
>> The lsb and width of these new 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.
>>
>> We made a design choice for the second operand of the halfword variant of
>> luti4 with two register tables. We could have either defined a new operand,
>> like SVE_Znx2, or we could have use the existing operand SVE_ZnxN. With
>> the new operand, we would need to implement constraints on register
>> lists based on either operand or opcode flag. With existing operand, we
>> could just existing constraint checks using opcode flag. We chose
>> the second approach and went with SVE_ZnxN and added opcode flag to
>> enforce lengths of vector register list operands. This way, we can reuse
>> the existing constraint check logic.
>> ---
>> 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
>> ---
>>   gas/config/tc-aarch64.c                      |   3 +
>>   gas/testsuite/gas/aarch64/sme2-8-invalid.l   |   2 +-
>>   gas/testsuite/gas/aarch64/sve2-lut-bad.d     |   3 +
>>   gas/testsuite/gas/aarch64/sve2-lut-bad.l     |  34 +++
>>   gas/testsuite/gas/aarch64/sve2-lut-illegal.d |   3 +
>>   gas/testsuite/gas/aarch64/sve2-lut-illegal.l | 212 +++++++++++++++++++
>>   gas/testsuite/gas/aarch64/sve2-lut-illegal.s | 128 +++++++++++
>>   gas/testsuite/gas/aarch64/sve2-lut.d         |  41 ++++
>>   gas/testsuite/gas/aarch64/sve2-lut.s         |  39 ++++
>>   include/opcode/aarch64.h                     |   3 +
>>   opcodes/aarch64-asm.c                        |  11 +
>>   opcodes/aarch64-asm.h                        |   1 +
>>   opcodes/aarch64-dis.c                        |  11 +
>>   opcodes/aarch64-dis.h                        |   1 +
>>   opcodes/aarch64-opc.c                        |  25 +++
>>   opcodes/aarch64-opc.h                        |   4 +
>>   opcodes/aarch64-tbl.h                        |  36 +++-
>>   17 files changed, 555 insertions(+), 2 deletions(-)
>>   create mode 100644 gas/testsuite/gas/aarch64/sve2-lut-bad.d
>>   create mode 100644 gas/testsuite/gas/aarch64/sve2-lut-bad.l
>>   create mode 100644 gas/testsuite/gas/aarch64/sve2-lut-illegal.d
>>   create mode 100644 gas/testsuite/gas/aarch64/sve2-lut-illegal.l
>>   create mode 100644 gas/testsuite/gas/aarch64/sve2-lut-illegal.s
>>   create mode 100644 gas/testsuite/gas/aarch64/sve2-lut.d
>>   create mode 100644 gas/testsuite/gas/aarch64/sve2-lut.s
>>
> 
>> diff --git a/gas/config/tc-aarch64.c b/gas/config/tc-aarch64.c
>> index 41547866d2c..fec17c40a43 100644
>> --- a/gas/config/tc-aarch64.c
>> +++ b/gas/config/tc-aarch64.c
>> @@ -6784,7 +6784,10 @@ parse_operands (char *str, const aarch64_opcode *opcode)
>>   	  info->qualifier = AARCH64_OPND_QLF_S_D;
>>   	  break;
>>   
>> +	case AARCH64_OPND_SVE_Zm1_23_INDEX:
>> +	case AARCH64_OPND_SVE_Zm2_22_INDEX:
>>   	case AARCH64_OPND_SVE_Zm3_INDEX:
>> +	case AARCH64_OPND_SVE_Zm3_12_INDEX:
>>   	case AARCH64_OPND_SVE_Zm3_22_INDEX:
>>   	case AARCH64_OPND_SVE_Zm3_19_INDEX:
>>   	case AARCH64_OPND_SVE_Zm3_11_INDEX:
>> diff --git a/gas/testsuite/gas/aarch64/sme2-8-invalid.l b/gas/testsuite/gas/aarch64/sme2-8-invalid.l
>> index afea8bb6735..aa393657c4b 100644
>> --- a/gas/testsuite/gas/aarch64/sme2-8-invalid.l
>> +++ b/gas/testsuite/gas/aarch64/sme2-8-invalid.l
>> @@ -128,7 +128,7 @@
>>   [^ :]+:[0-9]+: Info:    	luti2 {z0\.h-z3\.h}, zt0, z0\[0\]
>>   [^ :]+:[0-9]+: Info:    	luti2 {z0\.s-z3\.s}, zt0, z0\[0\]
>>   [^ :]+:[0-9]+: Error: expected a register or register list at operand 1 -- `luti4 0,zt0,z0\[0\]'
>> -[^ :]+:[0-9]+: Error: expected a register at operand 2 -- `luti4 z0\.b,0,z0\[0\]'
>> +[^ :]+:[0-9]+: Error: expected a register or register list at operand 2 -- `luti4 z0\.b,0,z0\[0\]'
>>   [^ :]+:[0-9]+: Error: expected an SVE vector register at operand 3 -- `luti4 z0\.b,zt0,0'
>>   [^ :]+:[0-9]+: Error: register element index out of range 0 to 7 at operand 3 -- `luti4 z0\.h,zt0,z0\[-1\]'
>>   [^ :]+:[0-9]+: Error: register element index out of range 0 to 7 at operand 3 -- `luti4 z0\.h,zt0,z0\[8\]'
>> diff --git a/gas/testsuite/gas/aarch64/sve2-lut-bad.d b/gas/testsuite/gas/aarch64/sve2-lut-bad.d
>> new file mode 100644
>> index 00000000000..1134589dc86
>> --- /dev/null
>> +++ b/gas/testsuite/gas/aarch64/sve2-lut-bad.d
>> @@ -0,0 +1,3 @@
>> +#as: -march=armv8-a+lut
>> +#source: sve2-lut.s
>> +#error_output: sve2-lut-bad.l
>> \ No newline at end of file
>> diff --git a/gas/testsuite/gas/aarch64/sve2-lut-bad.l b/gas/testsuite/gas/aarch64/sve2-lut-bad.l
>> new file mode 100644
>> index 00000000000..8bbdc3e8518
>> --- /dev/null
>> +++ b/gas/testsuite/gas/aarch64/sve2-lut-bad.l
>> @@ -0,0 +1,34 @@
>> +[^ :]+: Assembler messages:
>> +.*: Error: selected processor does not support `luti2 z0.b,{z0.b},z0\[0\]'
>> +.*: Error: selected processor does not support `luti2 z31.b,{z0.b},z0\[0\]'
>> +.*: Error: selected processor does not support `luti2 z0.b,{z31.b},z0\[0\]'
>> +.*: Error: selected processor does not support `luti2 z0.b,{z0.b},z31\[0\]'
>> +.*: Error: selected processor does not support `luti2 z0.b,{z0.b},z0\[3\]'
>> +.*: Error: selected processor does not support `luti2 z4.b,{z9.b},z15\[2\]'
>> +.*: Error: selected processor does not support `luti2 z0.h,{z0.h},z0\[0\]'
>> +.*: Error: selected processor does not support `luti2 z31.h,{z0.h},z0\[0\]'
>> +.*: Error: selected processor does not support `luti2 z0.h,{z31.h},z0\[0\]'
>> +.*: Error: selected processor does not support `luti2 z0.h,{z0.h},z31\[0\]'
>> +.*: Error: selected processor does not support `luti2 z0.h,{z0.h},z0\[7\]'
>> +.*: Error: selected processor does not support `luti2 z4.h,{z9.h},z15\[2\]'
>> +.*: Error: selected processor does not support `luti2 z4.h,{z9.h},z15\[1\]'
>> +.*: Error: selected processor does not support `luti2 z4.h,{z9.h},z15\[4\]'
>> +.*: Error: selected processor does not support `luti4 z0.b,{z0.b},z0\[0\]'
>> +.*: Error: selected processor does not support `luti4 z31.b,{z0.b},z0\[0\]'
>> +.*: Error: selected processor does not support `luti4 z0.b,{z31.b},z0\[0\]'
>> +.*: Error: selected processor does not support `luti4 z0.b,{z0.b},z31\[0\]'
>> +.*: Error: selected processor does not support `luti4 z0.b,{z0.b},z0\[1\]'
>> +.*: Error: selected processor does not support `luti4 z4.b,{z9.b},z15\[1\]'
>> +.*: Error: selected processor does not support `luti4 z0.h,{z0.h},z0\[0\]'
>> +.*: Error: selected processor does not support `luti4 z31.h,{z0.h},z0\[0\]'
>> +.*: Error: selected processor does not support `luti4 z0.h,{z30.h},z0\[0\]'
>> +.*: Error: selected processor does not support `luti4 z0.h,{z0.h},z31\[0\]'
>> +.*: Error: selected processor does not support `luti4 z0.h,{z0.h},z0\[3\]'
>> +.*: Error: selected processor does not support `luti4 z4.h,{z9.h},z15\[2\]'
>> +.*: Error: selected processor does not support `luti4 z0.h,{z0.h,z1.h},z0\[0\]'
>> +.*: Error: selected processor does not support `luti4 z31.h,{z0.h,z1.h},z0\[0\]'
>> +.*: Error: selected processor does not support `luti4 z0.h,{z30.h,z31.h},z0\[0\]'
>> +.*: Error: selected processor does not support `luti4 z0.h,{z31.h,z0.h},z0\[0\]'
>> +.*: Error: selected processor does not support `luti4 z0.h,{z0.h,z1.h},z31\[0\]'
>> +.*: Error: selected processor does not support `luti4 z0.h,{z0.h,z1.h},z0\[3\]'
>> +.*: Error: selected processor does not support `luti4 z4.h,{z9.h,z10.h},z15\[2\]'
>> diff --git a/gas/testsuite/gas/aarch64/sve2-lut-illegal.d b/gas/testsuite/gas/aarch64/sve2-lut-illegal.d
>> new file mode 100644
>> index 00000000000..542096321b0
>> --- /dev/null
>> +++ b/gas/testsuite/gas/aarch64/sve2-lut-illegal.d
>> @@ -0,0 +1,3 @@
>> +#as: -march=armv8-a+lut+sve2
>> +#source: sve2-lut-illegal.s
>> +#error_output: sve2-lut-illegal.l
>> \ No newline at end of file
>> diff --git a/gas/testsuite/gas/aarch64/sve2-lut-illegal.l b/gas/testsuite/gas/aarch64/sve2-lut-illegal.l
>> new file mode 100644
>> index 00000000000..bd6e41937d1
>> --- /dev/null
>> +++ b/gas/testsuite/gas/aarch64/sve2-lut-illegal.l
>> @@ -0,0 +1,212 @@
>> +[^ :]+: Assembler messages:
>> +[^ :]+:[0-9]+: Error: operand mismatch -- `luti2 z2\.b,\{z5\.h\},z7\[1\]'
>> +[^ :]+:[0-9]+: Info:    did you mean this\?
>> +[^ :]+:[0-9]+: Info:    	luti2 z2\.b, \{z5\.b\}, z7\[1\]
>> +[^ :]+:[0-9]+: Error: operand mismatch -- `luti2 z2\.h,\{z5\.b\},z7\[1\]'
>> +[^ :]+:[0-9]+: Info:    did you mean this\?
>> +[^ :]+:[0-9]+: Info:    	luti2 z2\.b, \{z5\.b\}, z7\[1\]
>> +[^ :]+:[0-9]+: Error: operand mismatch -- `luti4 z2\.b,\{z5\.h\},z7\[1\]'
>> +[^ :]+:[0-9]+: Info:    did you mean this\?
>> +[^ :]+:[0-9]+: Info:    	luti4 z2\.b, \{z5\.b\}, z7\[1\]
>> +[^ :]+:[0-9]+: Error: operand mismatch -- `luti4 z2\.h,\{z5\.b\},z7\[1\]'
>> +[^ :]+:[0-9]+: Info:    did you mean this\?
>> +[^ :]+:[0-9]+: Info:    	luti4 z2\.b, \{z5\.b\}, z7\[1\]
>> +[^ :]+:[0-9]+: Error: operand mismatch -- `luti4 z2\.b,\{z5\.h,z6\.h\},z12\[1\]'
>> +[^ :]+:[0-9]+: Info:    did you mean this\?
>> +[^ :]+:[0-9]+: Info:    	luti4 z2\.b, \{z5\.b-z6\.b\}, z12\[1\]
>> +[^ :]+:[0-9]+: Error: operand mismatch -- `luti4 z2\.h,\{z5\.b,z6\.b\},z12\[1\]'
>> +[^ :]+:[0-9]+: Info:    did you mean this\?
>> +[^ :]+:[0-9]+: Info:    	luti4 z2\.b, \{z5\.b-z6\.b\}, z12\[1\]
>> +[^ :]+:[0-9]+: Error: type mismatch in vector register list at operand 2 -- `luti4 z2\.b,\{z5\.b,z6\.h\},z12\[1\]'
>> +[^ :]+:[0-9]+: Error: type mismatch in vector register list at operand 2 -- `luti4 z2\.h,\{z5\.h,z6\.b\},z12\[1\]'
>> +[^ :]+:[0-9]+: Error: syntax error in register list at operand 2 -- `luti2 z5\.b,\{\},z7\[1\]'
>> +[^ :]+:[0-9]+:  Info: macro invoked from here
>> +[^ :]+:[0-9]+: Error: unexpected register type at operand 2 -- `luti2 \{z5\.b\},z6\.b,z7\[1\]'
>> +[^ :]+:[0-9]+:  Info: macro invoked from here
>> +[^ :]+:[0-9]+: Error: expected a single-register list at operand 2 -- `luti2 z5\.b,\{z7\.b,z8\.b\},z9\[1\]'
>> +[^ :]+:[0-9]+:  Info: macro invoked from here
>> +[^ :]+:[0-9]+: Error: syntax error in register list at operand 2 -- `luti2 z5\.h,\{\},z7\[1\]'
>> +[^ :]+:[0-9]+:  Info: macro invoked from here
>> +[^ :]+:[0-9]+: Error: unexpected register type at operand 2 -- `luti2 \{z5\.h\},z6\.h,z7\[1\]'
>> +[^ :]+:[0-9]+:  Info: macro invoked from here
>> +[^ :]+:[0-9]+: Error: expected a single-register list at operand 2 -- `luti2 z5\.h,\{z7\.h,z8\.h\},z9\[1\]'
>> +[^ :]+:[0-9]+:  Info: macro invoked from here
>> +[^ :]+:[0-9]+: Error: syntax error in register list at operand 2 -- `luti4 z5\.b,\{\},z7\[1\]'
>> +[^ :]+:[0-9]+:  Info: macro invoked from here
>> +[^ :]+:[0-9]+: Error: unexpected register type at operand 2 -- `luti4 \{z5\.b\},z6\.b,z7\[1\]'
>> +[^ :]+:[0-9]+:  Info: macro invoked from here
>> +[^ :]+:[0-9]+: Error: expected a single-register list at operand 2 -- `luti4 z5\.b,\{z7\.b,z8\.b\},z9\[1\]'
>> +[^ :]+:[0-9]+:  Info: macro invoked from here
>> +[^ :]+:[0-9]+: Error: syntax error in register list at operand 2 -- `luti4 z5\.h,\{\},z7\[1\]'
>> +[^ :]+:[0-9]+: Error: unexpected register type at operand 2 -- `luti4 \{z5\.h\},z6\.h,z7\[1\]'
>> +[^ :]+:[0-9]+: Error: the register list must have a stride of 1 at operand 2 -- `luti4 z5\.h,\{z7\.h,z9\.h\},z3\[3\]'
>> +[^ :]+:[0-9]+: Error: operand mismatch -- `luti2 z5\.s,\{z7\.s\},z9\[1\]'
>> +[^ :]+:[0-9]+: Info:    did you mean this\?
>> +[^ :]+:[0-9]+: Info:    	luti2 z5\.b, \{z7\.b\}, z9\[1\]
>> +[^ :]+:[0-9]+: Error: operand mismatch -- `luti4 z5\.s,\{z7\.s\},z9\[1\]'
>> +[^ :]+:[0-9]+: Info:    did you mean this\?
>> +[^ :]+:[0-9]+: Info:    	luti4 z5\.b, \{z7\.b\}, z9\[1\]
>> +[^ :]+:[0-9]+: Error: operand mismatch -- `luti4 z5\.s,\{z7\.s,z8\.s\},z9\[1\]'
>> +[^ :]+:[0-9]+: Info:    did you mean this\?
>> +[^ :]+:[0-9]+: Info:    	luti4 z5\.b, \{z7\.b-z8\.b\}, z9\[1\]
>> +[^ :]+:[0-9]+: Error: comma expected between operands at operand 2 -- `luti2 z5\.b'
>> +[^ :]+:[0-9]+:  Info: macro invoked from here
>> +[^ :]+:[0-9]+: Error: comma expected between operands at operand 3 -- `luti2 z5\.b,\{z7\.b\}'
>> +[^ :]+:[0-9]+:  Info: macro invoked from here
>> +[^ :]+:[0-9]+: Error: unexpected characters following instruction at operand 3 -- `luti2 z5\.b,\{z7\.b\},z9\[1\],z11\.b'
>> +[^ :]+:[0-9]+:  Info: macro invoked from here
>> +[^ :]+:[0-9]+: Error: comma expected between operands at operand 2 -- `luti2 z5\.h'
>> +[^ :]+:[0-9]+:  Info: macro invoked from here
>> +[^ :]+:[0-9]+: Error: comma expected between operands at operand 3 -- `luti2 z5\.h,\{z7\.h\}'
>> +[^ :]+:[0-9]+:  Info: macro invoked from here
>> +[^ :]+:[0-9]+: Error: unexpected characters following instruction at operand 3 -- `luti2 z5\.h,\{z7\.h\},z9\[1\],z11\.h'
>> +[^ :]+:[0-9]+:  Info: macro invoked from here
>> +[^ :]+:[0-9]+: Error: comma expected between operands at operand 2 -- `luti4 z5\.b'
>> +[^ :]+:[0-9]+:  Info: macro invoked from here
>> +[^ :]+:[0-9]+: Error: comma expected between operands at operand 3 -- `luti4 z5\.b,\{z7\.b\}'
>> +[^ :]+:[0-9]+:  Info: macro invoked from here
>> +[^ :]+:[0-9]+: Error: unexpected characters following instruction at operand 3 -- `luti4 z5\.b,\{z7\.b\},z9\[1\],z11\.b'
>> +[^ :]+:[0-9]+:  Info: macro invoked from here
>> +[^ :]+:[0-9]+: Error: comma expected between operands at operand 2 -- `luti4 z5\.h'
>> +[^ :]+:[0-9]+: Error: comma expected between operands at operand 3 -- `luti4 z5\.h,\{z7\.h\}'
>> +[^ :]+:[0-9]+: Error: unexpected characters following instruction at operand 3 -- `luti4 z5\.h,\{z7\.h\},z9\[1\],z11\.h'
>> +[^ :]+:[0-9]+: Error: comma expected between operands at operand 3 -- `luti4 z5\.h,\{z7\.h,z8\.h\}'
>> +[^ :]+:[0-9]+: Error: unexpected characters following instruction at operand 3 -- `luti4 z5\.h,\{z7\.h,z8\.h\},z9\[1\],z11\.h'
>> +[^ :]+:[0-9]+: Error: unexpected character `t' in element size at operand 1 -- `luti2 z5\.t,\{z7\.b},z9\[1\]'
>> +[^ :]+:[0-9]+:  Info: macro invoked from here
>> +[^ :]+:[0-9]+: Error: unexpected character `t' in element size at operand 2 -- `luti2 z5\.b,\{z7\.t},z9\[1\]'
>> +[^ :]+:[0-9]+:  Info: macro invoked from here
>> +[^ :]+:[0-9]+: Error: operand 3 must be an indexed SVE vector register -- `luti2 z5\.b,\{z7\.b},z9\.b'
>> +[^ :]+:[0-9]+:  Info: macro invoked from here
>> +[^ :]+:[0-9]+: Error: unexpected character `t' in element size at operand 1 -- `luti2 z5\.t,\{z7\.h},z9\[1\]'
>> +[^ :]+:[0-9]+:  Info: macro invoked from here
>> +[^ :]+:[0-9]+: Error: unexpected character `t' in element size at operand 2 -- `luti2 z5\.h,\{z7\.t},z9\[1\]'
>> +[^ :]+:[0-9]+:  Info: macro invoked from here
>> +[^ :]+:[0-9]+: Error: operand 3 must be an indexed SVE vector register -- `luti2 z5\.h,\{z7\.h},z9\.h'
>> +[^ :]+:[0-9]+:  Info: macro invoked from here
>> +[^ :]+:[0-9]+: Error: unexpected character `t' in element size at operand 1 -- `luti4 z5\.t,\{z7\.b},z9\[1\]'
>> +[^ :]+:[0-9]+:  Info: macro invoked from here
>> +[^ :]+:[0-9]+: Error: unexpected character `t' in element size at operand 2 -- `luti4 z5\.b,\{z7\.t},z9\[1\]'
>> +[^ :]+:[0-9]+:  Info: macro invoked from here
>> +[^ :]+:[0-9]+: Error: operand 3 must be an indexed SVE vector register -- `luti4 z5\.b,\{z7\.b},z9\.b'
>> +[^ :]+:[0-9]+:  Info: macro invoked from here
>> +[^ :]+:[0-9]+: Error: unexpected character `t' in element size at operand 1 -- `luti4 z5\.t,\{z7\.h,z8\.h},z9\[1\]'
>> +[^ :]+:[0-9]+: Error: unexpected character `t' in element size at operand 2 -- `luti4 z5\.h,\{z7\.t,z8\.h},z9\[1\]'
>> +[^ :]+:[0-9]+: Error: unexpected character `t' in element size at operand 2 -- `luti4 z5\.h,\{z7\.h,z8\.t},z9\[1\]'
>> +[^ :]+:[0-9]+: Error: operand 3 must be an indexed SVE vector register -- `luti4 z5\.h,\{z7\.h,z8\.h},z9\.h'
>> +[^ :]+:[0-9]+: Error: expected a register or register list at operand 1 -- `luti2 5.b,\{z7.b\},z9\[1\]'
>> +[^ :]+:[0-9]+:  Info: macro invoked from here
>> +[^ :]+:[0-9]+: Error: missing type suffix at operand 2 -- `luti2 z5.b,\{z7\},z9\[1\]'
>> +[^ :]+:[0-9]+:  Info: macro invoked from here
>> +[^ :]+:[0-9]+: Error: syntax error in register list at operand 2 -- `luti2 z5.b,\{7.b\},z9\[1\]'
>> +[^ :]+:[0-9]+:  Info: macro invoked from here
>> +[^ :]+:[0-9]+: Error: expected an SVE vector register at operand 3 -- `luti2 z5.b,\{z7.b\},9\[1\]'
>> +[^ :]+:[0-9]+:  Info: macro invoked from here
>> +[^ :]+:[0-9]+: Error: expected a register or register list at operand 1 -- `luti2 5.h,\{z7.h\},z9\[1\]'
>> +[^ :]+:[0-9]+:  Info: macro invoked from here
>> +[^ :]+:[0-9]+: Error: missing type suffix at operand 2 -- `luti2 z5.h,\{z7\},z9\[1\]'
>> +[^ :]+:[0-9]+:  Info: macro invoked from here
>> +[^ :]+:[0-9]+: Error: syntax error in register list at operand 2 -- `luti2 z5.h,\{7.h\},z9\[1\]'
>> +[^ :]+:[0-9]+:  Info: macro invoked from here
>> +[^ :]+:[0-9]+: Error: expected an SVE vector register at operand 3 -- `luti2 z5.h,\{z7.h\},9\[1\]'
>> +[^ :]+:[0-9]+:  Info: macro invoked from here
>> +[^ :]+:[0-9]+: Error: expected a register or register list at operand 1 -- `luti4 5\.b,\{z7.b},z9\[1\]'
>> +[^ :]+:[0-9]+:  Info: macro invoked from here
>> +[^ :]+:[0-9]+: Error: missing type suffix at operand 2 -- `luti4 z5\.b,\{z7\},z9\[1\]'
>> +[^ :]+:[0-9]+:  Info: macro invoked from here
>> +[^ :]+:[0-9]+: Error: syntax error in register list at operand 2 -- `luti4 z5\.b,\{7\.b\},z9\[1\]'
>> +[^ :]+:[0-9]+:  Info: macro invoked from here
>> +[^ :]+:[0-9]+: Error: expected an SVE vector register at operand 3 -- `luti4 z5\.b,\{z7\.b\},9\[1\]'
>> +[^ :]+:[0-9]+:  Info: macro invoked from here
>> +[^ :]+:[0-9]+: Error: type mismatch in vector register list at operand 2 -- `luti4 z5\.h,\{z7,z8\.h\},z9\[1\]'
>> +[^ :]+:[0-9]+: Error: expected a register or register list at operand 1 -- `luti4 5\.h,\{z7\.h,z8\.h},z9\[1\]'
>> +[^ :]+:[0-9]+: Error: syntax error in register list at operand 2 -- `luti4 z5\.h,\{7\.h,z8\.h\},z9\[1\]'
>> +[^ :]+:[0-9]+: Error: expected an SVE vector register at operand 3 -- `luti4 z5\.h,\{z7\.h,z8\.h\},9\[1\]'
>> +[^ :]+:[0-9]+: Error: operand mismatch -- `luti2 z5\.b,\{z7\.b\},z9\.b\[2\]'
>> +[^ :]+:[0-9]+: Info:    did you mean this\?
>> +[^ :]+:[0-9]+: Info:    	luti2 z5\.b, \{z7\.b\}, z9\[2\]
>> +[^ :]+:[0-9]+: Error: operand mismatch -- `luti2 z5\.h,\{z7\.h\},z9\.h\[2\]'
>> +[^ :]+:[0-9]+: Info:    did you mean this\?
>> +[^ :]+:[0-9]+: Info:    	luti2 z5\.h, \{z7\.h\}, z9\[2\]
>> +[^ :]+:[0-9]+: Error: operand mismatch -- `luti4 z5\.b,\{z7\.b\},z9\.b\[1\]'
>> +[^ :]+:[0-9]+: Info:    did you mean this\?
>> +[^ :]+:[0-9]+: Info:    	luti4 z5\.b, \{z7\.b\}, z9\[1\]
>> +[^ :]+:[0-9]+: Error: operand mismatch -- `luti4 z5\.h,\{z7\.h\},z9\.h\[2\]'
>> +[^ :]+:[0-9]+: Info:    did you mean this\?
>> +[^ :]+:[0-9]+: Info:    	luti4 z5\.h, \{z7\.h\}, z9\[2\]
>> +[^ :]+:[0-9]+: Error: operand mismatch -- `luti4 z5\.h,\{z7\.h,z8\.h\},z9\.h\[2\]'
>> +[^ :]+:[0-9]+: Info:    did you mean this\?
>> +[^ :]+:[0-9]+: Info:    	luti4 z5\.h, \{z7\.h-z8\.h\}, z9\[2\]
>> +[^ :]+:[0-9]+: Error: missing braces at operand 1 -- `luti2 z4\.b\[2\],\{z9\.b\},z15'
>> +[^ :]+:[0-9]+:  Info: macro invoked from here
>> +[^ :]+:[0-9]+: Error: missing braces at operand 1 -- `luti2 z4\[2\],\{z9\.b\},z15'
>> +[^ :]+:[0-9]+:  Info: macro invoked from here
>> +[^ :]+:[0-9]+: Error: index not allowed inside register list at operand 2 -- `luti2 z4.b,\{z9.b\[2\]\},z15'
>> +[^ :]+:[0-9]+:  Info: macro invoked from here
>> +[^ :]+:[0-9]+: Error: missing braces at operand 1 -- `luti2 z4\[2\],\{z9\[2\]\},z15'
>> +[^ :]+:[0-9]+:  Info: macro invoked from here
>> +[^ :]+:[0-9]+: Error: missing braces at operand 1 -- `luti2 z4\.h\[2\],\{z9\.h\},z15'
>> +[^ :]+:[0-9]+:  Info: macro invoked from here
>> +[^ :]+:[0-9]+: Error: missing braces at operand 1 -- `luti2 z4\[2\],\{z9\.h\},z15'
>> +[^ :]+:[0-9]+:  Info: macro invoked from here
>> +[^ :]+:[0-9]+: Error: index not allowed inside register list at operand 2 -- `luti2 z4.h,\{z9.h\[2\]\},z15'
>> +[^ :]+:[0-9]+:  Info: macro invoked from here
>> +[^ :]+:[0-9]+: Error: missing braces at operand 1 -- `luti2 z4\[2\],\{z9\[2\]\},z15'
>> +[^ :]+:[0-9]+:  Info: macro invoked from here
>> +[^ :]+:[0-9]+: Error: missing braces at operand 1 -- `luti4 z4\.b\[2\],\{z9\.b\},z15'
>> +[^ :]+:[0-9]+:  Info: macro invoked from here
>> +[^ :]+:[0-9]+: Error: missing braces at operand 1 -- `luti4 z4\[2\],\{z9\.b\},z15'
>> +[^ :]+:[0-9]+:  Info: macro invoked from here
>> +[^ :]+:[0-9]+: Error: index not allowed inside register list at operand 2 -- `luti4 z4.b,\{z9.b\[2\]\},z15'
>> +[^ :]+:[0-9]+:  Info: macro invoked from here
>> +[^ :]+:[0-9]+: Error: missing braces at operand 1 -- `luti4 z4\[2\],\{z9\[2\]\},z15'
>> +[^ :]+:[0-9]+:  Info: macro invoked from here
>> +[^ :]+:[0-9]+: Error: missing braces at operand 1 -- `luti4 z4\.h\[2\],\{z9.h,z10.h\},z15'
>> +[^ :]+:[0-9]+: Error: missing braces at operand 1 -- `luti4 z4\[2\],\{z9.h,z10.h\},z15'
>> +[^ :]+:[0-9]+: Error: index not allowed inside register list at operand 2 -- `luti4 z4.h,\{z9.h,z10.h\[2\]\},z15'
>> +[^ :]+:[0-9]+: Error: missing braces at operand 1 -- `luti4 z4\[2\],\{z9,z10\[2\]\},z15'
>> +[^ :]+:[0-9]+: Error: operand 3 must be an indexed SVE vector register -- `luti2 z4.b,\{z9.b\},z15.b'
>> +[^ :]+:[0-9]+: Error: operand 3 must be an indexed SVE vector register -- `luti2 z4.b,\{z9.b\},z15'
>> +[^ :]+:[0-9]+: Error: operand 3 must be an indexed SVE vector register -- `luti2 z4.h,\{z9.h\},z15.h'
>> +[^ :]+:[0-9]+: Error: operand 3 must be an indexed SVE vector register -- `luti2 z4.h,\{z9.h\},z15'
>> +[^ :]+:[0-9]+: Error: operand 3 must be an indexed SVE vector register -- `luti4 z4.b,\{z9.b\},z15.b'
>> +[^ :]+:[0-9]+: Error: operand 3 must be an indexed SVE vector register -- `luti4 z4.b,\{z9.b\},z15'
>> +[^ :]+:[0-9]+: Error: operand 3 must be an indexed SVE vector register -- `luti4 z4.h,\{z9.h\},z15.h'
>> +[^ :]+:[0-9]+: Error: operand 3 must be an indexed SVE vector register -- `luti4 z4.h,\{z9.h\},z15'
>> +[^ :]+:[0-9]+: Error: operand 3 must be an indexed SVE vector register -- `luti4 z4.h,\{z9.h,z10.h\},z15.h'
>> +[^ :]+:[0-9]+: Error: operand 3 must be an indexed SVE vector register -- `luti4 z4.h,\{z9.h,z10.h\},z15'
>> +[^ :]+:[0-9]+: Error: expected a register or register list at operand 1 -- `luti2 z32.b,\{z9.b\},z15\[1\]'
>> +[^ :]+:[0-9]+:  Info: macro invoked from here
>> +[^ :]+:[0-9]+: Error: expected an SVE vector register at operand 2 -- `luti2 z4.b,\{z32.b\},z4\[1\]'
>> +[^ :]+:[0-9]+:  Info: macro invoked from here
>> +[^ :]+:[0-9]+: Error: expected an SVE vector register at operand 3 -- `luti2 z4.b,\{z9.b\},z32\[1\]'
>> +[^ :]+:[0-9]+:  Info: macro invoked from here
>> +[^ :]+:[0-9]+: Error: register element index out of range 0 to 3 at operand 3 -- `luti2 z2.b,\{z9.b\},z4\[4\]'
>> +[^ :]+:[0-9]+:  Info: macro invoked from here
>> +[^ :]+:[0-9]+: Error: register element index out of range 0 to 3 at operand 3 -- `luti2 z4.b,\{z9.b\},z15\[-1\]'
>> +[^ :]+:[0-9]+:  Info: macro invoked from here
>> +[^ :]+:[0-9]+: Error: expected a register or register list at operand 1 -- `luti2 z32.h,\{z9.h\},z15\[1\]'
>> +[^ :]+:[0-9]+:  Info: macro invoked from here
>> +[^ :]+:[0-9]+: Error: expected an SVE vector register at operand 2 -- `luti2 z4.h,\{z32.h\},z4\[1\]'
>> +[^ :]+:[0-9]+:  Info: macro invoked from here
>> +[^ :]+:[0-9]+: Error: expected an SVE vector register at operand 3 -- `luti2 z4.h,\{z9.h\},z32\[1\]'
>> +[^ :]+:[0-9]+:  Info: macro invoked from here
>> +[^ :]+:[0-9]+: Error: register element index out of range 0 to 7 at operand 3 -- `luti2 z2.h,\{z9.h\},z4\[8\]'
>> +[^ :]+:[0-9]+:  Info: macro invoked from here
>> +[^ :]+:[0-9]+: Error: register element index out of range 0 to 7 at operand 3 -- `luti2 z4.h,\{z9.h\},z15\[-1\]'
>> +[^ :]+:[0-9]+:  Info: macro invoked from here
>> +[^ :]+:[0-9]+: Error: expected a register or register list at operand 1 -- `luti4 z32.b,\{z9.b\},z15\[1\]'
>> +[^ :]+:[0-9]+:  Info: macro invoked from here
>> +[^ :]+:[0-9]+: Error: expected an SVE vector register at operand 2 -- `luti4 z4.b,\{z32.b\},z4\[1\]'
>> +[^ :]+:[0-9]+:  Info: macro invoked from here
>> +[^ :]+:[0-9]+: Error: expected an SVE vector register at operand 3 -- `luti4 z4.b,\{z9.b\},z32\[1\]'
>> +[^ :]+:[0-9]+:  Info: macro invoked from here
>> +[^ :]+:[0-9]+: Error: register element index out of range 0 to 1 at operand 3 -- `luti4 z2.b,\{z9.b\},z4\[2\]'
>> +[^ :]+:[0-9]+:  Info: macro invoked from here
>> +[^ :]+:[0-9]+: Error: register element index out of range 0 to 1 at operand 3 -- `luti4 z4.b,\{z9.b\},z15\[-1\]'
>> +[^ :]+:[0-9]+:  Info: macro invoked from here
>> +[^ :]+:[0-9]+: Error: expected a register or register list at operand 1 -- `luti4 z32.h,\{z9.h\},z4\[2\]'
>> +[^ :]+:[0-9]+: Error: expected an SVE vector register at operand 2 -- `luti4 z4.h,\{z32.h\},z15\[2\]'
>> +[^ :]+:[0-9]+: Error: expected an SVE vector register at operand 3 -- `luti4 z4.h,\{z9.h\},z32\[2\]'
>> +[^ :]+:[0-9]+: Error: register element index out of range 0 to 3 at operand 3 -- `luti4 z2.h,\{z9.h\},z15\[4\]'
>> +[^ :]+:[0-9]+: Error: register element index out of range 0 to 3 at operand 3 -- `luti4 z4.h,\{z9.h\},z15\[-1\]'
>> diff --git a/gas/testsuite/gas/aarch64/sve2-lut-illegal.s b/gas/testsuite/gas/aarch64/sve2-lut-illegal.s
>> new file mode 100644
>> index 00000000000..6be60e22823
>> --- /dev/null
>> +++ b/gas/testsuite/gas/aarch64/sve2-lut-illegal.s
>> @@ -0,0 +1,128 @@
>> +	// Operand mismatch
>> +	luti2	z2.b, { z5.h }, z7[1]
>> +	luti2	z2.h, { z5.b }, z7[1]
>> +	luti4	z2.b, { z5.h }, z7[1]
>> +	luti4	z2.h, { z5.b }, z7[1]
>> +	luti4	z2.b, { z5.h, z6.h }, z12[1]
>> +	luti4	z2.h, { z5.b, z6.b }, z12[1]
>> +	luti4	z2.b, { z5.b, z6.h }, z12[1]
>> +	luti4	z2.h, { z5.h, z6.b }, z12[1]
>> +
>> +	// Incorrect operands
>> +	.macro incorrect_operands, op, operand_type
>> +	\op	z5\operand_type, { }, z7[1]
>> +	\op	{ z5\operand_type }, z6\operand_type, z7[1]
>> +	\op	z5\operand_type, { z7\operand_type, z8\operand_type }, z9[1]
>> +	.endm
>> +
>> +	incorrect_operands luti2 .b
>> +	incorrect_operands luti2 .h
>> +	incorrect_operands luti4 .b
>> +	luti4	z5.h, { }, z7[1]
>> +	luti4	{ z5.h }, z6.h, z7[1]
>> +	luti4	z5.h, { z7.h, z9.h }, z3[3]
>> +
>> +	// Disallowed types
>> +	luti2	z5.s, { z7.s }, z9[1]
>> +	luti4	z5.s, { z7.s }, z9[1]
>> +	luti4	z5.s, { z7.s, z8.s }, z9[1]
>> +
>> +	// Incorrect number of operands
>> +	.macro incorrect_number_of_operands, op, operand_type
>> +	\op	z5\operand_type
>> +	\op	z5\operand_type, { z7\operand_type }
>> +	\op	z5\operand_type, { z7\operand_type }, z9[1], z11\operand_type
>> +	.endm
>> +	incorrect_number_of_operands luti2 .b
>> +	incorrect_number_of_operands luti2 .h
>> +	incorrect_number_of_operands luti4 .b
>> +	luti4	z5.h
>> +	luti4	z5.h, { z7.h }
>> +	luti4	z5.h, { z7.h }, z9[1], z11.h
>> +	luti4	z5.h, { z7.h, z8.h }
>> +	luti4	z5.h, { z7.h, z8.h }, z9[1], z11.h
>> +
>> +	// Spelling mistakes
>> +	.macro spelling_mistakes, op, operand_type
>> +	\op	z5.t, { z7\operand_type }, z9[1]
>> +	\op	z5\operand_type, { z7.t }, z9[1]
>> +	\op	z5\operand_type, { z7\operand_type }, z9\operand_type
>> +	.endm
>> +
>> +	spelling_mistakes luti2 .b
>> +	spelling_mistakes luti2 .h
>> +	spelling_mistakes luti4 .b
>> +	luti4	z5.t, { z7.h, z8.h }, z9[1]
>> +	luti4	z5.h, { z7.t, z8.h }, z9[1]
>> +	luti4	z5.h, { z7.h, z8.t }, z9[1]
>> +	luti4	z5.h, { z7.h, z8.h }, z9.h
>> +
>> +	// Missing qualifiers
>> +	.macro missing_qualifiers, op, operand_type
>> +	\op	5\operand_type, { z7\operand_type }, z9[1]
>> +	\op	z5\operand_type, { z7 }, z9[1]
>> +	\op	z5\operand_type, { 7\operand_type }, z9[1]
>> +	\op	z5\operand_type, { z7\operand_type }, 9[1]
>> +	.endm
>> +
>> +	missing_qualifiers luti2 .b
>> +	missing_qualifiers luti2 .h
>> +	missing_qualifiers luti4 .b
>> +	luti4	z5.h, { z7, z8.h }, z9[1]
>> +	luti4	5.h, { z7.h, z8.h }, z9[1]
>> +	luti4	z5.h, { 7.h, z8.h }, z9[1]
>> +	luti4	z5.h, { z7.h, z8.h }, 9[1]
>> +
>> +	// Index with qualifiers
>> +	luti2	z5.b, { z7.b }, z9.b[2]
>> +	luti2	z5.h, { z7.h }, z9.h[2]
>> +	luti4	z5.b, { z7.b }, z9.b[1]
>> +	luti4	z5.h, { z7.h }, z9.h[2]
>> +	luti4	z5.h, { z7.h, z8.h }, z9.h[2]
>> +
>> +	// Index on the wrong operand
>> +	.macro index_wrong_operand op, operand_type
>> +	\op	z4\operand_type[2], { z9\operand_type }, z15
>> +	\op	z4[2], { z9\operand_type }, z15
>> +	\op	z4\operand_type, { z9\operand_type[2] }, z15
>> +	\op	z4[2], { z9[2] }, z15
>> +	.endm
>> +
>> +	index_wrong_operand luti2 .b
>> +	index_wrong_operand luti2 .h
>> +	index_wrong_operand luti4 .b
>> +	luti4	z4.h[2], { z9.h, z10.h }, z15
>> +	luti4	z4[2], { z9.h, z10.h }, z15
>> +	luti4	z4.h, { z9.h, z10.h[2] }, z15
>> +	luti4	z4[2], { z9, z10[2] }, z15
>> +
>> +	// Missing index
>> +	luti2	z4.b, { z9.b }, z15.b
>> +	luti2	z4.b, { z9.b }, z15
>> +	luti2	z4.h, { z9.h }, z15.h
>> +	luti2	z4.h, { z9.h }, z15
>> +
>> +	luti4	z4.b, { z9.b }, z15.b
>> +	luti4	z4.b, { z9.b }, z15
>> +	luti4	z4.h, { z9.h }, z15.h
>> +	luti4	z4.h, { z9.h }, z15
>> +	luti4	z4.h, { z9.h, z10.h }, z15.h
>> +	luti4	z4.h, { z9.h, z10.h }, z15
>> +
>> +	// Out of range numbers
>> +	.macro out_of_range op, operand_type, max_index_plus_one
>> +	\op	z32\operand_type, { z9\operand_type }, z15[1]
>> +	\op	z4\operand_type, { z32\operand_type }, z4[1]
>> +	\op	z4\operand_type, { z9\operand_type }, z32[1]
>> +	\op	z2\operand_type, { z9\operand_type }, z4[\max_index_plus_one]
>> +	\op	z4\operand_type, { z9\operand_type }, z15[-1]
>> +	.endm
>> +
>> +	out_of_range luti2, .b, 4
>> +	out_of_range luti2, .h, 8
>> +	out_of_range luti4, .b, 2
>> +	luti4	z32.h, { z9.h }, z4[2]
>> +	luti4	z4.h, { z32.h }, z15[2]
>> +	luti4	z4.h, { z9.h }, z32[2]
>> +	luti4	z2.h, { z9.h }, z15[4]
>> +	luti4	z4.h, { z9.h }, z15[-1]
>> diff --git a/gas/testsuite/gas/aarch64/sve2-lut.d b/gas/testsuite/gas/aarch64/sve2-lut.d
>> new file mode 100644
>> index 00000000000..7b39b17d35d
>> --- /dev/null
>> +++ b/gas/testsuite/gas/aarch64/sve2-lut.d
>> @@ -0,0 +1,41 @@
>> +#objdump: -dr
>> +#as: -march=armv8-a+lut+sve2
>> +
>> +.*:     file format .*
>> +
>> +Disassembly of section \.text:
>> +
>> +0+ <.*>:
>> +[^:]+:	4520b000 	luti2	z0.b, \{z0.b\}, z0\[0\]
>> +[^:]+:	4520b01f 	luti2	z31.b, \{z0.b\}, z0\[0\]
>> +[^:]+:	4520b3e0 	luti2	z0.b, \{z31.b\}, z0\[0\]
>> +[^:]+:	453fb000 	luti2	z0.b, \{z0.b\}, z31\[0\]
>> +[^:]+:	45e0b000 	luti2	z0.b, \{z0.b\}, z0\[3\]
>> +[^:]+:	45afb124 	luti2	z4.b, \{z9.b\}, z15\[2\]
>> +[^:]+:	4520a800 	luti2	z0.h, \{z0.h\}, z0\[0\]
>> +[^:]+:	4520a81f 	luti2	z31.h, \{z0.h\}, z0\[0\]
>> +[^:]+:	4520abe0 	luti2	z0.h, \{z31.h\}, z0\[0\]
>> +[^:]+:	453fa800 	luti2	z0.h, \{z0.h\}, z31\[0\]
>> +[^:]+:	45e0b800 	luti2	z0.h, \{z0.h\}, z0\[7\]
>> +[^:]+:	456fa924 	luti2	z4.h, \{z9.h\}, z15\[2\]
>> +[^:]+:	452fb924 	luti2	z4.h, \{z9.h\}, z15\[1\]
>> +[^:]+:	45afa924 	luti2	z4.h, \{z9.h\}, z15\[4\]
>> +[^:]+:	4560a400 	luti4	z0.b, \{z0.b\}, z0\[0\]
>> +[^:]+:	4560a41f 	luti4	z31.b, \{z0.b\}, z0\[0\]
>> +[^:]+:	4560a7e0 	luti4	z0.b, \{z31.b\}, z0\[0\]
>> +[^:]+:	457fa400 	luti4	z0.b, \{z0.b\}, z31\[0\]
>> +[^:]+:	45e0a400 	luti4	z0.b, \{z0.b\}, z0\[1\]
>> +[^:]+:	45efa524 	luti4	z4.b, \{z9.b\}, z15\[1\]
>> +[^:]+:	4520bc00 	luti4	z0.h, \{z0.h\}, z0\[0\]
>> +[^:]+:	4520bc1f 	luti4	z31.h, \{z0.h\}, z0\[0\]
>> +[^:]+:	4520bfc0 	luti4	z0.h, \{z30.h\}, z0\[0\]
>> +[^:]+:	453fbc00 	luti4	z0.h, \{z0.h\}, z31\[0\]
>> +[^:]+:	45e0bc00 	luti4	z0.h, \{z0.h\}, z0\[3\]
>> +[^:]+:	45afbd24 	luti4	z4.h, \{z9.h\}, z15\[2\]
>> +[^:]+:	4520b400 	luti4	z0.h, \{z0.h-z1.h\}, z0\[0\]
>> +[^:]+:	4520b41f 	luti4	z31.h, \{z0.h-z1.h\}, z0\[0\]
>> +[^:]+:	4520b7c0 	luti4	z0.h, \{z30.h-z31.h\}, z0\[0\]
>> +[^:]+:	4520b7e0 	luti4	z0.h, \{z31.h-z0.h\}, z0\[0\]
>> +[^:]+:	453fb400 	luti4	z0.h, \{z0.h-z1.h\}, z31\[0\]
>> +[^:]+:	45e0b400 	luti4	z0.h, \{z0.h-z1.h\}, z0\[3\]
>> +[^:]+:	45afb524 	luti4	z4.h, \{z9.h-z10.h\}, z15\[2\]
>> \ No newline at end of file
>> diff --git a/gas/testsuite/gas/aarch64/sve2-lut.s b/gas/testsuite/gas/aarch64/sve2-lut.s
>> new file mode 100644
>> index 00000000000..e9c79c6e84e
>> --- /dev/null
>> +++ b/gas/testsuite/gas/aarch64/sve2-lut.s
>> @@ -0,0 +1,39 @@
>> +	// Valid luti2 instructions
>> +	luti2	z0.b, { z0.b }, z0[0]
>> +	luti2	z31.b, { z0.b }, z0[0]
>> +	luti2	z0.b, { z31.b }, z0[0]
>> +	luti2	z0.b, { z0.b }, z31[0]
>> +	luti2	z0.b, { z0.b }, z0[3]
>> +	luti2	z4.b, { z9.b }, z15[2]
>> +
>> +	luti2	z0.h, { z0.h }, z0[0]
>> +	luti2	z31.h, { z0.h }, z0[0]
>> +	luti2	z0.h, { z31.h }, z0[0]
>> +	luti2	z0.h, { z0.h }, z31[0]
>> +	luti2	z0.h, { z0.h }, z0[7]
>> +	luti2	z4.h, { z9.h }, z15[2]
>> +	luti2	z4.h, { z9.h }, z15[1]
>> +	luti2	z4.h, { z9.h }, z15[4]
>> +
>> +	// Valid luti4 instructions
>> +	luti4	z0.b, { z0.b }, z0[0]
>> +	luti4	z31.b, { z0.b }, z0[0]
>> +	luti4	z0.b, { z31.b }, z0[0]
>> +	luti4	z0.b, { z0.b }, z31[0]
>> +	luti4	z0.b, { z0.b }, z0[1]
>> +	luti4	z4.b, { z9.b }, z15[1]
>> +
>> +	luti4	z0.h, { z0.h }, z0[0]
>> +	luti4	z31.h, { z0.h }, z0[0]
>> +	luti4	z0.h, { z30.h }, z0[0]
>> +	luti4	z0.h, { z0.h }, z31[0]
>> +	luti4	z0.h, { z0.h }, z0[3]
>> +	luti4	z4.h, { z9.h }, z15[2]
>> +
>> +	luti4	z0.h, { z0.h, z1.h }, z0[0]
>> +	luti4	z31.h, { z0.h, z1.h }, z0[0]
>> +	luti4	z0.h, { z30.h, z31.h }, z0[0]
>> +	luti4	z0.h, { z31.h, z0.h }, z0[0]
>> +	luti4	z0.h, { z0.h, z1.h }, z31[0]
>> +	luti4	z0.h, { z0.h, z1.h }, z0[3]
>> +	luti4	z4.h, { z9.h, z10.h }, z15[2]
>> diff --git a/include/opcode/aarch64.h b/include/opcode/aarch64.h
>> index 95448b58721..8a21611e3ff 100644
>> --- a/include/opcode/aarch64.h
>> +++ b/include/opcode/aarch64.h
>> @@ -737,8 +737,11 @@ enum aarch64_opnd
>>     AARCH64_OPND_SVE_Zd,		/* SVE vector register in Zd.  */
>>     AARCH64_OPND_SVE_Zm_5,	/* SVE vector register in Zm, bits [9,5].  */
>>     AARCH64_OPND_SVE_Zm_16,	/* SVE vector register in Zm, bits [20,16].  */
>> +  AARCH64_OPND_SVE_Zm1_23_INDEX, /* SVE bit index in Zm, bit 23.  */
>> +  AARCH64_OPND_SVE_Zm2_22_INDEX, /* SVE bit index in Zm, bits [23,22].  */
>>     AARCH64_OPND_SVE_Zm3_INDEX,	/* z0-z7[0-3] in Zm, bits [20,16].  */
>>     AARCH64_OPND_SVE_Zm3_11_INDEX, /* z0-z7[0-7] in Zm3_INDEX plus bit 11.  */
>> +  AARCH64_OPND_SVE_Zm3_12_INDEX, /* SVE bit index in Zm, bits 12 plus bit [23,22].  */
>>     AARCH64_OPND_SVE_Zm3_19_INDEX, /* z0-z7[0-3] in Zm3_INDEX plus bit 19.  */
>>     AARCH64_OPND_SVE_Zm3_22_INDEX, /* z0-z7[0-7] in Zm3_INDEX plus bit 22.  */
>>     AARCH64_OPND_SVE_Zm4_11_INDEX, /* z0-z15[0-3] in Zm plus bit 11.  */
>> diff --git a/opcodes/aarch64-asm.c b/opcodes/aarch64-asm.c
>> index 338ed54165d..a71284691eb 100644
>> --- a/opcodes/aarch64-asm.c
>> +++ b/opcodes/aarch64-asm.c
>> @@ -1307,6 +1307,17 @@ aarch64_ins_sve_index (const aarch64_operand *self,
>>     return true;
>>   }
>>   
>> +bool
>> +aarch64_ins_sve_bit_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)
>> +{
>> +  insert_field (self->fields[0], code, info->reglane.regno, 0);
>> +  insert_all_fields_after (self, 1, code, info->reglane.index);
>> +  return true;
>> +}
>> +
>>   /* Encode Zn.<T>[<imm>], where <imm> is an immediate with range of 0 to one less
>>      than the number of elements in 128 bit, which can encode il:tsz.  */
>>   bool
>> diff --git a/opcodes/aarch64-asm.h b/opcodes/aarch64-asm.h
>> index edeb6d8de7e..9feac82cd20 100644
>> --- a/opcodes/aarch64-asm.h
>> +++ b/opcodes/aarch64-asm.h
>> @@ -98,6 +98,7 @@ AARCH64_DECL_OPD_INSERTER (ins_sve_index);
>>   AARCH64_DECL_OPD_INSERTER (ins_sve_index_imm);
>>   AARCH64_DECL_OPD_INSERTER (ins_sve_limm_mov);
>>   AARCH64_DECL_OPD_INSERTER (ins_sve_quad_index);
>> +AARCH64_DECL_OPD_INSERTER (ins_sve_bit_index);
>>   AARCH64_DECL_OPD_INSERTER (ins_sve_reglist);
>>   AARCH64_DECL_OPD_INSERTER (ins_sve_strided_reglist);
>>   AARCH64_DECL_OPD_INSERTER (ins_sve_scale);
>> diff --git a/opcodes/aarch64-dis.c b/opcodes/aarch64-dis.c
>> index 213df616608..b89339d1763 100644
>> --- a/opcodes/aarch64-dis.c
>> +++ b/opcodes/aarch64-dis.c
>> @@ -2279,6 +2279,17 @@ aarch64_ext_sve_quad_index (const aarch64_operand *self,
>>     return true;
>>   }
>>   
>> +bool
>> +aarch64_ext_sve_bit_index (const aarch64_operand *self,
>> +			    aarch64_opnd_info *info, aarch64_insn code,
>> +			    const aarch64_inst *inst ATTRIBUTE_UNUSED,
>> +			    aarch64_operand_error *errors ATTRIBUTE_UNUSED)
>> +{
>> +  info->reglane.regno = extract_field (self->fields[0], code, 0);
>> +  info->reglane.index = extract_all_fields_after (self, 1, code);
>> +  return true;
>> +}
>> +
>>   /* Decode {Zn.<T> - Zm.<T>}.  The fields array specifies which field
>>      to use for Zn.  The opcode-dependent value specifies the number
>>      of registers in the list.  */
>> diff --git a/opcodes/aarch64-dis.h b/opcodes/aarch64-dis.h
>> index 9e8f7c214d7..3446c0ef1ee 100644
>> --- a/opcodes/aarch64-dis.h
>> +++ b/opcodes/aarch64-dis.h
>> @@ -122,6 +122,7 @@ AARCH64_DECL_OPD_EXTRACTOR (ext_sve_index);
>>   AARCH64_DECL_OPD_EXTRACTOR (ext_sve_index_imm);
>>   AARCH64_DECL_OPD_EXTRACTOR (ext_sve_limm_mov);
>>   AARCH64_DECL_OPD_EXTRACTOR (ext_sve_quad_index);
>> +AARCH64_DECL_OPD_EXTRACTOR (ext_sve_bit_index);
>>   AARCH64_DECL_OPD_EXTRACTOR (ext_sve_reglist);
>>   AARCH64_DECL_OPD_EXTRACTOR (ext_sve_strided_reglist);
>>   AARCH64_DECL_OPD_EXTRACTOR (ext_sve_scale);
>> diff --git a/opcodes/aarch64-opc.c b/opcodes/aarch64-opc.c
>> index 84a3955b83b..cbc49ade02a 100644
>> --- a/opcodes/aarch64-opc.c
>> +++ b/opcodes/aarch64-opc.c
>> @@ -294,10 +294,14 @@ const aarch64_field fields[] =
>>       {  5,  5 }, /* SVE_Zn: SVE vector register, bits [9,5].  */
>>       {  0,  5 }, /* SVE_Zt: SVE vector register, bits [4,0].  */
>>       {  5,  1 }, /* SVE_i1: single-bit immediate.  */
>> +    { 23,  1 }, /* SVE_i1_23: single-bit immediate.  */
>> +    { 22,  2 }, /* SVE_i2: 2-bit index, bits [23,22].  */
>>       { 20,  1 }, /* SVE_i2h: high bit of 2bit immediate, bits.  */
>>       { 22,  1 }, /* SVE_i3h: high bit of 3-bit immediate.  */
>>       { 19,  2 }, /* SVE_i3h2: two high bits of 3bit immediate, bits [20,19].  */
>> +    { 22,  2 }, /* SVE_i3h3: two high bits of 3bit immediate, bits [22,23].  */
>>       { 11,  1 }, /* SVE_i3l: low bit of 3-bit immediate.  */
>> +    { 12,  1 }, /* SVE_i3l2: low bit of 3-bit immediate, bit 12.  */
>>       { 16,  3 }, /* SVE_imm3: 3-bit immediate field.  */
>>       { 16,  4 }, /* SVE_imm4: 4-bit immediate field.  */
>>       {  5,  5 }, /* SVE_imm5: 5-bit immediate field.  */
>> @@ -1813,6 +1817,24 @@ operand_general_constraint_met_p (const aarch64_opnd_info *opnds, int idx,
>>   	    return 0;
>>   	  break;
>>   
>> +	case AARCH64_OPND_SVE_Zm1_23_INDEX:
>> +	  size = get_operand_fields_width (get_operand_from_code (type));
>> +	  if (!check_reglane (opnd, mismatch_detail, idx, "z", 0, 31, 0, 1))
>> +	    return 0;
>> +	  break;
>> +
>> +	case AARCH64_OPND_SVE_Zm2_22_INDEX:
>> +	  size = get_operand_fields_width (get_operand_from_code (type));
>> +	  if (!check_reglane (opnd, mismatch_detail, idx, "z", 0, 31, 0, 3))
>> +	    return 0;
>> +	  break;
>> +
>> +	case AARCH64_OPND_SVE_Zm3_12_INDEX:
>> +	  size = get_operand_fields_width (get_operand_from_code (type));
>> +	  if (!check_reglane (opnd, mismatch_detail, idx, "z", 0, 31, 0, 7))
>> +	    return 0;
>> +	  break;
>> +
> 
> You can handle these together with the set of cases that includes
> AARCH64_OPND_SME_Zn_INDEX1_16.
>
Thanks for pointing it out. Fixed here 
https://sourceware.org/pipermail/binutils/2024-May/134336.html

>>   	case AARCH64_OPND_SVE_Zn_INDEX:
>>   	  size = aarch64_get_qualifier_esize (opnd->qualifier);
>>   	  if (!check_reglane (opnd, mismatch_detail, idx, "z", 0, 31,
>> @@ -4194,9 +4216,12 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
>>         print_register_list (buf, size, opnd, "z", styler);
>>         break;
>>   
>> +    case AARCH64_OPND_SVE_Zm1_23_INDEX:
>> +    case AARCH64_OPND_SVE_Zm2_22_INDEX:
>>       case AARCH64_OPND_SVE_Zm3_INDEX:
>>       case AARCH64_OPND_SVE_Zm3_22_INDEX:
>>       case AARCH64_OPND_SVE_Zm3_19_INDEX:
>> +    case AARCH64_OPND_SVE_Zm3_12_INDEX:
>>       case AARCH64_OPND_SVE_Zm3_11_INDEX:
>>       case AARCH64_OPND_SVE_Zm4_11_INDEX:
>>       case AARCH64_OPND_SVE_Zm4_INDEX:
>> diff --git a/opcodes/aarch64-opc.h b/opcodes/aarch64-opc.h
>> index 23e634f1250..8bf3fc8b874 100644
>> --- a/opcodes/aarch64-opc.h
>> +++ b/opcodes/aarch64-opc.h
>> @@ -104,10 +104,14 @@ enum aarch64_field_kind
>>     FLD_SVE_Zn,
>>     FLD_SVE_Zt,
>>     FLD_SVE_i1,
>> +  FLD_SVE_i1_23,
>> +  FLD_SVE_i2,
>>     FLD_SVE_i2h,
>>     FLD_SVE_i3h,
>>     FLD_SVE_i3h2,
>> +  FLD_SVE_i3h3,
>>     FLD_SVE_i3l,
>> +  FLD_SVE_i3l2,
>>     FLD_SVE_imm3,
>>     FLD_SVE_imm4,
>>     FLD_SVE_imm5,
>> diff --git a/opcodes/aarch64-tbl.h b/opcodes/aarch64-tbl.h
>> index 6b98a1bc22d..6dc59d2cad3 100644
>> --- a/opcodes/aarch64-tbl.h
>> +++ b/opcodes/aarch64-tbl.h
>> @@ -1529,9 +1529,21 @@
>>   {							\
>>     QLF2(S_H,S_H),					\
>>   }
>> +/* e.g. luti2 <Zd>.B, { <Zn>.B }, <Zm>[index].  */
>> +/* The third operand is an index (e.g. immediate or bit)
>> +   without a type qualifier and is checked separately
>> +   based on operand enum.  */
>>   #define OP_SVE_BBU                                      \
>>   {                                                       \
>> -  QLF3(S_B,S_B,NIL),                                \
>> +  QLF3(S_B,S_B,NIL),					\
>> +}
>> +/* e.g. luti2 <Zd>.H, { <Zn>.H }, <Zm>[index].  */
>> +/* The third operand is an index (e.g. immediate or bit)
>> +   without a type qualifier and is checked separately
>> +   based on operand enum.  */
>> +#define OP_SVE_HHU                                      \
>> +{                                                       \
>> +  QLF3(S_H,S_H,NIL),					\
>>   }
>>   #define OP_SVE_BBB                                      \
>>   {                                                       \
>> @@ -2731,6 +2743,8 @@ static const aarch64_feature_set aarch64_feature_fp8_sme2 =
>>     AARCH64_FEATURES (2, FP8, SME2);
>>   static const aarch64_feature_set aarch64_feature_lut =
>>     AARCH64_FEATURE (LUT);
>> +static const aarch64_feature_set aarch64_feature_lut_sve2 =
>> +  AARCH64_FEATURES (2, LUT, SVE2);
>>   
>>   #define CORE		&aarch64_feature_v8
>>   #define FP		&aarch64_feature_fp
>> @@ -2806,6 +2820,7 @@ static const aarch64_feature_set aarch64_feature_lut =
>>   #define FP8_SVE2   &aarch64_feature_fp8_sve2
>>   #define FP8_SME2   &aarch64_feature_fp8_sme2
>>   #define LUT &aarch64_feature_lut
>> +#define LUT_SVE2 &aarch64_feature_lut_sve2
>>   
>>   #define CORE_INSN(NAME,OPCODE,MASK,CLASS,OP,OPS,QUALS,FLAGS) \
>>     { NAME, OPCODE, MASK, CLASS, OP, CORE, OPS, QUALS, FLAGS, 0, 0, NULL }
>> @@ -3001,6 +3016,9 @@ static const aarch64_feature_set aarch64_feature_lut =
>>       F_STRICT | FLAGS, 0, TIED, NULL }
>>   #define LUT_INSN(NAME,OPCODE,MASK,OPS,QUALS,FLAGS)		\
>>     { NAME, OPCODE, MASK, lut, 0, LUT, OPS, QUALS, FLAGS, 0, 0, NULL }
>> +#define LUT_SVE2_INSN(NAME,OPCODE,MASK,OPS,QUALS,FLAGS,CONSTRAINTS) \
>> +  { NAME, OPCODE, MASK, lut, 0, LUT_SVE2, OPS, QUALS, \
>> +    FLAGS, CONSTRAINTS, 0, NULL }
>>   
>>   #define MOPS_CPY_OP1_OP2_PME_INSN(NAME, OPCODE, MASK, FLAGS, CONSTRAINTS) \
>>     MOPS_INSN (NAME, OPCODE, MASK, 0, \
>> @@ -6579,6 +6597,13 @@ const struct aarch64_opcode aarch64_opcode_table[] =
>>     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)),
>>   
>> +  /* SVE2 lut.  */
>> +  LUT_SVE2_INSN ("luti2", 0x4520b000, 0xff20fc00, OP3 (SVE_Zd, SVE_ZnxN, SVE_Zm2_22_INDEX), OP_SVE_BBU, F_OD(1), 0),
>> +  LUT_SVE2_INSN ("luti2", 0x4520a800, 0xff20ec00, OP3 (SVE_Zd, SVE_ZnxN, SVE_Zm3_12_INDEX), OP_SVE_HHU, F_OD(1), 0),
>> +  LUT_SVE2_INSN ("luti4", 0x4560a400, 0xff60fc00, OP3 (SVE_Zd, SVE_ZnxN, SVE_Zm1_23_INDEX), OP_SVE_BBU, F_OD(1), 0),
>> +  LUT_SVE2_INSN ("luti4", 0x4520b400, 0xff20fc00, OP3 (SVE_Zd, SVE_ZnxN, SVE_Zm2_22_INDEX), OP_SVE_HHU, F_OD(2), 0),
>> +  LUT_SVE2_INSN ("luti4", 0x4520bc00, 0xff20fc00, OP3 (SVE_Zd, SVE_ZnxN, SVE_Zm2_22_INDEX), OP_SVE_HHU, F_OD(1), 0),
>> +
>>     {0, 0, 0, 0, 0, 0, {}, {}, 0, 0, 0, NULL},
>>   };
>>   
>> @@ -7052,12 +7077,21 @@ const struct aarch64_opcode aarch64_opcode_table[] =
>>         "an SVE vector register")						\
>>       Y(SVE_REG, regno, "SVE_Zm_16", 0, F(FLD_SVE_Zm_16),			\
>>         "an SVE vector register")						\
>> +    Y(SVE_REG, sve_bit_index, "SVE_Zm1_23_INDEX",			\
>> +      0, F(FLD_SVE_Zm_16, FLD_SVE_i1_23),				\
>> +      "an indexed SVE vector register")					\
>> +    Y(SVE_REG, sve_bit_index, "SVE_Zm2_22_INDEX",			\
>> +      0, F(FLD_SVE_Zm_16, FLD_SVE_i2),					\
>> +      "an indexed SVE vector register")					\
> 
> Sorry for not replying about this when I reviewed your first patch, but I think
> these can also be a simple_index (allowing you to eliminate your new
> inserter/extracter).
Thanks, fixed here: 
https://sourceware.org/pipermail/binutils/2024-May/134336.html
> 
>>       Y(SVE_REG, sve_quad_index, "SVE_Zm3_INDEX",				\
>>         3 << OPD_F_OD_LSB, F(FLD_SVE_Zm_16),				\
>>         "an indexed SVE vector register")					\
>>       Y(SVE_REG, sve_quad_index, "SVE_Zm3_11_INDEX", 			\
>>         3 << OPD_F_OD_LSB, F(FLD_SVE_i3h2, FLD_SVE_i3l, FLD_SVE_imm3),    \
>>         "an indexed SVE vector register")					\
>> +    Y(SVE_REG, sve_bit_index, "SVE_Zm3_12_INDEX",			\
>> +      0, F(FLD_SVE_Zm_16, FLD_SVE_i3h3, FLD_SVE_i3l2),			\
>> +      "an indexed SVE vector register")					\
>>       Y(SVE_REG, sve_quad_index, "SVE_Zm3_19_INDEX", 			\
>>         3 << OPD_F_OD_LSB, F(FLD_imm2_19, FLD_SVE_imm3),			\
>>         "an indexed SVE vector register")					\
> 


More information about the Binutils mailing list