aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKyrylo Tkachov <kyrylo.tkachov@arm.com>2013-12-19 17:55:38 +0000
committerKyrylo Tkachov <ktkachov@gcc.gnu.org>2013-12-19 17:55:38 +0000
commit582e2e430089a54069f3e38eb8a2bacd36c42af5 (patch)
tree5dbc4d790863ae940c88cbba1311205ba3131028
parentcd494e4d434e92727f9812ad54bb5ce5bf375880 (diff)
downloadgcc-582e2e430089a54069f3e38eb8a2bacd36c42af5.zip
gcc-582e2e430089a54069f3e38eb8a2bacd36c42af5.tar.gz
gcc-582e2e430089a54069f3e38eb8a2bacd36c42af5.tar.bz2
Makefile.in (TEXI_GCC_FILES): Add arm-acle-intrinsics.texi.
[gcc/] 2013-12-19 Kyrylo Tkachov <kyrylo.tkachov@arm.com> * Makefile.in (TEXI_GCC_FILES): Add arm-acle-intrinsics.texi. * config.gcc (extra_headers): Add arm_acle.h. * config/arm/arm.c (FL_CRC32): Define. (arm_have_crc): Likewise. (arm_option_override): Set arm_have_crc. (arm_builtins): Add CRC32 builtins. (bdesc_2arg): Likewise. (arm_init_crc32_builtins): New function. (arm_init_builtins): Initialise CRC32 builtins. (arm_file_start): Handle architecture extensions. * config/arm/arm.h (TARGET_CPU_CPP_BUILTINS): Define __ARM_FEATURE_CRC32. Define __ARM_32BIT_STATE. (TARGET_CRC32): Define. * config/arm/arm-arches.def: Add armv8-a+crc. * config/arm/arm-tables.opt: Regenerate. * config/arm/arm.md (type): Add crc. (<crc_variant>): New insn. * config/arm/arm_acle.h: New file. * config/arm/iterators.md (CRC): New int iterator. (crc_variant, crc_mode): New int attributes. * confg/arm/unspecs.md (UNSPEC_CRC32B, UNSPEC_CRC32H, UNSPEC_CRC32W, UNSPEC_CRC32CB, UNSPEC_CRC32CH, UNSPEC_CRC32CW): New unspecs. * doc/invoke.texi: Document -march=armv8-a+crc option. * doc/extend.texi: Document ACLE intrinsics. [gcc/testsuite/] 2013-12-19 Kyrylo Tkachov <kyrylo.tkachov@arm.com> * lib/target-supports.exp (add_options_for_arm_crc): New procedure. (check_effective_target_arm_crc_ok_nocache): Likewise. (check_effective_target_arm_crc_ok): Likewise. * gcc.target/arm/acle/: New directory. * gcc.target/arm/acle/acle.exp: New. * gcc.target/arm/acle/crc32b.c: New test. * gcc.target/arm/acle/crc32h.c: Likewise. * gcc.target/arm/acle/crc32w.c: Likewise. * gcc.target/arm/acle/crc32d.c: Likewise. * gcc.target/arm/acle/crc32cb.c: Likewise. * gcc.target/arm/acle/crc32ch.c: Likewise. * gcc.target/arm/acle/crc32cw.c: Likewise. * gcc.target/arm/acle/crc32cd.c: Likewise. From-SVN: r206128
-rw-r--r--gcc/ChangeLog27
-rw-r--r--gcc/Makefile.in3
-rw-r--r--gcc/config.gcc2
-rw-r--r--gcc/config/arm/arm-arches.def1
-rw-r--r--gcc/config/arm/arm-tables.opt7
-rw-r--r--gcc/config/arm/arm.c81
-rw-r--r--gcc/config/arm/arm.h9
-rw-r--r--gcc/config/arm/arm.md11
-rw-r--r--gcc/config/arm/arm_acle.h100
-rw-r--r--gcc/config/arm/iterators.md12
-rw-r--r--gcc/config/arm/types.md1
-rw-r--r--gcc/config/arm/unspecs.md6
-rw-r--r--gcc/doc/arm-acle-intrinsics.texi55
-rw-r--r--gcc/doc/extend.texi9
-rw-r--r--gcc/doc/invoke.texi5
-rw-r--r--gcc/testsuite/ChangeLog16
-rw-r--r--gcc/testsuite/gcc.target/arm/acle/acle.exp35
-rw-r--r--gcc/testsuite/gcc.target/arm/acle/crc32b.c20
-rw-r--r--gcc/testsuite/gcc.target/arm/acle/crc32cb.c20
-rw-r--r--gcc/testsuite/gcc.target/arm/acle/crc32cd.c20
-rw-r--r--gcc/testsuite/gcc.target/arm/acle/crc32ch.c20
-rw-r--r--gcc/testsuite/gcc.target/arm/acle/crc32cw.c20
-rw-r--r--gcc/testsuite/gcc.target/arm/acle/crc32d.c20
-rw-r--r--gcc/testsuite/gcc.target/arm/acle/crc32h.c20
-rw-r--r--gcc/testsuite/gcc.target/arm/acle/crc32w.c20
-rw-r--r--gcc/testsuite/lib/target-supports.exp23
26 files changed, 556 insertions, 7 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 7786c66..5729893 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,30 @@
+2013-12-19 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
+
+ * Makefile.in (TEXI_GCC_FILES): Add arm-acle-intrinsics.texi.
+ * config.gcc (extra_headers): Add arm_acle.h.
+ * config/arm/arm.c (FL_CRC32): Define.
+ (arm_have_crc): Likewise.
+ (arm_option_override): Set arm_have_crc.
+ (arm_builtins): Add CRC32 builtins.
+ (bdesc_2arg): Likewise.
+ (arm_init_crc32_builtins): New function.
+ (arm_init_builtins): Initialise CRC32 builtins.
+ (arm_file_start): Handle architecture extensions.
+ * config/arm/arm.h (TARGET_CPU_CPP_BUILTINS): Define __ARM_FEATURE_CRC32.
+ Define __ARM_32BIT_STATE.
+ (TARGET_CRC32): Define.
+ * config/arm/arm-arches.def: Add armv8-a+crc.
+ * config/arm/arm-tables.opt: Regenerate.
+ * config/arm/arm.md (type): Add crc.
+ (<crc_variant>): New insn.
+ * config/arm/arm_acle.h: New file.
+ * config/arm/iterators.md (CRC): New int iterator.
+ (crc_variant, crc_mode): New int attributes.
+ * confg/arm/unspecs.md (UNSPEC_CRC32B, UNSPEC_CRC32H, UNSPEC_CRC32W,
+ UNSPEC_CRC32CB, UNSPEC_CRC32CH, UNSPEC_CRC32CW): New unspecs.
+ * doc/invoke.texi: Document -march=armv8-a+crc option.
+ * doc/extend.texi: Document ACLE intrinsics.
+
2013-12-19 Charles Baylis <charles.baylis@linaro.org>
PR target/59142
diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index 0d09ba9..b79bb0c 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -2794,7 +2794,8 @@ TEXI_GCC_FILES = gcc.texi gcc-common.texi gcc-vers.texi frontends.texi \
gcov.texi trouble.texi bugreport.texi service.texi \
contribute.texi compat.texi funding.texi gnu.texi gpl_v3.texi \
fdl.texi contrib.texi cppenv.texi cppopts.texi avr-mmcu.texi \
- implement-c.texi implement-cxx.texi arm-neon-intrinsics.texi
+ implement-c.texi implement-cxx.texi arm-neon-intrinsics.texi \
+ arm-acle-intrinsics.texi
# we explicitly use $(srcdir)/doc/tm.texi here to avoid confusion with
# the generated tm.texi; the latter might have a more recent timestamp,
diff --git a/gcc/config.gcc b/gcc/config.gcc
index 8464d8f..fbfc121 100644
--- a/gcc/config.gcc
+++ b/gcc/config.gcc
@@ -329,8 +329,8 @@ arc*-*-*)
;;
arm*-*-*)
cpu_type=arm
- extra_headers="mmintrin.h arm_neon.h"
extra_objs="aarch-common.o"
+ extra_headers="mmintrin.h arm_neon.h arm_acle.h"
target_type_format_char='%'
c_target_objs="arm-c.o"
cxx_target_objs="arm-c.o"
diff --git a/gcc/config/arm/arm-arches.def b/gcc/config/arm/arm-arches.def
index fcf3401..9b7d20c 100644
--- a/gcc/config/arm/arm-arches.def
+++ b/gcc/config/arm/arm-arches.def
@@ -54,5 +54,6 @@ ARM_ARCH("armv7-r", cortexr4, 7R, FL_CO_PROC | FL_FOR_ARCH7R)
ARM_ARCH("armv7-m", cortexm3, 7M, FL_CO_PROC | FL_FOR_ARCH7M)
ARM_ARCH("armv7e-m", cortexm4, 7EM, FL_CO_PROC | FL_FOR_ARCH7EM)
ARM_ARCH("armv8-a", cortexa53, 8A, FL_CO_PROC | FL_FOR_ARCH8A)
+ARM_ARCH("armv8-a+crc",cortexa53, 8A,FL_CO_PROC | FL_CRC32 | FL_FOR_ARCH8A)
ARM_ARCH("iwmmxt", iwmmxt, 5TE, FL_LDSCHED | FL_STRONG | FL_FOR_ARCH5TE | FL_XSCALE | FL_IWMMXT)
ARM_ARCH("iwmmxt2", iwmmxt2, 5TE, FL_LDSCHED | FL_STRONG | FL_FOR_ARCH5TE | FL_XSCALE | FL_IWMMXT | FL_IWMMXT2)
diff --git a/gcc/config/arm/arm-tables.opt b/gcc/config/arm/arm-tables.opt
index 702338c..3a17c2c 100644
--- a/gcc/config/arm/arm-tables.opt
+++ b/gcc/config/arm/arm-tables.opt
@@ -371,10 +371,13 @@ EnumValue
Enum(arm_arch) String(armv8-a) Value(23)
EnumValue
-Enum(arm_arch) String(iwmmxt) Value(24)
+Enum(arm_arch) String(armv8-a+crc) Value(24)
EnumValue
-Enum(arm_arch) String(iwmmxt2) Value(25)
+Enum(arm_arch) String(iwmmxt) Value(25)
+
+EnumValue
+Enum(arm_arch) String(iwmmxt2) Value(26)
Enum
Name(arm_fpu) Type(int)
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index 8fea2a6..be9044e 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -736,6 +736,7 @@ static int thumb_call_reg_needed;
#define FL_ARCH7 (1 << 22) /* Architecture 7. */
#define FL_ARM_DIV (1 << 23) /* Hardware divide (ARM mode). */
#define FL_ARCH8 (1 << 24) /* Architecture 8. */
+#define FL_CRC32 (1 << 25) /* ARMv8 CRC32 instructions. */
#define FL_IWMMXT (1 << 29) /* XScale v2 or "Intel Wireless MMX technology". */
#define FL_IWMMXT2 (1 << 30) /* "Intel Wireless MMX2 technology". */
@@ -901,6 +902,9 @@ int arm_condexec_mask = 0;
/* The number of bits used in arm_condexec_mask. */
int arm_condexec_masklen = 0;
+/* Nonzero if chip supports the ARMv8 CRC instructions. */
+int arm_arch_crc = 0;
+
/* The condition codes of the ARM, and the inverse function. */
static const char * const arm_condition_codes[] =
{
@@ -2480,6 +2484,7 @@ arm_option_override (void)
arm_arch_thumb_hwdiv = (insn_flags & FL_THUMB_DIV) != 0;
arm_arch_arm_hwdiv = (insn_flags & FL_ARM_DIV) != 0;
arm_tune_cortex_a9 = (arm_tune == cortexa9) != 0;
+ arm_arch_crc = (insn_flags & FL_CRC32) != 0;
if (arm_restrict_it == 2)
arm_restrict_it = arm_arch8 && TARGET_THUMB2;
@@ -23139,6 +23144,13 @@ enum arm_builtins
ARM_BUILTIN_WMERGE,
+ ARM_BUILTIN_CRC32B,
+ ARM_BUILTIN_CRC32H,
+ ARM_BUILTIN_CRC32W,
+ ARM_BUILTIN_CRC32CB,
+ ARM_BUILTIN_CRC32CH,
+ ARM_BUILTIN_CRC32CW,
+
#include "arm_neon_builtins.def"
,ARM_BUILTIN_MAX
@@ -23718,7 +23730,7 @@ struct builtin_description
const enum rtx_code comparison;
const unsigned int flag;
};
-
+
static const struct builtin_description bdesc_2arg[] =
{
#define IWMMXT_BUILTIN(code, string, builtin) \
@@ -23824,6 +23836,17 @@ static const struct builtin_description bdesc_2arg[] =
IWMMXT_BUILTIN2 (iwmmxt_wpackdus, WPACKDUS)
IWMMXT_BUILTIN2 (iwmmxt_wmacuz, WMACUZ)
IWMMXT_BUILTIN2 (iwmmxt_wmacsz, WMACSZ)
+
+#define CRC32_BUILTIN(L, U) \
+ {0, CODE_FOR_##L, "__builtin_arm_"#L, ARM_BUILTIN_##U, \
+ UNKNOWN, 0},
+ CRC32_BUILTIN (crc32b, CRC32B)
+ CRC32_BUILTIN (crc32h, CRC32H)
+ CRC32_BUILTIN (crc32w, CRC32W)
+ CRC32_BUILTIN (crc32cb, CRC32CB)
+ CRC32_BUILTIN (crc32ch, CRC32CH)
+ CRC32_BUILTIN (crc32cw, CRC32CW)
+#undef CRC32_BUILTIN
};
static const struct builtin_description bdesc_1arg[] =
@@ -24243,6 +24266,42 @@ arm_init_fp16_builtins (void)
}
static void
+arm_init_crc32_builtins ()
+{
+ tree si_ftype_si_qi
+ = build_function_type_list (unsigned_intSI_type_node,
+ unsigned_intSI_type_node,
+ unsigned_intQI_type_node, NULL_TREE);
+ tree si_ftype_si_hi
+ = build_function_type_list (unsigned_intSI_type_node,
+ unsigned_intSI_type_node,
+ unsigned_intHI_type_node, NULL_TREE);
+ tree si_ftype_si_si
+ = build_function_type_list (unsigned_intSI_type_node,
+ unsigned_intSI_type_node,
+ unsigned_intSI_type_node, NULL_TREE);
+
+ arm_builtin_decls[ARM_BUILTIN_CRC32B]
+ = add_builtin_function ("__builtin_arm_crc32b", si_ftype_si_qi,
+ ARM_BUILTIN_CRC32B, BUILT_IN_MD, NULL, NULL_TREE);
+ arm_builtin_decls[ARM_BUILTIN_CRC32H]
+ = add_builtin_function ("__builtin_arm_crc32h", si_ftype_si_hi,
+ ARM_BUILTIN_CRC32H, BUILT_IN_MD, NULL, NULL_TREE);
+ arm_builtin_decls[ARM_BUILTIN_CRC32W]
+ = add_builtin_function ("__builtin_arm_crc32w", si_ftype_si_si,
+ ARM_BUILTIN_CRC32W, BUILT_IN_MD, NULL, NULL_TREE);
+ arm_builtin_decls[ARM_BUILTIN_CRC32CB]
+ = add_builtin_function ("__builtin_arm_crc32cb", si_ftype_si_qi,
+ ARM_BUILTIN_CRC32CB, BUILT_IN_MD, NULL, NULL_TREE);
+ arm_builtin_decls[ARM_BUILTIN_CRC32CH]
+ = add_builtin_function ("__builtin_arm_crc32ch", si_ftype_si_hi,
+ ARM_BUILTIN_CRC32CH, BUILT_IN_MD, NULL, NULL_TREE);
+ arm_builtin_decls[ARM_BUILTIN_CRC32CW]
+ = add_builtin_function ("__builtin_arm_crc32cw", si_ftype_si_si,
+ ARM_BUILTIN_CRC32CW, BUILT_IN_MD, NULL, NULL_TREE);
+}
+
+static void
arm_init_builtins (void)
{
if (TARGET_REALLY_IWMMXT)
@@ -24253,6 +24312,9 @@ arm_init_builtins (void)
if (arm_fp16_format)
arm_init_fp16_builtins ();
+
+ if (TARGET_CRC32)
+ arm_init_crc32_builtins ();
}
/* Return the ARM builtin for CODE. */
@@ -27526,7 +27588,22 @@ arm_file_start (void)
{
const char *fpu_name;
if (arm_selected_arch)
- asm_fprintf (asm_out_file, "\t.arch %s\n", arm_selected_arch->name);
+ {
+ const char* pos = strchr (arm_selected_arch->name, '+');
+ if (pos)
+ {
+ char buf[15];
+ gcc_assert (strlen (arm_selected_arch->name)
+ <= sizeof (buf) / sizeof (*pos));
+ strncpy (buf, arm_selected_arch->name,
+ (pos - arm_selected_arch->name) * sizeof (*pos));
+ buf[pos - arm_selected_arch->name] = '\0';
+ asm_fprintf (asm_out_file, "\t.arch %s\n", buf);
+ asm_fprintf (asm_out_file, "\t.arch_extension %s\n", pos + 1);
+ }
+ else
+ asm_fprintf (asm_out_file, "\t.arch %s\n", arm_selected_arch->name);
+ }
else if (strncmp (arm_selected_cpu->name, "generic", 7) == 0)
asm_fprintf (asm_out_file, "\t.arch %s\n", arm_selected_cpu->name + 8);
else
diff --git a/gcc/config/arm/arm.h b/gcc/config/arm/arm.h
index 7b5a7f9..e02b2ad 100644
--- a/gcc/config/arm/arm.h
+++ b/gcc/config/arm/arm.h
@@ -51,6 +51,10 @@ extern char arm_arch_name[];
builtin_define ("__ARM_FEATURE_SAT"); \
if (unaligned_access) \
builtin_define ("__ARM_FEATURE_UNALIGNED"); \
+ if (TARGET_CRC32) \
+ builtin_define ("__ARM_FEATURE_CRC32"); \
+ if (TARGET_32BIT) \
+ builtin_define ("__ARM_32BIT_STATE"); \
if (TARGET_ARM_FEATURE_LDREX) \
builtin_define_with_int_value ( \
"__ARM_FEATURE_LDREX", TARGET_ARM_FEATURE_LDREX); \
@@ -274,6 +278,8 @@ extern void (*arm_lang_output_object_attributes_hook)(void);
#define TARGET_LDRD (arm_arch5e && ARM_DOUBLEWORD_ALIGN \
&& !TARGET_THUMB1)
+#define TARGET_CRC32 (arm_arch_crc)
+
/* The following two macros concern the ability to execute coprocessor
instructions for VFPv3 or NEON. TARGET_VFP3/TARGET_VFPD32 are currently
only ever tested when we know we are generating for VFP hardware; we need
@@ -561,6 +567,9 @@ extern int prefer_neon_for_64bits;
extern bool arm_disable_literal_pool;
#endif
+/* Nonzero if chip supports the ARMv8 CRC instructions. */
+extern int arm_arch_crc;
+
#ifndef TARGET_DEFAULT
#define TARGET_DEFAULT (MASK_APCS_FRAME)
#endif
diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md
index 6e1b47d..0440ce6 100644
--- a/gcc/config/arm/arm.md
+++ b/gcc/config/arm/arm.md
@@ -12870,6 +12870,17 @@
(set_attr "predicable" "yes")
(set_attr "predicable_short_it" "no")])
+;; ARMv8 CRC32 instructions.
+(define_insn "<crc_variant>"
+ [(set (match_operand:SI 0 "s_register_operand" "=r")
+ (unspec:SI [(match_operand:SI 1 "s_register_operand" "r")
+ (match_operand:<crc_mode> 2 "s_register_operand" "r")]
+ CRC))]
+ "TARGET_CRC32"
+ "<crc_variant>\\t%0, %1, %2"
+ [(set_attr "type" "crc")
+ (set_attr "conds" "unconditional")]
+)
;; Load the load/store double peephole optimizations.
(include "ldrdstrd.md")
diff --git a/gcc/config/arm/arm_acle.h b/gcc/config/arm/arm_acle.h
new file mode 100644
index 0000000..b04605b
--- /dev/null
+++ b/gcc/config/arm/arm_acle.h
@@ -0,0 +1,100 @@
+/* ARM Non-NEON ACLE intrinsics include file.
+
+ Copyright (C) 2013 Free Software Foundation, Inc.
+ Contributed by ARM Ltd.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+ License for more details.
+
+ Under Section 7 of GPL version 3, you are granted additional
+ permissions described in the GCC Runtime Library Exception, version
+ 3.1, as published by the Free Software Foundation.
+
+ You should have received a copy of the GNU General Public License and
+ a copy of the GCC Runtime Library Exception along with this program;
+ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef _GCC_ARM_ACLE_H
+#define _GCC_ARM_ACLE_H
+
+#include <stdint.h>
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef __ARM_FEATURE_CRC32
+__extension__ static __inline uint32_t __attribute__ ((__always_inline__))
+__crc32b (uint32_t a, uint8_t b)
+{
+ return __builtin_arm_crc32b (a, b);
+}
+
+__extension__ static __inline uint32_t __attribute__ ((__always_inline__))
+__crc32h (uint32_t a, uint16_t b)
+{
+ return __builtin_arm_crc32h (a, b);
+}
+
+__extension__ static __inline uint32_t __attribute__ ((__always_inline__))
+__crc32w (uint32_t a, uint32_t b)
+{
+ return __builtin_arm_crc32w (a, b);
+}
+
+#ifdef __ARM_32BIT_STATE
+__extension__ static __inline uint32_t __attribute__ ((__always_inline__))
+__crc32d (uint32_t a, uint64_t b)
+{
+ uint32_t d;
+
+ d = __crc32w (__crc32w (a, b & 0xffffffffULL), b >> 32);
+ return d;
+}
+#endif
+
+__extension__ static __inline uint32_t __attribute__ ((__always_inline__))
+__crc32cb (uint32_t a, uint8_t b)
+{
+ return __builtin_arm_crc32cb (a, b);
+}
+
+__extension__ static __inline uint32_t __attribute__ ((__always_inline__))
+__crc32ch (uint32_t a, uint16_t b)
+{
+ return __builtin_arm_crc32ch (a, b);
+}
+
+__extension__ static __inline uint32_t __attribute__ ((__always_inline__))
+__crc32cw (uint32_t a, uint32_t b)
+{
+ return __builtin_arm_crc32cw (a, b);
+}
+
+#ifdef __ARM_32BIT_STATE
+__extension__ static __inline uint32_t __attribute__ ((__always_inline__))
+__crc32cd (uint32_t a, uint64_t b)
+{
+ uint32_t d;
+
+ d = __crc32cw (__crc32cw (a, b & 0xffffffffULL), b >> 32);
+ return d;
+}
+#endif
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/gcc/config/arm/iterators.md b/gcc/config/arm/iterators.md
index 66779a7..ff5462c 100644
--- a/gcc/config/arm/iterators.md
+++ b/gcc/config/arm/iterators.md
@@ -201,6 +201,9 @@
(define_int_iterator NEON_VRINT [UNSPEC_NVRINTP UNSPEC_NVRINTZ UNSPEC_NVRINTM
UNSPEC_NVRINTX UNSPEC_NVRINTA UNSPEC_NVRINTN])
+(define_int_iterator CRC [UNSPEC_CRC32B UNSPEC_CRC32H UNSPEC_CRC32W
+ UNSPEC_CRC32CB UNSPEC_CRC32CH UNSPEC_CRC32CW])
+
;;----------------------------------------------------------------------------
;; Mode attributes
;;----------------------------------------------------------------------------
@@ -518,6 +521,15 @@
(define_int_attr nvrint_variant [(UNSPEC_NVRINTZ "z") (UNSPEC_NVRINTP "p")
(UNSPEC_NVRINTA "a") (UNSPEC_NVRINTM "m")
(UNSPEC_NVRINTX "x") (UNSPEC_NVRINTN "n")])
+
+(define_int_attr crc_variant [(UNSPEC_CRC32B "crc32b") (UNSPEC_CRC32H "crc32h")
+ (UNSPEC_CRC32W "crc32w") (UNSPEC_CRC32CB "crc32cb")
+ (UNSPEC_CRC32CH "crc32ch") (UNSPEC_CRC32CW "crc32cw")])
+
+(define_int_attr crc_mode [(UNSPEC_CRC32B "QI") (UNSPEC_CRC32H "HI")
+ (UNSPEC_CRC32W "SI") (UNSPEC_CRC32CB "QI")
+ (UNSPEC_CRC32CH "HI") (UNSPEC_CRC32CW "SI")])
+
;; Both kinds of return insn.
(define_code_iterator returns [return simple_return])
(define_code_attr return_str [(return "") (simple_return "simple_")])
diff --git a/gcc/config/arm/types.md b/gcc/config/arm/types.md
index 0ff9b08f..40c4a78 100644
--- a/gcc/config/arm/types.md
+++ b/gcc/config/arm/types.md
@@ -554,6 +554,7 @@
clz,\
no_insn,\
csel,\
+ crc,\
extend,\
f_cvt,\
f_cvtf2i,\
diff --git a/gcc/config/arm/unspecs.md b/gcc/config/arm/unspecs.md
index 508603c..f8faba3 100644
--- a/gcc/config/arm/unspecs.md
+++ b/gcc/config/arm/unspecs.md
@@ -149,6 +149,12 @@
(define_c_enum "unspec" [
UNSPEC_ASHIFT_SIGNED
UNSPEC_ASHIFT_UNSIGNED
+ UNSPEC_CRC32B
+ UNSPEC_CRC32H
+ UNSPEC_CRC32W
+ UNSPEC_CRC32CB
+ UNSPEC_CRC32CH
+ UNSPEC_CRC32CW
UNSPEC_LOAD_COUNT
UNSPEC_VABD
UNSPEC_VABDL
diff --git a/gcc/doc/arm-acle-intrinsics.texi b/gcc/doc/arm-acle-intrinsics.texi
new file mode 100644
index 0000000..bb6290b
--- /dev/null
+++ b/gcc/doc/arm-acle-intrinsics.texi
@@ -0,0 +1,55 @@
+@c Copyright (C) 2013 Free Software Foundation, Inc.
+@c This is part of the GCC manual.
+@c For copying conditions, see the file gcc.texi.
+
+@subsubsection CRC32 intrinsics
+
+@itemize @bullet
+@item uint32_t __crc32b (uint32_t, uint8_t)
+@*@emph{Form of expected instruction(s):} @code{crc32b @var{r0}, @var{r0}, @var{r0}}
+@end itemize
+
+
+@itemize @bullet
+@item uint32_t __crc32h (uint32_t, uint16_t)
+@*@emph{Form of expected instruction(s):} @code{crc32h @var{r0}, @var{r0}, @var{r0}}
+@end itemize
+
+
+@itemize @bullet
+@item uint32_t __crc32w (uint32_t, uint32_t)
+@*@emph{Form of expected instruction(s):} @code{crc32w @var{r0}, @var{r0}, @var{r0}}
+@end itemize
+
+
+@itemize @bullet
+@item uint32_t __crc32d (uint32_t, uint64_t)
+@*@emph{Form of expected instruction(s):} Two @code{crc32w @var{r0}, @var{r0}, @var{r0}}
+instructions for AArch32. One @code{crc32w @var{w0}, @var{w0}, @var{x0}} instruction for
+AArch64.
+@end itemize
+
+@itemize @bullet
+@item uint32_t __crc32cb (uint32_t, uint8_t)
+@*@emph{Form of expected instruction(s):} @code{crc32cb @var{r0}, @var{r0}, @var{r0}}
+@end itemize
+
+
+@itemize @bullet
+@item uint32_t __crc32ch (uint32_t, uint16_t)
+@*@emph{Form of expected instruction(s):} @code{crc32ch @var{r0}, @var{r0}, @var{r0}}
+@end itemize
+
+
+@itemize @bullet
+@item uint32_t __crc32cw (uint32_t, uint32_t)
+@*@emph{Form of expected instruction(s):} @code{crc32cw @var{r0}, @var{r0}, @var{r0}}
+@end itemize
+
+
+@itemize @bullet
+@item uint32_t __crc32cd (uint32_t, uint64_t)
+@*@emph{Form of expected instruction(s):} Two @code{crc32cw @var{r0}, @var{r0}, @var{r0}}
+instructions for AArch32. One @code{crc32cw @var{w0}, @var{w0}, @var{x0}} instruction for
+AArch64.
+@end itemize
diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
index 2ce0098..d539bd1 100644
--- a/gcc/doc/extend.texi
+++ b/gcc/doc/extend.texi
@@ -9016,6 +9016,7 @@ instructions, but allow the compiler to schedule those calls.
* ARC SIMD Built-in Functions::
* ARM iWMMXt Built-in Functions::
* ARM NEON Intrinsics::
+* ARM ACLE Intrinsics::
* AVR Built-in Functions::
* Blackfin Built-in Functions::
* FR-V Built-in Functions::
@@ -9708,6 +9709,14 @@ when the @option{-mfpu=neon} switch is used:
@include arm-neon-intrinsics.texi
+@node ARM ACLE Intrinsics
+@subsection ARM ACLE Intrinsics
+
+These built-in intrinsics for the ARMv8-A CRC32 extension are available when
+the @option{-march=armv8-a+crc} switch is used:
+
+@include arm-acle-intrinsics.texi
+
@node AVR Built-in Functions
@subsection AVR Built-in Functions
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 6e888bd..689b3ab 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -12228,9 +12228,12 @@ of the @option{-mcpu=} option. Permissible names are: @samp{armv2},
@samp{armv6}, @samp{armv6j},
@samp{armv6t2}, @samp{armv6z}, @samp{armv6zk}, @samp{armv6-m},
@samp{armv7}, @samp{armv7-a}, @samp{armv7-r}, @samp{armv7-m},
-@samp{armv8-a},
+@samp{armv8-a}, @samp{armv8-a+crc},
@samp{iwmmxt}, @samp{iwmmxt2}, @samp{ep9312}.
+@option{-march=armv8-a+crc} enables code generation for the ARMv8-A
+architecture together with the optional CRC32 extensions.
+
@option{-march=native} causes the compiler to auto-detect the architecture
of the build computer. At present, this feature is only supported on
Linux, and not all architectures are recognized. If the auto-detect is
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 8d61415..318550a 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,5 +1,21 @@
2013-12-19 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
+ * lib/target-supports.exp (add_options_for_arm_crc): New procedure.
+ (check_effective_target_arm_crc_ok_nocache): Likewise.
+ (check_effective_target_arm_crc_ok): Likewise.
+ * gcc.target/arm/acle/: New directory.
+ * gcc.target/arm/acle/acle.exp: New.
+ * gcc.target/arm/acle/crc32b.c: New test.
+ * gcc.target/arm/acle/crc32h.c: Likewise.
+ * gcc.target/arm/acle/crc32w.c: Likewise.
+ * gcc.target/arm/acle/crc32d.c: Likewise.
+ * gcc.target/arm/acle/crc32cb.c: Likewise.
+ * gcc.target/arm/acle/crc32ch.c: Likewise.
+ * gcc.target/arm/acle/crc32cw.c: Likewise.
+ * gcc.target/arm/acle/crc32cd.c: Likewise.
+
+2013-12-19 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
+
* c-c++-common/cilk-plus/SE/ef_error.c: Use -fopen-simd.
2013-12-19 Oleg Endo <olegendo@gcc.gnu.org>
diff --git a/gcc/testsuite/gcc.target/arm/acle/acle.exp b/gcc/testsuite/gcc.target/arm/acle/acle.exp
new file mode 100644
index 0000000..a1822a1
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/acle/acle.exp
@@ -0,0 +1,35 @@
+# Copyright (C) 2013 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GCC; see the file COPYING3. If not see
+# <http://www.gnu.org/licenses/>.
+
+# GCC testsuite that uses the `dg.exp' driver.
+
+# Exit immediately if this isn't an ARM target.
+if ![istarget arm*-*-*] then {
+ return
+}
+
+# Load support procs.
+load_lib gcc-dg.exp
+
+# Initialize `dg'.
+dg-init
+
+# Main loop.
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.\[cCS\]]] \
+ "" ""
+
+# All done.
+dg-finish
diff --git a/gcc/testsuite/gcc.target/arm/acle/crc32b.c b/gcc/testsuite/gcc.target/arm/acle/crc32b.c
new file mode 100644
index 0000000..d6f35e9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/acle/crc32b.c
@@ -0,0 +1,20 @@
+/* Test the crc32b ACLE intrinsic. */
+
+/* { dg-do assemble } */
+/* { dg-require-effective-target arm_crc_ok } */
+/* { dg-options "-save-temps -O0" } */
+/* { dg-add-options arm_crc } */
+
+#include "arm_acle.h"
+
+void test_crc32b (void)
+{
+ uint32_t out_uint32_t;
+ uint32_t arg0_uint32_t;
+ uint8_t arg1_uint8_t;
+
+ out_uint32_t = __crc32b (arg0_uint32_t, arg1_uint8_t);
+}
+
+/* { dg-final { scan-assembler "crc32b\t...?, ...?, ...?\n" } } */
+/* { dg-final { cleanup-saved-temps } } */
diff --git a/gcc/testsuite/gcc.target/arm/acle/crc32cb.c b/gcc/testsuite/gcc.target/arm/acle/crc32cb.c
new file mode 100644
index 0000000..44aea21
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/acle/crc32cb.c
@@ -0,0 +1,20 @@
+/* Test the crc32cb ACLE intrinsic. */
+
+/* { dg-do assemble } */
+/* { dg-require-effective-target arm_crc_ok } */
+/* { dg-options "-save-temps -O0" } */
+/* { dg-add-options arm_crc } */
+
+#include "arm_acle.h"
+
+void test_crc32cb (void)
+{
+ uint32_t out_uint32_t;
+ uint32_t arg0_uint32_t;
+ uint8_t arg1_uint8_t;
+
+ out_uint32_t = __crc32cb (arg0_uint32_t, arg1_uint8_t);
+}
+
+/* { dg-final { scan-assembler "crc32cb\t...?, ...?, ...?\n" } } */
+/* { dg-final { cleanup-saved-temps } } */
diff --git a/gcc/testsuite/gcc.target/arm/acle/crc32cd.c b/gcc/testsuite/gcc.target/arm/acle/crc32cd.c
new file mode 100644
index 0000000..cb7ee0d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/acle/crc32cd.c
@@ -0,0 +1,20 @@
+/* Test the crc32cd ACLE intrinsic. */
+
+/* { dg-do assemble } */
+/* { dg-require-effective-target arm_crc_ok } */
+/* { dg-options "-save-temps -O0" } */
+/* { dg-add-options arm_crc } */
+
+#include "arm_acle.h"
+
+void test_crc32cd (void)
+{
+ uint32_t out_uint32_t;
+ uint32_t arg0_uint32_t;
+ uint64_t arg1_uint64_t;
+
+ out_uint32_t = __crc32cd (arg0_uint32_t, arg1_uint64_t);
+}
+
+/* { dg-final { scan-assembler-times "crc32cw\t...?, ...?, ...?\n" 2 } } */
+/* { dg-final { cleanup-saved-temps } } */
diff --git a/gcc/testsuite/gcc.target/arm/acle/crc32ch.c b/gcc/testsuite/gcc.target/arm/acle/crc32ch.c
new file mode 100644
index 0000000..d8e7338
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/acle/crc32ch.c
@@ -0,0 +1,20 @@
+/* Test the crc32ch ACLE intrinsic. */
+
+/* { dg-do assemble } */
+/* { dg-require-effective-target arm_crc_ok } */
+/* { dg-options "-save-temps -O0" } */
+/* { dg-add-options arm_crc } */
+
+#include "arm_acle.h"
+
+void test_crc32ch (void)
+{
+ uint32_t out_uint32_t;
+ uint32_t arg0_uint32_t;
+ uint16_t arg1_uint16_t;
+
+ out_uint32_t = __crc32ch (arg0_uint32_t, arg1_uint16_t);
+}
+
+/* { dg-final { scan-assembler "crc32ch\t...?, ...?, ...?\n" } } */
+/* { dg-final { cleanup-saved-temps } } */
diff --git a/gcc/testsuite/gcc.target/arm/acle/crc32cw.c b/gcc/testsuite/gcc.target/arm/acle/crc32cw.c
new file mode 100644
index 0000000..84384c5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/acle/crc32cw.c
@@ -0,0 +1,20 @@
+/* Test the crc32cw ACLE intrinsic. */
+
+/* { dg-do assemble } */
+/* { dg-require-effective-target arm_crc_ok } */
+/* { dg-options "-save-temps -O0" } */
+/* { dg-add-options arm_crc } */
+
+#include "arm_acle.h"
+
+void test_crc32cw (void)
+{
+ uint32_t out_uint32_t;
+ uint32_t arg0_uint32_t;
+ uint32_t arg1_uint32_t;
+
+ out_uint32_t = __crc32cw (arg0_uint32_t, arg1_uint32_t);
+}
+
+/* { dg-final { scan-assembler "crc32cw\t...?, ...?, ...?\n" } } */
+/* { dg-final { cleanup-saved-temps } } */
diff --git a/gcc/testsuite/gcc.target/arm/acle/crc32d.c b/gcc/testsuite/gcc.target/arm/acle/crc32d.c
new file mode 100644
index 0000000..c90fad9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/acle/crc32d.c
@@ -0,0 +1,20 @@
+/* Test the crc32d ACLE intrinsic. */
+
+/* { dg-do assemble } */
+/* { dg-require-effective-target arm_crc_ok } */
+/* { dg-options "-save-temps -O0" } */
+/* { dg-add-options arm_crc } */
+
+#include "arm_acle.h"
+
+void test_crc32d (void)
+{
+ uint32_t out_uint32_t;
+ uint32_t arg0_uint32_t;
+ uint64_t arg1_uint64_t;
+
+ out_uint32_t = __crc32d (arg0_uint32_t, arg1_uint64_t);
+}
+
+/* { dg-final { scan-assembler-times "crc32w\t...?, ...?, ...?\n" 2 } } */
+/* { dg-final { cleanup-saved-temps } } */
diff --git a/gcc/testsuite/gcc.target/arm/acle/crc32h.c b/gcc/testsuite/gcc.target/arm/acle/crc32h.c
new file mode 100644
index 0000000..c21a4ae
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/acle/crc32h.c
@@ -0,0 +1,20 @@
+/* Test the crc32h ACLE intrinsic. */
+
+/* { dg-do assemble } */
+/* { dg-require-effective-target arm_crc_ok } */
+/* { dg-options "-save-temps -O0" } */
+/* { dg-add-options arm_crc } */
+
+#include "arm_acle.h"
+
+void test_crc32h (void)
+{
+ uint32_t out_uint32_t;
+ uint32_t arg0_uint32_t;
+ uint16_t arg1_uint16_t;
+
+ out_uint32_t = __crc32h (arg0_uint32_t, arg1_uint16_t);
+}
+
+/* { dg-final { scan-assembler "crc32h\t...?, ...?, ...?\n" } } */
+/* { dg-final { cleanup-saved-temps } } */
diff --git a/gcc/testsuite/gcc.target/arm/acle/crc32w.c b/gcc/testsuite/gcc.target/arm/acle/crc32w.c
new file mode 100644
index 0000000..60cd09e4
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/acle/crc32w.c
@@ -0,0 +1,20 @@
+/* Test the crc32w ACLE intrinsic. */
+
+/* { dg-do assemble } */
+/* { dg-require-effective-target arm_crc_ok } */
+/* { dg-options "-save-temps -O0" } */
+/* { dg-add-options arm_crc } */
+
+#include "arm_acle.h"
+
+void test_crc32w (void)
+{
+ uint32_t out_uint32_t;
+ uint32_t arg0_uint32_t;
+ uint32_t arg1_uint32_t;
+
+ out_uint32_t = __crc32w (arg0_uint32_t, arg1_uint32_t);
+}
+
+/* { dg-final { scan-assembler "crc32w\t...?, ...?, ...?\n" } } */
+/* { dg-final { cleanup-saved-temps } } */
diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp
index 642c344..0f9ef4c 100644
--- a/gcc/testsuite/lib/target-supports.exp
+++ b/gcc/testsuite/lib/target-supports.exp
@@ -2327,6 +2327,14 @@ proc add_options_for_arm_v8_neon { flags } {
return "$flags $et_arm_v8_neon_flags -march=armv8-a"
}
+proc add_options_for_arm_crc { flags } {
+ if { ! [check_effective_target_arm_crc_ok] } {
+ return "$flags"
+ }
+ global et_arm_crc_flags
+ return "$flags $et_arm_crc_flags"
+}
+
# Add the options needed for NEON. We need either -mfloat-abi=softfp
# or -mfloat-abi=hard, but if one is already specified by the
# multilib, use it. Similarly, if a -mfpu option already enables
@@ -2368,6 +2376,21 @@ proc check_effective_target_arm_neon_ok { } {
check_effective_target_arm_neon_ok_nocache]
}
+proc check_effective_target_arm_crc_ok_nocache { } {
+ global et_arm_crc_flags
+ set et_arm_crc_flags "-march=armv8-a+crc"
+ return [check_no_compiler_messages_nocache arm_crc_ok object {
+ #if !defined (__ARM_FEATURE_CRC32)
+ #error FOO
+ #endif
+ } "$et_arm_crc_flags"]
+}
+
+proc check_effective_target_arm_crc_ok { } {
+ return [check_cached_effective_target arm_crc_ok \
+ check_effective_target_arm_crc_ok_nocache]
+}
+
# Return 1 if this is an ARM target supporting -mfpu=neon-fp16
# -mfloat-abi=softfp or equivalent options. Some multilibs may be
# incompatible with these options. Also set et_arm_neon_flags to the