Enable SSE (for the right subtargets)
[oota-llvm.git] / lib / Target / X86 / X86Subtarget.cpp
1 //===-- X86Subtarget.cpp - X86 Subtarget Information ------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file was developed by Nate Begeman and is distributed under the
6 // University of Illinois Open Source License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file implements the X86 specific subclass of TargetSubtarget.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #include "X86Subtarget.h"
15 #include "llvm/Module.h"
16 #include "X86GenSubtarget.inc"
17 using namespace llvm;
18
19 #include "llvm/Support/CommandLine.h"
20 namespace {
21   cl::opt<bool> DisableSSE("disable-x86-sse", cl::Hidden,
22                           cl::desc("Disable sse on X86"));
23 }
24
25 /// GetCpuIDAndInfo - Execute the specified cpuid and return the 4 values in the
26 /// specified arguments.  If we can't run cpuid on the host, return true.
27 static bool GetCpuIDAndInfo(unsigned value, unsigned *rEAX, unsigned *rEBX,
28                             unsigned *rECX, unsigned *rEDX) {
29 #if defined(i386) || defined(__i386__) || defined(__x86__) || defined(_M_IX86)
30 #if defined(__GNUC__)
31   asm ("pushl\t%%ebx\n\t"
32        "cpuid\n\t"
33        "movl\t%%ebx, %%esi\n\t"
34        "popl\t%%ebx"
35        : "=a" (*rEAX),
36          "=S" (*rEBX),
37          "=c" (*rECX),
38          "=d" (*rEDX)
39        :  "a" (value));
40   return false;
41 #elif defined(_MSC_VER)
42   __asm {
43     mov   eax,value
44     cpuid
45     mov   esi,rEAX
46     mov   dword ptr [esi],eax
47     mov   esi,rEBX
48     mov   dword ptr [esi],ebx
49     mov   esi,rECX
50     mov   dword ptr [esi],ecx
51     mov   esi,rEDX
52     mov   dword ptr [esi],edx
53   }
54   return false;
55 #endif
56 #endif
57   return true;
58 }
59
60 static const char *GetCurrentX86CPU() {
61   unsigned EAX = 0, EBX = 0, ECX = 0, EDX = 0;
62   if (GetCpuIDAndInfo(0x1, &EAX, &EBX, &ECX, &EDX))
63     return "generic";
64   unsigned Family  = (EAX & (0xffffffff >> (32 - 4)) << 8) >> 8; // Bits 8 - 11
65   unsigned Model   = (EAX & (0xffffffff >> (32 - 4)) << 4) >> 4; // Bits 4 - 7
66   GetCpuIDAndInfo(0x80000001, &EAX, &EBX, &ECX, &EDX);
67   bool Em64T = EDX & (1 << 29);
68
69   union {
70     unsigned u[3];
71     char     c[12];
72   } text;
73
74   GetCpuIDAndInfo(0, &EAX, text.u+0, text.u+2, text.u+1);
75   if (memcmp(text.c, "GenuineIntel", 12) == 0) {
76     switch (Family) {
77       case 3:
78         return "i386";
79       case 4:
80         return "i486";
81       case 5:
82         switch (Model) {
83         case 4:  return "pentium-mmx";
84         default: return "pentium";
85         }
86       case 6:
87         switch (Model) {
88         case 1:  return "pentiumpro";
89         case 3:
90         case 5:
91         case 6:  return "pentium2";
92         case 7:
93         case 8:
94         case 10:
95         case 11: return "pentium3";
96         case 9:
97         case 13: return "pentium-m";
98         case 14: return "yonah";
99         default: return "i686";
100         }
101       case 15: {
102         switch (Model) {
103         case 3:  
104         case 4:
105           return (Em64T) ? "nocona" : "prescott";
106         default:
107           return (Em64T) ? "x86-64" : "pentium4";
108         }
109       }
110         
111     default:
112       return "generic";
113     }
114   } else if (memcmp(text.c, "AuthenticAMD", 12) == 0) {
115     // FIXME: this poorly matches the generated SubtargetFeatureKV table.  There
116     // appears to be no way to generate the wide variety of AMD-specific targets
117     // from the information returned from CPUID.
118     switch (Family) {
119       case 4:
120         return "i486";
121       case 5:
122         switch (Model) {
123         case 6:
124         case 7:  return "k6";
125         case 8:  return "k6-2";
126         case 9:
127         case 13: return "k6-3";
128         default: return "pentium";
129         }
130       case 6:
131         switch (Model) {
132         case 4:  return "athlon-tbird";
133         case 6:
134         case 7:
135         case 8:  return "athlon-mp";
136         case 10: return "athlon-xp";
137         default: return "athlon";
138         }
139       case 15:
140         switch (Model) {
141         case 5:  return "athlon-fx"; // also opteron
142         default: return "athlon64";
143         }
144
145     default:
146       return "generic";
147     }
148   } else {
149     return "generic";
150   }
151 }
152
153 X86Subtarget::X86Subtarget(const Module &M, const std::string &FS) {
154   stackAlignment = 8;
155   indirectExternAndWeakGlobals = false;
156   X86SSELevel = NoMMXSSE;
157   X863DNowLevel = NoThreeDNow;
158   Is64Bit = false;
159
160   // Determine default and user specified characteristics
161   std::string CPU = GetCurrentX86CPU();
162
163   // Parse features string.
164   ParseSubtargetFeatures(FS, CPU);
165
166   // Default to ELF unless otherwise specified.
167   TargetType = isELF;
168   
169   if (DisableSSE) {
170     X86SSELevel = NoMMXSSE;
171     X863DNowLevel = NoThreeDNow;
172   }
173       
174   // Set the boolean corresponding to the current target triple, or the default
175   // if one cannot be determined, to true.
176   const std::string& TT = M.getTargetTriple();
177   if (TT.length() > 5) {
178     if (TT.find("cygwin") != std::string::npos ||
179         TT.find("mingw")  != std::string::npos)
180       TargetType = isCygwin;
181     else if (TT.find("darwin") != std::string::npos)
182       TargetType = isDarwin;
183     else if (TT.find("win32") != std::string::npos)
184       TargetType = isWindows;
185   } else if (TT.empty()) {
186 #if defined(__CYGWIN__) || defined(__MINGW32__)
187     TargetType = isCygwin;
188 #elif defined(__APPLE__)
189     TargetType = isDarwin;
190 #elif defined(_WIN32)
191     TargetType = isWindows;
192 #endif
193   }
194
195   if (TargetType == isDarwin) {
196     stackAlignment = 16;
197     indirectExternAndWeakGlobals = true;
198   }
199 }