X86MCTargetDesc.cpp revision c60f9b752381baa6c4b80c0739034660f1748c84
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_MC_DESC
29#include "X86GenSubtargetInfo.inc"
30
31using namespace llvm;
32
33
34std::string X86_MC::ParseX86Triple(StringRef TT) {
35  Triple TheTriple(TT);
36  if (TheTriple.getArch() == Triple::x86_64)
37    return "+64bit-mode";
38  return "-64bit-mode";
39}
40
41/// GetCpuIDAndInfo - Execute the specified cpuid and return the 4 values in the
42/// specified arguments.  If we can't run cpuid on the host, return true.
43bool X86_MC::GetCpuIDAndInfo(unsigned value, unsigned *rEAX,
44                             unsigned *rEBX, unsigned *rECX, unsigned *rEDX) {
45#if defined(__x86_64__) || defined(_M_AMD64) || defined (_M_X64)
46  #if defined(__GNUC__)
47    // gcc doesn't know cpuid would clobber ebx/rbx. Preseve it manually.
48    asm ("movq\t%%rbx, %%rsi\n\t"
49         "cpuid\n\t"
50         "xchgq\t%%rbx, %%rsi\n\t"
51         : "=a" (*rEAX),
52           "=S" (*rEBX),
53           "=c" (*rECX),
54           "=d" (*rEDX)
55         :  "a" (value));
56    return false;
57  #elif defined(_MSC_VER)
58    int registers[4];
59    __cpuid(registers, value);
60    *rEAX = registers[0];
61    *rEBX = registers[1];
62    *rECX = registers[2];
63    *rEDX = registers[3];
64    return false;
65  #endif
66#elif defined(i386) || defined(__i386__) || defined(__x86__) || defined(_M_IX86)
67  #if defined(__GNUC__)
68    asm ("movl\t%%ebx, %%esi\n\t"
69         "cpuid\n\t"
70         "xchgl\t%%ebx, %%esi\n\t"
71         : "=a" (*rEAX),
72           "=S" (*rEBX),
73           "=c" (*rECX),
74           "=d" (*rEDX)
75         :  "a" (value));
76    return false;
77  #elif defined(_MSC_VER)
78    __asm {
79      mov   eax,value
80      cpuid
81      mov   esi,rEAX
82      mov   dword ptr [esi],eax
83      mov   esi,rEBX
84      mov   dword ptr [esi],ebx
85      mov   esi,rECX
86      mov   dword ptr [esi],ecx
87      mov   esi,rEDX
88      mov   dword ptr [esi],edx
89    }
90    return false;
91  #endif
92#endif
93  return true;
94}
95
96void X86_MC::DetectFamilyModel(unsigned EAX, unsigned &Family,
97                               unsigned &Model) {
98  Family = (EAX >> 8) & 0xf; // Bits 8 - 11
99  Model  = (EAX >> 4) & 0xf; // Bits 4 - 7
100  if (Family == 6 || Family == 0xf) {
101    if (Family == 0xf)
102      // Examine extended family ID if family ID is F.
103      Family += (EAX >> 20) & 0xff;    // Bits 20 - 27
104    // Examine extended model ID if family ID is 6 or F.
105    Model += ((EAX >> 16) & 0xf) << 4; // Bits 16 - 19
106  }
107}
108
109MCSubtargetInfo *X86_MC::createX86MCSubtargetInfo(StringRef TT, StringRef CPU,
110                                                  StringRef FS) {
111  std::string ArchFS = X86_MC::ParseX86Triple(TT);
112  if (!FS.empty()) {
113    if (!ArchFS.empty())
114      ArchFS = ArchFS + "," + FS.str();
115    else
116      ArchFS = FS;
117  }
118
119  std::string CPUName = CPU;
120  if (CPUName.empty()) {
121#if defined (__x86_64__) || defined(__i386__)
122    CPUName = sys::getHostCPUName();
123#else
124    CPUName = "generic";
125#endif
126  }
127
128  MCSubtargetInfo *X = new MCSubtargetInfo();
129  InitX86MCSubtargetInfo(X, TT, CPUName, ArchFS);
130  return X;
131}
132
133MCInstrInfo *createX86MCInstrInfo() {
134  MCInstrInfo *X = new MCInstrInfo();
135  InitX86MCInstrInfo(X);
136  return X;
137}
138
139MCRegisterInfo *createX86MCRegisterInfo() {
140  MCRegisterInfo *X = new MCRegisterInfo();
141  InitX86MCRegisterInfo(X);
142  return X;
143}
144
145// Force static initialization.
146extern "C" void LLVMInitializeX86MCInstrInfo() {
147  TargetRegistry::RegisterMCInstrInfo(TheX86_32Target, createX86MCInstrInfo);
148  TargetRegistry::RegisterMCInstrInfo(TheX86_64Target, createX86MCInstrInfo);
149}
150
151extern "C" void LLVMInitializeX86MCRegInfo() {
152  TargetRegistry::RegisterMCRegInfo(TheX86_32Target, createX86MCRegisterInfo);
153  TargetRegistry::RegisterMCRegInfo(TheX86_64Target, createX86MCRegisterInfo);
154}
155
156
157extern "C" void LLVMInitializeX86MCSubtargetInfo() {
158  TargetRegistry::RegisterMCSubtargetInfo(TheX86_32Target,
159                                          X86_MC::createX86MCSubtargetInfo);
160  TargetRegistry::RegisterMCSubtargetInfo(TheX86_64Target,
161                                          X86_MC::createX86MCSubtargetInfo);
162}
163