+2016-01-20 Peter Bergner <bergner@vnet.ibm.com>
+
+ * config/rs6000/ppc-auxv.h: New file.
+ * config/rs6000/rs6000-builtin.def (cpu_init): Add new builtin.
+ (cpu_is): Likewise.
+ (cpu_supports): Likewise.
+ * config/rs6000/rs6000.c: include "ppc-auxv.h".
+ (cpu_is_info): New variable.
+ (cpu_supports_info): Likewise.
+ (tcb_verification_symbol): Likewise.
+ (cpu_builtin_p): Likewise.
+ (cpu_expand_builtin): New function.
+ (rs6000_expand_ternop_builtin): Add support for CPU builtin functions.
+ (rs6000_init_builtins): Likewise.
+ (rs6000_elf_file_end): Emit HWCAP in TCB verification symbol.
+ * config/rs6000/rs6000.h (TLS_REGNUM): New define.
+ * configure.ac (gcc_cv_libc_provides_hwcap_in_tcb): New test.
+ * configure: Regenerate.
+ * config.in: Likewise.
+ * doc/extend.texi (PowerPC Built-in Functions): Document
+ __builtin_cpu_init, __builtin_cpu_is and __builtin_cpu_supports.
+
2016-01-20 David Edelsohn <dje.gcc@gmail.com>
PR target/68609
#endif
+/* Define if your target C Library provides the AT_HWCAP value in the TCB */
+#ifndef USED_FOR_TARGET
+#undef TARGET_LIBC_PROVIDES_HWCAP_IN_TCB
+#endif
+
+
/* Define if your target C library provides stack protector support */
#ifndef USED_FOR_TARGET
#undef TARGET_LIBC_PROVIDES_SSP
--- /dev/null
+/* PowerPC support for accessing the AUXV AT_PLATFORM, AT_HWCAP and AT_HWCAP2
+ values from the Thread Control Block (TCB).
+
+ Copyright (C) 2016 Free Software Foundation, Inc.
+ Contributed by Peter Bergner <bergner@vnet.ibm.com>.
+
+ 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 _PPC_AUXV_H
+#define _PPC_AUXV_H
+
+/* The PLATFORM value stored in the TCB is offset by _DL_FIRST_PLATFORM. */
+#define _DL_FIRST_PLATFORM 32
+
+/* AT_PLATFORM bits. These must match the values defined in GLIBC. */
+#define PPC_PLATFORM_POWER4 0
+#define PPC_PLATFORM_PPC970 1
+#define PPC_PLATFORM_POWER5 2
+#define PPC_PLATFORM_POWER5_PLUS 3
+#define PPC_PLATFORM_POWER6 4
+#define PPC_PLATFORM_CELL_BE 5
+#define PPC_PLATFORM_POWER6X 6
+#define PPC_PLATFORM_POWER7 7
+#define PPC_PLATFORM_PPCA2 8
+#define PPC_PLATFORM_PPC405 9
+#define PPC_PLATFORM_PPC440 10
+#define PPC_PLATFORM_PPC464 11
+#define PPC_PLATFORM_PPC476 12
+#define PPC_PLATFORM_POWER8 13
+#define PPC_PLATFORM_POWER9 14
+
+/* AT_HWCAP bits. These must match the values defined in the Linux kernel. */
+#define PPC_FEATURE_32 0x80000000
+#define PPC_FEATURE_64 0x40000000
+#define PPC_FEATURE_601_INSTR 0x20000000
+#define PPC_FEATURE_HAS_ALTIVEC 0x10000000
+#define PPC_FEATURE_HAS_FPU 0x08000000
+#define PPC_FEATURE_HAS_MMU 0x04000000
+#define PPC_FEATURE_HAS_4xxMAC 0x02000000
+#define PPC_FEATURE_UNIFIED_CACHE 0x01000000
+#define PPC_FEATURE_HAS_SPE 0x00800000
+#define PPC_FEATURE_HAS_EFP_SINGLE 0x00400000
+#define PPC_FEATURE_HAS_EFP_DOUBLE 0x00200000
+#define PPC_FEATURE_NO_TB 0x00100000
+#define PPC_FEATURE_POWER4 0x00080000
+#define PPC_FEATURE_POWER5 0x00040000
+#define PPC_FEATURE_POWER5_PLUS 0x00020000
+#define PPC_FEATURE_CELL_BE 0x00010000
+#define PPC_FEATURE_BOOKE 0x00008000
+#define PPC_FEATURE_SMT 0x00004000
+#define PPC_FEATURE_ICACHE_SNOOP 0x00002000
+#define PPC_FEATURE_ARCH_2_05 0x00001000
+#define PPC_FEATURE_PA6T 0x00000800
+#define PPC_FEATURE_HAS_DFP 0x00000400
+#define PPC_FEATURE_POWER6_EXT 0x00000200
+#define PPC_FEATURE_ARCH_2_06 0x00000100
+#define PPC_FEATURE_HAS_VSX 0x00000080
+#define PPC_FEATURE_PERFMON_COMPAT 0x00000040
+#define PPC_FEATURE_TRUE_LE 0x00000002
+#define PPC_FEATURE_PPC_LE 0x00000001
+
+/* AT_HWCAP2 bits. These must match the values defined in the Linux kernel. */
+#define PPC_FEATURE2_ARCH_2_07 0x80000000
+#define PPC_FEATURE2_HAS_HTM 0x40000000
+#define PPC_FEATURE2_HAS_DSCR 0x20000000
+#define PPC_FEATURE2_HAS_EBB 0x10000000
+#define PPC_FEATURE2_HAS_ISEL 0x08000000
+#define PPC_FEATURE2_HAS_TAR 0x04000000
+#define PPC_FEATURE2_HAS_VEC_CRYPTO 0x02000000
+#define PPC_FEATURE2_HTM_NOSC 0x01000000
+#define PPC_FEATURE2_ARCH_3_00 0x00800000
+#define PPC_FEATURE2_HAS_IEEE128 0x00400000
+
+
+/* Thread Control Block (TCB) offsets of the AT_PLATFORM, AT_HWCAP and
+ AT_HWCAP2 values. These must match the values defined in GLIBC. */
+#define TCB_PLATFORM_OFFSET ((TARGET_64BIT) ? -28764 : -28724)
+#define TCB_HWCAP_BASE_OFFSET ((TARGET_64BIT) ? -28776 : -28736)
+#define TCB_HWCAP1_OFFSET \
+ ((BYTES_BIG_ENDIAN) ? TCB_HWCAP_BASE_OFFSET : TCB_HWCAP_BASE_OFFSET+4)
+#define TCB_HWCAP2_OFFSET \
+ ((BYTES_BIG_ENDIAN) ? TCB_HWCAP_BASE_OFFSET+4 : TCB_HWCAP_BASE_OFFSET)
+#define TCB_HWCAP_OFFSET(ID) \
+ (((ID) == 0) ? TCB_HWCAP1_OFFSET : TCB_HWCAP2_OFFSET)
+
+#endif /* _PPC_AUXV_H */
RS6000_BTC_MISC | RS6000_BTC_UNARY | RS6000_BTC_VOID,
CODE_FOR_rs6000_mtfsf)
+BU_SPECIAL_X (RS6000_BUILTIN_CPU_INIT, "__builtin_cpu_init",
+ RS6000_BTM_ALWAYS, RS6000_BTC_MISC)
+
+BU_SPECIAL_X (RS6000_BUILTIN_CPU_IS, "__builtin_cpu_is",
+ RS6000_BTM_ALWAYS, RS6000_BTC_MISC)
+
+BU_SPECIAL_X (RS6000_BUILTIN_CPU_SUPPORTS, "__builtin_cpu_supports",
+ RS6000_BTM_ALWAYS, RS6000_BTC_MISC)
+
/* Darwin CfString builtin. */
BU_SPECIAL_X (RS6000_BUILTIN_CFSTRING, "__builtin_cfstring", RS6000_BTM_ALWAYS,
RS6000_BTC_MISC)
#include "gstab.h" /* for N_SLINE */
#endif
#include "case-cfn-macros.h"
+#include "ppc-auxv.h"
/* This file should be included last. */
#include "target-def.h"
{ "rsqrtd", (RECIP_DF_RSQRT | RECIP_V2DF_RSQRT) },
};
+/* Used by __builtin_cpu_is(), mapping from PLATFORM names to values. */
+static const struct
+{
+ const char *cpu;
+ unsigned int cpuid;
+} cpu_is_info[] = {
+ { "power9", PPC_PLATFORM_POWER9 },
+ { "power8", PPC_PLATFORM_POWER8 },
+ { "power7", PPC_PLATFORM_POWER7 },
+ { "power6x", PPC_PLATFORM_POWER6X },
+ { "power6", PPC_PLATFORM_POWER6 },
+ { "power5+", PPC_PLATFORM_POWER5_PLUS },
+ { "power5", PPC_PLATFORM_POWER5 },
+ { "ppc970", PPC_PLATFORM_PPC970 },
+ { "power4", PPC_PLATFORM_POWER4 },
+ { "ppca2", PPC_PLATFORM_PPCA2 },
+ { "ppc476", PPC_PLATFORM_PPC476 },
+ { "ppc464", PPC_PLATFORM_PPC464 },
+ { "ppc440", PPC_PLATFORM_PPC440 },
+ { "ppc405", PPC_PLATFORM_PPC405 },
+ { "ppc-cell-be", PPC_PLATFORM_CELL_BE }
+};
+
+/* Used by __builtin_cpu_supports(), mapping from HWCAP names to masks. */
+static const struct
+{
+ const char *hwcap;
+ int mask;
+ unsigned int id;
+} cpu_supports_info[] = {
+ /* AT_HWCAP masks. */
+ { "4xxmac", PPC_FEATURE_HAS_4xxMAC, 0 },
+ { "altivec", PPC_FEATURE_HAS_ALTIVEC, 0 },
+ { "arch_2_05", PPC_FEATURE_ARCH_2_05, 0 },
+ { "arch_2_06", PPC_FEATURE_ARCH_2_06, 0 },
+ { "archpmu", PPC_FEATURE_PERFMON_COMPAT, 0 },
+ { "booke", PPC_FEATURE_BOOKE, 0 },
+ { "cellbe", PPC_FEATURE_CELL_BE, 0 },
+ { "dfp", PPC_FEATURE_HAS_DFP, 0 },
+ { "efpdouble", PPC_FEATURE_HAS_EFP_DOUBLE, 0 },
+ { "efpsingle", PPC_FEATURE_HAS_EFP_SINGLE, 0 },
+ { "fpu", PPC_FEATURE_HAS_FPU, 0 },
+ { "ic_snoop", PPC_FEATURE_ICACHE_SNOOP, 0 },
+ { "mmu", PPC_FEATURE_HAS_MMU, 0 },
+ { "notb", PPC_FEATURE_NO_TB, 0 },
+ { "pa6t", PPC_FEATURE_PA6T, 0 },
+ { "power4", PPC_FEATURE_POWER4, 0 },
+ { "power5", PPC_FEATURE_POWER5, 0 },
+ { "power5+", PPC_FEATURE_POWER5_PLUS, 0 },
+ { "power6x", PPC_FEATURE_POWER6_EXT, 0 },
+ { "ppc32", PPC_FEATURE_32, 0 },
+ { "ppc601", PPC_FEATURE_601_INSTR, 0 },
+ { "ppc64", PPC_FEATURE_64, 0 },
+ { "ppcle", PPC_FEATURE_PPC_LE, 0 },
+ { "smt", PPC_FEATURE_SMT, 0 },
+ { "spe", PPC_FEATURE_HAS_SPE, 0 },
+ { "true_le", PPC_FEATURE_TRUE_LE, 0 },
+ { "ucache", PPC_FEATURE_UNIFIED_CACHE, 0 },
+ { "vsx", PPC_FEATURE_HAS_VSX, 0 },
+
+ /* AT_HWCAP2 masks. */
+ { "arch_2_07", PPC_FEATURE2_ARCH_2_07, 1 },
+ { "dscr", PPC_FEATURE2_HAS_DSCR, 1 },
+ { "ebb", PPC_FEATURE2_HAS_EBB, 1 },
+ { "htm", PPC_FEATURE2_HAS_HTM, 1 },
+ { "htm-nosc", PPC_FEATURE2_HTM_NOSC, 1 },
+ { "isel", PPC_FEATURE2_HAS_ISEL, 1 },
+ { "tar", PPC_FEATURE2_HAS_TAR, 1 },
+ { "vcrypto", PPC_FEATURE2_HAS_VEC_CRYPTO, 1 },
+ { "arch_3_00", PPC_FEATURE2_ARCH_3_00, 1 },
+ { "ieee128", PPC_FEATURE2_HAS_IEEE128, 1 }
+};
+
+/* Newer LIBCs explicitly export this symbol to declare that they provide
+ the AT_PLATFORM and AT_HWCAP/AT_HWCAP2 values in the TCB. We emit a
+ reference to this symbol whenever we expand a CPU builtin, so that
+ we never link against an old LIBC. */
+const char *tcb_verification_symbol = "__parse_hwcap_and_convert_at_platform";
+
+/* True if we have expanded a CPU builtin. */
+bool cpu_builtin_p;
+
/* Pointer to function (in rs6000-c.c) that can define or undefine target
macros that have changed. Languages that don't support the preprocessor
don't link in rs6000-c.c, so we can't call it directly. */
return NULL_RTX;
}
+/* Expand the CPU builtin in FCODE and store the result in TARGET. */
+
+static rtx
+cpu_expand_builtin (enum rs6000_builtins fcode, tree exp ATTRIBUTE_UNUSED,
+ rtx target)
+{
+ /* __builtin_cpu_init () is a nop, so expand to nothing. */
+ if (fcode == RS6000_BUILTIN_CPU_INIT)
+ return const0_rtx;
+
+ if (target == 0 || GET_MODE (target) != SImode)
+ target = gen_reg_rtx (SImode);
+
+#ifdef TARGET_LIBC_PROVIDES_HWCAP_IN_TCB
+ tree arg = TREE_OPERAND (CALL_EXPR_ARG (exp, 0), 0);
+ if (TREE_CODE (arg) != STRING_CST)
+ {
+ error ("builtin %s only accepts a string argument",
+ rs6000_builtin_info[(size_t) fcode].name);
+ return const0_rtx;
+ }
+
+ if (fcode == RS6000_BUILTIN_CPU_IS)
+ {
+ const char *cpu = TREE_STRING_POINTER (arg);
+ rtx cpuid = NULL_RTX;
+ for (size_t i = 0; i < ARRAY_SIZE (cpu_is_info); i++)
+ if (strcmp (cpu, cpu_is_info[i].cpu) == 0)
+ {
+ /* The CPUID value in the TCB is offset by _DL_FIRST_PLATFORM. */
+ cpuid = GEN_INT (cpu_is_info[i].cpuid + _DL_FIRST_PLATFORM);
+ break;
+ }
+ if (cpuid == NULL_RTX)
+ {
+ /* Invalid CPU argument. */
+ error ("cpu %s is an invalid argument to builtin %s",
+ cpu, rs6000_builtin_info[(size_t) fcode].name);
+ return const0_rtx;
+ }
+
+ rtx platform = gen_reg_rtx (SImode);
+ rtx tcbmem = gen_const_mem (SImode,
+ gen_rtx_PLUS (Pmode,
+ gen_rtx_REG (Pmode, TLS_REGNUM),
+ GEN_INT (TCB_PLATFORM_OFFSET)));
+ emit_move_insn (platform, tcbmem);
+ emit_insn (gen_eqsi3 (target, platform, cpuid));
+ }
+ else if (fcode == RS6000_BUILTIN_CPU_SUPPORTS)
+ {
+ const char *hwcap = TREE_STRING_POINTER (arg);
+ rtx mask = NULL_RTX;
+ int hwcap_offset;
+ for (size_t i = 0; i < ARRAY_SIZE (cpu_supports_info); i++)
+ if (strcmp (hwcap, cpu_supports_info[i].hwcap) == 0)
+ {
+ mask = GEN_INT (cpu_supports_info[i].mask);
+ hwcap_offset = TCB_HWCAP_OFFSET (cpu_supports_info[i].id);
+ break;
+ }
+ if (mask == NULL_RTX)
+ {
+ /* Invalid HWCAP argument. */
+ error ("hwcap %s is an invalid argument to builtin %s",
+ hwcap, rs6000_builtin_info[(size_t) fcode].name);
+ return const0_rtx;
+ }
+
+ rtx tcb_hwcap = gen_reg_rtx (SImode);
+ rtx tcbmem = gen_const_mem (SImode,
+ gen_rtx_PLUS (Pmode,
+ gen_rtx_REG (Pmode, TLS_REGNUM),
+ GEN_INT (hwcap_offset)));
+ emit_move_insn (tcb_hwcap, tcbmem);
+ rtx scratch1 = gen_reg_rtx (SImode);
+ emit_insn (gen_rtx_SET (scratch1, gen_rtx_AND (SImode, tcb_hwcap, mask)));
+ rtx scratch2 = gen_reg_rtx (SImode);
+ emit_insn (gen_eqsi3 (scratch2, scratch1, const0_rtx));
+ emit_insn (gen_rtx_SET (target, gen_rtx_XOR (SImode, scratch2, const1_rtx)));
+ }
+
+ /* Record that we have expanded a CPU builtin, so that we can later
+ emit a reference to the special symbol exported by LIBC to ensure we
+ do not link against an old LIBC that doesn't support this feature. */
+ cpu_builtin_p = true;
+
+#else
+ /* For old LIBCs, always return FALSE. */
+ emit_move_insn (target, GEN_INT (0));
+#endif /* TARGET_LIBC_PROVIDES_HWCAP_IN_TCB */
+
+ return target;
+}
+
static rtx
rs6000_expand_ternop_builtin (enum insn_code icode, tree exp, rtx target)
{
case RS6000_BUILTIN_MTFSF:
return rs6000_expand_mtfsf_builtin (CODE_FOR_rs6000_mtfsf, exp);
+ case RS6000_BUILTIN_CPU_INIT:
+ case RS6000_BUILTIN_CPU_IS:
+ case RS6000_BUILTIN_CPU_SUPPORTS:
+ return cpu_expand_builtin (fcode, exp, target);
+
case ALTIVEC_BUILTIN_MASK_FOR_LOAD:
case ALTIVEC_BUILTIN_MASK_FOR_STORE:
{
NULL_TREE);
def_builtin ("__builtin_mtfsf", ftype, RS6000_BUILTIN_MTFSF);
+ ftype = build_function_type_list (void_type_node, NULL_TREE);
+ def_builtin ("__builtin_cpu_init", ftype, RS6000_BUILTIN_CPU_INIT);
+
+ ftype = build_function_type_list (bool_int_type_node, const_ptr_type_node,
+ NULL_TREE);
+ def_builtin ("__builtin_cpu_is", ftype, RS6000_BUILTIN_CPU_IS);
+ def_builtin ("__builtin_cpu_supports", ftype, RS6000_BUILTIN_CPU_SUPPORTS);
+
#if TARGET_XCOFF
/* AIX libm provides clog as __clog. */
if ((tdecl = builtin_decl_explicit (BUILT_IN_CLOG)) != NULL_TREE)
if (flag_split_stack)
file_end_indicate_split_stack ();
+
+ if (cpu_builtin_p)
+ {
+ /* We have expanded a CPU builtin, so we need to emit a reference to
+ the special symbol that LIBC uses to declare it supports the
+ AT_PLATFORM and AT_HWCAP/AT_HWCAP2 in the TCB feature. */
+ switch_to_section (data_section);
+ fprintf (asm_out_file, "\t.align %u\n", TARGET_32BIT ? 2 : 3);
+ fprintf (asm_out_file, "\t%s %s\n",
+ TARGET_32BIT ? ".long" : ".quad", tcb_verification_symbol);
+ }
}
#endif
/* Place to put static chain when calling a function that requires it. */
#define STATIC_CHAIN_REGNUM 11
+/* Base register for access to thread local storage variables. */
+#define TLS_REGNUM ((TARGET_64BIT) ? 13 : 2)
+
\f
/* Define the classes of registers for register constraints in the
machine description. Also define ranges of constants.
fi
+# Check if the target LIBC supports exporting the AT_PLATFORM and AT_HWCAP
+# values in the TCB. Currently, only GLIBC 2.23 and later support this.
+gcc_cv_libc_provides_hwcap_in_tcb=no
+case "$target" in
+ powerpc*-*-linux*)
+
+if test $glibc_version_major -gt 2 \
+ || ( test $glibc_version_major -eq 2 && test $glibc_version_minor -ge 23 ); then :
+ gcc_cv_libc_provides_hwcap_in_tcb=yes
+fi
+ ;;
+esac
+if test x$gcc_cv_libc_provides_hwcap_in_tcb = xyes; then
+
+$as_echo "#define TARGET_LIBC_PROVIDES_HWCAP_IN_TCB 1" >>confdefs.h
+
+fi
+
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking dl_iterate_phdr in target C library" >&5
$as_echo_n "checking dl_iterate_phdr in target C library... " >&6; }
gcc_cv_target_dl_iterate_phdr=unknown
[Define if TFmode long double should be the default])
fi
+# Check if the target LIBC supports exporting the AT_PLATFORM and AT_HWCAP
+# values in the TCB. Currently, only GLIBC 2.23 and later support this.
+gcc_cv_libc_provides_hwcap_in_tcb=no
+case "$target" in
+ powerpc*-*-linux*)
+ GCC_GLIBC_VERSION_GTE_IFELSE([2], [23], [gcc_cv_libc_provides_hwcap_in_tcb=yes], )
+ ;;
+esac
+if test x$gcc_cv_libc_provides_hwcap_in_tcb = xyes; then
+ AC_DEFINE(TARGET_LIBC_PROVIDES_HWCAP_IN_TCB, 1,
+ [Define if your target C Library provides the AT_HWCAP value in the TCB])
+fi
+
AC_MSG_CHECKING(dl_iterate_phdr in target C library)
gcc_cv_target_dl_iterate_phdr=unknown
case "$target" in
@node PowerPC Built-in Functions
@subsection PowerPC Built-in Functions
+The following built-in functions are always available and can be used to
+check the PowerPC target platform type:
+
+@deftypefn {Built-in Function} void __builtin_cpu_init (void)
+This function is a @code{nop} on the PowerPC platform and is included solely
+to maintain API compatibility with the x86 builtins.
+@end deftypefn
+
+@deftypefn {Built-in Function} int __builtin_cpu_is (const char *@var{cpuname})
+This function returns a value of @code{1} if the run-time CPU is of type
+@var{cpuname} and returns @code{0} otherwise. The following CPU names can be
+detected:
+
+@table @samp
+@item power9
+IBM POWER9 Server CPU.
+@item power8
+IBM POWER8 Server CPU.
+@item power7
+IBM POWER7 Server CPU.
+@item power6x
+IBM POWER6 Server CPU (RAW mode).
+@item power6
+IBM POWER6 Server CPU (Architected mode).
+@item power5+
+IBM POWER5+ Server CPU.
+@item power5
+IBM POWER5 Server CPU.
+@item ppc970
+IBM 970 Server CPU (ie, Apple G5).
+@item power4
+IBM POWER4 Server CPU.
+@item ppca2
+IBM A2 64-bit Embedded CPU
+@item ppc476
+IBM PowerPC 476FP 32-bit Embedded CPU.
+@item ppc464
+IBM PowerPC 464 32-bit Embedded CPU.
+@item ppc440
+PowerPC 440 32-bit Embedded CPU.
+@item ppc405
+PowerPC 405 32-bit Embedded CPU.
+@item ppc-cell-be
+IBM PowerPC Cell Broadband Engine Architecture CPU.
+@end table
+
+Here is an example:
+@smallexample
+if (__builtin_cpu_is ("power8"))
+ @{
+ do_power8 (); // POWER8 specific implementation.
+ @}
+else
+ @{
+ do_generic (); // Generic implementation.
+ @}
+@end smallexample
+@end deftypefn
+
+@deftypefn {Built-in Function} int __builtin_cpu_supports (const char *@var{feature})
+This function returns a value of @code{1} if the run-time CPU supports the HWCAP
+feature @var{feature} and returns @code{0} otherwise. The following features can be
+detected:
+
+@table @samp
+@item 4xxmac
+4xx CPU has a Multiply Accumulator.
+@item altivec
+CPU has a SIMD/Vector Unit.
+@item arch_2_05
+CPU supports ISA 2.05 (eg, POWER6)
+@item arch_2_06
+CPU supports ISA 2.06 (eg, POWER7)
+@item arch_2_07
+CPU supports ISA 2.07 (eg, POWER8)
+@item arch_3_00
+CPU supports ISA 3.00 (eg, POWER9)
+@item archpmu
+CPU supports the set of compatible performance monitoring events.
+@item booke
+CPU supports the Embedded ISA category.
+@item cellbe
+CPU has a CELL broadband engine.
+@item dfp
+CPU has a decimal floating point unit.
+@item dscr
+CPU supports the data stream control register.
+@item ebb
+CPU supports event base branching.
+@item efpdouble
+CPU has a SPE double precision floating point unit.
+@item efpsingle
+CPU has a SPE single precision floating point unit.
+@item fpu
+CPU has a floating point unit.
+@item htm
+CPU has hardware transaction memory instructions.
+@item htm-nosc
+Kernel aborts hardware transactions when a syscall is made.
+@item ic_snoop
+CPU supports icache snooping capabilities.
+@item ieee128
+CPU supports 128-bit IEEE binary floating point instructions.
+@item isel
+CPU supports the integer select instruction.
+@item mmu
+CPU has a memory management unit.
+@item notb
+CPU does not have a timebase (eg, 601 and 403gx).
+@item pa6t
+CPU supports the PA Semi 6T CORE ISA.
+@item power4
+CPU supports ISA 2.00 (eg, POWER4)
+@item power5
+CPU supports ISA 2.02 (eg, POWER5)
+@item power5+
+CPU supports ISA 2.03 (eg, POWER5+)
+@item power6x
+CPU supports ISA 2.05 (eg, POWER6) extended opcodes mffgpr and mftgpr.
+@item ppc32
+CPU supports 32-bit mode execution.
+@item ppc601
+CPU supports the old POWER ISA (eg, 601)
+@item ppc64
+CPU supports 64-bit mode execution.
+@item ppcle
+CPU supports a little-endian mode that uses address swizzling.
+@item smt
+CPU support simultaneous multi-threading.
+@item spe
+CPU has a signal processing extension unit.
+@item tar
+CPU supports the target address register.
+@item true_le
+CPU supports true little-endian mode.
+@item ucache
+CPU has unified I/D cache.
+@item vcrypto
+CPU supports the vector cryptography instructions.
+@item vsx
+CPU supports the vector-scalar extension.
+@end table
+
+Here is an example:
+@smallexample
+if (__builtin_cpu_supports ("fpu"))
+ @{
+ asm("fadd %0,%1,%2" : "=d"(dst) : "d"(src1), "d"(src2));
+ @}
+else
+ @{
+ dst = __fadd (src1, src2); // Software FP addition function.
+ @}
+@end smallexample
+@end deftypefn
+
These built-in functions are available for the PowerPC family of
processors:
@smallexample
+2016-01-20 Peter Bergner <bergner@vnet.ibm.com>
+
+ * gcc.target/powerpc/cpu-builtin-1.c: New test.
+
2016-01-20 Prathamesh Kulkarni <prathamesh.kulkarni@linaro.org>
PR c/24293
--- /dev/null
+/* { dg-do compile { target { powerpc*-*-* } } } */
+/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
+
+void
+use_cpu_is_builtins (unsigned int *p)
+{
+ p[0] = __builtin_cpu_is ("power9");
+ p[1] = __builtin_cpu_is ("power8");
+ p[2] = __builtin_cpu_is ("power7");
+ p[3] = __builtin_cpu_is ("power6x");
+ p[4] = __builtin_cpu_is ("power6");
+ p[5] = __builtin_cpu_is ("power5+");
+ p[6] = __builtin_cpu_is ("power5");
+ p[7] = __builtin_cpu_is ("ppc970");
+ p[8] = __builtin_cpu_is ("power4");
+ p[9] = __builtin_cpu_is ("ppca2");
+ p[10] = __builtin_cpu_is ("ppc476");
+ p[11] = __builtin_cpu_is ("ppc464");
+ p[12] = __builtin_cpu_is ("ppc440");
+ p[13] = __builtin_cpu_is ("ppc405");
+ p[14] = __builtin_cpu_is ("ppc-cell-be");
+}
+
+void
+use_cpu_supports_builtins (unsigned int *p)
+{
+ p[0] = __builtin_cpu_supports ("4xxmac");
+ p[1] = __builtin_cpu_supports ("altivec");
+ p[2] = __builtin_cpu_supports ("arch_2_05");
+ p[3] = __builtin_cpu_supports ("arch_2_06");
+ p[4] = __builtin_cpu_supports ("arch_2_07");
+ p[5] = __builtin_cpu_supports ("arch_3_00");
+ p[6] = __builtin_cpu_supports ("archpmu");
+ p[7] = __builtin_cpu_supports ("booke");
+ p[8] = __builtin_cpu_supports ("cellbe");
+ p[9] = __builtin_cpu_supports ("dfp");
+ p[10] = __builtin_cpu_supports ("dscr");
+ p[11] = __builtin_cpu_supports ("ebb");
+ p[12] = __builtin_cpu_supports ("efpdouble");
+ p[13] = __builtin_cpu_supports ("efpsingle");
+ p[14] = __builtin_cpu_supports ("fpu");
+ p[15] = __builtin_cpu_supports ("htm");
+ p[16] = __builtin_cpu_supports ("htm-nosc");
+ p[17] = __builtin_cpu_supports ("ic_snoop");
+ p[18] = __builtin_cpu_supports ("ieee128");
+ p[19] = __builtin_cpu_supports ("isel");
+ p[20] = __builtin_cpu_supports ("mmu");
+ p[21] = __builtin_cpu_supports ("notb");
+ p[22] = __builtin_cpu_supports ("pa6t");
+ p[23] = __builtin_cpu_supports ("power4");
+ p[24] = __builtin_cpu_supports ("power5");
+ p[25] = __builtin_cpu_supports ("power5+");
+ p[26] = __builtin_cpu_supports ("power6x");
+ p[27] = __builtin_cpu_supports ("ppc32");
+ p[28] = __builtin_cpu_supports ("ppc601");
+ p[29] = __builtin_cpu_supports ("ppc64");
+ p[30] = __builtin_cpu_supports ("ppcle");
+ p[31] = __builtin_cpu_supports ("smt");
+ p[32] = __builtin_cpu_supports ("spe");
+ p[33] = __builtin_cpu_supports ("tar");
+ p[34] = __builtin_cpu_supports ("true_le");
+ p[35] = __builtin_cpu_supports ("ucache");
+ p[36] = __builtin_cpu_supports ("vcrypto");
+ p[37] = __builtin_cpu_supports ("vsx");
+}