From: Rainer Orth Date: Thu, 10 May 2012 08:51:39 +0000 (+0000) Subject: Use i386-cpuinfo.c on all i386 targets X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=aca06c900e84dcbd57eaee3e94011a1710ef1e4e;p=gcc.git Use i386-cpuinfo.c on all i386 targets libgcc: * config.host (i[34567]86-*-linux*, x86_64-*-linux*) (i[34567]86-*-kfreebsd*-gnu, x86_64-*-kfreebsd*-gnu) (i[34567]86-*-knetbsd*-gnu, i[34567]86-*-gnu*): Move i386/t-cpuinfo ... (i[34567]86-*-*, x86_64-*-*): ... here. * config/i386/libgcc-bsd.ver (GCC_4.8.0): New version. * config/i386/libgcc-sol2.ver (GCC_4.8.0): New version. * config/i386/i386-cpuinfo.c: Rename to ... * config/i386/cpuinfo.c: ... this. * config/i386/t-cpuinfo (LIB2ADD): Reflect this. * configure.ac (AC_CONFIG_HEADER): Call for auto-target.h. (libgcc_cv_init_priority): New test. * configure: Regenerate. * config.in: New file. * Makefile.in (clean): Rename config.h to auto-target.h. (config.h): Likewise. (stamp-h): Likewise. * config/i386/cpuinfo.c (auto-target.h): Include. (CONSTRUCTOR_PRIORITY): Define. (__cpu_indicator_init): Use it. gcc * doc/extend.texi (X86 Built-in Functions, __builtin_cpu_init): Document requirement to call in constructors. * config/i386/i386.c: Update comments for i386-cpuinfo.c name change. From-SVN: r187365 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index afe2c63f6d9..7a8814afe10 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +2012-05-10 Rainer Orth + + * doc/extend.texi (X86 Built-in Functions, __builtin_cpu_init): + Document requirement to call in constructors. + + * config/i386/i386.c: Update comments for i386-cpuinfo.c name + change. + 2012-05-10 Richard Guenther * tree.h (TYPE_IS_SIZETYPE): Remove. diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index 36370b2f6d1..8c97054395d 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -27665,7 +27665,7 @@ ix86_init_mmx_sse_builtins (void) } /* This builds the processor_model struct type defined in - libgcc/config/i386/i386-cpuinfo.c */ + libgcc/config/i386/cpuinfo.c */ static tree build_processor_model_struct (void) @@ -27725,7 +27725,7 @@ make_var_decl (tree type, const char *name) } /* FNDECL is a __builtin_cpu_is or a __builtin_cpu_supports call that is folded - into an integer defined in libgcc/config/i386/i386-cpuinfo.c */ + into an integer defined in libgcc/config/i386/cpuinfo.c */ static tree fold_builtin_cpu (tree fndecl, tree *args) @@ -27735,8 +27735,7 @@ fold_builtin_cpu (tree fndecl, tree *args) DECL_FUNCTION_CODE (fndecl); tree param_string_cst = NULL; - /* This is the order of bit-fields in __processor_features in - i386-cpuinfo.c */ + /* This is the order of bit-fields in __processor_features in cpuinfo.c */ enum processor_features { F_CMOV = 0, @@ -27754,7 +27753,7 @@ fold_builtin_cpu (tree fndecl, tree *args) }; /* These are the values for vendor types and cpu types and subtypes - in i386-cpuinfo.c. Cpu types and subtypes should be subtracted by + in cpuinfo.c. Cpu types and subtypes should be subtracted by the corresponding start value. */ enum processor_model { diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi index 53ce2b38f34..6aaf4535647 100644 --- a/gcc/doc/extend.texi +++ b/gcc/doc/extend.texi @@ -9449,8 +9449,9 @@ executed before any constructors are called. The CPU detection code is automatically executed in a very high priority constructor. For example, this function has to be used in @code{ifunc} resolvers which -check for CPU type using the builtins, @code{__builtin_cpu_is} -and @code{__builtin_cpu_supports}. +check for CPU type using the builtins @code{__builtin_cpu_is} +and @code{__builtin_cpu_supports}, or in constructors on targets which +don't support constructor priority. @smallexample static void (*resolve_memcpy (void)) (void) diff --git a/libgcc/ChangeLog b/libgcc/ChangeLog index b78368619e2..05478d68560 100644 --- a/libgcc/ChangeLog +++ b/libgcc/ChangeLog @@ -1,3 +1,30 @@ +2012-05-10 Rainer Orth + + * config.host (i[34567]86-*-linux*, x86_64-*-linux*) + (i[34567]86-*-kfreebsd*-gnu, x86_64-*-kfreebsd*-gnu) + (i[34567]86-*-knetbsd*-gnu, i[34567]86-*-gnu*): Move + i386/t-cpuinfo ... + (i[34567]86-*-*, x86_64-*-*): ... here. + + * config/i386/libgcc-bsd.ver (GCC_4.8.0): New version. + * config/i386/libgcc-sol2.ver (GCC_4.8.0): New version. + + * config/i386/i386-cpuinfo.c: Rename to ... + * config/i386/cpuinfo.c: ... this. + * config/i386/t-cpuinfo (LIB2ADD): Reflect this. + + * configure.ac (AC_CONFIG_HEADER): Call for auto-target.h. + (libgcc_cv_init_priority): New test. + * configure: Regenerate. + * config.in: New file. + * Makefile.in (clean): Rename config.h to auto-target.h. + (config.h): Likewise. + (stamp-h): Likewise. + + * config/i386/cpuinfo.c (auto-target.h): Include. + (CONSTRUCTOR_PRIORITY): Define. + (__cpu_indicator_init): Use it. + 2012-05-09 H.J. Lu * longlong.h: Use a URL instead of an FSF postal address. diff --git a/libgcc/Makefile.in b/libgcc/Makefile.in index e9ea2e9c90d..f529fa22195 100644 --- a/libgcc/Makefile.in +++ b/libgcc/Makefile.in @@ -121,7 +121,7 @@ installcheck: .PHONY: all clean clean: - -rm -f config.h libgcc_tm.h stamp-h stmp-ldirs libgcc.map + -rm -f auto-target.h libgcc_tm.h stamp-h stmp-ldirs libgcc.map -rm -f *$(objext) -rm -f *.dep -rm -f *.a @@ -139,9 +139,9 @@ Makefile: $(srcdir)/Makefile.in config.status # Depending on Makefile makes sure that config.status has been re-run # if needed. This prevents problems with parallel builds. -config.h: stamp-h ; @true +auto-target.h: stamp-h ; @true stamp-h: $(srcdir)/config.in config.status Makefile - CONFIG_FILES= CONFIG_HEADERS=config.h:$(srcdir)/config.in $(SHELL) ./config.status + CONFIG_FILES= CONFIG_HEADERS=auto-target.h:$(srcdir)/config.in $(SHELL) ./config.status config.status: $(srcdir)/configure $(srcdir)/config.host $(SHELL) ./config.status --recheck diff --git a/libgcc/config.host b/libgcc/config.host index 2dbb95b6d76..14c705b967b 100644 --- a/libgcc/config.host +++ b/libgcc/config.host @@ -1123,12 +1123,18 @@ mep*-*-*) ;; esac +case ${host} in +i[34567]86-*-* | x86_64-*-*) + tmake_file="${tmake_file} i386/t-cpuinfo" + ;; +esac + case ${host} in i[34567]86-*-linux* | x86_64-*-linux* | \ i[34567]86-*-kfreebsd*-gnu | x86_64-*-kfreebsd*-gnu | \ i[34567]86-*-knetbsd*-gnu | \ i[34567]86-*-gnu*) - tmake_file="${tmake_file} t-tls i386/t-linux i386/t-cpuinfo" + tmake_file="${tmake_file} t-tls i386/t-linux" if test "$libgcc_cv_cfi" = "yes"; then tmake_file="${tmake_file} t-stack i386/t-stack-i386" fi diff --git a/libgcc/config.in b/libgcc/config.in new file mode 100644 index 00000000000..4baab989197 --- /dev/null +++ b/libgcc/config.in @@ -0,0 +1,70 @@ +/* config.in. Generated from configure.ac by autoheader. */ + +/* Define to 1 if the target assembler supports thread-local storage. */ +#undef HAVE_CC_TLS + +/* Define if _Unwind_GetIPInfo is available. */ +#undef HAVE_GETIPINFO + +/* Define if the compiler supports init priority. */ +#undef HAVE_INIT_PRIORITY + +/* Define to 1 if you have the header file. */ +#undef HAVE_INTTYPES_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_MEMORY_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDINT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDLIB_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRINGS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRING_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_STAT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_TYPES_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_UNISTD_H + +/* Define if the C compiler is configured for setjmp/longjmp exceptions. */ +#undef LIBGCC_SJLJ_EXCEPTIONS + +/* Define to the address where bug reports for this package should be sent. */ +#undef PACKAGE_BUGREPORT + +/* Define to the full name of this package. */ +#undef PACKAGE_NAME + +/* Define to the full name and version of this package. */ +#undef PACKAGE_STRING + +/* Define to the one symbol short name of this package. */ +#undef PACKAGE_TARNAME + +/* Define to the home page for this package. */ +#undef PACKAGE_URL + +/* Define to the version of this package. */ +#undef PACKAGE_VERSION + +/* The size of `double', as computed by sizeof. */ +#undef SIZEOF_DOUBLE + +/* The size of `long double', as computed by sizeof. */ +#undef SIZEOF_LONG_DOUBLE + +/* Define to 1 if you have the ANSI C header files. */ +#undef STDC_HEADERS + +/* Define to 1 if the target use emutls for thread-local storage. */ +#undef USE_EMUTLS diff --git a/libgcc/config/i386/cpuinfo.c b/libgcc/config/i386/cpuinfo.c new file mode 100644 index 00000000000..1c22d7a4070 --- /dev/null +++ b/libgcc/config/i386/cpuinfo.c @@ -0,0 +1,346 @@ +/* Get CPU type and Features for x86 processors. + Copyright (C) 2012 Free Software Foundation, Inc. + Contributed by Sriraman Tallam (tmsriram@google.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. + +You should have received a copy of the GNU General Public License +along with GCC; see the file COPYING3. If not see +. */ + +#include "cpuid.h" +#include "tsystem.h" +#include "auto-target.h" + +#ifdef HAVE_INIT_PRIORITY +#define CONSTRUCTOR_PRIORITY (101) +#else +#define CONSTRUCTOR_PRIORITY +#endif + +int __cpu_indicator_init (void) + __attribute__ ((constructor CONSTRUCTOR_PRIORITY)); + +enum vendor_signatures +{ + SIG_INTEL = 0x756e6547 /* Genu */, + SIG_AMD = 0x68747541 /* Auth */ +}; + +/* Processor Vendor and Models. */ + +enum processor_vendor +{ + VENDOR_INTEL = 1, + VENDOR_AMD, + VENDOR_OTHER, + VENDOR_MAX +}; + +enum processor_types +{ + INTEL_ATOM = 1, + INTEL_CORE2, + INTEL_COREI7, + AMDFAM10H, + AMDFAM15H, + CPU_TYPE_MAX +}; + +enum processor_subtypes +{ + INTEL_COREI7_NEHALEM = 1, + INTEL_COREI7_WESTMERE, + INTEL_COREI7_SANDYBRIDGE, + AMDFAM10H_BARCELONA, + AMDFAM10H_SHANGHAI, + AMDFAM10H_ISTANBUL, + AMDFAM15H_BDVER1, + AMDFAM15H_BDVER2, + CPU_SUBTYPE_MAX +}; + +/* ISA Features supported. */ + +enum processor_features +{ + FEATURE_CMOV = 0, + FEATURE_MMX, + FEATURE_POPCNT, + FEATURE_SSE, + FEATURE_SSE2, + FEATURE_SSE3, + FEATURE_SSSE3, + FEATURE_SSE4_1, + FEATURE_SSE4_2, + FEATURE_AVX, + FEATURE_AVX2 +}; + +struct __processor_model +{ + unsigned int __cpu_vendor; + unsigned int __cpu_type; + unsigned int __cpu_subtype; + unsigned int __cpu_features[1]; +} __cpu_model; + + +/* Get the specific type of AMD CPU. */ + +static void +get_amd_cpu (unsigned int family, unsigned int model) +{ + switch (family) + { + /* AMD Family 10h. */ + case 0x10: + switch (model) + { + case 0x2: + /* Barcelona. */ + __cpu_model.__cpu_type = AMDFAM10H; + __cpu_model.__cpu_subtype = AMDFAM10H_BARCELONA; + break; + case 0x4: + /* Shanghai. */ + __cpu_model.__cpu_type = AMDFAM10H; + __cpu_model.__cpu_subtype = AMDFAM10H_SHANGHAI; + break; + case 0x8: + /* Istanbul. */ + __cpu_model.__cpu_type = AMDFAM10H; + __cpu_model.__cpu_subtype = AMDFAM10H_ISTANBUL; + break; + default: + break; + } + break; + /* AMD Family 15h. */ + case 0x15: + __cpu_model.__cpu_type = AMDFAM15H; + /* Bulldozer version 1. */ + if ( model <= 0xf) + __cpu_model.__cpu_subtype = AMDFAM15H_BDVER1; + /* Bulldozer version 2. */ + if (model >= 0x10 && model <= 0x1f) + __cpu_model.__cpu_subtype = AMDFAM15H_BDVER2; + break; + default: + break; + } +} + +/* Get the specific type of Intel CPU. */ + +static void +get_intel_cpu (unsigned int family, unsigned int model, unsigned int brand_id) +{ + /* Parse family and model only if brand ID is 0. */ + if (brand_id == 0) + { + switch (family) + { + case 0x5: + /* Pentium. */ + break; + case 0x6: + switch (model) + { + case 0x1c: + case 0x26: + /* Atom. */ + __cpu_model.__cpu_type = INTEL_ATOM; + break; + case 0x1a: + case 0x1e: + case 0x1f: + case 0x2e: + /* Nehalem. */ + __cpu_model.__cpu_type = INTEL_COREI7; + __cpu_model.__cpu_subtype = INTEL_COREI7_NEHALEM; + break; + case 0x25: + case 0x2c: + case 0x2f: + /* Westmere. */ + __cpu_model.__cpu_type = INTEL_COREI7; + __cpu_model.__cpu_subtype = INTEL_COREI7_WESTMERE; + break; + case 0x2a: + /* Sandy Bridge. */ + __cpu_model.__cpu_type = INTEL_COREI7; + __cpu_model.__cpu_subtype = INTEL_COREI7_SANDYBRIDGE; + break; + case 0x17: + case 0x1d: + /* Penryn. */ + case 0x0f: + /* Merom. */ + __cpu_model.__cpu_type = INTEL_CORE2; + break; + default: + break; + } + break; + default: + /* We have no idea. */ + break; + } + } +} + +/* ECX and EDX are output of CPUID at level one. MAX_CPUID_LEVEL is + the max possible level of CPUID insn. */ +static void +get_available_features (unsigned int ecx, unsigned int edx, + int max_cpuid_level) +{ + unsigned int features = 0; + + if (edx & bit_CMOV) + features |= (1 << FEATURE_CMOV); + if (edx & bit_MMX) + features |= (1 << FEATURE_MMX); + if (edx & bit_SSE) + features |= (1 << FEATURE_SSE); + if (edx & bit_SSE2) + features |= (1 << FEATURE_SSE2); + if (ecx & bit_POPCNT) + features |= (1 << FEATURE_POPCNT); + if (ecx & bit_SSE3) + features |= (1 << FEATURE_SSE3); + if (ecx & bit_SSSE3) + features |= (1 << FEATURE_SSSE3); + if (ecx & bit_SSE4_1) + features |= (1 << FEATURE_SSE4_1); + if (ecx & bit_SSE4_2) + features |= (1 << FEATURE_SSE4_2); + if (ecx & bit_AVX) + features |= (1 << FEATURE_AVX); + + /* Get Advanced Features at level 7 (eax = 7, ecx = 0). */ + if (max_cpuid_level >= 7) + { + unsigned int eax, ebx, ecx, edx; + __cpuid_count (7, 0, eax, ebx, ecx, edx); + if (ebx & bit_AVX2) + features |= (1 << FEATURE_AVX2); + } + + __cpu_model.__cpu_features[0] = features; +} + +/* A noinline function calling __get_cpuid. Having many calls to + cpuid in one function in 32-bit mode causes GCC to complain: + "can't find a register in class CLOBBERED_REGS". This is + related to PR rtl-optimization 44174. */ + +static int __attribute__ ((noinline)) +__get_cpuid_output (unsigned int __level, + unsigned int *__eax, unsigned int *__ebx, + unsigned int *__ecx, unsigned int *__edx) +{ + return __get_cpuid (__level, __eax, __ebx, __ecx, __edx); +} + + +/* A constructor function that is sets __cpu_model and __cpu_features with + the right values. This needs to run only once. This constructor is + given the highest priority and it should run before constructors without + the priority set. However, it still runs after ifunc initializers and + needs to be called explicitly there. */ + +int __attribute__ ((constructor CONSTRUCTOR_PRIORITY)) +__cpu_indicator_init (void) +{ + unsigned int eax, ebx, ecx, edx; + + int max_level = 5; + unsigned int vendor; + unsigned int model, family, brand_id; + unsigned int extended_model, extended_family; + + /* This function needs to run just once. */ + if (__cpu_model.__cpu_vendor) + return 0; + + /* Assume cpuid insn present. Run in level 0 to get vendor id. */ + if (!__get_cpuid_output (0, &eax, &ebx, &ecx, &edx)) + { + __cpu_model.__cpu_vendor = VENDOR_OTHER; + return -1; + } + + vendor = ebx; + max_level = eax; + + if (max_level < 1) + { + __cpu_model.__cpu_vendor = VENDOR_OTHER; + return -1; + } + + if (!__get_cpuid_output (1, &eax, &ebx, &ecx, &edx)) + { + __cpu_model.__cpu_vendor = VENDOR_OTHER; + return -1; + } + + model = (eax >> 4) & 0x0f; + family = (eax >> 8) & 0x0f; + brand_id = ebx & 0xff; + extended_model = (eax >> 12) & 0xf0; + extended_family = (eax >> 20) & 0xff; + + if (vendor == SIG_INTEL) + { + /* Adjust model and family for Intel CPUS. */ + if (family == 0x0f) + { + family += extended_family; + model += extended_model; + } + else if (family == 0x06) + model += extended_model; + + /* Get CPU type. */ + get_intel_cpu (family, model, brand_id); + /* Find available features. */ + get_available_features (ecx, edx, max_level); + __cpu_model.__cpu_vendor = VENDOR_INTEL; + } + else if (vendor == SIG_AMD) + { + /* Adjust model and family for AMD CPUS. */ + if (family == 0x0f) + { + family += extended_family; + model += (extended_model << 4); + } + + /* Get CPU type. */ + get_amd_cpu (family, model); + /* Find available features. */ + get_available_features (ecx, edx, max_level); + __cpu_model.__cpu_vendor = VENDOR_AMD; + } + else + __cpu_model.__cpu_vendor = VENDOR_OTHER; + + gcc_assert (__cpu_model.__cpu_vendor < VENDOR_MAX); + gcc_assert (__cpu_model.__cpu_type < CPU_TYPE_MAX); + gcc_assert (__cpu_model.__cpu_subtype < CPU_SUBTYPE_MAX); + + return 0; +} diff --git a/libgcc/config/i386/i386-cpuinfo.c b/libgcc/config/i386/i386-cpuinfo.c deleted file mode 100644 index 6934778c0fc..00000000000 --- a/libgcc/config/i386/i386-cpuinfo.c +++ /dev/null @@ -1,338 +0,0 @@ -/* Get CPU type and Features for x86 processors. - Copyright (C) 2012 Free Software Foundation, Inc. - Contributed by Sriraman Tallam (tmsriram@google.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. - -You should have received a copy of the GNU General Public License -along with GCC; see the file COPYING3. If not see -. */ - -#include "cpuid.h" -#include "tsystem.h" - -int __cpu_indicator_init (void) __attribute__ ((constructor (101))); - -enum vendor_signatures -{ - SIG_INTEL = 0x756e6547 /* Genu */, - SIG_AMD = 0x68747541 /* Auth */ -}; - -/* Processor Vendor and Models. */ - -enum processor_vendor -{ - VENDOR_INTEL = 1, - VENDOR_AMD, - VENDOR_OTHER, - VENDOR_MAX -}; - -enum processor_types -{ - INTEL_ATOM = 1, - INTEL_CORE2, - INTEL_COREI7, - AMDFAM10H, - AMDFAM15H, - CPU_TYPE_MAX -}; - -enum processor_subtypes -{ - INTEL_COREI7_NEHALEM = 1, - INTEL_COREI7_WESTMERE, - INTEL_COREI7_SANDYBRIDGE, - AMDFAM10H_BARCELONA, - AMDFAM10H_SHANGHAI, - AMDFAM10H_ISTANBUL, - AMDFAM15H_BDVER1, - AMDFAM15H_BDVER2, - CPU_SUBTYPE_MAX -}; - -/* ISA Features supported. */ - -enum processor_features -{ - FEATURE_CMOV = 0, - FEATURE_MMX, - FEATURE_POPCNT, - FEATURE_SSE, - FEATURE_SSE2, - FEATURE_SSE3, - FEATURE_SSSE3, - FEATURE_SSE4_1, - FEATURE_SSE4_2, - FEATURE_AVX, - FEATURE_AVX2 -}; - -struct __processor_model -{ - unsigned int __cpu_vendor; - unsigned int __cpu_type; - unsigned int __cpu_subtype; - unsigned int __cpu_features[1]; -} __cpu_model; - - -/* Get the specific type of AMD CPU. */ - -static void -get_amd_cpu (unsigned int family, unsigned int model) -{ - switch (family) - { - /* AMD Family 10h. */ - case 0x10: - switch (model) - { - case 0x2: - /* Barcelona. */ - __cpu_model.__cpu_type = AMDFAM10H; - __cpu_model.__cpu_subtype = AMDFAM10H_BARCELONA; - break; - case 0x4: - /* Shanghai. */ - __cpu_model.__cpu_type = AMDFAM10H; - __cpu_model.__cpu_subtype = AMDFAM10H_SHANGHAI; - break; - case 0x8: - /* Istanbul. */ - __cpu_model.__cpu_type = AMDFAM10H; - __cpu_model.__cpu_subtype = AMDFAM10H_ISTANBUL; - break; - default: - break; - } - break; - /* AMD Family 15h. */ - case 0x15: - __cpu_model.__cpu_type = AMDFAM15H; - /* Bulldozer version 1. */ - if ( model <= 0xf) - __cpu_model.__cpu_subtype = AMDFAM15H_BDVER1; - /* Bulldozer version 2. */ - if (model >= 0x10 && model <= 0x1f) - __cpu_model.__cpu_subtype = AMDFAM15H_BDVER2; - break; - default: - break; - } -} - -/* Get the specific type of Intel CPU. */ - -static void -get_intel_cpu (unsigned int family, unsigned int model, unsigned int brand_id) -{ - /* Parse family and model only if brand ID is 0. */ - if (brand_id == 0) - { - switch (family) - { - case 0x5: - /* Pentium. */ - break; - case 0x6: - switch (model) - { - case 0x1c: - case 0x26: - /* Atom. */ - __cpu_model.__cpu_type = INTEL_ATOM; - break; - case 0x1a: - case 0x1e: - case 0x1f: - case 0x2e: - /* Nehalem. */ - __cpu_model.__cpu_type = INTEL_COREI7; - __cpu_model.__cpu_subtype = INTEL_COREI7_NEHALEM; - break; - case 0x25: - case 0x2c: - case 0x2f: - /* Westmere. */ - __cpu_model.__cpu_type = INTEL_COREI7; - __cpu_model.__cpu_subtype = INTEL_COREI7_WESTMERE; - break; - case 0x2a: - /* Sandy Bridge. */ - __cpu_model.__cpu_type = INTEL_COREI7; - __cpu_model.__cpu_subtype = INTEL_COREI7_SANDYBRIDGE; - break; - case 0x17: - case 0x1d: - /* Penryn. */ - case 0x0f: - /* Merom. */ - __cpu_model.__cpu_type = INTEL_CORE2; - break; - default: - break; - } - break; - default: - /* We have no idea. */ - break; - } - } -} - -/* ECX and EDX are output of CPUID at level one. MAX_CPUID_LEVEL is - the max possible level of CPUID insn. */ -static void -get_available_features (unsigned int ecx, unsigned int edx, - int max_cpuid_level) -{ - unsigned int features = 0; - - if (edx & bit_CMOV) - features |= (1 << FEATURE_CMOV); - if (edx & bit_MMX) - features |= (1 << FEATURE_MMX); - if (edx & bit_SSE) - features |= (1 << FEATURE_SSE); - if (edx & bit_SSE2) - features |= (1 << FEATURE_SSE2); - if (ecx & bit_POPCNT) - features |= (1 << FEATURE_POPCNT); - if (ecx & bit_SSE3) - features |= (1 << FEATURE_SSE3); - if (ecx & bit_SSSE3) - features |= (1 << FEATURE_SSSE3); - if (ecx & bit_SSE4_1) - features |= (1 << FEATURE_SSE4_1); - if (ecx & bit_SSE4_2) - features |= (1 << FEATURE_SSE4_2); - if (ecx & bit_AVX) - features |= (1 << FEATURE_AVX); - - /* Get Advanced Features at level 7 (eax = 7, ecx = 0). */ - if (max_cpuid_level >= 7) - { - unsigned int eax, ebx, ecx, edx; - __cpuid_count (7, 0, eax, ebx, ecx, edx); - if (ebx & bit_AVX2) - features |= (1 << FEATURE_AVX2); - } - - __cpu_model.__cpu_features[0] = features; -} - -/* A noinline function calling __get_cpuid. Having many calls to - cpuid in one function in 32-bit mode causes GCC to complain: - "can't find a register in class CLOBBERED_REGS". This is - related to PR rtl-optimization 44174. */ - -static int __attribute__ ((noinline)) -__get_cpuid_output (unsigned int __level, - unsigned int *__eax, unsigned int *__ebx, - unsigned int *__ecx, unsigned int *__edx) -{ - return __get_cpuid (__level, __eax, __ebx, __ecx, __edx); -} - - -/* A constructor function that is sets __cpu_model and __cpu_features with - the right values. This needs to run only once. This constructor is - given the highest priority and it should run before constructors without - the priority set. However, it still runs after ifunc initializers and - needs to be called explicitly there. */ - -int __attribute__ ((constructor (101))) -__cpu_indicator_init (void) -{ - unsigned int eax, ebx, ecx, edx; - - int max_level = 5; - unsigned int vendor; - unsigned int model, family, brand_id; - unsigned int extended_model, extended_family; - - /* This function needs to run just once. */ - if (__cpu_model.__cpu_vendor) - return 0; - - /* Assume cpuid insn present. Run in level 0 to get vendor id. */ - if (!__get_cpuid_output (0, &eax, &ebx, &ecx, &edx)) - { - __cpu_model.__cpu_vendor = VENDOR_OTHER; - return -1; - } - - vendor = ebx; - max_level = eax; - - if (max_level < 1) - { - __cpu_model.__cpu_vendor = VENDOR_OTHER; - return -1; - } - - if (!__get_cpuid_output (1, &eax, &ebx, &ecx, &edx)) - { - __cpu_model.__cpu_vendor = VENDOR_OTHER; - return -1; - } - - model = (eax >> 4) & 0x0f; - family = (eax >> 8) & 0x0f; - brand_id = ebx & 0xff; - extended_model = (eax >> 12) & 0xf0; - extended_family = (eax >> 20) & 0xff; - - if (vendor == SIG_INTEL) - { - /* Adjust model and family for Intel CPUS. */ - if (family == 0x0f) - { - family += extended_family; - model += extended_model; - } - else if (family == 0x06) - model += extended_model; - - /* Get CPU type. */ - get_intel_cpu (family, model, brand_id); - /* Find available features. */ - get_available_features (ecx, edx, max_level); - __cpu_model.__cpu_vendor = VENDOR_INTEL; - } - else if (vendor == SIG_AMD) - { - /* Adjust model and family for AMD CPUS. */ - if (family == 0x0f) - { - family += extended_family; - model += (extended_model << 4); - } - - /* Get CPU type. */ - get_amd_cpu (family, model); - /* Find available features. */ - get_available_features (ecx, edx, max_level); - __cpu_model.__cpu_vendor = VENDOR_AMD; - } - else - __cpu_model.__cpu_vendor = VENDOR_OTHER; - - gcc_assert (__cpu_model.__cpu_vendor < VENDOR_MAX); - gcc_assert (__cpu_model.__cpu_type < CPU_TYPE_MAX); - gcc_assert (__cpu_model.__cpu_subtype < CPU_SUBTYPE_MAX); - - return 0; -} diff --git a/libgcc/config/i386/libgcc-bsd.ver b/libgcc/config/i386/libgcc-bsd.ver index d9d74f95186..74622bf7763 100644 --- a/libgcc/config/i386/libgcc-bsd.ver +++ b/libgcc/config/i386/libgcc-bsd.ver @@ -1,4 +1,4 @@ -# Copyright (C) 2010 Free Software Foundation, Inc. +# Copyright (C) 2010, 2012 Free Software Foundation, Inc. # # This file is part of GCC. # @@ -106,3 +106,7 @@ GCC_4.6.0 { __trunctfxf2 __unordtf2 } + +GCC_4.8.0 { + __cpu_model +} diff --git a/libgcc/config/i386/libgcc-glibc.ver b/libgcc/config/i386/libgcc-glibc.ver index b297362920d..07fd1f9c5a7 100644 --- a/libgcc/config/i386/libgcc-glibc.ver +++ b/libgcc/config/i386/libgcc-glibc.ver @@ -1,4 +1,4 @@ -# Copyright (C) 2008, 2010 Free Software Foundation, Inc. +# Copyright (C) 2008, 2010, 2012 Free Software Foundation, Inc. # # This file is part of GCC. # diff --git a/libgcc/config/i386/libgcc-sol2.ver b/libgcc/config/i386/libgcc-sol2.ver index 26a0abfb541..af8a9a0bddb 100644 --- a/libgcc/config/i386/libgcc-sol2.ver +++ b/libgcc/config/i386/libgcc-sol2.ver @@ -1,4 +1,4 @@ -# Copyright (C) 2010 Free Software Foundation, Inc. +# Copyright (C) 2010, 2012 Free Software Foundation, Inc. # # This file is part of GCC. # @@ -106,3 +106,7 @@ GCC_4.5.0 { __trunctfxf2 __unordtf2 } + +GCC_4.8.0 { + __cpu_model +} diff --git a/libgcc/config/i386/t-cpuinfo b/libgcc/config/i386/t-cpuinfo index dd271f9db6a..31c8db991c5 100644 --- a/libgcc/config/i386/t-cpuinfo +++ b/libgcc/config/i386/t-cpuinfo @@ -1 +1 @@ -LIB2ADD += $(srcdir)/config/i386/i386-cpuinfo.c +LIB2ADD += $(srcdir)/config/i386/cpuinfo.c diff --git a/libgcc/configure b/libgcc/configure index 37afe9deaa8..9ce74e48d4e 100644 --- a/libgcc/configure +++ b/libgcc/configure @@ -2176,6 +2176,8 @@ ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var. ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. +ac_config_headers="$ac_config_headers auto-target.h:config.in" + # Check whether --enable-shared was given. if test "${enable_shared+set}" = set; then : @@ -4756,6 +4758,38 @@ if test "$enable_tls $gcc_cv_use_emutls" = "yes yes"; then fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for init priority support" >&5 +$as_echo_n "checking for init priority support... " >&6; } +if test "${libgcc_cv_init_priority+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ +void ip (void) __attribute__ ((constructor (1))); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + libgcc_cv_init_priority=yes +else + libgcc_cv_init_priority=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libgcc_cv_init_priority" >&5 +$as_echo "$libgcc_cv_init_priority" >&6; } +if test $libgcc_cv_init_priority = yes; then + +$as_echo "#define HAVE_INIT_PRIORITY 1" >>confdefs.h + +fi + # Conditionalize the sfp-machine.h header for this target machine. if test -z "${sfp_machine_header}"; then sfp_machine_header=$cpu_type/sfp-machine.h @@ -4902,43 +4936,7 @@ test "x$prefix" = xNONE && prefix=$ac_default_prefix # Let make expand exec_prefix. test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' -# Transform confdefs.h into DEFS. -# Protect against shell expansion while executing Makefile rules. -# Protect against Makefile macro expansion. -# -# If the first sed substitution is executed (which looks for macros that -# take arguments), then branch to the quote section. Otherwise, -# look for a macro that doesn't take arguments. -ac_script=' -:mline -/\\$/{ - N - s,\\\n,, - b mline -} -t clear -:clear -s/^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*([^)]*)\)[ ]*\(.*\)/-D\1=\2/g -t quote -s/^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\)/-D\1=\2/g -t quote -b any -:quote -s/[ `~#$^&*(){}\\|;'\''"<>?]/\\&/g -s/\[/\\&/g -s/\]/\\&/g -s/\$/$$/g -H -:any -${ - g - s/^\n// - s/\n/ /g - p -} -' -DEFS=`sed -n "$ac_script" confdefs.h` - +DEFS=-DHAVE_CONFIG_H ac_libobjs= ac_ltlibobjs= @@ -5382,11 +5380,15 @@ case $ac_config_files in *" "*) set x $ac_config_files; shift; ac_config_files=$*;; esac +case $ac_config_headers in *" +"*) set x $ac_config_headers; shift; ac_config_headers=$*;; +esac cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 # Files that config.status was made for. config_files="$ac_config_files" +config_headers="$ac_config_headers" config_links="$ac_config_links" config_commands="$ac_config_commands" @@ -5408,10 +5410,15 @@ Usage: $0 [OPTION]... [TAG]... --recheck update $as_me by reconfiguring in the same conditions --file=FILE[:TEMPLATE] instantiate the configuration file FILE + --header=FILE[:TEMPLATE] + instantiate the configuration header FILE Configuration files: $config_files +Configuration headers: +$config_headers + Configuration links: $config_links @@ -5473,7 +5480,18 @@ do esac as_fn_append CONFIG_FILES " '$ac_optarg'" ac_need_defaults=false;; - --he | --h | --help | --hel | -h ) + --header | --heade | --head | --hea ) + $ac_shift + case $ac_optarg in + *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + as_fn_append CONFIG_HEADERS " '$ac_optarg'" + ac_need_defaults=false;; + --he | --h) + # Conflict between --help and --header + as_fn_error "ambiguous option: \`$1' +Try \`$0 --help' for more information.";; + --help | --hel | -h ) $as_echo "$ac_cs_usage"; exit ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil | --si | --s) @@ -5542,6 +5560,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 for ac_config_target in $ac_config_targets do case $ac_config_target in + "auto-target.h") CONFIG_HEADERS="$CONFIG_HEADERS auto-target.h:config.in" ;; "enable-execute-stack.c") CONFIG_LINKS="$CONFIG_LINKS enable-execute-stack.c:$enable_execute_stack" ;; "unwind.h") CONFIG_LINKS="$CONFIG_LINKS unwind.h:$unwind_header" ;; "md-unwind-support.h") CONFIG_LINKS="$CONFIG_LINKS md-unwind-support.h:config/$md_unwind_header" ;; @@ -5561,6 +5580,7 @@ done # bizarre bug on SunOS 4.1.3. if $ac_need_defaults; then test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files + test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers test "${CONFIG_LINKS+set}" = set || CONFIG_LINKS=$config_links test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands fi @@ -5740,8 +5760,116 @@ fi cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 fi # test -n "$CONFIG_FILES" +# Set up the scripts for CONFIG_HEADERS section. +# No need to generate them if there are no CONFIG_HEADERS. +# This happens for instance with `./config.status Makefile'. +if test -n "$CONFIG_HEADERS"; then +cat >"$tmp/defines.awk" <<\_ACAWK || +BEGIN { +_ACEOF + +# Transform confdefs.h into an awk script `defines.awk', embedded as +# here-document in config.status, that substitutes the proper values into +# config.h.in to produce config.h. + +# Create a delimiter string that does not exist in confdefs.h, to ease +# handling of long lines. +ac_delim='%!_!# ' +for ac_last_try in false false :; do + ac_t=`sed -n "/$ac_delim/p" confdefs.h` + if test -z "$ac_t"; then + break + elif $ac_last_try; then + as_fn_error "could not make $CONFIG_HEADERS" "$LINENO" 5 + else + ac_delim="$ac_delim!$ac_delim _$ac_delim!! " + fi +done -eval set X " :F $CONFIG_FILES :L $CONFIG_LINKS :C $CONFIG_COMMANDS" +# For the awk script, D is an array of macro values keyed by name, +# likewise P contains macro parameters if any. Preserve backslash +# newline sequences. + +ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]* +sed -n ' +s/.\{148\}/&'"$ac_delim"'/g +t rset +:rset +s/^[ ]*#[ ]*define[ ][ ]*/ / +t def +d +:def +s/\\$// +t bsnl +s/["\\]/\\&/g +s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ +D["\1"]=" \3"/p +s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2"/p +d +:bsnl +s/["\\]/\\&/g +s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ +D["\1"]=" \3\\\\\\n"\\/p +t cont +s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p +t cont +d +:cont +n +s/.\{148\}/&'"$ac_delim"'/g +t clear +:clear +s/\\$// +t bsnlc +s/["\\]/\\&/g; s/^/"/; s/$/"/p +d +:bsnlc +s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p +b cont +' >$CONFIG_STATUS || ac_write_fail=1 + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 + for (key in D) D_is_set[key] = 1 + FS = "" +} +/^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ { + line = \$ 0 + split(line, arg, " ") + if (arg[1] == "#") { + defundef = arg[2] + mac1 = arg[3] + } else { + defundef = substr(arg[1], 2) + mac1 = arg[2] + } + split(mac1, mac2, "(") #) + macro = mac2[1] + prefix = substr(line, 1, index(line, defundef) - 1) + if (D_is_set[macro]) { + # Preserve the white space surrounding the "#". + print prefix "define", macro P[macro] D[macro] + next + } else { + # Replace #undef with comments. This is necessary, for example, + # in the case of _POSIX_SOURCE, which is predefined and required + # on some systems where configure will not decide to define it. + if (defundef == "undef") { + print "/*", prefix defundef, macro, "*/" + next + } + } +} +{ print } +_ACAWK +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 + as_fn_error "could not setup config headers machinery" "$LINENO" 5 +fi # test -n "$CONFIG_HEADERS" + + +eval set X " :F $CONFIG_FILES :H $CONFIG_HEADERS :L $CONFIG_LINKS :C $CONFIG_COMMANDS" shift for ac_tag do @@ -5953,7 +6081,30 @@ which seems to be undefined. Please make sure it is defined." >&2;} esac \ || as_fn_error "could not create $ac_file" "$LINENO" 5 ;; - + :H) + # + # CONFIG_HEADER + # + if test x"$ac_file" != x-; then + { + $as_echo "/* $configure_input */" \ + && eval '$AWK -f "$tmp/defines.awk"' "$ac_file_inputs" + } >"$tmp/config.h" \ + || as_fn_error "could not create $ac_file" "$LINENO" 5 + if diff "$ac_file" "$tmp/config.h" >/dev/null 2>&1; then + { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5 +$as_echo "$as_me: $ac_file is unchanged" >&6;} + else + rm -f "$ac_file" + mv "$tmp/config.h" "$ac_file" \ + || as_fn_error "could not create $ac_file" "$LINENO" 5 + fi + else + $as_echo "/* $configure_input */" \ + && eval '$AWK -f "$tmp/defines.awk"' "$ac_file_inputs" \ + || as_fn_error "could not create -" "$LINENO" 5 + fi + ;; :L) # # CONFIG_LINK diff --git a/libgcc/configure.ac b/libgcc/configure.ac index 748189393e6..2a93b9e6142 100644 --- a/libgcc/configure.ac +++ b/libgcc/configure.ac @@ -39,6 +39,7 @@ else fi AC_SUBST(libgcc_topdir) AC_CONFIG_AUX_DIR($libgcc_topdir) +AC_CONFIG_HEADER(auto-target.h:config.in) AC_ARG_ENABLE(shared, [ --disable-shared don't provide a shared libgcc], @@ -327,6 +328,15 @@ if test "$enable_tls $gcc_cv_use_emutls" = "yes yes"; then fi AC_SUBST(set_use_emutls) +AC_CACHE_CHECK(for init priority support, libgcc_cv_init_priority, [ +AC_COMPILE_IFELSE([AC_LANG_PROGRAM(, + [[void ip (void) __attribute__ ((constructor (1)));]])], + [libgcc_cv_init_priority=yes],[libgcc_cv_init_priority=no])]) +if test $libgcc_cv_init_priority = yes; then + AC_DEFINE(HAVE_INIT_PRIORITY, 1, + [Define if the compiler supports init priority.]) +fi + # Conditionalize the sfp-machine.h header for this target machine. if test -z "${sfp_machine_header}"; then sfp_machine_header=$cpu_type/sfp-machine.h