diff --git a/gas/config/tc-aarch64.c b/gas/config/tc-aarch64.c
index 6ad4fae8b0ece71e5ac448be889846369c657420..b21b37faf1c8b775b8f444b007947a9ca71c0ad8 100644
--- a/gas/config/tc-aarch64.c
+++ b/gas/config/tc-aarch64.c
@@ -1513,6 +1513,54 @@ parse_vector_reg_list (char **ccp, aarch64_reg_type type,
   return error ? PARSE_FAIL : (ret_val << 2) | (nb_regs - 1);
 }
 
+/* Parse a SIMD vector register with a bit index. The SIMD vectors with
+   bit indices don't have type qualifiers.
+
+   Return null if the string pointed to by *CCP is not a valid AdvSIMD
+   vector register with a bit index.
+
+   Otherwise return the register and the bit index information
+   in *typeinfo.
+
+   The validity of the bit index itself is checked separately in encoding.
+ */
+
+static const reg_entry *
+parse_simd_vector_with_bit_index (char **ccp, struct vector_type_el *typeinfo)
+{
+  char *str = *ccp;
+  const reg_entry *reg = parse_reg (&str);
+  struct vector_type_el atype;
+
+  // Setting it here as this is the convention followed in the
+  // rest of the code with indices.
+  atype.defined = NTA_HASINDEX;
+  // This will be set to correct value in parse_index_expressions.
+  atype.index = 0;
+  // The rest of the fields are not applicable for this operand.
+  atype.type = NT_invtype;
+  atype.width = -1;
+  atype.element_size = 0;
+
+  if (reg == NULL)
+    return NULL;
+
+  if (reg->type != REG_TYPE_V)
+    return NULL;
+
+  // Parse the bit index.
+  if (!skip_past_char (&str, '['))
+    return NULL;
+  if (!parse_index_expression (&str, &atype.index))
+    return NULL;
+  if (!skip_past_char (&str, ']'))
+    return NULL;
+
+  *typeinfo = atype;
+  *ccp = str;
+  return reg;
+}
+
 /* Directives: register aliases.  */
 
 static reg_entry *
@@ -6790,6 +6838,23 @@ parse_operands (char *str, const aarch64_opcode *opcode)
 	  info->reglane.index = vectype.index;
 	  break;
 
+	case AARCH64_OPND_Em_INDEX1_14:
+	case AARCH64_OPND_Em_INDEX2_13:
+	case AARCH64_OPND_Em_INDEX3_12:
+	  // These are SIMD vector operands with bit indices. For example,
+	  // 'V27[3]'. These operands don't have type qualifiers before
+	  // indices.
+	  reg = parse_simd_vector_with_bit_index(&str, &vectype);
+
+	  if (!reg)
+	    goto failure;
+	  gas_assert (vectype.defined & NTA_HASINDEX);
+
+	  info->qualifier = AARCH64_OPND_QLF_NIL;
+	  info->reglane.regno = reg->number;
+	  info->reglane.index = vectype.index;
+	  break;
+
 	case AARCH64_OPND_SVE_ZnxN:
 	case AARCH64_OPND_SVE_ZtxN:
 	case AARCH64_OPND_SME_Zdnx2:
@@ -6812,6 +6877,7 @@ parse_operands (char *str, const aarch64_opcode *opcode)
 	  goto vector_reg_list;
 
 	case AARCH64_OPND_LVn:
+	case AARCH64_OPND_LVn_LUT:
 	case AARCH64_OPND_LVt:
 	case AARCH64_OPND_LVt_AL:
 	case AARCH64_OPND_LEt:
@@ -10477,6 +10543,7 @@ static const struct aarch64_option_cpu_value_table aarch64_features[] = {
   {"rcpc3",		AARCH64_FEATURE (RCPC3), AARCH64_FEATURE (RCPC2)},
   {"cpa",		AARCH64_FEATURE (CPA), AARCH64_NO_FEATURES},
   {"faminmax",		AARCH64_FEATURE (FAMINMAX), AARCH64_FEATURE (SIMD)},
+  {"lut",		AARCH64_FEATURE (LUT), AARCH64_FEATURE (SIMD)},
   {NULL,		AARCH64_NO_FEATURES, AARCH64_NO_FEATURES},
 };
 
