summaryrefslogtreecommitdiff
path: root/gas
diff options
context:
space:
mode:
authorMatthew Malcomson <matthew.malcomson@arm.com>2020-02-10 16:38:00 +0000
committerMatthew Malcomson <matthew.malcomson@arm.com>2020-02-10 16:50:14 +0000
commit4934a27c8c1d5c8623366f5dbafae8af60b96bc0 (patch)
tree158a8b56e97476a4a068001bf7c3d90f72a2f162 /gas
parent4b5aaf5f6992319c2c72e080a1a55842640b8732 (diff)
downloadbinutils-gdb-4934a27c8c1d5c8623366f5dbafae8af60b96bc0.tar.gz
[binutils][arm] arm support for ARMv8.m Custom Datapath Extension
This patch is part of a series that adds support for the Armv8.m ARMv8.m Custom Datapath Extension to binutils. This patch introduces the Custom Instructions Class 1/2/3 (Single/ Dual, Accumulator/Non-accumulator varianats) to the arm backend. The following Custom Instructions are added: cx1, cx1a, cx1d, cx1da, cx2, cx2a, cx2d, cx2da, cx3, cx3a, cx3d, cx3da. Specification can be found at https://developer.arm.com/docs/ddi0607/latest This patch distinguishes between enabling CDE for different coprocessor numbers by defining multiple architecture flags. This means that the parsing of the architecture extension flags is kept entirely in the existing code path. We introduce a new IT block state to indicate the behaviour of these instructions. This new state allows being used in an IT block or outside an IT block, but does not allow the instruction to be used inside a VPT block. We need this since the CX*A instruction versions can be used in IT blocks, but they aren't to have the conditional suffixes on them. Hence we need to mark an instruction as allowed in either position. We also need a new flag to objdump, in order to determine whether to disassemble an instruction as CDE related or not. Successfully regression tested on arm-none-eabi, and arm-wince-pe. gas/ChangeLog: 2020-02-10 Stam Markianos-Wright <stam.markianos-wright@arm.com> Matthew Malcomson <matthew.malcomson@arm.com> * config/tc-arm.c (arm_ext_cde*): New feature sets for each CDE coprocessor that can be enabled. (enum pred_instruction_type): New pred type. (BAD_NO_VPT): New error message. (BAD_CDE): New error message. (BAD_CDE_COPROC): New error message. (enum operand_parse_code): Add new immediate operands. (parse_operands): Account for new immediate operands. (check_cde_operand): New. (cde_coproc_enabled): New. (cde_coproc_pos): New. (cde_handle_coproc): New. (cxn_handle_predication): New. (do_custom_instruction_1): New. (do_custom_instruction_2): New. (do_custom_instruction_3): New. (do_cx1): New. (do_cx1a): New. (do_cx1d): New. (do_cx1da): New. (do_cx2): New. (do_cx2a): New. (do_cx2d): New. (do_cx2da): New. (do_cx3): New. (do_cx3a): New. (do_cx3d): New. (do_cx3da): New. (handle_pred_state): Define new IT block behaviour. (insns): Add newn CX*{,d}{,a} instructions. (CDE_EXTENSIONS,armv8m_main_ext_table,armv8_1m_main_ext_table): Define new cdecp extension strings. * doc/c-arm.texi: Document new cdecp extension arguments. * testsuite/gas/arm/cde-scalar.d: New test. * testsuite/gas/arm/cde-scalar.s: New test. * testsuite/gas/arm/cde-warnings.d: New test. * testsuite/gas/arm/cde-warnings.l: New test. * testsuite/gas/arm/cde-warnings.s: New test. * testsuite/gas/arm/cde.d: New test. * testsuite/gas/arm/cde.s: New test. include/ChangeLog: 2020-02-10 Stam Markianos-Wright <stam.markianos-wright@arm.com> Matthew Malcomson <matthew.malcomson@arm.com> * opcode/arm.h (ARM_EXT2_CDE): New extension macro. (ARM_EXT2_CDE0): New extension macro. (ARM_EXT2_CDE1): New extension macro. (ARM_EXT2_CDE2): New extension macro. (ARM_EXT2_CDE3): New extension macro. (ARM_EXT2_CDE4): New extension macro. (ARM_EXT2_CDE5): New extension macro. (ARM_EXT2_CDE6): New extension macro. (ARM_EXT2_CDE7): New extension macro. opcodes/ChangeLog: 2020-02-10 Stam Markianos-Wright <stam.markianos-wright@arm.com> Matthew Malcomson <matthew.malcomson@arm.com> * arm-dis.c (struct cdeopcode32): New. (CDE_OPCODE): New macro. (cde_opcodes): New disassembly table. (regnames): New option to table. (cde_coprocs): New global variable. (print_insn_cde): New (print_insn_thumb32): Use print_insn_cde. (parse_arm_disassembler_options): Parse coprocN args.
Diffstat (limited to 'gas')
-rw-r--r--gas/ChangeLog44
-rw-r--r--gas/config/tc-arm.c321
-rw-r--r--gas/doc/c-arm.texi8
-rw-r--r--gas/testsuite/gas/arm/cde-scalar.d117
-rw-r--r--gas/testsuite/gas/arm/cde-scalar.s206
-rw-r--r--gas/testsuite/gas/arm/cde-warnings.d5
-rw-r--r--gas/testsuite/gas/arm/cde-warnings.l175
-rw-r--r--gas/testsuite/gas/arm/cde-warnings.s335
-rw-r--r--gas/testsuite/gas/arm/cde.d119
-rw-r--r--gas/testsuite/gas/arm/cde.s3
10 files changed, 1330 insertions, 3 deletions
diff --git a/gas/ChangeLog b/gas/ChangeLog
index d7d91a42457..6df870a9519 100644
--- a/gas/ChangeLog
+++ b/gas/ChangeLog
@@ -1,3 +1,47 @@
+2020-02-10 Stam Markianos-Wright <stam.markianos-wright@arm.com>
+ Matthew Malcomson <matthew.malcomson@arm.com>
+
+ * config/tc-arm.c (arm_ext_cde*): New feature sets for each
+ CDE coprocessor that can be enabled.
+ (enum pred_instruction_type): New pred type.
+ (BAD_NO_VPT): New error message.
+ (BAD_CDE): New error message.
+ (BAD_CDE_COPROC): New error message.
+ (enum operand_parse_code): Add new immediate operands.
+ (parse_operands): Account for new immediate operands.
+ (check_cde_operand): New.
+ (cde_coproc_enabled): New.
+ (cde_coproc_pos): New.
+ (cde_handle_coproc): New.
+ (cxn_handle_predication): New.
+ (do_custom_instruction_1): New.
+ (do_custom_instruction_2): New.
+ (do_custom_instruction_3): New.
+ (do_cx1): New.
+ (do_cx1a): New.
+ (do_cx1d): New.
+ (do_cx1da): New.
+ (do_cx2): New.
+ (do_cx2a): New.
+ (do_cx2d): New.
+ (do_cx2da): New.
+ (do_cx3): New.
+ (do_cx3a): New.
+ (do_cx3d): New.
+ (do_cx3da): New.
+ (handle_pred_state): Define new IT block behaviour.
+ (insns): Add newn CX*{,d}{,a} instructions.
+ (CDE_EXTENSIONS,armv8m_main_ext_table,armv8_1m_main_ext_table):
+ Define new cdecp extension strings.
+ * doc/c-arm.texi: Document new cdecp extension arguments.
+ * testsuite/gas/arm/cde-scalar.d: New test.
+ * testsuite/gas/arm/cde-scalar.s: New test.
+ * testsuite/gas/arm/cde-warnings.d: New test.
+ * testsuite/gas/arm/cde-warnings.l: New test.
+ * testsuite/gas/arm/cde-warnings.s: New test.
+ * testsuite/gas/arm/cde.d: New test.
+ * testsuite/gas/arm/cde.s: New test.
+
2020-02-10 H.J. Lu <hongjiu.lu@intel.com>
PR gas/25516
diff --git a/gas/config/tc-arm.c b/gas/config/tc-arm.c
index 26a76f3fe12..93d04eecfe8 100644
--- a/gas/config/tc-arm.c
+++ b/gas/config/tc-arm.c
@@ -282,6 +282,24 @@ static const arm_feature_set arm_ext_i8mm =
ARM_FEATURE_CORE_HIGH (ARM_EXT2_I8MM);
static const arm_feature_set arm_ext_crc =
ARM_FEATURE_CORE_HIGH (ARM_EXT2_CRC);
+static const arm_feature_set arm_ext_cde =
+ ARM_FEATURE_CORE_HIGH (ARM_EXT2_CDE);
+static const arm_feature_set arm_ext_cde0 =
+ ARM_FEATURE_CORE_HIGH (ARM_EXT2_CDE0);
+static const arm_feature_set arm_ext_cde1 =
+ ARM_FEATURE_CORE_HIGH (ARM_EXT2_CDE1);
+static const arm_feature_set arm_ext_cde2 =
+ ARM_FEATURE_CORE_HIGH (ARM_EXT2_CDE2);
+static const arm_feature_set arm_ext_cde3 =
+ ARM_FEATURE_CORE_HIGH (ARM_EXT2_CDE3);
+static const arm_feature_set arm_ext_cde4 =
+ ARM_FEATURE_CORE_HIGH (ARM_EXT2_CDE4);
+static const arm_feature_set arm_ext_cde5 =
+ ARM_FEATURE_CORE_HIGH (ARM_EXT2_CDE5);
+static const arm_feature_set arm_ext_cde6 =
+ ARM_FEATURE_CORE_HIGH (ARM_EXT2_CDE6);
+static const arm_feature_set arm_ext_cde7 =
+ ARM_FEATURE_CORE_HIGH (ARM_EXT2_CDE7);
static const arm_feature_set arm_arch_any = ARM_ANY;
static const arm_feature_set fpu_any = FPU_ANY;
@@ -482,7 +500,9 @@ enum pred_instruction_type
VPT_INSN, /* The VPT/VPST insn has been parsed. */
MVE_OUTSIDE_PRED_INSN , /* Instruction to indicate a MVE instruction without
a predication code. */
- MVE_UNPREDICABLE_INSN /* MVE instruction that is non-predicable. */
+ MVE_UNPREDICABLE_INSN, /* MVE instruction that is non-predicable. */
+ NEUTRAL_IT_NO_VPT_INSN, /* Instruction that can be either inside or outside
+ an IT block, but must not be in a VPT block. */
};
/* The maximum number of operands we need. */
@@ -882,6 +902,7 @@ struct asm_opcode
#define BAD_ADDR_MODE _("instruction does not accept this addressing mode")
#define BAD_BRANCH _("branch must be last instruction in IT block")
#define BAD_BRANCH_OFF _("branch out of range or not a multiple of 2")
+#define BAD_NO_VPT _("instruction not allowed in VPT block")
#define BAD_NOT_IT _("instruction not allowed in IT block")
#define BAD_NOT_VPT _("instruction missing MVE vector predication code")
#define BAD_FPU _("selected FPU does not support instruction")
@@ -899,6 +920,8 @@ struct asm_opcode
#define BAD_RANGE _("branch out of range")
#define BAD_FP16 _("selected processor does not support fp16 instruction")
#define BAD_BF16 _("selected processor does not support bf16 instruction")
+#define BAD_CDE _("selected processor does not support cde instruction")
+#define BAD_CDE_COPROC _("coprocessor for insn is not enabled for cde")
#define UNPRED_REG(R) _("using " R " results in unpredictable behaviour")
#define THUMB1_RELOC_ONLY _("relocation valid in thumb1 code only")
#define MVE_NOT_IT _("Warning: instruction is UNPREDICTABLE in an IT " \
@@ -7138,7 +7161,8 @@ enum operand_parse_code
OP_I64, /* 1 .. 64 */
OP_I64z, /* 0 .. 64 */
OP_I255, /* 0 .. 255 */
-
+ OP_I511, /* 0 .. 511 */
+ OP_I8191, /* 0 .. 8191 */
OP_I4b, /* immediate, prefix optional, 1 .. 4 */
OP_I7b, /* 0 .. 7 */
OP_I15b, /* 0 .. 15 */
@@ -7653,7 +7677,8 @@ parse_operands (char *str, const unsigned int *pattern, bfd_boolean thumb)
case OP_I64: po_imm_or_fail ( 1, 64, FALSE); break;
case OP_I64z: po_imm_or_fail ( 0, 64, FALSE); break;
case OP_I255: po_imm_or_fail ( 0, 255, FALSE); break;
-
+ case OP_I511: po_imm_or_fail ( 0, 511, FALSE); break;
+ case OP_I8191: po_imm_or_fail ( 0, 8191, FALSE); break;
case OP_I4b: po_imm_or_fail ( 1, 4, TRUE); break;
case OP_oI7b:
case OP_I7b: po_imm_or_fail ( 0, 7, TRUE); break;
@@ -21572,6 +21597,249 @@ do_vummla (void)
}
+static void
+check_cde_operand (size_t index, int is_dual)
+{
+ unsigned Rx = inst.operands[index].reg;
+ bfd_boolean isvec = inst.operands[index].isvec;
+ if (is_dual == 0 && thumb_mode)
+ constraint (
+ !((Rx <= 14 && Rx != 13) || (Rx == REG_PC && isvec)),
+ _("Register must be r0-r14 except r13, or APSR_nzcv."));
+ else
+ constraint ( !((Rx <= 10 && Rx % 2 == 0 )),
+ _("Register must be an even register between r0-r10."));
+}
+
+static bfd_boolean
+cde_coproc_enabled (unsigned coproc)
+{
+ switch (coproc)
+ {
+ case 0: return mark_feature_used (&arm_ext_cde0);
+ case 1: return mark_feature_used (&arm_ext_cde1);
+ case 2: return mark_feature_used (&arm_ext_cde2);
+ case 3: return mark_feature_used (&arm_ext_cde3);
+ case 4: return mark_feature_used (&arm_ext_cde4);
+ case 5: return mark_feature_used (&arm_ext_cde5);
+ case 6: return mark_feature_used (&arm_ext_cde6);
+ case 7: return mark_feature_used (&arm_ext_cde7);
+ default: return FALSE;
+ }
+}
+
+#define cde_coproc_pos 8
+static void
+cde_handle_coproc (void)
+{
+ unsigned coproc = inst.operands[0].reg;
+ constraint (coproc > 7, _("CDE Coprocessor must be in range 0-7"));
+ constraint (!(cde_coproc_enabled (coproc)), BAD_CDE_COPROC);
+ inst.instruction |= coproc << cde_coproc_pos;
+}
+#undef cde_coproc_pos
+
+static void
+cxn_handle_predication (bfd_boolean is_accum)
+{
+ /* This function essentially checks for a suffix, not whether the instruction
+ is inside an IT block or not.
+ The CX* instructions should never have a conditional suffix -- this is not
+ mentioned in the syntax. */
+ if (conditional_insn ())
+ inst.error = BAD_SYNTAX;
+ /* Here we ensure that if the current element */
+ else if (is_accum)
+ set_pred_insn_type (NEUTRAL_IT_NO_VPT_INSN);
+ else
+ set_pred_insn_type (OUTSIDE_PRED_INSN);
+}
+
+static void
+do_custom_instruction_1 (int is_dual, bfd_boolean is_accum)
+{
+
+ constraint (!mark_feature_used (&arm_ext_cde), _(BAD_CDE));
+
+ unsigned imm, Rd;
+
+ Rd = inst.operands[1].reg;
+ check_cde_operand (1, is_dual);
+
+ if (is_dual == 1)
+ {
+ constraint (inst.operands[2].reg != Rd + 1,
+ _("cx1d requires consecutive destination registers."));
+ imm = inst.operands[3].imm;
+ }
+ else if (is_dual == 0)
+ imm = inst.operands[2].imm;
+ else
+ abort ();
+
+ inst.instruction |= Rd << 12;
+ inst.instruction |= (imm & 0x1F80) << 9;
+ inst.instruction |= (imm & 0x0040) << 1;
+ inst.instruction |= (imm & 0x003f);
+
+ cde_handle_coproc ();
+ cxn_handle_predication (is_accum);
+}
+
+static void
+do_custom_instruction_2 (int is_dual, bfd_boolean is_accum)
+{
+
+ constraint (!mark_feature_used (&arm_ext_cde), _(BAD_CDE));
+
+ unsigned imm, Rd, Rn;
+
+ Rd = inst.operands[1].reg;
+
+ if (is_dual == 1)
+ {
+ constraint (inst.operands[2].reg != Rd + 1,
+ _("cx2d requires consecutive destination registers."));
+ imm = inst.operands[4].imm;
+ Rn = inst.operands[3].reg;
+ }
+ else if (is_dual == 0)
+ {
+ imm = inst.operands[3].imm;
+ Rn = inst.operands[2].reg;
+ }
+ else
+ abort ();
+
+ check_cde_operand (2 + is_dual, /* is_dual = */0);
+ check_cde_operand (1, is_dual);
+
+ inst.instruction |= Rd << 12;
+ inst.instruction |= Rn << 16;
+
+ inst.instruction |= (imm & 0x0380) << 13;
+ inst.instruction |= (imm & 0x0040) << 1;
+ inst.instruction |= (imm & 0x003f);
+
+ cde_handle_coproc ();
+ cxn_handle_predication (is_accum);
+}
+
+static void
+do_custom_instruction_3 (int is_dual, bfd_boolean is_accum)
+{
+
+ constraint (!mark_feature_used (&arm_ext_cde), _(BAD_CDE));
+
+ unsigned imm, Rd, Rn, Rm;
+
+ Rd = inst.operands[1].reg;
+
+ if (is_dual == 1)
+ {
+ constraint (inst.operands[2].reg != Rd + 1,
+ _("cx3d requires consecutive destination registers."));
+ imm = inst.operands[5].imm;
+ Rn = inst.operands[3].reg;
+ Rm = inst.operands[4].reg;
+ }
+ else if (is_dual == 0)
+ {
+ imm = inst.operands[4].imm;
+ Rn = inst.operands[2].reg;
+ Rm = inst.operands[3].reg;
+ }
+ else
+ abort ();
+
+ check_cde_operand (1, is_dual);
+ check_cde_operand (2 + is_dual, /* is_dual = */0);
+ check_cde_operand (3 + is_dual, /* is_dual = */0);
+
+ inst.instruction |= Rd;
+ inst.instruction |= Rn << 16;
+ inst.instruction |= Rm << 12;
+
+ inst.instruction |= (imm & 0x0038) << 17;
+ inst.instruction |= (imm & 0x0004) << 5;
+ inst.instruction |= (imm & 0x0003) << 4;
+
+ cde_handle_coproc ();
+ cxn_handle_predication (is_accum);
+}
+
+static void
+do_cx1 (void)
+{
+ return do_custom_instruction_1 (0, 0);
+}
+
+static void
+do_cx1a (void)
+{
+ return do_custom_instruction_1 (0, 1);
+}
+
+static void
+do_cx1d (void)
+{
+ return do_custom_instruction_1 (1, 0);
+}
+
+static void
+do_cx1da (void)
+{
+ return do_custom_instruction_1 (1, 1);
+}
+
+static void
+do_cx2 (void)
+{
+ return do_custom_instruction_2 (0, 0);
+}
+
+static void
+do_cx2a (void)
+{
+ return do_custom_instruction_2 (0, 1);
+}
+
+static void
+do_cx2d (void)
+{
+ return do_custom_instruction_2 (1, 0);
+}
+
+static void
+do_cx2da (void)
+{
+ return do_custom_instruction_2 (1, 1);
+}
+
+static void
+do_cx3 (void)
+{
+ return do_custom_instruction_3 (0, 0);
+}
+
+static void
+do_cx3a (void)
+{
+ return do_custom_instruction_3 (0, 1);
+}
+
+static void
+do_cx3d (void)
+{
+ return do_custom_instruction_3 (1, 0);
+}
+
+static void
+do_cx3da (void)
+{
+ return do_custom_instruction_3 (1, 1);
+}
+
/* Crypto v1 instructions. */
static void
do_crypto_2op_1 (unsigned elttype, int op)
@@ -22474,6 +22742,7 @@ handle_pred_state (void)
gas_assert (0);
case IF_INSIDE_IT_LAST_INSN:
case NEUTRAL_IT_INSN:
+ case NEUTRAL_IT_NO_VPT_INSN:
break;
case VPT_INSN:
@@ -22537,6 +22806,13 @@ handle_pred_state (void)
close_automatic_it_block ();
break;
+ case NEUTRAL_IT_NO_VPT_INSN:
+ if (now_pred.type == VECTOR_PRED)
+ {
+ inst.error = BAD_NO_VPT;
+ break;
+ }
+ /* Fallthrough. */
case NEUTRAL_IT_INSN:
now_pred.block_length++;
now_pred.insn_cond = TRUE;
@@ -22720,6 +22996,13 @@ handle_pred_state (void)
}
break;
+ case NEUTRAL_IT_NO_VPT_INSN:
+ if (now_pred.type == VECTOR_PRED)
+ {
+ inst.error = BAD_NO_VPT;
+ break;
+ }
+ /* Fallthrough. */
case NEUTRAL_IT_INSN:
/* The BKPT instruction is unconditional even in a IT or VPT
block. */
@@ -26099,6 +26382,24 @@ static const struct asm_opcode insns[] =
TUF ("vusmmla", ca00c40, fca00c40, 3, (RNQ, RNQ, RNQ), vsmmla, vsmmla),
TUF ("vusdot", c800d00, fc800d00, 3, (RNDQ, RNDQ, RNDQ_RNSC), vusdot, vusdot),
TUF ("vsudot", c800d10, fc800d10, 3, (RNDQ, RNDQ, RNSC), vsudot, vsudot),
+
+#undef ARM_VARIANT
+#undef THUMB_VARIANT
+#define THUMB_VARIANT &arm_ext_cde
+ ToC ("cx1", ee000000, 3, (RCP, APSR_RR, I8191), cx1),
+ ToC ("cx1a", fe000000, 3, (RCP, APSR_RR, I8191), cx1a),
+ ToC ("cx1d", ee000040, 4, (RCP, RR, APSR_RR, I8191), cx1d),
+ ToC ("cx1da", fe000040, 4, (RCP, RR, APSR_RR, I8191), cx1da),
+
+ ToC ("cx2", ee400000, 4, (RCP, APSR_RR, APSR_RR, I511), cx2),
+ ToC ("cx2a", fe400000, 4, (RCP, APSR_RR, APSR_RR, I511), cx2a),
+ ToC ("cx2d", ee400040, 5, (RCP, RR, APSR_RR, APSR_RR, I511), cx2d),
+ ToC ("cx2da", fe400040, 5, (RCP, RR, APSR_RR, APSR_RR, I511), cx2da),
+
+ ToC ("cx3", ee800000, 5, (RCP, APSR_RR, APSR_RR, APSR_RR, I63), cx3),
+ ToC ("cx3a", fe800000, 5, (RCP, APSR_RR, APSR_RR, APSR_RR, I63), cx3a),
+ ToC ("cx3d", ee800040, 6, (RCP, RR, APSR_RR, APSR_RR, APSR_RR, I63), cx3d),
+ ToC ("cx3da", fe800040, 6, (RCP, RR, APSR_RR, APSR_RR, APSR_RR, I63), cx3da),
};
#undef ARM_VARIANT
#undef THUMB_VARIANT
@@ -31280,12 +31581,23 @@ static const struct arm_ext_table armv86a_ext_table[] =
{ NULL, 0, ARM_ARCH_NONE, ARM_ARCH_NONE }
};
+#define CDE_EXTENSIONS \
+ ARM_ADD ("cdecp0", ARM_FEATURE_CORE_HIGH (ARM_EXT2_CDE | ARM_EXT2_CDE0)), \
+ ARM_ADD ("cdecp1", ARM_FEATURE_CORE_HIGH (ARM_EXT2_CDE | ARM_EXT2_CDE1)), \
+ ARM_ADD ("cdecp2", ARM_FEATURE_CORE_HIGH (ARM_EXT2_CDE | ARM_EXT2_CDE2)), \
+ ARM_ADD ("cdecp3", ARM_FEATURE_CORE_HIGH (ARM_EXT2_CDE | ARM_EXT2_CDE3)), \
+ ARM_ADD ("cdecp4", ARM_FEATURE_CORE_HIGH (ARM_EXT2_CDE | ARM_EXT2_CDE4)), \
+ ARM_ADD ("cdecp5", ARM_FEATURE_CORE_HIGH (ARM_EXT2_CDE | ARM_EXT2_CDE5)), \
+ ARM_ADD ("cdecp6", ARM_FEATURE_CORE_HIGH (ARM_EXT2_CDE | ARM_EXT2_CDE6)), \
+ ARM_ADD ("cdecp7", ARM_FEATURE_CORE_HIGH (ARM_EXT2_CDE | ARM_EXT2_CDE7))
+
static const struct arm_ext_table armv8m_main_ext_table[] =
{
ARM_EXT ("dsp", ARM_FEATURE_CORE_LOW (ARM_AEXT_V8M_MAIN_DSP),
ARM_FEATURE_CORE_LOW (ARM_AEXT_V8M_MAIN_DSP)),
ARM_EXT ("fp", FPU_ARCH_VFP_V5_SP_D16, ALL_FP),
ARM_ADD ("fp.dp", FPU_ARCH_VFP_V5D16),
+ CDE_EXTENSIONS,
{ NULL, 0, ARM_ARCH_NONE, ARM_ARCH_NONE }
};
@@ -31307,9 +31619,12 @@ static const struct arm_ext_table armv8_1m_main_ext_table[] =
ARM_FEATURE (ARM_AEXT_V8M_MAIN_DSP,
ARM_EXT2_FP16_INST | ARM_EXT2_MVE | ARM_EXT2_MVE_FP,
FPU_VFP_V5_SP_D16 | FPU_VFP_EXT_FP16 | FPU_VFP_EXT_FMA)),
+ CDE_EXTENSIONS,
{ NULL, 0, ARM_ARCH_NONE, ARM_ARCH_NONE }
};
+#undef CDE_EXTENSIONS
+
static const struct arm_ext_table armv8r_ext_table[] =
{
ARM_ADD ("crc", ARM_FEATURE_CORE_HIGH (ARM_EXT2_CRC)),
diff --git a/gas/doc/c-arm.texi b/gas/doc/c-arm.texi
index e19d2a83aad..91803605775 100644
--- a/gas/doc/c-arm.texi
+++ b/gas/doc/c-arm.texi
@@ -359,6 +359,14 @@ For @code{armv8-m.main}:
@code{+fp}: Enables single-precision only VFPv5 instructions with 16
double-word registers.
@code{+fp.dp}: Enables VFPv5 instructions with 16 double-word registers.
+@code{+cdecp0} (CDE extensions for v8-m architecture with coprocessor 0),
+@code{+cdecp1} (CDE extensions for v8-m architecture with coprocessor 1),
+@code{+cdecp2} (CDE extensions for v8-m architecture with coprocessor 2),
+@code{+cdecp3} (CDE extensions for v8-m architecture with coprocessor 3),
+@code{+cdecp4} (CDE extensions for v8-m architecture with coprocessor 4),
+@code{+cdecp5} (CDE extensions for v8-m architecture with coprocessor 5),
+@code{+cdecp6} (CDE extensions for v8-m architecture with coprocessor 6),
+@code{+cdecp7} (CDE extensions for v8-m architecture with coprocessor 7),
@code{+nofp}: Disables all FPU instructions.
@code{+nodsp}: Disables DSP Extension.
diff --git a/gas/testsuite/gas/arm/cde-scalar.d b/gas/testsuite/gas/arm/cde-scalar.d
new file mode 100644
index 00000000000..36260128f41
--- /dev/null
+++ b/gas/testsuite/gas/arm/cde-scalar.d
@@ -0,0 +1,117 @@
+#name: Custom Datapath Extension Scalar bits (CDE)
+#source: cde-scalar.s
+#as: -mno-warn-deprecated -march=armv8-m.main+cdecp0+cdecp7 -I$srcdir/$subdir
+#as: -mno-warn-deprecated -march=armv8-m.main+cdecp0+cdecp1+cdecp2+cdecp3+cdecp4+cdecp5+cdecp6+cdecp7 -I$srcdir/$subdir
+#objdump: -M force-thumb -dr --show-raw-insn -marmv8-m.main -M coproc0=cde -M coproc7=cde
+#...
+00000000 <\.text>:
+ *[0-9a-f]+: ee00 0000 cx1 p0, r0, #0
+ *[0-9a-f]+: ee3f 0000 cx1 p0, r0, #8064
+ *[0-9a-f]+: ee00 0080 cx1 p0, r0, #64
+ *[0-9a-f]+: ee00 003f cx1 p0, r0, #63
+ *[0-9a-f]+: ee00 0700 cx1 p7, r0, #0
+ *[0-9a-f]+: ee00 f000 cx1 p0, APSR_nzcv, #0
+ *[0-9a-f]+: ee00 9000 cx1 p0, r9, #0
+ *[0-9a-f]+: fe00 0000 cx1a p0, r0, #0
+ *[0-9a-f]+: fe3f 0000 cx1a p0, r0, #8064
+ *[0-9a-f]+: fe00 0080 cx1a p0, r0, #64
+ *[0-9a-f]+: fe00 003f cx1a p0, r0, #63
+ *[0-9a-f]+: fe00 0700 cx1a p7, r0, #0
+ *[0-9a-f]+: fe00 f000 cx1a p0, APSR_nzcv, #0
+ *[0-9a-f]+: fe00 9000 cx1a p0, r9, #0
+ *[0-9a-f]+: bf18 it ne
+ *[0-9a-f]+: fe00 0000 cx1a p0, r0, #0
+ *[0-9a-f]+: ee00 0040 cx1d p0, r0, r1, #0
+ *[0-9a-f]+: ee3f 0040 cx1d p0, r0, r1, #8064
+ *[0-9a-f]+: ee00 00c0 cx1d p0, r0, r1, #64
+ *[0-9a-f]+: ee00 007f cx1d p0, r0, r1, #63
+ *[0-9a-f]+: ee00 0740 cx1d p7, r0, r1, #0
+ *[0-9a-f]+: ee00 a040 cx1d p0, sl, fp, #0
+ *[0-9a-f]+: fe00 0040 cx1da p0, r0, r1, #0
+ *[0-9a-f]+: fe3f 0040 cx1da p0, r0, r1, #8064
+ *[0-9a-f]+: fe00 00c0 cx1da p0, r0, r1, #64
+ *[0-9a-f]+: fe00 007f cx1da p0, r0, r1, #63
+ *[0-9a-f]+: fe00 0740 cx1da p7, r0, r1, #0
+ *[0-9a-f]+: fe00 a040 cx1da p0, sl, fp, #0
+ *[0-9a-f]+: bf18 it ne
+ *[0-9a-f]+: fe00 0040 cx1da p0, r0, r1, #0
+ *[0-9a-f]+: ee40 0000 cx2 p0, r0, r0, #0
+ *[0-9a-f]+: ee70 0000 cx2 p0, r0, r0, #384
+ *[0-9a-f]+: ee40 0080 cx2 p0, r0, r0, #64
+ *[0-9a-f]+: ee40 003f cx2 p0, r0, r0, #63
+ *[0-9a-f]+: ee40 0700 cx2 p7, r0, r0, #0
+ *[0-9a-f]+: ee40 f000 cx2 p0, APSR_nzcv, r0, #0
+ *[0-9a-f]+: ee40 9000 cx2 p0, r9, r0, #0
+ *[0-9a-f]+: ee4f 0000 cx2 p0, r0, APSR_nzcv, #0
+ *[0-9a-f]+: ee49 0000 cx2 p0, r0, r9, #0
+ *[0-9a-f]+: fe40 0000 cx2a p0, r0, r0, #0
+ *[0-9a-f]+: fe70 0000 cx2a p0, r0, r0, #384
+ *[0-9a-f]+: fe40 0080 cx2a p0, r0, r0, #64
+ *[0-9a-f]+: fe40 003f cx2a p0, r0, r0, #63
+ *[0-9a-f]+: fe40 0700 cx2a p7, r0, r0, #0
+ *[0-9a-f]+: fe40 f000 cx2a p0, APSR_nzcv, r0, #0
+ *[0-9a-f]+: fe40 9000 cx2a p0, r9, r0, #0
+ *[0-9a-f]+: fe4f 0000 cx2a p0, r0, APSR_nzcv, #0
+ *[0-9a-f]+: fe49 0000 cx2a p0, r0, r9, #0
+ *[0-9a-f]+: bf18 it ne
+ *[0-9a-f]+: fe40 0000 cx2a p0, r0, r0, #0
+ *[0-9a-f]+: ee40 0040 cx2d p0, r0, r1, r0, #0
+ *[0-9a-f]+: ee70 0040 cx2d p0, r0, r1, r0, #384
+ *[0-9a-f]+: ee40 00c0 cx2d p0, r0, r1, r0, #64
+ *[0-9a-f]+: ee40 007f cx2d p0, r0, r1, r0, #63
+ *[0-9a-f]+: ee40 0740 cx2d p7, r0, r1, r0, #0
+ *[0-9a-f]+: ee40 a040 cx2d p0, sl, fp, r0, #0
+ *[0-9a-f]+: ee4f 0040 cx2d p0, r0, r1, APSR_nzcv, #0
+ *[0-9a-f]+: ee49 0040 cx2d p0, r0, r1, r9, #0
+ *[0-9a-f]+: fe40 0040 cx2da p0, r0, r1, r0, #0
+ *[0-9a-f]+: fe70 0040 cx2da p0, r0, r1, r0, #384
+ *[0-9a-f]+: fe40 00c0 cx2da p0, r0, r1, r0, #64
+ *[0-9a-f]+: fe40 007f cx2da p0, r0, r1, r0, #63
+ *[0-9a-f]+: fe40 0740 cx2da p7, r0, r1, r0, #0
+ *[0-9a-f]+: fe40 a040 cx2da p0, sl, fp, r0, #0
+ *[0-9a-f]+: fe4f 0040 cx2da p0, r0, r1, APSR_nzcv, #0
+ *[0-9a-f]+: fe49 0040 cx2da p0, r0, r1, r9, #0
+ *[0-9a-f]+: ee80 0000 cx3 p0, r0, r0, r0, #0
+ *[0-9a-f]+: eef0 0000 cx3 p0, r0, r0, r0, #56
+ *[0-9a-f]+: ee80 0080 cx3 p0, r0, r0, r0, #4
+ *[0-9a-f]+: ee80 0030 cx3 p0, r0, r0, r0, #3
+ *[0-9a-f]+: ee80 0700 cx3 p7, r0, r0, r0, #0
+ *[0-9a-f]+: ee80 000f cx3 p0, APSR_nzcv, r0, r0, #0
+ *[0-9a-f]+: ee80 0009 cx3 p0, r9, r0, r0, #0
+ *[0-9a-f]+: ee8f 0000 cx3 p0, r0, APSR_nzcv, r0, #0
+ *[0-9a-f]+: ee89 0000 cx3 p0, r0, r9, r0, #0
+ *[0-9a-f]+: ee80 f000 cx3 p0, r0, r0, APSR_nzcv, #0
+ *[0-9a-f]+: ee80 9000 cx3 p0, r0, r0, r9, #0
+ *[0-9a-f]+: fe80 0000 cx3a p0, r0, r0, r0, #0
+ *[0-9a-f]+: fef0 0000 cx3a p0, r0, r0, r0, #56
+ *[0-9a-f]+: fe80 0080 cx3a p0, r0, r0, r0, #4
+ *[0-9a-f]+: fe80 0030 cx3a p0, r0, r0, r0, #3
+ *[0-9a-f]+: fe80 0700 cx3a p7, r0, r0, r0, #0
+ *[0-9a-f]+: fe80 000f cx3a p0, APSR_nzcv, r0, r0, #0
+ *[0-9a-f]+: fe80 0009 cx3a p0, r9, r0, r0, #0
+ *[0-9a-f]+: fe8f 0000 cx3a p0, r0, APSR_nzcv, r0, #0
+ *[0-9a-f]+: fe89 0000 cx3a p0, r0, r9, r0, #0
+ *[0-9a-f]+: fe80 f000 cx3a p0, r0, r0, APSR_nzcv, #0
+ *[0-9a-f]+: fe80 9000 cx3a p0, r0, r0, r9, #0
+ *[0-9a-f]+: bf18 it ne
+ *[0-9a-f]+: fe80 0000 cx3a p0, r0, r0, r0, #0
+ *[0-9a-f]+: ee80 0040 cx3d p0, r0, r1, r0, r0, #0
+ *[0-9a-f]+: eef0 0040 cx3d p0, r0, r1, r0, r0, #56
+ *[0-9a-f]+: ee80 00c0 cx3d p0, r0, r1, r0, r0, #4
+ *[0-9a-f]+: ee80 0070 cx3d p0, r0, r1, r0, r0, #3
+ *[0-9a-f]+: ee80 0740 cx3d p7, r0, r1, r0, r0, #0
+ *[0-9a-f]+: ee80 004a cx3d p0, sl, fp, r0, r0, #0
+ *[0-9a-f]+: ee8f 0040 cx3d p0, r0, r1, APSR_nzcv, r0, #0
+ *[0-9a-f]+: ee89 0040 cx3d p0, r0, r1, r9, r0, #0
+ *[0-9a-f]+: ee80 f040 cx3d p0, r0, r1, r0, APSR_nzcv, #0
+ *[0-9a-f]+: ee80 9040 cx3d p0, r0, r1, r0, r9, #0
+ *[0-9a-f]+: fe80 0040 cx3da p0, r0, r1, r0, r0, #0
+ *[0-9a-f]+: fef0 0040 cx3da p0, r0, r1, r0, r0, #56
+ *[0-9a-f]+: fe80 00c0 cx3da p0, r0, r1, r0, r0, #4
+ *[0-9a-f]+: fe80 0070 cx3da p0, r0, r1, r0, r0, #3
+ *[0-9a-f]+: fe80 0740 cx3da p7, r0, r1, r0, r0, #0
+ *[0-9a-f]+: fe80 004a cx3da p0, sl, fp, r0, r0, #0
+ *[0-9a-f]+: fe8f 0040 cx3da p0, r0, r1, APSR_nzcv, r0, #0
+ *[0-9a-f]+: fe89 0040 cx3da p0, r0, r1, r9, r0, #0
+ *[0-9a-f]+: fe80 f040 cx3da p0, r0, r1, r0, APSR_nzcv, #0
+ *[0-9a-f]+: fe80 9040 cx3da p0, r0, r1, r0, r9, #0
diff --git a/gas/testsuite/gas/arm/cde-scalar.s b/gas/testsuite/gas/arm/cde-scalar.s
new file mode 100644
index 00000000000..ac188a3aa03
--- /dev/null
+++ b/gas/testsuite/gas/arm/cde-scalar.s
@@ -0,0 +1,206 @@
+.syntax unified
+# Extra tests everywhere:
+# Ensure that setting the register to something in r[1-12] works.
+
+# cx1{a} Has arguments in the following form
+# 111a111000iiiiiidddd0pppi0iiiiii
+#
+# Variants to test:
+# - Base (everything we can set to zero)
+# - immediates that set each set of `i` to ones in turn.
+# (imm = op1:op2:op3 , which is each group of `i` from left to write
+# concatenated)
+# - Each register 9 (0b1001), APSR_nzcv, or all zeros
+# - Coprocessor num set to 7
+# - Everything again with the `a` version (to double check parsing).
+# - Accumulator versions without optional argument (to check parsing)
+#
+# IT blocks:
+# Non-accumulator versions are UNPREDICTABLE in IT blocks.
+# Accumulator versions are allowed in IT blocks.
+
+# cx1{a} extra tests.
+# Arm conditional
+cx1 p0, r0, #0
+cx1 p0, r0, #8064
+cx1 p0, r0, #64
+cx1 p0, r0, #63
+cx1 p7, r0, #0
+cx1 p0, APSR_nzcv, #0
+cx1 p0, r9, #0
+cx1a p0, r0, #0
+cx1a p0, r0, #8064
+cx1a p0, r0, #64
+cx1a p0, r0, #63
+cx1a p7, r0, #0
+cx1a p0, APSR_nzcv, #0
+cx1a p0, r9, #0
+
+it ne
+cx1a p0, r0, #0
+
+# cx1d{a} encoding of following form:
+# 111a111000iiiiiidddd0pppi1iiiiii
+#
+# Variants to test:
+# - Base (everything we can set to zero)
+# - immediates that set each set of `i` to ones in turn.
+# (imm = op1:op2:op3 , which is each group of `i` from left to write
+# concatenated)
+# - Destination register 10 (0b1010) or all zeros
+# - Coprocessor num set to 7
+# - Everything again with the `a` version (to double check parsing).
+# - Accumulator versions without optional argument (to check parsing)
+cx1d p0, r0, r1, #0
+cx1d p0, r0, r1, #8064
+cx1d p0, r0, r1, #64
+cx1d p0, r0, r1, #63
+cx1d p7, r0, r1, #0
+cx1d p0, r10, r11, #0
+cx1da p0, r0, r1, #0
+cx1da p0, r0, r1, #8064
+cx1da p0, r0, r1, #64
+cx1da p0, r0, r1, #63
+cx1da p7, r0, r1, #0
+cx1da p0, r10, r11, #0
+
+it ne
+cx1da p0, r0, r1, #0
+
+
+# cx2{a} Has arguments of the following form:
+# 111a111001iinnnndddd0pppi0iiiiii
+#
+# Variants to test:
+# - Base (everything we can set to zero)
+# - immediates that set each set of `i` to ones in turn.
+# (imm = op1:op2:op3 , which is each group of `i` from left to write
+# concatenated)
+# - Each register 9 (0b1001), APSR_nzcv, or all zeros
+# - Coprocessor num set to 7
+# - Everything again with the `a` version (to double check parsing).
+# - Accumulator versions without optional argument (to check parsing)
+cx2 p0, r0, r0, #0
+cx2 p0, r0, r0, #384
+cx2 p0, r0, r0, #64
+cx2 p0, r0, r0, #63
+cx2 p7, r0, r0, #0
+cx2 p0, APSR_nzcv, r0, #0
+cx2 p0, r9, r0, #0
+cx2 p0, r0, APSR_nzcv, #0
+cx2 p0, r0, r9, #0
+cx2a p0, r0, r0, #0
+cx2a p0, r0, r0, #384
+cx2a p0, r0, r0, #64
+cx2a p0, r0, r0, #63
+cx2a p7, r0, r0, #0
+cx2a p0, APSR_nzcv, r0, #0
+cx2a p0, r9, r0, #0
+cx2a p0, r0, APSR_nzcv, #0
+cx2a p0, r0, r9, #0
+
+it ne
+cx2a p0, r0, r0, #0
+
+# cx2d{a} encoding has following form:
+# 111a111001iinnnndddd0pppi1iiiiii
+#
+# - Base (everything we can set to zero)
+# - immediates that set each set of `i` to ones in turn.
+# (imm = op1:op2:op3 , which is each group of `i` from left to write
+# concatenated)
+# - Destination register 10 (0b1010) or all zeros
+# - Coprocessor num set to 7
+# - Everything again with the `a` version (to double check parsing).
+# - Accumulator versions without optional argument (to check parsing)
+cx2d p0, r0, r1, r0, #0
+cx2d p0, r0, r1, r0, #384
+cx2d p0, r0, r1, r0, #64
+cx2d p0, r0, r1, r0, #63
+cx2d p7, r0, r1, r0, #0
+cx2d p0, r10, r11, r0, #0
+cx2d p0, r0, r1, APSR_nzcv, #0
+cx2d p0, r0, r1, r9, #0
+cx2da p0, r0, r1, r0, #0
+cx2da p0, r0, r1, r0, #384
+cx2da p0, r0, r1, r0, #64
+cx2da p0, r0, r1, r0, #63
+cx2da p7, r0, r1, r0, #0
+cx2da p0, r10, r11, r0, #0
+cx2da p0, r0, r1, APSR_nzcv, #0
+cx2da p0, r0, r1, r9, #0
+
+# cx3{a} Has arguments in the following form:
+# 111a11101iiinnnnmmmm0pppi0iidddd
+#
+# Variants to test:
+# - immediates that set each set of `i` to ones in turn.
+# (imm = op1:op2:op3 , which is each group of `i` from left to write
+# - Base (everything we can set to zero)
+# - immediates that set each set of `i` to ones in turn.
+# (imm = op1:op2:op3 , which is each group of `i` from left to write
+# concatenated)
+# - Each register 9 (0b1001), APSR_nzcv, or all zeros
+# - Coprocessor num set to 7
+# - Everything again with the `a` version (to double check parsing).
+# - Accumulator versions without optional argument (to check parsing)
+cx3 p0, r0, r0, r0, #0
+cx3 p0, r0, r0, r0, #56
+cx3 p0, r0, r0, r0, #4
+cx3 p0, r0, r0, r0, #3
+cx3 p7, r0, r0, r0, #0
+cx3 p0, APSR_nzcv, r0, r0, #0
+cx3 p0, r9, r0, r0, #0
+cx3 p0, r0, APSR_nzcv, r0, #0
+cx3 p0, r0, r9, r0, #0
+cx3 p0, r0, r0, APSR_nzcv, #0
+cx3 p0, r0, r0, r9, #0
+cx3a p0, r0, r0, r0, #0
+cx3a p0, r0, r0, r0, #56
+cx3a p0, r0, r0, r0, #4
+cx3a p0, r0, r0, r0, #3
+cx3a p7, r0, r0, r0, #0
+cx3a p0, APSR_nzcv, r0, r0, #0
+cx3a p0, r9, r0, r0, #0
+cx3a p0, r0, APSR_nzcv, r0, #0
+cx3a p0, r0, r9, r0, #0
+cx3a p0, r0, r0, APSR_nzcv, #0
+cx3a p0, r0, r0, r9, #0
+
+it ne
+cx3a p0, r0, r0, r0, #0
+
+# cx3d{a} encoding has following form:
+# 111a11101iiinnnnmmmm0pppi1iidddd
+#
+# Variants to test:
+# - Toggle 'a'
+# - immediates that set each set of `i` to ones in turn.
+# (imm = op1:op2:op3 , which is each group of `i` from left to write
+# concatenated)
+# - Destination register 10 (0b1010) or all zeros
+# - Source register 9 (0b1001), APSR_nzcv, or all zeros
+
+# No longer allows APSR_nzcv in destination register
+cx3d p0, r0, r1, r0, r0, #0
+cx3d p0, r0, r1, r0, r0, #56
+cx3d p0, r0, r1, r0, r0, #4
+cx3d p0, r0, r1, r0, r0, #3
+cx3d p7, r0, r1, r0, r0, #0
+cx3d p0, r10, r11, r0, r0, #0
+cx3d p0, r0, r1, APSR_nzcv, r0, #0
+cx3d p0, r0, r1, r9, r0, #0
+cx3d p0, r0, r1, r0, APSR_nzcv, #0
+cx3d p0, r0, r1, r0, r9, #0
+cx3da p0, r0, r1, r0, r0, #0
+cx3da p0, r0, r1, r0, r0, #56
+cx3da p0, r0, r1, r0, r0, #4
+cx3da p0, r0, r1, r0, r0, #3
+cx3da p7, r0, r1, r0, r0, #0
+cx3da p0, r10, r11, r0, r0, #0
+cx3da p0, r0, r1, APSR_nzcv, r0, #0
+cx3da p0, r0, r1, r9, r0, #0
+cx3da p0, r0, r1, r0, APSR_nzcv, #0
+cx3da p0, r0, r1, r0, r9, #0
+
+
diff --git a/gas/testsuite/gas/arm/cde-warnings.d b/gas/testsuite/gas/arm/cde-warnings.d
new file mode 100644
index 00000000000..1421b998d1c
--- /dev/null
+++ b/gas/testsuite/gas/arm/cde-warnings.d
@@ -0,0 +1,5 @@
+#name: Custom Datapath Extension (CDE) Warnings
+#source: cde-warnings.s
+#as: -mno-warn-deprecated -march=armv8.1-m.main+cdecp0+mve -I$srcdir/$subdir
+#as: -mno-warn-deprecated -march=armv8.1-m.main+cdecp0+cdecp2+cdecp3+cdecp4+cdecp5+cdecp6+cdecp7+mve -I$srcdir/$subdir
+#error_output: cde-warnings.l
diff --git a/gas/testsuite/gas/arm/cde-warnings.l b/gas/testsuite/gas/arm/cde-warnings.l
new file mode 100644
index 00000000000..abbd10aed4a
--- /dev/null
+++ b/gas/testsuite/gas/arm/cde-warnings.l
@@ -0,0 +1,175 @@
+[^ :]+: Assembler messages:
+[^ :]+:[0-9]+: Error: immediate value out of range -- `cx1 p0,r0,#8192'
+[^ :]+:[0-9]+: Error: immediate value out of range -- `cx1a p0,r0,#8192'
+[^ :]+:[0-9]+: Error: immediate value out of range -- `cx1 p0,r0,#-1'
+[^ :]+:[0-9]+: Error: immediate value out of range -- `cx1a p0,r0,#-1'
+[^ :]+:[0-9]+: Error: CDE Coprocessor must be in range 0-7 -- `cx1 p8,r0,#0'
+[^ :]+:[0-9]+: Error: CDE Coprocessor must be in range 0-7 -- `cx1a p8,r0,#0'
+[^ :]+:[0-9]+: Error: syntax error -- `cx1 p0,r16,#0'
+[^ :]+:[0-9]+: Error: syntax error -- `cx1a p0,r16,#0'
+[^ :]+:[0-9]+: Error: Register must be r0-r14 except r13, or APSR_nzcv\. -- `cx1 p0,r13,#0'
+[^ :]+:[0-9]+: Error: Register must be r0-r14 except r13, or APSR_nzcv\. -- `cx1a p0,r13,#0'
+[^ :]+:[0-9]+: Error: instruction not allowed in IT block -- `cx1 p0,r0,#0'
+[^ :]+:[0-9]+: Error: syntax error -- `cx1ne p0,r0,#0'
+[^ :]+:[0-9]+: Error: syntax error -- `cx1ane p0,r0,#0'
+[^ :]+:[0-9]+: Error: coprocessor for insn is not enabled for cde -- `cx1 p1,r0,#0'
+[^ :]+:[0-9]+: Error: coprocessor for insn is not enabled for cde -- `cx1a p1,r0,#0'
+[^ :]+:[0-9]+: Error: constant expression required -- `cx1 p0,r0,r0,#0'
+[^ :]+:[0-9]+: Error: constant expression required -- `cx1a p0,r0,r0,#0'
+[^ :]+:[0-9]+: Error: syntax error -- `cx1 p0,#0'
+[^ :]+:[0-9]+: Error: syntax error -- `cx1a p0,#0'
+[^ :]+:[0-9]+: Error: Register must be r0-r14 except r13, or APSR_nzcv\. -- `cx1 p0,r15,#0'
+[^ :]+:[0-9]+: Error: Register must be r0-r14 except r13, or APSR_nzcv\. -- `cx1a p0,r15,#0'
+[^ :]+:[0-9]+: Error: immediate value out of range -- `cx1d p0,r0,r1,#8192'
+[^ :]+:[0-9]+: Error: immediate value out of range -- `cx1da p0,r0,r1,#8192'
+[^ :]+:[0-9]+: Error: immediate value out of range -- `cx1d p0,r0,r1,#-1'
+[^ :]+:[0-9]+: Error: immediate value out of range -- `cx1da p0,r0,r1,#-1'
+[^ :]+:[0-9]+: Error: CDE Coprocessor must be in range 0-7 -- `cx1d p8,r0,r1,#0'
+[^ :]+:[0-9]+: Error: CDE Coprocessor must be in range 0-7 -- `cx1da p8,r0,r1,#0'
+[^ :]+:[0-9]+: Error: ARM register expected -- `cx1d p0,r16,r17,#0'
+[^ :]+:[0-9]+: Error: ARM register expected -- `cx1da p0,r16,r17,#0'
+[^ :]+:[0-9]+: Error: ARM register expected -- `cx1d p0,APSR_nzcv,r15,#0'
+[^ :]+:[0-9]+: Error: ARM register expected -- `cx1da p0,APSR_nzcv,r15,#0'
+[^ :]+:[0-9]+: Error: Register must be an even register between r0-r10\. -- `cx1d p0,r9,r10,#0'
+[^ :]+:[0-9]+: Error: Register must be an even register between r0-r10\. -- `cx1da p0,r9,r10,#0'
+[^ :]+:[0-9]+: Error: Register must be an even register between r0-r10\. -- `cx1d p0,r13,r14,#0'
+[^ :]+:[0-9]+: Error: Register must be an even register between r0-r10\. -- `cx1da p0,r13,r14,#0'
+[^ :]+:[0-9]+: Error: instruction not allowed in IT block -- `cx1d p0,r0,r1,#0'
+[^ :]+:[0-9]+: Error: syntax error -- `cx1dne p0,r0,r1,#0'
+[^ :]+:[0-9]+: Error: syntax error -- `cx1dane p0,r0,r1,#0'
+[^ :]+:[0-9]+: Error: coprocessor for insn is not enabled for cde -- `cx1d p1,r0,r1,#0'
+[^ :]+:[0-9]+: Error: coprocessor for insn is not enabled for cde -- `cx1da p1,r0,r1,#0'
+[^ :]+:[0-9]+: Error: cx1d requires consecutive destination registers\. -- `cx1d p0,r0,r2,#0'
+[^ :]+:[0-9]+: Error: cx1d requires consecutive destination registers\. -- `cx1da p0,r0,r2,#0'
+[^ :]+:[0-9]+: Error: constant expression required -- `cx1d p0,r0,r1,r0,#0'
+[^ :]+:[0-9]+: Error: constant expression required -- `cx1da p0,r0,r1,r0,#0'
+[^ :]+:[0-9]+: Error: syntax error -- `cx1d p0,r0,#0'
+[^ :]+:[0-9]+: Error: syntax error -- `cx1da p0,r0,#0'
+[^ :]+:[0-9]+: Error: immediate value out of range -- `cx2 p0,r0,r0,#512'
+[^ :]+:[0-9]+: Error: immediate value out of range -- `cx2a p0,r0,r0,#512'
+[^ :]+:[0-9]+: Error: immediate value out of range -- `cx2 p0,r0,r0,#-1'
+[^ :]+:[0-9]+: Error: immediate value out of range -- `cx2a p0,r0,r0,#-1'
+[^ :]+:[0-9]+: Error: CDE Coprocessor must be in range 0-7 -- `cx2 p8,r0,r0,#0'
+[^ :]+:[0-9]+: Error: CDE Coprocessor must be in range 0-7 -- `cx2a p8,r0,r0,#0'
+[^ :]+:[0-9]+: Error: syntax error -- `cx2 p0,r16,r0,#0'
+[^ :]+:[0-9]+: Error: syntax error -- `cx2a p0,r16,r0,#0'
+[^ :]+:[0-9]+: Error: syntax error -- `cx2 p0,r0,r16,#0'
+[^ :]+:[0-9]+: Error: syntax error -- `cx2a p0,r0,r16,#0'
+[^ :]+:[0-9]+: Error: Register must be r0-r14 except r13, or APSR_nzcv\. -- `cx2 p0,r13,r0,#0'
+[^ :]+:[0-9]+: Error: Register must be r0-r14 except r13, or APSR_nzcv\. -- `cx2a p0,r13,r0,#0'
+[^ :]+:[0-9]+: Error: Register must be r0-r14 except r13, or APSR_nzcv\. -- `cx2 p0,r0,r13,#0'
+[^ :]+:[0-9]+: Error: Register must be r0-r14 except r13, or APSR_nzcv\. -- `cx2a p0,r0,r13,#0'
+[^ :]+:[0-9]+: Error: instruction not allowed in IT block -- `cx2 p0,r0,r0,#0'
+[^ :]+:[0-9]+: Error: syntax error -- `cx2ne p0,r0,r0,#0'
+[^ :]+:[0-9]+: Error: syntax error -- `cx2ane p0,r0,r0,#0'
+[^ :]+:[0-9]+: Error: coprocessor for insn is not enabled for cde -- `cx2 p1,r0,r0,#0'
+[^ :]+:[0-9]+: Error: coprocessor for insn is not enabled for cde -- `cx2a p1,r0,r0,#0'
+[^ :]+:[0-9]+: Error: constant expression required -- `cx2 p0,r0,r0,r0,#0'
+[^ :]+:[0-9]+: Error: constant expression required -- `cx2a p0,r0,r0,r0,#0'
+[^ :]+:[0-9]+: Error: syntax error -- `cx2 p0,r0,#0'
+[^ :]+:[0-9]+: Error: syntax error -- `cx2a p0,r0,#0'
+[^ :]+:[0-9]+: Error: Register must be r0-r14 except r13, or APSR_nzcv\. -- `cx2 p0,r0,r15,#0'
+[^ :]+:[0-9]+: Error: Register must be r0-r14 except r13, or APSR_nzcv\. -- `cx2a p0,r0,r15,#0'
+[^ :]+:[0-9]+: Error: Register must be r0-r14 except r13, or APSR_nzcv\. -- `cx2 p0,r15,r0,#0'
+[^ :]+:[0-9]+: Error: Register must be r0-r14 except r13, or APSR_nzcv\. -- `cx2a p0,r15,r0,#0'
+[^ :]+:[0-9]+: Error: immediate value out of range -- `cx2d p0,r0,r1,r0,#512'
+[^ :]+:[0-9]+: Error: immediate value out of range -- `cx2da p0,r0,r1,r0,#512'
+[^ :]+:[0-9]+: Error: immediate value out of range -- `cx2d p0,r0,r1,r0,#-1'
+[^ :]+:[0-9]+: Error: immediate value out of range -- `cx2da p0,r0,r1,r0,#-1'
+[^ :]+:[0-9]+: Error: CDE Coprocessor must be in range 0-7 -- `cx2d p8,r0,r1,r0,#0'
+[^ :]+:[0-9]+: Error: CDE Coprocessor must be in range 0-7 -- `cx2da p8,r0,r1,r0,#0'
+[^ :]+:[0-9]+: Error: ARM register expected -- `cx2d p0,r16,r17,r0,#0'
+[^ :]+:[0-9]+: Error: ARM register expected -- `cx2da p0,r16,r17,r0,#0'
+[^ :]+:[0-9]+: Error: syntax error -- `cx2d p0,r0,r1,r16,#0'
+[^ :]+:[0-9]+: Error: syntax error -- `cx2da p0,r0,r1,r16,#0'
+[^ :]+:[0-9]+: Error: ARM register expected -- `cx2d p0,APSR_nzcv,r15,r0,#0'
+[^ :]+:[0-9]+: Error: ARM register expected -- `cx2da p0,APSR_nzcv,r15,r0,#0'
+[^ :]+:[0-9]+: Error: Register must be an even register between r0-r10\. -- `cx2d p0,r9,r10,r0,#0'
+[^ :]+:[0-9]+: Error: Register must be an even register between r0-r10\. -- `cx2da p0,r9,r10,r0,#0'
+[^ :]+:[0-9]+: Error: Register must be an even register between r0-r10\. -- `cx2d p0,r12,r13,r0,#0'
+[^ :]+:[0-9]+: Error: Register must be an even register between r0-r10\. -- `cx2da p0,r12,r13,r0,#0'
+[^ :]+:[0-9]+: Error: Register must be r0-r14 except r13, or APSR_nzcv\. -- `cx2d p0,r0,r1,r13,#0'
+[^ :]+:[0-9]+: Error: Register must be r0-r14 except r13, or APSR_nzcv\. -- `cx2da p0,r0,r1,r13,#0'
+[^ :]+:[0-9]+: Error: Register must be r0-r14 except r13, or APSR_nzcv\. -- `cx2d p0,r0,r1,r15,#0'
+[^ :]+:[0-9]+: Error: Register must be r0-r14 except r13, or APSR_nzcv\. -- `cx2da p0,r0,r1,r15,#0'
+[^ :]+:[0-9]+: Error: instruction not allowed in IT block -- `cx2d p0,r0,r1,r0,#0'
+[^ :]+:[0-9]+: Error: syntax error -- `cx2dne p0,r0,r1,r0,#0'
+[^ :]+:[0-9]+: Error: syntax error -- `cx2dane p0,r0,r1,r0,#0'
+[^ :]+:[0-9]+: Error: coprocessor for insn is not enabled for cde -- `cx2d p1,r0,r1,r0,#0'
+[^ :]+:[0-9]+: Error: coprocessor for insn is not enabled for cde -- `cx2da p1,r0,r1,r0,#0'
+[^ :]+:[0-9]+: Error: cx2d requires consecutive destination registers\. -- `cx2d p0,r0,r2,r0,#0'
+[^ :]+:[0-9]+: Error: cx2d requires consecutive destination registers\. -- `cx2da p0,r0,r2,r0,#0'
+[^ :]+:[0-9]+: Error: constant expression required -- `cx2d p0,r0,r1,r0,r0,#0'
+[^ :]+:[0-9]+: Error: constant expression required -- `cx2da p0,r0,r1,r0,r0,#0'
+[^ :]+:[0-9]+: Error: syntax error -- `cx2d p0,r0,r0,#0'
+[^ :]+:[0-9]+: Error: syntax error -- `cx2da p0,r0,r0,#0'
+[^ :]+:[0-9]+: Error: immediate value out of range -- `cx3 p0,r0,r0,r0,#64'
+[^ :]+:[0-9]+: Error: immediate value out of range -- `cx3a p0,r0,r0,r0,#64'
+[^ :]+:[0-9]+: Error: immediate value out of range -- `cx3 p0,r0,r0,r0,#-1'
+[^ :]+:[0-9]+: Error: immediate value out of range -- `cx3a p0,r0,r0,r0,#-1'
+[^ :]+:[0-9]+: Error: CDE Coprocessor must be in range 0-7 -- `cx3 p8,r0,r0,r0,#0'
+[^ :]+:[0-9]+: Error: CDE Coprocessor must be in range 0-7 -- `cx3a p8,r0,r0,r0,#0'
+[^ :]+:[0-9]+: Error: syntax error -- `cx3 p0,r16,r0,r0,#0'
+[^ :]+:[0-9]+: Error: syntax error -- `cx3a p0,r16,r0,r0,#0'
+[^ :]+:[0-9]+: Error: syntax error -- `cx3 p0,r0,r16,r0,#0'
+[^ :]+:[0-9]+: Error: syntax error -- `cx3a p0,r0,r16,r0,#0'
+[^ :]+:[0-9]+: Error: syntax error -- `cx3 p0,r0,r0,r16,#0'
+[^ :]+:[0-9]+: Error: syntax error -- `cx3a p0,r0,r0,r16,#0'
+[^ :]+:[0-9]+: Error: Register must be r0-r14 except r13, or APSR_nzcv\. -- `cx3 p0,r13,r0,r0,#0'
+[^ :]+:[0-9]+: Error: Register must be r0-r14 except r13, or APSR_nzcv\. -- `cx3a p0,r13,r0,r0,#0'
+[^ :]+:[0-9]+: Error: Register must be r0-r14 except r13, or APSR_nzcv\. -- `cx3 p0,r0,r13,r0,#0'
+[^ :]+:[0-9]+: Error: Register must be r0-r14 except r13, or APSR_nzcv\. -- `cx3a p0,r0,r13,r0,#0'
+[^ :]+:[0-9]+: Error: Register must be r0-r14 except r13, or APSR_nzcv\. -- `cx3 p0,r0,r0,r13,#0'
+[^ :]+:[0-9]+: Error: Register must be r0-r14 except r13, or APSR_nzcv\. -- `cx3a p0,r0,r0,r13,#0'
+[^ :]+:[0-9]+: Error: instruction not allowed in IT block -- `cx3 p0,r0,r0,r0,#0'
+[^ :]+:[0-9]+: Error: syntax error -- `cx3ne p0,r0,r0,r0,#0'
+[^ :]+:[0-9]+: Error: syntax error -- `cx3ane p0,r0,r0,r0,#0'
+[^ :]+:[0-9]+: Error: coprocessor for insn is not enabled for cde -- `cx3 p1,r0,r0,r0,#0'
+[^ :]+:[0-9]+: Error: coprocessor for insn is not enabled for cde -- `cx3a p1,r0,r0,r0,#0'
+[^ :]+:[0-9]+: Error: constant expression required -- `cx3 p0,r0,r0,r0,r0,#0'
+[^ :]+:[0-9]+: Error: constant expression required -- `cx3a p0,r0,r0,r0,r0,#0'
+[^ :]+:[0-9]+: Error: syntax error -- `cx3 p0,r0,r0,#0'
+[^ :]+:[0-9]+: Error: syntax error -- `cx3a p0,r0,r0,#0'
+[^ :]+:[0-9]+: Error: Register must be r0-r14 except r13, or APSR_nzcv\. -- `cx3 p0,r15,r0,r0,#0'
+[^ :]+:[0-9]+: Error: Register must be r0-r14 except r13, or APSR_nzcv\. -- `cx3a p0,r15,r0,r0,#0'
+[^ :]+:[0-9]+: Error: Register must be r0-r14 except r13, or APSR_nzcv\. -- `cx3 p0,r0,r15,r0,#0'
+[^ :]+:[0-9]+: Error: Register must be r0-r14 except r13, or APSR_nzcv\. -- `cx3a p0,r0,r15,r0,#0'
+[^ :]+:[0-9]+: Error: Register must be r0-r14 except r13, or APSR_nzcv\. -- `cx3 p0,r0,r0,r15,#0'
+[^ :]+:[0-9]+: Error: Register must be r0-r14 except r13, or APSR_nzcv\. -- `cx3a p0,r0,r0,r15,#0'
+[^ :]+:[0-9]+: Error: immediate value out of range -- `cx3d p0,r0,r1,r0,r0,#64'
+[^ :]+:[0-9]+: Error: immediate value out of range -- `cx3da p0,r0,r1,r0,r0,#64'
+[^ :]+:[0-9]+: Error: immediate value out of range -- `cx3d p0,r0,r1,r0,r0,#-1'
+[^ :]+:[0-9]+: Error: immediate value out of range -- `cx3da p0,r0,r1,r0,r0,#-1'
+[^ :]+:[0-9]+: Error: CDE Coprocessor must be in range 0-7 -- `cx3d p8,r0,r1,r0,r0,#0'
+[^ :]+:[0-9]+: Error: CDE Coprocessor must be in range 0-7 -- `cx3da p8,r0,r1,r0,r0,#0'
+[^ :]+:[0-9]+: Error: ARM register expected -- `cx3d p0,r16,r17,r0,r0,#0'
+[^ :]+:[0-9]+: Error: ARM register expected -- `cx3da p0,r16,r17,r0,r0,#0'
+[^ :]+:[0-9]+: Error: syntax error -- `cx3d p0,r0,r1,r16,r0,#0'
+[^ :]+:[0-9]+: Error: syntax error -- `cx3da p0,r0,r1,r16,r0,#0'
+[^ :]+:[0-9]+: Error: syntax error -- `cx3d p0,r0,r1,r0,r16,#0'
+[^ :]+:[0-9]+: Error: syntax error -- `cx3da p0,r0,r1,r0,r16,#0'
+[^ :]+:[0-9]+: Error: ARM register expected -- `cx3d p0,APSR_nzcv,r15,r0,r0,#0'
+[^ :]+:[0-9]+: Error: ARM register expected -- `cx3da p0,APSR_nzcv,r15,r0,r0,#0'
+[^ :]+:[0-9]+: Error: Register must be an even register between r0-r10\. -- `cx3d p0,r9,r10,r0,r0,#0'
+[^ :]+:[0-9]+: Error: Register must be an even register between r0-r10\. -- `cx3da p0,r9,r10,r0,r0,#0'
+[^ :]+:[0-9]+: Error: Register must be an even register between r0-r10\. -- `cx3d p0,r12,r13,r0,r0,#0'
+[^ :]+:[0-9]+: Error: Register must be an even register between r0-r10\. -- `cx3da p0,r12,r13,r0,r0,#0'
+[^ :]+:[0-9]+: Error: Register must be r0-r14 except r13, or APSR_nzcv\. -- `cx3d p0,r0,r1,r13,r0,#0'
+[^ :]+:[0-9]+: Error: Register must be r0-r14 except r13, or APSR_nzcv\. -- `cx3da p0,r0,r1,r13,r0,#0'
+[^ :]+:[0-9]+: Error: Register must be r0-r14 except r13, or APSR_nzcv\. -- `cx3d p0,r0,r1,r0,r13,#0'
+[^ :]+:[0-9]+: Error: Register must be r0-r14 except r13, or APSR_nzcv\. -- `cx3da p0,r0,r1,r0,r13,#0'
+[^ :]+:[0-9]+: Error: Register must be r0-r14 except r13, or APSR_nzcv\. -- `cx3d p0,r0,r1,r15,r0,#0'
+[^ :]+:[0-9]+: Error: Register must be r0-r14 except r13, or APSR_nzcv\. -- `cx3da p0,r0,r1,r15,r0,#0'
+[^ :]+:[0-9]+: Error: Register must be r0-r14 except r13, or APSR_nzcv\. -- `cx3d p0,r0,r1,r0,r15,#0'
+[^ :]+:[0-9]+: Error: Register must be r0-r14 except r13, or APSR_nzcv\. -- `cx3da p0,r0,r1,r0,r15,#0'
+[^ :]+:[0-9]+: Error: instruction not allowed in IT block -- `cx3d p0,r0,r1,r0,r0,#0'
+[^ :]+:[0-9]+: Error: syntax error -- `cx3dne p0,r0,r1,r0,r0,#0'
+[^ :]+:[0-9]+: Error: syntax error -- `cx3dane p0,r0,r1,r0,r0,#0'
+[^ :]+:[0-9]+: Error: coprocessor for insn is not enabled for cde -- `cx3d p1,r0,r1,r0,r0,#0'
+[^ :]+:[0-9]+: Error: coprocessor for insn is not enabled for cde -- `cx3da p1,r0,r1,r0,r0,#0'
+[^ :]+:[0-9]+: Error: cx3d requires consecutive destination registers\. -- `cx3d p0,r0,r2,r0,r0,#0'
+[^ :]+:[0-9]+: Error: cx3d requires consecutive destination registers\. -- `cx3da p0,r0,r2,r0,r0,#0'
+[^ :]+:[0-9]+: Error: constant expression required -- `cx3d p0,r0,r1,r0,r0,r0,#0'
+[^ :]+:[0-9]+: Error: constant expression required -- `cx3da p0,r0,r1,r0,r0,r0,#0'
+[^ :]+:[0-9]+: Error: syntax error -- `cx3d p0,r0,r0,r0,#0'
+[^ :]+:[0-9]+: Error: syntax error -- `cx3da p0,r0,r0,r0,#0'
diff --git a/gas/testsuite/gas/arm/cde-warnings.s b/gas/testsuite/gas/arm/cde-warnings.s
new file mode 100644
index 00000000000..8e5759a64e4
--- /dev/null
+++ b/gas/testsuite/gas/arm/cde-warnings.s
@@ -0,0 +1,335 @@
+.syntax unified
+# cx1{a}
+# Immediate out of range.
+# Each register out of range.
+# r13 => constrained unpredictable
+# itblock => constrained unpredictable
+# Error given when using coprocessor number not enabled on command line.
+# Too many arguments
+# Too little arguments
+# r15 instead of APSR_nzcv
+
+cx1 p0, r0, #8192
+cx1a p0, r0, #8192
+cx1 p0, r0, #-1
+cx1a p0, r0, #-1
+
+cx1 p8, r0, #0
+cx1a p8, r0, #0
+
+cx1 p0, r16, #0
+cx1a p0, r16, #0
+
+cx1 p0, r13, #0
+cx1a p0, r13, #0
+
+ittt ne
+cx1 p0, r0, #0
+cx1ne p0, r0, #0
+cx1ane p0, r0, #0
+
+cx1 p1, r0, #0
+cx1a p1, r0, #0
+
+cx1 p0, r0, r0, #0
+cx1a p0, r0, r0, #0
+
+cx1 p0, #0
+cx1a p0, #0
+
+cx1 p0, r15, #0
+cx1a p0, r15, #0
+
+# cx1d{a}
+# Immediate out of range.
+# Each register out of range.
+# APSR_nzcv disallowed as destination register.
+# rd<odd> => constrained unpredictable
+# r< N > 10 > => constrained unpredictable
+# IT block => constrained unpredictable
+#
+# Error given when using coprocessor number not enabled on command line.
+# Disallow non-incrementing values in destination.
+# Too many arguments
+# Too little arguments
+
+cx1d p0, r0, r1, #8192
+cx1da p0, r0, r1, #8192
+cx1d p0, r0, r1, #-1
+cx1da p0, r0, r1, #-1
+
+cx1d p8, r0, r1, #0
+cx1da p8, r0, r1, #0
+
+cx1d p0, r16, r17, #0
+cx1da p0, r16, r17, #0
+
+cx1d p0, APSR_nzcv, r15, #0
+cx1da p0, APSR_nzcv, r15, #0
+
+cx1d p0, r9, r10, #0
+cx1da p0, r9, r10, #0
+
+cx1d p0, r13, r14, #0
+cx1da p0, r13, r14, #0
+
+ittt ne
+cx1d p0, r0, r1, #0
+cx1dne p0, r0, r1, #0
+cx1dane p0, r0, r1, #0
+
+cx1d p1, r0, r1, #0
+cx1da p1, r0, r1, #0
+
+cx1d p0, r0, r2, #0
+cx1da p0, r0, r2, #0
+
+cx1d p0, r0, r1, r0, #0
+cx1da p0, r0, r1, r0, #0
+
+cx1d p0, r0, #0
+cx1da p0, r0, #0
+
+# cx2{a}
+# Immediate out of range.
+# Each register out of range.
+# rd13 => constrained unpredictable
+# rn13 => constrained unpredictable
+# IT block => constrained unpredictable
+#
+# Error given when using coprocessor number not enabled on command line.
+# Too many arguments
+# Too little arguments.
+# r15 instead of APSR_nzcv
+
+cx2 p0, r0, r0, #512
+cx2a p0, r0, r0, #512
+cx2 p0, r0, r0, #-1
+cx2a p0, r0, r0, #-1
+
+cx2 p8, r0, r0, #0
+cx2a p8, r0, r0, #0
+
+cx2 p0, r16, r0, #0
+cx2a p0, r16, r0, #0
+
+cx2 p0, r0, r16, #0
+cx2a p0, r0, r16, #0
+
+cx2 p0, r13, r0, #0
+cx2a p0, r13, r0, #0
+
+cx2 p0, r0, r13, #0
+cx2a p0, r0, r13, #0
+
+ittt ne
+cx2 p0, r0, r0, #0
+cx2ne p0, r0, r0, #0
+cx2ane p0, r0, r0, #0
+
+cx2 p1, r0, r0, #0
+cx2a p1, r0, r0, #0
+
+cx2 p0, r0, r0, r0, #0
+cx2a p0, r0, r0, r0, #0
+
+cx2 p0, r0, #0
+cx2a p0, r0, #0
+
+cx2 p0, r0, r15, #0
+cx2a p0, r0, r15, #0
+
+cx2 p0, r15, r0, #0
+cx2a p0, r15, r0, #0
+
+# cx2d{a}
+# Immediate out of range.
+# Each register out of range.
+# APSR_nzcv disallowed as destination register.
+# rd<odd> => constrained unpredictable
+# rd< N > 10 > => constrained unpredictable
+# rn13 => constrained unpredictable
+# IT block => constrained unpredictable
+#
+# Error given when using coprocessor number not enabled on command line.
+# Disallow non-incrementing values in destination.
+# Too many arguments
+# Too little arguments
+cx2d p0, r0, r1, r0, #512
+cx2da p0, r0, r1, r0, #512
+cx2d p0, r0, r1, r0, #-1
+cx2da p0, r0, r1, r0, #-1
+
+cx2d p8, r0, r1, r0, #0
+cx2da p8, r0, r1, r0, #0
+
+cx2d p0, r16, r17, r0, #0
+cx2da p0, r16, r17, r0, #0
+
+cx2d p0, r0, r1, r16, #0
+cx2da p0, r0, r1, r16, #0
+
+cx2d p0, APSR_nzcv, r15, r0, #0
+cx2da p0, APSR_nzcv, r15, r0, #0
+
+cx2d p0, r9, r10, r0, #0
+cx2da p0, r9, r10, r0, #0
+
+cx2d p0, r12, r13, r0, #0
+cx2da p0, r12, r13, r0, #0
+
+cx2d p0, r0, r1, r13, #0
+cx2da p0, r0, r1, r13, #0
+
+cx2d p0, r0, r1, r15, #0
+cx2da p0, r0, r1, r15, #0
+
+ittt ne
+cx2d p0, r0, r1, r0, #0
+cx2dne p0, r0, r1, r0, #0
+cx2dane p0, r0, r1, r0, #0
+
+cx2d p1, r0, r1, r0, #0
+cx2da p1, r0, r1, r0, #0
+
+cx2d p0, r0, r2, r0, #0
+cx2da p0, r0, r2, r0, #0
+
+cx2d p0, r0, r1, r0, r0, #0
+cx2da p0, r0, r1, r0, r0, #0
+
+cx2d p0, r0, r0, #0
+cx2da p0, r0, r0, #0
+
+# cx2{a}
+# Immediate out of range.
+# Each register out of range.
+# rd13 => constrained unpredictable
+# rn13 => constrained unpredictable
+# rm13 => constrained unpredictable
+# IT block => constrained unpredictable
+#
+# Error given when using coprocessor number not enabled on command line.
+# Too many arguments
+# Too little arguments.
+# r15 instead of APSR_nzcv
+
+cx3 p0, r0, r0, r0, #64
+cx3a p0, r0, r0, r0, #64
+cx3 p0, r0, r0, r0, #-1
+cx3a p0, r0, r0, r0, #-1
+
+cx3 p8, r0, r0, r0, #0
+cx3a p8, r0, r0, r0, #0
+
+cx3 p0, r16, r0, r0, #0
+cx3a p0, r16, r0, r0, #0
+
+cx3 p0, r0, r16, r0, #0
+cx3a p0, r0, r16, r0, #0
+
+cx3 p0, r0, r0, r16, #0
+cx3a p0, r0, r0, r16, #0
+
+cx3 p0, r13, r0, r0, #0
+cx3a p0, r13, r0, r0, #0
+
+cx3 p0, r0, r13, r0, #0
+cx3a p0, r0, r13, r0, #0
+
+cx3 p0, r0, r0, r13, #0
+cx3a p0, r0, r0, r13, #0
+
+ittt ne
+cx3 p0, r0, r0, r0, #0
+cx3ne p0, r0, r0, r0, #0
+cx3ane p0, r0, r0, r0, #0
+
+cx3 p1, r0, r0, r0, #0
+cx3a p1, r0, r0, r0, #0
+
+cx3 p0, r0, r0, r0, r0, #0
+cx3a p0, r0, r0, r0, r0, #0
+
+cx3 p0, r0, r0, #0
+cx3a p0, r0, r0, #0
+
+cx3 p0, r15, r0, r0, #0
+cx3a p0, r15, r0, r0, #0
+
+cx3 p0, r0, r15, r0, #0
+cx3a p0, r0, r15, r0, #0
+
+cx3 p0, r0, r0, r15, #0
+cx3a p0, r0, r0, r15, #0
+
+# cx3d{a}
+# Immediate out of range.
+# Each register out of range.
+# APSR_nzcv disallowed as destination register.
+# rd<odd> => constrained unpredictable
+# rd< N > 10 > => constrained unpredictable
+# rn13 => constrained unpredictable
+# rm13 => constrained unpredictable
+# rn15 disallowed (pattern matches APSR_nzcv)
+# rm15 disallowed (pattern matches APSR_nzcv)
+# IT block => constrained unpredictable
+#
+# Error given when using coprocessor number not enabled on command line.
+# Disallow non-incrementing values in destination.
+# Too many arguments
+# Too little arguments
+cx3d p0, r0, r1, r0, r0, #64
+cx3da p0, r0, r1, r0, r0, #64
+cx3d p0, r0, r1, r0, r0, #-1
+cx3da p0, r0, r1, r0, r0, #-1
+
+cx3d p8, r0, r1, r0, r0, #0
+cx3da p8, r0, r1, r0, r0, #0
+
+cx3d p0, r16, r17, r0, r0, #0
+cx3da p0, r16, r17, r0, r0, #0
+
+cx3d p0, r0, r1, r16, r0, #0
+cx3da p0, r0, r1, r16, r0, #0
+
+cx3d p0, r0, r1, r0, r16, #0
+cx3da p0, r0, r1, r0, r16, #0
+
+cx3d p0, APSR_nzcv, r15, r0, r0, #0
+cx3da p0, APSR_nzcv, r15, r0, r0, #0
+
+cx3d p0, r9, r10, r0, r0, #0
+cx3da p0, r9, r10, r0, r0, #0
+
+cx3d p0, r12, r13, r0, r0, #0
+cx3da p0, r12, r13, r0, r0, #0
+
+cx3d p0, r0, r1, r13, r0, #0
+cx3da p0, r0, r1, r13, r0, #0
+
+cx3d p0, r0, r1, r0, r13, #0
+cx3da p0, r0, r1, r0, r13, #0
+
+cx3d p0, r0, r1, r15, r0, #0
+cx3da p0, r0, r1, r15, r0, #0
+
+cx3d p0, r0, r1, r0, r15, #0
+cx3da p0, r0, r1, r0, r15, #0
+
+ittt ne
+cx3d p0, r0, r1, r0, r0, #0
+cx3dne p0, r0, r1, r0, r0, #0
+cx3dane p0, r0, r1, r0, r0, #0
+
+cx3d p1, r0, r1, r0, r0, #0
+cx3da p1, r0, r1, r0, r0, #0
+
+cx3d p0, r0, r2, r0, r0, #0
+cx3da p0, r0, r2, r0, r0, #0
+
+cx3d p0, r0, r1, r0, r0, r0, #0
+cx3da p0, r0, r1, r0, r0, r0, #0
+
+cx3d p0, r0, r0, r0, #0
+cx3da p0, r0, r0, r0, #0
diff --git a/gas/testsuite/gas/arm/cde.d b/gas/testsuite/gas/arm/cde.d
new file mode 100644
index 00000000000..34de201513b
--- /dev/null
+++ b/gas/testsuite/gas/arm/cde.d
@@ -0,0 +1,119 @@
+#name: Custom Datapath Extension (CDE)
+#source: cde.s
+#as: -mno-warn-deprecated -march=armv8.1-m.main+cdecp0+cdecp7+mve.fp -I$srcdir/$subdir
+#as: -mno-warn-deprecated -march=armv8.1-m.main+cdecp0+cdecp7+mve -I$srcdir/$subdir
+#as: -mno-warn-deprecated -march=armv8.1-m.main+cdecp0+cdecp1+cdecp2+cdecp3+cdecp4+cdecp5+cdecp6+cdecp7+mve.fp -I$srcdir/$subdir
+#as: -mno-warn-deprecated -march=armv8.1-m.main+cdecp0+cdecp1+cdecp2+cdecp3+cdecp4+cdecp5+cdecp6+cdecp7+mve -I$srcdir/$subdir
+#objdump: -M force-thumb -dr --show-raw-insn -marmv8.1-m.main -M coproc0=cde -M coproc7=cde
+#...
+00000000 <\.text>:
+ *[0-9a-f]+: ee00 0000 cx1 p0, r0, #0
+ *[0-9a-f]+: ee3f 0000 cx1 p0, r0, #8064
+ *[0-9a-f]+: ee00 0080 cx1 p0, r0, #64
+ *[0-9a-f]+: ee00 003f cx1 p0, r0, #63
+ *[0-9a-f]+: ee00 0700 cx1 p7, r0, #0
+ *[0-9a-f]+: ee00 f000 cx1 p0, APSR_nzcv, #0
+ *[0-9a-f]+: ee00 9000 cx1 p0, r9, #0
+ *[0-9a-f]+: fe00 0000 cx1a p0, r0, #0
+ *[0-9a-f]+: fe3f 0000 cx1a p0, r0, #8064
+ *[0-9a-f]+: fe00 0080 cx1a p0, r0, #64
+ *[0-9a-f]+: fe00 003f cx1a p0, r0, #63
+ *[0-9a-f]+: fe00 0700 cx1a p7, r0, #0
+ *[0-9a-f]+: fe00 f000 cx1a p0, APSR_nzcv, #0
+ *[0-9a-f]+: fe00 9000 cx1a p0, r9, #0
+ *[0-9a-f]+: bf18 it ne
+ *[0-9a-f]+: fe00 0000 cx1a p0, r0, #0
+ *[0-9a-f]+: ee00 0040 cx1d p0, r0, r1, #0
+ *[0-9a-f]+: ee3f 0040 cx1d p0, r0, r1, #8064
+ *[0-9a-f]+: ee00 00c0 cx1d p0, r0, r1, #64
+ *[0-9a-f]+: ee00 007f cx1d p0, r0, r1, #63
+ *[0-9a-f]+: ee00 0740 cx1d p7, r0, r1, #0
+ *[0-9a-f]+: ee00 a040 cx1d p0, sl, fp, #0
+ *[0-9a-f]+: fe00 0040 cx1da p0, r0, r1, #0
+ *[0-9a-f]+: fe3f 0040 cx1da p0, r0, r1, #8064
+ *[0-9a-f]+: fe00 00c0 cx1da p0, r0, r1, #64
+ *[0-9a-f]+: fe00 007f cx1da p0, r0, r1, #63
+ *[0-9a-f]+: fe00 0740 cx1da p7, r0, r1, #0
+ *[0-9a-f]+: fe00 a040 cx1da p0, sl, fp, #0
+ *[0-9a-f]+: bf18 it ne
+ *[0-9a-f]+: fe00 0040 cx1da p0, r0, r1, #0
+ *[0-9a-f]+: ee40 0000 cx2 p0, r0, r0, #0
+ *[0-9a-f]+: ee70 0000 cx2 p0, r0, r0, #384
+ *[0-9a-f]+: ee40 0080 cx2 p0, r0, r0, #64
+ *[0-9a-f]+: ee40 003f cx2 p0, r0, r0, #63
+ *[0-9a-f]+: ee40 0700 cx2 p7, r0, r0, #0
+ *[0-9a-f]+: ee40 f000 cx2 p0, APSR_nzcv, r0, #0
+ *[0-9a-f]+: ee40 9000 cx2 p0, r9, r0, #0
+ *[0-9a-f]+: ee4f 0000 cx2 p0, r0, APSR_nzcv, #0
+ *[0-9a-f]+: ee49 0000 cx2 p0, r0, r9, #0
+ *[0-9a-f]+: fe40 0000 cx2a p0, r0, r0, #0
+ *[0-9a-f]+: fe70 0000 cx2a p0, r0, r0, #384
+ *[0-9a-f]+: fe40 0080 cx2a p0, r0, r0, #64
+ *[0-9a-f]+: fe40 003f cx2a p0, r0, r0, #63
+ *[0-9a-f]+: fe40 0700 cx2a p7, r0, r0, #0
+ *[0-9a-f]+: fe40 f000 cx2a p0, APSR_nzcv, r0, #0
+ *[0-9a-f]+: fe40 9000 cx2a p0, r9, r0, #0
+ *[0-9a-f]+: fe4f 0000 cx2a p0, r0, APSR_nzcv, #0
+ *[0-9a-f]+: fe49 0000 cx2a p0, r0, r9, #0
+ *[0-9a-f]+: bf18 it ne
+ *[0-9a-f]+: fe40 0000 cx2a p0, r0, r0, #0
+ *[0-9a-f]+: ee40 0040 cx2d p0, r0, r1, r0, #0
+ *[0-9a-f]+: ee70 0040 cx2d p0, r0, r1, r0, #384
+ *[0-9a-f]+: ee40 00c0 cx2d p0, r0, r1, r0, #64
+ *[0-9a-f]+: ee40 007f cx2d p0, r0, r1, r0, #63
+ *[0-9a-f]+: ee40 0740 cx2d p7, r0, r1, r0, #0
+ *[0-9a-f]+: ee40 a040 cx2d p0, sl, fp, r0, #0
+ *[0-9a-f]+: ee4f 0040 cx2d p0, r0, r1, APSR_nzcv, #0
+ *[0-9a-f]+: ee49 0040 cx2d p0, r0, r1, r9, #0
+ *[0-9a-f]+: fe40 0040 cx2da p0, r0, r1, r0, #0
+ *[0-9a-f]+: fe70 0040 cx2da p0, r0, r1, r0, #384
+ *[0-9a-f]+: fe40 00c0 cx2da p0, r0, r1, r0, #64
+ *[0-9a-f]+: fe40 007f cx2da p0, r0, r1, r0, #63
+ *[0-9a-f]+: fe40 0740 cx2da p7, r0, r1, r0, #0
+ *[0-9a-f]+: fe40 a040 cx2da p0, sl, fp, r0, #0
+ *[0-9a-f]+: fe4f 0040 cx2da p0, r0, r1, APSR_nzcv, #0
+ *[0-9a-f]+: fe49 0040 cx2da p0, r0, r1, r9, #0
+ *[0-9a-f]+: ee80 0000 cx3 p0, r0, r0, r0, #0
+ *[0-9a-f]+: eef0 0000 cx3 p0, r0, r0, r0, #56
+ *[0-9a-f]+: ee80 0080 cx3 p0, r0, r0, r0, #4
+ *[0-9a-f]+: ee80 0030 cx3 p0, r0, r0, r0, #3
+ *[0-9a-f]+: ee80 0700 cx3 p7, r0, r0, r0, #0
+ *[0-9a-f]+: ee80 000f cx3 p0, APSR_nzcv, r0, r0, #0
+ *[0-9a-f]+: ee80 0009 cx3 p0, r9, r0, r0, #0
+ *[0-9a-f]+: ee8f 0000 cx3 p0, r0, APSR_nzcv, r0, #0
+ *[0-9a-f]+: ee89 0000 cx3 p0, r0, r9, r0, #0
+ *[0-9a-f]+: ee80 f000 cx3 p0, r0, r0, APSR_nzcv, #0
+ *[0-9a-f]+: ee80 9000 cx3 p0, r0, r0, r9, #0
+ *[0-9a-f]+: fe80 0000 cx3a p0, r0, r0, r0, #0
+ *[0-9a-f]+: fef0 0000 cx3a p0, r0, r0, r0, #56
+ *[0-9a-f]+: fe80 0080 cx3a p0, r0, r0, r0, #4
+ *[0-9a-f]+: fe80 0030 cx3a p0, r0, r0, r0, #3
+ *[0-9a-f]+: fe80 0700 cx3a p7, r0, r0, r0, #0
+ *[0-9a-f]+: fe80 000f cx3a p0, APSR_nzcv, r0, r0, #0
+ *[0-9a-f]+: fe80 0009 cx3a p0, r9, r0, r0, #0
+ *[0-9a-f]+: fe8f 0000 cx3a p0, r0, APSR_nzcv, r0, #0
+ *[0-9a-f]+: fe89 0000 cx3a p0, r0, r9, r0, #0
+ *[0-9a-f]+: fe80 f000 cx3a p0, r0, r0, APSR_nzcv, #0
+ *[0-9a-f]+: fe80 9000 cx3a p0, r0, r0, r9, #0
+ *[0-9a-f]+: bf18 it ne
+ *[0-9a-f]+: fe80 0000 cx3a p0, r0, r0, r0, #0
+ *[0-9a-f]+: ee80 0040 cx3d p0, r0, r1, r0, r0, #0
+ *[0-9a-f]+: eef0 0040 cx3d p0, r0, r1, r0, r0, #56
+ *[0-9a-f]+: ee80 00c0 cx3d p0, r0, r1, r0, r0, #4
+ *[0-9a-f]+: ee80 0070 cx3d p0, r0, r1, r0, r0, #3
+ *[0-9a-f]+: ee80 0740 cx3d p7, r0, r1, r0, r0, #0
+ *[0-9a-f]+: ee80 004a cx3d p0, sl, fp, r0, r0, #0
+ *[0-9a-f]+: ee8f 0040 cx3d p0, r0, r1, APSR_nzcv, r0, #0
+ *[0-9a-f]+: ee89 0040 cx3d p0, r0, r1, r9, r0, #0
+ *[0-9a-f]+: ee80 f040 cx3d p0, r0, r1, r0, APSR_nzcv, #0
+ *[0-9a-f]+: ee80 9040 cx3d p0, r0, r1, r0, r9, #0
+ *[0-9a-f]+: fe80 0040 cx3da p0, r0, r1, r0, r0, #0
+ *[0-9a-f]+: fef0 0040 cx3da p0, r0, r1, r0, r0, #56
+ *[0-9a-f]+: fe80 00c0 cx3da p0, r0, r1, r0, r0, #4
+ *[0-9a-f]+: fe80 0070 cx3da p0, r0, r1, r0, r0, #3
+ *[0-9a-f]+: fe80 0740 cx3da p7, r0, r1, r0, r0, #0
+ *[0-9a-f]+: fe80 004a cx3da p0, sl, fp, r0, r0, #0
+ *[0-9a-f]+: fe8f 0040 cx3da p0, r0, r1, APSR_nzcv, r0, #0
+ *[0-9a-f]+: fe89 0040 cx3da p0, r0, r1, r9, r0, #0
+ *[0-9a-f]+: fe80 f040 cx3da p0, r0, r1, r0, APSR_nzcv, #0
+ *[0-9a-f]+: fe80 9040 cx3da p0, r0, r1, r0, r9, #0
diff --git a/gas/testsuite/gas/arm/cde.s b/gas/testsuite/gas/arm/cde.s
new file mode 100644
index 00000000000..1ee18704941
--- /dev/null
+++ b/gas/testsuite/gas/arm/cde.s
@@ -0,0 +1,3 @@
+.syntax unified
+
+.include "cde-scalar.s"