diff mbox

[6/6,ARM] Implement support for ACLE Coprocessor MCRR and MRRC intrinsics

Message ID 586FB082.5010903@arm.com
State New
Headers show

Commit Message

Andre Vieira (lists) Jan. 6, 2017, 2:58 p.m. UTC
On 05/01/17 11:11, 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 MCR and MRC
>> intrinsics. See below a table mapping the intrinsics to their respective
>> instructions:
>>
>> +-------------------------------------------------------------------+---------------------------------------+
>>
>> | Intrinsic signature                                               |
>> Instruction pattern                   |
>> +-------------------------------------------------------------------+---------------------------------------+
>>
>> |void __arm_mcrr(coproc, opc1, uint64_t value, CRm)                 |
>> MCRR coproc, opc1, Rt, Rt2, CRm       |
>> +-------------------------------------------------------------------+---------------------------------------+
>>
>> |void __arm_mcrr2(coproc, opc1, uint64_t value, CRm)                |
>> MCRR2 coproc, opc1, Rt, Rt2, CRm      |
>> +-------------------------------------------------------------------+---------------------------------------+
>>
>> |uint64_t __arm_mrrc(coproc, opc1, CRm)                             |
>> MRRC coproc, opc1, Rt, Rt2, CRm       |
>> +-------------------------------------------------------------------+---------------------------------------+
>>
>> |uint64_t __arm_mrrc2(coproc, opc1, CRm)                            |
>> MRRC2 coproc, opc1, Rt, Rt2, CRm      |
>> +-------------------------------------------------------------------+---------------------------------------+
>>
>> 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]. If either of
>> these requirements are not met a diagnostic is issued.
>>
>> I added a new arm_arch variable for ARMv5TE to use when deciding whether
>> or not the MCRR and MRCC intrinsics are available.
>>
>> Is this OK for trunk?
> 
> Same as with the previous two patches the define_insns need constraints
> and also I believe you'll want to rebase this patch on top of Richard's
> rework of the
> architecture feature bits for the ARMv5TE hunk.
> 
> Thanks,
> Kyrill
> 
>> Regards,
>> Andre
>>
>> gcc/ChangeLog:
>> 2016-11-09  Andre Vieira  <andre.simoesdiasvieira@arm.com>
>>
>>    * config/arm/arm.md (<mcrr>): New.
>>    (<mrrc>): New.
>>    * config/arm/arm.c (arm_arch5te): New.
>>    (arm_option_override): Set arm_arch5te.
>>    (arm_coproc_builtin_available): Add support for mcrr, mcrr2, mrrc
>>    and mrrc2.
>>    * config/arm/arm-builtins.c (MCRR_QUALIFIERS): Define to...
>>    (arm_mcrr_qualifiers): ... this. New.
>>    (MRRC_QUALIFIERS): Define to...
>>    (arm_mrrc_qualifiers): ... this. New.
>>    * config/arm/arm_acle.h (__arm_mcrr, __arm_mcrr2, __arm_mrrc,
>>    __arm_mrrc2): New.
>>    * config/arm/arm_acle_builtins.def (mcrr, mcrr2, mrrc, mrrc2): New.
>>    * config/arm/iterators.md (MCRRI, mcrr, MCRR): New.
>>    (MRRCI, mrrc, MRRC): New.
>>    * config/arm/unspecs.md (VUNSPEC_MCRR, VUNSPEC_MCRR2, VUNSPEC_MRRC,
>>    VUNSPEC_MRRC2): New.
>>
>> gcc/testsuite/ChangeLog:
>>
>> 2016-11-09  Andre Vieira  <andre.simoesdiasvieira@arm.com>
>>
>>    * gcc.target/arm/acle/mcrr: New.
>>    * gcc.target/arm/acle/mcrr2: New.
>>    * gcc.target/arm/acle/mrrc: New.
>>    * gcc.target/arm/acle/mrrc2: New.
>>
> 
Hi,

Reworked this patch according to comments, rebased and fixed the
availability of MCRR2/MRRC2 to only be available for ARMv6 and later.

Is this OK for trunk?

Regards,
Andre

