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