From patchwork Fri Jan 6 14:18:17 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Andre Vieira (lists)" X-Patchwork-Id: 711937 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 3tw69h6RWbz9svs for ; Sat, 7 Jan 2017 01:19:04 +1100 (AEDT) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="OZMjxYSS"; 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 :subject:to:references:cc:from:message-id:date:mime-version :in-reply-to:content-type; q=dns; s=default; b=K44jjeoLW4OB/RErh rcnHnLO2oTpI+qKwCg9PH+djnMz7jCwcztw7xMtSZpRJLHmqpXQEOtbJqNNljvOi 5y/a4GvmoiPiqtwu3cObbpMIdX/jCB8bUBAon21vVn3ISmZnDK3xUz/aB0rPmUT5 kV6t+vQ0oaLy/iiPc30HVhYzwA= 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 :subject:to:references:cc:from:message-id:date:mime-version :in-reply-to:content-type; s=default; bh=gIHeDqwARHpIP1LBqnt8T+N SWWE=; b=OZMjxYSS4qrs81gFpP+t1GhJ5U4VvFY7xSZHs9Oj51m+itNyhepN9Se Iw73K+uJePq6U4DVR0hnU38Rv/KvWlB6jc4WWuHwRjMhkHwdBOynugcUVKfOxrx5 zcgvSqr2nh/51wywlS/30BbTN884RMxZuMWU0oNL7pqe6X4RLp1E= Received: (qmail 65838 invoked by alias); 6 Jan 2017 14:18:32 -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 65552 invoked by uid 89); 6 Jan 2017 14:18:31 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-4.0 required=5.0 tests=BAYES_00, KAM_ASCII_DIVIDERS, KAM_LOTSOFHASH, RP_MATCHES_RCVD, SPF_PASS autolearn=ham version=3.3.2 spammy=178, 6, 1786, REG_P, reg_p 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; Fri, 06 Jan 2017 14:18:20 +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 5B8EDC14; Fri, 6 Jan 2017 06:18:19 -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 915EE3F24D; Fri, 6 Jan 2017 06:18:18 -0800 (PST) Subject: Re: [PATCH 4/6][ARM] Implement support for ACLE Coprocessor LDC and STC intrinsics To: Kyrill Tkachov , gcc-patches@gcc.gnu.org References: <5822F3CB.3040202@arm.com> <5822F683.40803@arm.com> <586E27E0.9050609@foss.arm.com> Cc: Ramana Radhakrishnan From: "Andre Vieira (lists)" Message-ID: <586FA729.1000609@arm.com> Date: Fri, 6 Jan 2017 14:18:17 +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: <586E27E0.9050609@foss.arm.com> X-IsSubscribed: yes On 05/01/17 11:02, Kyrill Tkachov wrote: > Hi Andre, > > On 09/11/16 10:12, Andre Vieira (lists) wrote: >> Hi, >> >> This patch implements support for the ARM ACLE Coprocessor LDC and STC >> intrinsics. See below a table mapping the intrinsics to their respective >> instructions: >> >> +----------------------------------------------------+--------------------------------------+ >> >> | Intrinsic signature | Instruction >> pattern | >> +----------------------------------------------------+--------------------------------------+ >> >> |void __arm_ldc(coproc, CRd, const void* p) |LDC coproc, CRd, >> [...] | >> +----------------------------------------------------+--------------------------------------+ >> >> |void __arm_ldcl(coproc, CRd, const void* p) |LDCL coproc, CRd, >> [...] | >> +----------------------------------------------------+--------------------------------------+ >> >> |void __arm_ldc2(coproc, CRd, const void* p) |LDC2 coproc, CRd, >> [...] | >> +----------------------------------------------------+--------------------------------------+ >> >> |void __arm_ldc2l(coproc, CRd, const void* p) |LDC2L coproc, CRd, >> [...] | >> +----------------------------------------------------+--------------------------------------+ >> >> |void __arm_stc(coproc, CRd, void* p) |STC coproc, CRd, >> [...] | >> +----------------------------------------------------+--------------------------------------+ >> >> |void __arm_stcl(coproc, CRd, void* p) |STCL coproc, CRd, >> [...] | >> +----------------------------------------------------+--------------------------------------+ >> >> |void __arm_stc2(coproc, CRd, void* p) |STC2 coproc, CRd, >> [...] | >> +----------------------------------------------------+--------------------------------------+ >> >> |void __arm_stc2l(coproc, CRd, void* p) |STC2L coproc, CRd, >> [...] | >> +----------------------------------------------------+--------------------------------------+ >> >> 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], CR*:[0-31]. If either of these >> requirements are not met a diagnostic is issued. >> >> >> Is this ok for trunk? > > I have a few comments below... > >> Regards, >> Andre >> >> gcc/ChangeLog: >> 2016-11-09 Andre Vieira >> >> * config/arm/arm.md (*ldcstc): New. >> (): New. >> * config/arm/arm.c (arm_coproc_builtin_available): Add >> support for ldc,ldcl,stc,stcl,ldc2,ldc2l,stc2 and stc2l. >> (arm_coproc_ldc_stc_legitimate_address): New. >> * config/arm/arm-builtins.c (arm_type_qualifiers): Add >> 'qualifier_const_pointer'. >> (LDC_QUALIFIERS): Define to... >> (arm_ldc_qualifiers): ... this. New. >> (STC_QUALIFIERS): Define to... >> (arm_stc_qualifiers): ... this. New. >> * config/arm/arm-protos.h >> (arm_coproc_ldc_stc_legitimate_address): New. >> * config/arm/arm_acle.h (__arm_ldc, __arm_ldcl, __arm_stc, >> __arm_stcl, __arm_ldc2, __arm_ldc2l, __arm_stc2, __arm_stc2l): New. >> * config/arm/arm_acle_builtins.def (ldc, ldc2, ldcl, ldc2l, stc, >> stc2, stcl, stc2l): New. >> * config/arm/constraints.md (Uz): New. >> * config/arm/iterators.md (LDCSTCI, ldcstc, LDCSTC): New. >> * config/arm/unspecs.md (VUNSPEC_LDC, VUNSPEC_LDC2, VUNSPEC_LDCL, >> VUNSPEC_LDC2L, VUNSPEC_STC, VUNSPEC_STC2, VUNSPEC_STCL, >> VUNSPEC_STC2L): New. >> >> gcc/testsuite/ChangeLog: >> >> 2016-11-09 Andre Vieira >> >> * gcc.target/arm/acle/ldc: New. >> * gcc.target/arm/acle/ldc2: New. >> * gcc.target/arm/acle/ldcl: New. >> * gcc.target/arm/acle/ldc2l: New. >> * gcc.target/arm/acle/stc: New. >> * gcc.target/arm/acle/stc2: New. >> * gcc.target/arm/acle/stcl: New. >> * gcc.target/arm/acle/stc2l: New. > > + /* const T * foo */ > + qualifier_const_pointer = 0x6, > > Nit: full stop at end of comment. > > + > +/* This function returns true if OP is a valid memory operand for the > ldc and > + stc coprocessor instructions and false otherwise. */ > + > +bool arm_coproc_ldc_stc_legitimate_address (rtx op) > +{ > > type and function name should be on separate lines. > > + int range; > + /* Has to be a memory operand. */ > + if (!MEM_P (op)) > + return false; > > + /* Within the range of [-1020,1020]. */ > + if (range < -1020 || range > 1020) > + return false; > > Use !IN_RANGE (-1020, 1020), also make 'range' a HOST_WIDE_INT (that is > what INTVAL returns). > > --- a/gcc/config/arm/arm.md > +++ b/gcc/config/arm/arm.md > @@ -11858,6 +11858,25 @@ > [(set_attr "length" "4") > (set_attr "type" "coproc")]) > > +(define_insn "*ldcstc" > + [(unspec_volatile [(match_operand:SI 0 "immediate_operand") > + (match_operand:SI 1 "immediate_operand") > + (match_operand:SI 2 "memory_operand" "Uz")] LDCSTCI)] > + "arm_coproc_builtin_available (VUNSPEC_)" > > You're missing constraints for operands 1 and 2? (just the general 'n' > constraint should do it since you do bounds checking in arm_const_bounds) > Also, the ldc reads memory, whereas stc writes to it, so at least the > stc variants will need > a '=' in their constraint string to tell LRA that the memory is written > to. For this I think it's better to split ldc* and stc* into separate > define_insns. > > +(define_memory_constraint "Uz" > + "@internal > + A memory access that is accessible" > + (and (match_code "mem") > + (match_test "arm_coproc_ldc_stc_legitimate_address (op)"))) > > That description doesn't make much sense. Did you mean "A memory access > suitable as an LDC/STC operand" ? > Hi, Reworked according to comments and rebased it. Is this ok for trunk? Regards, Andre gcc/ChangeLog: 2017-01-xx Andre Vieira * config/arm/arm.md (*ldc): New. (*stc): New. (): New. (): New. * config/arm/arm.c (arm_coproc_builtin_available): Add support for ldc,ldcl,stc,stcl,ldc2,ldc2l,stc2 and stc2l. (arm_coproc_ldc_stc_legitimate_address): New. * config/arm/arm-builtins.c (arm_type_qualifiers): Add 'qualifier_const_pointer'. (LDC_QUALIFIERS): Define to... (arm_ldc_qualifiers): ... this. New. (STC_QUALIFIERS): Define to... (arm_stc_qualifiers): ... this. New. * config/arm/arm-protos.h (arm_coproc_ldc_stc_legitimate_address): New. * config/arm/arm_acle.h (__arm_ldc, __arm_ldcl, __arm_stc, __arm_stcl, __arm_ldc2, __arm_ldc2l, __arm_stc2, __arm_stc2l): New. * config/arm/arm_acle_builtins.def (ldc, ldc2, ldcl, ldc2l, stc, stc2, stcl, stc2l): New. * config/arm/constraints.md (Uz): New. * config/arm/iterators.md (LDCI, STCI, ldc, stc, LDC STC): New. * config/arm/unspecs.md (VUNSPEC_LDC, VUNSPEC_LDC2, VUNSPEC_LDCL, VUNSPEC_LDC2L, VUNSPEC_STC, VUNSPEC_STC2, VUNSPEC_STCL, VUNSPEC_STC2L): New. gcc/testsuite/ChangeLog: 2017-01-xx Andre Vieira * gcc.target/arm/acle/ldc: New. * gcc.target/arm/acle/ldc2: New. * gcc.target/arm/acle/ldcl: New. * gcc.target/arm/acle/ldc2l: New. * gcc.target/arm/acle/stc: New. * gcc.target/arm/acle/stc2: New. * gcc.target/arm/acle/stcl: New. * gcc.target/arm/acle/stc2l: New. diff --git a/gcc/config/arm/arm-builtins.c b/gcc/config/arm/arm-builtins.c index 2bb9e22bb8cf7ae2d8a5698e970af4845016d93c..103ae762f7c2de62f445a5f48b80222ac4f37767 100644 --- a/gcc/config/arm/arm-builtins.c +++ b/gcc/config/arm/arm-builtins.c @@ -51,6 +51,8 @@ enum arm_type_qualifiers qualifier_const = 0x2, /* 1 << 1 */ /* T *foo. */ qualifier_pointer = 0x4, /* 1 << 2 */ + /* const T * foo. */ + qualifier_const_pointer = 0x6, /* Used when expanding arguments if an operand could be an immediate. */ qualifier_immediate = 0x8, /* 1 << 3 */ @@ -178,6 +180,23 @@ arm_cdp_qualifiers[SIMD_MAX_BUILTIN_ARGS] qualifier_unsigned_immediate }; #define CDP_QUALIFIERS \ (arm_cdp_qualifiers) + +/* void (unsigned immediate, unsigned immediate, const void *). */ +static enum arm_type_qualifiers +arm_ldc_qualifiers[SIMD_MAX_BUILTIN_ARGS] + = { qualifier_void, qualifier_unsigned_immediate, + qualifier_unsigned_immediate, qualifier_const_pointer }; +#define LDC_QUALIFIERS \ + (arm_ldc_qualifiers) + +/* void (unsigned immediate, unsigned immediate, void *). */ +static enum arm_type_qualifiers +arm_stc_qualifiers[SIMD_MAX_BUILTIN_ARGS] + = { qualifier_void, qualifier_unsigned_immediate, + qualifier_unsigned_immediate, qualifier_pointer }; +#define STC_QUALIFIERS \ + (arm_stc_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-protos.h b/gcc/config/arm/arm-protos.h index 4d6a3ed3d47952728c3c4c1a8bd5ec0b9274bb16..1b1623917273b7f7d1708b2429fc6bdd0c1613ab 100644 --- a/gcc/config/arm/arm-protos.h +++ b/gcc/config/arm/arm-protos.h @@ -177,6 +177,7 @@ extern void arm_split_compare_and_swap (rtx op[]); extern void arm_split_atomic_op (enum rtx_code, rtx, rtx, rtx, rtx, rtx, rtx); extern rtx arm_load_tp (rtx); extern bool arm_coproc_builtin_available (enum unspecv); +extern bool arm_coproc_ldc_stc_legitimate_address (rtx); #if defined TREE_CODE extern void arm_init_cumulative_args (CUMULATIVE_ARGS *, tree, rtx, tree); diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c index 64599981961d80c5493a88f30743b98a138ca932..5e098461ec71d16768c9e6cde4e8cc5303c3eb59 100644 --- a/gcc/config/arm/arm.c +++ b/gcc/config/arm/arm.c @@ -30904,10 +30904,18 @@ arm_coproc_builtin_available (enum unspecv builtin) switch (builtin) { case VUNSPEC_CDP: + case VUNSPEC_LDC: + case VUNSPEC_LDCL: + case VUNSPEC_STC: + case VUNSPEC_STCL: if (arm_arch4) return true; break; case VUNSPEC_CDP2: + case VUNSPEC_LDC2: + case VUNSPEC_LDC2L: + case VUNSPEC_STC2: + case VUNSPEC_STC2L: /* Only present in ARMv5*, ARMv6 (but not ARMv6-M), ARMv7* and ARMv8-{A,M}. */ if (arm_arch5) @@ -30918,4 +30926,55 @@ arm_coproc_builtin_available (enum unspecv builtin) } return false; } + +/* This function returns true if OP is a valid memory operand for the ldc and + stc coprocessor instructions and false otherwise. */ + +bool +arm_coproc_ldc_stc_legitimate_address (rtx op) +{ + HOST_WIDE_INT range; + /* Has to be a memory operand. */ + if (!MEM_P (op)) + return false; + + op = XEXP (op, 0); + + /* We accept registers. */ + if (REG_P (op)) + return true; + + switch GET_CODE (op) + { + case PLUS: + { + /* Or registers with an offset. */ + if (!REG_P (XEXP (op, 0))) + return false; + + op = XEXP (op, 1); + + /* The offset must be an immediate though. */ + if (!CONST_INT_P (op)) + return false; + + range = INTVAL (op); + + /* Within the range of [-1020,1020]. */ + if (!IN_RANGE (range, -1020, 1020)) + return false; + + /* And a multiple of 4. */ + return (range % 4) == 0; + } + case PRE_INC: + case POST_INC: + case PRE_DEC: + case POST_DEC: + return REG_P (XEXP (op, 0)); + default: + gcc_unreachable (); + } + return false; +} #include "gt-arm.h" diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md index b5325013c2179c06e0079f35a5c5bd0ae9388d4c..799a9cae3707202ce45ae72fcbeda97dccf62529 100644 --- a/gcc/config/arm/arm.md +++ b/gcc/config/arm/arm.md @@ -11939,6 +11939,44 @@ [(set_attr "length" "4") (set_attr "type" "coproc")]) +(define_insn "*ldc" + [(unspec_volatile [(match_operand:SI 0 "immediate_operand" "n") + (match_operand:SI 1 "immediate_operand" "n") + (match_operand:SI 2 "memory_operand" "Uz")] LDCI)] + "arm_coproc_builtin_available (VUNSPEC_)" +{ + arm_const_bounds (operands[0], 0, 16); + arm_const_bounds (operands[1], 0, (1 << 5)); + return "\\tp%c0, CR%c1, %2"; +} + [(set_attr "length" "4") + (set_attr "type" "coproc")]) + +(define_insn "*stc" + [(unspec_volatile [(match_operand:SI 0 "immediate_operand" "n") + (match_operand:SI 1 "immediate_operand" "n") + (match_operand:SI 2 "memory_operand" "=Uz")] STCI)] + "arm_coproc_builtin_available (VUNSPEC_)" +{ + arm_const_bounds (operands[0], 0, 16); + arm_const_bounds (operands[1], 0, (1 << 5)); + return "\\tp%c0, CR%c1, %2"; +} + [(set_attr "length" "4") + (set_attr "type" "coproc")]) + +(define_expand "" + [(unspec_volatile [(match_operand:SI 0 "immediate_operand") + (match_operand:SI 1 "immediate_operand") + (mem:SI (match_operand:SI 2 "s_register_operand"))] LDCI)] + "arm_coproc_builtin_available (VUNSPEC_)") + +(define_expand "" + [(unspec_volatile [(match_operand:SI 0 "immediate_operand") + (match_operand:SI 1 "immediate_operand") + (mem:SI (match_operand:SI 2 "s_register_operand"))] STCI)] + "arm_coproc_builtin_available (VUNSPEC_)") + ;; 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 08add2b7ac79f487dea92477d39b9db886a3f027..1c7a44d9087b4c4b9e46669deb833f585564d053 100644 --- a/gcc/config/arm/arm_acle.h +++ b/gcc/config/arm/arm_acle.h @@ -41,6 +41,33 @@ __arm_cdp (const unsigned int __coproc, const unsigned int __opc1, return __builtin_arm_cdp (__coproc, __opc1, __CRd, __CRn, __CRm, __opc2); } +__extension__ static __inline void __attribute__ ((__always_inline__)) +__arm_ldc (const unsigned int __coproc, const unsigned int __CRd, + const void * __p) +{ + return __builtin_arm_ldc (__coproc, __CRd, __p); +} + +__extension__ static __inline void __attribute__ ((__always_inline__)) +__arm_ldcl (const unsigned int __coproc, const unsigned int __CRd, + const void * __p) +{ + return __builtin_arm_ldcl (__coproc, __CRd, __p); +} + +__extension__ static __inline void __attribute__ ((__always_inline__)) +__arm_stc (const unsigned int __coproc, const unsigned int __CRd, + void * __p) +{ + return __builtin_arm_stc (__coproc, __CRd, __p); +} + +__extension__ static __inline void __attribute__ ((__always_inline__)) +__arm_stcl (const unsigned int __coproc, const unsigned int __CRd, + void * __p) +{ + return __builtin_arm_stcl (__coproc, __CRd, __p); +} #if __ARM_ARCH >= 5 __extension__ static __inline void __attribute__ ((__always_inline__)) __arm_cdp2 (const unsigned int __coproc, const unsigned int __opc1, @@ -49,6 +76,34 @@ __arm_cdp2 (const unsigned int __coproc, const unsigned int __opc1, { return __builtin_arm_cdp2 (__coproc, __opc1, __CRd, __CRn, __CRm, __opc2); } + +__extension__ static __inline void __attribute__ ((__always_inline__)) +__arm_ldc2 (const unsigned int __coproc, const unsigned int __CRd, + const void * __p) +{ + return __builtin_arm_ldc2 (__coproc, __CRd, __p); +} + +__extension__ static __inline void __attribute__ ((__always_inline__)) +__arm_ldc2l (const unsigned int __coproc, const unsigned int __CRd, + const void * __p) +{ + return __builtin_arm_ldc2l (__coproc, __CRd, __p); +} + +__extension__ static __inline void __attribute__ ((__always_inline__)) +__arm_stc2 (const unsigned int __coproc, const unsigned int __CRd, + void * __p) +{ + return __builtin_arm_stc2 (__coproc, __CRd, __p); +} + +__extension__ static __inline void __attribute__ ((__always_inline__)) +__arm_stc2l (const unsigned int __coproc, const unsigned int __CRd, + void * __p) +{ + return __builtin_arm_stc2l (__coproc, __CRd, __p); +} #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 03b5bf88ef2632bceedba1e64c0f83bc50337364..eb6168d98a897280aef2954372613487ca256fb0 100644 --- a/gcc/config/arm/arm_acle_builtins.def +++ b/gcc/config/arm/arm_acle_builtins.def @@ -26,3 +26,11 @@ VAR1 (UBINOP, crc32ch, si) VAR1 (UBINOP, crc32cw, si) VAR1 (CDP, cdp, void) VAR1 (CDP, cdp2, void) +VAR1 (LDC, ldc, void) +VAR1 (LDC, ldc2, void) +VAR1 (LDC, ldcl, void) +VAR1 (LDC, ldc2l, void) +VAR1 (STC, stc, void) +VAR1 (STC, stc2, void) +VAR1 (STC, stcl, void) +VAR1 (STC, stc2l, void) diff --git a/gcc/config/arm/constraints.md b/gcc/config/arm/constraints.md index ceea46ae9fa31fbab855e8250a410d3e6d8177bd..0bd87dd32af1de9a0be58640ec94e83a76ce092c 100644 --- a/gcc/config/arm/constraints.md +++ b/gcc/config/arm/constraints.md @@ -447,6 +447,12 @@ (match_code "symbol_ref") ) +(define_memory_constraint "Uz" + "@internal + A memory access that is accessible as an LDC/STC operand" + (and (match_code "mem") + (match_test "arm_coproc_ldc_stc_legitimate_address (op)"))) + ;; We used to have constraint letters for S and R in ARM state, but ;; all uses of these now appear to have been removed. diff --git a/gcc/config/arm/iterators.md b/gcc/config/arm/iterators.md index 86d6aa70e5766bc42a4209f14e929942ee63b773..ec74868a9b99c3a4bb379b82d3a77057ce238f03 100644 --- a/gcc/config/arm/iterators.md +++ b/gcc/config/arm/iterators.md @@ -948,3 +948,19 @@ (define_int_iterator CDPI [VUNSPEC_CDP VUNSPEC_CDP2]) (define_int_attr cdp [(VUNSPEC_CDP "cdp") (VUNSPEC_CDP2 "cdp2")]) (define_int_attr CDP [(VUNSPEC_CDP "CDP") (VUNSPEC_CDP2 "CDP2")]) + +;; An iterator for the LDC coprocessor instruction +(define_int_iterator LDCI [VUNSPEC_LDC VUNSPEC_LDC2 + VUNSPEC_LDCL VUNSPEC_LDC2L]) +(define_int_attr ldc [(VUNSPEC_LDC "ldc") (VUNSPEC_LDC2 "ldc2") + (VUNSPEC_LDCL "ldcl") (VUNSPEC_LDC2L "ldc2l")]) +(define_int_attr LDC [(VUNSPEC_LDC "LDC") (VUNSPEC_LDC2 "LDC2") + (VUNSPEC_LDCL "LDCL") (VUNSPEC_LDC2L "LDC2L")]) + +;; An iterator for the STC coprocessor instructions +(define_int_iterator STCI [VUNSPEC_STC VUNSPEC_STC2 + VUNSPEC_STCL VUNSPEC_STC2L]) +(define_int_attr stc [(VUNSPEC_STC "stc") (VUNSPEC_STC2 "stc2") + (VUNSPEC_STCL "stcl") (VUNSPEC_STC2L "stc2l")]) +(define_int_attr STC [(VUNSPEC_STC "STC") (VUNSPEC_STC2 "STC2") + (VUNSPEC_STCL "STCL") (VUNSPEC_STC2L "STC2L")]) diff --git a/gcc/config/arm/unspecs.md b/gcc/config/arm/unspecs.md index 01dd700a0af8043ce40ada939f9b0c34d846eded..2cc5eb8e1dbeafd156567c8e507e39d8057a99f1 100644 --- a/gcc/config/arm/unspecs.md +++ b/gcc/config/arm/unspecs.md @@ -152,6 +152,14 @@ VUNSPEC_PROBE_STACK_RANGE ; Represent stack range probing. VUNSPEC_CDP ; Represent the coprocessor cdp instruction. VUNSPEC_CDP2 ; Represent the coprocessor cdp2 instruction. + VUNSPEC_LDC ; Represent the coprocessor ldc instruction. + VUNSPEC_LDC2 ; Represent the coprocessor ldc2 instruction. + VUNSPEC_LDCL ; Represent the coprocessor ldcl instruction. + VUNSPEC_LDC2L ; Represent the coprocessor ldc2l instruction. + VUNSPEC_STC ; Represent the coprocessor stc instruction. + VUNSPEC_STC2 ; Represent the coprocessor stc2 instruction. + VUNSPEC_STCL ; Represent the coprocessor stcl instruction. + VUNSPEC_STC2L ; Represent the coprocessor stc2l instruction. ]) ;; Enumerators for NEON unspecs. diff --git a/gcc/testsuite/gcc.target/arm/acle/ldc.c b/gcc/testsuite/gcc.target/arm/acle/ldc.c new file mode 100644 index 0000000000000000000000000000000000000000..f45f25d8c973e6aff715fcf17fbd9d2fc1ac2edf --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/acle/ldc.c @@ -0,0 +1,18 @@ +/* Test the ldc ACLE intrinsic. */ + +/* { dg-do assemble } */ +/* { dg-options "-save-temps" } */ +/* { dg-require-effective-target arm_coproc1_ok } */ + +#include "arm_acle.h" + +extern void * p; + +void test_ldc (void) +{ + __arm_ldc (10, 1, p + 4); + __arm_ldc (11, 1, p + 1024); +} + +/* { dg-final { scan-assembler "ldc\tp10, CR1, \[r\[0-9\]+" } } */ +/* { dg-final { scan-assembler "ldc\tp11, CR1, \[r\[0-9\]+\]\n" } } */ diff --git a/gcc/testsuite/gcc.target/arm/acle/ldc2.c b/gcc/testsuite/gcc.target/arm/acle/ldc2.c new file mode 100644 index 0000000000000000000000000000000000000000..433bf8a12043c3876e8c961d86b64365faa4b30f --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/acle/ldc2.c @@ -0,0 +1,18 @@ +/* Test the ldc2 ACLE intrinsic. */ + +/* { dg-do assemble } */ +/* { dg-options "-save-temps" } */ +/* { dg-require-effective-target arm_coproc2_ok } */ + +#include "arm_acle.h" + +extern void * p; + +void test_ldc2 (void) +{ + __arm_ldc2 (10, 1, p - 120); + __arm_ldc2 (11, 1, p - 122); +} + +/* { dg-final { scan-assembler "ldc2\tp10, CR1, \[r\[0-9\]+" } } */ +/* { dg-final { scan-assembler "ldc2\tp11, CR1, \[r\[0-9\]+\]\n" } } */ diff --git a/gcc/testsuite/gcc.target/arm/acle/ldc2l.c b/gcc/testsuite/gcc.target/arm/acle/ldc2l.c new file mode 100644 index 0000000000000000000000000000000000000000..88c8aa447656d64c0890101005708675c8f02b38 --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/acle/ldc2l.c @@ -0,0 +1,18 @@ +/* Test the ldc2l ACLE intrinsic. */ + +/* { dg-do assemble } */ +/* { dg-options "-save-temps" } */ +/* { dg-require-effective-target arm_coproc2_ok } */ + +#include "arm_acle.h" + +extern void * p; + +void test_ldc2l (void) +{ + __arm_ldc2l (10, 1, p - 120); + __arm_ldc2l (11, 1, p - 122); +} + +/* { dg-final { scan-assembler "ldc2l\tp10, CR1, \[r\[0-9\]+" } } */ +/* { dg-final { scan-assembler "ldc2l\tp11, CR1, \[r\[0-9\]+\]\n" } } */ diff --git a/gcc/testsuite/gcc.target/arm/acle/ldcl.c b/gcc/testsuite/gcc.target/arm/acle/ldcl.c new file mode 100644 index 0000000000000000000000000000000000000000..72a97f1d7b7d1a1aea99af638240ad50b708e137 --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/acle/ldcl.c @@ -0,0 +1,18 @@ +/* Test the ldcl ACLE intrinsic. */ + +/* { dg-do assemble } */ +/* { dg-options "-save-temps" } */ +/* { dg-require-effective-target arm_coproc1_ok } */ + +#include "arm_acle.h" + +extern void * p; + +void test_ldcl (void) +{ + __arm_ldcl (10, 1, p + 4); + __arm_ldcl (11, 1, p + 1024); +} + +/* { dg-final { scan-assembler "ldcl\tp10, CR1, \[r\[0-9\]+" } } */ +/* { dg-final { scan-assembler "ldcl\tp11, CR1, \[r\[0-9\]+\]\n" } } */ diff --git a/gcc/testsuite/gcc.target/arm/acle/stc.c b/gcc/testsuite/gcc.target/arm/acle/stc.c new file mode 100644 index 0000000000000000000000000000000000000000..7c6e04fe0fe5cd63a259566c34d976657ae03509 --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/acle/stc.c @@ -0,0 +1,18 @@ +/* Test the stc ACLE intrinsic. */ + +/* { dg-do assemble } */ +/* { dg-options "-save-temps" } */ +/* { dg-require-effective-target arm_coproc1_ok } */ + +#include "arm_acle.h" + +extern void * p; + +void test_stc (void) +{ + __arm_stc (10, 1, p + 4); + __arm_stc (11, 1, p + 1024); +} + +/* { dg-final { scan-assembler "stc\tp10, CR1, \[r\[0-9\]+" } } */ +/* { dg-final { scan-assembler "stc\tp11, CR1, \[r\[0-9\]+\]\n" } } */ diff --git a/gcc/testsuite/gcc.target/arm/acle/stc2.c b/gcc/testsuite/gcc.target/arm/acle/stc2.c new file mode 100644 index 0000000000000000000000000000000000000000..1578f7b113676c9d5692c7e5b48b910f091ca29c --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/acle/stc2.c @@ -0,0 +1,18 @@ +/* Test the stc2 ACLE intrinsic. */ + +/* { dg-do assemble } */ +/* { dg-options "-save-temps" } */ +/* { dg-require-effective-target arm_coproc2_ok } */ + +#include "arm_acle.h" + +extern void * p; + +void test_stc2 (void) +{ + __arm_stc2 (10, 1, p - 120); + __arm_stc2 (11, 1, p - 122); +} + +/* { dg-final { scan-assembler "stc2\tp10, CR1, \[r\[0-9\]+" } } */ +/* { dg-final { scan-assembler "stc2\tp11, CR1, \[r\[0-9\]+\]\n" } } */ diff --git a/gcc/testsuite/gcc.target/arm/acle/stc2l.c b/gcc/testsuite/gcc.target/arm/acle/stc2l.c new file mode 100644 index 0000000000000000000000000000000000000000..7adbd60d48ac3f5a0f77dce98a3d3ba931ec58e3 --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/acle/stc2l.c @@ -0,0 +1,18 @@ +/* Test the stc2l ACLE intrinsic. */ + +/* { dg-do assemble } */ +/* { dg-options "-save-temps" } */ +/* { dg-require-effective-target arm_coproc2_ok } */ + +#include "arm_acle.h" + +extern void * p; + +void test_stc2l (void) +{ + __arm_stc2l (10, 1, p - 120); + __arm_stc2l (11, 1, p - 122); +} + +/* { dg-final { scan-assembler "stc2l\tp10, CR1, \[r\[0-9\]+" } } */ +/* { dg-final { scan-assembler "stc2l\tp11, CR1, \[r\[0-9\]+\]\n" } } */ diff --git a/gcc/testsuite/gcc.target/arm/acle/stcl.c b/gcc/testsuite/gcc.target/arm/acle/stcl.c new file mode 100644 index 0000000000000000000000000000000000000000..2fd5edd02d7e83efdcfaa2203ef1be9f612e414e --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/acle/stcl.c @@ -0,0 +1,18 @@ +/* Test the stcl ACLE intrinsic. */ + +/* { dg-do assemble } */ +/* { dg-options "-save-temps" } */ +/* { dg-require-effective-target arm_coproc1_ok } */ + +#include "arm_acle.h" + +extern void * p; + +void test_stcl (void) +{ + __arm_stcl (14, 10, p + 4); + __arm_stcl (10, 10, p + 1024); +} + +/* { dg-final { scan-assembler "stcl\tp14, CR10, \[r\[0-9\]+" } } */ +/* { dg-final { scan-assembler "stcl\tp10, CR10, \[r\[0-9\]+\]\n" } } */