From: Peter Bergner Date: Wed, 20 Jan 2016 20:30:24 +0000 (-0600) Subject: ppc-auxv.h: New file. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=26a2e6aed46f0690aee229788887908b7116f515;p=gcc.git ppc-auxv.h: New file. gcc/ * 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. gcc/testsuite/ * gcc.target/powerpc/cpu-builtin-1.c: New test. From-SVN: r232634 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index ee05d496695..f2eb93636f0 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,25 @@ +2016-01-20 Peter Bergner + + * 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 PR target/68609 diff --git a/gcc/config.in b/gcc/config.in index c3340bb0901..1796e1d895e 100644 --- a/gcc/config.in +++ b/gcc/config.in @@ -2074,6 +2074,12 @@ #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 diff --git a/gcc/config/rs6000/ppc-auxv.h b/gcc/config/rs6000/ppc-auxv.h new file mode 100644 index 00000000000..590fdb8a298 --- /dev/null +++ b/gcc/config/rs6000/ppc-auxv.h @@ -0,0 +1,105 @@ +/* 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 . + + 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 + . */ + +#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 */ diff --git a/gcc/config/rs6000/rs6000-builtin.def b/gcc/config/rs6000/rs6000-builtin.def index 709992b3772..5b82b00449e 100644 --- a/gcc/config/rs6000/rs6000-builtin.def +++ b/gcc/config/rs6000/rs6000-builtin.def @@ -2013,6 +2013,15 @@ RS6000_BUILTIN_X (RS6000_BUILTIN_MTFSF, "__builtin_mtfsf", 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) diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index 539446ce45f..b0ce68e5b38 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -71,6 +71,7 @@ #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" @@ -293,6 +294,88 @@ static struct { "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. */ @@ -13380,6 +13463,101 @@ htm_expand_builtin (tree exp, rtx target, bool * expandedp) 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) { @@ -14706,6 +14884,11 @@ rs6000_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED, 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: { @@ -15095,6 +15278,14 @@ rs6000_init_builtins (void) 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) @@ -31601,6 +31792,17 @@ rs6000_elf_file_end (void) 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 diff --git a/gcc/config/rs6000/rs6000.h b/gcc/config/rs6000/rs6000.h index 6b0e64e693d..8c6bd07dd5e 100644 --- a/gcc/config/rs6000/rs6000.h +++ b/gcc/config/rs6000/rs6000.h @@ -1361,6 +1361,9 @@ enum data_align { align_abi, align_opt, align_both }; /* 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) + /* Define the classes of registers for register constraints in the machine description. Also define ranges of constants. diff --git a/gcc/configure b/gcc/configure index 7db75526dd2..42e97a8a8af 100755 --- a/gcc/configure +++ b/gcc/configure @@ -28539,6 +28539,24 @@ $as_echo "#define TARGET_DEFAULT_LONG_DOUBLE_128 1" >>confdefs.h 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 diff --git a/gcc/configure.ac b/gcc/configure.ac index 8d3a86943af..bf38dfe986b 100644 --- a/gcc/configure.ac +++ b/gcc/configure.ac @@ -5544,6 +5544,19 @@ if test x$gcc_cv_target_ldbl128 = xyes; then [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 diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi index a78282211dd..0dab6465b70 100644 --- a/gcc/doc/extend.texi +++ b/gcc/doc/extend.texi @@ -13527,6 +13527,162 @@ implementing assertions. @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 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index a2c9ba919dc..bd23b365483 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2016-01-20 Peter Bergner + + * gcc.target/powerpc/cpu-builtin-1.c: New test. + 2016-01-20 Prathamesh Kulkarni PR c/24293 diff --git a/gcc/testsuite/gcc.target/powerpc/cpu-builtin-1.c b/gcc/testsuite/gcc.target/powerpc/cpu-builtin-1.c new file mode 100644 index 00000000000..a0e30410050 --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/cpu-builtin-1.c @@ -0,0 +1,65 @@ +/* { 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"); +}