From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 124546 invoked by alias); 1 May 2019 16:59:38 -0000 Mailing-List: contact binutils-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: binutils-owner@sourceware.org Received: (qmail 124538 invoked by uid 89); 1 May 2019 16:59:38 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-24.5 required=5.0 tests=AWL,BAYES_00,GIT_PATCH_0,GIT_PATCH_1,GIT_PATCH_2,GIT_PATCH_3,KAM_LOTSOFHASH autolearn=ham version=3.3.1 spammy= X-HELO: foss.arm.com Received: from foss.arm.com (HELO foss.arm.com) (217.140.101.70) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Wed, 01 May 2019 16:59:36 +0000 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.72.51.249]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 2A8EB80D for ; Wed, 1 May 2019 09:59:35 -0700 (PDT) Received: from [10.2.207.62] (e107157-lin.cambridge.arm.com [10.2.207.62]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id A108F3F719 for ; Wed, 1 May 2019 09:59:34 -0700 (PDT) Subject: [PATCH 5/57][Arm][GAS] Add support for MVE instructions: vmull{b,t} To: binutils@sourceware.org References: <19569550-4d2e-0bb3-592a-d91050d490f6@arm.com> From: "Andre Vieira (lists)" Message-ID: <3545f6f6-b1a0-1779-e57d-0b3aec92d750@arm.com> Date: Wed, 01 May 2019 16:59:00 -0000 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Thunderbird/60.6.1 MIME-Version: 1.0 In-Reply-To: <19569550-4d2e-0bb3-592a-d91050d490f6@arm.com> Content-Type: multipart/mixed; boundary="------------D24FE48D03863C6D0D6F1B4E" X-IsSubscribed: yes X-SW-Source: 2019-05/txt/msg00034.txt.bz2 This is a multi-part message in MIME format. --------------D24FE48D03863C6D0D6F1B4E Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: 7bit Content-length: 1292 Hi, This patch implements support for the MVE VMULL[BT] instruction. This instruction presents a new challenge to the implementation of GAS as depending on architecture the same mnemonic can be split in different ways because of condition codes. In a NEON context 'vmullt' should be parsed as a 'vmul' instruction with 'lt' condition code, whereas in a MVE context this same mnemonic should be parsed as a 'vmullt' instruction. The way we implement this is to catch any 'vmullt' in 'do_mve_vmull' and if we detect we are dealing with a NEON context, we set the correct condition code, encoding, and call the neon encoding function. gas/ChangeLog: 2019-05-01 Andre Vieira * config/tc-arm.c (BAD_MVE_AUTO): New error message. (BAD_MVE_SRCDEST): Likewise. (mark_feature_used): Diagnose MVE only instructions when in auto-detection mode or -march=all. (enum operand_parse_code): Define new operand. (parse_operands): Handle new operand. (M_MNEM_vmullt, M_MNEM_vmullb): New encodings. (mve_encode_qqq): New encoding helper function. (do_mve_vmull): New encoding function. (insns): * testsuite/gas/arm/mve-vmullbt-bad.d: New test. * testsuite/gas/arm/mve-vmullbt-bad.l: New test. * testsuite/gas/arm/mve-vmullbt-bad.s: New test. --------------D24FE48D03863C6D0D6F1B4E Content-Type: text/x-patch; name="5.patch" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="5.patch" Content-length: 9756 diff --git a/gas/config/tc-arm.c b/gas/config/tc-arm.c index 1984cf23b7dc2b32dae1958bfac54eebb55584a0..4db934c8594f6660baff7e21c925d4b819e4ccf5 100644 --- a/gas/config/tc-arm.c +++ b/gas/config/tc-arm.c @@ -890,6 +890,11 @@ struct asm_opcode #define MVE_BAD_SP _("Warning: instruction is UNPREDICTABLE with SP" \ " operand") #define BAD_SIMD_TYPE _("bad type in SIMD instruction") +#define BAD_MVE_AUTO \ + _("GAS auto-detection mode and -march=all is deprecated for MVE, please" \ + " use a valid -march or -mcpu option.") +#define BAD_MVE_SRCDEST _("Warning: 32-bit element size and same destination "\ + "and source operands makes instruction UNPREDICTABLE") static struct hash_control * arm_ops_hsh; static struct hash_control * arm_cond_hsh; @@ -1541,6 +1546,15 @@ record_feature_use (const arm_feature_set *feature) static bfd_boolean mark_feature_used (const arm_feature_set *feature) { + + /* Do not support the use of MVE only instructions when in auto-detection or + -march=all. */ + if (((feature == &mve_ext) || (feature == &mve_fp_ext)) + && ARM_CPU_IS_ANY (cpu_variant)) + { + first_error (BAD_MVE_AUTO); + return FALSE; + } /* Ensure the option is valid on the current architecture. */ if (!ARM_CPU_HAS_FEATURE (cpu_variant, *feature)) return FALSE; @@ -6743,6 +6757,8 @@ enum operand_parse_code 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. */ + OP_RNSDQ_RNSC_MQ, /* Vector S, D or Q reg, Neon scalar or MVE vector register. + */ OP_RNDQ_RNSC, /* Neon D or Q reg, or Neon scalar. */ OP_RND_RNSC, /* Neon D reg, or Neon scalar. */ OP_VMOV, /* Neon VMOV operands. */ @@ -7094,6 +7110,10 @@ parse_operands (char *str, const unsigned int *pattern, bfd_boolean thumb) } break; + case OP_RNSDQ_RNSC_MQ: + po_reg_or_goto (REG_TYPE_MQ, try_rnsdq_rnsc); + break; + try_rnsdq_rnsc: case OP_RNSDQ_RNSC: { po_scalar_or_goto (8, try_nsdq); @@ -13836,6 +13856,8 @@ do_t_loloop (void) #define M_MNEM_vmlsdava 0xeef00e21 #define M_MNEM_vmlsdavx 0xeef01e01 #define M_MNEM_vmlsdavax 0xeef01e21 +#define M_MNEM_vmullt 0xee011e00 +#define M_MNEM_vmullb 0xee010e00 /* Neon instruction encoder helpers. */ @@ -15223,6 +15245,23 @@ mve_encode_rqq (unsigned bit28, unsigned size) inst.is_neon = 1; } +static void +mve_encode_qqq (int ubit, int size) +{ + + inst.instruction |= (ubit != 0) << 28; + inst.instruction |= HI1 (inst.operands[0].reg) << 22; + inst.instruction |= neon_logbits (size) << 20; + inst.instruction |= LOW4 (inst.operands[1].reg) << 16; + inst.instruction |= LOW4 (inst.operands[0].reg) << 12; + inst.instruction |= HI1 (inst.operands[1].reg) << 7; + inst.instruction |= HI1 (inst.operands[2].reg) << 5; + inst.instruction |= LOW4 (inst.operands[2].reg); + + inst.is_neon = 1; +} + + /* Encode insns with bit pattern: |28/24|23|22 |21 20|19 16|15 12|11 8|7|6|5|4|3 0| @@ -15941,6 +15980,61 @@ do_neon_qdmulh (void) } } +static void +do_mve_vmull (void) +{ + + enum neon_shape rs = neon_select_shape (NS_HHH, NS_FFF, NS_DDD, NS_DDS, + NS_QQS, NS_QQQ, NS_QQR, NS_NULL); + if (!ARM_CPU_HAS_FEATURE (cpu_variant, mve_ext) + && inst.cond == COND_ALWAYS + && ((unsigned)inst.instruction) == M_MNEM_vmullt) + { + if (rs == NS_QQQ) + { + + struct neon_type_el et = neon_check_type (3, rs, N_EQK , N_EQK, + N_SUF_32 | N_F64 | N_P8 + | N_P16 | N_I_MVE | N_KEY); + if (((et.type == NT_poly) && et.size == 8 + && ARM_CPU_IS_ANY (cpu_variant)) + || (et.type == NT_integer) || (et.type == NT_float)) + goto neon_vmul; + } + else + goto neon_vmul; + } + + constraint (rs != NS_QQQ, BAD_FPU); + struct neon_type_el et = neon_check_type (3, rs, N_EQK , N_EQK, + N_SU_32 | N_P8 | N_P16 | N_KEY); + + /* We are dealing with MVE's vmullt. */ + if (et.size == 32 + && (inst.operands[0].reg == inst.operands[1].reg + || inst.operands[0].reg == inst.operands[2].reg)) + as_tsktsk (BAD_MVE_SRCDEST); + + if (inst.cond > COND_ALWAYS) + inst.pred_insn_type = INSIDE_VPT_INSN; + else + inst.pred_insn_type = MVE_OUTSIDE_PRED_INSN; + + if (et.type == NT_poly) + mve_encode_qqq (neon_logbits (et.size), 64); + else + mve_encode_qqq (et.type == NT_unsigned, et.size); + + return; + +neon_vmul: + inst.instruction = N_MNEM_vmul; + inst.cond = 0xb; + if (thumb_mode) + inst.pred_insn_type = INSIDE_IT_INSN; + do_neon_mul (); +} + static void do_mve_vabav (void) { @@ -22751,6 +22845,7 @@ static const struct asm_opcode insns[] = ToC("vpsteee", fe712f4d, 0, (), mve_vpt), /* MVE and MVE FP only. */ + mCEF(vmullb, _vmullb, 3, (RMQ, RMQ, RMQ), mve_vmull), mCEF(vabav, _vabav, 3, (RRnpcsp, RMQ, RMQ), mve_vabav), mCEF(vmladav, _vmladav, 3, (RRe, RMQ, RMQ), mve_vmladav), mCEF(vmladava, _vmladava, 3, (RRe, RMQ, RMQ), mve_vmladav), @@ -22768,8 +22863,9 @@ static const struct asm_opcode insns[] = #undef THUMB_VARIANT #define THUMB_VARIANT & arm_ext_v6t2 - mnCEF(vadd, _vadd, 3, (RNSDQMQ, oRNSDQMQ, RNSDQMQR), neon_addsub_if_i), - mnCEF(vsub, _vsub, 3, (RNSDQMQ, oRNSDQMQ, RNSDQMQR), neon_addsub_if_i), + mCEF(vmullt, _vmullt, 3, (RNSDQMQ, oRNSDQMQ, RNSDQ_RNSC_MQ), mve_vmull), + mnCEF(vadd, _vadd, 3, (RNSDQMQ, oRNSDQMQ, RNSDQMQR), neon_addsub_if_i), + mnCEF(vsub, _vsub, 3, (RNSDQMQ, oRNSDQMQ, RNSDQMQR), neon_addsub_if_i), MNCEF(vabs, 1b10300, 2, (RNSDQMQ, RNSDQMQ), neon_abs_neg), MNCEF(vneg, 1b10380, 2, (RNSDQMQ, RNSDQMQ), neon_abs_neg), diff --git a/gas/testsuite/gas/arm/mve-vmullbt-bad.d b/gas/testsuite/gas/arm/mve-vmullbt-bad.d new file mode 100644 index 0000000000000000000000000000000000000000..91cbb1c1b71570595bb64b664489024da0f0722e --- /dev/null +++ b/gas/testsuite/gas/arm/mve-vmullbt-bad.d @@ -0,0 +1,5 @@ +#name: bad MVE VMULL instructions +#as: -march=armv8.1-m.main+mve.fp +#error_output: mve-vmullbt-bad.l + +.*: +file format .*arm.* diff --git a/gas/testsuite/gas/arm/mve-vmullbt-bad.l b/gas/testsuite/gas/arm/mve-vmullbt-bad.l new file mode 100644 index 0000000000000000000000000000000000000000..19f99dcc2ea3b04d1ce7ac656c47c1d08718ef26 --- /dev/null +++ b/gas/testsuite/gas/arm/mve-vmullbt-bad.l @@ -0,0 +1,33 @@ +[^:]*: Assembler messages: +[^:]*:13: Error: bad type in SIMD instruction -- `vmullb.s64 q0,q1,q2' +[^:]*:14: Error: bad type in SIMD instruction -- `vmullb.f16 q0,q1,q2' +[^:]*:15: Error: bad type in SIMD instruction -- `vmullb.f32 q0,q1,q2' +[^:]*:16: Warning: 32-bit element size and same destination and source operands makes instruction UNPREDICTABLE +[^:]*:17: Warning: 32-bit element size and same destination and source operands makes instruction UNPREDICTABLE +[^:]*:18: Warning: instruction is UNPREDICTABLE in an IT block +[^:]*:18: Warning: instruction is UNPREDICTABLE in an IT block +[^:]*:18: Warning: instruction is UNPREDICTABLE in an IT block +[^:]*:18: Warning: instruction is UNPREDICTABLE in an IT block +[^:]*:18: Warning: instruction is UNPREDICTABLE in an IT block +[^:]*:18: Warning: instruction is UNPREDICTABLE in an IT block +[^:]*:19: Error: bad type in SIMD instruction -- `vmullt.s64 q0,q1,q2' +[^:]*:20: Error: bad type in SIMD instruction -- `vmullt.f16 q0,q1,q2' +[^:]*:21: Error: bad type in SIMD instruction -- `vmullt.f32 q0,q1,q2' +[^:]*:22: Warning: 32-bit element size and same destination and source operands makes instruction UNPREDICTABLE +[^:]*:23: Warning: 32-bit element size and same destination and source operands makes instruction UNPREDICTABLE +[^:]*: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 +[^:]*:26: Error: syntax error -- `vmullbeq.s32 q0,q1,q2' +[^:]*:27: Error: syntax error -- `vmullbeq.s32 q0,q1,q2' +[^:]*:29: Error: syntax error -- `vmullbeq.s32 q0,q1,q2' +[^:]*:31: Error: instruction missing MVE vector predication code -- `vmullb.s32 q0,q1,q2' +[^:]*:32: Error: vector predicated instruction should be in VPT/VPST block -- `vmullbt.s32 q0,q1,q2' +[^:]*:34: Error: syntax error -- `vmullteq.s32 q0,q1,q2' +[^:]*:35: Error: syntax error -- `vmullteq.s32 q0,q1,q2' +[^:]*:37: Error: syntax error -- `vmullteq.s32 q0,q1,q2' +[^:]*:39: Error: instruction missing MVE vector predication code -- `vmullt.s32 q0,q1,q2' +[^:]*:40: Error: vector predicated instruction should be in VPT/VPST block -- `vmulltt.s32 q0,q1,q2' diff --git a/gas/testsuite/gas/arm/mve-vmullbt-bad.s b/gas/testsuite/gas/arm/mve-vmullbt-bad.s new file mode 100644 index 0000000000000000000000000000000000000000..e48269492b65990812abd1e6ab3766dd35723759 --- /dev/null +++ b/gas/testsuite/gas/arm/mve-vmullbt-bad.s @@ -0,0 +1,40 @@ +.macro cond op +.irp cond, eq, ne, gt, ge, lt, le +it \cond +\op\().s32 q0, q1, q2 +.endr +.endm + + + +.syntax unified +.text +.thumb +vmullb.s64 q0, q1, q2 +vmullb.f16 q0, q1, q2 +vmullb.f32 q0, q1, q2 +vmullb.s32 q1, q1, q2 +vmullb.s32 q2, q1, q2 +cond vmullb +vmullt.s64 q0, q1, q2 +vmullt.f16 q0, q1, q2 +vmullt.f32 q0, q1, q2 +vmullt.u32 q1, q1, q2 +vmullt.u32 q2, q1, q2 +cond vmullt +it eq +vmullbeq.s32 q0, q1, q2 +vmullbeq.s32 q0, q1, q2 +vpst +vmullbeq.s32 q0, q1, q2 +vpst +vmullb.s32 q0, q1, q2 +vmullbt.s32 q0, q1, q2 +it eq +vmullteq.s32 q0, q1, q2 +vmullteq.s32 q0, q1, q2 +vpst +vmullteq.s32 q0, q1, q2 +vpst +vmullt.s32 q0, q1, q2 +vmulltt.s32 q0, q1, q2 --------------D24FE48D03863C6D0D6F1B4E--