blob: d48c5265a4d92795ddec5439877fbcc9c6863f6a [file] [log] [blame]
Daniel Dunbarbb146722008-10-02 01:17:28 +00001//===-- Host.cpp - Implement OS Host Concept --------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This header file implements the operating system Host concept.
11//
12//===----------------------------------------------------------------------===//
13
Hal Finkel4db738a2012-06-12 03:03:13 +000014#include "llvm/ADT/StringRef.h"
15#include "llvm/ADT/StringSwitch.h"
16#include "llvm/Support/DataStream.h"
17#include "llvm/Support/Debug.h"
Michael J. Spencer1f6efa32010-11-29 18:16:10 +000018#include "llvm/Support/Host.h"
Hal Finkel4db738a2012-06-12 03:03:13 +000019#include "llvm/Support/raw_ostream.h"
Daniel Dunbarbb146722008-10-02 01:17:28 +000020#include "llvm/Config/config.h"
Daniel Dunbar067d0242009-11-14 10:09:12 +000021#include <string.h>
Daniel Dunbarbb146722008-10-02 01:17:28 +000022
23// Include the platform-specific parts of this class.
24#ifdef LLVM_ON_UNIX
25#include "Unix/Host.inc"
26#endif
27#ifdef LLVM_ON_WIN32
Michael J. Spencer1f6efa32010-11-29 18:16:10 +000028#include "Windows/Host.inc"
Daniel Dunbarbb146722008-10-02 01:17:28 +000029#endif
Benjamin Kramerac07b3d2009-11-19 12:17:31 +000030#ifdef _MSC_VER
31#include <intrin.h>
32#endif
Hal Finkel4db738a2012-06-12 03:03:13 +000033#if defined(__APPLE__) && (defined(__ppc__) || defined(__powerpc__))
34#include <mach/mach.h>
35#include <mach/mach_host.h>
36#include <mach/host_info.h>
37#include <mach/machine.h>
38#endif
Daniel Dunbarbb146722008-10-02 01:17:28 +000039
Daniel Dunbar067d0242009-11-14 10:09:12 +000040//===----------------------------------------------------------------------===//
41//
42// Implementations of the CPU detection routines
43//
44//===----------------------------------------------------------------------===//
45
46using namespace llvm;
47
48#if defined(i386) || defined(__i386__) || defined(__x86__) || defined(_M_IX86)\
49 || defined(__x86_64__) || defined(_M_AMD64) || defined (_M_X64)
50
51/// GetX86CpuIDAndInfo - Execute the specified cpuid and return the 4 values in the
52/// specified arguments. If we can't run cpuid on the host, return true.
53static bool GetX86CpuIDAndInfo(unsigned value, unsigned *rEAX,
54 unsigned *rEBX, unsigned *rECX, unsigned *rEDX) {
55#if defined(__x86_64__) || defined(_M_AMD64) || defined (_M_X64)
56 #if defined(__GNUC__)
57 // gcc doesn't know cpuid would clobber ebx/rbx. Preseve it manually.
58 asm ("movq\t%%rbx, %%rsi\n\t"
59 "cpuid\n\t"
60 "xchgq\t%%rbx, %%rsi\n\t"
61 : "=a" (*rEAX),
62 "=S" (*rEBX),
63 "=c" (*rECX),
64 "=d" (*rEDX)
65 : "a" (value));
66 return false;
67 #elif defined(_MSC_VER)
68 int registers[4];
69 __cpuid(registers, value);
70 *rEAX = registers[0];
71 *rEBX = registers[1];
72 *rECX = registers[2];
73 *rEDX = registers[3];
74 return false;
David Blaikiefdebc382012-01-17 04:43:56 +000075 #else
76 return true;
Daniel Dunbar067d0242009-11-14 10:09:12 +000077 #endif
78#elif defined(i386) || defined(__i386__) || defined(__x86__) || defined(_M_IX86)
79 #if defined(__GNUC__)
80 asm ("movl\t%%ebx, %%esi\n\t"
81 "cpuid\n\t"
82 "xchgl\t%%ebx, %%esi\n\t"
83 : "=a" (*rEAX),
84 "=S" (*rEBX),
85 "=c" (*rECX),
86 "=d" (*rEDX)
87 : "a" (value));
88 return false;
89 #elif defined(_MSC_VER)
90 __asm {
91 mov eax,value
92 cpuid
93 mov esi,rEAX
94 mov dword ptr [esi],eax
95 mov esi,rEBX
96 mov dword ptr [esi],ebx
97 mov esi,rECX
98 mov dword ptr [esi],ecx
99 mov esi,rEDX
100 mov dword ptr [esi],edx
101 }
102 return false;
David Blaikiefdebc382012-01-17 04:43:56 +0000103// pedantic #else returns to appease -Wunreachable-code (so we don't generate
104// postprocessed code that looks like "return true; return false;")
105 #else
106 return true;
Daniel Dunbar067d0242009-11-14 10:09:12 +0000107 #endif
David Blaikiefdebc382012-01-17 04:43:56 +0000108#else
Daniel Dunbar067d0242009-11-14 10:09:12 +0000109 return true;
David Blaikiefdebc382012-01-17 04:43:56 +0000110#endif
Daniel Dunbar067d0242009-11-14 10:09:12 +0000111}
112
Chris Lattner9c7f0752010-09-06 05:19:44 +0000113static void DetectX86FamilyModel(unsigned EAX, unsigned &Family,
114 unsigned &Model) {
Daniel Dunbar067d0242009-11-14 10:09:12 +0000115 Family = (EAX >> 8) & 0xf; // Bits 8 - 11
116 Model = (EAX >> 4) & 0xf; // Bits 4 - 7
117 if (Family == 6 || Family == 0xf) {
118 if (Family == 0xf)
119 // Examine extended family ID if family ID is F.
120 Family += (EAX >> 20) & 0xff; // Bits 20 - 27
121 // Examine extended model ID if family ID is 6 or F.
122 Model += ((EAX >> 16) & 0xf) << 4; // Bits 16 - 19
123 }
124}
Daniel Dunbar067d0242009-11-14 10:09:12 +0000125
126std::string sys::getHostCPUName() {
Daniel Dunbar067d0242009-11-14 10:09:12 +0000127 unsigned EAX = 0, EBX = 0, ECX = 0, EDX = 0;
128 if (GetX86CpuIDAndInfo(0x1, &EAX, &EBX, &ECX, &EDX))
129 return "generic";
130 unsigned Family = 0;
131 unsigned Model = 0;
132 DetectX86FamilyModel(EAX, Family, Model);
133
Chris Lattner9c7f0752010-09-06 05:19:44 +0000134 bool HasSSE3 = (ECX & 0x1);
Daniel Dunbar067d0242009-11-14 10:09:12 +0000135 GetX86CpuIDAndInfo(0x80000001, &EAX, &EBX, &ECX, &EDX);
136 bool Em64T = (EDX >> 29) & 0x1;
Daniel Dunbar067d0242009-11-14 10:09:12 +0000137
138 union {
139 unsigned u[3];
140 char c[12];
141 } text;
142
143 GetX86CpuIDAndInfo(0, &EAX, text.u+0, text.u+2, text.u+1);
144 if (memcmp(text.c, "GenuineIntel", 12) == 0) {
145 switch (Family) {
Daniel Dunbara7ac3ce2009-11-14 21:36:19 +0000146 case 3:
147 return "i386";
148 case 4:
149 switch (Model) {
NAKAMURA Takumid4d4c7f2010-09-09 13:30:48 +0000150 case 0: // Intel486 DX processors
151 case 1: // Intel486 DX processors
Daniel Dunbara7ac3ce2009-11-14 21:36:19 +0000152 case 2: // Intel486 SX processors
NAKAMURA Takumid4d4c7f2010-09-09 13:30:48 +0000153 case 3: // Intel487 processors, IntelDX2 OverDrive processors,
154 // IntelDX2 processors
Daniel Dunbara7ac3ce2009-11-14 21:36:19 +0000155 case 4: // Intel486 SL processor
NAKAMURA Takumid4d4c7f2010-09-09 13:30:48 +0000156 case 5: // IntelSX2 processors
Daniel Dunbara7ac3ce2009-11-14 21:36:19 +0000157 case 7: // Write-Back Enhanced IntelDX2 processors
NAKAMURA Takumid4d4c7f2010-09-09 13:30:48 +0000158 case 8: // IntelDX4 OverDrive processors, IntelDX4 processors
Daniel Dunbara7ac3ce2009-11-14 21:36:19 +0000159 default: return "i486";
Daniel Dunbar067d0242009-11-14 10:09:12 +0000160 }
Daniel Dunbara7ac3ce2009-11-14 21:36:19 +0000161 case 5:
162 switch (Model) {
163 case 1: // Pentium OverDrive processor for Pentium processor (60, 66),
NAKAMURA Takumid4d4c7f2010-09-09 13:30:48 +0000164 // Pentium processors (60, 66)
Daniel Dunbara7ac3ce2009-11-14 21:36:19 +0000165 case 2: // Pentium OverDrive processor for Pentium processor (75, 90,
166 // 100, 120, 133), Pentium processors (75, 90, 100, 120, 133,
167 // 150, 166, 200)
168 case 3: // Pentium OverDrive processors for Intel486 processor-based
169 // systems
170 return "pentium";
171
NAKAMURA Takumid4d4c7f2010-09-09 13:30:48 +0000172 case 4: // Pentium OverDrive processor with MMX technology for Pentium
Daniel Dunbara7ac3ce2009-11-14 21:36:19 +0000173 // processor (75, 90, 100, 120, 133), Pentium processor with
NAKAMURA Takumid4d4c7f2010-09-09 13:30:48 +0000174 // MMX technology (166, 200)
Daniel Dunbara7ac3ce2009-11-14 21:36:19 +0000175 return "pentium-mmx";
176
177 default: return "pentium";
178 }
179 case 6:
180 switch (Model) {
181 case 1: // Pentium Pro processor
182 return "pentiumpro";
183
184 case 3: // Intel Pentium II OverDrive processor, Pentium II processor,
185 // model 03
186 case 5: // Pentium II processor, model 05, Pentium II Xeon processor,
NAKAMURA Takumid4d4c7f2010-09-09 13:30:48 +0000187 // model 05, and Intel Celeron processor, model 05
Daniel Dunbara7ac3ce2009-11-14 21:36:19 +0000188 case 6: // Celeron processor, model 06
189 return "pentium2";
190
191 case 7: // Pentium III processor, model 07, and Pentium III Xeon
192 // processor, model 07
193 case 8: // Pentium III processor, model 08, Pentium III Xeon processor,
194 // model 08, and Celeron processor, model 08
195 case 10: // Pentium III Xeon processor, model 0Ah
196 case 11: // Pentium III processor, model 0Bh
197 return "pentium3";
198
199 case 9: // Intel Pentium M processor, Intel Celeron M processor model 09.
200 case 13: // Intel Pentium M processor, Intel Celeron M processor, model
201 // 0Dh. All processors are manufactured using the 90 nm process.
202 return "pentium-m";
203
NAKAMURA Takumid4d4c7f2010-09-09 13:30:48 +0000204 case 14: // Intel Core Duo processor, Intel Core Solo processor, model
Daniel Dunbara7ac3ce2009-11-14 21:36:19 +0000205 // 0Eh. All processors are manufactured using the 65 nm process.
206 return "yonah";
207
NAKAMURA Takumid4d4c7f2010-09-09 13:30:48 +0000208 case 15: // Intel Core 2 Duo processor, Intel Core 2 Duo mobile
209 // processor, Intel Core 2 Quad processor, Intel Core 2 Quad
210 // mobile processor, Intel Core 2 Extreme processor, Intel
Daniel Dunbara7ac3ce2009-11-14 21:36:19 +0000211 // Pentium Dual-Core processor, Intel Xeon processor, model
212 // 0Fh. All processors are manufactured using the 65 nm process.
213 case 22: // Intel Celeron processor model 16h. All processors are
214 // manufactured using the 65 nm process
215 return "core2";
216
217 case 21: // Intel EP80579 Integrated Processor and Intel EP80579
218 // Integrated Processor with Intel QuickAssist Technology
219 return "i686"; // FIXME: ???
220
NAKAMURA Takumid4d4c7f2010-09-09 13:30:48 +0000221 case 23: // Intel Core 2 Extreme processor, Intel Xeon processor, model
Daniel Dunbara7ac3ce2009-11-14 21:36:19 +0000222 // 17h. All processors are manufactured using the 45 nm process.
223 //
224 // 45nm: Penryn , Wolfdale, Yorkfield (XE)
225 return "penryn";
226
227 case 26: // Intel Core i7 processor and Intel Xeon processor. All
228 // processors are manufactured using the 45 nm process.
229 case 29: // Intel Xeon processor MP. All processors are manufactured using
230 // the 45 nm process.
Jakob Stoklund Olesen71c60952010-09-19 17:54:28 +0000231 case 30: // Intel(R) Core(TM) i7 CPU 870 @ 2.93GHz.
232 // As found in a Summer 2010 model iMac.
Chris Lattner222920d2010-09-19 00:31:58 +0000233 case 37: // Intel Core i7, laptop version.
Benjamin Kramercf847bf2011-08-25 18:05:56 +0000234 case 44: // Intel Core i7 processor and Intel Xeon processor. All
235 // processors are manufactured using the 32 nm process.
Daniel Dunbara7ac3ce2009-11-14 21:36:19 +0000236 return "corei7";
Bob Wilson7c3a5ca2011-07-08 22:33:59 +0000237
238 // SandyBridge:
239 case 42: // Intel Core i7 processor. All processors are manufactured
240 // using the 32 nm process.
Chris Lattner78a113c2011-06-09 06:38:17 +0000241 case 45:
Benjamin Kramereb274e62011-05-20 15:11:26 +0000242 return "corei7-avx";
Daniel Dunbara7ac3ce2009-11-14 21:36:19 +0000243
Evan Chengaff59682012-04-23 22:41:39 +0000244 // Ivy Bridge:
245 case 58:
246 return "core-avx-i";
247
Preston Gurd79bbe852012-05-02 21:38:46 +0000248 case 28: // Most 45 nm Intel Atom processors
249 case 38: // 45 nm Atom Lincroft
250 case 39: // 32 nm Atom Medfield
Daniel Dunbara7ac3ce2009-11-14 21:36:19 +0000251 return "atom";
252
Bob Wilson0d38d3a2012-05-09 17:47:03 +0000253 default: return (Em64T) ? "x86-64" : "i686";
Daniel Dunbara7ac3ce2009-11-14 21:36:19 +0000254 }
255 case 15: {
256 switch (Model) {
257 case 0: // Pentium 4 processor, Intel Xeon processor. All processors are
258 // model 00h and manufactured using the 0.18 micron process.
259 case 1: // Pentium 4 processor, Intel Xeon processor, Intel Xeon
260 // processor MP, and Intel Celeron processor. All processors are
261 // model 01h and manufactured using the 0.18 micron process.
NAKAMURA Takumid4d4c7f2010-09-09 13:30:48 +0000262 case 2: // Pentium 4 processor, Mobile Intel Pentium 4 processor - M,
Daniel Dunbara7ac3ce2009-11-14 21:36:19 +0000263 // Intel Xeon processor, Intel Xeon processor MP, Intel Celeron
264 // processor, and Mobile Intel Celeron processor. All processors
265 // are model 02h and manufactured using the 0.13 micron process.
266 return (Em64T) ? "x86-64" : "pentium4";
267
268 case 3: // Pentium 4 processor, Intel Xeon processor, Intel Celeron D
269 // processor. All processors are model 03h and manufactured using
270 // the 90 nm process.
271 case 4: // Pentium 4 processor, Pentium 4 processor Extreme Edition,
272 // Pentium D processor, Intel Xeon processor, Intel Xeon
273 // processor MP, Intel Celeron D processor. All processors are
274 // model 04h and manufactured using the 90 nm process.
275 case 6: // Pentium 4 processor, Pentium D processor, Pentium processor
276 // Extreme Edition, Intel Xeon processor, Intel Xeon processor
277 // MP, Intel Celeron D processor. All processors are model 06h
278 // and manufactured using the 65 nm process.
279 return (Em64T) ? "nocona" : "prescott";
280
Daniel Dunbara7ac3ce2009-11-14 21:36:19 +0000281 default:
282 return (Em64T) ? "x86-64" : "pentium4";
283 }
284 }
285
Daniel Dunbar067d0242009-11-14 10:09:12 +0000286 default:
Benjamin Kramer110e7bb2009-11-17 17:57:04 +0000287 return "generic";
Daniel Dunbar067d0242009-11-14 10:09:12 +0000288 }
289 } else if (memcmp(text.c, "AuthenticAMD", 12) == 0) {
290 // FIXME: this poorly matches the generated SubtargetFeatureKV table. There
291 // appears to be no way to generate the wide variety of AMD-specific targets
292 // from the information returned from CPUID.
293 switch (Family) {
294 case 4:
295 return "i486";
296 case 5:
297 switch (Model) {
298 case 6:
299 case 7: return "k6";
300 case 8: return "k6-2";
301 case 9:
302 case 13: return "k6-3";
303 default: return "pentium";
304 }
305 case 6:
306 switch (Model) {
307 case 4: return "athlon-tbird";
308 case 6:
309 case 7:
310 case 8: return "athlon-mp";
311 case 10: return "athlon-xp";
312 default: return "athlon";
313 }
314 case 15:
Chris Lattner9c7f0752010-09-06 05:19:44 +0000315 if (HasSSE3)
Daniel Dunbar067d0242009-11-14 10:09:12 +0000316 return "k8-sse3";
Chris Lattner9c7f0752010-09-06 05:19:44 +0000317 switch (Model) {
318 case 1: return "opteron";
319 case 5: return "athlon-fx"; // also opteron
320 default: return "athlon64";
Daniel Dunbar067d0242009-11-14 10:09:12 +0000321 }
322 case 16:
323 return "amdfam10";
Benjamin Kramer66a7fd72012-01-10 11:50:02 +0000324 case 20:
325 return "btver1";
Benjamin Kramer618f89f2011-12-01 18:24:17 +0000326 case 21:
327 return "bdver1";
Daniel Dunbar067d0242009-11-14 10:09:12 +0000328 default:
Benjamin Kramer110e7bb2009-11-17 17:57:04 +0000329 return "generic";
Daniel Dunbar067d0242009-11-14 10:09:12 +0000330 }
Daniel Dunbar067d0242009-11-14 10:09:12 +0000331 }
Torok Edwin546d8d02009-12-14 12:38:18 +0000332 return "generic";
Torok Edwinc4174d62009-12-13 08:59:40 +0000333}
Hal Finkel4db738a2012-06-12 03:03:13 +0000334#elif defined(__APPLE__) && (defined(__ppc__) || defined(__powerpc__))
335std::string sys::getHostCPUName() {
336 host_basic_info_data_t hostInfo;
337 mach_msg_type_number_t infoCount;
338
339 infoCount = HOST_BASIC_INFO_COUNT;
340 host_info(mach_host_self(), HOST_BASIC_INFO, (host_info_t)&hostInfo,
341 &infoCount);
342
343 if (hostInfo.cpu_type != CPU_TYPE_POWERPC) return "generic";
344
345 switch(hostInfo.cpu_subtype) {
346 case CPU_SUBTYPE_POWERPC_601: return "601";
347 case CPU_SUBTYPE_POWERPC_602: return "602";
348 case CPU_SUBTYPE_POWERPC_603: return "603";
349 case CPU_SUBTYPE_POWERPC_603e: return "603e";
350 case CPU_SUBTYPE_POWERPC_603ev: return "603ev";
351 case CPU_SUBTYPE_POWERPC_604: return "604";
352 case CPU_SUBTYPE_POWERPC_604e: return "604e";
353 case CPU_SUBTYPE_POWERPC_620: return "620";
354 case CPU_SUBTYPE_POWERPC_750: return "750";
355 case CPU_SUBTYPE_POWERPC_7400: return "7400";
356 case CPU_SUBTYPE_POWERPC_7450: return "7450";
357 case CPU_SUBTYPE_POWERPC_970: return "970";
358 default: ;
359 }
360
361 return "generic";
362}
363#elif defined(__linux__) && (defined(__ppc__) || defined(__powerpc__))
364std::string sys::getHostCPUName() {
365 // Access to the Processor Version Register (PVR) on PowerPC is privileged,
366 // and so we must use an operating-system interface to determine the current
367 // processor type. On Linux, this is exposed through the /proc/cpuinfo file.
368 const char *generic = "generic";
369
370 // Note: We cannot mmap /proc/cpuinfo here and then process the resulting
371 // memory buffer because the 'file' has 0 size (it can be read from only
372 // as a stream).
373
374 std::string Err;
375 DataStreamer *DS = getDataFileStreamer("/proc/cpuinfo", &Err);
376 if (!DS) {
377 DEBUG(dbgs() << "Unable to open /proc/cpuinfo: " << Err << "\n");
378 return generic;
379 }
380
381 // The cpu line is second (after the 'processor: 0' line), so if this
382 // buffer is too small then something has changed (or is wrong).
383 char buffer[1024];
384 size_t CPUInfoSize = DS->GetBytes((unsigned char*) buffer, sizeof(buffer));
385 delete DS;
386
387 const char *CPUInfoStart = buffer;
388 const char *CPUInfoEnd = buffer + CPUInfoSize;
389
390 const char *CIP = CPUInfoStart;
391
392 const char *CPUStart = 0;
393 size_t CPULen = 0;
394
395 // We need to find the first line which starts with cpu, spaces, and a colon.
396 // After the colon, there may be some additional spaces and then the cpu type.
397 while (CIP < CPUInfoEnd && CPUStart == 0) {
398 if (CIP < CPUInfoEnd && *CIP == '\n')
399 ++CIP;
400
401 if (CIP < CPUInfoEnd && *CIP == 'c') {
402 ++CIP;
403 if (CIP < CPUInfoEnd && *CIP == 'p') {
404 ++CIP;
405 if (CIP < CPUInfoEnd && *CIP == 'u') {
406 ++CIP;
407 while (CIP < CPUInfoEnd && (*CIP == ' ' || *CIP == '\t'))
408 ++CIP;
409
410 if (CIP < CPUInfoEnd && *CIP == ':') {
411 ++CIP;
412 while (CIP < CPUInfoEnd && (*CIP == ' ' || *CIP == '\t'))
413 ++CIP;
414
415 if (CIP < CPUInfoEnd) {
416 CPUStart = CIP;
417 while (CIP < CPUInfoEnd && (*CIP != ' ' && *CIP != '\t' &&
418 *CIP != ',' && *CIP != '\n'))
419 ++CIP;
420 CPULen = CIP - CPUStart;
421 }
422 }
423 }
424 }
425 }
426
427 if (CPUStart == 0)
428 while (CIP < CPUInfoEnd && *CIP != '\n')
429 ++CIP;
430 }
431
432 if (CPUStart == 0)
433 return generic;
434
435 return StringSwitch<const char *>(StringRef(CPUStart, CPULen))
436 .Case("604e", "604e")
437 .Case("604", "604")
438 .Case("7400", "7400")
439 .Case("7410", "7400")
440 .Case("7447", "7400")
441 .Case("7455", "7450")
442 .Case("G4", "g4")
443 .Case("POWER4", "g4")
444 .Case("PPC970FX", "970")
445 .Case("PPC970MP", "970")
446 .Case("G5", "g5")
447 .Case("POWER5", "g5")
448 .Case("A2", "a2")
449 .Case("POWER6", "pwr6")
450 .Case("POWER7", "pwr7")
451 .Default(generic);
452}
Torok Edwinc4174d62009-12-13 08:59:40 +0000453#else
454std::string sys::getHostCPUName() {
Benjamin Kramer110e7bb2009-11-17 17:57:04 +0000455 return "generic";
Daniel Dunbar067d0242009-11-14 10:09:12 +0000456}
Torok Edwinc4174d62009-12-13 08:59:40 +0000457#endif
Xerxes Ranby1c8183d2010-01-19 21:26:05 +0000458
459bool sys::getHostCPUFeatures(StringMap<bool> &Features){
460 return false;
461}