This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH][AArch64] Add ARMv8.3 FCMLA and FCADD instructions


Add support for FCMLA and FCADD complex arithmetic SIMD instructions.
FCMLA has an indexed element variant where the index range has to be
treated specially because a complex number takes two elements and the
indexed vector size depends on the other operands.

These complex number SIMD instructions are part of ARMv8.3
https://community.arm.com/groups/processors/blog/2016/10/27/armv8-a-architecture-2016-additions

(generated files are not in the diff.)

gas/
2016-11-07  Szabolcs Nagy  <szabolcs.nagy@arm.com>

	* config/tc-aarch64.c (parse_operands): Handle AARCH64_OPND_IMM_ROT*.

include/
2016-11-07  Szabolcs Nagy  <szabolcs.nagy@arm.com>

	* opcode/aarch64.h (enum aarch64_opnd): Add AARCH64_OPND_IMM_ROT1,
	AARCH64_OPND_IMM_ROT2, AARCH64_OPND_IMM_ROT3.
	(enum aarch64_op): Add OP_FCMLA_ELEM.

opcodes/
2016-11-07  Szabolcs Nagy  <szabolcs.nagy@arm.com>

	* aarch64-tbl.h (QL_V3SAMEHSD_ROT, QL_ELEMENT_ROT): Define.
	(aarch64_feature_simd_v8_3, SIMD_V8_3): Define.
	(aarch64_opcode_table): Add fcmla and fcadd.
	(AARCH64_OPERANDS): Add IMM_ROT{1,2,3}.
	* aarch64-asm.h (aarch64_ins_imm_rotate): Declare.
	* aarch64-asm.c (aarch64_ins_imm_rotate): Define.
	* aarch64-dis.h (aarch64_ext_imm_rotate): Declare.
	* aarch64-dis.c (aarch64_ext_imm_rotate): Define.
	* aarch64-opc.h (enum aarch64_field_kind): Add FLD_rotate{1,2,3}.
	* aarch64-opc.c (fields): Add FLD_rotate{1,2,3}.
	(operand_general_constraint_met_p): Rotate and index range check.
	(aarch64_print_operand): Handle rotate operand.
	* aarch64-asm-2.c: Regenerate.
	* aarch64-dis-2.c: Likewise.
	* aarch64-opc-2.c: Likewise.

gas/testsuite/
2016-11-07  Szabolcs Nagy  <szabolcs.nagy@arm.com>

	* gas/aarch64/advsimd-armv8_3.d: New.
	* gas/aarch64/advsimd-armv8_3.s: New.
	* gas/aarch64/illegal-fcmla.s: New.
	* gas/aarch64/illegal-fcmla.l: New.
	* gas/aarch64/illegal-fcmla.d: New.

diff --git a/gas/config/tc-aarch64.c b/gas/config/tc-aarch64.c
index a9cee79..8b839c6 100644
--- a/gas/config/tc-aarch64.c
+++ b/gas/config/tc-aarch64.c
@@ -5561,6 +5561,9 @@ parse_operands (char *str, const aarch64_opcode *opcode)
 	case AARCH64_OPND_SVE_UIMM7:
 	case AARCH64_OPND_SVE_UIMM8:
 	case AARCH64_OPND_SVE_UIMM8_53:
+	case AARCH64_OPND_IMM_ROT1:
+	case AARCH64_OPND_IMM_ROT2:
+	case AARCH64_OPND_IMM_ROT3:
 	  po_imm_nc_or_fail ();
 	  info->imm.value = val;
 	  break;
