OSDN Git Service

Move PPC host-CPU detection logic from PPCSubtarget into sys::getHostCPUName().
[android-x86/external-llvm.git] / lib / Support / Host.cpp
1 //===-- 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
14 #include "llvm/ADT/StringRef.h"
15 #include "llvm/ADT/StringSwitch.h"
16 #include "llvm/Support/DataStream.h"
17 #include "llvm/Support/Debug.h"
18 #include "llvm/Support/Host.h"
19 #include "llvm/Support/raw_ostream.h"
20 #include "llvm/Config/config.h"
21 #include <string.h>
22
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
28 #include "Windows/Host.inc"
29 #endif
30 #ifdef _MSC_VER
31 #include <intrin.h>
32 #endif
33 #ifdef __APPLE__
34 #include <mach/mach.h>
35 #include <mach/mach_host.h>
36 #include <mach/host_info.h>
37 #include <mach/machine.h>
38 #endif
39
40 //===----------------------------------------------------------------------===//
41 //
42 //  Implementations of the CPU detection routines
43 //
44 //===----------------------------------------------------------------------===//
45
46 using 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.
53 static 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;
75   #else
76     return true;
77   #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;
103 // 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;
107   #endif
108 #else
109   return true;
110 #endif
111 }
112
113 static void DetectX86FamilyModel(unsigned EAX, unsigned &Family,
114                                  unsigned &Model) {
115   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 }
125
126 std::string sys::getHostCPUName() {
127   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
134   bool HasSSE3 = (ECX & 0x1);
135   GetX86CpuIDAndInfo(0x80000001, &EAX, &EBX, &ECX, &EDX);
136   bool Em64T = (EDX >> 29) & 0x1;
137
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) {
146     case 3:
147       return "i386";
148     case 4:
149       switch (Model) {
150       case 0: // Intel486 DX processors
151       case 1: // Intel486 DX processors
152       case 2: // Intel486 SX processors
153       case 3: // Intel487 processors, IntelDX2 OverDrive processors,
154               // IntelDX2 processors
155       case 4: // Intel486 SL processor
156       case 5: // IntelSX2 processors
157       case 7: // Write-Back Enhanced IntelDX2 processors
158       case 8: // IntelDX4 OverDrive processors, IntelDX4 processors
159       default: return "i486";
160       }
161     case 5:
162       switch (Model) {
163       case  1: // Pentium OverDrive processor for Pentium processor (60, 66),
164                // Pentium processors (60, 66)
165       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
172       case  4: // Pentium OverDrive processor with MMX technology for Pentium
173                // processor (75, 90, 100, 120, 133), Pentium processor with
174                // MMX technology (166, 200)
175         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,
187                // model 05, and Intel Celeron processor, model 05
188       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
204       case 14: // Intel Core Duo processor, Intel Core Solo processor, model
205                // 0Eh. All processors are manufactured using the 65 nm process.
206         return "yonah";
207
208       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
211                // 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
221       case 23: // Intel Core 2 Extreme processor, Intel Xeon processor, model
222                // 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.
231       case 30: // Intel(R) Core(TM) i7 CPU         870  @ 2.93GHz.
232                // As found in a Summer 2010 model iMac.
233       case 37: // Intel Core i7, laptop version.
234       case 44: // Intel Core i7 processor and Intel Xeon processor. All
235                // processors are manufactured using the 32 nm process.
236         return "corei7";
237
238       // SandyBridge:
239       case 42: // Intel Core i7 processor. All processors are manufactured
240                // using the 32 nm process.
241       case 45:
242         return "corei7-avx";
243
244       // Ivy Bridge:
245       case 58:
246         return "core-avx-i";
247
248       case 28: // Most 45 nm Intel Atom processors
249       case 38: // 45 nm Atom Lincroft
250       case 39: // 32 nm Atom Medfield
251         return "atom";
252
253       default: return (Em64T) ? "x86-64" : "i686";
254       }
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.
262       case  2: // Pentium 4 processor, Mobile Intel Pentium 4 processor - M,
263                // 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
281       default:
282         return (Em64T) ? "x86-64" : "pentium4";
283       }
284     }
285
286     default:
287       return "generic";
288     }
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:
315         if (HasSSE3)
316           return "k8-sse3";
317         switch (Model) {
318         case 1:  return "opteron";
319         case 5:  return "athlon-fx"; // also opteron
320         default: return "athlon64";
321         }
322       case 16:
323         return "amdfam10";
324       case 20:
325         return "btver1";
326       case 21:
327         return "bdver1";
328     default:
329       return "generic";
330     }
331   }
332   return "generic";
333 }
334 #elif defined(__APPLE__)
335 std::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__))
364 std::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 }
453 #else
454 std::string sys::getHostCPUName() {
455   return "generic";
456 }
457 #endif
458
459 bool sys::getHostCPUFeatures(StringMap<bool> &Features){
460   return false;
461 }