gcc/ChangeLog:
2017-01-xx  Andre Vieira  <andre.simoesdiasvieira@arm.com>

  * config/arm/arm.md (<mcrr>): New.
  (<mrrc>): New.
  * config/arm/arm.c (arm_arch5te): New.
  (arm_option_override): Set arm_arch5te.
  (arm_coproc_builtin_available): Add support for mcrr, mcrr2, mrrc
  and mrrc2.
  * config/arm/arm-builtins.c (MCRR_QUALIFIERS): Define to...
  (arm_mcrr_qualifiers): ... this. New.
  (MRRC_QUALIFIERS): Define to...
  (arm_mrrc_qualifiers): ... this. New.
  * config/arm/arm_acle.h (__arm_mcrr, __arm_mcrr2, __arm_mrrc,
  __arm_mrrc2): New.
  * config/arm/arm_acle_builtins.def (mcrr, mcrr2, mrrc, mrrc2): New.
  * config/arm/iterators.md (MCRRI, mcrr, MCRR): New.
  (MRRCI, mrrc, MRRC): New.
  * config/arm/unspecs.md (VUNSPEC_MCRR, VUNSPEC_MCRR2, VUNSPEC_MRRC,
  VUNSPEC_MRRC2): New.

gcc/testsuite/ChangeLog:

2017-01-xx  Andre Vieira  <andre.simoesdiasvieira@arm.com>

  * gcc.target/arm/acle/mcrr: New.
  * gcc.target/arm/acle/mcrr2: New.
  * gcc.target/arm/acle/mrrc: New.
  * gcc.target/arm/acle/mrrc2: New.

Comments

Kyrill Tkachov Jan. 6, 2017, 3:15 p.m. UTC | #1
On 06/01/17 14:58, Andre Vieira (lists) wrote:
> On 05/01/17 11:11, 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 MCR and MRC
>>> intrinsics. See below a table mapping the intrinsics to their respective
>>> instructions:
>>>
>>> +-------------------------------------------------------------------+---------------------------------------+
>>>
>>> | Intrinsic signature                                               |
>>> Instruction pattern                   |
>>> +-------------------------------------------------------------------+---------------------------------------+
>>>
>>> |void __arm_mcrr(coproc, opc1, uint64_t value, CRm)                 |
>>> MCRR coproc, opc1, Rt, Rt2, CRm       |
>>> +-------------------------------------------------------------------+---------------------------------------+
>>>
>>> |void __arm_mcrr2(coproc, opc1, uint64_t value, CRm)                |
>>> MCRR2 coproc, opc1, Rt, Rt2, CRm      |
>>> +-------------------------------------------------------------------+---------------------------------------+
>>>
>>> |uint64_t __arm_mrrc(coproc, opc1, CRm)                             |
>>> MRRC coproc, opc1, Rt, Rt2, CRm       |
>>> +-------------------------------------------------------------------+---------------------------------------+
>>>
>>> |uint64_t __arm_mrrc2(coproc, opc1, CRm)                            |
>>> MRRC2 coproc, opc1, Rt, Rt2, CRm      |
>>> +-------------------------------------------------------------------+---------------------------------------+
>>>
>>> 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]. If either of
>>> these requirements are not met a diagnostic is issued.
>>>
>>> I added a new arm_arch variable for ARMv5TE to use when deciding whether
>>> or not the MCRR and MRCC intrinsics are available.
>>>
>>> Is this OK for trunk?
>> Same as with the previous two patches the define_insns need constraints
>> and also I believe you'll want to rebase this patch on top of Richard's
>> rework of the
>> architecture feature bits for the ARMv5TE hunk.
>>
>> Thanks,
>> Kyrill
>>
>>> Regards,
>>> Andre
>>>
>>> gcc/ChangeLog:
>>> 2016-11-09  Andre Vieira  <andre.simoesdiasvieira@arm.com>
>>>
>>>     * config/arm/arm.md (<mcrr>): New.
>>>     (<mrrc>): New.
>>>     * config/arm/arm.c (arm_arch5te): New.
>>>     (arm_option_override): Set arm_arch5te.
>>>     (arm_coproc_builtin_available): Add support for mcrr, mcrr2, mrrc
>>>     and mrrc2.
>>>     * config/arm/arm-builtins.c (MCRR_QUALIFIERS): Define to...
>>>     (arm_mcrr_qualifiers): ... this. New.
>>>     (MRRC_QUALIFIERS): Define to...
>>>     (arm_mrrc_qualifiers): ... this. New.
>>>     * config/arm/arm_acle.h (__arm_mcrr, __arm_mcrr2, __arm_mrrc,
>>>     __arm_mrrc2): New.
>>>     * config/arm/arm_acle_builtins.def (mcrr, mcrr2, mrrc, mrrc2): New.
>>>     * config/arm/iterators.md (MCRRI, mcrr, MCRR): New.
>>>     (MRRCI, mrrc, MRRC): New.
>>>     * config/arm/unspecs.md (VUNSPEC_MCRR, VUNSPEC_MCRR2, VUNSPEC_MRRC,
>>>     VUNSPEC_MRRC2): New.
>>>
>>> gcc/testsuite/ChangeLog:
>>>
>>> 2016-11-09  Andre Vieira  <andre.simoesdiasvieira@arm.com>
>>>
>>>     * gcc.target/arm/acle/mcrr: New.
>>>     * gcc.target/arm/acle/mcrr2: New.
>>>     * gcc.target/arm/acle/mrrc: New.
>>>     * gcc.target/arm/acle/mrrc2: New.
>>>
> Hi,
>
> Reworked this patch according to comments, rebased and fixed the
> availability of MCRR2/MRRC2 to only be available for ARMv6 and later.
>
> Is this OK for trunk?

