X86MCTargetDesc.cpp revision cc0ddc707d5a7b1dd11141881df0bf4210f8aeee
1//===-- X86MCTargetDesc.cpp - X86 Target Descriptions -----------*- C++ -*-===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9// 10// This file provides X86 specific target descriptions. 11// 12//===----------------------------------------------------------------------===// 13 14#include "X86MCTargetDesc.h" 15#include "llvm/MC/MCInstrInfo.h" 16#include "llvm/MC/MCRegisterInfo.h" 17#include "llvm/MC/MCSubtargetInfo.h" 18#include "llvm/Target/TargetRegistry.h" 19#include "llvm/ADT/Triple.h" 20#include "llvm/Support/Host.h" 21 22#define GET_REGINFO_MC_DESC 23#include "X86GenRegisterInfo.inc" 24 25#define GET_INSTRINFO_MC_DESC 26#include "X86GenInstrInfo.inc" 27 28#define GET_SUBTARGETINFO_ENUM 29#define GET_SUBTARGETINFO_MC_DESC 30#include "X86GenSubtargetInfo.inc" 31 32using namespace llvm; 33 34 35std::string X86_MC::ParseX86Triple(StringRef TT) { 36 Triple TheTriple(TT); 37 if (TheTriple.getArch() == Triple::x86_64) 38 return "+64bit-mode"; 39 return "-64bit-mode"; 40} 41 42/// GetCpuIDAndInfo - Execute the specified cpuid and return the 4 values in the 43/// specified arguments. If we can't run cpuid on the host, return true. 44bool X86_MC::GetCpuIDAndInfo(unsigned value, unsigned *rEAX, 45 unsigned *rEBX, unsigned *rECX, unsigned *rEDX) { 46#if defined(__x86_64__) || defined(_M_AMD64) || defined (_M_X64) 47 #if defined(__GNUC__) 48 // gcc doesn't know cpuid would clobber ebx/rbx. Preseve it manually. 49 asm ("movq\t%%rbx, %%rsi\n\t" 50 "cpuid\n\t" 51 "xchgq\t%%rbx, %%rsi\n\t" 52 : "=a" (*rEAX), 53 "=S" (*rEBX), 54 "=c" (*rECX), 55 "=d" (*rEDX) 56 : "a" (value)); 57 return false; 58 #elif defined(_MSC_VER) 59 int registers[4]; 60 __cpuid(registers, value); 61 *rEAX = registers[0]; 62 *rEBX = registers[1]; 63 *rECX = registers[2]; 64 *rEDX = registers[3]; 65 return false; 66 #endif 67#elif defined(i386) || defined(__i386__) || defined(__x86__) || defined(_M_IX86) 68 #if defined(__GNUC__) 69 asm ("movl\t%%ebx, %%esi\n\t" 70 "cpuid\n\t" 71 "xchgl\t%%ebx, %%esi\n\t" 72 : "=a" (*rEAX), 73 "=S" (*rEBX), 74 "=c" (*rECX), 75 "=d" (*rEDX) 76 : "a" (value)); 77 return false; 78 #elif defined(_MSC_VER) 79 __asm { 80 mov eax,value 81 cpuid 82 mov esi,rEAX 83 mov dword ptr [esi],eax 84 mov esi,rEBX 85 mov dword ptr [esi],ebx 86 mov esi,rECX 87 mov dword ptr [esi],ecx 88 mov esi,rEDX 89 mov dword ptr [esi],edx 90 } 91 return false; 92 #endif 93#endif 94 return true; 95} 96 97void X86_MC::DetectFamilyModel(unsigned EAX, unsigned &Family, 98 unsigned &Model) { 99 Family = (EAX >> 8) & 0xf; // Bits 8 - 11 100 Model = (EAX >> 4) & 0xf; // Bits 4 - 7 101 if (Family == 6 || Family == 0xf) { 102 if (Family == 0xf) 103 // Examine extended family ID if family ID is F. 104 Family += (EAX >> 20) & 0xff; // Bits 20 - 27 105 // Examine extended model ID if family ID is 6 or F. 106 Model += ((EAX >> 16) & 0xf) << 4; // Bits 16 - 19 107 } 108} 109 110static bool hasX86_64() { 111 // FIXME: Code duplication. See X86Subtarget::AutoDetectSubtargetFeatures. 112 unsigned EAX = 0, EBX = 0, ECX = 0, EDX = 0; 113 union { 114 unsigned u[3]; 115 char c[12]; 116 } text; 117 118 if (X86_MC::GetCpuIDAndInfo(0, &EAX, text.u+0, text.u+2, text.u+1)) 119 return false; 120 121 bool IsIntel = memcmp(text.c, "GenuineIntel", 12) == 0; 122 bool IsAMD = !IsIntel && memcmp(text.c, "AuthenticAMD", 12) == 0; 123 if (IsIntel || IsAMD) { 124 X86_MC::GetCpuIDAndInfo(0x80000001, &EAX, &EBX, &ECX, &EDX); 125 if ((EDX >> 29) & 0x1) 126 return true; 127 } 128 129 return false; 130} 131 132MCSubtargetInfo *X86_MC::createX86MCSubtargetInfo(StringRef TT, StringRef CPU, 133 StringRef FS) { 134 std::string ArchFS = X86_MC::ParseX86Triple(TT); 135 if (!FS.empty()) { 136 if (!ArchFS.empty()) 137 ArchFS = ArchFS + "," + FS.str(); 138 else 139 ArchFS = FS; 140 } 141 142 std::string CPUName = CPU; 143 if (CPUName.empty()) { 144#if defined (__x86_64__) || defined(__i386__) 145 CPUName = sys::getHostCPUName(); 146#else 147 CPUName = "generic"; 148#endif 149 } 150 151 if (ArchFS.empty() && CPUName.empty() && hasX86_64()) 152 // Auto-detect if host is 64-bit capable, it's the default if true. 153 ArchFS = "+64bit-mode"; 154 155 MCSubtargetInfo *X = new MCSubtargetInfo(); 156 InitX86MCSubtargetInfo(X, CPUName, ArchFS); 157 return X; 158} 159 160MCInstrInfo *createX86MCInstrInfo() { 161 MCInstrInfo *X = new MCInstrInfo(); 162 InitX86MCInstrInfo(X); 163 return X; 164} 165 166MCRegisterInfo *createX86MCRegisterInfo() { 167 MCRegisterInfo *X = new MCRegisterInfo(); 168 InitX86MCRegisterInfo(X); 169 return X; 170} 171 172// Force static initialization. 173extern "C" void LLVMInitializeX86MCInstrInfo() { 174 RegisterMCInstrInfo<MCInstrInfo> X(TheX86_32Target); 175 RegisterMCInstrInfo<MCInstrInfo> Y(TheX86_64Target); 176 177 TargetRegistry::RegisterMCInstrInfo(TheX86_32Target, createX86MCInstrInfo); 178 TargetRegistry::RegisterMCInstrInfo(TheX86_64Target, createX86MCInstrInfo); 179} 180 181extern "C" void LLVMInitializeX86MCRegInfo() { 182 RegisterMCRegInfo<MCRegisterInfo> X(TheX86_32Target); 183 RegisterMCRegInfo<MCRegisterInfo> Y(TheX86_64Target); 184 185 TargetRegistry::RegisterMCRegInfo(TheX86_32Target, createX86MCRegisterInfo); 186 TargetRegistry::RegisterMCRegInfo(TheX86_64Target, createX86MCRegisterInfo); 187} 188