CPUの物理CPU数・ソケット数等を取得(32/64bit)・他のプログラムで他のCPUをエミュレーションする方法

icon 項目のみ表示/展開表示の切り替え

他のプログラムで他のCPUをエミュレーションする方法

例えば、CPUがサポートしているSIMD(MMX,SSE,SSE2,SSE3,SSE3,AVX,AVX2)とWindowsのサポート状況を表示(32/64bit) は起動したシステムのCPUIDに基づき動作しているが、他のCPUに置き換える場合は、元のソースコードに赤字の行を追加する。
コンパイル時には、エミュレーション用のヘッダーファイルAtom_D2701_2130MHz_emu.hとcpu.h cpu.cppをプロジェクトに加える必要がある。
//      SIMD拡張命令のサポート状況を表示
//      Visual C++ 2008,2013

#include <windows.h>
#include <tchar.h>
#include <intrin.h>

#if 1800 <= _MSC_VER //      Visual C++ 2013以上 
        #include <VersionHelpers.h>
#else
#ifndef _WIN32_WINNT_WIN7
        #define _WIN32_WINNT_WIN7 0x0601
#endif
inline bool IsWindowsVersionOrGreater(WORD wMajorVersion, WORD wMinorVersion, WORD wServicePackMajor){
        OSVERSIONINFOEXW osvi = { sizeof(osvi), 0, 0, 0, 0, { 0 }, 0, 0 };
        DWORDLONG        const dwlConditionMask = VerSetConditionMask(
                VerSetConditionMask(
                VerSetConditionMask(
                0, VER_MAJORVERSION, VER_GREATER_EQUAL),
                VER_MINORVERSION, VER_GREATER_EQUAL),
                VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL);

        osvi.dwMajorVersion = wMajorVersion;
        osvi.dwMinorVersion = wMinorVersion;
        osvi.wServicePackMajor = wServicePackMajor;

        return VerifyVersionInfoW(&osvi, VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR, dwlConditionMask) != FALSE;
}

inline bool IsWindows7SP1OrGreater(void){
        return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WIN7), LOBYTE(_WIN32_WINNT_WIN7), 1);
}

#endif

#include "cpu.h"
#include "Atom_D2701_2130MHz_emu.h"

CPU_EMU_CLASS cpu_emu;

#define __cpuid(info,eax)  cpu.cpuid( (info), (eax) )
#define __cpuidex(info,eax,ecx)  cpu.cpuid( (info), (eax),(ecx) )
#define SetThreadAffinityMask(h,m) cpu.emuSetThreadAffinityMask((h),(m))
#define GetSystemInfo(s) cpu.emuGetSystemInfo((s))


//      CPUID 1 ECX
#define AVX_READY (1<<28)
#define SSE42_READY (1<<20)
#define SSE41_READY (1<<19)
#define SSSE3_READY (1<<9)
#define SSE3_READY (1)

//      CPUID 1 EDX
#define IA64_READY (1<<30)
#define HTT_READY (1<<8)
#define SSE2_READY (1<<26)
#define SSE_READY (1<<25)
#define MMX_READY (1<<23)
#define FPU_READY (1)

//      CPUID 1 EBX
#define AVX2_READY (1<<5)


inline int _MSC_CVER(void) {
        int cver = 0;
#if _MSC_VER==1400
cver = 2005;
#endif
#if _MSC_VER==1500
cver = 2008;
#endif
#if _MSC_VER==1600
cver = 2010;
#endif
#if _MSC_VER==1700
cver = 2012;
#endif
#if _MSC_VER==1800
cver = 2013;
#endif
return cver;
}