Ok.
Thanks,
Kyrill

> Regards,
> Andre
>
> gcc/ChangeLog:
> 2017-01-xx  Andre Vieira  <andre.simoesdiasvieira@arm.com>
>
>    * config/arm/arm.md (<mcrr>): New.
>    (<mrrc>): New.
>    * config/arm/arm.c (arm_arch5te): New.
>    (arm_option_override): Set arm_arch5te.
>    (arm_coproc_builtin_available): Add support for mcrr, mcrr2, mrrc
>    and mrrc2.
>    * config/arm/arm-builtins.c (MCRR_QUALIFIERS): Define to...
>    (arm_mcrr_qualifiers): ... this. New.
>    (MRRC_QUALIFIERS): Define to...
>    (arm_mrrc_qualifiers): ... this. New.
>    * config/arm/arm_acle.h (__arm_mcrr, __arm_mcrr2, __arm_mrrc,
>    __arm_mrrc2): New.
>    * config/arm/arm_acle_builtins.def (mcrr, mcrr2, mrrc, mrrc2): New.
>    * config/arm/iterators.md (MCRRI, mcrr, MCRR): New.
>    (MRRCI, mrrc, MRRC): New.
>    * config/arm/unspecs.md (VUNSPEC_MCRR, VUNSPEC_MCRR2, VUNSPEC_MRRC,
>    VUNSPEC_MRRC2): New.
>
> gcc/testsuite/ChangeLog:
>
> 2017-01-xx  Andre Vieira  <andre.simoesdiasvieira@arm.com>
>
>    * gcc.target/arm/acle/mcrr: New.
>    * gcc.target/arm/acle/mcrr2: New.
>    * gcc.target/arm/acle/mrrc: New.
>    * gcc.target/arm/acle/mrrc2: New.
Kyrill Tkachov Jan. 9, 2017, 10:25 a.m. UTC | #2
Hi Andre,

