X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FTarget%2FX86%2FX86Subtarget.cpp;h=cafa09cc7d96f6518591f908606877e184816f8e;hb=932ad51feabc4119dda978c4f147dfe1b010a95d;hp=f2ebdd4abec89504dbcce1f6e3f2474e2868cd25;hpb=00b16889ab461b7ecef1c91ade101186b7f1fce2;p=oota-llvm.git diff --git a/lib/Target/X86/X86Subtarget.cpp b/lib/Target/X86/X86Subtarget.cpp index f2ebdd4abec..cafa09cc7d9 100644 --- a/lib/Target/X86/X86Subtarget.cpp +++ b/lib/Target/X86/X86Subtarget.cpp @@ -1,4 +1,4 @@ -//===- X86Subtarget.cpp - X86 Instruction Information -----------*- C++ -*-===// +//===-- X86Subtarget.cpp - X86 Subtarget Information ------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -13,45 +13,175 @@ #include "X86Subtarget.h" #include "llvm/Module.h" +#include "X86GenSubtarget.inc" using namespace llvm; -X86Subtarget::X86Subtarget(const Module &M) - : TargetSubtarget(), stackAlignment(8), - indirectExternAndWeakGlobals(false), asmDarwinLinkerStubs(false), - asmLeadingUnderscore(false), asmAlignmentIsInBytes(false), - asmPrintDotLocalConstants(false), asmPrintDotLCommConstants(false), - asmPrintConstantAlignment(false) { - // Declare a boolean for each major platform. - bool forCygwin = false; - bool forDarwin = false; - bool forWindows = false; +/// GetCpuIDAndInfo - Execute the specified cpuid and return the 4 values in the +/// specified arguments. If we can't run cpuid on the host, return true. +static bool GetCpuIDAndInfo(unsigned value, unsigned *rEAX, unsigned *rEBX, + unsigned *rECX, unsigned *rEDX) { +#if defined(i386) || defined(__i386__) || defined(__x86__) || defined(_M_IX86) +#if defined(__GNUC__) + asm ("pushl\t%%ebx\n\t" + "cpuid\n\t" + "movl\t%%ebx, %%esi\n\t" + "popl\t%%ebx" + : "=a" (*rEAX), + "=S" (*rEBX), + "=c" (*rECX), + "=d" (*rEDX) + : "a" (value)); + return false; +#elif defined(_MSC_VER) + __asm { + mov eax,value + cpuid + mov esi,rEAX + mov dword ptr [esi],eax + mov esi,rEBX + mov dword ptr [esi],ebx + mov esi,rECX + mov dword ptr [esi],ecx + mov esi,rEDX + mov dword ptr [esi],edx + } + return false; +#endif +#endif + return true; +} + +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 & (0xffffffff >> (32 - 4)) << 8) >> 8; // Bits 8 - 11 + unsigned Model = (EAX & (0xffffffff >> (32 - 4)) << 4) >> 4; // 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"; + 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) { + stackAlignment = 8; + // FIXME: this is a known good value for Yonah. Not sure about others. + MinRepStrSizeThreshold = 128; + X86SSELevel = NoMMXSSE; + X863DNowLevel = NoThreeDNow; + Is64Bit = false; + + // Determine default and user specified characteristics + std::string CPU = GetCurrentX86CPU(); + + // Parse features string. + ParseSubtargetFeatures(FS, CPU); + + // Default to ELF unless otherwise specified. + TargetType = isELF; + // Set the boolean corresponding to the current target triple, or the default // if one cannot be determined, to true. const std::string& TT = M.getTargetTriple(); if (TT.length() > 5) { - forCygwin = TT.find("cygwin") != std::string::npos || - TT.find("mingw") != std::string::npos; - forDarwin = TT.find("darwin") != std::string::npos; - forWindows = TT.find("win32") != std::string::npos; + if (TT.find("cygwin") != std::string::npos || + TT.find("mingw") != std::string::npos) + TargetType = isCygwin; + else if (TT.find("darwin") != std::string::npos) + TargetType = isDarwin; + else if (TT.find("win32") != std::string::npos) + TargetType = isWindows; } else if (TT.empty()) { #if defined(__CYGWIN__) || defined(__MINGW32__) - forCygwin = true; + TargetType = isCygwin; #elif defined(__APPLE__) - forDarwin = true; + TargetType = isDarwin; #elif defined(_WIN32) - forWindows = true; + TargetType = isWindows; #endif } - if (forCygwin) { - asmLeadingUnderscore = true; - } else if (forDarwin) { + if (TargetType == isDarwin || TargetType == isCygwin) stackAlignment = 16; - indirectExternAndWeakGlobals = true; - asmDarwinLinkerStubs = true; - asmLeadingUnderscore = true; - asmPrintDotLCommConstants = true; - } else if (forWindows) { - } }