int WINAPI WinMain(HINSTANCE hCurInst, HINSTANCE hPrevInst, LPSTR lpsCmdLine, int nCmdShow){

        CPU cpu(1);
        cpu.add(0,&cpu_emu);
        cpu.init();
        cpu.parse();

        TCHAR cpuname[4*4*4];
        TCHAR inst[256];
        TCHAR buf[256];
        int cver = 0;
        TCHAR* project;
        TCHAR* win;
        TCHAR* dll;
#ifdef _DEBUG
        project = _TEXT("Debug");
#else
        project = _TEXT("Release");
#endif

#ifdef _WIN64
        win=_TEXT("x64");
#else
        win = _TEXT("Win32");
#endif

#ifdef _DLL
        dll = _TEXT("マルチスレッドDLL");
#else
        dll = _TEXT("マルチスレッド");
#endif

        cver=_MSC_CVER();
        _stprintf_s(buf, sizeof(buf) / sizeof(TCHAR), _TEXT("ビルド Visual C++ %i %s %s %s\r\n"), cver,project,win,dll);

        inst[0] = 0;
        cpuname[0] = 0;

        int CPUInfo[4];
        __cpuid(CPUInfo, 0x80000000);
        if (0x80000002 <= CPUInfo[0]){       //      プロセッサブランド文字列の取得が可能である
                int CPUInfoV[3][4];
                __cpuid(CPUInfoV[0], 0x80000002);
                __cpuid(CPUInfoV[1], 0x80000003);
                __cpuid(CPUInfoV[2], 0x80000004);
                char* p = (char*)CPUInfoV;
                for (int n = 0; n < 4*4*3; n++){
                        cpuname[n] = *p++;
                }
                _tcscat_s(buf, sizeof(buf) / sizeof(TCHAR), cpuname);
                _tcscat_s(buf, sizeof(buf) / sizeof(TCHAR), _TEXT("\r\n"));
        }
        __cpuid(CPUInfo, 1);
        if (CPUInfo[3] & MMX_READY){
                _tcscat_s(inst,sizeof(inst)/sizeof(TCHAR),_TEXT("MMX "));
        }
        if (CPUInfo[3] & SSE_READY){
                _tcscat_s(inst, sizeof(inst) / sizeof(TCHAR), _TEXT("SSE "));
        }
        if (CPUInfo[3] & SSE2_READY){
                _tcscat_s(inst, sizeof(inst) / sizeof(TCHAR), _TEXT("SSE2 "));
        }
        if (CPUInfo[2] & SSE3_READY){
                _tcscat_s(inst, sizeof(inst) / sizeof(TCHAR), _TEXT("SSE3 "));
        }
        if (CPUInfo[2] & SSSE3_READY){
                _tcscat_s(inst, sizeof(inst) / sizeof(TCHAR), _TEXT("SSSE3 "));
        }
        if (CPUInfo[2] & SSE41_READY){
                _tcscat_s(inst, sizeof(inst) / sizeof(TCHAR), _TEXT("SSE4.1 "));
        }
        if (CPUInfo[2] & SSE42_READY){
                _tcscat_s(inst, sizeof(inst) / sizeof(TCHAR), _TEXT("SSE4.2 "));
        }
        if (CPUInfo[2] & AVX_READY){
                _tcscat_s(inst, sizeof(inst) / sizeof(TCHAR), _TEXT("AVX "));
        }
        __cpuid(CPUInfo, 1);
        if (CPUInfo[1] & AVX2_READY){
                _tcscat_s(inst, sizeof(inst) / sizeof(TCHAR), _TEXT("AVX2 "));
        }

        if (inst[0]){
                _tcscat_s(buf, sizeof(buf) / sizeof(TCHAR), _TEXT("CPUサポート "));
                _tcscat_s(buf, sizeof(buf) / sizeof(TCHAR), inst);
                _tcscat_s(buf, sizeof(buf) / sizeof(TCHAR), _TEXT("\r\n"));
        }
        if (IsWindows7SP1OrGreater()){
                _tcscat_s(buf, sizeof(buf) / sizeof(TCHAR), _TEXT("OS AVX Suport"));
        }
        else{
                _tcscat_s(buf, sizeof(buf) / sizeof(TCHAR), _TEXT("OS AVX Not Suport"));
        }
        MessageBox(0, buf, _TEXT("システムのSIMD命令のサポート状況"), MB_OK);
        return (int)0;
}
Pentium4 上で実行しているにもかかわらずAtomに変身している。