Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(244)

Unified Diff: libgcc/config/i386/i386-cpuinfo.c

Issue 4893046: [4.7][google]Support for getting CPU type and feature information at run-time. Base URL: svn+ssh://gcc.gnu.org/svn/gcc/branches/google/gcc-4_6/
Patch Set: Created 14 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « libgcc/config.host ('k') | libgcc/config/i386/t-cpuinfo » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: libgcc/config/i386/i386-cpuinfo.c
===================================================================
--- libgcc/config/i386/i386-cpuinfo.c (revision 0)
+++ libgcc/config/i386/i386-cpuinfo.c (revision 0)
@@ -0,0 +1,275 @@
+/* Copyright (C) 2011 Free Software Foundation, Inc.
+ * Contributed by Sriraman Tallam <tmsriram@google.com>.
+ *
+ * This file 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.
+ *
+ * This file 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/>.
+ *
+ *
+ * This code is adapted from gcc/config/i386/driver-i386.c. The CPUID
+ * instruction is used to figure out the cpu type and supported features.
+ * GCC runs __cpu_indicator_init from a constructor which sets the members
+ * of __cpu_model and __cpu_features.
+ */
+
+#include <string.h>
+
+#ifdef __GNUC__
+#include "cpuid.h"
+
+enum processor_type
+{
+ PROCESSOR_PENTIUM = 0,
+ PROCESSOR_CORE2,
+ PROCESSOR_COREI7_NEHALEM,
+ PROCESSOR_COREI7_WESTMERE,
+ PROCESSOR_COREI7_SANDYBRIDGE,
+ PROCESSOR_INTEL_GENERIC,
+ PROCESSOR_AMDFAM10_BARCELONA,
+ PROCESSOR_AMDFAM10_SHANGHAI,
+ PROCESSOR_AMDFAM10_ISTANBUL,
+ PROCESSOR_AMDFAM10_GENERIC,
+ PROCESSOR_AMD_GENERIC,
+ PROCESSOR_GENERIC,
+ PROCESSOR_max
+};
+
+enum vendor_signatures
+{
+ SIG_INTEL = 0x756e6547 /* Genu */,
+ SIG_AMD = 0x68747541 /* Auth */
+};
+
+
+/* Features supported. */
+
+struct __processor_features
+{
+ unsigned int __cpu_cmov : 1;
+ unsigned int __cpu_mmx : 1;
+ unsigned int __cpu_popcnt : 1;
+ unsigned int __cpu_sse : 1;
+ unsigned int __cpu_sse2 : 1;
+ unsigned int __cpu_sse3 : 1;
+ unsigned int __cpu_ssse3 : 1;
+ unsigned int __cpu_sse4_1 : 1;
+ unsigned int __cpu_sse4_2 : 1;
+};
+
+/* Flags exported. */
+
+struct __processor_model
+{
+ unsigned int __cpu_is_amd : 1;
+ unsigned int __cpu_is_intel : 1;
+ unsigned int __cpu_is_corei7_nehalem : 1;
+ unsigned int __cpu_is_corei7_westmere : 1;
+ unsigned int __cpu_is_corei7_sandybridge : 1;
+ unsigned int __cpu_is_amdfam10_barcelona : 1;
+ unsigned int __cpu_is_amdfam10_shanghai : 1;
+ unsigned int __cpu_is_amdfam10_istanbul : 1;
+};
+
+enum processor_type __cpu_type = PROCESSOR_GENERIC;
+struct __processor_features __cpu_features;
+struct __processor_model __cpu_model;
+
+static void
+get_amd_cpu (unsigned int family, unsigned int model)
+{
+ switch (family)
+ {
+ case 0x10:
+ switch (model)
+ {
+ case 0x2:
+ __cpu_type = PROCESSOR_AMDFAM10_BARCELONA;
+ __cpu_model.__cpu_is_amdfam10_barcelona = 1;
+ break;
+ case 0x4:
+ __cpu_type = PROCESSOR_AMDFAM10_SHANGHAI;
+ __cpu_model.__cpu_is_amdfam10_shanghai = 1;
+ break;
+ case 0x8:
+ __cpu_type = PROCESSOR_AMDFAM10_ISTANBUL;
+ __cpu_model.__cpu_is_amdfam10_istanbul = 1;
+ break;
+ default:
+ __cpu_type = PROCESSOR_AMDFAM10_GENERIC;
+ break;
+ }
+ break;
+ default:
+ __cpu_type = PROCESSOR_AMD_GENERIC;
+ }
+}
+
+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:
+ __cpu_type = PROCESSOR_PENTIUM;
+ break;
+ case 0x6:
+ switch (model)
+ {
+ case 0x1a:
+ case 0x1e:
+ case 0x1f:
+ case 0x2e:
+ /* Nehalem. */
+ __cpu_type = PROCESSOR_COREI7_NEHALEM;
+ __cpu_model.__cpu_is_corei7_nehalem = 1;
+ break;
+ case 0x25:
+ case 0x2c:
+ case 0x2f:
+ /* Westmere. */
+ __cpu_type = PROCESSOR_COREI7_WESTMERE;
+ __cpu_model.__cpu_is_corei7_westmere = 1;
+ break;
+ case 0x2a:
+ /* Sandy Bridge. */
+ __cpu_type = PROCESSOR_COREI7_SANDYBRIDGE;
+ __cpu_model.__cpu_is_corei7_sandybridge = 1;
+ break;
+ case 0x17:
+ case 0x1d:
+ /* Penryn. */
+ case 0x0f:
+ /* Merom. */
+ __cpu_type = PROCESSOR_CORE2;
+ break;
+ default:
+ __cpu_type = PROCESSOR_INTEL_GENERIC;
+ break;
+ }
+ break;
+ default:
+ /* We have no idea. */
+ __cpu_type = PROCESSOR_INTEL_GENERIC;
+ break;
+ }
+ }
+}
+
+static void
+get_available_features (unsigned int ecx, unsigned int edx)
+{
+ __cpu_features.__cpu_cmov = (edx & bit_CMOV) ? 1 : 0;
+ __cpu_features.__cpu_mmx = (edx & bit_MMX) ? 1 : 0;
+ __cpu_features.__cpu_sse = (edx & bit_SSE) ? 1 : 0;
+ __cpu_features.__cpu_sse2 = (edx & bit_SSE2) ? 1 : 0;
+ __cpu_features.__cpu_popcnt = (ecx & bit_POPCNT) ? 1 : 0;
+ __cpu_features.__cpu_sse3 = (ecx & bit_SSE3) ? 1 : 0;
+ __cpu_features.__cpu_ssse3 = (ecx & bit_SSSE3) ? 1 : 0;
+ __cpu_features.__cpu_sse4_1 = (ecx & bit_SSE4_1) ? 1 : 0;
+ __cpu_features.__cpu_sse4_2 = (ecx & bit_SSE4_2) ? 1 : 0;
+}
+
+/* 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);
+}
+
+/* This function will be linked in to binaries that need to look up
+ CPU information. */
+
+void
+__cpu_indicator_init(void)
+{
+ unsigned int eax, ebx, ecx, edx;
+
+ int max_level = 5;
+ unsigned int vendor;
+ unsigned int model, family, brand_id;
+
+ memset (&__cpu_features, 0, sizeof (struct __processor_features));
+ memset (&__cpu_model, 0, sizeof (struct __processor_model));
+
+ /* Assume cpuid insn present. Run in level 0 to get vendor id. */
+ if (!__get_cpuid_output (0, &eax, &ebx, &ecx, &edx))
+ return;
+
+ vendor = ebx;
+ max_level = eax;
+
+ if (max_level < 1)
+ return;
+
+ if (!__get_cpuid_output (1, &eax, &ebx, &ecx, &edx))
+ return;
+
+ model = (eax >> 4) & 0x0f;
+ family = (eax >> 8) & 0x0f;
+ brand_id = ebx & 0xff;
+
+ /* Adjust model and family for Intel CPUS. */
+ if (vendor == SIG_INTEL)
+ {
+ unsigned int extended_model, extended_family;
+
+ extended_model = (eax >> 12) & 0xf0;
+ extended_family = (eax >> 20) & 0xff;
+ if (family == 0x0f)
+ {
+ family += extended_family;
+ model += extended_model;
+ }
+ else if (family == 0x06)
+ model += extended_model;
+ }
+
+ /* Find CPU model. */
+
+ if (vendor == SIG_AMD)
+ {
+ __cpu_model.__cpu_is_amd = 1;
+ get_amd_cpu (family, model);
+ }
+ else if (vendor == SIG_INTEL)
+ {
+ __cpu_model.__cpu_is_intel = 1;
+ get_intel_cpu (family, model, brand_id);
+ }
+
+ /* Find available features. */
+ get_available_features (ecx, edx);
+}
+
+#else
+
+void
+__cpu_indicator_init(void)
+{
+}
+
+#endif /* __GNUC__ */
« no previous file with comments | « libgcc/config.host ('k') | libgcc/config/i386/t-cpuinfo » ('j') | no next file with comments »

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b