On 06/01/17 15:15, Kyrill Tkachov wrote:
>
> On 06/01/17 14:58, Andre Vieira (lists) wrote:
>> On 05/01/17 11:11, 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 MCR and MRC
>>>> intrinsics. See below a table mapping the intrinsics to their respective
>>>> instructions:
>>>>
>>>> +-------------------------------------------------------------------+---------------------------------------+
>>>>
>>>> | Intrinsic signature                                               |
>>>> Instruction pattern                   |
>>>> +-------------------------------------------------------------------+---------------------------------------+
>>>>
>>>> |void __arm_mcrr(coproc, opc1, uint64_t value, CRm)                 |
>>>> MCRR coproc, opc1, Rt, Rt2, CRm       |
>>>> +-------------------------------------------------------------------+---------------------------------------+
>>>>
>>>> |void __arm_mcrr2(coproc, opc1, uint64_t value, CRm)                |
>>>> MCRR2 coproc, opc1, Rt, Rt2, CRm      |
>>>> +-------------------------------------------------------------------+---------------------------------------+
>>>>
>>>> |uint64_t __arm_mrrc(coproc, opc1, CRm)                             |
>>>> MRRC coproc, opc1, Rt, Rt2, CRm       |
>>>> +-------------------------------------------------------------------+---------------------------------------+
>>>>
>>>> |uint64_t __arm_mrrc2(coproc, opc1, CRm)                            |
>>>> MRRC2 coproc, opc1, Rt, Rt2, CRm      |
>>>> +-------------------------------------------------------------------+---------------------------------------+
>>>>
>>>> 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]. If either of
>>>> these requirements are not met a diagnostic is issued.
>>>>
>>>> I added a new arm_arch variable for ARMv5TE to use when deciding whether
>>>> or not the MCRR and MRCC intrinsics are available.
>>>>
>>>> Is this OK for trunk?
>>> Same as with the previous two patches the define_insns need constraints
>>> and also I believe you'll want to rebase this patch on top of Richard's
>>> rework of the
>>> architecture feature bits for the ARMv5TE hunk.
>>>
>>> Thanks,
>>> Kyrill
>>>
>>>> Regards,
>>>> Andre
>>>>
>>>> gcc/ChangeLog:
>>>> 2016-11-09  Andre Vieira <andre.simoesdiasvieira@arm.com>
>>>>
>>>>     * config/arm/arm.md (<mcrr>): New.
>>>>     (<mrrc>): New.
>>>>     * config/arm/arm.c (arm_arch5te): New.
>>>>     (arm_option_override): Set arm_arch5te.
>>>>     (arm_coproc_builtin_available): Add support for mcrr, mcrr2, mrrc
>>>>     and mrrc2.
>>>>     * config/arm/arm-builtins.c (MCRR_QUALIFIERS): Define to...
>>>>     (arm_mcrr_qualifiers): ... this. New.
>>>>     (MRRC_QUALIFIERS): Define to...
>>>>     (arm_mrrc_qualifiers): ... this. New.
>>>>     * config/arm/arm_acle.h (__arm_mcrr, __arm_mcrr2, __arm_mrrc,
>>>>     __arm_mrrc2): New.
>>>>     * config/arm/arm_acle_builtins.def (mcrr, mcrr2, mrrc, mrrc2): New.
>>>>     * config/arm/iterators.md (MCRRI, mcrr, MCRR): New.
>>>>     (MRRCI, mrrc, MRRC): New.
>>>>     * config/arm/unspecs.md (VUNSPEC_MCRR, VUNSPEC_MCRR2, VUNSPEC_MRRC,
>>>>     VUNSPEC_MRRC2): New.
>>>>
>>>> gcc/testsuite/ChangeLog:
>>>>
>>>> 2016-11-09  Andre Vieira <andre.simoesdiasvieira@arm.com>
>>>>
>>>>     * gcc.target/arm/acle/mcrr: New.
>>>>     * gcc.target/arm/acle/mcrr2: New.
>>>>     * gcc.target/arm/acle/mrrc: New.
>>>>     * gcc.target/arm/acle/mrrc2: New.
>>>>
>> Hi,
>>
>> Reworked this patch according to comments, rebased and fixed the
>> availability of MCRR2/MRRC2 to only be available for ARMv6 and later.
>>
>> Is this OK for trunk?
>
> Ok.
> Thanks,
> Kyrill
>

Also, can you please propose a patch for the GCC 7 changes page mentioning this work?

Thanks,
Kyrill


