From patchwork Wed Nov 9 10:12:29 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Andre Vieira (lists)" X-Patchwork-Id: 692673 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3tDMSk2N66z9vDV for ; Wed, 9 Nov 2016 21:13:10 +1100 (AEDT) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="Yw4UteVh"; dkim-atps=neutral DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:to :references:from:cc:subject:message-id:date:mime-version :in-reply-to:content-type; q=dns; s=default; b=okfV9uXkBAY6FkAMq 8TgX35akxDWQNmfZerSL8aZWmVWe42K0ciB/4iIg9XSwvPP34GLZkODQI0hU+xFW gHpXUQFtT5n5z2TT3xWTyJajpbfywQyZBq71Z2tw8lik8j8ZvDjX90UeA3Nc+ERK E1riWxHCTU/Fn3bJ1gONg1xmyM= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:to :references:from:cc:subject:message-id:date:mime-version :in-reply-to:content-type; s=default; bh=GNTzug6kGczpFuqXQgVfN21 1O/4=; b=Yw4UteVhDp7hCIi3KEIkfby+AmBmlmqbrZkNcuNunJnq99aaeGCiGvF ctcvlP7cf7EEtyDJDndj37wzSaj3mHP6z7HQTBQ08B/appYr5Dx8S7T7/E0PacaD k/GkR1v6RCbXVU7vEJsFtezDL6Nn9/eAyKPhIfpys3zdwMYMGlZ4= Received: (qmail 55053 invoked by alias); 9 Nov 2016 10:12:41 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 54869 invoked by uid 89); 9 Nov 2016 10:12:38 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-3.8 required=5.0 tests=BAYES_00, KAM_ASCII_DIVIDERS, KAM_LOTSOFHASH, RP_MATCHES_RCVD, SPF_PASS autolearn=ham version=3.3.2 spammy=cr0, 1046, 1586, (unknown) 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, 09 Nov 2016 10:12:34 +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 9319A13D9; Wed, 9 Nov 2016 02:12:33 -0800 (PST) Received: from [10.2.206.251] (e107157-lin.cambridge.arm.com [10.2.206.251]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 7250E3F24D; Wed, 9 Nov 2016 02:12:32 -0800 (PST) To: gcc-patches@gcc.gnu.org References: <5822F3CB.3040202@arm.com> From: "Andre Vieira (lists)" Cc: Kyrill Tkachov , Ramana Radhakrishnan Subject: [PATCH 5/6][ARM] Implement support for ACLE Coprocessor MCR and MRC intrinsics Message-ID: <5822F68D.3050006@arm.com> Date: Wed, 9 Nov 2016 10:12:29 +0000 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Thunderbird/38.2.0 MIME-Version: 1.0 In-Reply-To: <5822F3CB.3040202@arm.com> X-IsSubscribed: yes Hi, This patch implements support for the ARM ACLE Coprocessor MCR and MRC intrinsics. See below a table mapping the intrinsics to their respective instructions: +-------------------------------------------------------------------+---------------------------------------+ | Intrinsic signature | Instruction pattern | +-------------------------------------------------------------------+---------------------------------------+ |void __arm_mcr(coproc, opc1, uint32_t value, CRn, CRm, opc2) | MCR coproc, opc1, Rt, CRn, CRm, opc2 | +-------------------------------------------------------------------+---------------------------------------+ |void __arm_mcr2(coproc, opc1, uint32_t value, CRn, CRm, opc2) | MCR2 coproc, opc1, Rt, CRn, CRm, opc2 | +-------------------------------------------------------------------+---------------------------------------+ |uint32_t __arm_mrc(coproc, opc1, CRn, CRm, opc2) | MRC coproc, opc1, Rt, CRn, CRm, opc2 | +-------------------------------------------------------------------+---------------------------------------+ |uint32_t __arm_mrc2(coproc, opc1, CRn, CRm, opc2) | MRC2 coproc, opc1, Rt, CRn, CRm, opc2 | +-------------------------------------------------------------------+---------------------------------------+ Note that any untyped variable in the intrinsic signature is required to be a compiler-time constant and has the type 'unsigned int'. We do some boundary checks for coproc:[0-15], opc1[0-7] CR*:[0-31],opc2:[0-7]. If either of these requirements are not met a diagnostic is issued. Is this OK for trunk? Regards, Andre gcc/ChangeLog: 2016-11-09 Andre Vieira * config/arm/arm.md (): New. (): New. * config/arm/arm.c (arm_coproc_builtin_available): Add support for mcr, mrc, mcr2 and mrc2. * config/arm/arm-builtins.c (MCR_QUALIFIERS): Define to... (arm_mcr_qualifiers): ... this. New. (MRC_QUALIFIERS): Define to ... (arm_mrc_qualifiers): ... this. New. (MCR_QUALIFIERS): Define to ... (arm_mcr_qualifiers): ... this. New. * config/arm/arm_acle.h (__arm_mcr, __arm_mrc, __arm_mcr2, __arm_mrc2): New. * config/arm/arm_acle_builtins.def (mcr, mcr2, mrc, mrc2): New. * config/arm/iterators.md (MCRI, mcr, MCR, MRCI, mrc, MRC): New. * config/arm/unspecs.md (VUNSPEC_MCR, VUNSPEC_MCR2, VUNSPEC_MRC, VUNSPEC_MRC2): New. gcc/ChangeLog: 2016-11-09 Andre Vieira * gcc.target/arm/acle/mcr.c: New. * gcc.target/arm/acle/mrc.c: New. * gcc.target/arm/acle/mcr2.c: New. * gcc.target/arm/acle/mrc2.c: New. diff --git a/gcc/config/arm/arm-builtins.c b/gcc/config/arm/arm-builtins.c index e6e58cd6a656732e37c6bca23ad980eea522a710..44f255356dcc3ea6b8f554ba96f99fd7856bf6a1 100644 --- a/gcc/config/arm/arm-builtins.c +++ b/gcc/config/arm/arm-builtins.c @@ -196,6 +196,26 @@ arm_stc_qualifiers[SIMD_MAX_BUILTIN_ARGS] #define STC_QUALIFIERS \ (arm_stc_qualifiers) +/* void (unsigned immediate, unsigned immediate, T, unsigned immediate, + unsigned immediate, unsigned immediate). */ +static enum arm_type_qualifiers +arm_mcr_qualifiers[SIMD_MAX_BUILTIN_ARGS] + = { qualifier_void, qualifier_unsigned_immediate, + qualifier_unsigned_immediate, qualifier_none, + qualifier_unsigned_immediate, qualifier_unsigned_immediate, + qualifier_unsigned_immediate }; +#define MCR_QUALIFIERS \ + (arm_mcr_qualifiers) + +/* T (unsigned immediate, unsigned immediate, unsigned immediate, + unsigned immediate, unsigned immediate). */ +static enum arm_type_qualifiers +arm_mrc_qualifiers[SIMD_MAX_BUILTIN_ARGS] + = { qualifier_none, qualifier_unsigned_immediate, + qualifier_unsigned_immediate, qualifier_unsigned_immediate, + qualifier_unsigned_immediate, qualifier_unsigned_immediate }; +#define MRC_QUALIFIERS \ + (arm_mrc_qualifiers) /* The first argument (return type) of a store should be void type, which we represent with qualifier_void. Their first operand will be a DImode pointer to the location to store to, so we must use diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c index d3191abee163d5fbf753fb5072be50fdb2b4c785..25439a343e8540c5fca5cbe19e8b76e2fdb97a73 100644 --- a/gcc/config/arm/arm.c +++ b/gcc/config/arm/arm.c @@ -30803,6 +30803,8 @@ bool arm_coproc_builtin_available (enum unspecv builtin) case VUNSPEC_LDCL: case VUNSPEC_STC: case VUNSPEC_STCL: + case VUNSPEC_MCR: + case VUNSPEC_MRC: if (arm_arch4) return true; break; @@ -30811,6 +30813,8 @@ bool arm_coproc_builtin_available (enum unspecv builtin) case VUNSPEC_LDC2L: case VUNSPEC_STC2: case VUNSPEC_STC2L: + case VUNSPEC_MCR2: + case VUNSPEC_MRC2: /* Only present in ARMv5*, ARMv6 (but not ARMv6-M), ARMv7* and ARMv8-{A,M}. */ if (arm_arch5) diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md index 45cdd576fa5b7f26e2d1cfa2c86a8c8767537e54..b74d0519f0c218167192bedeaa493468e301943b 100644 --- a/gcc/config/arm/arm.md +++ b/gcc/config/arm/arm.md @@ -11877,6 +11877,45 @@ (mem:SI (match_operand:SI 2 "s_register_operand"))] LDCSTCI)] "arm_coproc_builtin_available (VUNSPEC_)") +(define_insn "" + [(unspec_volatile [(match_operand:SI 0 "immediate_operand") + (match_operand:SI 1 "immediate_operand") + (match_operand:SI 2 "s_register_operand") + (match_operand:SI 3 "immediate_operand") + (match_operand:SI 4 "immediate_operand") + (match_operand:SI 5 "immediate_operand")] MCRI) + (use (match_dup 2))] + "arm_coproc_builtin_available (VUNSPEC_)" +{ + arm_const_bounds (operands[0], 0, 16); + arm_const_bounds (operands[1], 0, 8); + arm_const_bounds (operands[3], 0, (1 << 5)); + arm_const_bounds (operands[4], 0, (1 << 5)); + arm_const_bounds (operands[5], 0, 8); + return "\\tp%c0, %1, %2, CR%c3, CR%c4, %5"; +} + [(set_attr "length" "4") + (set_attr "type" "coproc")]) + +(define_insn "" + [(set (match_operand:SI 0 "s_register_operand") + (unspec_volatile [(match_operand:SI 1 "immediate_operand") + (match_operand:SI 2 "immediate_operand") + (match_operand:SI 3 "immediate_operand") + (match_operand:SI 4 "immediate_operand") + (match_operand:SI 5 "immediate_operand")] MRCI))] + "arm_coproc_builtin_available (VUNSPEC_)" +{ + arm_const_bounds (operands[1], 0, 16); + arm_const_bounds (operands[2], 0, 8); + arm_const_bounds (operands[3], 0, (1 << 5)); + arm_const_bounds (operands[4], 0, (1 << 5)); + arm_const_bounds (operands[5], 0, 8); + return "\\tp%c1, %2, %0, CR%c3, CR%c4, %5"; +} + [(set_attr "length" "4") + (set_attr "type" "coproc")]) + ;; Vector bits common to IWMMXT and Neon (include "vec-common.md") ;; Load the Intel Wireless Multimedia Extension patterns diff --git a/gcc/config/arm/arm_acle.h b/gcc/config/arm/arm_acle.h index 81527782dfe16fa3be7638ddd38051e333f7e18c..2a202f3982176ba8fd7475ee75863034eff662e6 100644 --- a/gcc/config/arm/arm_acle.h +++ b/gcc/config/arm/arm_acle.h @@ -68,6 +68,22 @@ __arm_stcl (const unsigned int __coproc, const unsigned int __CRd, { return __builtin_arm_stcl (__coproc, __CRd, __p); } + +__extension__ static __inline void __attribute__ ((__always_inline__)) +__arm_mcr (const unsigned int __coproc, const unsigned int __opc1, + uint32_t __value, const unsigned int __CRn, const unsigned int __CRm, + const unsigned int __opc2) +{ + return __builtin_arm_mcr (__coproc, __opc1, __value, __CRn, __CRm, __opc2); +} + +__extension__ static __inline uint32_t __attribute__ ((__always_inline__)) +__arm_mrc (const unsigned int __coproc, const unsigned int __opc1, + const unsigned int __CRn, const unsigned int __CRm, + const unsigned int __opc2) +{ + return __builtin_arm_mrc (__coproc, __opc1, __CRn, __CRm, __opc2); +} #if __ARM_ARCH >= 5 __extension__ static __inline void __attribute__ ((__always_inline__)) __arm_cdp2 (const unsigned int __coproc, const unsigned int __opc1, @@ -104,6 +120,22 @@ __arm_stc2l (const unsigned int __coproc, const unsigned int __CRd, { return __builtin_arm_stc2l (__coproc, __CRd, __p); } + +__extension__ static __inline void __attribute__ ((__always_inline__)) +__arm_mcr2 (const unsigned int __coproc, const unsigned int __opc1, + uint32_t __value, const unsigned int __CRn, + const unsigned int __CRm, const unsigned int __opc2) +{ + return __builtin_arm_mcr2 (__coproc, __opc1, __value, __CRn, __CRm, __opc2); +} + +__extension__ static __inline uint32_t __attribute__ ((__always_inline__)) +__arm_mrc2 (const unsigned int __coproc, const unsigned int __opc1, + const unsigned int __CRn, const unsigned int __CRm, + const unsigned int __opc2) +{ + return __builtin_arm_mrc2 (__coproc, __opc1, __CRn, __CRm, __opc2); +} #endif /* __ARM_ARCH >= 5. */ #endif /* (!__thumb__ || __thumb2__) && __ARM_ARCH >= 4. */ diff --git a/gcc/config/arm/arm_acle_builtins.def b/gcc/config/arm/arm_acle_builtins.def index eb6168d98a897280aef2954372613487ca256fb0..d258f8a3748f6b4f0aeb3d4a28c6d4d79597f69c 100644 --- a/gcc/config/arm/arm_acle_builtins.def +++ b/gcc/config/arm/arm_acle_builtins.def @@ -34,3 +34,7 @@ VAR1 (STC, stc, void) VAR1 (STC, stc2, void) VAR1 (STC, stcl, void) VAR1 (STC, stc2l, void) +VAR1 (MCR, mcr, void) +VAR1 (MCR, mcr2, void) +VAR1 (MRC, mrc, si) +VAR1 (MRC, mrc2, si) diff --git a/gcc/config/arm/iterators.md b/gcc/config/arm/iterators.md index e1f5e4911a8f76ae0cd283dd55328dd7720f50d6..899e5184c61bf7a2800df01b31d56a8dab1abcb3 100644 --- a/gcc/config/arm/iterators.md +++ b/gcc/config/arm/iterators.md @@ -963,3 +963,15 @@ (VUNSPEC_LDCL "LDCL") (VUNSPEC_LDC2L "LDC2L") (VUNSPEC_STC "STC") (VUNSPEC_STC2 "STC2") (VUNSPEC_STCL "STCL") (VUNSPEC_STC2L "STC2L")]) + +;; An iterator for the MCR coprocessor instructions +(define_int_iterator MCRI [VUNSPEC_MCR VUNSPEC_MCR2]) + +(define_int_attr mcr [(VUNSPEC_MCR "mcr") (VUNSPEC_MCR2 "mcr2")]) +(define_int_attr MCR [(VUNSPEC_MCR "MCR") (VUNSPEC_MCR2 "MCR2")]) + +;; An iterator for the MRC coprocessor instructions +(define_int_iterator MRCI [VUNSPEC_MRC VUNSPEC_MRC2]) + +(define_int_attr mrc [(VUNSPEC_MRC "mrc") (VUNSPEC_MRC2 "mrc2")]) +(define_int_attr MRC [(VUNSPEC_MRC "MRC") (VUNSPEC_MRC2 "MRC2")]) diff --git a/gcc/config/arm/unspecs.md b/gcc/config/arm/unspecs.md index 2b6ba8b4b4b08742204153462c3d0dff02374d42..48a711e6c7160a85435ae45b6668b55494a9a671 100644 --- a/gcc/config/arm/unspecs.md +++ b/gcc/config/arm/unspecs.md @@ -158,6 +158,10 @@ VUNSPEC_STC2 ; Represent the coprocessor stc2 instruction. VUNSPEC_STCL ; Represent the coprocessor stcl instruction. VUNSPEC_STC2L ; Represent the coprocessor stc2l instruction. + VUNSPEC_MCR ; Represent the coprocessor mcr instruction. + VUNSPEC_MCR2 ; Represent the coprocessor mcr2 instruction. + VUNSPEC_MRC ; Represent the coprocessor mrc instruction. + VUNSPEC_MRC2 ; Represent the coprocessor mrc2 instruction. ]) ;; Enumerators for NEON unspecs. diff --git a/gcc/testsuite/gcc.target/arm/acle/mcr.c b/gcc/testsuite/gcc.target/arm/acle/mcr.c new file mode 100644 index 0000000000000000000000000000000000000000..93f977a2bdb03ece206cf36b4d67f47811dd0073 --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/acle/mcr.c @@ -0,0 +1,16 @@ +/* Test the mcr ACLE intrinsic. */ + +/* { dg-do assemble } */ +/* { dg-options "-save-temps" } */ +/* { dg-require-effective-target arm_coproc1_ok } */ + +#include "arm_acle.h" + +void test_mcr (uint32_t a) +{ + a += 77; + __arm_mcr (10, 5, a, 3, 4, 7); +} + +/* { dg-final { scan-assembler "add\[^\n\]*#77\n" } } */ +/* { dg-final { scan-assembler "mcr\tp10, #5, r\[r0-9\]*, CR3, CR4, #7\n" } } */ diff --git a/gcc/testsuite/gcc.target/arm/acle/mcr2.c b/gcc/testsuite/gcc.target/arm/acle/mcr2.c new file mode 100644 index 0000000000000000000000000000000000000000..5b60d10ff255a0a72dc93fcc13056b0d424ffec7 --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/acle/mcr2.c @@ -0,0 +1,16 @@ +/* Test the mcr2 ACLE intrinsic. */ + +/* { dg-do assemble } */ +/* { dg-options "-save-temps" } */ +/* { dg-require-effective-target arm_coproc2_ok } */ + +#include "arm_acle.h" + +void test_mcr2 (uint32_t a) +{ + a += 77; + __arm_mcr2 (10, 5, a, 3, 4, 7); +} + +/* { dg-final { scan-assembler "add\[^\n\]*#77\n" } } */ +/* { dg-final { scan-assembler "mcr2\tp10, #5, r\[r0-9\]*, CR3, CR4, #7\n" } } */ diff --git a/gcc/testsuite/gcc.target/arm/acle/mrc.c b/gcc/testsuite/gcc.target/arm/acle/mrc.c new file mode 100644 index 0000000000000000000000000000000000000000..34ca6a1638c5667b3ef529ebcf448caecc6e3492 --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/acle/mrc.c @@ -0,0 +1,14 @@ +/* Test the mrc ACLE intrinsic. */ + +/* { dg-do assemble } */ +/* { dg-options "-save-temps" } */ +/* { dg-require-effective-target arm_coproc1_ok } */ + +#include "arm_acle.h" + +uint32_t test_mrc (void) +{ + return __arm_mrc (10, 0, 0, 15, 3); +} + +/* { dg-final { scan-assembler "mrc\tp10, #0, r\[r0-9\]*, CR0, CR15, #3\n" } } */ diff --git a/gcc/testsuite/gcc.target/arm/acle/mrc2.c b/gcc/testsuite/gcc.target/arm/acle/mrc2.c new file mode 100644 index 0000000000000000000000000000000000000000..3b72a402224dec5544349c9e4d79c9a8aa5a1f8c --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/acle/mrc2.c @@ -0,0 +1,14 @@ +/* Test the mrc2 ACLE intrinsic. */ + +/* { dg-do assemble } */ +/* { dg-options "-save-temps" } */ +/* { dg-require-effective-target arm_coproc2_ok } */ + +#include "arm_acle.h" + +uint32_t test_mrc2 (void) +{ + return __arm_mrc2 (10, 0, 0, 15, 3); +} + +/* { dg-final { scan-assembler "mrc2\tp10, #0, r\[r0-9\]*, CR0, CR15, #3\n" } } */