X86MCTargetDesc.cpp revision 224133
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 "X86MCAsmInfo.h"
16#include "llvm/MC/MCInstrInfo.h"
17#include "llvm/MC/MCRegisterInfo.h"
18#include "llvm/MC/MCSubtargetInfo.h"
19#include "llvm/Target/TargetRegistry.h"
20#include "llvm/ADT/Triple.h"
21#include "llvm/Support/Host.h"
22
23#define GET_REGINFO_MC_DESC
24#include "X86GenRegisterInfo.inc"
25
26#define GET_INSTRINFO_MC_DESC
27#include "X86GenInstrInfo.inc"
28
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
110MCSubtargetInfo *X86_MC::createX86MCSubtargetInfo(StringRef TT, StringRef CPU,
111                                                  StringRef FS) {
112  std::string ArchFS = X86_MC::ParseX86Triple(TT);
113  if (!FS.empty()) {
114    if (!ArchFS.empty())
115      ArchFS = ArchFS + "," + FS.str();
116    else
117      ArchFS = FS;
118  }
119
120  std::string CPUName = CPU;
121  if (CPUName.empty()) {
122#if defined (__x86_64__) || defined(__i386__)
123    CPUName = sys::getHostCPUName();
124#else
125    CPUName = "generic";
126#endif
127  }
128
129  MCSubtargetInfo *X = new MCSubtargetInfo();
130  InitX86MCSubtargetInfo(X, TT, CPUName, ArchFS);
131  return X;
132}
133
134// Force static initialization.
135extern "C" void LLVMInitializeX86MCSubtargetInfo() {
136  TargetRegistry::RegisterMCSubtargetInfo(TheX86_32Target,
137                                          X86_MC::createX86MCSubtargetInfo);
138  TargetRegistry::RegisterMCSubtargetInfo(TheX86_64Target,
139                                          X86_MC::createX86MCSubtargetInfo);
140}
141
142static MCInstrInfo *createX86MCInstrInfo() {
143  MCInstrInfo *X = new MCInstrInfo();
144  InitX86MCInstrInfo(X);
145  return X;
146}
147
148extern "C" void LLVMInitializeX86MCInstrInfo() {
149  TargetRegistry::RegisterMCInstrInfo(TheX86_32Target, createX86MCInstrInfo);
150  TargetRegistry::RegisterMCInstrInfo(TheX86_64Target, createX86MCInstrInfo);
151}
152
153static MCRegisterInfo *createX86MCRegisterInfo() {
154  MCRegisterInfo *X = new MCRegisterInfo();
155  InitX86MCRegisterInfo(X);
156  return X;
157}
158
159extern "C" void LLVMInitializeX86MCRegInfo() {
160  TargetRegistry::RegisterMCRegInfo(TheX86_32Target, createX86MCRegisterInfo);
161  TargetRegistry::RegisterMCRegInfo(TheX86_64Target, createX86MCRegisterInfo);
162}
163
164
165static MCAsmInfo *createX86MCAsmInfo(const Target &T, StringRef TT) {
166  Triple TheTriple(TT);
167
168  if (TheTriple.isOSDarwin() || TheTriple.getEnvironment() == Triple::MachO) {
169    if (TheTriple.getArch() == Triple::x86_64)
170      return new X86_64MCAsmInfoDarwin(TheTriple);
171    else
172      return new X86MCAsmInfoDarwin(TheTriple);
173  }
174
175  if (TheTriple.isOSWindows())
176    return new X86MCAsmInfoCOFF(TheTriple);
177
178  return new X86ELFMCAsmInfo(TheTriple);
179}
180
181extern "C" void LLVMInitializeX86MCAsmInfo() {
182  // Register the target asm info.
183  RegisterMCAsmInfoFn A(TheX86_32Target, createX86MCAsmInfo);
184  RegisterMCAsmInfoFn B(TheX86_64Target, createX86MCAsmInfo);
185}
186