>> Regards,
>> Andre
>>
>> gcc/ChangeLog:
>> 2017-01-xx  Andre Vieira  <andre.simoesdiasvieira@arm.com>
>>
>>    * config/arm/arm.md (<mcrr>): New.
>>    (<mrrc>): New.
>>    * config/arm/arm.c (arm_arch5te): New.
>>    (arm_option_override): Set arm_arch5te.
>>    (arm_coproc_builtin_available): Add support for mcrr, mcrr2, mrrc
>>    and mrrc2.
>>    * config/arm/arm-builtins.c (MCRR_QUALIFIERS): Define to...
>>    (arm_mcrr_qualifiers): ... this. New.
>>    (MRRC_QUALIFIERS): Define to...
>>    (arm_mrrc_qualifiers): ... this. New.
>>    * config/arm/arm_acle.h (__arm_mcrr, __arm_mcrr2, __arm_mrrc,
>>    __arm_mrrc2): New.
>>    * config/arm/arm_acle_builtins.def (mcrr, mcrr2, mrrc, mrrc2): New.
>>    * config/arm/iterators.md (MCRRI, mcrr, MCRR): New.
>>    (MRRCI, mrrc, MRRC): New.
>>    * config/arm/unspecs.md (VUNSPEC_MCRR, VUNSPEC_MCRR2, VUNSPEC_MRRC,
>>    VUNSPEC_MRRC2): New.
>>
>> gcc/testsuite/ChangeLog:
>>
>> 2017-01-xx  Andre Vieira  <andre.simoesdiasvieira@arm.com>
>>
>>    * gcc.target/arm/acle/mcrr: New.
>>    * gcc.target/arm/acle/mcrr2: New.
>>    * gcc.target/arm/acle/mrrc: New.
>>    * gcc.target/arm/acle/mrrc2: New.
>
diff mbox

Patch

diff --git a/gcc/config/arm/arm-builtins.c b/gcc/config/arm/arm-builtins.c
index 1a983b27961e96cfab651244af3ba1fb44b87d2e..689219c1923bc0f720f70870bfde8b60f7514167 100644
--- a/gcc/config/arm/arm-builtins.c
+++ b/gcc/config/arm/arm-builtins.c
@@ -217,6 +217,24 @@  arm_mrc_qualifiers[SIMD_MAX_BUILTIN_ARGS]
       qualifier_unsigned_immediate, qualifier_unsigned_immediate };
 #define MRC_QUALIFIERS \
   (arm_mrc_qualifiers)
+
+/* void (unsigned immediate, unsigned immediate,  T, unsigned immediate).  */
+static enum arm_type_qualifiers
+arm_mcrr_qualifiers[SIMD_MAX_BUILTIN_ARGS]
+  = { qualifier_void, qualifier_unsigned_immediate,
+      qualifier_unsigned_immediate, qualifier_none,
+      qualifier_unsigned_immediate };
+#define MCRR_QUALIFIERS \
+  (arm_mcrr_qualifiers)
+
+/* T (unsigned immediate, unsigned immediate, unsigned immediate).  */
+static enum arm_type_qualifiers
+arm_mrrc_qualifiers[SIMD_MAX_BUILTIN_ARGS]
+  = { qualifier_none, qualifier_unsigned_immediate,
+      qualifier_unsigned_immediate, qualifier_unsigned_immediate };
+#define MRRC_QUALIFIERS \
+  (arm_mrrc_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 e376ab3f4bfc0d4c47e99e1f7f681960f7609f17..ccdf1ab80242b996d5770a5b4da2c669491c00aa 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -814,6 +814,9 @@  int arm_arch5 = 0;
 /* Nonzero if this chip supports the ARM Architecture 5E extensions.  */
 int arm_arch5e = 0;
 
+/* Nonzero if this chip supports the ARM Architecture 5TE extensions.  */
+int arm_arch5te = 0;
+
 /* Nonzero if this chip supports the ARM Architecture 6 extensions.  */
 int arm_arch6 = 0;
 
@@ -3372,6 +3375,8 @@  arm_option_override (void)
   arm_arch4t = arm_arch4 && bitmap_bit_p (arm_active_target.isa, isa_bit_thumb);
   arm_arch5 = bitmap_bit_p (arm_active_target.isa, isa_bit_ARMv5);
   arm_arch5e = bitmap_bit_p (arm_active_target.isa, isa_bit_ARMv5e);
+  arm_arch5te = arm_arch5e
+    && bitmap_bit_p (arm_active_target.isa, isa_bit_thumb);
   arm_arch6 = bitmap_bit_p (arm_active_target.isa, isa_bit_ARMv6);
   arm_arch6k = bitmap_bit_p (arm_active_target.isa, isa_bit_ARMv6k);
   arm_arch_notm = bitmap_bit_p (arm_active_target.isa, isa_bit_notm);
@@ -30925,6 +30930,18 @@  arm_coproc_builtin_available (enum unspecv builtin)
 	if (arm_arch5)
 	  return true;
 	break;
+      case VUNSPEC_MCRR:
+      case VUNSPEC_MRRC:
+	/* Only present in ARMv5TE, ARMv6 (but not ARMv6-M), ARMv7* and
+	   ARMv8-{A,M}.  */
+	if (arm_arch6 || arm_arch5te)
+	  return true;
+	break;
+      case VUNSPEC_MCRR2:
+      case VUNSPEC_MRRC2:
+	if (arm_arch6)
+	  return true;
+	break;
       default:
 	gcc_unreachable ();
     }
diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md
index 15926f13bac7beb55f8942cf4c1923cf875a782f..446fb226f6a48755786da73f621ef8d433d001cb 100644
--- a/gcc/config/arm/arm.md
+++ b/gcc/config/arm/arm.md
@@ -12016,6 +12016,37 @@ 
   [(set_attr "length" "4")
    (set_attr "type" "coproc")])
 
+(define_insn "<mcrr>"
+  [(unspec_volatile [(match_operand:SI 0 "immediate_operand" "n")
+		     (match_operand:SI 1 "immediate_operand" "n")
+		     (match_operand:DI 2 "s_register_operand" "r")
+		     (match_operand:SI 3 "immediate_operand" "n")] MCRRI)
+   (use (match_dup 2))]
+  "arm_coproc_builtin_available (VUNSPEC_<MCRR>)"
+{
+  arm_const_bounds (operands[0], 0, 16);
+  arm_const_bounds (operands[1], 0, 8);
+  arm_const_bounds (operands[3], 0, (1 << 5));
+  return "<mcrr>\\tp%c0, %1, %Q2, %R2, CR%c3";
+}
+  [(set_attr "length" "4")
+   (set_attr "type" "coproc")])
+
+(define_insn "<mrrc>"
+  [(set (match_operand:DI 0 "s_register_operand" "=r")
+	(unspec_volatile [(match_operand:SI 1 "immediate_operand" "n")
+			  (match_operand:SI 2 "immediate_operand" "n")
+			  (match_operand:SI 3 "immediate_operand" "n")] MRRCI))]
+  "arm_coproc_builtin_available (VUNSPEC_<MRRC>)"
+{
+  arm_const_bounds (operands[1], 0, 16);
+  arm_const_bounds (operands[2], 0, 8);
+  arm_const_bounds (operands[3], 0, (1 << 5));
+  return "<mrrc>\\tp%c1, %2, %Q0, %R0, CR%c3";
+}
+  [(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 a218547bac9ec761487a260bca71a8fe195bc08e..972e28edb86c1f137e16982acc6f346e0eac04fb 100644
--- a/gcc/config/arm/arm_acle.h
+++ b/gcc/config/arm/arm_acle.h
@@ -136,6 +136,40 @@  __arm_mrc2 (const unsigned int __coproc, const unsigned int __opc1,
 {
   return __builtin_arm_mrc2 (__coproc, __opc1, __CRn, __CRm, __opc2);
 }
+
+#if __ARM_ARCH >= 6 ||  defined (__ARM_ARCH_5TE__)
+
+__extension__ static __inline void __attribute__ ((__always_inline__))
+__arm_mcrr (const unsigned int __coproc, const unsigned int __opc1,
+	    uint64_t __value, const unsigned int __CRm)
+{
+  return __builtin_arm_mcrr (__coproc, __opc1, __value, __CRm);
+}
+
+__extension__ static __inline uint64_t __attribute__ ((__always_inline__))
+__arm_mrrc (const unsigned int __coproc, const unsigned int __opc1,
+	    const unsigned int __CRm)
+{
+  return __builtin_arm_mrrc (__coproc, __opc1, __CRm);
+}
+
+#if __ARM_ARCH >= 6
+
+__extension__ static __inline void __attribute__ ((__always_inline__))
+__arm_mcrr2 (const unsigned int __coproc, const unsigned int __opc1,
+	    uint64_t __value, const unsigned int __CRm)
+{
+  return __builtin_arm_mcrr2 (__coproc, __opc1, __value, __CRm);
+}
+
+__extension__ static __inline uint64_t __attribute__ ((__always_inline__))
+__arm_mrrc2 (const unsigned int __coproc, const unsigned int __opc1,
+	     const unsigned int __CRm)
+{
+  return __builtin_arm_mrrc2 (__coproc, __opc1,  __CRm);
+}
+#endif /* __ARM_ARCH >= 6.  */
+#endif /* __ARM_ARCH >= 6 ||  defined (__ARM_ARCH_5TE__).  */
 #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 d258f8a3748f6b4f0aeb3d4a28c6d4d79597f69c..bd1f66272c9c9832a74081838ee81be26bd8ee50 100644
--- a/gcc/config/arm/arm_acle_builtins.def
+++ b/gcc/config/arm/arm_acle_builtins.def
@@ -38,3 +38,7 @@  VAR1 (MCR, mcr, void)
 VAR1 (MCR, mcr2, void)
 VAR1 (MRC, mrc, si)
 VAR1 (MRC, mrc2, si)
+VAR1 (MCRR, mcrr, void)
+VAR1 (MCRR, mcrr2, void)
+VAR1 (MRRC, mrrc, di)
+VAR1 (MRRC, mrrc2, di)
diff --git a/gcc/config/arm/iterators.md b/gcc/config/arm/iterators.md
index d34a705cd428821c0e2a48a4df428c0aeb61cdda..e2e588688eb04c158d1c146bca12d84cfb5ff130 100644
--- a/gcc/config/arm/iterators.md
+++ b/gcc/config/arm/iterators.md
@@ -976,3 +976,15 @@ 
 
 (define_int_attr mrc [(VUNSPEC_MRC "mrc") (VUNSPEC_MRC2 "mrc2")])
 (define_int_attr MRC [(VUNSPEC_MRC "MRC") (VUNSPEC_MRC2 "MRC2")])
+
+;; An iterator for the MCRR coprocessor instructions
+(define_int_iterator MCRRI [VUNSPEC_MCRR VUNSPEC_MCRR2])
+
+(define_int_attr mcrr [(VUNSPEC_MCRR "mcrr") (VUNSPEC_MCRR2 "mcrr2")])
+(define_int_attr MCRR [(VUNSPEC_MCRR "MCRR") (VUNSPEC_MCRR2 "MCRR2")])
+
+;; An iterator for the MRRC coprocessor instructions
+(define_int_iterator MRRCI [VUNSPEC_MRRC VUNSPEC_MRRC2])
+
+(define_int_attr mrrc [(VUNSPEC_MRRC "mrrc") (VUNSPEC_MRRC2 "mrrc2")])
+(define_int_attr MRRC [(VUNSPEC_MRRC "MRRC") (VUNSPEC_MRRC2 "MRRC2")])
diff --git a/gcc/config/arm/unspecs.md b/gcc/config/arm/unspecs.md
index 6bde96e357917a9c1c2eb4d292bc71797232df29..99cfa41b08dad24a85e78f069331e83c03c8bce1 100644
--- a/gcc/config/arm/unspecs.md
+++ b/gcc/config/arm/unspecs.md
@@ -164,6 +164,10 @@ 
   VUNSPEC_MCR2		; Represent the coprocessor mcr2 instruction.
   VUNSPEC_MRC		; Represent the coprocessor mrc instruction.
   VUNSPEC_MRC2		; Represent the coprocessor mrc2 instruction.
+  VUNSPEC_MCRR		; Represent the coprocessor mcrr instruction.
+  VUNSPEC_MCRR2		; Represent the coprocessor mcrr2 instruction.
+  VUNSPEC_MRRC		; Represent the coprocessor mrrc instruction.
+  VUNSPEC_MRRC2		; Represent the coprocessor mrrc2 instruction.
 ])
 
 ;; Enumerators for NEON unspecs.
diff --git a/gcc/testsuite/gcc.target/arm/acle/mcrr.c b/gcc/testsuite/gcc.target/arm/acle/mcrr.c
new file mode 100644
index 0000000000000000000000000000000000000000..dcc223c713d8aabb1d51c1d3bb3a7ed817a4be30
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/acle/mcrr.c
@@ -0,0 +1,16 @@ 
+/* Test the mcrr ACLE intrinsic.  */
+
+/* { dg-do assemble } */
+/* { dg-options "-save-temps" } */
+/* { dg-require-effective-target arm_coproc3_ok } */
+
+#include "arm_acle.h"
+
+void test_mcrr (uint64_t a)
+{
+  a += 77;
+  __arm_mcrr (10, 5, a, 3);
+}
+
+/* { dg-final { scan-assembler "add\[^\n\]*#77\n" } } */
+/* { dg-final { scan-assembler "mcrr\tp10, #5, r\[r0-9\]*, r\[r0-9\]*, CR3\n" } } */
diff --git a/gcc/testsuite/gcc.target/arm/acle/mcrr2.c b/gcc/testsuite/gcc.target/arm/acle/mcrr2.c
new file mode 100644
index 0000000000000000000000000000000000000000..10f2014d4474c0d78862894023dd8672a80a9189
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/acle/mcrr2.c
@@ -0,0 +1,16 @@ 
+/* Test the mcrr2 ACLE intrinsic.  */
+
+/* { dg-do assemble } */
+/* { dg-options "-save-temps" } */
+/* { dg-require-effective-target arm_coproc4_ok } */
+
+#include "arm_acle.h"
+
+void test_mcrr2 (uint64_t a)
+{
+  a += 77;
+  __arm_mcrr2 (10, 5, a, 3);
+}
+
+/* { dg-final { scan-assembler "add\[^\n\]*#77\n" } } */
+/* { dg-final { scan-assembler "mcrr2\tp10, #5, r\[r0-9\]*, r\[r0-9\]*, CR3\n" } } */
diff --git a/gcc/testsuite/gcc.target/arm/acle/mrrc.c b/gcc/testsuite/gcc.target/arm/acle/mrrc.c
new file mode 100644
index 0000000000000000000000000000000000000000..28c3b8ea6b53f7e8cf95d86d4d0eda367fca2041
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/acle/mrrc.c
@@ -0,0 +1,14 @@ 
+/* Test the mrrc ACLE intrinsic.  */
+
+/* { dg-do assemble } */
+/* { dg-options "-save-temps" } */
+/* { dg-require-effective-target arm_coproc3_ok } */
+
+#include "arm_acle.h"
+
+uint64_t test_mrrc (void)
+{
+  return __arm_mrrc (10, 5, 3);
+}
+
+/* { dg-final { scan-assembler "mrrc\tp10, #5, r\[r0-9\]*, r\[r0-9\]*, CR3\n" } } */
diff --git a/gcc/testsuite/gcc.target/arm/acle/mrrc2.c b/gcc/testsuite/gcc.target/arm/acle/mrrc2.c
new file mode 100644
index 0000000000000000000000000000000000000000..5b7aab06222e07bf37a46edb02b189ed5b796388
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/acle/mrrc2.c
@@ -0,0 +1,14 @@ 
+/* Test the mrrc2 ACLE intrinsic.  */
+
+/* { dg-do assemble } */
+/* { dg-options "-save-temps" } */
+/* { dg-require-effective-target arm_coproc4_ok } */
+
+#include "arm_acle.h"
+
+uint64_t test_mrrc2 (void)
+{
+  return __arm_mrrc2 (10, 5, 3);
+}
+
+/* { dg-final { scan-assembler "mrrc2\tp10, #5, r\[r0-9\]*, r\[r0-9\]*, CR3\n" } } */