#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;
+// FIXME: temporary.
+#include "llvm/Support/CommandLine.h"
+namespace {
+ cl::opt<bool> EnableSSE("enable-x86-sse", cl::Hidden,
+ cl::desc("Enable sse on X86"));
+}
+
+static void GetCpuIDAndInfo(unsigned value, unsigned *EAX, unsigned *EBX,
+ unsigned *ECX, unsigned *EDX) {
+#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" (*EAX),
+ "=S" (*EBX),
+ "=c" (*ECX),
+ "=d" (*EDX)
+ : "a" (value));
+#endif
+#endif
+}
+
+static const char *GetCurrentX86CPU() {
+ unsigned EAX = 0, EBX = 0, ECX = 0, EDX = 0;
+ GetCpuIDAndInfo(0x1, &EAX, &EBX, &ECX, &EDX);
+ 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);
+ switch (Family) {
+ case 3:
+ return "i386";
+ case 4:
+ return "i486";
+ case 5:
+ switch (Model) {
+ case 4: return "pentium-mmx";
+ default: return "pentium";
+ }
+ break;
+ 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";
+ }
+}
+
+X86Subtarget::X86Subtarget(const Module &M, const std::string &FS)
+ : stackAlignment(8), indirectExternAndWeakGlobals(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;
+
+ // FIXME: Force these off until they work. An llc-beta option should turn
+ // them back on.
+ if (!EnableSSE) {
+ X86SSELevel = NoMMXSSE;
+ X863DNowLevel = NoThreeDNow;
+ }
+
// 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) {
stackAlignment = 16;
indirectExternAndWeakGlobals = true;
- asmDarwinLinkerStubs = true;
- asmLeadingUnderscore = true;
- asmPrintDotLCommConstants = true;
- } else if (forWindows) {
}
}