LLVM API Documentation

X86Subtarget.cpp

Go to the documentation of this file.
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 }