@@ -1513,6 +1513,54 @@ parse_vector_reg_list (char **ccp, aarch64_reg_type type,
return error ? PARSE_FAIL : (ret_val << 2) | (nb_regs - 1);
}
+/* Parse a SIMD vector register with a bit index. The SIMD vectors with
+ bit indices don't have type qualifiers.
+
+ Return null if the string pointed to by *CCP is not a valid AdvSIMD
+ vector register with a bit index.
+
+ Otherwise return the register and the bit index information
+ in *typeinfo.
+
+ The validity of the bit index itself is checked separately in encoding.
+ */
+
+static const reg_entry *
+parse_simd_vector_with_bit_index (char **ccp, struct vector_type_el *typeinfo)
+{
+ char *str = *ccp;
+ const reg_entry *reg = parse_reg (&str);
+ struct vector_type_el atype;
+
+ // Setting it here as this is the convention followed in the
+ // rest of the code with indices.
+ atype.defined = NTA_HASINDEX;
+ // This will be set to correct value in parse_index_expressions.
+ atype.index = 0;
+ // The rest of the fields are not applicable for this operand.
+ atype.type = NT_invtype;
+ atype.width = -1;
+ atype.element_size = 0;
+
+ if (reg == NULL)
+ return NULL;
+
+ if (reg->type != REG_TYPE_V)
+ return NULL;
+
+ // Parse the bit index.
+ if (!skip_past_char (&str, '['))
+ return NULL;
+ if (!parse_index_expression (&str, &atype.index))
+ return NULL;
+ if (!skip_past_char (&str, ']'))
+ return NULL;
+
+ *typeinfo = atype;
+ *ccp = str;
+ return reg;
+}
+
/* Directives: register aliases. */
static reg_entry *
@@ -6761,6 +6809,23 @@ parse_operands (char *str, const aarch64_opcode *opcode)
reg_type = REG_TYPE_Z;
goto vector_reg_index;
+ case AARCH64_OPND_Em_INDEX1_14:
+ case AARCH64_OPND_Em_INDEX2_13:
+ case AARCH64_OPND_Em_INDEX3_12:
+ // These are SIMD vector operands with bit indices. For example,
+ // 'V27[3]'. These operands don't have type qualifiers before
+ // indices.
+ reg = parse_simd_vector_with_bit_index(&str, &vectype);
+
+ if (!reg)
+ goto failure;
+ gas_assert (vectype.defined & NTA_HASINDEX);
+
+ info->qualifier = AARCH64_OPND_QLF_NIL;
+ info->reglane.regno = reg->number;
+ info->reglane.index = vectype.index;
+ break;
+
case AARCH64_OPND_Ed:
case AARCH64_OPND_En:
case AARCH64_OPND_Em:
@@ -6812,6 +6877,7 @@ parse_operands (char *str, const aarch64_opcode *opcode)
goto vector_reg_list;
case AARCH64_OPND_LVn:
+ case AARCH64_OPND_LVn_LUT:
case AARCH64_OPND_LVt:
case AARCH64_OPND_LVt_AL:
case AARCH64_OPND_LEt:
@@ -10477,6 +10543,7 @@ static const struct aarch64_option_cpu_value_table aarch64_features[] = {
{"rcpc3", AARCH64_FEATURE (RCPC3), AARCH64_FEATURE (RCPC2)},
{"cpa", AARCH64_FEATURE (CPA), AARCH64_NO_FEATURES},
{"faminmax", AARCH64_FEATURE (FAMINMAX), AARCH64_FEATURE (SIMD)},
+ {"lut", AARCH64_FEATURE (LUT), AARCH64_FEATURE (SIMD)},
{NULL, AARCH64_NO_FEATURES, AARCH64_NO_FEATURES},
};
new file mode 100644
@@ -0,0 +1,3 @@
+#as:
+#source: advsimd-lut.s
+#error_output: advsimd-lut-bad.l
\ No newline at end of file
new file mode 100644
@@ -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\]'
new file mode 100644
@@ -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
new file mode 100644
@@ -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.8h, \{v4.8h\}, 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.8h, \{v4.8h\}, 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.8h, \{v4.8h\}, 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.8h, \{v4.8h\}, 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.8h, \{v4.8h\}, 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.8h, \{v4.8h\}, 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.8h, \{v4.8h\}, 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.8h, \{v4.8h-v5.8h\}, 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\]'
new file mode 100644
@@ -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]
new file mode 100644
@@ -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\]
new file mode 100644
@@ -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]
@@ -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. */
@@ -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);
@@ -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
@@ -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);
@@ -398,6 +398,23 @@ aarch64_ext_reglane (const aarch64_operand *self, aarch64_opnd_info *info,
/* index for e.g. SM3TT2A <Vd>.4S, <Vn>.4S, <Vm>S[<imm2>]. */
info->reglane.index = extract_field (FLD_SM3_imm2, code, 0);
}
+ else if (inst->opcode->iclass == lut)
+ {
+ switch (info->type)
+ {
+ case AARCH64_OPND_Em_INDEX1_14:
+ info->reglane.index = extract_field (FLD_imm1_14, code, 0);
+ break;
+ case AARCH64_OPND_Em_INDEX2_13:
+ info->reglane.index = extract_field (FLD_imm2_13, code, 0);
+ break;
+ case AARCH64_OPND_Em_INDEX3_12:
+ info->reglane.index = extract_field (FLD_imm3_12, code, 0);
+ break;
+ default:
+ return false;
+ }
+ }
else
{
/* Index only for e.g. SQDMLAL <Va><d>, <Vb><n>, <Vm>.<Ts>[<index>]
@@ -533,6 +550,21 @@ aarch64_ext_ldst_reglist_r (const aarch64_operand *self ATTRIBUTE_UNUSED,
return true;
}
+/* Decode AdvSIMD vector register list for AdvSIMD lut instructions.
+ The number of of registers in the list is determined by the opcode
+ flag. */
+bool
+aarch64_ext_lut_reglist (const aarch64_operand *self, aarch64_opnd_info *info,
+ const aarch64_insn code,
+ const aarch64_inst *inst ATTRIBUTE_UNUSED,
+ aarch64_operand_error *errors ATTRIBUTE_UNUSED)
+{
+ info->reglist.first_regno = extract_field (self->fields[0], code, 0);
+ info->reglist.num_regs = get_opcode_dependent_value (inst->opcode);
+ info->reglist.stride = 1;
+ return true;
+}
+
/* Decode Q, opcode<2:1>, S, size and Rt fields of Vt in AdvSIMD
load/store single element instructions. */
bool
@@ -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,
@@ -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:
@@ -1004,6 +1004,24 @@
QLF3(V_16B, V_16B, V_16B), \
}
+/* e.g. luti2 <Vd>.16B, { <Vn>.16B }, <Vm>[index]. */
+/* The third operand is an AdvSIMD vector with a bit index
+ and without a type qualifier and is checked separately
+ based on operand enum. */
+#define QL_VVUB \
+{ \
+ QLF3(V_16B , V_16B , NIL), \
+}
+
+/* e.g. luti2 <Vd>.8H, { <Vn>.8H }, <Vm>[index]. */
+/* The third operand is an AdvSIMD vector with a bit index
+ and without a type qualifier and is checked separately
+ based on operand enum. */
+#define QL_VVUH \
+{ \
+ QLF3(V_8H , V_8H , NIL), \
+}
+
/* e.g. EXT <Vd>.<T>, <Vn>.<T>, <Vm>.<T>, #<index>. */
#define QL_VEXT \
{ \
@@ -2669,6 +2687,8 @@ static const aarch64_feature_set aarch64_feature_faminmax_sve2 =
AARCH64_FEATURES (2, FAMINMAX, SVE2);
static const aarch64_feature_set aarch64_feature_faminmax_sme2 =
AARCH64_FEATURES (3, SVE2, FAMINMAX, SME2);
+static const aarch64_feature_set aarch64_feature_lut =
+ AARCH64_FEATURE (LUT);
#define CORE &aarch64_feature_v8
#define FP &aarch64_feature_fp
@@ -2740,6 +2760,7 @@ static const aarch64_feature_set aarch64_feature_faminmax_sme2 =
#define FAMINMAX &aarch64_feature_faminmax
#define FAMINMAX_SVE2 &aarch64_feature_faminmax_sve2
#define FAMINMAX_SME2 &aarch64_feature_faminmax_sme2
+#define LUT &aarch64_feature_lut
#define CORE_INSN(NAME,OPCODE,MASK,CLASS,OP,OPS,QUALS,FLAGS) \
{ NAME, OPCODE, MASK, CLASS, OP, CORE, OPS, QUALS, FLAGS, 0, 0, NULL }
@@ -2925,6 +2946,8 @@ static const aarch64_feature_set aarch64_feature_faminmax_sme2 =
#define FAMINMAX_SME2_INSN(NAME,OPCODE,MASK,OPS,QUALS) \
{ NAME, OPCODE, MASK, sme_size_22_hsd, 0, FAMINMAX_SME2, OPS, QUALS, \
F_STRICT | 0, 0, 1, NULL }
+#define LUT_INSN(NAME,OPCODE,MASK,OPS,QUALS,FLAGS) \
+ { NAME, OPCODE, MASK, lut, 0, LUT, OPS, QUALS, FLAGS, 0, 0, NULL }
#define MOPS_CPY_OP1_OP2_PME_INSN(NAME, OPCODE, MASK, FLAGS, CONSTRAINTS) \
MOPS_INSN (NAME, OPCODE, MASK, 0, \
@@ -4275,6 +4298,11 @@ const struct aarch64_opcode aarch64_opcode_table[] =
FAMINMAX_SME2_INSN ("famax", 0xc120b940, 0xff23ffe3, OP3 (SME_Zdnx4, SME_Zdnx4, SME_Zmx4), OP_SVE_VVV_HSD),
FAMINMAX_SME2_INSN ("famin", 0xc120b141, 0xff21ffe1, OP3 (SME_Zdnx2, SME_Zdnx2, SME_Zmx2), OP_SVE_VVV_HSD),
FAMINMAX_SME2_INSN ("famin", 0xc120b941, 0xff23ffe3, OP3 (SME_Zdnx4, SME_Zdnx4, SME_Zmx4), OP_SVE_VVV_HSD),
+ /* AdvSIMD lut. */
+ LUT_INSN ("luti2", 0x4e801000, 0xffe09c00, OP3 (Vd, LVn_LUT, Em_INDEX2_13), QL_VVUB, F_OD(1)),
+ LUT_INSN ("luti2", 0x4ec00000, 0xffe08c00, OP3 (Vd, LVn_LUT, Em_INDEX3_12), QL_VVUH, F_OD(1)),
+ LUT_INSN ("luti4", 0x4e402000, 0xffe0bc00, OP3 (Vd, LVn_LUT, Em_INDEX1_14), QL_VVUB, F_OD(1)),
+ LUT_INSN ("luti4", 0x4e401000, 0xffe09c00, OP3 (Vd, LVn_LUT, Em_INDEX2_13), QL_VVUH, F_OD(2)),
/* Move wide (immediate). */
CORE_INSN ("movn", 0x12800000, 0x7f800000, movewide, OP_MOVN, OP2 (Rd, HALF), QL_DST_R, F_SF | F_HAS_ALIAS),
CORE_INSN ("mov", 0x12800000, 0x7f800000, movewide, OP_MOV_IMM_WIDEN, OP2 (Rd, IMM_MOV), QL_DST_R, F_SF | F_ALIAS | F_CONV),
@@ -6531,12 +6559,20 @@ const struct aarch64_opcode aarch64_opcode_table[] =
"a SIMD vector element") \
Y(SIMD_ELEMENT, reglane, "Em16", 0, F(FLD_Rm), \
"a SIMD vector element limited to V0-V15") \
+ Y(SIMD_ELEMENT, reglane, "Em_INDEX1_14", 0, F(FLD_Rm, FLD_imm1_14), \
+ "a SIMD vector without a type qualifier encoding a bit index") \
+ Y(SIMD_ELEMENT, reglane, "Em_INDEX2_13", 0, F(FLD_Rm, FLD_imm2_13), \
+ "a SIMD vector without a type qualifier encoding a bit index") \
+ Y(SIMD_ELEMENT, reglane, "Em_INDEX3_12", 0, F(FLD_Rm, FLD_imm3_12), \
+ "a SIMD vector without a type qualifier encoding a bit index") \
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), \