diff options
Diffstat (limited to 'lib/Target/X86/X86Subtarget.cpp')
-rw-r--r-- | lib/Target/X86/X86Subtarget.cpp | 107 |
1 files changed, 104 insertions, 3 deletions
diff --git a/lib/Target/X86/X86Subtarget.cpp b/lib/Target/X86/X86Subtarget.cpp index caa846bc59..3fe25fdac4 100644 --- a/lib/Target/X86/X86Subtarget.cpp +++ b/lib/Target/X86/X86Subtarget.cpp @@ -12,7 +12,7 @@ //===----------------------------------------------------------------------===// #include "X86Subtarget.h" -//#include "X86GenSubtarget.inc" +#include "X86GenSubtarget.inc" #include "llvm/Module.h" #include "llvm/Support/CommandLine.h" #include <iostream> @@ -72,7 +72,7 @@ static inline bool GetCpuIDAndInfo(unsigned value, unsigned *rEAX, unsigned *rEB return true; } -void X86Subtarget::DetectSubtargetFeatures() { +void X86Subtarget::AutoDetectSubtargetFeatures() { unsigned EAX = 0, EBX = 0, ECX = 0, EDX = 0; union { unsigned u[3]; @@ -96,6 +96,100 @@ void X86Subtarget::DetectSubtargetFeatures() { } } +static const char *GetCurrentX86CPU() { + unsigned EAX = 0, EBX = 0, ECX = 0, EDX = 0; + if (GetCpuIDAndInfo(0x1, &EAX, &EBX, &ECX, &EDX)) + return "generic"; + unsigned Family = (EAX >> 8) & 0xf; // Bits 8 - 11 + unsigned Model = (EAX >> 4) & 0xf; // Bits 4 - 7 + GetCpuIDAndInfo(0x80000001, &EAX, &EBX, &ECX, &EDX); + bool Em64T = EDX & (1 << 29); + + union { + unsigned u[3]; + char c[12]; + } text; + + GetCpuIDAndInfo(0, &EAX, text.u+0, text.u+2, text.u+1); + if (memcmp(text.c, "GenuineIntel", 12) == 0) { + switch (Family) { + case 3: + return "i386"; + case 4: + return "i486"; + case 5: + switch (Model) { + case 4: return "pentium-mmx"; + default: return "pentium"; + } + case 6: + switch (Model) { + case 1: return "pentiumpro"; + case 3: + case 5: + case 6: return "pentium2"; + case 7: + case 8: + case 10: + case 11: return "pentium3"; + case 9: + case 13: return "pentium-m"; + case 14: return "yonah"; + case 15: return "core2"; + default: return "i686"; + } + case 15: { + switch (Model) { + case 3: + case 4: + return (Em64T) ? "nocona" : "prescott"; + default: + return (Em64T) ? "x86-64" : "pentium4"; + } + } + + default: + return "generic"; + } + } else if (memcmp(text.c, "AuthenticAMD", 12) == 0) { + // FIXME: this poorly matches the generated SubtargetFeatureKV table. There + // appears to be no way to generate the wide variety of AMD-specific targets + // from the information returned from CPUID. + switch (Family) { + case 4: + return "i486"; + case 5: + switch (Model) { + case 6: + case 7: return "k6"; + case 8: return "k6-2"; + case 9: + case 13: return "k6-3"; + default: return "pentium"; + } + case 6: + switch (Model) { + case 4: return "athlon-tbird"; + case 6: + case 7: + case 8: return "athlon-mp"; + case 10: return "athlon-xp"; + default: return "athlon"; + } + case 15: + switch (Model) { + case 5: return "athlon-fx"; // also opteron + default: return "athlon64"; + } + + default: + return "generic"; + } + } else { + return "generic"; + } +} + X86Subtarget::X86Subtarget(const Module &M, const std::string &FS, bool is64Bit) : AsmFlavor(AsmWriterFlavor) , X86SSELevel(NoMMXSSE) @@ -107,7 +201,14 @@ X86Subtarget::X86Subtarget(const Module &M, const std::string &FS, bool is64Bit) , TargetType(isELF) { // Default to ELF unless otherwise specified. // Determine default and user specified characteristics - DetectSubtargetFeatures(); + if (!FS.empty()) { + // If feature string is not empty, parse features string. + std::string CPU = GetCurrentX86CPU(); + ParseSubtargetFeatures(FS, CPU); + } else + // Otherwise, use CPUID to auto-detect feature set. + AutoDetectSubtargetFeatures(); + if (Is64Bit && !HasX86_64) { std::cerr << "Warning: Generation of 64-bit code for a 32-bit processor " "requested.\n"; |