diff --git a/gas/config/tc-arm.c b/gas/config/tc-arm.c index abe37b72eacd9c2b4ea2fae113dcd9ab339cb2f5..a4b79dc9d4edf131608fe28a56c2d12080c59724 100644 --- a/gas/config/tc-arm.c +++ b/gas/config/tc-arm.c @@ -6957,6 +6957,9 @@ enum operand_parse_code OP_RNSDQ_RNSC_MQ_RR, /* Vector S, D or Q reg, or MVE vector reg , or Neon scalar, or ARM register. */ OP_RNDQ_RNSC, /* Neon D or Q reg, or Neon scalar. */ + OP_RNDQ_RNSC_RR, /* Neon D or Q reg, Neon scalar, or ARM register. */ + OP_RNDQMQ_RNSC_RR, /* Neon D or Q reg, Neon scalar, MVE vector or ARM + register. */ OP_RNDQMQ_RNSC, /* Neon D, Q or MVE vector reg, or Neon scalar. */ OP_RND_RNSC, /* Neon D reg, or Neon scalar. */ OP_VMOV, /* Neon VMOV operands. */ @@ -7361,6 +7364,13 @@ parse_operands (char *str, const unsigned int *pattern, bfd_boolean thumb) } break; + case OP_RNDQMQ_RNSC_RR: + po_reg_or_goto (REG_TYPE_MQ, try_rndq_rnsc_rr); + break; + try_rndq_rnsc_rr: + case OP_RNDQ_RNSC_RR: + po_reg_or_goto (REG_TYPE_RN, try_rndq_rnsc); + break; case OP_RNDQMQ_RNSC: po_reg_or_goto (REG_TYPE_MQ, try_rndq_rnsc); break; @@ -15996,6 +16006,15 @@ mve_encode_qqr (int size, int U, int fp) /* vqsub. */ else if (((unsigned)inst.instruction) == 0x210) inst.instruction = 0xee001f60; + /* vqrdmlah. */ + else if (((unsigned)inst.instruction) == 0x3000b10) + inst.instruction = 0xee000e40; + /* vqdmulh. */ + else if (((unsigned)inst.instruction) == 0x0000b00) + inst.instruction = 0xee010e60; + /* vqrdmulh. */ + else if (((unsigned)inst.instruction) == 0x1000b00) + inst.instruction = 0xfe010e60; /* Set U-bit. */ inst.instruction |= U << 28; @@ -17184,8 +17203,12 @@ do_neon_mul (void) static void do_neon_qdmulh (void) { + if (check_simd_pred_availability (0, NEON_CHECK_ARCH | NEON_CHECK_CC)) + return; + if (inst.operands[2].isscalar) { + constraint (ARM_CPU_HAS_FEATURE (cpu_variant, mve_ext), BAD_FPU); enum neon_shape rs = neon_select_shape (NS_DDS, NS_QQS, NS_NULL); struct neon_type_el et = neon_check_type (3, rs, N_EQK, N_EQK, N_S16 | N_S32 | N_KEY); @@ -17194,12 +17217,27 @@ do_neon_qdmulh (void) } else { - enum neon_shape rs = neon_select_shape (NS_DDD, NS_QQQ, NS_NULL); - struct neon_type_el et = neon_check_type (3, rs, - N_EQK, N_EQK, N_S16 | N_S32 | N_KEY); + enum neon_shape rs; + struct neon_type_el et; + if (ARM_CPU_HAS_FEATURE (cpu_variant, mve_ext)) + { + rs = neon_select_shape (NS_QQR, NS_QQQ, NS_NULL); + et = neon_check_type (3, rs, + N_EQK, N_EQK, N_S8 | N_S16 | N_S32 | N_KEY); + } + else + { + rs = neon_select_shape (NS_DDD, NS_QQQ, NS_NULL); + et = neon_check_type (3, rs, + N_EQK, N_EQK, N_S16 | N_S32 | N_KEY); + } + NEON_ENCODE (INTEGER, inst); - /* The U bit (rounding) comes from bit mask. */ - neon_three_same (neon_quad (rs), 0, et.size); + if (rs == NS_QQR) + mve_encode_qqr (et.size, 0, 0); + else + /* The U bit (rounding) comes from bit mask. */ + neon_three_same (neon_quad (rs), 0, et.size); } } @@ -17308,6 +17346,20 @@ do_mve_vmulh (void) mve_encode_qqq (et.type == NT_unsigned, et.size); } +static void +do_mve_vqdmlah (void) +{ + enum neon_shape rs = neon_select_shape (NS_QQR, NS_NULL); + struct neon_type_el et + = neon_check_type (3, rs, N_EQK, N_EQK, N_SU_MVE | N_KEY); + + if (inst.cond > COND_ALWAYS) + inst.pred_insn_type = INSIDE_VPT_INSN; + else + inst.pred_insn_type = MVE_OUTSIDE_PRED_INSN; + + mve_encode_qqr (et.size, et.type == NT_unsigned, 0); +} static void do_mve_vqdmladh (void) @@ -17559,32 +17611,45 @@ do_mve_vmaxv (void) static void do_neon_qrdmlah (void) { - /* Check we're on the correct architecture. */ - if (!mark_feature_used (&fpu_neon_ext_armv8)) - inst.error = - _("instruction form not available on this architecture."); - else if (!mark_feature_used (&fpu_neon_ext_v8_1)) - { - as_warn (_("this instruction implies use of ARMv8.1 AdvSIMD.")); - record_feature_use (&fpu_neon_ext_v8_1); - } - - if (inst.operands[2].isscalar) + if (check_simd_pred_availability (0, NEON_CHECK_ARCH | NEON_CHECK_CC)) + return; + if (!ARM_CPU_HAS_FEATURE (cpu_variant, mve_ext)) { - enum neon_shape rs = neon_select_shape (NS_DDS, NS_QQS, NS_NULL); - struct neon_type_el et = neon_check_type (3, rs, - N_EQK, N_EQK, N_S16 | N_S32 | N_KEY); - NEON_ENCODE (SCALAR, inst); - neon_mul_mac (et, neon_quad (rs)); + /* Check we're on the correct architecture. */ + if (!mark_feature_used (&fpu_neon_ext_armv8)) + inst.error + = _("instruction form not available on this architecture."); + else if (!mark_feature_used (&fpu_neon_ext_v8_1)) + { + as_warn (_("this instruction implies use of ARMv8.1 AdvSIMD.")); + record_feature_use (&fpu_neon_ext_v8_1); + } + if (inst.operands[2].isscalar) + { + enum neon_shape rs = neon_select_shape (NS_DDS, NS_QQS, NS_NULL); + struct neon_type_el et = neon_check_type (3, rs, + N_EQK, N_EQK, N_S16 | N_S32 | N_KEY); + NEON_ENCODE (SCALAR, inst); + neon_mul_mac (et, neon_quad (rs)); + } + else + { + enum neon_shape rs = neon_select_shape (NS_DDD, NS_QQQ, NS_NULL); + struct neon_type_el et = neon_check_type (3, rs, + N_EQK, N_EQK, N_S16 | N_S32 | N_KEY); + NEON_ENCODE (INTEGER, inst); + /* The U bit (rounding) comes from bit mask. */ + neon_three_same (neon_quad (rs), 0, et.size); + } } else { - enum neon_shape rs = neon_select_shape (NS_DDD, NS_QQQ, NS_NULL); - struct neon_type_el et = neon_check_type (3, rs, - N_EQK, N_EQK, N_S16 | N_S32 | N_KEY); + enum neon_shape rs = neon_select_shape (NS_QQR, NS_NULL); + struct neon_type_el et + = neon_check_type (3, rs, N_EQK, N_EQK, N_SU_MVE | N_KEY); + NEON_ENCODE (INTEGER, inst); - /* The U bit (rounding) comes from bit mask. */ - neon_three_same (neon_quad (rs), 0, et.size); + mve_encode_qqr (et.size, et.type == NT_unsigned, 0); } } @@ -24071,9 +24136,7 @@ static const struct asm_opcode insns[] = /* VMUL takes I8 I16 I32 F32 P8. */ nUF(vmulq, _vmul, 3, (RNQ, oRNQ, RNDQ_RNSC), neon_mul), /* VQD{R}MULH takes S16 S32. */ - nUF(vqdmulh, _vqdmulh, 3, (RNDQ, oRNDQ, RNDQ_RNSC), neon_qdmulh), nUF(vqdmulhq, _vqdmulh, 3, (RNQ, oRNQ, RNDQ_RNSC), neon_qdmulh), - nUF(vqrdmulh, _vqrdmulh, 3, (RNDQ, oRNDQ, RNDQ_RNSC), neon_qdmulh), nUF(vqrdmulhq, _vqrdmulh, 3, (RNQ, oRNQ, RNDQ_RNSC), neon_qdmulh), NUF(vacge, 0000e10, 3, (RNDQ, oRNDQ, RNDQ), neon_fcmp_absolute), NUF(vacgeq, 0000e10, 3, (RNQ, oRNQ, RNQ), neon_fcmp_absolute), @@ -24088,7 +24151,6 @@ static const struct asm_opcode insns[] = NUF(vrsqrts, 0200f10, 3, (RNDQ, oRNDQ, RNDQ), neon_step), NUF(vrsqrtsq, 0200f10, 3, (RNQ, oRNQ, RNQ), neon_step), /* ARM v8.1 extension. */ - nUF (vqrdmlah, _vqrdmlah, 3, (RNDQ, oRNDQ, RNDQ_RNSC), neon_qrdmlah), nUF (vqrdmlahq, _vqrdmlah, 3, (RNQ, oRNQ, RNDQ_RNSC), neon_qrdmlah), nUF (vqrdmlsh, _vqrdmlsh, 3, (RNDQ, oRNDQ, RNDQ_RNSC), neon_qrdmlah), nUF (vqrdmlshq, _vqrdmlsh, 3, (RNQ, oRNQ, RNDQ_RNSC), neon_qrdmlah), @@ -24776,6 +24838,9 @@ static const struct asm_opcode insns[] = mToC("vqdmlsdhx", fe001e00, 3, (RMQ, RMQ, RMQ), mve_vqdmladh), mToC("vqrdmlsdh", fe000e01, 3, (RMQ, RMQ, RMQ), mve_vqdmladh), mToC("vqrdmlsdhx",fe001e01, 3, (RMQ, RMQ, RMQ), mve_vqdmladh), + mToC("vqdmlah", ee000e60, 3, (RMQ, RMQ, RR), mve_vqdmlah), + mToC("vqdmlash", ee001e60, 3, (RMQ, RMQ, RR), mve_vqdmlah), + mToC("vqrdmlash", ee001e40, 3, (RMQ, RMQ, RR), mve_vqdmlah), #undef THUMB_VARIANT #define THUMB_VARIANT & mve_fp_ext @@ -24859,6 +24924,9 @@ static const struct asm_opcode insns[] = mnUF(vmvn, _vmvn, 2, (RNDQMQ, RNDQMQ_Ibig), neon_mvn), MNUF(vqabs, 1b00700, 2, (RNDQMQ, RNDQMQ), neon_sat_abs_neg), MNUF(vqneg, 1b00780, 2, (RNDQMQ, RNDQMQ), neon_sat_abs_neg), + mnUF(vqrdmlah, _vqrdmlah,3, (RNDQMQ, oRNDQMQ, RNDQ_RNSC_RR), neon_qrdmlah), + mnUF(vqdmulh, _vqdmulh, 3, (RNDQMQ, oRNDQMQ, RNDQMQ_RNSC_RR), neon_qdmulh), + mnUF(vqrdmulh, _vqrdmulh,3, (RNDQMQ, oRNDQMQ, RNDQMQ_RNSC_RR), neon_qdmulh), #undef ARM_VARIANT #define ARM_VARIANT & arm_ext_v8_3 diff --git a/gas/testsuite/gas/arm/mve-vqdmulh-bad.d b/gas/testsuite/gas/arm/mve-vqdmulh-bad.d new file mode 100644 index 0000000000000000000000000000000000000000..cdf63ba933e9d0d65ff8287b060f7fc358dc5f4b --- /dev/null +++ b/gas/testsuite/gas/arm/mve-vqdmulh-bad.d @@ -0,0 +1,5 @@ +#name: bad MVE VQDMULH and VQRDMULH instructions +#as: -march=armv8.1-m.main+mve.fp +#error_output: mve-vqdmulh-bad.l + +.*: +file format .*arm.* diff --git a/gas/testsuite/gas/arm/mve-vqdmulh-bad.l b/gas/testsuite/gas/arm/mve-vqdmulh-bad.l new file mode 100644 index 0000000000000000000000000000000000000000..01e824efbf0a759c20ea32502f2856fdb6d2d4eb --- /dev/null +++ b/gas/testsuite/gas/arm/mve-vqdmulh-bad.l @@ -0,0 +1,57 @@ +[^:]*: Assembler messages: +[^:]*:10: Error: bad type in SIMD instruction -- `vqdmulh.s64 q0,q1,q2' +[^:]*:11: Error: bad type in SIMD instruction -- `vqdmulh.u8 q0,q1,q2' +[^:]*:12: Error: bad type in SIMD instruction -- `vqrdmulh.s64 q0,q1,q2' +[^:]*:13: Error: bad type in SIMD instruction -- `vqrdmulh.u8 q0,q1,q2' +[^:]*:14: Error: bad type in SIMD instruction -- `vqdmulh.s64 q0,q1,r2' +[^:]*:15: Error: bad type in SIMD instruction -- `vqdmulh.u8 q0,q1,r2' +[^:]*:16: Error: bad type in SIMD instruction -- `vqrdmulh.s64 q0,q1,r2' +[^:]*:17: Error: bad type in SIMD instruction -- `vqrdmulh.u8 q0,q1,r2' +[^:]*:18: Warning: instruction is UNPREDICTABLE with SP operand +[^:]*:19: Warning: instruction is UNPREDICTABLE with PC operand +[^:]*:20: Warning: instruction is UNPREDICTABLE with SP operand +[^:]*:21: Warning: instruction is UNPREDICTABLE with PC operand +[^:]*:22: Warning: instruction is UNPREDICTABLE in an IT block +[^:]*:22: Warning: instruction is UNPREDICTABLE in an IT block +[^:]*:22: Warning: instruction is UNPREDICTABLE in an IT block +[^:]*:22: Warning: instruction is UNPREDICTABLE in an IT block +[^:]*:22: Warning: instruction is UNPREDICTABLE in an IT block +[^:]*:22: Warning: instruction is UNPREDICTABLE in an IT block +[^:]*:23: Warning: instruction is UNPREDICTABLE in an IT block +[^:]*:23: Warning: instruction is UNPREDICTABLE in an IT block +[^:]*:23: Warning: instruction is UNPREDICTABLE in an IT block +[^:]*:23: Warning: instruction is UNPREDICTABLE in an IT block +[^:]*:23: Warning: instruction is UNPREDICTABLE in an IT block +[^:]*:23: Warning: instruction is UNPREDICTABLE in an IT block +[^:]*:24: Warning: instruction is UNPREDICTABLE in an IT block +[^:]*:24: Warning: instruction is UNPREDICTABLE in an IT block +[^:]*:24: Warning: instruction is UNPREDICTABLE in an IT block +[^:]*:24: Warning: instruction is UNPREDICTABLE in an IT block +[^:]*:24: Warning: instruction is UNPREDICTABLE in an IT block +[^:]*:24: Warning: instruction is UNPREDICTABLE in an IT block +[^:]*:25: Warning: instruction is UNPREDICTABLE in an IT block +[^:]*:25: Warning: instruction is UNPREDICTABLE in an IT block +[^:]*:25: Warning: instruction is UNPREDICTABLE in an IT block +[^:]*:25: Warning: instruction is UNPREDICTABLE in an IT block +[^:]*:25: Warning: instruction is UNPREDICTABLE in an IT block +[^:]*:25: Warning: instruction is UNPREDICTABLE in an IT block +[^:]*:27: Error: syntax error -- `vqdmulheq.s8 q0,q1,q2' +[^:]*:28: Error: syntax error -- `vqdmulheq.s8 q0,q1,q2' +[^:]*:30: Error: syntax error -- `vqdmulheq.s8 q0,q1,q2' +[^:]*:31: Error: vector predicated instruction should be in VPT/VPST block -- `vqdmulht.s8 q0,q1,q2' +[^:]*:33: Error: instruction missing MVE vector predication code -- `vqdmulh.s8 q0,q1,q2' +[^:]*:35: Error: syntax error -- `vqrdmulheq.s8 q0,q1,q2' +[^:]*:36: Error: syntax error -- `vqrdmulheq.s8 q0,q1,q2' +[^:]*:38: Error: syntax error -- `vqrdmulheq.s8 q0,q1,q2' +[^:]*:39: Error: vector predicated instruction should be in VPT/VPST block -- `vqrdmulht.s8 q0,q1,q2' +[^:]*:41: Error: instruction missing MVE vector predication code -- `vqrdmulh.s8 q0,q1,q2' +[^:]*:43: Error: syntax error -- `vqdmulheq.s8 q0,q1,r2' +[^:]*:44: Error: syntax error -- `vqdmulheq.s8 q0,q1,r2' +[^:]*:46: Error: syntax error -- `vqdmulheq.s8 q0,q1,r2' +[^:]*:47: Error: vector predicated instruction should be in VPT/VPST block -- `vqdmulht.s8 q0,q1,r2' +[^:]*:49: Error: instruction missing MVE vector predication code -- `vqdmulh.s8 q0,q1,r2' +[^:]*:51: Error: syntax error -- `vqrdmulheq.s8 q0,q1,r2' +[^:]*:52: Error: syntax error -- `vqrdmulheq.s8 q0,q1,r2' +[^:]*:54: Error: syntax error -- `vqrdmulheq.s8 q0,q1,r2' +[^:]*:55: Error: vector predicated instruction should be in VPT/VPST block -- `vqrdmulht.s8 q0,q1,r2' +[^:]*:57: Error: instruction missing MVE vector predication code -- `vqrdmulh.s8 q0,q1,r2' diff --git a/gas/testsuite/gas/arm/mve-vqdmulh-bad.s b/gas/testsuite/gas/arm/mve-vqdmulh-bad.s new file mode 100644 index 0000000000000000000000000000000000000000..db44de6d4d25288b18067a7fdeac1f904d5b4ade --- /dev/null +++ b/gas/testsuite/gas/arm/mve-vqdmulh-bad.s @@ -0,0 +1,57 @@ +.macro cond op, lastreg +.irp cond, eq, ne, gt, ge, lt, le +it \cond +\op\().s16 q0, q1, \lastreg +.endr +.endm + +.syntax unified +.thumb +vqdmulh.s64 q0, q1, q2 +vqdmulh.u8 q0, q1, q2 +vqrdmulh.s64 q0, q1, q2 +vqrdmulh.u8 q0, q1, q2 +vqdmulh.s64 q0, q1, r2 +vqdmulh.u8 q0, q1, r2 +vqrdmulh.s64 q0, q1, r2 +vqrdmulh.u8 q0, q1, r2 +vqdmulh.s8 q0, q1, sp +vqdmulh.s8 q0, q1, pc +vqrdmulh.s8 q0, q1, sp +vqrdmulh.s8 q0, q1, pc +cond vqdmulh, q2 +cond vqrdmulh, q2 +cond vqdmulh, r2 +cond vqrdmulh, r2 +it eq +vqdmulheq.s8 q0, q1, q2 +vqdmulheq.s8 q0, q1, q2 +vpst +vqdmulheq.s8 q0, q1, q2 +vqdmulht.s8 q0, q1, q2 +vpst +vqdmulh.s8 q0, q1, q2 +it eq +vqrdmulheq.s8 q0, q1, q2 +vqrdmulheq.s8 q0, q1, q2 +vpst +vqrdmulheq.s8 q0, q1, q2 +vqrdmulht.s8 q0, q1, q2 +vpst +vqrdmulh.s8 q0, q1, q2 +it eq +vqdmulheq.s8 q0, q1, r2 +vqdmulheq.s8 q0, q1, r2 +vpst +vqdmulheq.s8 q0, q1, r2 +vqdmulht.s8 q0, q1, r2 +vpst +vqdmulh.s8 q0, q1, r2 +it eq +vqrdmulheq.s8 q0, q1, r2 +vqrdmulheq.s8 q0, q1, r2 +vpst +vqrdmulheq.s8 q0, q1, r2 +vqrdmulht.s8 q0, q1, r2 +vpst +vqrdmulh.s8 q0, q1, r2