diff --git a/gas/config/tc-arm.c b/gas/config/tc-arm.c index e739c5b94ab1924f65a262e15342a748e2a4dc40..af6550eeb95db17f444acc7e6bfdb73e3dc14f3c 100644 --- a/gas/config/tc-arm.c +++ b/gas/config/tc-arm.c @@ -14157,6 +14157,10 @@ do_t_loloop (void) #define M_MNEM_vaddlva 0xee890f20 #define M_MNEM_vaddv 0xeef10f00 #define M_MNEM_vaddva 0xeef10f20 +#define M_MNEM_vddup 0xee011f6e +#define M_MNEM_vdwdup 0xee011f60 +#define M_MNEM_vidup 0xee010f6e +#define M_MNEM_viwdup 0xee010f60 /* Neon instruction encoder helpers. */ @@ -14321,8 +14325,10 @@ NEON_ENC_TAB - a table used to drive neon_select_shape. */ #define NEON_SHAPE_DEF \ + X(4, (Q, R, R, I), QUAD), \ X(4, (R, R, S, S), QUAD), \ X(4, (S, S, R, R), QUAD), \ + X(3, (Q, R, I), QUAD), \ X(3, (I, Q, Q), QUAD), \ X(3, (I, Q, R), QUAD), \ X(3, (R, Q, Q), QUAD), \ @@ -15608,6 +15614,49 @@ do_mve_vfmas (void) inst.is_neon = 1; } +static void +do_mve_viddup (void) +{ + if (inst.cond > COND_ALWAYS) + inst.pred_insn_type = INSIDE_VPT_INSN; + else + inst.pred_insn_type = MVE_OUTSIDE_PRED_INSN; + + unsigned imm = inst.relocs[0].exp.X_add_number; + constraint (imm != 1 && imm != 2 && imm != 4 && imm != 8, + _("immediate must be either 1, 2, 4 or 8")); + + enum neon_shape rs; + struct neon_type_el et; + unsigned Rm; + if (inst.instruction == M_MNEM_vddup || inst.instruction == M_MNEM_vidup) + { + rs = neon_select_shape (NS_QRI, NS_NULL); + et = neon_check_type (2, rs, N_KEY | N_U8 | N_U16 | N_U32, N_EQK); + Rm = 7; + } + else + { + constraint ((inst.operands[2].reg % 2) != 1, BAD_EVEN); + if (inst.operands[2].reg == REG_SP) + as_tsktsk (MVE_BAD_SP); + else if (inst.operands[2].reg == REG_PC) + first_error (BAD_PC); + + rs = neon_select_shape (NS_QRRI, NS_NULL); + et = neon_check_type (3, rs, N_KEY | N_U8 | N_U16 | N_U32, N_EQK, N_EQK); + Rm = inst.operands[2].reg >> 1; + } + inst.instruction |= HI1 (inst.operands[0].reg) << 22; + inst.instruction |= neon_logbits (et.size) << 20; + inst.instruction |= inst.operands[1].reg << 16; + inst.instruction |= LOW4 (inst.operands[0].reg) << 12; + inst.instruction |= (imm > 2) << 7; + inst.instruction |= Rm << 1; + inst.instruction |= (imm == 2 || imm == 8); + inst.is_neon = 1; +} + static void do_mve_vcmul (void) { @@ -18407,6 +18456,8 @@ do_neon_dup (void) { if (inst.operands[1].isscalar) { + constraint (!ARM_CPU_HAS_FEATURE (cpu_variant, fpu_neon_ext_v1), + BAD_FPU); enum neon_shape rs = neon_select_shape (NS_DS, NS_QS, NS_NULL); struct neon_type_el et = neon_check_type (2, rs, N_EQK, N_8 | N_16 | N_32 | N_KEY); @@ -18434,6 +18485,23 @@ do_neon_dup (void) enum neon_shape rs = neon_select_shape (NS_DR, NS_QR, NS_NULL); struct neon_type_el et = neon_check_type (2, rs, N_8 | N_16 | N_32 | N_KEY, N_EQK); + if (rs == NS_QR) + { + if (check_simd_pred_availability (0, NEON_CHECK_ARCH)) + return; + } + else + constraint (!ARM_CPU_HAS_FEATURE (cpu_variant, fpu_neon_ext_v1), + BAD_FPU); + + if (ARM_CPU_HAS_FEATURE (cpu_variant, mve_ext)) + { + if (inst.operands[1].reg == REG_SP) + as_tsktsk (MVE_BAD_SP); + else if (inst.operands[1].reg == REG_PC) + as_tsktsk (MVE_BAD_PC); + } + /* Duplicate ARM register to lanes of vector. */ NEON_ENCODE (ARMREG, inst); switch (et.size) @@ -23659,7 +23727,6 @@ static const struct asm_opcode insns[] = NUF(vrev16, 1b00100, 2, (RNDQ, RNDQ), neon_rev), NUF(vrev16q, 1b00100, 2, (RNQ, RNQ), neon_rev), /* Vector replicate. Sizes 8 16 32. */ - nCE(vdup, _vdup, 2, (RNDQ, RR_RNSC), neon_dup), nCE(vdupq, _vdup, 2, (RNQ, RR_RNSC), neon_dup), /* VMOVL. Types S8 S16 S32 U8 U16 U32. */ NUF(vmovl, 0800a10, 2, (RNQ, RND), neon_movl), @@ -24221,6 +24288,10 @@ static const struct asm_opcode insns[] = mCEF(vaddlva, _vaddlva, 3, (RRe, RRo, RMQ), mve_vaddlv), mCEF(vaddv, _vaddv, 2, (RRe, RMQ), mve_vaddv), mCEF(vaddva, _vaddva, 2, (RRe, RMQ), mve_vaddv), + mCEF(vddup, _vddup, 3, (RMQ, RRe, EXPi), mve_viddup), + mCEF(vdwdup, _vdwdup, 4, (RMQ, RRe, RR, EXPi), mve_viddup), + mCEF(vidup, _vidup, 3, (RMQ, RRe, EXPi), mve_viddup), + mCEF(viwdup, _viwdup, 4, (RMQ, RRe, RR, EXPi), mve_viddup), #undef THUMB_VARIANT #define THUMB_VARIANT & mve_fp_ext @@ -24283,6 +24354,7 @@ static const struct asm_opcode insns[] = mnUF(veor, _veor, 3, (RNDQMQ, oRNDQMQ, RNDQMQ), neon_logic), MNUF(vcls, 1b00400, 2, (RNDQMQ, RNDQMQ), neon_cls), MNUF(vclz, 1b00480, 2, (RNDQMQ, RNDQMQ), neon_clz), + mnCE(vdup, _vdup, 2, (RNDQMQ, RR_RNSC), neon_dup), #undef ARM_VARIANT #define ARM_VARIANT & arm_ext_v8_3 diff --git a/gas/testsuite/gas/arm/mve-vddup-bad.d b/gas/testsuite/gas/arm/mve-vddup-bad.d new file mode 100644 index 0000000000000000000000000000000000000000..a6522dc25423352b027d58a0b0f495f7f0705245 --- /dev/null +++ b/gas/testsuite/gas/arm/mve-vddup-bad.d @@ -0,0 +1,6 @@ +#name: bad MVE VDDUP and VDWDUP instructions +#as: -march=armv8.1-m.main+mve +#error_output: mve-vddup-bad.l + +.*: +file format .*arm.* + diff --git a/gas/testsuite/gas/arm/mve-vddup-bad.l b/gas/testsuite/gas/arm/mve-vddup-bad.l new file mode 100644 index 0000000000000000000000000000000000000000..92ff9657446829f1f703d99be34384d21307e3a9 --- /dev/null +++ b/gas/testsuite/gas/arm/mve-vddup-bad.l @@ -0,0 +1,33 @@ +[^:]*: Assembler messages: +[^:]*:16: Error: bad type in SIMD instruction -- `vddup.s16 q0,r0,#1' +[^:]*:17: Error: bad type in SIMD instruction -- `vddup.u64 q0,r0,#1' +[^:]*:18: Error: immediate must be either 1, 2, 4 or 8 -- `vddup.u32 q0,r0,#3' +[^:]*:19: Error: immediate must be either 1, 2, 4 or 8 -- `vddup.u32 q0,r0,#0' +[^:]*:20: Error: bad type in SIMD instruction -- `vdwdup.s16 q0,r0,r1,#1' +[^:]*:21: Error: bad type in SIMD instruction -- `vdwdup.u64 q0,r0,r1,#1' +[^:]*:22: Error: immediate must be either 1, 2, 4 or 8 -- `vdwdup.u32 q0,r0,r1,#3' +[^:]*:23: Error: immediate must be either 1, 2, 4 or 8 -- `vdwdup.u32 q0,r0,r1,#0' +[^:]*:24: Warning: instruction is UNPREDICTABLE with SP operand +[^:]*:25: Error: r15 not allowed here -- `vdwdup.u32 q0,r0,pc,#1' +[^:]*:26: Warning: instruction is UNPREDICTABLE in an IT block +[^:]*:26: Warning: instruction is UNPREDICTABLE in an IT block +[^:]*:26: Warning: instruction is UNPREDICTABLE in an IT block +[^:]*:26: Warning: instruction is UNPREDICTABLE in an IT block +[^:]*:26: Warning: instruction is UNPREDICTABLE in an IT block +[^:]*:26: Warning: instruction is UNPREDICTABLE in an IT block +[^:]*:27: Warning: instruction is UNPREDICTABLE in an IT block +[^:]*:27: Warning: instruction is UNPREDICTABLE in an IT block +[^:]*:27: Warning: instruction is UNPREDICTABLE in an IT block +[^:]*:27: Warning: instruction is UNPREDICTABLE in an IT block +[^:]*:27: Warning: instruction is UNPREDICTABLE in an IT block +[^:]*:27: Warning: instruction is UNPREDICTABLE in an IT block +[^:]*:29: Error: syntax error -- `vddupeq.u32 q0,r0,#1' +[^:]*:30: Error: syntax error -- `vddupeq.u32 q0,r0,#1' +[^:]*:32: Error: syntax error -- `vddupeq.u32 q0,r0,#1' +[^:]*:33: Error: vector predicated instruction should be in VPT/VPST block -- `vddupt.u32 q0,r0,#1' +[^:]*:35: Error: instruction missing MVE vector predication code -- `vddup.u32 q0,r0,#1' +[^:]*:37: Error: syntax error -- `vdwdupeq.u32 q0,r0,r1,#1' +[^:]*:38: Error: syntax error -- `vdwdupeq.u32 q0,r0,r1,#1' +[^:]*:40: Error: syntax error -- `vdwdupeq.u32 q0,r0,r1,#1' +[^:]*:41: Error: vector predicated instruction should be in VPT/VPST block -- `vdwdupt.u32 q0,r0,r1,#1' +[^:]*:43: Error: instruction missing MVE vector predication code -- `vdwdup.u32 q0,r0,r1,#1' diff --git a/gas/testsuite/gas/arm/mve-vddup-bad.s b/gas/testsuite/gas/arm/mve-vddup-bad.s new file mode 100644 index 0000000000000000000000000000000000000000..9951e9d11843d3302823e7805bbbe20abc79d3eb --- /dev/null +++ b/gas/testsuite/gas/arm/mve-vddup-bad.s @@ -0,0 +1,43 @@ +.macro cond1 +.irp cond, eq, ne, gt, ge, lt, le +it \cond +vddup.u32 q0, r2, #1 +.endr +.endm + +.macro cond2 +.irp cond, eq, ne, gt, ge, lt, le +it \cond +vdwdup.u32 q0, r2, r1, #1 +.endr +.endm +.syntax unified +.thumb +vddup.s16 q0, r0, #1 +vddup.u64 q0, r0, #1 +vddup.u32 q0, r0, #3 +vddup.u32 q0, r0, #0 +vdwdup.s16 q0, r0, r1, #1 +vdwdup.u64 q0, r0, r1, #1 +vdwdup.u32 q0, r0, r1, #3 +vdwdup.u32 q0, r0, r1, #0 +vdwdup.u32 q0, r0, sp, #1 +vdwdup.u32 q0, r0, pc, #1 +cond1 +cond2 +it eq +vddupeq.u32 q0, r0, #1 +vddupeq.u32 q0, r0, #1 +vpst +vddupeq.u32 q0, r0, #1 +vddupt.u32 q0, r0, #1 +vpst +vddup.u32 q0, r0, #1 +it eq +vdwdupeq.u32 q0, r0, r1, #1 +vdwdupeq.u32 q0, r0, r1, #1 +vpst +vdwdupeq.u32 q0, r0, r1, #1 +vdwdupt.u32 q0, r0, r1, #1 +vpst +vdwdup.u32 q0, r0, r1, #1 diff --git a/gas/testsuite/gas/arm/mve-vdup-bad.d b/gas/testsuite/gas/arm/mve-vdup-bad.d new file mode 100644 index 0000000000000000000000000000000000000000..2ad95976135bb46535720195d17b0024cf391abc --- /dev/null +++ b/gas/testsuite/gas/arm/mve-vdup-bad.d @@ -0,0 +1,5 @@ +#name: bad MVE VDUP instructions +#as: -march=armv8.1-m.main+mve +#error_output: mve-vdup-bad.l + +.*: +file format .*arm.* diff --git a/gas/testsuite/gas/arm/mve-vdup-bad.l b/gas/testsuite/gas/arm/mve-vdup-bad.l new file mode 100644 index 0000000000000000000000000000000000000000..08808393569f7e7a839680b001e38e9f1ca66886 --- /dev/null +++ b/gas/testsuite/gas/arm/mve-vdup-bad.l @@ -0,0 +1,16 @@ +[^:]*: Assembler messages: +[^:]*:11: Error: bad type in SIMD instruction -- `vdup.64 q0,r1' +[^:]*:12: Error: selected FPU does not support instruction -- `vdup.32 q0,d0\[1\]' +[^:]*:13: Warning: instruction is UNPREDICTABLE with SP operand +[^:]*:14: Warning: instruction is UNPREDICTABLE with PC operand +[^:]*:15: Warning: instruction is UNPREDICTABLE in an IT block +[^:]*:15: Warning: instruction is UNPREDICTABLE in an IT block +[^:]*:15: Warning: instruction is UNPREDICTABLE in an IT block +[^:]*:15: Warning: instruction is UNPREDICTABLE in an IT block +[^:]*:15: Warning: instruction is UNPREDICTABLE in an IT block +[^:]*:15: Warning: instruction is UNPREDICTABLE in an IT block +[^:]*:17: Error: syntax error -- `vdupeq.32 q0,r2' +[^:]*:18: Error: syntax error -- `vdupeq.32 q0,r2' +[^:]*:20: Error: syntax error -- `vdupeq.32 q0,r2' +[^:]*:21: Error: incorrect condition in VPT/VPST block -- `vdupt.32 q0,r2' +[^:]*:23: Error: instruction missing MVE vector predication code -- `vdup.32 q0,r2' diff --git a/gas/testsuite/gas/arm/mve-vdup-bad.s b/gas/testsuite/gas/arm/mve-vdup-bad.s new file mode 100644 index 0000000000000000000000000000000000000000..c6539d860575184fcf6745d165995edf80270f6e --- /dev/null +++ b/gas/testsuite/gas/arm/mve-vdup-bad.s @@ -0,0 +1,23 @@ +.macro cond +.irp cond, eq, ne, gt, ge, lt, le +it \cond +vdup.32 q0, r2 +.endr +.endm + +.syntax unified +.thumb +vdup.f16 q0, r1 +vdup.64 q0, r1 +vdup.32 q0, d0[1] +vdup.32 q0, sp +vdup.32 q0, pc +cond +it eq +vdupeq.32 q0, r2 +vdupeq.32 q0, r2 +vpste +vdupeq.32 q0, r2 +vdupt.32 q0, r2 +vpst +vdup.32 q0, r2 diff --git a/gas/testsuite/gas/arm/mve-vidup-bad.d b/gas/testsuite/gas/arm/mve-vidup-bad.d new file mode 100644 index 0000000000000000000000000000000000000000..6a9a0384048c05c0f962130078755c6dd983e962 --- /dev/null +++ b/gas/testsuite/gas/arm/mve-vidup-bad.d @@ -0,0 +1,5 @@ +#name: bad MVE VIDUP and VIWDUP instructions +#as: -march=armv8.1-m.main+mve +#error_output: mve-vidup-bad.l + +.*: +file format .*arm.* diff --git a/gas/testsuite/gas/arm/mve-vidup-bad.l b/gas/testsuite/gas/arm/mve-vidup-bad.l new file mode 100644 index 0000000000000000000000000000000000000000..5fb742559f5bd1573aa03ea767a56112a5acb9f0 --- /dev/null +++ b/gas/testsuite/gas/arm/mve-vidup-bad.l @@ -0,0 +1,34 @@ +[^:]*: Assembler messages: +[^:]*:16: Error: bad type in SIMD instruction -- `vidup.s16 q0,r0,#1' +[^:]*:17: Error: bad type in SIMD instruction -- `vidup.u64 q0,r0,#1' +[^:]*:18: Error: immediate must be either 1, 2, 4 or 8 -- `vidup.u32 q0,r0,#3' +[^:]*:19: Error: immediate must be either 1, 2, 4 or 8 -- `vidup.u32 q0,r0,#0' +[^:]*:20: Error: bad type in SIMD instruction -- `viwdup.s16 q0,r0,r1,#1' +[^:]*:21: Error: bad type in SIMD instruction -- `viwdup.u64 q0,r0,r1,#1' +[^:]*:22: Error: immediate must be either 1, 2, 4 or 8 -- `viwdup.u32 q0,r0,r1,#3' +[^:]*:23: Error: immediate must be either 1, 2, 4 or 8 -- `viwdup.u32 q0,r0,r1,#0' +[^:]*:24: Warning: instruction is UNPREDICTABLE with SP operand +[^:]*:25: Error: r15 not allowed here -- `viwdup.u32 q0,r0,pc,#1' +[^:]*:26: Warning: instruction is UNPREDICTABLE in an IT block +[^:]*:26: Warning: instruction is UNPREDICTABLE in an IT block +[^:]*:26: Warning: instruction is UNPREDICTABLE in an IT block +[^:]*:26: Warning: instruction is UNPREDICTABLE in an IT block +[^:]*:26: Warning: instruction is UNPREDICTABLE in an IT block +[^:]*:26: Warning: instruction is UNPREDICTABLE in an IT block +[^:]*:27: Warning: instruction is UNPREDICTABLE in an IT block +[^:]*:27: Warning: instruction is UNPREDICTABLE in an IT block +[^:]*:27: Warning: instruction is UNPREDICTABLE in an IT block +[^:]*:27: Warning: instruction is UNPREDICTABLE in an IT block +[^:]*:27: Warning: instruction is UNPREDICTABLE in an IT block +[^:]*:27: Warning: instruction is UNPREDICTABLE in an IT block +[^:]*:29: Error: syntax error -- `vidupeq.u32 q0,r0,#1' +[^:]*:30: Error: syntax error -- `vidupeq.u32 q0,r0,#1' +[^:]*:32: Error: syntax error -- `vidupeq.u32 q0,r0,#1' +[^:]*:33: Error: vector predicated instruction should be in VPT/VPST block -- `vidupt.u32 q0,r0,#1' +[^:]*:35: Error: instruction missing MVE vector predication code -- `vidup.u32 q0,r0,#1' +[^:]*:37: Error: syntax error -- `viwdupeq.u32 q0,r0,r1,#1' +[^:]*:38: Error: syntax error -- `viwdupeq.u32 q0,r0,r1,#1' +[^:]*:40: Error: syntax error -- `viwdupeq.u32 q0,r0,r1,#1' +[^:]*:41: Error: vector predicated instruction should be in VPT/VPST block -- `viwdupt.u32 q0,r0,r1,#1' +[^:]*:43: Error: instruction missing MVE vector predication code -- `viwdup.u32 q0,r0,r1,#1' + diff --git a/gas/testsuite/gas/arm/mve-vidup-bad.s b/gas/testsuite/gas/arm/mve-vidup-bad.s new file mode 100644 index 0000000000000000000000000000000000000000..3d3a4488d9c780123754a3243241720a513f4d3c --- /dev/null +++ b/gas/testsuite/gas/arm/mve-vidup-bad.s @@ -0,0 +1,43 @@ +.macro cond1 +.irp cond, eq, ne, gt, ge, lt, le +it \cond +vidup.u32 q0, r2, #1 +.endr +.endm + +.macro cond2 +.irp cond, eq, ne, gt, ge, lt, le +it \cond +viwdup.u32 q0, r2, r1, #1 +.endr +.endm +.syntax unified +.thumb +vidup.s16 q0, r0, #1 +vidup.u64 q0, r0, #1 +vidup.u32 q0, r0, #3 +vidup.u32 q0, r0, #0 +viwdup.s16 q0, r0, r1, #1 +viwdup.u64 q0, r0, r1, #1 +viwdup.u32 q0, r0, r1, #3 +viwdup.u32 q0, r0, r1, #0 +viwdup.u32 q0, r0, sp, #1 +viwdup.u32 q0, r0, pc, #1 +cond1 +cond2 +it eq +vidupeq.u32 q0, r0, #1 +vidupeq.u32 q0, r0, #1 +vpst +vidupeq.u32 q0, r0, #1 +vidupt.u32 q0, r0, #1 +vpst +vidup.u32 q0, r0, #1 +it eq +viwdupeq.u32 q0, r0, r1, #1 +viwdupeq.u32 q0, r0, r1, #1 +vpst +viwdupeq.u32 q0, r0, r1, #1 +viwdupt.u32 q0, r0, r1, #1 +vpst +viwdup.u32 q0, r0, r1, #1