mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-27 13:30:05 +00:00
Add X86 feature detection support for BMI instructions. Added new cpuid function for accessing leafs with sub leafs specified in ECX. Also added code to keep track of the max cpuid level supported in both basic and extended leaves and qualified the existing cpuid calls and the new call to leaf 7.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@142089 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
566f233ba6
commit
4145c49aa0
@ -107,6 +107,74 @@ bool X86_MC::GetCpuIDAndInfo(unsigned value, unsigned *rEAX,
|
||||
return true;
|
||||
}
|
||||
|
||||
/// GetCpuIDAndInfoEx - Execute the specified cpuid with subleaf and return the
|
||||
/// 4 values in the specified arguments. If we can't run cpuid on the host,
|
||||
/// return true.
|
||||
bool X86_MC::GetCpuIDAndInfoEx(unsigned value, unsigned subleaf, unsigned *rEAX,
|
||||
unsigned *rEBX, unsigned *rECX, unsigned *rEDX) {
|
||||
#if defined(__x86_64__) || defined(_M_AMD64) || defined (_M_X64)
|
||||
#if defined(__GNUC__)
|
||||
// gcc desn't know cpuid would clobber ebx/rbx. Preseve it manually.
|
||||
asm ("movq\t%%rbx, %%rsi\n\t"
|
||||
"cpuid\n\t"
|
||||
"xchgq\t%%rbx, %%rsi\n\t"
|
||||
: "=a" (*rEAX),
|
||||
"=S" (*rEBX),
|
||||
"=c" (*rECX),
|
||||
"=d" (*rEDX)
|
||||
: "a" (value),
|
||||
"c" (subleaf));
|
||||
return false;
|
||||
#elif defined(_MSC_VER)
|
||||
// can't use __cpuidex because it isn't available in all supported versions
|
||||
// of MSC
|
||||
__asm {
|
||||
mov eax,value
|
||||
mov ecx,subleaf
|
||||
cpuid
|
||||
mov rsi,rEAX
|
||||
mov dword ptr [rsi],eax
|
||||
mov rsi,rEBX
|
||||
mov dword ptr [rsi],ebx
|
||||
mov rsi,rECX
|
||||
mov dword ptr [rsi],ecx
|
||||
mov rsi,rEDX
|
||||
mov dword ptr [rsi],edx
|
||||
}
|
||||
return false;
|
||||
#endif
|
||||
#elif defined(i386) || defined(__i386__) || defined(__x86__) || defined(_M_IX86)
|
||||
#if defined(__GNUC__)
|
||||
asm ("movl\t%%ebx, %%esi\n\t"
|
||||
"cpuid\n\t"
|
||||
"xchgl\t%%ebx, %%esi\n\t"
|
||||
: "=a" (*rEAX),
|
||||
"=S" (*rEBX),
|
||||
"=c" (*rECX),
|
||||
"=d" (*rEDX)
|
||||
: "a" (value),
|
||||
"c" (subleaf));
|
||||
return false;
|
||||
#elif defined(_MSC_VER)
|
||||
__asm {
|
||||
mov eax,value
|
||||
mov ecx,subleaf
|
||||
cpuid
|
||||
mov esi,rEAX
|
||||
mov dword ptr [esi],eax
|
||||
mov esi,rEBX
|
||||
mov dword ptr [esi],ebx
|
||||
mov esi,rECX
|
||||
mov dword ptr [esi],ecx
|
||||
mov esi,rEDX
|
||||
mov dword ptr [esi],edx
|
||||
}
|
||||
return false;
|
||||
#endif
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
void X86_MC::DetectFamilyModel(unsigned EAX, unsigned &Family,
|
||||
unsigned &Model) {
|
||||
Family = (EAX >> 8) & 0xf; // Bits 8 - 11
|
||||
|
@ -54,6 +54,11 @@ namespace X86_MC {
|
||||
/// the specified arguments. If we can't run cpuid on the host, return true.
|
||||
bool GetCpuIDAndInfo(unsigned value, unsigned *rEAX,
|
||||
unsigned *rEBX, unsigned *rECX, unsigned *rEDX);
|
||||
/// GetCpuIDAndInfoEx - Execute the specified cpuid with subleaf and return
|
||||
/// the 4 values in the specified arguments. If we can't run cpuid on the
|
||||
/// host, return true.
|
||||
bool GetCpuIDAndInfoEx(unsigned value, unsigned subleaf, unsigned *rEAX,
|
||||
unsigned *rEBX, unsigned *rECX, unsigned *rEDX);
|
||||
|
||||
void DetectFamilyModel(unsigned EAX, unsigned &Family, unsigned &Model);
|
||||
|
||||
|
@ -177,16 +177,18 @@ unsigned X86Subtarget::getSpecialAddressLatency() const {
|
||||
|
||||
void X86Subtarget::AutoDetectSubtargetFeatures() {
|
||||
unsigned EAX = 0, EBX = 0, ECX = 0, EDX = 0;
|
||||
unsigned MaxLevel;
|
||||
union {
|
||||
unsigned u[3];
|
||||
char c[12];
|
||||
} text;
|
||||
|
||||
if (X86_MC::GetCpuIDAndInfo(0, &EAX, text.u+0, text.u+2, text.u+1))
|
||||
|
||||
if (X86_MC::GetCpuIDAndInfo(0, &MaxLevel, text.u+0, text.u+2, text.u+1) ||
|
||||
MaxLevel < 1)
|
||||
return;
|
||||
|
||||
X86_MC::GetCpuIDAndInfo(0x1, &EAX, &EBX, &ECX, &EDX);
|
||||
|
||||
|
||||
if ((EDX >> 15) & 1) { HasCMov = true; ToggleFeature(X86::FeatureCMOV); }
|
||||
if ((EDX >> 23) & 1) { X86SSELevel = MMX; ToggleFeature(X86::FeatureMMX); }
|
||||
if ((EDX >> 25) & 1) { X86SSELevel = SSE1; ToggleFeature(X86::FeatureSSE1); }
|
||||
@ -245,27 +247,41 @@ void X86Subtarget::AutoDetectSubtargetFeatures() {
|
||||
ToggleFeature(X86::FeatureSlowBTMem);
|
||||
}
|
||||
// If it's Nehalem, unaligned memory access is fast.
|
||||
// FIXME: Nehalem is family 6. Also include Westmere and later processors?
|
||||
if (Family == 15 && Model == 26) {
|
||||
IsUAMemFast = true;
|
||||
ToggleFeature(X86::FeatureFastUAMem);
|
||||
}
|
||||
|
||||
X86_MC::GetCpuIDAndInfo(0x80000001, &EAX, &EBX, &ECX, &EDX);
|
||||
if ((EDX >> 29) & 0x1) {
|
||||
HasX86_64 = true;
|
||||
ToggleFeature(X86::Feature64Bit);
|
||||
unsigned MaxExtLevel;
|
||||
X86_MC::GetCpuIDAndInfo(0x80000000, &MaxExtLevel, &EBX, &ECX, &EDX);
|
||||
|
||||
if (MaxExtLevel >= 0x80000001) {
|
||||
X86_MC::GetCpuIDAndInfo(0x80000001, &EAX, &EBX, &ECX, &EDX);
|
||||
if ((EDX >> 29) & 0x1) {
|
||||
HasX86_64 = true;
|
||||
ToggleFeature(X86::Feature64Bit);
|
||||
}
|
||||
if ((ECX >> 5) & 0x1) {
|
||||
HasLZCNT = true;
|
||||
ToggleFeature(X86::FeatureLZCNT);
|
||||
}
|
||||
if (IsAMD && ((ECX >> 6) & 0x1)) {
|
||||
HasSSE4A = true;
|
||||
ToggleFeature(X86::FeatureSSE4A);
|
||||
}
|
||||
if (IsAMD && ((ECX >> 16) & 0x1)) {
|
||||
HasFMA4 = true;
|
||||
ToggleFeature(X86::FeatureFMA4);
|
||||
}
|
||||
}
|
||||
if ((ECX >> 5) & 0x1) {
|
||||
HasLZCNT = true;
|
||||
ToggleFeature(X86::FeatureLZCNT);
|
||||
}
|
||||
if (IsAMD && ((ECX >> 6) & 0x1)) {
|
||||
HasSSE4A = true;
|
||||
ToggleFeature(X86::FeatureSSE4A);
|
||||
}
|
||||
if (IsAMD && ((ECX >> 16) & 0x1)) {
|
||||
HasFMA4 = true;
|
||||
ToggleFeature(X86::FeatureFMA4);
|
||||
}
|
||||
|
||||
if (IsIntel && MaxLevel >= 7) {
|
||||
X86_MC::GetCpuIDAndInfoEx(0x7, 0x0, &EAX, &EBX, &ECX, &EDX);
|
||||
if ((EBX >> 3) & 0x1) {
|
||||
HasBMI = true;
|
||||
ToggleFeature(X86::FeatureBMI);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user