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