diff --git a/gas/testsuite/gas/aarch64/advsimd-armv8_3.d b/gas/testsuite/gas/aarch64/advsimd-armv8_3.d
new file mode 100644
index 0000000..0e477e4
--- /dev/null
+++ b/gas/testsuite/gas/aarch64/advsimd-armv8_3.d
@@ -0,0 +1,33 @@
+#as: -march=armv8.3-a
+#objdump: -dr
+
+.*:     file format .*
+
+Disassembly of section \.text:
+
+0000000000000000 <.*>:
+[^:]+:	6ec3c441 	fcmla	v1.2d, v2.2d, v3.2d, #0
+[^:]+:	6ec3cc41 	fcmla	v1.2d, v2.2d, v3.2d, #90
+[^:]+:	6ec3d441 	fcmla	v1.2d, v2.2d, v3.2d, #180
+[^:]+:	6ec3dc41 	fcmla	v1.2d, v2.2d, v3.2d, #270
+[^:]+:	2e83cc41 	fcmla	v1.2s, v2.2s, v3.2s, #90
+[^:]+:	6e83cc41 	fcmla	v1.4s, v2.4s, v3.4s, #90
+[^:]+:	2e43cc41 	fcmla	v1.4h, v2.4h, v3.4h, #90
+[^:]+:	6e43cc41 	fcmla	v1.8h, v2.8h, v3.8h, #90
+[^:]+:	6f831041 	fcmla	v1.4s, v2.4s, v3.s\[0\], #0
+[^:]+:	6f833041 	fcmla	v1.4s, v2.4s, v3.s\[0\], #90
+[^:]+:	6f835041 	fcmla	v1.4s, v2.4s, v3.s\[0\], #180
+[^:]+:	6f837041 	fcmla	v1.4s, v2.4s, v3.s\[0\], #270
+[^:]+:	6f833841 	fcmla	v1.4s, v2.4s, v3.s\[1\], #90
+[^:]+:	2f433041 	fcmla	v1.4h, v2.4h, v3.h\[0\], #90
+[^:]+:	2f633041 	fcmla	v1.4h, v2.4h, v3.h\[1\], #90
+[^:]+:	6f433041 	fcmla	v1.8h, v2.8h, v3.h\[0\], #90
+[^:]+:	6f633041 	fcmla	v1.8h, v2.8h, v3.h\[1\], #90
+[^:]+:	6f433841 	fcmla	v1.8h, v2.8h, v3.h\[2\], #90
+[^:]+:	6f633841 	fcmla	v1.8h, v2.8h, v3.h\[3\], #90
+[^:]+:	6ec3e441 	fcadd	v1.2d, v2.2d, v3.2d, #90
+[^:]+:	6ec3f441 	fcadd	v1.2d, v2.2d, v3.2d, #270
+[^:]+:	2e83e441 	fcadd	v1.2s, v2.2s, v3.2s, #90
+[^:]+:	6e83e441 	fcadd	v1.4s, v2.4s, v3.4s, #90
+[^:]+:	2e43e441 	fcadd	v1.4h, v2.4h, v3.4h, #90
+[^:]+:	6e43e441 	fcadd	v1.8h, v2.8h, v3.8h, #90
diff --git a/gas/testsuite/gas/aarch64/advsimd-armv8_3.s b/gas/testsuite/gas/aarch64/advsimd-armv8_3.s
new file mode 100644
index 0000000..bfb94e5
--- /dev/null
+++ b/gas/testsuite/gas/aarch64/advsimd-armv8_3.s
@@ -0,0 +1,36 @@
+/* Test file for ARMv8.3 complex arithmetics instructions.  */
+	.text
+
+	/* Three-same operands FCMLA.  */
+	fcmla	v1.2d, v2.2d, v3.2d, #0
+	fcmla	v1.2d, v2.2d, v3.2d, #90
+	fcmla	v1.2d, v2.2d, v3.2d, #180
+	fcmla	v1.2d, v2.2d, v3.2d, #270
+
+	fcmla	v1.2s, v2.2s, v3.2s, #90
+	fcmla	v1.4s, v2.4s, v3.4s, #90
+	fcmla	v1.4h, v2.4h, v3.4h, #90
+	fcmla	v1.8h, v2.8h, v3.8h, #90
+
+	/* Indexed element FCMLA.  */
+	fcmla	v1.4s, v2.4s, v3.s[0], #0
+	fcmla	v1.4s, v2.4s, v3.s[0], #90
+	fcmla	v1.4s, v2.4s, v3.s[0], #180
+	fcmla	v1.4s, v2.4s, v3.s[0], #270
+	fcmla	v1.4s, v2.4s, v3.s[1], #90
+
+	fcmla	v1.4h, v2.4h, v3.h[0], #90
+	fcmla	v1.4h, v2.4h, v3.h[1], #90
+	fcmla	v1.8h, v2.8h, v3.h[0], #90
+	fcmla	v1.8h, v2.8h, v3.h[1], #90
+	fcmla	v1.8h, v2.8h, v3.h[2], #90
+	fcmla	v1.8h, v2.8h, v3.h[3], #90
+
+	/* Three-same operands FADD.  */
+	fcadd	v1.2d, v2.2d, v3.2d, #90
+	fcadd	v1.2d, v2.2d, v3.2d, #270
+
+	fcadd	v1.2s, v2.2s, v3.2s, #90
+	fcadd	v1.4s, v2.4s, v3.4s, #90
+	fcadd	v1.4h, v2.4h, v3.4h, #90
+	fcadd	v1.8h, v2.8h, v3.8h, #90
diff --git a/gas/testsuite/gas/aarch64/illegal-fcmla.d b/gas/testsuite/gas/aarch64/illegal-fcmla.d
new file mode 100644
index 0000000..af94c51
--- /dev/null
+++ b/gas/testsuite/gas/aarch64/illegal-fcmla.d
@@ -0,0 +1,2 @@
+#as: -march=armv8.3-a -mno-verbose-error
+#error-output: illegal-fcmla.l
diff --git a/gas/testsuite/gas/aarch64/illegal-fcmla.l b/gas/testsuite/gas/aarch64/illegal-fcmla.l
new file mode 100644
index 0000000..1c0f1e4
--- /dev/null
+++ b/gas/testsuite/gas/aarch64/illegal-fcmla.l
@@ -0,0 +1,17 @@
+[^:]*: Assembler messages:
+[^:]+:10: Error: rotate expected to be 0, 90, 180 or 270 at operand 4 -- `fcmla v0\.4s,v1\.4s,v2\.s\[0\],#-90'
+[^:]+:11: Error: rotate expected to be 0, 90, 180 or 270 at operand 4 -- `fcmla v0\.4s,v1\.4s,v2\.s\[0\],#30'
+[^:]+:12: Error: rotate expected to be 0, 90, 180 or 270 at operand 4 -- `fcmla v0\.4s,v1\.4s,v2\.s\[0\],#360'
+[^:]+:13: Error: register element index out of range 0 to 1 at operand 3 -- `fcmla v0\.4h,v1\.4h,v2\.h\[2\],#90'
+[^:]+:14: Error: register element index out of range 0 to 3 at operand 3 -- `fcmla v0\.8h,v1\.8h,v2\.h\[4\],#90'
+[^:]+:15: Error: register element index out of range 0 to 1 at operand 3 -- `fcmla v0\.4s,v1\.4s,v2\.s\[2\],#90'
+[^:]+:16: Error: operand mismatch -- `fcmla v0\.2s,v1\.2s,v2\.s\[0\],#90'
+[^:]+:17: Error: operand mismatch -- `fcmla v0\.4s,v1\.4s,v2\.d\[0\],#90'
+[^:]+:18: Error: operand mismatch -- `fcmla v0\.2d,v1\.2d,v2\.d\[0\],#0'
+[^:]+:19: Error: rotate expected to be 0, 90, 180 or 270 at operand 4 -- `fcmla v0\.4s,v1\.4s,v2\.4s,#-90'
+[^:]+:20: Error: rotate expected to be 0, 90, 180 or 270 at operand 4 -- `fcmla v0\.4s,v1\.4s,v2\.4s,#30'
+[^:]+:21: Error: rotate expected to be 0, 90, 180 or 270 at operand 4 -- `fcmla v0\.4s,v1\.4s,v2\.4s,#360'
+[^:]+:22: Error: invalid element size 8 and vector size combination s at operand 1 -- `fcmla v0\.8s,v1\.8s,v2\.8s,#0'
+[^:]+:23: Error: operand mismatch -- `fcmla v0\.1d,v1\.1d,v2\.1d,#0'
+[^:]+:24: Error: rotate expected to be 90 or 270 at operand 4 -- `fcadd v0\.4h,v1\.4h,v2\.4h,#0'
+[^:]+:25: Error: rotate expected to be 90 or 270 at operand 4 -- `fcadd v0\.4h,v1\.4h,v2\.4h,#180'
diff --git a/gas/testsuite/gas/aarch64/illegal-fcmla.s b/gas/testsuite/gas/aarch64/illegal-fcmla.s
new file mode 100644
index 0000000..882c7ba
--- /dev/null
+++ b/gas/testsuite/gas/aarch64/illegal-fcmla.s
@@ -0,0 +1,25 @@
+// Test illegal ARMv8.3 FCMLA and FCADD instructions with -march=armv8.3-a.
+.text
+
+	// Good.
+	fcmla v0.4s, v1.4s, v2.s[0], #90
+	fcmla v0.4s, v1.4s, v2.4s, #90
+	fcadd v0.4h, v1.4h, v2.4h, #90
+
+	// Bad.
+	fcmla v0.4s, v1.4s, v2.s[0], #-90
+	fcmla v0.4s, v1.4s, v2.s[0], #30
+	fcmla v0.4s, v1.4s, v2.s[0], #360
+	fcmla v0.4h, v1.4h, v2.h[2], #90
+	fcmla v0.8h, v1.8h, v2.h[4], #90
+	fcmla v0.4s, v1.4s, v2.s[2], #90
+	fcmla v0.2s, v1.2s, v2.s[0], #90
+	fcmla v0.4s, v1.4s, v2.d[0], #90
+	fcmla v0.2d, v1.2d, v2.d[0], #0
+	fcmla v0.4s, v1.4s, v2.4s, #-90
+	fcmla v0.4s, v1.4s, v2.4s, #30
+	fcmla v0.4s, v1.4s, v2.4s, #360
+	fcmla v0.8s, v1.8s, v2.8s, #0
+	fcmla v0.1d, v1.1d, v2.1d, #0
+	fcadd v0.4h, v1.4h, v2.4h, #0
+	fcadd v0.4h, v1.4h, v2.4h, #180
diff --git a/include/opcode/aarch64.h b/include/opcode/aarch64.h
index a35a813..69645d0 100644
--- a/include/opcode/aarch64.h
+++ b/include/opcode/aarch64.h
@@ -204,6 +204,9 @@ enum aarch64_opnd
   AARCH64_OPND_HALF,	/* #<imm16>{, LSL #<shift>} operand in move wide.  */
   AARCH64_OPND_FBITS,	/* FP #<fbits> operand in e.g. SCVTF */
   AARCH64_OPND_IMM_MOV,	/* Immediate operand for the MOV alias.  */
