From 1b8833198c014f2d7f7a67097061f3b990707084 Mon Sep 17 00:00:00 2001 From: Andre Vieira Date: Wed, 15 May 2019 17:35:43 +0100 Subject: [PATCH] [PATCH 10/57][Arm][GAS] Add support for MVE instructions: vcmp and vpt gas/ChangeLog: 2019-05-16 Andre Vieira * config/tc-arm.c (MVE_BAD_QREG): New error message. (enum operand_parse_code): Define new operand. (parse_operands): Handle new operand. (do_mve_vpt): Change for VPT blocks. (NEON_SHAPE_DEF): New shape. (neon_logbits): Moved. (LOW4): Moved (HI1): Moved (mve_get_vcmp_vpt_cond): New function to translate vpt conditions. (do_mve_vcmp): New encoding function. (do_vfp_nsyn_cmp): Changed to support MVE variants. (insns): Change to support MVE variants of vcmp and add vpt. * testsuite/gas/arm/mve-vcmp-bad-1.d: New test. * testsuite/gas/arm/mve-vcmp-bad-1.l: New test. * testsuite/gas/arm/mve-vcmp-bad-1.s: New test. * testsuite/gas/arm/mve-vcmp-bad-2.d: New test. * testsuite/gas/arm/mve-vcmp-bad-2.l: New test. * testsuite/gas/arm/mve-vcmp-bad-2.s: New test. * testsuite/gas/arm/mve-vpt-bad-1.d: New test. * testsuite/gas/arm/mve-vpt-bad-1.l: New test. * testsuite/gas/arm/mve-vpt-bad-1.s: New test. * testsuite/gas/arm/mve-vpt-bad-2.d: New test. * testsuite/gas/arm/mve-vpt-bad-2.l: New test. * testsuite/gas/arm/mve-vpt-bad-2.s: New test. --- gas/ChangeLog | 27 +++ gas/config/tc-arm.c | 319 +++++++++++++++++++++++-- gas/testsuite/gas/arm/mve-vcmp-bad-1.d | 5 + gas/testsuite/gas/arm/mve-vcmp-bad-1.l | 31 +++ gas/testsuite/gas/arm/mve-vcmp-bad-1.s | 47 ++++ gas/testsuite/gas/arm/mve-vcmp-bad-2.d | 5 + gas/testsuite/gas/arm/mve-vcmp-bad-2.l | 25 ++ gas/testsuite/gas/arm/mve-vcmp-bad-2.s | 41 ++++ gas/testsuite/gas/arm/mve-vpt-bad-1.d | 5 + gas/testsuite/gas/arm/mve-vpt-bad-1.l | 23 ++ gas/testsuite/gas/arm/mve-vpt-bad-1.s | 30 +++ gas/testsuite/gas/arm/mve-vpt-bad-2.d | 5 + gas/testsuite/gas/arm/mve-vpt-bad-2.l | 21 ++ gas/testsuite/gas/arm/mve-vpt-bad-2.s | 27 +++ 14 files changed, 585 insertions(+), 26 deletions(-) create mode 100644 gas/testsuite/gas/arm/mve-vcmp-bad-1.d create mode 100644 gas/testsuite/gas/arm/mve-vcmp-bad-1.l create mode 100644 gas/testsuite/gas/arm/mve-vcmp-bad-1.s create mode 100644 gas/testsuite/gas/arm/mve-vcmp-bad-2.d create mode 100644 gas/testsuite/gas/arm/mve-vcmp-bad-2.l create mode 100644 gas/testsuite/gas/arm/mve-vcmp-bad-2.s create mode 100644 gas/testsuite/gas/arm/mve-vpt-bad-1.d create mode 100644 gas/testsuite/gas/arm/mve-vpt-bad-1.l create mode 100644 gas/testsuite/gas/arm/mve-vpt-bad-1.s create mode 100644 gas/testsuite/gas/arm/mve-vpt-bad-2.d create mode 100644 gas/testsuite/gas/arm/mve-vpt-bad-2.l create mode 100644 gas/testsuite/gas/arm/mve-vpt-bad-2.s diff --git a/gas/ChangeLog b/gas/ChangeLog index 6d4342a1cfa..a14aa2527da 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,30 @@ +2019-05-16 Andre Vieira + + * config/tc-arm.c (MVE_BAD_QREG): New error message. + (enum operand_parse_code): Define new operand. + (parse_operands): Handle new operand. + (do_mve_vpt): Change for VPT blocks. + (NEON_SHAPE_DEF): New shape. + (neon_logbits): Moved. + (LOW4): Moved + (HI1): Moved + (mve_get_vcmp_vpt_cond): New function to translate vpt conditions. + (do_mve_vcmp): New encoding function. + (do_vfp_nsyn_cmp): Changed to support MVE variants. + (insns): Change to support MVE variants of vcmp and add vpt. + * testsuite/gas/arm/mve-vcmp-bad-1.d: New test. + * testsuite/gas/arm/mve-vcmp-bad-1.l: New test. + * testsuite/gas/arm/mve-vcmp-bad-1.s: New test. + * testsuite/gas/arm/mve-vcmp-bad-2.d: New test. + * testsuite/gas/arm/mve-vcmp-bad-2.l: New test. + * testsuite/gas/arm/mve-vcmp-bad-2.s: New test. + * testsuite/gas/arm/mve-vpt-bad-1.d: New test. + * testsuite/gas/arm/mve-vpt-bad-1.l: New test. + * testsuite/gas/arm/mve-vpt-bad-1.s: New test. + * testsuite/gas/arm/mve-vpt-bad-2.d: New test. + * testsuite/gas/arm/mve-vpt-bad-2.l: New test. + * testsuite/gas/arm/mve-vpt-bad-2.s: New test. + 2019-05-16 Andre Vieira * config/tc-arm.c (struct arm_it): Expand isscalar field to be able to diff --git a/gas/config/tc-arm.c b/gas/config/tc-arm.c index b1033450781..b806916cc59 100644 --- a/gas/config/tc-arm.c +++ b/gas/config/tc-arm.c @@ -522,6 +522,7 @@ struct arm_it unsigned isvec : 1; /* Is a single, double or quad VFP/Neon reg. */ unsigned isquad : 1; /* Operand is SIMD quad register. */ unsigned issingle : 1; /* Operand is VFP single-precision register. */ + unsigned iszr : 1; /* Operand is ZR register. */ unsigned hasreloc : 1; /* Operand has relocation suffix. */ unsigned writeback : 1; /* Operand has trailing ! */ unsigned preind : 1; /* Preindexed address. */ @@ -646,6 +647,7 @@ enum arm_reg_type REG_TYPE_MMXWCG, REG_TYPE_XSCALE, REG_TYPE_RNB, + REG_TYPE_ZR }; /* Structure for a hash table entry for a register. @@ -898,6 +900,7 @@ struct asm_opcode #define BAD_MVE_SRCDEST _("Warning: 32-bit element size and same destination "\ "and source operands makes instruction UNPREDICTABLE") #define BAD_EL_TYPE _("bad element type for instruction") +#define MVE_BAD_QREG _("MVE vector register Q[0..7] expected") static struct hash_control * arm_ops_hsh; static struct hash_control * arm_cond_hsh; @@ -6894,6 +6897,7 @@ enum operand_parse_code OP_RNQ, /* Neon quad precision register */ OP_RNQMQ, /* Neon quad or MVE vector register. */ OP_RVSD, /* VFP single or double precision register */ + OP_RVSD_COND, /* VFP single, double precision register or condition code. */ OP_RVSDMQ, /* VFP single, double precision or MVE vector register. */ OP_RNSD, /* Neon single or double precision register */ OP_RNDQ, /* Neon double or quad precision register */ @@ -6917,6 +6921,7 @@ enum operand_parse_code OP_RNSDQMQR, /* Neon single, double or quad register, MVE vector register or GPR (no SP/SP) */ OP_RMQ, /* MVE vector register. */ + OP_RMQRZ, /* MVE vector or ARM register including ZR. */ /* New operands for Armv8.1-M Mainline. */ OP_LR, /* ARM LR register */ @@ -6938,6 +6943,8 @@ enum operand_parse_code OP_RNDQ_I0, /* Neon D or Q reg, or immediate zero. */ OP_RVSD_I0, /* VFP S or D reg, or immediate zero. */ OP_RSVD_FI0, /* VFP S or D reg, or floating point immediate zero. */ + OP_RSVDMQ_FI0, /* VFP S, D, MVE vector register or floating point immediate + zero. */ OP_RR_RNSC, /* ARM reg or Neon scalar. */ OP_RNSD_RNSC, /* Neon S or D reg, or Neon scalar. */ OP_RNSDQ_RNSC, /* Vector S, D or Q reg, or Neon scalar. */ @@ -7028,6 +7035,8 @@ enum operand_parse_code OP_oROR, /* ROR 0/8/16/24 */ OP_oBARRIER_I15, /* Option argument for a barrier instruction. */ + OP_oRMQRZ, /* optional MVE vector or ARM register including ZR. */ + /* Some pre-defined mixed (ARM/THUMB) operands. */ OP_RR_npcsp = MIX_ARM_THUMB_OPERANDS (OP_RR, OP_RRnpcsp), OP_RRnpc_npcsp = MIX_ARM_THUMB_OPERANDS (OP_RRnpc, OP_RRnpcsp), @@ -7077,6 +7086,7 @@ parse_operands (char *str, const unsigned int *pattern, bfd_boolean thumb) inst.operands[i].isvec = (rtype == REG_TYPE_VFS \ || rtype == REG_TYPE_VFD \ || rtype == REG_TYPE_NQ); \ + inst.operands[i].iszr = (rtype == REG_TYPE_ZR); \ } \ while (0) @@ -7095,6 +7105,7 @@ parse_operands (char *str, const unsigned int *pattern, bfd_boolean thumb) inst.operands[i].isvec = (rtype == REG_TYPE_VFS \ || rtype == REG_TYPE_VFD \ || rtype == REG_TYPE_NQ); \ + inst.operands[i].iszr = (rtype == REG_TYPE_ZR); \ } \ while (0) @@ -7240,6 +7251,9 @@ parse_operands (char *str, const unsigned int *pattern, bfd_boolean thumb) break; try_rvsd: case OP_RVSD: po_reg_or_fail (REG_TYPE_VFSD); break; + case OP_RVSD_COND: + po_reg_or_goto (REG_TYPE_VFSD, try_cond); + break; case OP_oRNSDQ: case OP_RNSDQ: po_reg_or_fail (REG_TYPE_NSDQ); break; case OP_RNSDQMQR: @@ -7274,6 +7288,10 @@ parse_operands (char *str, const unsigned int *pattern, bfd_boolean thumb) po_reg_or_goto (REG_TYPE_VFSD, try_imm0); break; + case OP_RSVDMQ_FI0: + po_reg_or_goto (REG_TYPE_MQ, try_rsvd_fi0); + break; + try_rsvd_fi0: case OP_RSVD_FI0: { po_reg_or_goto (REG_TYPE_VFSD, try_ifimm0); @@ -7548,6 +7566,7 @@ parse_operands (char *str, const unsigned int *pattern, bfd_boolean thumb) case OP_CPSF: val = parse_cps_flags (&str); break; case OP_ENDI: val = parse_endian_specifier (&str); break; case OP_oROR: val = parse_ror (&str); break; + try_cond: case OP_COND: val = parse_cond (&str); break; case OP_oBARRIER_I15: po_barrier_or_imm (str); break; @@ -7721,6 +7740,17 @@ parse_operands (char *str, const unsigned int *pattern, bfd_boolean thumb) po_misc_or_fail (parse_shift (&str, i, SHIFT_LSL_OR_ASR_IMMEDIATE)); break; + case OP_RMQRZ: + case OP_oRMQRZ: + po_reg_or_goto (REG_TYPE_MQ, try_rr_zr); + break; + try_rr_zr: + po_reg_or_goto (REG_TYPE_RN, ZR); + break; + ZR: + po_reg_or_fail (REG_TYPE_ZR); + break; + default: as_fatal (_("unhandled operand code %d"), op_parse_code); } @@ -7764,10 +7794,12 @@ parse_operands (char *str, const unsigned int *pattern, bfd_boolean thumb) inst.error = BAD_PC; break; + case OP_RVSD_COND: case OP_VLDR: if (inst.operands[i].isreg) break; /* fall through. */ + case OP_CPSF: case OP_ENDI: case OP_oROR: @@ -7796,6 +7828,12 @@ parse_operands (char *str, const unsigned int *pattern, bfd_boolean thumb) inst.error = _("operand must be LR register"); break; + case OP_RMQRZ: + case OP_oRMQRZ: + if (!inst.operands[i].iszr && inst.operands[i].reg == REG_PC) + inst.error = BAD_PC; + break; + case OP_RRe: if (inst.operands[i].isreg && (inst.operands[i].reg & 0x00000001) != 0) @@ -12006,18 +12044,6 @@ do_t_it (void) inst.instruction |= cond << 4; } -static void -do_mve_vpt (void) -{ - /* We are dealing with a vector predicated block. */ - set_pred_insn_type (VPT_INSN); - now_pred.cc = 0; - now_pred.mask = ((inst.instruction & 0x00400000) >> 19) - | ((inst.instruction & 0xe000) >> 13); - now_pred.warn_deprecated = FALSE; - now_pred.type = VECTOR_PRED; -} - /* Helper function used for both push/pop and ldm/stm. */ static void encode_thumb2_multi (bfd_boolean do_io, int base, unsigned mask, @@ -14276,6 +14302,8 @@ NEON_ENC_TAB #define NEON_SHAPE_DEF \ X(4, (R, R, S, S), QUAD), \ X(4, (S, S, R, R), QUAD), \ + X(3, (I, Q, Q), QUAD), \ + X(3, (I, Q, R), QUAD), \ X(3, (R, Q, Q), QUAD), \ X(3, (D, D, D), DOUBLE), \ X(3, (Q, Q, Q), QUAD), \ @@ -15314,10 +15342,239 @@ do_vfp_nsyn_nmul (void) } +/* Turn a size (8, 16, 32, 64) into the respective bit number minus 3 + (0, 1, 2, 3). */ + +static unsigned +neon_logbits (unsigned x) +{ + return ffs (x) - 4; +} + +#define LOW4(R) ((R) & 0xf) +#define HI1(R) (((R) >> 4) & 1) + +static unsigned +mve_get_vcmp_vpt_cond (struct neon_type_el et) +{ + switch (et.type) + { + default: + first_error (BAD_EL_TYPE); + return 0; + case NT_float: + switch (inst.operands[0].imm) + { + default: + first_error (_("invalid condition")); + return 0; + case 0x0: + /* eq. */ + return 0; + case 0x1: + /* ne. */ + return 1; + case 0xa: + /* ge/ */ + return 4; + case 0xb: + /* lt. */ + return 5; + case 0xc: + /* gt. */ + return 6; + case 0xd: + /* le. */ + return 7; + } + case NT_integer: + /* only accept eq and ne. */ + if (inst.operands[0].imm > 1) + { + first_error (_("invalid condition")); + return 0; + } + return inst.operands[0].imm; + case NT_unsigned: + if (inst.operands[0].imm == 0x2) + return 2; + else if (inst.operands[0].imm == 0x8) + return 3; + else + { + first_error (_("invalid condition")); + return 0; + } + case NT_signed: + switch (inst.operands[0].imm) + { + default: + first_error (_("invalid condition")); + return 0; + case 0xa: + /* ge. */ + return 4; + case 0xb: + /* lt. */ + return 5; + case 0xc: + /* gt. */ + return 6; + case 0xd: + /* le. */ + return 7; + } + } + /* Should be unreachable. */ + abort (); +} + +static void +do_mve_vpt (void) +{ + /* We are dealing with a vector predicated block. */ + if (inst.operands[0].present) + { + enum neon_shape rs = neon_select_shape (NS_IQQ, NS_IQR, NS_NULL); + struct neon_type_el et + = neon_check_type (3, rs, N_EQK, N_KEY | N_F_MVE | N_I_MVE | N_SU_32, + N_EQK); + + unsigned fcond = mve_get_vcmp_vpt_cond (et); + + constraint (inst.operands[1].reg > 14, MVE_BAD_QREG); + + if (et.type == NT_invtype) + return; + + if (et.type == NT_float) + { + constraint (!ARM_CPU_HAS_FEATURE (cpu_variant, mve_fp_ext), + BAD_FPU); + constraint (et.size != 16 && et.size != 32, BAD_EL_TYPE); + inst.instruction |= (et.size == 16) << 28; + inst.instruction |= 0x3 << 20; + } + else + { + constraint (et.size != 8 && et.size != 16 && et.size != 32, + BAD_EL_TYPE); + inst.instruction |= 1 << 28; + inst.instruction |= neon_logbits (et.size) << 20; + } + + if (inst.operands[2].isquad) + { + inst.instruction |= HI1 (inst.operands[2].reg) << 5; + inst.instruction |= LOW4 (inst.operands[2].reg); + inst.instruction |= (fcond & 0x2) >> 1; + } + else + { + if (inst.operands[2].reg == REG_SP) + as_tsktsk (MVE_BAD_SP); + inst.instruction |= 1 << 6; + inst.instruction |= (fcond & 0x2) << 4; + inst.instruction |= inst.operands[2].reg; + } + inst.instruction |= LOW4 (inst.operands[1].reg) << 16; + inst.instruction |= (fcond & 0x4) << 10; + inst.instruction |= (fcond & 0x1) << 7; + + } + set_pred_insn_type (VPT_INSN); + now_pred.cc = 0; + now_pred.mask = ((inst.instruction & 0x00400000) >> 19) + | ((inst.instruction & 0xe000) >> 13); + now_pred.warn_deprecated = FALSE; + now_pred.type = VECTOR_PRED; + inst.is_neon = 1; +} + +static void +do_mve_vcmp (void) +{ + constraint (!ARM_CPU_HAS_FEATURE (cpu_variant, mve_ext), BAD_FPU); + if (!inst.operands[1].isreg || !inst.operands[1].isquad) + first_error (_(reg_expected_msgs[REG_TYPE_MQ])); + if (!inst.operands[2].present) + first_error (_("MVE vector or ARM register expected")); + constraint (inst.operands[1].reg > 14, MVE_BAD_QREG); + + /* Deal with 'else' conditional MVE's vcmp, it will be parsed as vcmpe. */ + if ((inst.instruction & 0xffffffff) == N_MNEM_vcmpe + && inst.operands[1].isquad) + { + inst.instruction = N_MNEM_vcmp; + inst.cond = 0x10; + } + + if (inst.cond > COND_ALWAYS) + inst.pred_insn_type = INSIDE_VPT_INSN; + else + inst.pred_insn_type = MVE_OUTSIDE_PRED_INSN; + + enum neon_shape rs = neon_select_shape (NS_IQQ, NS_IQR, NS_NULL); + struct neon_type_el et + = neon_check_type (3, rs, N_EQK, N_KEY | N_F_MVE | N_I_MVE | N_SU_32, + N_EQK); + + constraint (rs == NS_IQR && inst.operands[2].reg == REG_PC + && !inst.operands[2].iszr, BAD_PC); + + unsigned fcond = mve_get_vcmp_vpt_cond (et); + + inst.instruction = 0xee010f00; + inst.instruction |= LOW4 (inst.operands[1].reg) << 16; + inst.instruction |= (fcond & 0x4) << 10; + inst.instruction |= (fcond & 0x1) << 7; + if (et.type == NT_float) + { + constraint (!ARM_CPU_HAS_FEATURE (cpu_variant, mve_fp_ext), + BAD_FPU); + inst.instruction |= (et.size == 16) << 28; + inst.instruction |= 0x3 << 20; + } + else + { + inst.instruction |= 1 << 28; + inst.instruction |= neon_logbits (et.size) << 20; + } + if (inst.operands[2].isquad) + { + inst.instruction |= HI1 (inst.operands[2].reg) << 5; + inst.instruction |= (fcond & 0x2) >> 1; + inst.instruction |= LOW4 (inst.operands[2].reg); + } + else + { + if (inst.operands[2].reg == REG_SP) + as_tsktsk (MVE_BAD_SP); + inst.instruction |= 1 << 6; + inst.instruction |= (fcond & 0x2) << 4; + inst.instruction |= inst.operands[2].reg; + } + + inst.is_neon = 1; + return; +} + static void do_vfp_nsyn_cmp (void) { enum neon_shape rs; + if (!inst.operands[0].isreg) + { + do_mve_vcmp (); + return; + } + else + { + constraint (inst.operands[2].present, BAD_SYNTAX); + constraint (!ARM_CPU_HAS_FEATURE (cpu_variant, fpu_vfp_ext_v1xd), + BAD_FPU); + } + if (inst.operands[1].isreg) { rs = neon_select_shape (NS_HH, NS_FF, NS_DD, NS_NULL); @@ -15435,18 +15692,6 @@ neon_dp_fixup (struct arm_it* insn) insn->instruction = i; } -/* Turn a size (8, 16, 32, 64) into the respective bit number minus 3 - (0, 1, 2, 3). */ - -static unsigned -neon_logbits (unsigned x) -{ - return ffs (x) - 4; -} - -#define LOW4(R) ((R) & 0xf) -#define HI1(R) (((R) >> 4) & 1) - static void mve_encode_qqr (int size, int fp) { @@ -21096,6 +21341,10 @@ static const struct reg_entry reg_names[] = REGDEF(WR, 7,RN), REGDEF(SB, 9,RN), REGDEF(SL,10,RN), REGDEF(FP,11,RN), REGDEF(IP,12,RN), REGDEF(SP,13,RN), REGDEF(LR,14,RN), REGDEF(PC,15,RN), + /* Defining the new Zero register from ARMv8.1-M. */ + REGDEF(zr,15,ZR), + REGDEF(ZR,15,ZR), + /* Coprocessor numbers. */ REGSET(p, CP), REGSET(P, CP), @@ -22911,8 +23160,6 @@ static const struct asm_opcode insns[] = nCE(vnmul, _vnmul, 3, (RVSD, RVSD, RVSD), vfp_nsyn_nmul), nCE(vnmla, _vnmla, 3, (RVSD, RVSD, RVSD), vfp_nsyn_nmul), nCE(vnmls, _vnmls, 3, (RVSD, RVSD, RVSD), vfp_nsyn_nmul), - nCE(vcmp, _vcmp, 2, (RVSD, RSVD_FI0), vfp_nsyn_cmp), - nCE(vcmpe, _vcmpe, 2, (RVSD, RSVD_FI0), vfp_nsyn_cmp), NCE(vpush, 0, 1, (VRSDLST), vfp_nsyn_push), NCE(vpop, 0, 1, (VRSDLST), vfp_nsyn_pop), NCE(vcvtz, 0, 2, (RVSD, RVSD), vfp_nsyn_cvtz), @@ -23628,6 +23875,23 @@ static const struct asm_opcode insns[] = #undef THUMB_VARIANT #define THUMB_VARIANT & mve_ext + + ToC("vpt", ee410f00, 3, (COND, RMQ, RMQRZ), mve_vpt), + ToC("vptt", ee018f00, 3, (COND, RMQ, RMQRZ), mve_vpt), + ToC("vpte", ee418f00, 3, (COND, RMQ, RMQRZ), mve_vpt), + ToC("vpttt", ee014f00, 3, (COND, RMQ, RMQRZ), mve_vpt), + ToC("vptte", ee01cf00, 3, (COND, RMQ, RMQRZ), mve_vpt), + ToC("vptet", ee41cf00, 3, (COND, RMQ, RMQRZ), mve_vpt), + ToC("vptee", ee414f00, 3, (COND, RMQ, RMQRZ), mve_vpt), + ToC("vptttt", ee012f00, 3, (COND, RMQ, RMQRZ), mve_vpt), + ToC("vpttte", ee016f00, 3, (COND, RMQ, RMQRZ), mve_vpt), + ToC("vpttet", ee01ef00, 3, (COND, RMQ, RMQRZ), mve_vpt), + ToC("vpttee", ee01af00, 3, (COND, RMQ, RMQRZ), mve_vpt), + ToC("vptett", ee41af00, 3, (COND, RMQ, RMQRZ), mve_vpt), + ToC("vptete", ee41ef00, 3, (COND, RMQ, RMQRZ), mve_vpt), + ToC("vpteet", ee416f00, 3, (COND, RMQ, RMQRZ), mve_vpt), + ToC("vpteee", ee412f00, 3, (COND, RMQ, RMQRZ), mve_vpt), + ToC("vpst", fe710f4d, 0, (), mve_vpt), ToC("vpstt", fe318f4d, 0, (), mve_vpt), ToC("vpste", fe718f4d, 0, (), mve_vpt), @@ -23707,6 +23971,9 @@ static const struct asm_opcode insns[] = mCEF(vmovlt, _vmovlt, 1, (VMOV), mve_movl), mCEF(vmovlb, _vmovlb, 1, (VMOV), mve_movl), + mnCE(vcmp, _vcmp, 3, (RVSD_COND, RSVDMQ_FI0, oRMQRZ), vfp_nsyn_cmp), + mnCE(vcmpe, _vcmpe, 3, (RVSD_COND, RSVDMQ_FI0, oRMQRZ), vfp_nsyn_cmp), + #undef ARM_VARIANT #define ARM_VARIANT & fpu_vfp_ext_v2 diff --git a/gas/testsuite/gas/arm/mve-vcmp-bad-1.d b/gas/testsuite/gas/arm/mve-vcmp-bad-1.d new file mode 100644 index 00000000000..dd2706f084f --- /dev/null +++ b/gas/testsuite/gas/arm/mve-vcmp-bad-1.d @@ -0,0 +1,5 @@ +#name: bad MVE VCMP instructions +#as: -march=armv8.1-m.main+mve +#error_output: mve-vcmp-bad-1.l + +.*: +file format .*arm.* diff --git a/gas/testsuite/gas/arm/mve-vcmp-bad-1.l b/gas/testsuite/gas/arm/mve-vcmp-bad-1.l new file mode 100644 index 00000000000..65db78ab61e --- /dev/null +++ b/gas/testsuite/gas/arm/mve-vcmp-bad-1.l @@ -0,0 +1,31 @@ +[^:]*: Assembler messages: +[^:]*: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: Error: selected FPU does not support instruction -- `vcmp.f32 eq,q0,q1' +[^:]*:25: Error: selected FPU does not support instruction -- `vcmp.f32 eq,q0,r1' +[^:]*:26: Error: bad type in SIMD instruction -- `vcmp.i64 eq,q0,q1' +[^:]*:27: Error: invalid condition -- `vcmp.s32 eq,q0,q1' +[^:]*:28: Error: invalid condition -- `vcmp.s16 cs,q0,q1' +[^:]*:29: Error: invalid condition -- `vcmp.u8 le,q0,q1' +[^:]*:30: Error: condition required -- `vcmp.s16 q0,q1' +[^:]*:31: Warning: instruction is UNPREDICTABLE with SP operand +[^:]*:33: Error: syntax error -- `vcmpeq.i32 eq,q0,q1' +[^:]*:34: Error: syntax error -- `vcmpeq.i32 eq,q0,q1' +[^:]*:36: Error: syntax error -- `vcmpeq.i32 eq,q0,q1' +[^:]*:37: Error: vector predicated instruction should be in VPT/VPST block -- `vcmpt.i32 eq,q0,q1' +[^:]*:39: Error: instruction missing MVE vector predication code -- `vcmp.i32 eq,q0,q1' +[^:]*:41: Error: syntax error -- `vcmpeq.i32 eq,q0,r1' +[^:]*:42: Error: syntax error -- `vcmpeq.i32 eq,q0,r1' +[^:]*:44: Error: syntax error -- `vcmpeq.i32 eq,q0,r1' +[^:]*:45: Error: vector predicated instruction should be in VPT/VPST block -- `vcmpt.i32 eq,q0,r1' +[^:]*:47: Error: instruction missing MVE vector predication code -- `vcmp.i32 eq,q0,r1' diff --git a/gas/testsuite/gas/arm/mve-vcmp-bad-1.s b/gas/testsuite/gas/arm/mve-vcmp-bad-1.s new file mode 100644 index 00000000000..116e23a8097 --- /dev/null +++ b/gas/testsuite/gas/arm/mve-vcmp-bad-1.s @@ -0,0 +1,47 @@ +.macro cond1 +.irp cond, eq, ne, gt, ge, lt, le +.irp size, . +it \cond +vcmp.s32 gt, q0, q1 +.endr +.endr +.endm + +.macro cond2 +.irp cond, eq, ne, gt, ge, lt, le +.irp size, . +it \cond +vcmp.i16 eq, q0, r1 +.endr +.endr +.endm + +.syntax unified +.thumb + +cond1 +cond2 +vcmp.f32 eq, q0, q1 +vcmp.f32 eq, q0, r1 +vcmp.i64 eq, q0, q1 +vcmp.s32 eq, q0, q1 +vcmp.s16 cs, q0, q1 +vcmp.u8 le, q0, q1 +vcmp.s16 q0, q1 +vcmp.i32 eq, q0, sp +it eq +vcmpeq.i32 eq, q0, q1 +vcmpeq.i32 eq, q0, q1 +vpst +vcmpeq.i32 eq, q0, q1 +vcmpt.i32 eq, q0, q1 +vpst +vcmp.i32 eq, q0, q1 +it eq +vcmpeq.i32 eq, q0, r1 +vcmpeq.i32 eq, q0, r1 +vpst +vcmpeq.i32 eq, q0, r1 +vcmpt.i32 eq, q0, r1 +vpst +vcmp.i32 eq, q0, r1 diff --git a/gas/testsuite/gas/arm/mve-vcmp-bad-2.d b/gas/testsuite/gas/arm/mve-vcmp-bad-2.d new file mode 100644 index 00000000000..7d262517cc6 --- /dev/null +++ b/gas/testsuite/gas/arm/mve-vcmp-bad-2.d @@ -0,0 +1,5 @@ +#name: bad MVE FP VCMP instructions +#as: -march=armv8.1-m.main+mve.fp +#error_output: mve-vcmp-bad-2.l + +.*: +file format .*arm.* diff --git a/gas/testsuite/gas/arm/mve-vcmp-bad-2.l b/gas/testsuite/gas/arm/mve-vcmp-bad-2.l new file mode 100644 index 00000000000..1305f069732 --- /dev/null +++ b/gas/testsuite/gas/arm/mve-vcmp-bad-2.l @@ -0,0 +1,25 @@ +[^:]*: Assembler messages: +[^:]*: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: Error: bad type in SIMD instruction -- `vcmp.f64 eq,q0,q1' +[^:]*:25: Warning: instruction is UNPREDICTABLE with SP operand +[^:]*:27: Error: syntax error -- `vcmpeq.f32 eq,q0,q1' +[^:]*:28: Error: syntax error -- `vcmpeq.f32 eq,q0,q1' +[^:]*:30: Error: syntax error -- `vcmpeq.f32 eq,q0,q1' +[^:]*:31: Error: vector predicated instruction should be in VPT/VPST block -- `vcmpt.f32 eq,q0,q1' +[^:]*:33: Error: instruction missing MVE vector predication code -- `vcmp.f32 eq,q0,q1' +[^:]*:35: Error: syntax error -- `vcmpeq.f32 eq,q0,r1' +[^:]*:36: Error: syntax error -- `vcmpeq.f32 eq,q0,r1' +[^:]*:38: Error: syntax error -- `vcmpeq.f32 eq,q0,r1' +[^:]*:39: Error: vector predicated instruction should be in VPT/VPST block -- `vcmpt.f32 eq,q0,r1' +[^:]*:41: Error: instruction missing MVE vector predication code -- `vcmp.f32 eq,q0,r1' diff --git a/gas/testsuite/gas/arm/mve-vcmp-bad-2.s b/gas/testsuite/gas/arm/mve-vcmp-bad-2.s new file mode 100644 index 00000000000..c54b0e94043 --- /dev/null +++ b/gas/testsuite/gas/arm/mve-vcmp-bad-2.s @@ -0,0 +1,41 @@ +.macro cond1 +.irp cond, eq, ne, gt, ge, lt, le +.irp size, . +it \cond +vcmp.f32 gt, q0, q1 +.endr +.endr +.endm + +.macro cond2 +.irp cond, eq, ne, gt, ge, lt, le +.irp size, . +it \cond +vcmp.f16 eq, q0, r1 +.endr +.endr +.endm + +.syntax unified +.thumb + +cond1 +cond2 +vcmp.f64 eq, q0, q1 +vcmp.f32 eq, q0, sp +it eq +vcmpeq.f32 eq, q0, q1 +vcmpeq.f32 eq, q0, q1 +vpst +vcmpeq.f32 eq, q0, q1 +vcmpt.f32 eq, q0, q1 +vpst +vcmp.f32 eq, q0, q1 +it eq +vcmpeq.f32 eq, q0, r1 +vcmpeq.f32 eq, q0, r1 +vpst +vcmpeq.f32 eq, q0, r1 +vcmpt.f32 eq, q0, r1 +vpst +vcmp.f32 eq, q0, r1 diff --git a/gas/testsuite/gas/arm/mve-vpt-bad-1.d b/gas/testsuite/gas/arm/mve-vpt-bad-1.d new file mode 100644 index 00000000000..8a4fe5371e8 --- /dev/null +++ b/gas/testsuite/gas/arm/mve-vpt-bad-1.d @@ -0,0 +1,5 @@ +#name: bad MVE VPT instructions +#as: -march=armv8.1-m.main+mve +#error_output: mve-vpt-bad-1.l + +.*: +file format .*arm.* diff --git a/gas/testsuite/gas/arm/mve-vpt-bad-1.l b/gas/testsuite/gas/arm/mve-vpt-bad-1.l new file mode 100644 index 00000000000..99036d29120 --- /dev/null +++ b/gas/testsuite/gas/arm/mve-vpt-bad-1.l @@ -0,0 +1,23 @@ +[^:]*: Assembler messages: +[^:]*:13: Warning: instruction is UNPREDICTABLE in an IT block +[^:]*:13: Warning: instruction is UNPREDICTABLE in an IT block +[^:]*:13: Warning: instruction is UNPREDICTABLE in an IT block +[^:]*:13: Warning: instruction is UNPREDICTABLE in an IT block +[^:]*:13: Warning: instruction is UNPREDICTABLE in an IT block +[^:]*:13: Warning: instruction is UNPREDICTABLE in an IT block +[^:]*:14: Warning: instruction is UNPREDICTABLE in an IT block +[^:]*:14: Warning: instruction is UNPREDICTABLE in an IT block +[^:]*:14: Warning: instruction is UNPREDICTABLE in an IT block +[^:]*:14: Warning: instruction is UNPREDICTABLE in an IT block +[^:]*:14: Warning: instruction is UNPREDICTABLE in an IT block +[^:]*:14: Warning: instruction is UNPREDICTABLE in an IT block +[^:]*:15: Warning: instruction is UNPREDICTABLE with SP operand +[^:]*:17: Error: bad type in SIMD instruction -- `vpt.i64 eq,q0,q1' +[^:]*:18: Error: selected FPU does not support instruction -- `vpt.f16 eq,q0,q1' +[^:]*:19: Error: selected FPU does not support instruction -- `vpt.f32 eq,q0,q1' +[^:]*:20: Error: bad type in SIMD instruction -- `vpt.f64 eq,q0,q1' +[^:]*:22: Error: syntax error -- `vpteq.i8 eq,q0,q1' +[^:]*:23: Error: syntax error -- `vpteq.i8 eq,q0,q1' +[^:]*:26: Warning: instruction is UNPREDICTABLE in a VPT block +[^:]*:27: Warning: instruction is UNPREDICTABLE in a VPT block +[^:]*:30: Warning: .* finished with an open VPT/VPST block. diff --git a/gas/testsuite/gas/arm/mve-vpt-bad-1.s b/gas/testsuite/gas/arm/mve-vpt-bad-1.s new file mode 100644 index 00000000000..66d9980998f --- /dev/null +++ b/gas/testsuite/gas/arm/mve-vpt-bad-1.s @@ -0,0 +1,30 @@ +.macro cond1, lastreg +.irp cond, eq, ne, gt, ge, lt, le +.irp size, . +it \cond +vpt.i8 eq, q0, \lastreg +vaddt.i32 q0, q1, q2 +.endr +.endr +.endm + +.syntax unified +.thumb +cond1 q1 +cond1 r1 +vpt.i8 eq, q0, sp +vaddt.i32 q0, q1, q2 +vpt.i64 eq, q0, q1 +vpt.f16 eq, q0, q1 +vpt.f32 eq, q0, q1 +vpt.f64 eq, q0, q1 +it eq +vpteq.i8 eq, q0, q1 +vpteq.i8 eq, q0, q1 +vaddt.i32 q0, q0, q1 +vpst +vptt.i8 eq, q0, q1 +vptt.i8 eq, q0, q1 +vaddt.i32 q0, q0, q1 +vaddt.i32 q0, q0, q1 +vpt.i8 eq, q0, q1 diff --git a/gas/testsuite/gas/arm/mve-vpt-bad-2.d b/gas/testsuite/gas/arm/mve-vpt-bad-2.d new file mode 100644 index 00000000000..27a5171aa2e --- /dev/null +++ b/gas/testsuite/gas/arm/mve-vpt-bad-2.d @@ -0,0 +1,5 @@ +#name: bad MVE FP VPT instructions +#as: -march=armv8.1-m.main+mve.fp +#error_output: mve-vpt-bad-2.l + +.*: +file format .*arm.* diff --git a/gas/testsuite/gas/arm/mve-vpt-bad-2.l b/gas/testsuite/gas/arm/mve-vpt-bad-2.l new file mode 100644 index 00000000000..9f11fe890fa --- /dev/null +++ b/gas/testsuite/gas/arm/mve-vpt-bad-2.l @@ -0,0 +1,21 @@ +[^:]*: Assembler messages: +[^:]*:13: Warning: instruction is UNPREDICTABLE in an IT block +[^:]*:13: Warning: instruction is UNPREDICTABLE in an IT block +[^:]*:13: Warning: instruction is UNPREDICTABLE in an IT block +[^:]*:13: Warning: instruction is UNPREDICTABLE in an IT block +[^:]*:13: Warning: instruction is UNPREDICTABLE in an IT block +[^:]*:13: Warning: instruction is UNPREDICTABLE in an IT block +[^:]*:14: Warning: instruction is UNPREDICTABLE in an IT block +[^:]*:14: Warning: instruction is UNPREDICTABLE in an IT block +[^:]*:14: Warning: instruction is UNPREDICTABLE in an IT block +[^:]*:14: Warning: instruction is UNPREDICTABLE in an IT block +[^:]*:14: Warning: instruction is UNPREDICTABLE in an IT block +[^:]*:14: Warning: instruction is UNPREDICTABLE in an IT block +[^:]*:15: Warning: instruction is UNPREDICTABLE with SP operand +[^:]*:17: Error: bad type in SIMD instruction -- `vpt.f64 eq,q0,q1' +[^:]*:19: Error: syntax error -- `vpteq.f32 eq,q0,q1' +[^:]*:20: Error: syntax error -- `vpteq.f32 eq,q0,q1' +[^:]*:23: Warning: instruction is UNPREDICTABLE in a VPT block +[^:]*:24: Warning: instruction is UNPREDICTABLE in a VPT block +[^:]*:27: Warning: .* finished with an open VPT/VPST block. + diff --git a/gas/testsuite/gas/arm/mve-vpt-bad-2.s b/gas/testsuite/gas/arm/mve-vpt-bad-2.s new file mode 100644 index 00000000000..83e9fd5b387 --- /dev/null +++ b/gas/testsuite/gas/arm/mve-vpt-bad-2.s @@ -0,0 +1,27 @@ +.macro cond1, lastreg +.irp cond, eq, ne, gt, ge, lt, le +.irp size, . +it \cond +vpt.f16 eq, q0, \lastreg +vaddt.i32 q0, q1, q2 +.endr +.endr +.endm + +.syntax unified +.thumb +cond1 q1 +cond1 r1 +vpt.f16 eq, q0, sp +vaddt.i32 q0, q1, q2 +vpt.f64 eq, q0, q1 +it eq +vpteq.f32 eq, q0, q1 +vpteq.f32 eq, q0, q1 +vaddt.i32 q0, q0, q1 +vpst +vptt.f16 eq, q0, q1 +vptt.f16 eq, q0, q1 +vaddt.i32 q0, q0, q1 +vaddt.i32 q0, q0, q1 +vpt.f32 eq, q0, q1 -- 2.30.2