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

Message ID 20240523135020.2492458-3-saujha01@e130340.arm.com
State Superseded
Headers
Series [v6,1/4] gas, aarch64: Add AdvSIMD lut extension |

Checks

Context Check Description
linaro-tcwg-bot/tcwg_binutils_build--master-arm success Testing passed
linaro-tcwg-bot/tcwg_binutils_build--master-aarch64 success Testing passed
linaro-tcwg-bot/tcwg_binutils_check--master-aarch64 fail Testing failed
linaro-tcwg-bot/tcwg_binutils_check--master-arm success Testing passed

Commit Message

Saurabh Jha May 23, 2024, 1:50 p.m. UTC
  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
  

Comments

Andrew Carlotti May 23, 2024, 4:34 p.m. UTC | #1
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.

>  	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).

>      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")					\
  
Saurabh Jha May 28, 2024, 2:57 p.m. UTC | #2
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")					\
>
  

Patch

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;
+
 	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")					\
     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")					\