카테고리 없음

VC++6.0에서 __cpuid, __cpuidex 함수 구현

안녕1999 2016. 5. 3. 23:30

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;

}



cpu.zip