VC++6.0에서 __cpuid, __cpuidex 함수 구현
VC++6.0에서 __cpuid, __cpuidex 함수를 사용할 수 없다는 글이 있어, 작성해보았다.
인터넷은 역시나 위대하다.
내가 생각한것은 그 누군가 먼저 생각한 사람이 있다.
안된다고 생각해보기전에, 한번 더 생각해보자.
"누가 ..하더라"와 같은 "카더라"통신은 맹신하지 말자.
http://stackoverflow.com/questions/1666093/cpuid-implementations-in-c
void __cpuid(int CPUInfo[4], int InfoType)
{
__asm
{
mov esi, CPUInfo
mov eax, InfoType
xor ecx, ecx
cpuid
mov dword ptr [esi + 0], eax
mov dword ptr [esi + 4], ebx
mov dword ptr [esi + 8], ecx
mov dword ptr [esi + 12], edx
}
}
void __cpuidex(int CPUInfo[4], int InfoType, int ECXValue)
{
__asm
{
mov esi, CPUInfo
mov eax, InfoType
mov ecx, ECXValue
cpuid
mov dword ptr [esi + 0], eax
mov dword ptr [esi + 4], ebx
mov dword ptr [esi + 8], ecx
mov dword ptr [esi + 12], edx
}
}
https://msdn.microsoft.com/ko-kr/library/hskdteyh.aspx
CPU정보(사용가능한 기능 목록)을 얻는 샘플을 VC++6.0에서 동작가능하도록 작성해보았다.
#ifndef __cpuid_H
#define __cpuid_H
//myj22000@naver.com
void __cpuid(int CPUInfo[4],int InfoType);
void __cpuidex(int CPUInfo[4],int InfoType,int ECXValue);
class CPU_InstructionSet_Internal
{
public:
int bisIntel;
int bisAMD;
char vendor[0x20];
char brand[0x40];
unsigned int f_1_ECX,f_1_EDX,f_7_EBX,f_7_ECX,nExIds,f_81_ECX,f_81_EDX;
CPU_InstructionSet_Internal();
};
#ifndef get_bit
#define get_bit(a,i) ((bool)(((a)>>(i))&1))
#endif
class CPU_InstructionSet
{
public:
CPU_InstructionSet_Internal m_cpu;
char *Vendor(void){return m_cpu.vendor;}
char *Brand(void){return m_cpu.brand;}
bool SSE3(void){return get_bit(m_cpu.f_1_ECX,0);}
bool PCLMULQDQ(void){return get_bit(m_cpu.f_1_ECX,1);}
bool MONITOR(void){return get_bit(m_cpu.f_1_ECX,3);}
bool SSSE3(void){return get_bit(m_cpu.f_1_ECX,9);}
bool FMA(void){return get_bit(m_cpu.f_1_ECX,12);}
bool CMPXCHG16B(void){return get_bit(m_cpu.f_1_ECX,13);}
bool SSE41(void){return get_bit(m_cpu.f_1_ECX,19);}
bool SSE42(void){return get_bit(m_cpu.f_1_ECX,20);}
bool MOVBE(void){return get_bit(m_cpu.f_1_ECX,22);}
bool POPCNT(void){return get_bit(m_cpu.f_1_ECX,23);}
bool AES(void){return get_bit(m_cpu.f_1_ECX,25);}
bool XSAVE(void){return get_bit(m_cpu.f_1_ECX,26);}
bool OSXSAVE(void){return get_bit(m_cpu.f_1_ECX,27);}
bool AVX(void){return get_bit(m_cpu.f_1_ECX,28);}
bool F16C(void){return get_bit(m_cpu.f_1_ECX,29);}
bool RDRAND(void){return get_bit(m_cpu.f_1_ECX,30);}
bool MSR(void){return get_bit(m_cpu.f_1_EDX,5);}
bool CX8(void){return get_bit(m_cpu.f_1_EDX,8);}
bool SEP(void){return get_bit(m_cpu.f_1_EDX,11);}
bool CMOV(void){return get_bit(m_cpu.f_1_EDX,15);}
bool CLFSH(void){return get_bit(m_cpu.f_1_EDX,19);}
bool MMX(void){return get_bit(m_cpu.f_1_EDX,23);}
bool FXSR(void){return get_bit(m_cpu.f_1_EDX,24);}
bool SSE(void){return get_bit(m_cpu.f_1_EDX,25);}
bool SSE2(void){return get_bit(m_cpu.f_1_EDX,26);}
bool FSGSBASE(void){return get_bit(m_cpu.f_7_EBX,0);}
bool BMI1(void){return get_bit(m_cpu.f_7_EBX,3);}
bool HLE(void){return m_cpu.bisIntel && get_bit(m_cpu.f_7_EBX,4);}
bool AVX2(void){return get_bit(m_cpu.f_7_EBX,5);}
bool BMI2(void){return get_bit(m_cpu.f_7_EBX,8);}
bool ERMS(void){return get_bit(m_cpu.f_7_EBX,9);}
bool INVPCID(void){return get_bit(m_cpu.f_7_EBX,10);}
bool RTM(void){return m_cpu.bisIntel && get_bit(m_cpu.f_7_EBX,11);}
bool AVX512F(void){return get_bit(m_cpu.f_7_EBX,16);}
bool RDSEED(void){return get_bit(m_cpu.f_7_EBX,18);}
bool ADX(void){return get_bit(m_cpu.f_7_EBX,19);}
bool AVX512PF(void){return get_bit(m_cpu.f_7_EBX,26);}
bool AVX512ER(void){return get_bit(m_cpu.f_7_EBX,27);}
bool AVX512CD(void){return get_bit(m_cpu.f_7_EBX,28);}
bool SHA(void){return get_bit(m_cpu.f_7_EBX,29);}
bool PREFETCHWT1(void){return get_bit(m_cpu.f_7_ECX,0);}
bool LAHF(void){return get_bit(m_cpu.f_81_ECX,0);}
bool LZCNT(void){return m_cpu.bisIntel && get_bit(m_cpu.f_81_ECX,5);}
bool ABM(void){return m_cpu.bisAMD && get_bit(m_cpu.f_81_ECX,5);}
bool SSE4a(void){return m_cpu.bisAMD && get_bit(m_cpu.f_81_ECX,6);}
bool XOP(void){return m_cpu.bisAMD && get_bit(m_cpu.f_81_ECX,11);}
bool TBM(void){return m_cpu.bisAMD && get_bit(m_cpu.f_81_ECX,21);}
bool SYSCALL(void){return m_cpu.bisIntel && get_bit(m_cpu.f_81_EDX,11);}
bool MMXEXT(void){return m_cpu.bisAMD && get_bit(m_cpu.f_81_EDX,22);}
bool RDTSCP(void){return m_cpu.bisIntel && get_bit(m_cpu.f_81_EDX,27);}
bool _3DNOWEXT(void){return m_cpu.bisAMD && get_bit(m_cpu.f_81_EDX,30);}
bool _3DNOW(void){return m_cpu.bisAMD && get_bit(m_cpu.f_81_EDX,31);}
};
char *get_CPU_InstructionStr(char *buf);
#endif
#include "__cpuid.h"
//#include <stdio.h>
//#include <Windows.h>
void __cpuid(int CPUInfo[4],int InfoType)
{
__asm
{
mov esi, CPUInfo
mov eax, InfoType
xor ecx, ecx
cpuid
mov dword ptr[esi+0], eax
mov dword ptr[esi+4], ebx
mov dword ptr[esi+8], ecx
mov dword ptr[esi+12], edx
}
}
void __cpuidex(int CPUInfo[4],int InfoType,int ECXValue)
{
__asm
{
mov esi, CPUInfo
mov eax, InfoType
mov ecx, ECXValue
cpuid
mov dword ptr[esi+0], eax
mov dword ptr[esi+4], ebx
mov dword ptr[esi+8], ecx
mov dword ptr[esi+12], edx
}
}
#include "STRING.H"
CPU_InstructionSet_Internal::CPU_InstructionSet_Internal()
{
unsigned int *p;int cpui[4];int number_of_the_function_ID;
vendor[0]=0;
brand[0]=0;
// Calling __cpuid with 0x0 as the function_id argument
// gets the number of the highest valid function ID.
__cpuid(cpui,0);
number_of_the_function_ID = cpui[0];
__cpuidex(cpui,0,0);
p=(unsigned int *)vendor;
p[0]=cpui[1];
p[1]=cpui[3];//순서주의
p[2]=cpui[2];
vendor[12]=0;
bisIntel=(strcmp(vendor,"GenuineIntel")==0);
bisAMD=(strcmp(vendor,"AuthenticAMD")==0);
// load bitset with flags for function 0x00000001
if (number_of_the_function_ID >= 1)
{
__cpuidex(cpui,1,0);
f_1_ECX = cpui[2];
f_1_EDX = cpui[3];
}
// load bitset with flags for function 0x00000007
if (number_of_the_function_ID >= 7)
{
__cpuidex(cpui,7,0);
f_7_EBX = cpui[1];
f_7_ECX = cpui[2];
}
// Calling __cpuid with 0x80000000 as the function_id argument
// gets the number of the highest valid extended ID.
__cpuid(cpui,0x80000000);
nExIds=(unsigned int)cpui[0];
// load bitset with flags for function 0x80000001
if (nExIds >= 0x80000001)
{
__cpuidex(cpui,0x80000001,0);
f_81_ECX = cpui[2];
f_81_EDX = cpui[3];
}
// Interpret CPU brand string if reported
if (nExIds >= 0x80000004)
{
p=(unsigned int *)brand;
__cpuidex((int*)&(brand[0]),0x80000002,0);
__cpuidex((int*)&(brand[16]),0x80000003,0);
__cpuidex((int*)&(brand[24]),0x80000004,0);
brand[12*4]=0;
}
};
#include "stdio.h"
/*
Vendor=GenuineIntel
Brand=Intel(R) Core(TM)2 Duo C6600 @ 2.20GHz
CLFSH
CMPXCHG16B
CX8
FXSR
LAHF
MMX
MONITOR
MSR
OSXSAVE
SEP
SSE
SSE2
SSE3
SSE4.1
SSSE3
XSAVE
*/
char *get_CPU_InstructionStr(char *buf)
{
CPU_InstructionSet cpu;char *p;
p=buf;
p+=sprintf(p,"Vendor=%s\r\n",cpu.Vendor());
p+=sprintf(p,"Brand=%s\r\n\r\n",cpu.Brand());
if(cpu._3DNOW())strcat(p,"3DNOW\r\n");
if(cpu._3DNOWEXT())strcat(p,"3DNOWEXT\r\n");
if(cpu.ABM())strcat(p,"ABM\r\n");
if(cpu.ADX())strcat(p,"ADX\r\n");
if(cpu.AES())strcat(p,"AES\r\n");
if(cpu.AVX())strcat(p,"AVX\r\n");
if(cpu.AVX2())strcat(p,"AVX2\r\n");
if(cpu.AVX512CD())strcat(p,"AVX512CD\r\n");
if(cpu.AVX512ER())strcat(p,"AVX512ER\r\n");
if(cpu.AVX512F())strcat(p,"AVX512F\r\n");
if(cpu.AVX512PF())strcat(p,"AVX512PF\r\n");
if(cpu.BMI1())strcat(p,"BMI1\r\n");
if(cpu.BMI2())strcat(p,"BMI2\r\n");
if(cpu.CLFSH())strcat(p,"CLFSH\r\n");
if(cpu.CMPXCHG16B())strcat(p,"CMPXCHG16B\r\n");
if(cpu.CX8())strcat(p,"CX8\r\n");
if(cpu.ERMS())strcat(p,"ERMS\r\n");
if(cpu.F16C())strcat(p,"F16C\r\n");
if(cpu.FMA())strcat(p,"FMA\r\n");
if(cpu.FSGSBASE())strcat(p,"FSGSBASE\r\n");
if(cpu.FXSR())strcat(p,"FXSR\r\n");
if(cpu.HLE())strcat(p,"HLE\r\n");
if(cpu.INVPCID())strcat(p,"INVPCID\r\n");
if(cpu.LAHF())strcat(p,"LAHF\r\n");
if(cpu.LZCNT())strcat(p,"LZCNT\r\n");
if(cpu.MMX())strcat(p,"MMX\r\n");
if(cpu.MMXEXT())strcat(p,"MMXEXT\r\n");
if(cpu.MONITOR())strcat(p,"MONITOR\r\n");
if(cpu.MOVBE())strcat(p,"MOVBE\r\n");
if(cpu.MSR())strcat(p,"MSR\r\n");
if(cpu.OSXSAVE())strcat(p,"OSXSAVE\r\n");
if(cpu.PCLMULQDQ())strcat(p,"PCLMULQDQ\r\n");
if(cpu.POPCNT())strcat(p,"POPCNT\r\n");
if(cpu.PREFETCHWT1())strcat(p,"PREFETCHWT1\r\n");
if(cpu.RDRAND())strcat(p,"RDRAND\r\n");
if(cpu.RDSEED())strcat(p,"RDSEED\r\n");
if(cpu.RDTSCP())strcat(p,"RDTSCP\r\n");
if(cpu.RTM())strcat(p,"RTM\r\n");
if(cpu.SEP())strcat(p,"SEP\r\n");
if(cpu.SHA())strcat(p,"SHA\r\n");
if(cpu.SSE())strcat(p,"SSE\r\n");
if(cpu.SSE2())strcat(p,"SSE2\r\n");
if(cpu.SSE3())strcat(p,"SSE3\r\n");
if(cpu.SSE41())strcat(p,"SSE4.1\r\n");
if(cpu.SSE42())strcat(p,"SSE4.2\r\n");
if(cpu.SSE4a())strcat(p,"SSE4a\r\n");
if(cpu.SSSE3())strcat(p,"SSSE3\r\n");
if(cpu.SYSCALL())strcat(p,"SYSCALL\r\n");
if(cpu.TBM())strcat(p,"TBM\r\n");
if(cpu.XOP())strcat(p,"XOP\r\n");
if(cpu.XSAVE())strcat(p,"XSAVE\r\n");
//printf(buf);
return buf;
}