+  AARCH64_OPND_IMM_ROT1,	/* Immediate rotate operand for FCMLA.  */
+  AARCH64_OPND_IMM_ROT2,	/* Immediate rotate operand for indexed FCMLA.  */
+  AARCH64_OPND_IMM_ROT3,	/* Immediate rotate operand for FCADD.  */
 
   AARCH64_OPND_COND,	/* Standard condition as the last operand.  */
   AARCH64_OPND_COND1,	/* Same as the above, but excluding AL and NV.  */
@@ -596,6 +599,8 @@ enum aarch64_op
   OP_NOTS_P_P_P_Z,
   OP_NOT_P_P_P_Z,
 
+  OP_FCMLA_ELEM,	/* ARMv8.3, indexed element version.  */
+
   OP_TOTAL_NUM,		/* Pseudo.  */
 };
 
diff --git a/opcodes/aarch64-asm.c b/opcodes/aarch64-asm.c
index 64051a9..cfe6630 100644
--- a/opcodes/aarch64-asm.c
+++ b/opcodes/aarch64-asm.c
@@ -125,19 +125,28 @@ aarch64_ins_reglane (const aarch64_operand *self, const aarch64_opnd_info *info,
     {
       /* index for e.g. SQDMLAL <Va><d>, <Vb><n>, <Vm>.<Ts>[<index>]
          or SQDMLAL <Va><d>, <Vb><n>, <Vm>.<Ts>[<index>].  */
+      unsigned index = info->reglane.index;
+
+      if (inst->opcode->op == OP_FCMLA_ELEM)
+	/* Complex operand takes two elements.  */
+	index *= 2;
+
       switch (info->qualifier)
 	{
 	case AARCH64_OPND_QLF_S_H:
 	  /* H:L:M */
-	  insert_fields (code, info->reglane.index, 0, 3, FLD_M, FLD_L, FLD_H);
+	  assert (index < 8);
+	  insert_fields (code, index, 0, 3, FLD_M, FLD_L, FLD_H);
 	  break;
 	case AARCH64_OPND_QLF_S_S:
 	  /* H:L */
-	  insert_fields (code, info->reglane.index, 0, 2, FLD_L, FLD_H);
+	  assert (index < 4);
+	  insert_fields (code, index, 0, 2, FLD_L, FLD_H);
 	  break;
 	case AARCH64_OPND_QLF_S_D:
 	  /* H */
-	  insert_field (FLD_H, code, info->reglane.index, 0);
+	  assert (index < 2);
+	  insert_field (FLD_H, code, index, 0);
 	  break;
 	default:
 	  assert (0);
@@ -427,6 +436,41 @@ aarch64_ins_fpimm (const aarch64_operand *self, const aarch64_opnd_info *info,
   return NULL;
 }
 
+/* Insert field rot for the rotate immediate in
+   FCMLA <Vd>.<T>, <Vn>.<T>, <Vm>.<T>, #<rotate>.  */
+const char *
+aarch64_ins_imm_rotate (const aarch64_operand *self,
+			const aarch64_opnd_info *info,
+			aarch64_insn *code, const aarch64_inst *inst)
+{
+  uint64_t rot = info->imm.value / 90;
+
+  switch (info->type)
+    {
+    case AARCH64_OPND_IMM_ROT1:
+    case AARCH64_OPND_IMM_ROT2:
+      /* value	rot
+	 0	0
+	 90	1
+	 180	2
+	 270	3  */
+      assert (rot < 4U);
+      break;
+    case AARCH64_OPND_IMM_ROT3:
+      /* value	rot
+	 90	0
+	 270	1  */
+      rot = (rot - 1) / 2;
+      assert (rot < 2U);
+      break;
+    default:
+      assert (0);
+    }
+  insert_field (self->fields[0], code, rot, inst->opcode->mask);
+
+  return NULL;
+}
+
 /* Insert #<fbits> for the immediate operand in fp fix-point instructions,
    e.g.  SCVTF <Dd>, <Wn>, #<fbits>.  */
 const char *
diff --git a/opcodes/aarch64-asm.h b/opcodes/aarch64-asm.h
index b49d3d5..7fce657 100644
--- a/opcodes/aarch64-asm.h
+++ b/opcodes/aarch64-asm.h
@@ -92,6 +92,7 @@ AARCH64_DECL_OPD_INSERTER (ins_sve_reglist);
 AARCH64_DECL_OPD_INSERTER (ins_sve_scale);
 AARCH64_DECL_OPD_INSERTER (ins_sve_shlimm);
 AARCH64_DECL_OPD_INSERTER (ins_sve_shrimm);
+AARCH64_DECL_OPD_INSERTER (ins_imm_rotate);
 
 #undef AARCH64_DECL_OPD_INSERTER
 
diff --git a/opcodes/aarch64-dis.c b/opcodes/aarch64-dis.c
index 245749c..ed58058 100644
--- a/opcodes/aarch64-dis.c
+++ b/opcodes/aarch64-dis.c
@@ -351,6 +351,14 @@ aarch64_ext_reglane (const aarch64_operand *self, aarch64_opnd_info *info,
 	default:
 	  return 0;
 	}
+
+      if (inst->opcode->op == OP_FCMLA_ELEM)
+	{
+	  /* Complex operand takes two elements.  */
+	  if (info->reglane.index & 1)
+	    return 0;
+	  info->reglane.index /= 2;
+	}
     }
 
   return 1;
@@ -703,6 +711,40 @@ aarch64_ext_fpimm (const aarch64_operand *self, aarch64_opnd_info *info,
   return 1;
 }
 
+/* Decode rotate immediate for FCMLA <Vd>.<T>, <Vn>.<T>, <Vm>.<T>, #rotate.  */
+int
+aarch64_ext_imm_rotate (const aarch64_operand *self, aarch64_opnd_info *info,
+			const aarch64_insn code,
+			const aarch64_inst *inst ATTRIBUTE_UNUSED)
+{
+  uint64_t rot = extract_field (self->fields[0], code, 0);
+
+  switch (info->type)
+    {
+    case AARCH64_OPND_IMM_ROT1:
+    case AARCH64_OPND_IMM_ROT2:
+      /* rot	value
+	 0	0
+	 1	90
+	 2	180
+	 3	270  */
+      assert (rot < 4U);
+      break;
+    case AARCH64_OPND_IMM_ROT3:
+      /* rot	value
+	 0	90
+	 1	270  */
+      assert (rot < 2U);
+      rot = 2 * rot + 1;
+      break;
+    default:
+      assert (0);
+      return 0;
+    }
+  info->imm.value = rot * 90;
+  return 1;
+}
+
 /* Decode scale for e.g. SCVTF <Dd>, <Wn>, #<fbits>.  */
 int
 aarch64_ext_fbits (const aarch64_operand *self ATTRIBUTE_UNUSED,
diff --git a/opcodes/aarch64-dis.h b/opcodes/aarch64-dis.h
index 48be5e4..b11f261 100644
--- a/opcodes/aarch64-dis.h
+++ b/opcodes/aarch64-dis.h
@@ -114,6 +114,7 @@ AARCH64_DECL_OPD_EXTRACTOR (ext_sve_reglist);
 AARCH64_DECL_OPD_EXTRACTOR (ext_sve_scale);
 AARCH64_DECL_OPD_EXTRACTOR (ext_sve_shlimm);
 AARCH64_DECL_OPD_EXTRACTOR (ext_sve_shrimm);
+AARCH64_DECL_OPD_EXTRACTOR (ext_imm_rotate);
 
 #undef AARCH64_DECL_OPD_EXTRACTOR
 
diff --git a/opcodes/aarch64-opc.c b/opcodes/aarch64-opc.c
index c85abc6..5b9eb27 100644
--- a/opcodes/aarch64-opc.c
+++ b/opcodes/aarch64-opc.c
@@ -309,7 +309,10 @@ const aarch64_field fields[] =
     {  8,  2 }, /* SVE_tszl_8: triangular size select low, bits [9,8].  */
     { 19,  2 }, /* SVE_tszl_19: triangular size select low, bits [20,19].  */
     { 14,  1 }, /* SVE_xs_14: UXTW/SXTW select (bit 14).  */
-    { 22,  1 }  /* SVE_xs_22: UXTW/SXTW select (bit 22).  */
+    { 22,  1 }, /* SVE_xs_22: UXTW/SXTW select (bit 22).  */
+    { 11,  2 }, /* rotate1: FCMLA immediate rotate.  */
+    { 13,  2 }, /* rotate2: Indexed element FCMLA immediate rotate.  */
+    { 12,  1 }, /* rotate3: FCADD immediate rotate.  */
 };
 
 enum aarch64_operand_class
@@ -2097,6 +2100,28 @@ operand_general_constraint_met_p (const aarch64_opnd_info *opnds, int idx,
 	    }
 	  break;
 
+	case AARCH64_OPND_IMM_ROT1:
+	case AARCH64_OPND_IMM_ROT2:
+	  if (opnd->imm.value != 0
+	      && opnd->imm.value != 90
+	      && opnd->imm.value != 180
+	      && opnd->imm.value != 270)
+	    {
+	      set_other_error (mismatch_detail, idx,
+			       _("rotate expected to be 0, 90, 180 or 270"));
+	      return 0;
+	    }
+	  break;
+
+	case AARCH64_OPND_IMM_ROT3:
+	  if (opnd->imm.value != 90 && opnd->imm.value != 270)
+	    {
+	      set_other_error (mismatch_detail, idx,
+			       _("rotate expected to be 90 or 270"));
+	      return 0;
+	    }
+	  break;
+
 	case AARCH64_OPND_SHLL_IMM:
 	  assert (idx == 2);
 	  size = 8 * aarch64_get_qualifier_esize (opnds[idx - 1].qualifier);
@@ -2436,7 +2461,15 @@ operand_general_constraint_met_p (const aarch64_opnd_info *opnds, int idx,
 
     case AARCH64_OPND_CLASS_SIMD_ELEMENT:
       /* Get the upper bound for the element index.  */
-      num = 16 / aarch64_get_qualifier_esize (qualifier) - 1;
+      if (opcode->op == OP_FCMLA_ELEM)
+	/* FCMLA index range depends on the vector size of other operands
+	   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
+	num = 16;
+      num = num / aarch64_get_qualifier_esize (qualifier) - 1;
+
       /* Index out-of-range.  */
       if (!value_in_range_p (opnd->reglane.index, 0, num))
 	{
@@ -3185,6 +3218,9 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
     case AARCH64_OPND_SVE_UIMM7:
     case AARCH64_OPND_SVE_UIMM8:
     case AARCH64_OPND_SVE_UIMM8_53:
+    case AARCH64_OPND_IMM_ROT1:
+    case AARCH64_OPND_IMM_ROT2:
+    case AARCH64_OPND_IMM_ROT3:
       snprintf (buf, size, "#%" PRIi64, opnd->imm.value);
       break;
 
diff --git a/opcodes/aarch64-opc.h b/opcodes/aarch64-opc.h
index 7bb895a..fe14d87 100644
--- a/opcodes/aarch64-opc.h
+++ b/opcodes/aarch64-opc.h
@@ -137,6 +137,9 @@ enum aarch64_field_kind
   FLD_SVE_tszl_19,
   FLD_SVE_xs_14,
   FLD_SVE_xs_22,
+  FLD_rotate1,
+  FLD_rotate2,
+  FLD_rotate3,
 };
 
 /* Field description.  */
diff --git a/opcodes/aarch64-tbl.h b/opcodes/aarch64-tbl.h
index 6960a56..0efd98e 100644
--- a/opcodes/aarch64-tbl.h
+++ b/opcodes/aarch64-tbl.h
@@ -969,6 +969,16 @@
   QLF3(V_2D , V_2D , V_2D )	\
 }
 
+/* e.g. FCMLA <Vd>.<T>, <Vn>.<T>, <Vm>.<T>, #<rotate>.  */
+#define QL_V3SAMEHSD_ROT	\
+{				\
+  QLF4 (V_4H, V_4H, V_4H, NIL),	\
+  QLF4 (V_8H, V_8H, V_8H, NIL),	\
+  QLF4 (V_2S, V_2S, V_2S, NIL),	\
+  QLF4 (V_4S, V_4S, V_4S, NIL),	\
+  QLF4 (V_2D, V_2D, V_2D, NIL),	\
+}
+
 /* e.g. FMAXNM <Vd>.<T>, <Vn>.<T>, <Vm>.<T>.  */
 #define QL_V3SAMEH		\
 {				\
@@ -1308,6 +1318,14 @@
   QLF3 (V_8H, V_8H, S_H),	\
 }
 
+/* e.g. FCMLA <Vd>.<T>, <Vn>.<T>, <Vm>.<Ts>[<index>], #<rotate>.  */
+#define QL_ELEMENT_ROT		\
+{				\
+  QLF4 (V_4H, V_4H, S_H, NIL),	\
+  QLF4 (V_8H, V_8H, S_H, NIL),	\
+  QLF4 (V_4S, V_4S, S_S, NIL),	\
+}
+
 /* e.g. MOVI <Vd>.4S, #<imm8> {, LSL #<amount>}.  */
 #define QL_SIMD_IMM_S0W		\
 {				\
@@ -1920,6 +1938,8 @@ static const aarch64_feature_set aarch64_feature_v8_3 =
   AARCH64_FEATURE (AARCH64_FEATURE_V8_3, 0);
 static const aarch64_feature_set aarch64_feature_fp_v8_3 =
   AARCH64_FEATURE (AARCH64_FEATURE_V8_3 | AARCH64_FEATURE_FP, 0);
+static const aarch64_feature_set aarch64_feature_simd_v8_3 =
+  AARCH64_FEATURE (AARCH64_FEATURE_V8_3 | AARCH64_FEATURE_SIMD, 0);
 
 #define CORE		&aarch64_feature_v8
 #define FP		&aarch64_feature_fp
@@ -1937,6 +1957,7 @@ static const aarch64_feature_set aarch64_feature_fp_v8_3 =
 #define SVE		&aarch64_feature_sve
 #define ARMV8_3		&aarch64_feature_v8_3
 #define FP_V8_3		&aarch64_feature_fp_v8_3
+#define SIMD_V8_3	&aarch64_feature_simd_v8_3
 
 #define CORE_INSN(NAME,OPCODE,MASK,CLASS,OP,OPS,QUALS,FLAGS) \
   { NAME, OPCODE, MASK, CLASS, OP, CORE, OPS, QUALS, FLAGS, 0, NULL }
@@ -2104,6 +2125,7 @@ struct aarch64_opcode aarch64_opcode_table[] =
   SF16_INSN ("fmulx",   0x2f009000, 0xbfc0f400, asimdelem, OP3 (Vd, Vn, Em), QL_ELEMENT_FP_H, F_SIZEQ),
   RDMA_INSN ("sqrdmlah",0x2f00d000, 0xbf00f400, asimdelem, OP3 (Vd, Vn, Em), QL_ELEMENT,      F_SIZEQ),
   RDMA_INSN ("sqrdmlsh",0x2f00f000, 0xbf00f400, asimdelem, OP3 (Vd, Vn, Em), QL_ELEMENT,      F_SIZEQ),
+  {"fcmla", 0x2f001000, 0xbf009400, asimdelem, OP_FCMLA_ELEM, SIMD_V8_3, OP4 (Vd, Vn, Em, IMM_ROT2), QL_ELEMENT_ROT, F_SIZEQ, 0, NULL},
   /* AdvSIMD EXT.  */
   SIMD_INSN ("ext",  0x2e000000, 0xbfe08400, asimdext, 0, OP4 (Vd, Vn, Vm, IDX), QL_VEXT, F_SIZEQ),
   /* AdvSIMD modified immediate.  */
@@ -2347,6 +2369,8 @@ struct aarch64_opcode aarch64_opcode_table[] =
   /* AdvSIMD three same extension.  */
   RDMA_INSN ("sqrdmlah",0x2e008400, 0xbf20fe00, asimdsame, OP3 (Vd, Vn, Vm), QL_V3SAMEHS, F_SIZEQ),
   RDMA_INSN ("sqrdmlsh",0x2e008c00, 0xbf20fe00, asimdsame, OP3 (Vd, Vn, Vm), QL_V3SAMEHS, F_SIZEQ),
+  {"fcmla", 0x2e00c400, 0xbf20e400, asimdsame, 0, SIMD_V8_3, OP4 (Vd, Vn, Vm, IMM_ROT1), QL_V3SAMEHSD_ROT, F_SIZEQ, 0, NULL},
+  {"fcadd", 0x2e00e400, 0xbf20ec00, asimdsame, 0, SIMD_V8_3, OP4 (Vd, Vn, Vm, IMM_ROT3), QL_V3SAMEHSD_ROT, F_SIZEQ, 0, NULL},
   /* AdvSIMD shift by immediate.  */
   SIMD_INSN ("sshr", 0xf000400, 0xbf80fc00, asimdshf, 0, OP3 (Vd, Vn, IMM_VLSR), QL_VSHIFT, 0),
   SIMD_INSN ("ssra", 0xf001400, 0xbf80fc00, asimdshf, 0, OP3 (Vd, Vn, IMM_VLSR), QL_VSHIFT, 0),
@@ -4116,6 +4140,12 @@ struct aarch64_opcode aarch64_opcode_table[] =
     Y(IMMEDIATE, fbits, "FBITS", 0, F(FLD_scale),			\
       "the number of bits after the binary point in the fixed-point value")\
     X(IMMEDIATE, 0, 0, "IMM_MOV", 0, F(), "an immediate")		\
+    Y(IMMEDIATE, imm_rotate, "IMM_ROT1", 0, F(FLD_rotate1),		\
+      "a 2-bit rotation specifier for complex arithmetic operations")	\
+    Y(IMMEDIATE, imm_rotate, "IMM_ROT2", 0, F(FLD_rotate2),		\
+      "a 2-bit rotation specifier for complex arithmetic operations")	\
+    Y(IMMEDIATE, imm_rotate, "IMM_ROT3", 0, F(FLD_rotate3),		\
+      "a 1-bit rotation specifier for complex arithmetic operations")	\
     Y(COND, cond, "COND", 0, F(), "a condition")			\
     Y(COND, cond, "COND1", 0, F(),					\
       "one of the standard conditions, excluding AL and NV.")		\


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]