LLVM API Documentation
00001 //===-- X86Subtarget.cpp - X86 Subtarget Information ------------*- C++ -*-===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file was developed by Nate Begeman and is distributed under the 00006 // University of Illinois Open Source License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // This file implements the X86 specific subclass of TargetSubtarget. 00011 // 00012 //===----------------------------------------------------------------------===// 00013 00014 #include "X86Subtarget.h" 00015 #include "llvm/Module.h" 00016 #include "X86GenSubtarget.inc" 00017 using namespace llvm; 00018 00019 /// GetCpuIDAndInfo - Execute the specified cpuid and return the 4 values in the 00020 /// specified arguments. If we can't run cpuid on the host, return true. 00021 static bool GetCpuIDAndInfo(unsigned value, unsigned *rEAX, unsigned *rEBX, 00022 unsigned *rECX, unsigned *rEDX) { 00023 #if defined(i386) || defined(__i386__) || defined(__x86__) || defined(_M_IX86) 00024 #if defined(__GNUC__) 00025 asm ("pushl\t%%ebx\n\t" 00026 "cpuid\n\t" 00027 "movl\t%%ebx, %%esi\n\t" 00028 "popl\t%%ebx" 00029 : "=a" (*rEAX), 00030 "=S" (*rEBX), 00031 "=c" (*rECX), 00032 "=d" (*rEDX) 00033 : "a" (value)); 00034 return false; 00035 #elif defined(_MSC_VER) 00036 __asm { 00037 mov eax,value 00038 cpuid 00039 mov esi,rEAX 00040 mov dword ptr [esi],eax 00041 mov esi,rEBX 00042 mov dword ptr [esi],ebx 00043 mov esi,rECX 00044 mov dword ptr [esi],ecx 00045 mov esi,rEDX 00046 mov dword ptr [esi],edx 00047 } 00048 return false; 00049 #endif 00050 #endif 00051 return true; 00052 } 00053 00054 static const char *GetCurrentX86CPU() { 00055 unsigned EAX = 0, EBX = 0, ECX = 0, EDX = 0; 00056 if (GetCpuIDAndInfo(0x1, &EAX, &EBX, &ECX, &EDX)) 00057 return "generic"; 00058 unsigned Family = (EAX & (0xffffffff >> (32 - 4)) << 8) >> 8; // Bits 8 - 11 00059 unsigned Model = (EAX & (0xffffffff >> (32 - 4)) << 4) >> 4; // Bits 4 - 7 00060 GetCpuIDAndInfo(0x80000001, &EAX, &EBX, &ECX, &EDX); 00061 bool Em64T = EDX & (1 << 29); 00062 00063 union { 00064 unsigned u[3]; 00065 char c[12]; 00066 } text; 00067 00068 GetCpuIDAndInfo(0, &EAX, text.u+0, text.u+2, text.u+1); 00069 if (memcmp(text.c, "GenuineIntel", 12) == 0) { 00070 switch (Family) { 00071 case 3: 00072 return "i386"; 00073 case 4: 00074 return "i486"; 00075 case 5: 00076 switch (Model) { 00077 case 4: return "pentium-mmx"; 00078 default: return "pentium"; 00079 } 00080 case 6: 00081 switch (Model) { 00082 case 1: return "pentiumpro"; 00083 case 3: 00084 case 5: 00085 case 6: return "pentium2"; 00086 case 7: 00087 case 8: 00088 case 10: 00089 case 11: return "pentium3"; 00090 case 9: 00091 case 13: return "pentium-m"; 00092 case 14: return "yonah"; 00093 default: 00094 return (Model > 14) ? "yonah" : "i686"; 00095 } 00096 case 15: { 00097 switch (Model) { 00098 case 3: 00099 case 4: 00100 return (Em64T) ? "nocona" : "prescott"; 00101 default: 00102 return (Em64T) ? "x86-64" : "pentium4"; 00103 } 00104 } 00105 00106 default: 00107 return "generic"; 00108 } 00109 } else if (memcmp(text.c, "AuthenticAMD", 12) == 0) { 00110 // FIXME: this poorly matches the generated SubtargetFeatureKV table. There 00111 // appears to be no way to generate the wide variety of AMD-specific targets 00112 // from the information returned from CPUID. 00113 switch (Family) { 00114 case 4: 00115 return "i486"; 00116 case 5: 00117 switch (Model) { 00118 case 6: 00119 case 7: return "k6"; 00120 case 8: return "k6-2"; 00121 case 9: 00122 case 13: return "k6-3"; 00123 default: return "pentium"; 00124 } 00125 case 6: 00126 switch (Model) { 00127 case 4: return "athlon-tbird"; 00128 case 6: 00129 case 7: 00130 case 8: return "athlon-mp"; 00131 case 10: return "athlon-xp"; 00132 default: return "athlon"; 00133 } 00134 case 15: 00135 switch (Model) { 00136 case 5: return "athlon-fx"; // also opteron 00137 default: return "athlon64"; 00138 } 00139 00140 default: 00141 return "generic"; 00142 } 00143 } else { 00144 return "generic"; 00145 } 00146 } 00147 00148 X86Subtarget::X86Subtarget(const Module &M, const std::string &FS) { 00149 stackAlignment = 8; 00150 // FIXME: this is a known good value for Yonah. Not sure about others. 00151 MinRepStrSizeThreshold = 128; 00152 X86SSELevel = NoMMXSSE; 00153 X863DNowLevel = NoThreeDNow; 00154 Is64Bit = false; 00155 00156 // Determine default and user specified characteristics 00157 std::string CPU = GetCurrentX86CPU(); 00158 00159 // Parse features string. 00160 ParseSubtargetFeatures(FS, CPU); 00161 00162 // Default to ELF unless otherwise specified. 00163 TargetType = isELF; 00164 00165 // Set the boolean corresponding to the current target triple, or the default 00166 // if one cannot be determined, to true. 00167 const std::string& TT = M.getTargetTriple(); 00168 if (TT.length() > 5) { 00169 if (TT.find("cygwin") != std::string::npos || 00170 TT.find("mingw") != std::string::npos) 00171 TargetType = isCygwin; 00172 else if (TT.find("darwin") != std::string::npos) 00173 TargetType = isDarwin; 00174 else if (TT.find("win32") != std::string::npos) 00175 TargetType = isWindows; 00176 } else if (TT.empty()) { 00177 #if defined(__CYGWIN__) || defined(__MINGW32__) 00178 TargetType = isCygwin; 00179 #elif defined(__APPLE__) 00180 TargetType = isDarwin; 00181 #elif defined(_WIN32) 00182 TargetType = isWindows; 00183 #endif 00184 } 00185 00186 if (TargetType == isDarwin || TargetType == isCygwin) 00187 stackAlignment = 16; 00188 }