X86MCTargetDesc.cpp revision 224133
1224133Sdim//===-- X86MCTargetDesc.cpp - X86 Target Descriptions -----------*- C++ -*-===// 2224133Sdim// 3224133Sdim// The LLVM Compiler Infrastructure 4224133Sdim// 5224133Sdim// This file is distributed under the University of Illinois Open Source 6224133Sdim// License. See LICENSE.TXT for details. 7224133Sdim// 8224133Sdim//===----------------------------------------------------------------------===// 9224133Sdim// 10224133Sdim// This file provides X86 specific target descriptions. 11224133Sdim// 12224133Sdim//===----------------------------------------------------------------------===// 13224133Sdim 14224133Sdim#include "X86MCTargetDesc.h" 15224133Sdim#include "X86MCAsmInfo.h" 16224133Sdim#include "llvm/MC/MCInstrInfo.h" 17224133Sdim#include "llvm/MC/MCRegisterInfo.h" 18224133Sdim#include "llvm/MC/MCSubtargetInfo.h" 19224133Sdim#include "llvm/Target/TargetRegistry.h" 20224133Sdim#include "llvm/ADT/Triple.h" 21224133Sdim#include "llvm/Support/Host.h" 22224133Sdim 23224133Sdim#define GET_REGINFO_MC_DESC 24224133Sdim#include "X86GenRegisterInfo.inc" 25224133Sdim 26224133Sdim#define GET_INSTRINFO_MC_DESC 27224133Sdim#include "X86GenInstrInfo.inc" 28224133Sdim 29224133Sdim#define GET_SUBTARGETINFO_MC_DESC 30224133Sdim#include "X86GenSubtargetInfo.inc" 31224133Sdim 32224133Sdimusing namespace llvm; 33224133Sdim 34224133Sdim 35224133Sdimstd::string X86_MC::ParseX86Triple(StringRef TT) { 36224133Sdim Triple TheTriple(TT); 37224133Sdim if (TheTriple.getArch() == Triple::x86_64) 38224133Sdim return "+64bit-mode"; 39224133Sdim return "-64bit-mode"; 40224133Sdim} 41224133Sdim 42224133Sdim/// GetCpuIDAndInfo - Execute the specified cpuid and return the 4 values in the 43224133Sdim/// specified arguments. If we can't run cpuid on the host, return true. 44224133Sdimbool X86_MC::GetCpuIDAndInfo(unsigned value, unsigned *rEAX, 45224133Sdim unsigned *rEBX, unsigned *rECX, unsigned *rEDX) { 46224133Sdim#if defined(__x86_64__) || defined(_M_AMD64) || defined (_M_X64) 47224133Sdim #if defined(__GNUC__) 48224133Sdim // gcc doesn't know cpuid would clobber ebx/rbx. Preseve it manually. 49224133Sdim asm ("movq\t%%rbx, %%rsi\n\t" 50224133Sdim "cpuid\n\t" 51224133Sdim "xchgq\t%%rbx, %%rsi\n\t" 52224133Sdim : "=a" (*rEAX), 53224133Sdim "=S" (*rEBX), 54224133Sdim "=c" (*rECX), 55224133Sdim "=d" (*rEDX) 56224133Sdim : "a" (value)); 57224133Sdim return false; 58224133Sdim #elif defined(_MSC_VER) 59224133Sdim int registers[4]; 60224133Sdim __cpuid(registers, value); 61224133Sdim *rEAX = registers[0]; 62224133Sdim *rEBX = registers[1]; 63224133Sdim *rECX = registers[2]; 64224133Sdim *rEDX = registers[3]; 65224133Sdim return false; 66224133Sdim #endif 67224133Sdim#elif defined(i386) || defined(__i386__) || defined(__x86__) || defined(_M_IX86) 68224133Sdim #if defined(__GNUC__) 69224133Sdim asm ("movl\t%%ebx, %%esi\n\t" 70224133Sdim "cpuid\n\t" 71224133Sdim "xchgl\t%%ebx, %%esi\n\t" 72224133Sdim : "=a" (*rEAX), 73224133Sdim "=S" (*rEBX), 74224133Sdim "=c" (*rECX), 75224133Sdim "=d" (*rEDX) 76224133Sdim : "a" (value)); 77224133Sdim return false; 78224133Sdim #elif defined(_MSC_VER) 79224133Sdim __asm { 80224133Sdim mov eax,value 81224133Sdim cpuid 82224133Sdim mov esi,rEAX 83224133Sdim mov dword ptr [esi],eax 84224133Sdim mov esi,rEBX 85224133Sdim mov dword ptr [esi],ebx 86224133Sdim mov esi,rECX 87224133Sdim mov dword ptr [esi],ecx 88224133Sdim mov esi,rEDX 89224133Sdim mov dword ptr [esi],edx 90224133Sdim } 91224133Sdim return false; 92224133Sdim #endif 93224133Sdim#endif 94224133Sdim return true; 95224133Sdim} 96224133Sdim 97224133Sdimvoid X86_MC::DetectFamilyModel(unsigned EAX, unsigned &Family, 98224133Sdim unsigned &Model) { 99224133Sdim Family = (EAX >> 8) & 0xf; // Bits 8 - 11 100224133Sdim Model = (EAX >> 4) & 0xf; // Bits 4 - 7 101224133Sdim if (Family == 6 || Family == 0xf) { 102224133Sdim if (Family == 0xf) 103224133Sdim // Examine extended family ID if family ID is F. 104224133Sdim Family += (EAX >> 20) & 0xff; // Bits 20 - 27 105224133Sdim // Examine extended model ID if family ID is 6 or F. 106224133Sdim Model += ((EAX >> 16) & 0xf) << 4; // Bits 16 - 19 107224133Sdim } 108224133Sdim} 109224133Sdim 110224133SdimMCSubtargetInfo *X86_MC::createX86MCSubtargetInfo(StringRef TT, StringRef CPU, 111224133Sdim StringRef FS) { 112224133Sdim std::string ArchFS = X86_MC::ParseX86Triple(TT); 113224133Sdim if (!FS.empty()) { 114224133Sdim if (!ArchFS.empty()) 115224133Sdim ArchFS = ArchFS + "," + FS.str(); 116224133Sdim else 117224133Sdim ArchFS = FS; 118224133Sdim } 119224133Sdim 120224133Sdim std::string CPUName = CPU; 121224133Sdim if (CPUName.empty()) { 122224133Sdim#if defined (__x86_64__) || defined(__i386__) 123224133Sdim CPUName = sys::getHostCPUName(); 124224133Sdim#else 125224133Sdim CPUName = "generic"; 126224133Sdim#endif 127224133Sdim } 128224133Sdim 129224133Sdim MCSubtargetInfo *X = new MCSubtargetInfo(); 130224133Sdim InitX86MCSubtargetInfo(X, TT, CPUName, ArchFS); 131224133Sdim return X; 132224133Sdim} 133224133Sdim 134224133Sdim// Force static initialization. 135224133Sdimextern "C" void LLVMInitializeX86MCSubtargetInfo() { 136224133Sdim TargetRegistry::RegisterMCSubtargetInfo(TheX86_32Target, 137224133Sdim X86_MC::createX86MCSubtargetInfo); 138224133Sdim TargetRegistry::RegisterMCSubtargetInfo(TheX86_64Target, 139224133Sdim X86_MC::createX86MCSubtargetInfo); 140224133Sdim} 141224133Sdim 142224133Sdimstatic MCInstrInfo *createX86MCInstrInfo() { 143224133Sdim MCInstrInfo *X = new MCInstrInfo(); 144224133Sdim InitX86MCInstrInfo(X); 145224133Sdim return X; 146224133Sdim} 147224133Sdim 148224133Sdimextern "C" void LLVMInitializeX86MCInstrInfo() { 149224133Sdim TargetRegistry::RegisterMCInstrInfo(TheX86_32Target, createX86MCInstrInfo); 150224133Sdim TargetRegistry::RegisterMCInstrInfo(TheX86_64Target, createX86MCInstrInfo); 151224133Sdim} 152224133Sdim 153224133Sdimstatic MCRegisterInfo *createX86MCRegisterInfo() { 154224133Sdim MCRegisterInfo *X = new MCRegisterInfo(); 155224133Sdim InitX86MCRegisterInfo(X); 156224133Sdim return X; 157224133Sdim} 158224133Sdim 159224133Sdimextern "C" void LLVMInitializeX86MCRegInfo() { 160224133Sdim TargetRegistry::RegisterMCRegInfo(TheX86_32Target, createX86MCRegisterInfo); 161224133Sdim TargetRegistry::RegisterMCRegInfo(TheX86_64Target, createX86MCRegisterInfo); 162224133Sdim} 163224133Sdim 164224133Sdim 165224133Sdimstatic MCAsmInfo *createX86MCAsmInfo(const Target &T, StringRef TT) { 166224133Sdim Triple TheTriple(TT); 167224133Sdim 168224133Sdim if (TheTriple.isOSDarwin() || TheTriple.getEnvironment() == Triple::MachO) { 169224133Sdim if (TheTriple.getArch() == Triple::x86_64) 170224133Sdim return new X86_64MCAsmInfoDarwin(TheTriple); 171224133Sdim else 172224133Sdim return new X86MCAsmInfoDarwin(TheTriple); 173224133Sdim } 174224133Sdim 175224133Sdim if (TheTriple.isOSWindows()) 176224133Sdim return new X86MCAsmInfoCOFF(TheTriple); 177224133Sdim 178224133Sdim return new X86ELFMCAsmInfo(TheTriple); 179224133Sdim} 180224133Sdim 181224133Sdimextern "C" void LLVMInitializeX86MCAsmInfo() { 182224133Sdim // Register the target asm info. 183224133Sdim RegisterMCAsmInfoFn A(TheX86_32Target, createX86MCAsmInfo); 184224133Sdim RegisterMCAsmInfoFn B(TheX86_64Target, createX86MCAsmInfo); 185224133Sdim} 186