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: return "i686"; 00094 } 00095 case 15: { 00096 switch (Model) { 00097 case 3: 00098 case 4: 00099 return (Em64T) ? "nocona" : "prescott"; 00100 default: 00101 return (Em64T) ? "x86-64" : "pentium4"; 00102 } 00103 } 00104 00105 default: 00106 return "generic"; 00107 } 00108 } else if (memcmp(text.c, "AuthenticAMD", 12) == 0) { 00109 // FIXME: this poorly matches the generated SubtargetFeatureKV table. There 00110 // appears to be no way to generate the wide variety of AMD-specific targets 00111 // from the information returned from CPUID. 00112 switch (Family) { 00113 case 4: 00114 return "i486"; 00115 case 5: 00116 switch (Model) { 00117 case 6: 00118 case 7: return "k6"; 00119 case 8: return "k6-2"; 00120 case 9: 00121 case 13: return "k6-3"; 00122 default: return "pentium"; 00123 } 00124 case 6: 00125 switch (Model) { 00126 case 4: return "athlon-tbird"; 00127 case 6: 00128 case 7: 00129 case 8: return "athlon-mp"; 00130 case 10: return "athlon-xp"; 00131 default: return "athlon"; 00132 } 00133 case 15: 00134 switch (Model) { 00135 case 5: return "athlon-fx"; // also opteron 00136 default: return "athlon64"; 00137 } 00138 00139 default: 00140 return "generic"; 00141 } 00142 } else { 00143 return "generic"; 00144 } 00145 } 00146 00147 X86Subtarget::X86Subtarget(const Module &M, const std::string &FS) { 00148 stackAlignment = 8; 00149 // FIXME: this is a known good value for Yonah. Not sure about others. 00150 MinRepStrSizeThreshold = 128; 00151 X86SSELevel = NoMMXSSE; 00152 X863DNowLevel = NoThreeDNow; 00153 Is64Bit = false; 00154 00155 // Determine default and user specified characteristics 00156 std::string CPU = GetCurrentX86CPU(); 00157 00158 // Parse features string. 00159 ParseSubtargetFeatures(FS, CPU); 00160 00161 // Default to ELF unless otherwise specified. 00162 TargetType = isELF; 00163 00164 // Set the boolean corresponding to the current target triple, or the default 00165 // if one cannot be determined, to true. 00166 const std::string& TT = M.getTargetTriple(); 00167 if (TT.length() > 5) { 00168 if (TT.find("cygwin") != std::string::npos || 00169 TT.find("mingw") != std::string::npos) 00170 TargetType = isCygwin; 00171 else if (TT.find("darwin") != std::string::npos) 00172 TargetType = isDarwin; 00173 else if (TT.find("win32") != std::string::npos) 00174 TargetType = isWindows; 00175 } else if (TT.empty()) { 00176 #if defined(__CYGWIN__) || defined(__MINGW32__) 00177 TargetType = isCygwin; 00178 #elif defined(__APPLE__) 00179 TargetType = isDarwin; 00180 #elif defined(_WIN32) 00181 TargetType = isWindows; 00182 #endif 00183 } 00184 00185 if (TargetType == isDarwin) 00186 stackAlignment = 16; 00187 }