//
include "../Target.td"
+//===----------------------------------------------------------------------===//
+// X86 Subtarget features.
+//
+
+def Feature64Bit : SubtargetFeature<"64bit", "HasX86_64", "true",
+ "Support 64-bit instructions">;
+def FeatureMMX : SubtargetFeature<"mmx","X86SSELevel", "MMX",
+ "Enable MMX instructions">;
+def FeatureSSE1 : SubtargetFeature<"sse", "X86SSELevel", "SSE1",
+ "Enable SSE instructions">;
+def FeatureSSE2 : SubtargetFeature<"sse2", "X86SSELevel", "SSE2",
+ "Enable SSE2 instructions">;
+def FeatureSSE3 : SubtargetFeature<"sse3", "X86SSELevel", "SSE3",
+ "Enable SSE3 instructions">;
+def Feature3DNow : SubtargetFeature<"3dnow", "X863DNowLevel", "ThreeDNow",
+ "Enable 3DNow! instructions">;
+def Feature3DNowA : SubtargetFeature<"3dnowa", "X863DNowLevel", "ThreeDNowA",
+ "Enable 3DNow! Athlon instructions">;
+
+//===----------------------------------------------------------------------===//
+// X86 processors supported.
+//===----------------------------------------------------------------------===//
+
+class Proc<string Name, list<SubtargetFeature> Features>
+ : Processor<Name, NoItineraries, Features>;
+
+def : Proc<"generic", []>;
+def : Proc<"i386", []>;
+def : Proc<"i486", []>;
+def : Proc<"pentium", []>;
+def : Proc<"pentium-mmx", [FeatureMMX]>;
+def : Proc<"i686", []>;
+def : Proc<"pentiumpro", []>;
+def : Proc<"pentium2", [FeatureMMX]>;
+def : Proc<"pentium3", [FeatureMMX, FeatureSSE1]>;
+def : Proc<"pentium-m", [FeatureMMX, FeatureSSE1, FeatureSSE2]>;
+def : Proc<"pentium4", [FeatureMMX, FeatureSSE1, FeatureSSE2]>;
+def : Proc<"x86-64", [FeatureMMX, FeatureSSE1, FeatureSSE2,
+ Feature64Bit]>;
+def : Proc<"yonah", [FeatureMMX, FeatureSSE1, FeatureSSE2,
+ FeatureSSE3]>;
+def : Proc<"prescott", [FeatureMMX, FeatureSSE1, FeatureSSE2,
+ FeatureSSE3]>;
+def : Proc<"nocona", [FeatureMMX, FeatureSSE1, FeatureSSE2,
+ FeatureSSE3, Feature64Bit]>;
+def : Proc<"core2", [FeatureMMX, FeatureSSE1, FeatureSSE2,
+ FeatureSSE3, Feature64Bit]>;
+
+def : Proc<"k6", [FeatureMMX]>;
+def : Proc<"k6-2", [FeatureMMX, Feature3DNow]>;
+def : Proc<"k6-3", [FeatureMMX, Feature3DNow]>;
+def : Proc<"athlon", [FeatureMMX, Feature3DNow, Feature3DNowA]>;
+def : Proc<"athlon-tbird", [FeatureMMX, Feature3DNow, Feature3DNowA]>;
+def : Proc<"athlon-4", [FeatureMMX, FeatureSSE1, Feature3DNow,
+ Feature3DNowA]>;
+def : Proc<"athlon-xp", [FeatureMMX, FeatureSSE1, Feature3DNow,
+ Feature3DNowA]>;
+def : Proc<"athlon-mp", [FeatureMMX, FeatureSSE1, Feature3DNow,
+ Feature3DNowA]>;
+def : Proc<"k8", [FeatureMMX, FeatureSSE1, FeatureSSE2,
+ Feature3DNow, Feature3DNowA, Feature64Bit]>;
+def : Proc<"opteron", [FeatureMMX, FeatureSSE1, FeatureSSE2,
+ Feature3DNow, Feature3DNowA, Feature64Bit]>;
+def : Proc<"athlon64", [FeatureMMX, FeatureSSE1, FeatureSSE2,
+ Feature3DNow, Feature3DNowA, Feature64Bit]>;
+def : Proc<"athlon-fx", [FeatureMMX, FeatureSSE1, FeatureSSE2,
+ Feature3DNow, Feature3DNowA, Feature64Bit]>;
+
+def : Proc<"winchip-c6", [FeatureMMX]>;
+def : Proc<"winchip2", [FeatureMMX, Feature3DNow]>;
+def : Proc<"c3", [FeatureMMX, Feature3DNow]>;
+def : Proc<"c3-2", [FeatureMMX, FeatureSSE1]>;
+
//===----------------------------------------------------------------------===//
// Register File Description
//===----------------------------------------------------------------------===//
//===----------------------------------------------------------------------===//
#include "X86Subtarget.h"
-//#include "X86GenSubtarget.inc"
+#include "X86GenSubtarget.inc"
#include "llvm/Module.h"
#include "llvm/Support/CommandLine.h"
#include <iostream>
return true;
}
-void X86Subtarget::DetectSubtargetFeatures() {
+void X86Subtarget::AutoDetectSubtargetFeatures() {
unsigned EAX = 0, EBX = 0, ECX = 0, EDX = 0;
union {
unsigned u[3];
}
}
+static const char *GetCurrentX86CPU() {
+ unsigned EAX = 0, EBX = 0, ECX = 0, EDX = 0;
+ if (GetCpuIDAndInfo(0x1, &EAX, &EBX, &ECX, &EDX))
+ return "generic";
+ unsigned Family = (EAX >> 8) & 0xf; // Bits 8 - 11
+ unsigned Model = (EAX >> 4) & 0xf; // Bits 4 - 7
+ GetCpuIDAndInfo(0x80000001, &EAX, &EBX, &ECX, &EDX);
+ bool Em64T = EDX & (1 << 29);
+
+ union {
+ unsigned u[3];
+ char c[12];
+ } text;
+
+ GetCpuIDAndInfo(0, &EAX, text.u+0, text.u+2, text.u+1);
+ if (memcmp(text.c, "GenuineIntel", 12) == 0) {
+ switch (Family) {
+ case 3:
+ return "i386";
+ case 4:
+ return "i486";
+ case 5:
+ switch (Model) {
+ case 4: return "pentium-mmx";
+ default: return "pentium";
+ }
+ case 6:
+ switch (Model) {
+ case 1: return "pentiumpro";
+ case 3:
+ case 5:
+ case 6: return "pentium2";
+ case 7:
+ case 8:
+ case 10:
+ case 11: return "pentium3";
+ case 9:
+ case 13: return "pentium-m";
+ case 14: return "yonah";
+ case 15: return "core2";
+ default: return "i686";
+ }
+ case 15: {
+ switch (Model) {
+ case 3:
+ case 4:
+ return (Em64T) ? "nocona" : "prescott";
+ default:
+ return (Em64T) ? "x86-64" : "pentium4";
+ }
+ }
+
+ default:
+ return "generic";
+ }
+ } else if (memcmp(text.c, "AuthenticAMD", 12) == 0) {
+ // FIXME: this poorly matches the generated SubtargetFeatureKV table. There
+ // appears to be no way to generate the wide variety of AMD-specific targets
+ // from the information returned from CPUID.
+ switch (Family) {
+ case 4:
+ return "i486";
+ case 5:
+ switch (Model) {
+ case 6:
+ case 7: return "k6";
+ case 8: return "k6-2";
+ case 9:
+ case 13: return "k6-3";
+ default: return "pentium";
+ }
+ case 6:
+ switch (Model) {
+ case 4: return "athlon-tbird";
+ case 6:
+ case 7:
+ case 8: return "athlon-mp";
+ case 10: return "athlon-xp";
+ default: return "athlon";
+ }
+ case 15:
+ switch (Model) {
+ case 5: return "athlon-fx"; // also opteron
+ default: return "athlon64";
+ }
+
+ default:
+ return "generic";
+ }
+ } else {
+ return "generic";
+ }
+}
+
X86Subtarget::X86Subtarget(const Module &M, const std::string &FS, bool is64Bit)
: AsmFlavor(AsmWriterFlavor)
, X86SSELevel(NoMMXSSE)
, TargetType(isELF) { // Default to ELF unless otherwise specified.
// Determine default and user specified characteristics
- DetectSubtargetFeatures();
+ if (!FS.empty()) {
+ // If feature string is not empty, parse features string.
+ std::string CPU = GetCurrentX86CPU();
+ ParseSubtargetFeatures(FS, CPU);
+ } else
+ // Otherwise, use CPUID to auto-detect feature set.
+ AutoDetectSubtargetFeatures();
+
if (Is64Bit && !HasX86_64) {
std::cerr << "Warning: Generation of 64-bit code for a 32-bit processor "
"requested.\n";
NoMMXSSE, MMX, SSE1, SSE2, SSE3
};
+ enum X863DNowEnum {
+ NoThreeDNow, ThreeDNow, ThreeDNowA
+ };
+
/// AsmFlavor - Which x86 asm dialect to use.
AsmWriterFlavorTy AsmFlavor;
/// X86SSELevel - MMX, SSE1, SSE2, SSE3, or none supported.
X86SSEEnum X86SSELevel;
+ /// X863DNowLevel - 3DNow or 3DNow Athlon, or none supported.
+ X863DNowEnum X863DNowLevel;
+
/// HasX86_64 - True if the processor supports X86-64 instructions.
bool HasX86_64;
/// aligned.
unsigned getMinRepStrSizeThreshold() const { return MinRepStrSizeThreshold; }
- /// DetectSubtargetFeatures - Auto-detect CPU features using CPUID instruction.
- ///
- void DetectSubtargetFeatures();
+ /// ParseSubtargetFeatures - Parses features string setting specified
+ /// subtarget options. Definition of function is auto generated by tblgen.
+ void ParseSubtargetFeatures(const std::string &FS, const std::string &CPU);
+
+ /// AutoDetectSubtargetFeatures - Auto-detect CPU features using CPUID
+ /// instruction.
+ void AutoDetectSubtargetFeatures();
bool is64Bit() const { return Is64Bit; }
bool hasSSE1() const { return X86SSELevel >= SSE1; }
bool hasSSE2() const { return X86SSELevel >= SSE2; }
bool hasSSE3() const { return X86SSELevel >= SSE3; }
+ bool has3DNow() const { return X863DNowLevel >= ThreeDNow; }
+ bool has3DNowA() const { return X863DNowLevel >= ThreeDNowA; }
bool isFlavorAtt() const { return AsmFlavor == att; }
bool isFlavorIntel() const { return AsmFlavor == intel; }