implement zextload bool and truncstore bool
[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 "X86GenSubtarget.inc"
16 #include "llvm/Module.h"
17 #include "llvm/Support/CommandLine.h"
18 #include <iostream>
19 using namespace llvm;
20
21 cl::opt<X86Subtarget::AsmWriterFlavorTy>
22 AsmWriterFlavor("x86-asm-syntax", cl::init(X86Subtarget::unset),
23   cl::desc("Choose style of code to emit from X86 backend:"),
24   cl::values(
25     clEnumValN(X86Subtarget::att,   "att",   "  Emit AT&T-style assembly"),
26     clEnumValN(X86Subtarget::intel, "intel", "  Emit Intel-style assembly"),
27     clEnumValEnd));
28
29
30 /// GetCpuIDAndInfo - Execute the specified cpuid and return the 4 values in the
31 /// specified arguments.  If we can't run cpuid on the host, return true.
32 bool X86::GetCpuIDAndInfo(unsigned value, unsigned *rEAX, unsigned *rEBX,
33                           unsigned *rECX, unsigned *rEDX) {
34 #if defined(__x86_64__)
35   // gcc doesn't know cpuid would clobber ebx/rbx. Preseve it manually.
36   asm ("movq\t%%rbx, %%rsi\n\t"
37        "cpuid\n\t"
38        "xchgq\t%%rbx, %%rsi\n\t"
39        : "=a" (*rEAX),
40          "=S" (*rEBX),
41          "=c" (*rECX),
42          "=d" (*rEDX)
43        :  "a" (value));
44   return false;
45 #elif defined(i386) || defined(__i386__) || defined(__x86__) || defined(_M_IX86)
46 #if defined(__GNUC__)
47   asm ("pushl\t%%ebx\n\t"
48        "cpuid\n\t"
49        "movl\t%%ebx, %%esi\n\t"
50        "popl\t%%ebx"
51        : "=a" (*rEAX),
52          "=S" (*rEBX),
53          "=c" (*rECX),
54          "=d" (*rEDX)
55        :  "a" (value));
56   return false;
57 #elif defined(_MSC_VER)
58   __asm {
59     mov   eax,value
60     cpuid
61     mov   esi,rEAX
62     mov   dword ptr [esi],eax
63     mov   esi,rEBX
64     mov   dword ptr [esi],ebx
65     mov   esi,rECX
66     mov   dword ptr [esi],ecx
67     mov   esi,rEDX
68     mov   dword ptr [esi],edx
69   }
70   return false;
71 #endif
72 #endif
73   return true;
74 }
75
76 void X86Subtarget::AutoDetectSubtargetFeatures() {
77   unsigned EAX = 0, EBX = 0, ECX = 0, EDX = 0;
78   union {
79     unsigned u[3];
80     char     c[12];
81   } text;
82
83   if (X86::GetCpuIDAndInfo(0, &EAX, text.u+0, text.u+2, text.u+1))
84     return;
85
86   // FIXME: support for AMD family of processors.
87   if (memcmp(text.c, "GenuineIntel", 12) == 0) {
88     X86::GetCpuIDAndInfo(0x1, &EAX, &EBX, &ECX, &EDX);
89
90     if ((EDX >> 23) & 0x1) X86SSELevel = MMX;
91     if ((EDX >> 25) & 0x1) X86SSELevel = SSE1;
92     if ((EDX >> 26) & 0x1) X86SSELevel = SSE2;
93     if (ECX & 0x1)         X86SSELevel = SSE3;
94
95     X86::GetCpuIDAndInfo(0x80000001, &EAX, &EBX, &ECX, &EDX);
96     HasX86_64 = (EDX >> 29) & 0x1;
97   }
98 }
99
100 static const char *GetCurrentX86CPU() {
101   unsigned EAX = 0, EBX = 0, ECX = 0, EDX = 0;
102   if (X86::GetCpuIDAndInfo(0x1, &EAX, &EBX, &ECX, &EDX))
103     return "generic";
104   unsigned Family  = (EAX >> 8) & 0xf; // Bits 8 - 11
105   unsigned Model   = (EAX >> 4) & 0xf; // Bits 4 - 7
106   X86::GetCpuIDAndInfo(0x80000001, &EAX, &EBX, &ECX, &EDX);
107   bool Em64T = (EDX >> 29) & 0x1;
108
109   union {
110     unsigned u[3];
111     char     c[12];
112   } text;
113
114   X86::GetCpuIDAndInfo(0, &EAX, text.u+0, text.u+2, text.u+1);
115   if (memcmp(text.c, "GenuineIntel", 12) == 0) {
116     switch (Family) {
117       case 3:
118         return "i386";
119       case 4:
120         return "i486";
121       case 5:
122         switch (Model) {
123         case 4:  return "pentium-mmx";
124         default: return "pentium";
125         }
126       case 6:
127         switch (Model) {
128         case 1:  return "pentiumpro";
129         case 3:
130         case 5:
131         case 6:  return "pentium2";
132         case 7:
133         case 8:
134         case 10:
135         case 11: return "pentium3";
136         case 9:
137         case 13: return "pentium-m";
138         case 14: return "yonah";
139         case 15: return "core2";
140         default: return "i686";
141         }
142       case 15: {
143         switch (Model) {
144         case 3:  
145         case 4:
146           return (Em64T) ? "nocona" : "prescott";
147         default:
148           return (Em64T) ? "x86-64" : "pentium4";
149         }
150       }
151         
152     default:
153       return "generic";
154     }
155   } else if (memcmp(text.c, "AuthenticAMD", 12) == 0) {
156     // FIXME: this poorly matches the generated SubtargetFeatureKV table.  There
157     // appears to be no way to generate the wide variety of AMD-specific targets
158     // from the information returned from CPUID.
159     switch (Family) {
160       case 4:
161         return "i486";
162       case 5:
163         switch (Model) {
164         case 6:
165         case 7:  return "k6";
166         case 8:  return "k6-2";
167         case 9:
168         case 13: return "k6-3";
169         default: return "pentium";
170         }
171       case 6:
172         switch (Model) {
173         case 4:  return "athlon-tbird";
174         case 6:
175         case 7:
176         case 8:  return "athlon-mp";
177         case 10: return "athlon-xp";
178         default: return "athlon";
179         }
180       case 15:
181         switch (Model) {
182         case 5:  return "athlon-fx"; // also opteron
183         default: return "athlon64";
184         }
185
186     default:
187       return "generic";
188     }
189   } else {
190     return "generic";
191   }
192 }
193
194 X86Subtarget::X86Subtarget(const Module &M, const std::string &FS, bool is64Bit)
195   : AsmFlavor(AsmWriterFlavor)
196   , X86SSELevel(NoMMXSSE)
197   , HasX86_64(false)
198   , stackAlignment(8)
199   // FIXME: this is a known good value for Yonah. How about others?
200   , MinRepStrSizeThreshold(128)
201   , Is64Bit(is64Bit)
202   , TargetType(isELF) { // Default to ELF unless otherwise specified.
203
204   // Determine default and user specified characteristics
205   if (!FS.empty()) {
206     // If feature string is not empty, parse features string.
207     std::string CPU = GetCurrentX86CPU();
208     ParseSubtargetFeatures(FS, CPU);
209   } else
210     // Otherwise, use CPUID to auto-detect feature set.
211     AutoDetectSubtargetFeatures();
212
213   if (Is64Bit && !HasX86_64) {
214       std::cerr << "Warning: Generation of 64-bit code for a 32-bit processor "
215                    "requested.\n";
216       HasX86_64 = true;
217   }
218
219   // Set the boolean corresponding to the current target triple, or the default
220   // if one cannot be determined, to true.
221   const std::string& TT = M.getTargetTriple();
222   if (TT.length() > 5) {
223     if (TT.find("cygwin") != std::string::npos ||
224         TT.find("mingw")  != std::string::npos)
225       TargetType = isCygwin;
226     else if (TT.find("darwin") != std::string::npos)
227       TargetType = isDarwin;
228     else if (TT.find("win32") != std::string::npos)
229       TargetType = isWindows;
230   } else if (TT.empty()) {
231 #if defined(__CYGWIN__) || defined(__MINGW32__)
232     TargetType = isCygwin;
233 #elif defined(__APPLE__)
234     TargetType = isDarwin;
235 #elif defined(_WIN32)
236     TargetType = isWindows;
237 #endif
238   }
239
240   // If the asm syntax hasn't been overridden on the command line, use whatever
241   // the target wants.
242   if (AsmFlavor == X86Subtarget::unset) {
243     if (TargetType == isWindows) {
244       AsmFlavor = X86Subtarget::intel;
245     } else {
246       AsmFlavor = X86Subtarget::att;
247     }
248   }
249
250   if (TargetType == isDarwin || TargetType == isCygwin)
251     stackAlignment = 16;
252 }