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