For non-x86 host, used generic as CPU name.
[oota-llvm.git] / lib / Target / X86 / MCTargetDesc / X86MCTargetDesc.cpp
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
32 using namespace llvm;
33
34
35 std::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.
44 bool 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
97 void 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
110 static 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
132 MCSubtargetInfo *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
160 MCInstrInfo *createX86MCInstrInfo() {
161   MCInstrInfo *X = new MCInstrInfo();
162   InitX86MCInstrInfo(X);
163   return X;
164 }
165
166 MCRegisterInfo *createX86MCRegisterInfo() {
167   MCRegisterInfo *X = new MCRegisterInfo();
168   InitX86MCRegisterInfo(X);
169   return X;
170 }
171
172 // Force static initialization.
173 extern "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
181 extern "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 }