Host.cpp revision 223017
1218885Sdim//===-- Host.cpp - Implement OS Host Concept --------------------*- C++ -*-===// 2218885Sdim// 3218885Sdim// The LLVM Compiler Infrastructure 4218885Sdim// 5218885Sdim// This file is distributed under the University of Illinois Open Source 6218885Sdim// License. See LICENSE.TXT for details. 7218885Sdim// 8218885Sdim//===----------------------------------------------------------------------===// 9218885Sdim// 10218885Sdim// This header file implements the operating system Host concept. 11218885Sdim// 12218885Sdim//===----------------------------------------------------------------------===// 13218885Sdim 14218885Sdim#include "llvm/Support/Host.h" 15218885Sdim#include "llvm/Config/config.h" 16218885Sdim#include <string.h> 17218885Sdim 18218885Sdim// Include the platform-specific parts of this class. 19218885Sdim#ifdef LLVM_ON_UNIX 20218885Sdim#include "Unix/Host.inc" 21218885Sdim#endif 22218885Sdim#ifdef LLVM_ON_WIN32 23218885Sdim#include "Windows/Host.inc" 24218885Sdim#endif 25218885Sdim#ifdef _MSC_VER 26218885Sdim#include <intrin.h> 27218885Sdim#endif 28218885Sdim 29218885Sdim//===----------------------------------------------------------------------===// 30218885Sdim// 31218885Sdim// Implementations of the CPU detection routines 32218885Sdim// 33218885Sdim//===----------------------------------------------------------------------===// 34218885Sdim 35218885Sdimusing namespace llvm; 36218885Sdim 37218885Sdim#if defined(i386) || defined(__i386__) || defined(__x86__) || defined(_M_IX86)\ 38218885Sdim || defined(__x86_64__) || defined(_M_AMD64) || defined (_M_X64) 39218885Sdim 40218885Sdim/// GetX86CpuIDAndInfo - Execute the specified cpuid and return the 4 values in the 41218885Sdim/// specified arguments. If we can't run cpuid on the host, return true. 42218885Sdimstatic bool GetX86CpuIDAndInfo(unsigned value, unsigned *rEAX, 43218885Sdim unsigned *rEBX, unsigned *rECX, unsigned *rEDX) { 44218885Sdim#if defined(__x86_64__) || defined(_M_AMD64) || defined (_M_X64) 45218885Sdim #if defined(__GNUC__) 46218885Sdim // gcc doesn't know cpuid would clobber ebx/rbx. Preseve it manually. 47218885Sdim asm ("movq\t%%rbx, %%rsi\n\t" 48218885Sdim "cpuid\n\t" 49218885Sdim "xchgq\t%%rbx, %%rsi\n\t" 50218885Sdim : "=a" (*rEAX), 51218885Sdim "=S" (*rEBX), 52218885Sdim "=c" (*rECX), 53218885Sdim "=d" (*rEDX) 54218885Sdim : "a" (value)); 55218885Sdim return false; 56218885Sdim #elif defined(_MSC_VER) 57218885Sdim int registers[4]; 58218885Sdim __cpuid(registers, value); 59218885Sdim *rEAX = registers[0]; 60218885Sdim *rEBX = registers[1]; 61218885Sdim *rECX = registers[2]; 62218885Sdim *rEDX = registers[3]; 63218885Sdim return false; 64218885Sdim #endif 65218885Sdim#elif defined(i386) || defined(__i386__) || defined(__x86__) || defined(_M_IX86) 66218885Sdim #if defined(__GNUC__) 67218885Sdim asm ("movl\t%%ebx, %%esi\n\t" 68218885Sdim "cpuid\n\t" 69218885Sdim "xchgl\t%%ebx, %%esi\n\t" 70218885Sdim : "=a" (*rEAX), 71218885Sdim "=S" (*rEBX), 72218885Sdim "=c" (*rECX), 73218885Sdim "=d" (*rEDX) 74218885Sdim : "a" (value)); 75218885Sdim return false; 76218885Sdim #elif defined(_MSC_VER) 77218885Sdim __asm { 78218885Sdim mov eax,value 79218885Sdim cpuid 80218885Sdim mov esi,rEAX 81218885Sdim mov dword ptr [esi],eax 82218885Sdim mov esi,rEBX 83218885Sdim mov dword ptr [esi],ebx 84218885Sdim mov esi,rECX 85218885Sdim mov dword ptr [esi],ecx 86218885Sdim mov esi,rEDX 87218885Sdim mov dword ptr [esi],edx 88218885Sdim } 89218885Sdim return false; 90218885Sdim #endif 91218885Sdim#endif 92218885Sdim return true; 93218885Sdim} 94218885Sdim 95218885Sdimstatic void DetectX86FamilyModel(unsigned EAX, unsigned &Family, 96218885Sdim unsigned &Model) { 97218885Sdim Family = (EAX >> 8) & 0xf; // Bits 8 - 11 98218885Sdim Model = (EAX >> 4) & 0xf; // Bits 4 - 7 99218885Sdim if (Family == 6 || Family == 0xf) { 100218885Sdim if (Family == 0xf) 101218885Sdim // Examine extended family ID if family ID is F. 102218885Sdim Family += (EAX >> 20) & 0xff; // Bits 20 - 27 103218885Sdim // Examine extended model ID if family ID is 6 or F. 104218885Sdim Model += ((EAX >> 16) & 0xf) << 4; // Bits 16 - 19 105218885Sdim } 106218885Sdim} 107218885Sdim 108218885Sdimstd::string sys::getHostCPUName() { 109218885Sdim unsigned EAX = 0, EBX = 0, ECX = 0, EDX = 0; 110218885Sdim if (GetX86CpuIDAndInfo(0x1, &EAX, &EBX, &ECX, &EDX)) 111218885Sdim return "generic"; 112218885Sdim unsigned Family = 0; 113218885Sdim unsigned Model = 0; 114218885Sdim DetectX86FamilyModel(EAX, Family, Model); 115218885Sdim 116218885Sdim bool HasSSE3 = (ECX & 0x1); 117218885Sdim GetX86CpuIDAndInfo(0x80000001, &EAX, &EBX, &ECX, &EDX); 118218885Sdim bool Em64T = (EDX >> 29) & 0x1; 119218885Sdim 120218885Sdim union { 121218885Sdim unsigned u[3]; 122218885Sdim char c[12]; 123218885Sdim } text; 124218885Sdim 125218885Sdim GetX86CpuIDAndInfo(0, &EAX, text.u+0, text.u+2, text.u+1); 126218885Sdim if (memcmp(text.c, "GenuineIntel", 12) == 0) { 127218885Sdim switch (Family) { 128218885Sdim case 3: 129218885Sdim return "i386"; 130218885Sdim case 4: 131218885Sdim switch (Model) { 132218885Sdim case 0: // Intel486 DX processors 133218885Sdim case 1: // Intel486 DX processors 134218885Sdim case 2: // Intel486 SX processors 135218885Sdim case 3: // Intel487 processors, IntelDX2 OverDrive processors, 136218885Sdim // IntelDX2 processors 137218885Sdim case 4: // Intel486 SL processor 138218885Sdim case 5: // IntelSX2 processors 139218885Sdim case 7: // Write-Back Enhanced IntelDX2 processors 140218885Sdim case 8: // IntelDX4 OverDrive processors, IntelDX4 processors 141218885Sdim default: return "i486"; 142218885Sdim } 143218885Sdim case 5: 144218885Sdim switch (Model) { 145218885Sdim case 1: // Pentium OverDrive processor for Pentium processor (60, 66), 146218885Sdim // Pentium processors (60, 66) 147218885Sdim case 2: // Pentium OverDrive processor for Pentium processor (75, 90, 148218885Sdim // 100, 120, 133), Pentium processors (75, 90, 100, 120, 133, 149218885Sdim // 150, 166, 200) 150218885Sdim case 3: // Pentium OverDrive processors for Intel486 processor-based 151218885Sdim // systems 152218885Sdim return "pentium"; 153218885Sdim 154218885Sdim case 4: // Pentium OverDrive processor with MMX technology for Pentium 155218885Sdim // processor (75, 90, 100, 120, 133), Pentium processor with 156218885Sdim // MMX technology (166, 200) 157218885Sdim return "pentium-mmx"; 158218885Sdim 159218885Sdim default: return "pentium"; 160218885Sdim } 161218885Sdim case 6: 162218885Sdim switch (Model) { 163218885Sdim case 1: // Pentium Pro processor 164218885Sdim return "pentiumpro"; 165218885Sdim 166218885Sdim case 3: // Intel Pentium II OverDrive processor, Pentium II processor, 167218885Sdim // model 03 168218885Sdim case 5: // Pentium II processor, model 05, Pentium II Xeon processor, 169218885Sdim // model 05, and Intel Celeron processor, model 05 170218885Sdim case 6: // Celeron processor, model 06 171218885Sdim return "pentium2"; 172218885Sdim 173218885Sdim case 7: // Pentium III processor, model 07, and Pentium III Xeon 174218885Sdim // processor, model 07 175218885Sdim case 8: // Pentium III processor, model 08, Pentium III Xeon processor, 176218885Sdim // model 08, and Celeron processor, model 08 177218885Sdim case 10: // Pentium III Xeon processor, model 0Ah 178218885Sdim case 11: // Pentium III processor, model 0Bh 179218885Sdim return "pentium3"; 180218885Sdim 181218885Sdim case 9: // Intel Pentium M processor, Intel Celeron M processor model 09. 182218885Sdim case 13: // Intel Pentium M processor, Intel Celeron M processor, model 183218885Sdim // 0Dh. All processors are manufactured using the 90 nm process. 184218885Sdim return "pentium-m"; 185218885Sdim 186218885Sdim case 14: // Intel Core Duo processor, Intel Core Solo processor, model 187218885Sdim // 0Eh. All processors are manufactured using the 65 nm process. 188218885Sdim return "yonah"; 189218885Sdim 190218885Sdim case 15: // Intel Core 2 Duo processor, Intel Core 2 Duo mobile 191218885Sdim // processor, Intel Core 2 Quad processor, Intel Core 2 Quad 192218885Sdim // mobile processor, Intel Core 2 Extreme processor, Intel 193218885Sdim // Pentium Dual-Core processor, Intel Xeon processor, model 194218885Sdim // 0Fh. All processors are manufactured using the 65 nm process. 195218885Sdim case 22: // Intel Celeron processor model 16h. All processors are 196218885Sdim // manufactured using the 65 nm process 197218885Sdim return "core2"; 198218885Sdim 199218885Sdim case 21: // Intel EP80579 Integrated Processor and Intel EP80579 200218885Sdim // Integrated Processor with Intel QuickAssist Technology 201218885Sdim return "i686"; // FIXME: ??? 202218885Sdim 203218885Sdim case 23: // Intel Core 2 Extreme processor, Intel Xeon processor, model 204218885Sdim // 17h. All processors are manufactured using the 45 nm process. 205218885Sdim // 206218885Sdim // 45nm: Penryn , Wolfdale, Yorkfield (XE) 207218885Sdim return "penryn"; 208218885Sdim 209218885Sdim case 26: // Intel Core i7 processor and Intel Xeon processor. All 210218885Sdim // processors are manufactured using the 45 nm process. 211218885Sdim case 29: // Intel Xeon processor MP. All processors are manufactured using 212218885Sdim // the 45 nm process. 213218885Sdim case 30: // Intel(R) Core(TM) i7 CPU 870 @ 2.93GHz. 214218885Sdim // As found in a Summer 2010 model iMac. 215218885Sdim case 37: // Intel Core i7, laptop version. 216218885Sdim return "corei7"; 217221345Sdim case 42: // SandyBridge 218223017Sdim case 45: 219223017Sdim return "corei7-avx"; 220218885Sdim 221218885Sdim case 28: // Intel Atom processor. All processors are manufactured using 222218885Sdim // the 45 nm process 223218885Sdim return "atom"; 224218885Sdim 225218885Sdim default: return "i686"; 226218885Sdim } 227218885Sdim case 15: { 228218885Sdim switch (Model) { 229218885Sdim case 0: // Pentium 4 processor, Intel Xeon processor. All processors are 230218885Sdim // model 00h and manufactured using the 0.18 micron process. 231218885Sdim case 1: // Pentium 4 processor, Intel Xeon processor, Intel Xeon 232218885Sdim // processor MP, and Intel Celeron processor. All processors are 233218885Sdim // model 01h and manufactured using the 0.18 micron process. 234218885Sdim case 2: // Pentium 4 processor, Mobile Intel Pentium 4 processor - M, 235218885Sdim // Intel Xeon processor, Intel Xeon processor MP, Intel Celeron 236218885Sdim // processor, and Mobile Intel Celeron processor. All processors 237218885Sdim // are model 02h and manufactured using the 0.13 micron process. 238218885Sdim return (Em64T) ? "x86-64" : "pentium4"; 239218885Sdim 240218885Sdim case 3: // Pentium 4 processor, Intel Xeon processor, Intel Celeron D 241218885Sdim // processor. All processors are model 03h and manufactured using 242218885Sdim // the 90 nm process. 243218885Sdim case 4: // Pentium 4 processor, Pentium 4 processor Extreme Edition, 244218885Sdim // Pentium D processor, Intel Xeon processor, Intel Xeon 245218885Sdim // processor MP, Intel Celeron D processor. All processors are 246218885Sdim // model 04h and manufactured using the 90 nm process. 247218885Sdim case 6: // Pentium 4 processor, Pentium D processor, Pentium processor 248218885Sdim // Extreme Edition, Intel Xeon processor, Intel Xeon processor 249218885Sdim // MP, Intel Celeron D processor. All processors are model 06h 250218885Sdim // and manufactured using the 65 nm process. 251218885Sdim return (Em64T) ? "nocona" : "prescott"; 252218885Sdim 253218885Sdim default: 254218885Sdim return (Em64T) ? "x86-64" : "pentium4"; 255218885Sdim } 256218885Sdim } 257218885Sdim 258218885Sdim default: 259218885Sdim return "generic"; 260218885Sdim } 261218885Sdim } else if (memcmp(text.c, "AuthenticAMD", 12) == 0) { 262218885Sdim // FIXME: this poorly matches the generated SubtargetFeatureKV table. There 263218885Sdim // appears to be no way to generate the wide variety of AMD-specific targets 264218885Sdim // from the information returned from CPUID. 265218885Sdim switch (Family) { 266218885Sdim case 4: 267218885Sdim return "i486"; 268218885Sdim case 5: 269218885Sdim switch (Model) { 270218885Sdim case 6: 271218885Sdim case 7: return "k6"; 272218885Sdim case 8: return "k6-2"; 273218885Sdim case 9: 274218885Sdim case 13: return "k6-3"; 275218885Sdim default: return "pentium"; 276218885Sdim } 277218885Sdim case 6: 278218885Sdim switch (Model) { 279218885Sdim case 4: return "athlon-tbird"; 280218885Sdim case 6: 281218885Sdim case 7: 282218885Sdim case 8: return "athlon-mp"; 283218885Sdim case 10: return "athlon-xp"; 284218885Sdim default: return "athlon"; 285218885Sdim } 286218885Sdim case 15: 287218885Sdim if (HasSSE3) 288218885Sdim return "k8-sse3"; 289218885Sdim switch (Model) { 290218885Sdim case 1: return "opteron"; 291218885Sdim case 5: return "athlon-fx"; // also opteron 292218885Sdim default: return "athlon64"; 293218885Sdim } 294218885Sdim case 16: 295218885Sdim return "amdfam10"; 296218885Sdim default: 297218885Sdim return "generic"; 298218885Sdim } 299218885Sdim } 300218885Sdim return "generic"; 301218885Sdim} 302218885Sdim#else 303218885Sdimstd::string sys::getHostCPUName() { 304218885Sdim return "generic"; 305218885Sdim} 306218885Sdim#endif 307218885Sdim 308218885Sdimbool sys::getHostCPUFeatures(StringMap<bool> &Features){ 309218885Sdim return false; 310218885Sdim} 311