diff --git a/gas/testsuite/gas/aarch64/advsimd-lut-bad.d b/gas/testsuite/gas/aarch64/advsimd-lut-bad.d
new file mode 100644
index 0000000000000000000000000000000000000000..a3b57730e9b175fc56f1c0a740159526341990fa
--- /dev/null
+++ b/gas/testsuite/gas/aarch64/advsimd-lut-bad.d
@@ -0,0 +1,3 @@
+#as:
+#source: advsimd-lut.s
+#error_output: advsimd-lut-bad.l
\ No newline at end of file
diff --git a/gas/testsuite/gas/aarch64/advsimd-lut-bad.l b/gas/testsuite/gas/aarch64/advsimd-lut-bad.l
new file mode 100644
index 0000000000000000000000000000000000000000..3afe4a39c546f48cb011b3beb51870322faf555e
--- /dev/null
+++ b/gas/testsuite/gas/aarch64/advsimd-lut-bad.l
@@ -0,0 +1,25 @@
+[^ :]+: Assembler messages:
+.*: Error: selected processor does not support `luti2 v0.16b,{v0.16b},v0\[0\]'
+.*: Error: selected processor does not support `luti2 v31.16b,{v0.16b},v0\[0\]'
+.*: Error: selected processor does not support `luti2 v0.16b,{v31.16b},v0\[0\]'
+.*: Error: selected processor does not support `luti2 v0.16b,{v0.16b},v31\[0\]'
+.*: Error: selected processor does not support `luti2 v0.16b,{v0.16b},v31\[3\]'
+.*: Error: selected processor does not support `luti2 v17.16b,{v21.16b},v27\[2\]'
+.*: Error: selected processor does not support `luti2 v0.8h,{v0.8h},v0\[0\]'
+.*: Error: selected processor does not support `luti2 v31.8h,{v0.8h},v0\[0\]'
+.*: Error: selected processor does not support `luti2 v0.8h,{v31.8h},v0\[0\]'
+.*: Error: selected processor does not support `luti2 v0.8h,{v0.8h},v31\[0\]'
+.*: Error: selected processor does not support `luti2 v0.8h,{v0.8h},v0\[7\]'
+.*: Error: selected processor does not support `luti2 v17.8h,{v21.8h},v27\[4\]'
+.*: Error: selected processor does not support `luti4 v0.16b,{v0.16b},v0\[0\]'
+.*: Error: selected processor does not support `luti4 v31.16b,{v0.16b},v0\[0\]'
+.*: Error: selected processor does not support `luti4 v0.16b,{v31.16b},v0\[0\]'
+.*: Error: selected processor does not support `luti4 v0.16b,{v0.16b},v31\[0\]'
+.*: Error: selected processor does not support `luti4 v0.16b,{v0.16b},v0\[1\]'
+.*: Error: selected processor does not support `luti4 v17.16b,{v21.16b},v27\[1\]'
+.*: Error: selected processor does not support `luti4 v0.8h,{v0.8h,v1.8h},v0\[0\]'
+.*: Error: selected processor does not support `luti4 v31.8h,{v0.8h,v1.8h},v0\[0\]'
+.*: Error: selected processor does not support `luti4 v0.8h,{v31.8h,v0.8h},v0\[0\]'
+.*: Error: selected processor does not support `luti4 v0.8h,{v0.8h,v1.8h},v31\[0\]'
+.*: Error: selected processor does not support `luti4 v0.8h,{v0.8h,v1.8h},v0\[3\]'
+.*: Error: selected processor does not support `luti4 v17.8h,{v21.8h,v22.8h},v27\[2\]'
diff --git a/gas/testsuite/gas/aarch64/advsimd-lut-illegal.d b/gas/testsuite/gas/aarch64/advsimd-lut-illegal.d
new file mode 100644
index 0000000000000000000000000000000000000000..32ddfebabe1e0362ed0eaa3f3aa93470050a304a
--- /dev/null
+++ b/gas/testsuite/gas/aarch64/advsimd-lut-illegal.d
@@ -0,0 +1,3 @@
+#as: -march=armv8-a+lut
+#source: advsimd-lut-illegal.s
+#error_output: advsimd-lut-illegal.l
\ No newline at end of file
diff --git a/gas/testsuite/gas/aarch64/advsimd-lut-illegal.l b/gas/testsuite/gas/aarch64/advsimd-lut-illegal.l
new file mode 100644
index 0000000000000000000000000000000000000000..86f6a7d2fdb841109a4db62baea5a9ef49663b7b
--- /dev/null
+++ b/gas/testsuite/gas/aarch64/advsimd-lut-illegal.l
@@ -0,0 +1,208 @@
+[^ :]+: Assembler messages:
+[^ :]+:[0-9]+: Error: operand mismatch -- `luti2 v2.16b,\{v4.8h\},v8\[1\]'
+[^ :]+:[0-9]+: Info:    did you mean this\?
+[^ :]+:[0-9]+: Info:    	luti2 v2.16b, \{v4.16b\}, v8\[1\]
+[^ :]+:[0-9]+: Error: operand mismatch -- `luti2 v2.8h,\{v4.16b\},v8\[1\]'
+[^ :]+:[0-9]+: Info:    did you mean this\?
+[^ :]+:[0-9]+: Info:    	luti2 v2.16b, \{v4.16b\}, v8\[1\]
+[^ :]+:[0-9]+: Error: operand mismatch -- `luti4 v2.16b,\{v4.8h\},v8\[5\]'
+[^ :]+:[0-9]+: Info:    did you mean this\?
+[^ :]+:[0-9]+: Info:    	luti4 v2.16b, \{v4.16b\}, v8\[5\]
+[^ :]+:[0-9]+: Error: operand mismatch -- `luti4 v2.8h,\{v4.16b\},v8\[5\]'
+[^ :]+:[0-9]+: Info:    did you mean this\?
+[^ :]+:[0-9]+: Info:    	luti4 v2.16b, \{v4.16b\}, v8\[5\]
+[^ :]+:[0-9]+: Error: missing braces at operand 2 -- `luti2 v2.16b,v4.16b,v8\[1\]'
+[^ :]+:[0-9]+:  Info: macro invoked from here
+[^ :]+:[0-9]+: Error: expected a vector register at operand 1 -- `luti2 x12,\{v4.16b\},v8\[1\]'
+[^ :]+:[0-9]+:  Info: macro invoked from here
+[^ :]+:[0-9]+: Error: expected an Advanced SIMD vector register at operand 2 -- `luti2 v2.16b,\{x12\},v8\[1\]'
+[^ :]+:[0-9]+:  Info: macro invoked from here
+[^ :]+:[0-9]+: Error: operand 3 must be a SIMD vector without a type qualifier encoding a bit index -- `luti2 v2.16b,\{v4.16b\},x12\[1\]'
+[^ :]+:[0-9]+:  Info: macro invoked from here
+[^ :]+:[0-9]+: Error: missing braces at operand 2 -- `luti2 v2.8h,v4.8h,v8\[1\]'
+[^ :]+:[0-9]+:  Info: macro invoked from here
+[^ :]+:[0-9]+: Error: expected a vector register at operand 1 -- `luti2 x12,\{v4.8h\},v8\[1\]'
+[^ :]+:[0-9]+:  Info: macro invoked from here
+[^ :]+:[0-9]+: Error: expected an Advanced SIMD vector register at operand 2 -- `luti2 v2.8h,\{x12\},v8\[1\]'
+[^ :]+:[0-9]+:  Info: macro invoked from here
+[^ :]+:[0-9]+: Error: operand 3 must be a SIMD vector without a type qualifier encoding a bit index -- `luti2 v2.8h,\{v4.8h\},x12\[1\]'
+[^ :]+:[0-9]+:  Info: macro invoked from here
+[^ :]+:[0-9]+: Error: missing braces at operand 2 -- `luti4 v2.16b,v4.16b,v8\[1\]'
+[^ :]+:[0-9]+:  Info: macro invoked from here
+[^ :]+:[0-9]+: Error: expected a vector register at operand 1 -- `luti4 x12,\{v4.16b\},v8\[1\]'
+[^ :]+:[0-9]+:  Info: macro invoked from here
+[^ :]+:[0-9]+: Error: expected an Advanced SIMD vector register at operand 2 -- `luti4 v2.16b,\{x12\},v8\[1\]'
+[^ :]+:[0-9]+:  Info: macro invoked from here
+[^ :]+:[0-9]+: Error: operand 3 must be a SIMD vector without a type qualifier encoding a bit index -- `luti4 v2.16b,\{v4.16b\},x12\[1\]'
+[^ :]+:[0-9]+:  Info: macro invoked from here
+[^ :]+:[0-9]+: Error: missing braces at operand 2 -- `luti4 v2.8h,v4.8h,v8\[1\]'
+[^ :]+:[0-9]+:  Info: macro invoked from here
+[^ :]+:[0-9]+: Error: expected a vector register at operand 1 -- `luti4 x12,\{v4.8h\},v8\[1\]'
+[^ :]+:[0-9]+:  Info: macro invoked from here
+[^ :]+:[0-9]+: Error: expected an Advanced SIMD vector register at operand 2 -- `luti4 v2.8h,\{x12\},v8\[1\]'
+[^ :]+:[0-9]+:  Info: macro invoked from here
+[^ :]+:[0-9]+: Error: operand 3 must be a SIMD vector without a type qualifier encoding a bit index -- `luti4 v2.8h,\{v4.8h\},x12\[1\]'
+[^ :]+:[0-9]+:  Info: macro invoked from here
+[^ :]+:[0-9]+: Error: operand 2 must be a SIMD vector register list -- `luti4 v2.8h,\{v4.8h,x12\},v8\[1\]'
+[^ :]+:[0-9]+: Error: operand mismatch -- `luti2 v2.8b,\{v4.8b\},v8\[1\]'
+[^ :]+:[0-9]+: Info:    did you mean this\?
+[^ :]+:[0-9]+: Info:    	luti2 v2.16b, \{v4.16b\}, v8\[1\]
+[^ :]+:[0-9]+: Error: operand mismatch -- `luti2 v2.4h,\{v4.4h\},v8\[1\]'
+[^ :]+:[0-9]+: Info:    did you mean this\?
+[^ :]+:[0-9]+: Info:    	luti2 v2.16b, \{v4.16b\}, v8\[1\]
+[^ :]+:[0-9]+: Error: operand mismatch -- `luti4 v2.8b,\{v4.8b\},v8\[5\]'
+[^ :]+:[0-9]+: Info:    did you mean this\?
+[^ :]+:[0-9]+: Info:    	luti4 v2.16b, \{v4.16b\}, v8\[5\]
+[^ :]+:[0-9]+: Error: operand mismatch -- `luti4 v2.4h,\{v4.4h,v5.4h\},v8\[5\]'
+[^ :]+:[0-9]+: Info:    did you mean this\?
+[^ :]+:[0-9]+: Info:    	luti4 v2.16b, \{v4.16b-v5.16b\}, v8\[5\]
+[^ :]+:[0-9]+: Error: comma expected between operands at operand 2 -- `luti2 v2.16b'
+[^ :]+:[0-9]+:  Info: macro invoked from here
+[^ :]+:[0-9]+: Error: expected element type rather than vector type at operand 2 -- `luti2 v2.16b,\{v4.16b\}'
+[^ :]+:[0-9]+:  Info: macro invoked from here
+[^ :]+:[0-9]+: Error: unexpected characters following instruction at operand 3 -- `luti2 v2.16b,\{v4.16b\},v8\[1\],v16.16b'
+[^ :]+:[0-9]+:  Info: macro invoked from here
+[^ :]+:[0-9]+: Error: unexpected characters following instruction at operand 3 -- `luti2 v2.16b,\{v4.16b\},v8\[1\],\{v16.16b\}'
+[^ :]+:[0-9]+:  Info: macro invoked from here
+[^ :]+:[0-9]+: Error: comma expected between operands at operand 2 -- `luti2 v2.8h'
+[^ :]+:[0-9]+:  Info: macro invoked from here
+[^ :]+:[0-9]+: Error: expected element type rather than vector type at operand 2 -- `luti2 v2.8h,\{v4.8h\}'
+[^ :]+:[0-9]+:  Info: macro invoked from here
+[^ :]+:[0-9]+: Error: unexpected characters following instruction at operand 3 -- `luti2 v2.8h,\{v4.8h\},v8\[1\],v16.8h'
+[^ :]+:[0-9]+:  Info: macro invoked from here
+[^ :]+:[0-9]+: Error: unexpected characters following instruction at operand 3 -- `luti2 v2.8h,\{v4.8h\},v8\[1\],\{v16.8h\}'
+[^ :]+:[0-9]+:  Info: macro invoked from here
+[^ :]+:[0-9]+: Error: comma expected between operands at operand 2 -- `luti4 v2.16b'
+[^ :]+:[0-9]+:  Info: macro invoked from here
+[^ :]+:[0-9]+: Error: expected element type rather than vector type at operand 2 -- `luti4 v2.16b,\{v4.16b\}'
+[^ :]+:[0-9]+:  Info: macro invoked from here
+[^ :]+:[0-9]+: Error: unexpected characters following instruction at operand 3 -- `luti4 v2.16b,\{v4.16b\},v8\[1\],v16.16b'
+[^ :]+:[0-9]+:  Info: macro invoked from here
+[^ :]+:[0-9]+: Error: unexpected characters following instruction at operand 3 -- `luti4 v2.16b,\{v4.16b\},v8\[1\],\{v16.16b\}'
+[^ :]+:[0-9]+:  Info: macro invoked from here
+[^ :]+:[0-9]+: Error: comma expected between operands at operand 2 -- `luti4 v2.8h'
+[^ :]+:[0-9]+: Error: expected element type rather than vector type at operand 2 -- `luti4 v2.8h,\{v4.8h,v5.8h\}'
+[^ :]+:[0-9]+: Error: unexpected characters following instruction at operand 3 -- `luti4 v2.8h,\{v4.8h,v5.8h\},v8\[1\],v16.8h'
+[^ :]+:[0-9]+: Error: unexpected characters following instruction at operand 3 -- `luti4 v2.8h,\{v4.8h,v5.8h\},v8\[1\],\{v16.8h\}'
+[^ :]+:[0-9]+: Error: unexpected character `t' in element size at operand 2 -- `luti2 v2.16b,\{v4.16t\},v8\[1\]'
+[^ :]+:[0-9]+:  Info: macro invoked from here
+[^ :]+:[0-9]+: Error: unexpected character `t' in element size at operand 1 -- `luti2 v2.16t,\{v4.16b\},v8\[1\]'
+[^ :]+:[0-9]+:  Info: macro invoked from here
+[^ :]+:[0-9]+: Error: unexpected character `m' in element size at operand 2 -- `luti2 v2.8h,\{v4.8m\},v8\[1\]'
+[^ :]+:[0-9]+:  Info: macro invoked from here
+[^ :]+:[0-9]+: Error: unexpected character `m' in element size at operand 1 -- `luti2 v2.8m,\{v4.8h\},v8\[1\]'
+[^ :]+:[0-9]+:  Info: macro invoked from here
+[^ :]+:[0-9]+: Error: unexpected character `t' in element size at operand 2 -- `luti4 v2.16b,\{v4.16t\},v8\[1\]'
+[^ :]+:[0-9]+:  Info: macro invoked from here
+[^ :]+:[0-9]+: Error: unexpected character `t' in element size at operand 1 -- `luti4 v2.16t,\{v4.16b\},v8\[1\]'
+[^ :]+:[0-9]+:  Info: macro invoked from here
+[^ :]+:[0-9]+: Error: unexpected character `t' in element size at operand 2 -- `luti4 v2.8h,\{v4.8h,v5.8t\},v8\[1\]'
+[^ :]+:[0-9]+: Error: unexpected character `t' in element size at operand 1 -- `luti4 v2.8t,\{v4.8h,v5.8h\},v8\[1\]'
+[^ :]+:[0-9]+: Error: invalid use of vector register at operand 2 -- `luti2 v2.16b,\{v4\},v8\[1\]'
+[^ :]+:[0-9]+:  Info: macro invoked from here
+[^ :]+:[0-9]+: Error: invalid use of vector register at operand 1 -- `luti2 v2,\{v4.16b\},v8\[1\]'
+[^ :]+:[0-9]+:  Info: macro invoked from here
+[^ :]+:[0-9]+: Error: expected a register or register list at operand 1 -- `luti2 2.16b,\{v4.16b\},v8\[1\]'
+[^ :]+:[0-9]+:  Info: macro invoked from here
+[^ :]+:[0-9]+: Error: syntax error in register list at operand 2 -- `luti2 v2.16b,\{4.16b\},v8\[1\]'
+[^ :]+:[0-9]+:  Info: macro invoked from here
+[^ :]+:[0-9]+: Error: invalid use of vector register at operand 2 -- `luti2 v2.8h,\{v4\},v8\[1\]'
+[^ :]+:[0-9]+:  Info: macro invoked from here
+[^ :]+:[0-9]+: Error: invalid use of vector register at operand 1 -- `luti2 v2,\{v4.8h\},v8\[1\]'
+[^ :]+:[0-9]+:  Info: macro invoked from here
+[^ :]+:[0-9]+: Error: expected a register or register list at operand 1 -- `luti2 2.8h,\{v4.8h\},v8\[1\]'
+[^ :]+:[0-9]+:  Info: macro invoked from here
+[^ :]+:[0-9]+: Error: syntax error in register list at operand 2 -- `luti2 v2.8h,\{4.8h\},v8\[1\]'
+[^ :]+:[0-9]+:  Info: macro invoked from here
+[^ :]+:[0-9]+: Error: invalid use of vector register at operand 2 -- `luti4 v2.16b,\{v4\},v8\[1\]'
+[^ :]+:[0-9]+:  Info: macro invoked from here
+[^ :]+:[0-9]+: Error: invalid use of vector register at operand 1 -- `luti4 v2,\{v4.16b\},v8\[1\]'
+[^ :]+:[0-9]+:  Info: macro invoked from here
+[^ :]+:[0-9]+: Error: expected a register or register list at operand 1 -- `luti4 2.16b,\{v4.16b\},v8\[1\]'
+[^ :]+:[0-9]+:  Info: macro invoked from here
+[^ :]+:[0-9]+: Error: syntax error in register list at operand 2 -- `luti4 v2.16b,\{4.16b\},v8\[1\]'
+[^ :]+:[0-9]+:  Info: macro invoked from here
+[^ :]+:[0-9]+: Error: invalid use of vector register at operand 2 -- `luti4 v2.16b,\{v4,v5.16b\},v8\[1\]'
+[^ :]+:[0-9]+: Error: invalid use of vector register at operand 1 -- `luti4 v2,\{v4.16b,v5.16b\},v8\[1\]'
+[^ :]+:[0-9]+: Error: expected a register or register list at operand 1 -- `luti4 2.16b,\{v4.16b,v5.16b\},v8\[1\]'
+[^ :]+:[0-9]+: Error: syntax error in register list at operand 2 -- `luti4 v2.16b,\{v4.16b,5.16b\},v8\[1\]'
+[^ :]+:[0-9]+: Error: operand 3 must be a SIMD vector without a type qualifier encoding a bit index -- `luti2 v17.16b,\{v21.16b\},v27.16b\[3\]'
+[^ :]+:[0-9]+: Error: operand 3 must be a SIMD vector without a type qualifier encoding a bit index -- `luti2 v17.8h,\{v21.8h\},v27.8h\[4\]'
+[^ :]+:[0-9]+: Error: operand 3 must be a SIMD vector without a type qualifier encoding a bit index -- `luti4 v17.16b,\{v21.16b\},v27.16b\[1\]'
+[^ :]+:[0-9]+: Error: operand 3 must be a SIMD vector without a type qualifier encoding a bit index -- `luti4 v17.8h,\{v21.8h,v22.8h\},v27.8h\[2\]'
+[^ :]+:[0-9]+: Error: expected an SVE vector register at operand 1 -- `luti2 v17.16b\[1\],\{v0.16b\},v31.16b'
+[^ :]+:[0-9]+:  Info: macro invoked from here
+[^ :]+:[0-9]+: Error: this type of register can't be indexed at operand 1 -- `luti2 v17\[1\],\{v0.16b\},v31.16b'
+[^ :]+:[0-9]+:  Info: macro invoked from here
+[^ :]+:[0-9]+: Error: index not allowed inside register list at operand 2 -- `luti2 v17.16b,\{v0.16b\[1\]\},v31.16b'
+[^ :]+:[0-9]+:  Info: macro invoked from here
+[^ :]+:[0-9]+: Error: this type of register can't be indexed at operand 2 -- `luti2 v17.16b,\{v0\[1\]\},v31.16b'
+[^ :]+:[0-9]+:  Info: macro invoked from here
+[^ :]+:[0-9]+: Error: expected an SVE vector register at operand 1 -- `luti2 v17.8h\[1\],\{v0.8h\},v31.8h'
+[^ :]+:[0-9]+:  Info: macro invoked from here
+[^ :]+:[0-9]+: Error: this type of register can't be indexed at operand 1 -- `luti2 v17\[1\],\{v0.8h\},v31.8h'
+[^ :]+:[0-9]+:  Info: macro invoked from here
+[^ :]+:[0-9]+: Error: index not allowed inside register list at operand 2 -- `luti2 v17.8h,\{v0.8h\[1\]\},v31.8h'
+[^ :]+:[0-9]+:  Info: macro invoked from here
+[^ :]+:[0-9]+: Error: this type of register can't be indexed at operand 2 -- `luti2 v17.8h,\{v0\[1\]\},v31.8h'
+[^ :]+:[0-9]+:  Info: macro invoked from here
+[^ :]+:[0-9]+: Error: expected an SVE vector register at operand 1 -- `luti4 v17.16b\[1\],\{v0.16b\},v31.16b'
+[^ :]+:[0-9]+:  Info: macro invoked from here
+[^ :]+:[0-9]+: Error: this type of register can't be indexed at operand 1 -- `luti4 v17\[1\],\{v0.16b\},v31.16b'
+[^ :]+:[0-9]+:  Info: macro invoked from here
+[^ :]+:[0-9]+: Error: index not allowed inside register list at operand 2 -- `luti4 v17.16b,\{v0.16b\[1\]\},v31.16b'
+[^ :]+:[0-9]+:  Info: macro invoked from here
+[^ :]+:[0-9]+: Error: this type of register can't be indexed at operand 2 -- `luti4 v17.16b,\{v0\[1\]\},v31.16b'
+[^ :]+:[0-9]+:  Info: macro invoked from here
+[^ :]+:[0-9]+: Error: expected an SVE vector register at operand 1 -- `luti4 v17.8h\[1\],\{v0.8h,v1.8h\},v31.8h'
+[^ :]+:[0-9]+: Error: this type of register can't be indexed at operand 1 -- `luti4 v17\[1\],\{v0.8h,v1.8h\},v31.8h'
+[^ :]+:[0-9]+: Error: index not allowed inside register list at operand 2 -- `luti4 v17.8h,\{v0.8h\[1\],v1.8h\},v31.8h'
+[^ :]+:[0-9]+: Error: this type of register can't be indexed at operand 2 -- `luti4 v17.8h,\{v0\[1\],v1.8h\},v31.8h'
+[^ :]+:[0-9]+: Error: operand 3 must be a SIMD vector without a type qualifier encoding a bit index -- `luti2 v2.16b,\{v4.16b\},v8.16b'
+[^ :]+:[0-9]+: Error: operand 3 must be a SIMD vector without a type qualifier encoding a bit index -- `luti2 v2.16b,\{v4.16b\},v8'
+[^ :]+:[0-9]+: Error: operand 3 must be a SIMD vector without a type qualifier encoding a bit index -- `luti2 v2.8h,\{v4.8h\},v8.8h'
+[^ :]+:[0-9]+: Error: operand 3 must be a SIMD vector without a type qualifier encoding a bit index -- `luti2 v2.8h,\{v4.8h\},v8'
+[^ :]+:[0-9]+: Error: operand 3 must be a SIMD vector without a type qualifier encoding a bit index -- `luti4 v2.16b,\{v4.16b\},v8.16b'
+[^ :]+:[0-9]+: Error: operand 3 must be a SIMD vector without a type qualifier encoding a bit index -- `luti4 v2.16b,\{v4.16b\},v8'
+[^ :]+:[0-9]+: Error: operand 3 must be a SIMD vector without a type qualifier encoding a bit index -- `luti4 v2.8h,\{v4.8h,v5.8h\},v8.8h'
+[^ :]+:[0-9]+: Error: operand 3 must be a SIMD vector without a type qualifier encoding a bit index -- `luti4 v2.8h,\{v4.8h,v5.8h\},v8'
+[^ :]+:[0-9]+: Error: expected a register or register list at operand 1 -- `luti2 v32.16b,\{v4.16b\},v8\[1\]'
+[^ :]+:[0-9]+:  Info: macro invoked from here
+[^ :]+:[0-9]+: Error: expected an Advanced SIMD vector register at operand 2 -- `luti2 v2.16b,\{v32.16b\},v8\[1\]'
+[^ :]+:[0-9]+:  Info: macro invoked from here
+[^ :]+:[0-9]+: Error: operand 3 must be a SIMD vector without a type qualifier encoding a bit index -- `luti2 v2.16b,\{v4.16b\},v32\[1\]'
+[^ :]+:[0-9]+:  Info: macro invoked from here
+[^ :]+:[0-9]+: Error: register element index out of range 0 to 3 at operand 3 -- `luti2 v2.16b,\{v4.16b\},v8\[4\]'
+[^ :]+:[0-9]+:  Info: macro invoked from here
+[^ :]+:[0-9]+: Error: register element index out of range 0 to 3 at operand 3 -- `luti2 v2.16b,\{v4.16b\},v8\[-1\]'
+[^ :]+:[0-9]+:  Info: macro invoked from here
+[^ :]+:[0-9]+: Error: expected a register or register list at operand 1 -- `luti2 v32.8h,\{v4.8h\},v8\[1\]'
+[^ :]+:[0-9]+:  Info: macro invoked from here
+[^ :]+:[0-9]+: Error: expected an Advanced SIMD vector register at operand 2 -- `luti2 v2.8h,\{v32.8h\},v8\[1\]'
+[^ :]+:[0-9]+:  Info: macro invoked from here
+[^ :]+:[0-9]+: Error: operand 3 must be a SIMD vector without a type qualifier encoding a bit index -- `luti2 v2.8h,\{v4.8h\},v32\[1\]'
+[^ :]+:[0-9]+:  Info: macro invoked from here
+[^ :]+:[0-9]+: Error: register element index out of range 0 to 7 at operand 3 -- `luti2 v2.8h,\{v4.8h\},v8\[8\]'
+[^ :]+:[0-9]+:  Info: macro invoked from here
+[^ :]+:[0-9]+: Error: register element index out of range 0 to 7 at operand 3 -- `luti2 v2.8h,\{v4.8h\},v8\[-1\]'
+[^ :]+:[0-9]+:  Info: macro invoked from here
+[^ :]+:[0-9]+: Error: expected a register or register list at operand 1 -- `luti4 v32.16b,\{v4.16b\},v8\[1\]'
+[^ :]+:[0-9]+:  Info: macro invoked from here
+[^ :]+:[0-9]+: Error: expected an Advanced SIMD vector register at operand 2 -- `luti4 v2.16b,\{v32.16b\},v8\[1\]'
+[^ :]+:[0-9]+:  Info: macro invoked from here
+[^ :]+:[0-9]+: Error: operand 3 must be a SIMD vector without a type qualifier encoding a bit index -- `luti4 v2.16b,\{v4.16b\},v32\[1\]'
+[^ :]+:[0-9]+:  Info: macro invoked from here
+[^ :]+:[0-9]+: Error: register element index out of range 0 to 1 at operand 3 -- `luti4 v2.16b,\{v4.16b\},v8\[2\]'
+[^ :]+:[0-9]+:  Info: macro invoked from here
+[^ :]+:[0-9]+: Error: register element index out of range 0 to 1 at operand 3 -- `luti4 v2.16b,\{v4.16b\},v8\[-1\]'
+[^ :]+:[0-9]+:  Info: macro invoked from here
+[^ :]+:[0-9]+: Error: expected a register or register list at operand 1 -- `luti4 v32.8h,\{v4.8h,v5.8h\},v8\[1\]'
+[^ :]+:[0-9]+: Error: operand 2 must be a SIMD vector register list -- `luti4 v2.8h,\{v31.8h,v32.8h\},v8\[1\]'
+[^ :]+:[0-9]+: Error: operand 3 must be a SIMD vector without a type qualifier encoding a bit index -- `luti4 v2.8h,\{v4.8h,v5.8h\},v32\[1\]'
+[^ :]+:[0-9]+: Error: register element index out of range 0 to 3 at operand 3 -- `luti4 v2.8h,\{v4.8h,v5.8h\},v8\[4\]'
+[^ :]+:[0-9]+: Error: register element index out of range 0 to 3 at operand 3 -- `luti4 v2.8h,\{v4.8h,v5.8h\},v8\[-1\]'
+[^ :]+:[0-9]+: Error: the register list must have a stride of 1 at operand 2 -- `luti4 v2.8h,\{v4.8h,v6.8h\},v8\[2\]'
+[^ :]+:[0-9]+: Error: expected a single-register list at operand 2 -- `luti2 v17.16b,\{v21.16b,v22.16b\},v27\[2\]'
+[^ :]+:[0-9]+: Error: expected a single-register list at operand 2 -- `luti2 v17.8h,\{v21.8h,v22.8h\},v27\[4\]'
+[^ :]+:[0-9]+: Error: expected a single-register list at operand 2 -- `luti4 v17.16b,\{v21.16b,v22.16b\},v27\[1\]'
+[^ :]+:[0-9]+: Error: expected a list of 2 registers at operand 2 -- `luti4 v17.8h,\{v21.8h\},v27\[2\]'
diff --git a/gas/testsuite/gas/aarch64/advsimd-lut-illegal.s b/gas/testsuite/gas/aarch64/advsimd-lut-illegal.s
new file mode 100644
index 0000000000000000000000000000000000000000..24771fa14745b4d52692956433b2129197d9fe7f
--- /dev/null
+++ b/gas/testsuite/gas/aarch64/advsimd-lut-illegal.s
@@ -0,0 +1,128 @@
+	// Operand mismatch
+	luti2	v2.16b, { v4.8h }, v8[1]
+	luti2	v2.8h, { v4.16b }, v8[1]
+	luti4	v2.16b, { v4.8h }, v8[5]
+	luti4	v2.8h, { v4.16b }, v8[5]
+
+	// Incorrect operand types
+	.macro incorrect_operand_types op, operand_type
+	\op	v2\operand_type, v4\operand_type, v8[1]
+	\op	x12, { v4\operand_type }, v8[1]
+	\op	v2\operand_type, { x12 }, v8[1]
+	\op	v2\operand_type, { v4\operand_type }, x12[1]
+	.endm
+
+	incorrect_operand_types luti2 .16b
+	incorrect_operand_types luti2 .8h
+	incorrect_operand_types luti4 .16b
+	incorrect_operand_types luti4 .8h
+	luti4	v2.8h, { v4.8h, x12 }, v8[1]
+
+	// Disallowed types
+	luti2	v2.8b, { v4.8b }, v8[1]
+	luti2	v2.4h, { v4.4h }, v8[1]
+	luti4	v2.8b, { v4.8b }, v8[5]
+	luti4	v2.4h, { v4.4h, v5.4h }, v8[5]
+
+	// Incorrect number of operands
+	.macro 	incorrect_operands, op, operand_type
+	\op	v2\operand_type
+	\op	v2\operand_type, { v4\operand_type }
+	\op	v2\operand_type, { v4\operand_type }, v8[1], v16\operand_type
+	\op	v2\operand_type, { v4\operand_type }, v8[1], { v16\operand_type }
+	.endm
+
+	incorrect_operands luti2 .16b
+	incorrect_operands luti2 .8h
+	incorrect_operands luti4 .16b
+	luti4	v2.8h
+	luti4	v2.8h, { v4.8h, v5.8h }
+	luti4	v2.8h, { v4.8h, v5.8h }, v8[1], v16.8h
+	luti4	v2.8h, { v4.8h, v5.8h }, v8[1], { v16.8h }
+
+	// Spelling mistakes
+	.macro 	spelling_mistakes, op, operand_type, incorrect_operand_type
+	\op	v2\operand_type, { v4\incorrect_operand_type }, v8[1]
+	\op	v2\incorrect_operand_type, { v4\operand_type }, v8[1]
+	.endm
+
+	spelling_mistakes luti2, .16b, .16t
+	spelling_mistakes luti2, .8h, .8m
+	spelling_mistakes luti4, .16b, .16t
+	luti4	v2.8h, { v4.8h, v5.8t }, v8[1]
+	luti4	v2.8t, { v4.8h, v5.8h }, v8[1]
+
+	// Missing qualifiers
+	.macro	missing_qualifiers, op, operand_type
+	\op	v2\operand_type, { v4 }, v8[1]
+	\op	v2, { v4\operand_type }, v8[1]
+	\op	2\operand_type, { v4\operand_type }, v8[1]
+	\op	v2\operand_type, { 4\operand_type }, v8[1]
+	.endm
+
+	missing_qualifiers luti2, .16b
+	missing_qualifiers luti2, .8h
+	missing_qualifiers luti4, .16b
+	luti4	v2.16b, { v4, v5.16b }, v8[1]
+	luti4	v2, { v4.16b, v5.16b }, v8[1]
+	luti4	2.16b, { v4.16b, v5.16b }, v8[1]
+	luti4	v2.16b, { v4.16b, 5.16b }, v8[1]
+
+	// Index with qualifiers
+	luti2	v17.16b, { v21.16b }, v27.16b[3]
+	luti2	v17.8h, { v21.8h }, v27.8h[4]
+	luti4	v17.16b, { v21.16b }, v27.16b[1]
+	luti4	v17.8h, { v21.8h, v22.8h }, v27.8h[2]
+
+	// Index on the wrong operand
+	.macro index_wrong_operand, op, operand_type
+	\op	v17\operand_type[1], { v0\operand_type }, v31\operand_type
+	\op	v17[1], { v0\operand_type }, v31\operand_type
+	\op	v17\operand_type, { v0\operand_type[1] }, v31\operand_type
+	\op	v17\operand_type, { v0[1] }, v31\operand_type
+	.endm
+
+	index_wrong_operand luti2, .16b
+	index_wrong_operand luti2, .8h
+	index_wrong_operand luti4, .16b
+	luti4	v17.8h[1], { v0.8h, v1.8h }, v31.8h
+	luti4	v17[1], { v0.8h, v1.8h }, v31.8h
+	luti4	v17.8h, { v0.8h[1], v1.8h }, v31.8h
+	luti4	v17.8h, { v0[1], v1.8h }, v31.8h
+
+	// Missing index
+	luti2	v2.16b, { v4.16b }, v8.16b
+	luti2	v2.16b, { v4.16b }, v8
+	luti2	v2.8h, { v4.8h }, v8.8h
+	luti2	v2.8h, { v4.8h }, v8
+	luti4	v2.16b, { v4.16b }, v8.16b
+	luti4	v2.16b, { v4.16b }, v8
+	luti4	v2.8h, { v4.8h, v5.8h }, v8.8h
+	luti4	v2.8h, { v4.8h, v5.8h }, v8
+
+	// Out of range operands
+	.macro	out_of_range, op, operand_type, max_index_plus_one
+	\op	v32\operand_type, { v4\operand_type }, v8[1]
+	\op	v2\operand_type, { v32\operand_type }, v8[1]
+	\op	v2\operand_type, { v4\operand_type }, v32[1]
+	\op	v2\operand_type, { v4\operand_type }, v8[\max_index_plus_one]
+	\op	v2\operand_type, { v4\operand_type }, v8[-1]
+	.endm
+
+	out_of_range luti2, .16b, 4
+	out_of_range luti2, .8h, 8
+	out_of_range luti4, .16b, 2
+	luti4	v32.8h, { v4.8h, v5.8h }, v8[1]
+	luti4	v2.8h, { v31.8h, v32.8h }, v8[1]
+	luti4	v2.8h, { v4.8h, v5.8h }, v32[1]
+	luti4	v2.8h, { v4.8h, v5.8h }, v8[4]
+	luti4	v2.8h, { v4.8h, v5.8h }, v8[-1]
+
+	// Incorrect stride of operand
+	luti4	v2.8h, { v4.8h, v6.8h }, v8[2]
+
+	// Incorrect operands
+	luti2	v17.16b, { v21.16b, v22.16b }, v27[2]
+	luti2	v17.8h, { v21.8h, v22.8h }, v27[4]
+	luti4	v17.16b, { v21.16b, v22.16b }, v27[1]
+	luti4	v17.8h, { v21.8h }, v27[2]
diff --git a/gas/testsuite/gas/aarch64/advsimd-lut.d b/gas/testsuite/gas/aarch64/advsimd-lut.d
new file mode 100644
index 0000000000000000000000000000000000000000..0240d0ded6da108a1b135ec61a93ce99f4b52286
--- /dev/null
+++ b/gas/testsuite/gas/aarch64/advsimd-lut.d
@@ -0,0 +1,32 @@
+#objdump: -dr
+#as: -march=armv8-a+lut
+
+.*:     file format .*
+
+Disassembly of section \.text:
+
+0+ <.*>:
+[^:]+:	4e801000 	luti2	v0.16b, \{v0.16b\}, v0\[0\]
+[^:]+:	4e80101f 	luti2	v31.16b, \{v0.16b\}, v0\[0\]
+[^:]+:	4e8013e0 	luti2	v0.16b, \{v31.16b\}, v0\[0\]
+[^:]+:	4e9f1000 	luti2	v0.16b, \{v0.16b\}, v31\[0\]
+[^:]+:	4e9f7000 	luti2	v0.16b, \{v0.16b\}, v31\[3\]
+[^:]+:	4e9b52b1 	luti2	v17.16b, \{v21.16b\}, v27\[2\]
+[^:]+:	4ec00000 	luti2	v0.8h, \{v0.8h\}, v0\[0\]
+[^:]+:	4ec0001f 	luti2	v31.8h, \{v0.8h\}, v0\[0\]
+[^:]+:	4ec003e0 	luti2	v0.8h, \{v31.8h\}, v0\[0\]
+[^:]+:	4edf0000 	luti2	v0.8h, \{v0.8h\}, v31\[0\]
+[^:]+:	4ec07000 	luti2	v0.8h, \{v0.8h\}, v0\[7\]
+[^:]+:	4edb42b1 	luti2	v17.8h, \{v21.8h\}, v27\[4\]
+[^:]+:	4e402000 	luti4	v0.16b, \{v0.16b\}, v0\[0\]
+[^:]+:	4e40201f 	luti4	v31.16b, \{v0.16b\}, v0\[0\]
+[^:]+:	4e4023e0 	luti4	v0.16b, \{v31.16b\}, v0\[0\]
+[^:]+:	4e5f2000 	luti4	v0.16b, \{v0.16b\}, v31\[0\]
+[^:]+:	4e406000 	luti4	v0.16b, \{v0.16b\}, v0\[1\]
+[^:]+:	4e5b62b1 	luti4	v17.16b, \{v21.16b\}, v27\[1\]
+[^:]+:	4e401000 	luti4	v0.8h, \{v0.8h-v1.8h\}, v0\[0\]
+[^:]+:	4e40101f 	luti4	v31.8h, \{v0.8h-v1.8h\}, v0\[0\]
+[^:]+:	4e4013e0 	luti4	v0.8h, \{v31.8h-v0.8h\}, v0\[0\]
+[^:]+:	4e5f1000 	luti4	v0.8h, \{v0.8h-v1.8h\}, v31\[0\]
+[^:]+:	4e407000 	luti4	v0.8h, \{v0.8h-v1.8h\}, v0\[3\]
+[^:]+:	4e5b52b1 	luti4	v17.8h, \{v21.8h-v22.8h\}, v27\[2\]
diff --git a/gas/testsuite/gas/aarch64/advsimd-lut.s b/gas/testsuite/gas/aarch64/advsimd-lut.s
new file mode 100644
index 0000000000000000000000000000000000000000..03bc27ab2ab7fc16e9aa949d83ff1c024c985ad2
--- /dev/null
+++ b/gas/testsuite/gas/aarch64/advsimd-lut.s
@@ -0,0 +1,29 @@
+	// Valid luti2 instructions
+	luti2	v0.16b, { v0.16b }, v0[0]
+	luti2	v31.16b, { v0.16b }, v0[0]
+	luti2	v0.16b, { v31.16b }, v0[0]
+	luti2	v0.16b, { v0.16b }, v31[0]
+	luti2	v0.16b, { v0.16b }, v31[3]
+	luti2	v17.16b, { v21.16b }, v27[2]
+
+	luti2	v0.8h, { v0.8h }, v0[0]
+	luti2	v31.8h, { v0.8h }, v0[0]
+	luti2	v0.8h, { v31.8h }, v0[0]
+	luti2	v0.8h, { v0.8h }, v31[0]
+	luti2	v0.8h, { v0.8h }, v0[7]
+	luti2	v17.8h, { v21.8h }, v27[4]
+
+	// Valid luti4 instructions
+	luti4	v0.16b, { v0.16b }, v0[0]
+	luti4	v31.16b, { v0.16b }, v0[0]
+	luti4	v0.16b, { v31.16b }, v0[0]
+	luti4	v0.16b, { v0.16b }, v31[0]
+	luti4	v0.16b, { v0.16b }, v0[1]
+	luti4	v17.16b, { v21.16b }, v27[1]
+
+	luti4	v0.8h, { v0.8h, v1.8h }, v0[0]
+	luti4	v31.8h, { v0.8h, v1.8h }, v0[0]
+	luti4	v0.8h, { v31.8h, v0.8h }, v0[0]
+	luti4	v0.8h, { v0.8h, v1.8h }, v31[0]
+	luti4	v0.8h, { v0.8h, v1.8h }, v0[3]
+	luti4	v17.8h, { v21.8h, v22.8h }, v27[2]
diff --git a/include/opcode/aarch64.h b/include/opcode/aarch64.h
index 2fca9528c2012be983c2414a30fa5930e57e5c92..63456021a1d167c747ca913a355dd02cf90fc726 100644
--- a/include/opcode/aarch64.h
+++ b/include/opcode/aarch64.h
@@ -232,6 +232,8 @@ enum aarch64_feature_bit {
   AARCH64_FEATURE_CPA,
   /* FAMINMAX instructions.  */
   AARCH64_FEATURE_FAMINMAX,
+  /* LUT instructions.  */
+  AARCH64_FEATURE_LUT,
   AARCH64_NUM_FEATURES
 };
 
@@ -518,10 +520,14 @@ enum aarch64_opnd
   AARCH64_OPND_Em,	/* AdvSIMD Vector Element Vm.  */
   AARCH64_OPND_Em16,	/* AdvSIMD Vector Element Vm restricted to V0 - V15 when
 			   qualifier is S_H.  */
+  AARCH64_OPND_Em_INDEX1_14,  /* AdvSIMD 1-bit encoded index in Vm at [14]  */
+  AARCH64_OPND_Em_INDEX2_13,  /* AdvSIMD 2-bit encoded index in Vm at [14:13]  */
+  AARCH64_OPND_Em_INDEX3_12,  /* AdvSIMD 3-bit encoded index in Vm at [14:12]  */
   AARCH64_OPND_LVn,	/* AdvSIMD Vector register list used in e.g. TBL.  */
   AARCH64_OPND_LVt,	/* AdvSIMD Vector register list used in ld/st.  */
   AARCH64_OPND_LVt_AL,	/* AdvSIMD Vector register list for loading single
 			   structure to all lanes.  */
+  AARCH64_OPND_LVn_LUT,	/* AdvSIMD Vector register list used in lut.  */
   AARCH64_OPND_LEt,	/* AdvSIMD Vector Element list.  */
 
   AARCH64_OPND_CRn,	/* Co-processor register in CRn field.  */
@@ -1018,7 +1024,8 @@ enum aarch64_insn_class
   the,
   sve2_urqvs,
   sve_index1,
-  rcpc3
+  rcpc3,
+  lut
 };
 
 /* Opcode enumerators.  */
diff --git a/opcodes/aarch64-asm.h b/opcodes/aarch64-asm.h
index 88e389bfebda001efbb578a6e144dd5e2513cf78..edeb6d8de7e2c3e117e0ad91a02b93c0e040a061 100644
--- a/opcodes/aarch64-asm.h
+++ b/opcodes/aarch64-asm.h
@@ -47,6 +47,7 @@ AARCH64_DECL_OPD_INSERTER (ins_reglane);
 AARCH64_DECL_OPD_INSERTER (ins_reglist);
 AARCH64_DECL_OPD_INSERTER (ins_ldst_reglist);
 AARCH64_DECL_OPD_INSERTER (ins_ldst_reglist_r);
+AARCH64_DECL_OPD_INSERTER (ins_lut_reglist);
 AARCH64_DECL_OPD_INSERTER (ins_ldst_elemlist);
 AARCH64_DECL_OPD_INSERTER (ins_advsimd_imm_shift);
 AARCH64_DECL_OPD_INSERTER (ins_imm);
diff --git a/opcodes/aarch64-asm.c b/opcodes/aarch64-asm.c
index 5a55ca2f86db2d45b6cb54b5ee22606ec27c51fd..338ed54165d26cec2f0634bc62c1d7355ca4956a 100644
--- a/opcodes/aarch64-asm.c
+++ b/opcodes/aarch64-asm.c
@@ -168,6 +168,27 @@ aarch64_ins_reglane (const aarch64_operand *self, const aarch64_opnd_info *info,
       assert (reglane_index < 4);
       insert_field (FLD_SM3_imm2, code, reglane_index, 0);
     }
+  else if (inst->opcode->iclass == lut)
+    {
+      unsigned reglane_index = info->reglane.index;
+      switch (info->type)
+	{
+	case AARCH64_OPND_Em_INDEX1_14:
+	  assert (reglane_index < 2);
+	  insert_field (FLD_imm1_14, code, reglane_index, 0);
+	  break;
+	case AARCH64_OPND_Em_INDEX2_13:
+	  assert (reglane_index < 4);
+	  insert_field (FLD_imm2_13, code, reglane_index, 0);
+	  break;
+	case AARCH64_OPND_Em_INDEX3_12:
+	  assert (reglane_index < 8);
+	  insert_field (FLD_imm3_12, code, reglane_index, 0);
+	  break;
+	default:
+	  return false;
+	}
+    }
   else
     {
       /* index for e.g. SQDMLAL <Va><d>, <Vb><n>, <Vm>.<Ts>[<index>]
@@ -286,6 +307,17 @@ aarch64_ins_ldst_reglist_r (const aarch64_operand *self ATTRIBUTE_UNUSED,
   return true;
 }
 
+/* Insert regnos of register list operand for AdvSIMD lut instructions.  */
+bool
+aarch64_ins_lut_reglist (const aarch64_operand *self, const aarch64_opnd_info *info,
+		     aarch64_insn *code,
+		     const aarch64_inst *inst ATTRIBUTE_UNUSED,
+		     aarch64_operand_error *errors ATTRIBUTE_UNUSED)
+{
+  insert_field (self->fields[0], code, info->reglist.first_regno, 0);
+  return true;
+}
+
 /* Insert Q, opcode<2:1>, S, size and Rt fields for a register element list
    operand e.g. Vt in AdvSIMD load/store single element instructions.  */
 bool
diff --git a/opcodes/aarch64-dis.h b/opcodes/aarch64-dis.h
index 86494cc30937b1d7e4caf90630caec30c8b31d3e..9e8f7c214d70390a72f93e38655a5ac0f562d085 100644
--- a/opcodes/aarch64-dis.h
+++ b/opcodes/aarch64-dis.h
@@ -70,6 +70,7 @@ AARCH64_DECL_OPD_EXTRACTOR (ext_reglane);
 AARCH64_DECL_OPD_EXTRACTOR (ext_reglist);
 AARCH64_DECL_OPD_EXTRACTOR (ext_ldst_reglist);
 AARCH64_DECL_OPD_EXTRACTOR (ext_ldst_reglist_r);
+AARCH64_DECL_OPD_EXTRACTOR (ext_lut_reglist);
 AARCH64_DECL_OPD_EXTRACTOR (ext_ldst_elemlist);
 AARCH64_DECL_OPD_EXTRACTOR (ext_advsimd_imm_shift);
 AARCH64_DECL_OPD_EXTRACTOR (ext_shll_imm);
diff --git a/opcodes/aarch64-dis.c b/opcodes/aarch64-dis.c
index 96f42ae862a395bf3aa498c495fdcea9a3d12a41..986813c0b03b32c7478409293d07aafa83b4e85b 100644
--- a/opcodes/aarch64-dis.c
+++ b/opcodes/aarch64-dis.c
@@ -533,6 +533,21 @@ aarch64_ext_ldst_reglist_r (const aarch64_operand *self ATTRIBUTE_UNUSED,
   return true;
 }
 
+/* Decode AdvSIMD vector register list for AdvSIMD lut instructions.
+   The number of of registers in the list is determined by the opcode
+   flag.  */
+bool
+aarch64_ext_lut_reglist (const aarch64_operand *self, aarch64_opnd_info *info,
+		     const aarch64_insn code,
+		     const aarch64_inst *inst ATTRIBUTE_UNUSED,
+		     aarch64_operand_error *errors ATTRIBUTE_UNUSED)
+{
+  info->reglist.first_regno = extract_field (self->fields[0], code, 0);
+  info->reglist.num_regs = get_opcode_dependent_value (inst->opcode);
+  info->reglist.stride = 1;
+  return true;
+}
+
 /* Decode Q, opcode<2:1>, S, size and Rt fields of Vt in AdvSIMD
    load/store single element instructions.  */
 bool
diff --git a/opcodes/aarch64-opc.h b/opcodes/aarch64-opc.h
index 4e781f000cc38c12058530e5851b08083d42af52..23e634f1250de579661bbeb14d611b868b76bc8d 100644
--- a/opcodes/aarch64-opc.h
+++ b/opcodes/aarch64-opc.h
@@ -147,6 +147,7 @@ enum aarch64_field_kind
   FLD_imm1_2,
   FLD_imm1_8,
   FLD_imm1_10,
+  FLD_imm1_14,
   FLD_imm1_15,
   FLD_imm1_16,
   FLD_imm2_0,
@@ -154,6 +155,7 @@ enum aarch64_field_kind
   FLD_imm2_8,
   FLD_imm2_10,
   FLD_imm2_12,
+  FLD_imm2_13,
   FLD_imm2_15,
   FLD_imm2_16,
   FLD_imm2_19,
diff --git a/opcodes/aarch64-opc.c b/opcodes/aarch64-opc.c
index e88c616f4a9f3657756b919dc1196c08831c3cc5..61ab4c14a6393150f29a3fa1679a30b642bf8844 100644
--- a/opcodes/aarch64-opc.c
+++ b/opcodes/aarch64-opc.c
@@ -337,6 +337,7 @@ const aarch64_field fields[] =
     {  2,  1 },	/* imm1_2: general immediate in bits [2].  */
     {  8,  1 },	/* imm1_8: general immediate in bits [8].  */
     { 10,  1 },	/* imm1_10: general immediate in bits [10].  */
+    { 14,  1 },	/* imm1_14: general immediate in bits [14].  */
     { 15,  1 },	/* imm1_15: general immediate in bits [15].  */
     { 16,  1 },	/* imm1_16: general immediate in bits [16].  */
     {  0,  2 },	/* imm2_0: general immediate in bits [1:0].  */
@@ -344,6 +345,7 @@ const aarch64_field fields[] =
     {  8,  2 },	/* imm2_8: general immediate in bits [9:8].  */
     { 10,  2 }, /* imm2_10: 2-bit immediate, bits [11:10] */
     { 12,  2 }, /* imm2_12: 2-bit immediate, bits [13:12] */
+    { 13,  2 }, /* imm2_13: 2-bit immediate, bits [14:13] */
     { 15,  2 }, /* imm2_15: 2-bit immediate, bits [16:15] */
     { 16,  2 }, /* imm2_16: 2-bit immediate, bits [17:16] */
     { 19,  2 }, /* imm2_19: 2-bit immediate, bits [20:19] */
@@ -2554,6 +2556,10 @@ operand_general_constraint_met_p (const aarch64_opnd_info *opnds, int idx,
       num = get_opcode_dependent_value (opcode);
       switch (type)
 	{
+	case AARCH64_OPND_LVn_LUT:
+	  if (!check_reglist (opnd, mismatch_detail, idx, num, 1))
+	    return 0;
+	  break;
 	case AARCH64_OPND_LVt:
 	  assert (num >= 1 && num <= 4);
 	  /* Unless LD1/ST1, the number of registers should be equal to that
@@ -3165,6 +3171,14 @@ operand_general_constraint_met_p (const aarch64_opnd_info *opnds, int idx,
 	   and is halfed because complex numbers take two elements.  */
 	num = aarch64_get_qualifier_nelem (opnds[0].qualifier)
 	      * aarch64_get_qualifier_esize (opnds[0].qualifier) / 2;
+      else if (opcode->iclass == lut)
+	{
+	  size = get_operand_fields_width (get_operand_from_code (type)) - 5;
+	  if (!check_reglane (opnd, mismatch_detail, idx, "v", 0, 31,
+			      0, (1 << size) - 1))
+	    return 0;
+	  break;
+	}
       else
 	num = 16;
       num = num / aarch64_get_qualifier_esize (qualifier) - 1;
@@ -4069,6 +4083,14 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
 		style_imm (styler, "%" PRIi64, opnd->reglane.index));
       break;
 
+    case AARCH64_OPND_Em_INDEX1_14:
+    case AARCH64_OPND_Em_INDEX2_13:
+    case AARCH64_OPND_Em_INDEX3_12:
+      snprintf (buf, size, "%s[%s]",
+		style_reg (styler, "v%d", opnd->reglane.regno),
+		style_imm (styler, "%" PRIi64, opnd->reglane.index));
+      break;
+
     case AARCH64_OPND_VdD1:
     case AARCH64_OPND_VnD1:
       snprintf (buf, size, "%s[%s]",
@@ -4077,6 +4099,7 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
       break;
 
     case AARCH64_OPND_LVn:
+    case AARCH64_OPND_LVn_LUT:
     case AARCH64_OPND_LVt:
     case AARCH64_OPND_LVt_AL:
     case AARCH64_OPND_LEt:
diff --git a/opcodes/aarch64-tbl.h b/opcodes/aarch64-tbl.h
index 5b1c8561ac6147e64ba99b6e9fba85ed8ee712c4..6c64f4f35851acdc1ae66191ede7b5709b2afa87 100644
--- a/opcodes/aarch64-tbl.h
+++ b/opcodes/aarch64-tbl.h
@@ -1004,6 +1004,24 @@
   QLF3(V_16B, V_16B, V_16B),	\
 }
 
+/* e.g. luti2 <Vd>.16B, { <Vn>.16B }, <Vm>[index].  */
+/* The third operand is an AdvSIMD vector with a bit index
+   and without a type qualifier and is checked separately
+   based on operand enum.  */
+#define QL_VVUB			\
+{				\
+  QLF3(V_16B , V_16B , NIL),	\
+}
+
+/* e.g. luti2 <Vd>.8H, { <Vn>.8H }, <Vm>[index].  */
+/* The third operand is an AdvSIMD vector with a bit index
+   and without a type qualifier and is checked separately
+   based on operand enum.  */
+#define QL_VVUH			\
+{				\
+  QLF3(V_8H , V_8H , NIL),	\
+}
+
 /* e.g. EXT <Vd>.<T>, <Vn>.<T>, <Vm>.<T>, #<index>.  */
 #define QL_VEXT			\
 {					\
@@ -2669,6 +2687,8 @@ static const aarch64_feature_set aarch64_feature_faminmax_sve2 =
   AARCH64_FEATURES (2, FAMINMAX, SVE2);
 static const aarch64_feature_set aarch64_feature_faminmax_sme2 =
   AARCH64_FEATURES (3, SVE2, FAMINMAX, SME2);
+static const aarch64_feature_set aarch64_feature_lut =
+  AARCH64_FEATURE (LUT);
 
 #define CORE		&aarch64_feature_v8
 #define FP		&aarch64_feature_fp
@@ -2740,6 +2760,7 @@ static const aarch64_feature_set aarch64_feature_faminmax_sme2 =
 #define FAMINMAX  &aarch64_feature_faminmax
 #define FAMINMAX_SVE2  &aarch64_feature_faminmax_sve2
 #define FAMINMAX_SME2  &aarch64_feature_faminmax_sme2
+#define LUT &aarch64_feature_lut
 
 #define CORE_INSN(NAME,OPCODE,MASK,CLASS,OP,OPS,QUALS,FLAGS) \
   { NAME, OPCODE, MASK, CLASS, OP, CORE, OPS, QUALS, FLAGS, 0, 0, NULL }
@@ -2925,6 +2946,8 @@ static const aarch64_feature_set aarch64_feature_faminmax_sme2 =
 #define FAMINMAX_SME2_INSN(NAME,OPCODE,MASK,OPS,QUALS) \
   { NAME, OPCODE, MASK, sme_size_22_hsd, 0, FAMINMAX_SME2, OPS, QUALS, \
     F_STRICT | 0, 0, 1, NULL }
+#define LUT_INSN(NAME,OPCODE,MASK,OPS,QUALS,FLAGS)		\
+  { NAME, OPCODE, MASK, lut, 0, LUT, OPS, QUALS, FLAGS, 0, 0, NULL }
 
 #define MOPS_CPY_OP1_OP2_PME_INSN(NAME, OPCODE, MASK, FLAGS, CONSTRAINTS) \
   MOPS_INSN (NAME, OPCODE, MASK, 0, \
@@ -6456,6 +6479,12 @@ const struct aarch64_opcode aarch64_opcode_table[] =
   CPA_SVE_INSNC ("madpt", 0x44c0d800, 0xffe0fc00, sve_misc, OP3 (SVE_Zd, SVE_Zm_16, SVE_Za_5), OP_SVE_VVV_D, C_SCAN_MOVPRFX, 0),
   CPA_SVE_INSNC ("mlapt", 0x44c0d000, 0xffe0fc00, sve_misc, OP3 (SVE_Zd, SVE_Zn, SVE_Zm_16), OP_SVE_VVV_D, C_SCAN_MOVPRFX, 0),
 
+  /* AdvSIMD lut.  */
+  LUT_INSN ("luti2", 0x4e801000, 0xffe09c00, OP3 (Vd, LVn_LUT, Em_INDEX2_13), QL_VVUB, F_OD(1)),
+  LUT_INSN ("luti2", 0x4ec00000, 0xffe08c00, OP3 (Vd, LVn_LUT, Em_INDEX3_12), QL_VVUH, F_OD(1)),
+  LUT_INSN ("luti4", 0x4e402000, 0xffe0bc00, OP3 (Vd, LVn_LUT, Em_INDEX1_14), QL_VVUB, F_OD(1)),
+  LUT_INSN ("luti4", 0x4e401000, 0xffe09c00, OP3 (Vd, LVn_LUT, Em_INDEX2_13), QL_VVUH, F_OD(2)),
+
   {0, 0, 0, 0, 0, 0, {}, {}, 0, 0, 0, NULL},
 };
 
@@ -6531,12 +6560,20 @@ const struct aarch64_opcode aarch64_opcode_table[] =
       "a SIMD vector element")						\
     Y(SIMD_ELEMENT, reglane, "Em16", 0, F(FLD_Rm),			\
       "a SIMD vector element limited to V0-V15")			\
+    Y(SIMD_ELEMENT, simple_index, "Em_INDEX1_14", 0, F(FLD_Rm, FLD_imm1_14),	\
+      "a SIMD vector without a type qualifier encoding a bit index")	\
+    Y(SIMD_ELEMENT, simple_index, "Em_INDEX2_13", 0, F(FLD_Rm, FLD_imm2_13),	\
+      "a SIMD vector without a type qualifier encoding a bit index")	\
+    Y(SIMD_ELEMENT, simple_index, "Em_INDEX3_12", 0, F(FLD_Rm, FLD_imm3_12),	\
+      "a SIMD vector without a type qualifier encoding a bit index")	\
     Y(SIMD_REGLIST, reglist, "LVn", 0, F(FLD_Rn),			\
       "a SIMD vector register list")					\
     Y(SIMD_REGLIST, ldst_reglist, "LVt", 0, F(),			\
       "a SIMD vector register list")					\
     Y(SIMD_REGLIST, ldst_reglist_r, "LVt_AL", 0, F(),			\
       "a SIMD vector register list")					\
+    Y(SIMD_REGLIST, lut_reglist, "LVn_LUT", 0, F(FLD_Rn),		\
+      "a SIMD vector register list")					\
     Y(SIMD_REGLIST, ldst_elemlist, "LEt", 0, F(),			\
       "a SIMD vector element list")					\
     Y(IMMEDIATE, imm, "CRn", 0, F(FLD_CRn),				\
