- Pentium 以降の世代の CPU なら問題なく実行できる
- VC++ (2005 以降?) なら
<intrin.h>
を#include
して、__cpuid()
および__cpuidex()
を使用する - gcc なら
<cpuid.h>
を#include
して、__get_cpuid()
,__cpuid_count()
を使用する - RDRAND を使ってみたかったのだけど、うちのは対応していなかった!
Last active
March 28, 2024 12:39
-
-
Save t-mat/3769328 to your computer and use it in GitHub Desktop.
CPUIDを使ってCPUの情報を取得する
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// CPUID example | |
// | |
// see below for details: | |
// | |
// Intel Processor Identification and the CPUID Instruction | |
// https://www.intel.com/content/www/us/en/architecture-and-technology/64-ia-32-architectures-software-developer-vol-2a-manual.html | |
// | |
// AMD : CPUID Specification | |
// http://support.amd.com/us/Embedded_TechDocs/25481.pdf | |
#include <stdio.h> | |
#include <stdint.h> | |
#include <stddef.h> | |
#if defined(_MSC_VER) | |
#include <intrin.h> | |
static void get_cpuid(void* p, int i) { | |
__cpuid((int*)p, i); | |
} | |
static void get_cpuidex(void* p, int i, int c) { | |
__cpuidex((int*)p, i, c); | |
} | |
#elif defined(__GNUC__) | |
#include <cpuid.h> | |
static void get_cpuid(void* p, int i) { | |
int* a = (int*) p; | |
__cpuid(i, a[0], a[1], a[2], a[3]); | |
} | |
static void get_cpuidex(void* p, int i, int c) { | |
int* a = (int*) p; | |
__cpuid_count(i, c, a[0], a[1], a[2], a[3]); | |
} | |
#endif | |
struct CpuInfo { | |
uint32_t eax, ebx, ecx, edx; // Do not change member order. | |
CpuInfo(int infoType) { | |
get_cpuid(&eax, infoType); | |
} | |
CpuInfo(int infoType, uint32_t ecxValue) { | |
get_cpuidex(&eax, infoType, ecxValue); | |
} | |
}; | |
static_assert(offsetof(CpuInfo, eax) == 0, "CpuInfo::eax"); | |
static_assert(offsetof(CpuInfo, ebx) == 4, "CpuInfo::ebx"); | |
static_assert(offsetof(CpuInfo, ecx) == 8, "CpuInfo::ecx"); | |
static_assert(offsetof(CpuInfo, edx) == 12, "CpuInfo::edx"); | |
int main() { | |
{ | |
char vendor[12+1] = { 0 }; | |
CpuInfo f0(0); | |
* (uint32_t*) &vendor[4*0] = f0.ebx; | |
* (uint32_t*) &vendor[4*1] = f0.edx; | |
* (uint32_t*) &vendor[4*2] = f0.ecx; | |
vendor[sizeof(vendor)-1] = 0; | |
printf("Vendor : [%s]\n", vendor); | |
} | |
{ | |
char brand[16*3+1] = { 0 }; | |
for(int i = 0; i < 3; ++i) { | |
CpuInfo e(i + 0x80000002); | |
* (uint32_t*) &brand[16*i + 4*0] = e.eax; | |
* (uint32_t*) &brand[16*i + 4*1] = e.ebx; | |
* (uint32_t*) &brand[16*i + 4*2] = e.ecx; | |
* (uint32_t*) &brand[16*i + 4*3] = e.edx; | |
}; | |
brand[sizeof(brand)-1] = 0; | |
printf("Brand String : [%s]\n", brand); | |
} | |
{ | |
CpuInfo f1(1); | |
printf("CMOV : %d\n", (f1.edx >> 15) & 1); | |
printf("SSE2 : %d\n", (f1.edx >> 26) & 1); | |
printf("SSE4.1 : %d\n", (f1.ecx >> 19) & 1); | |
printf("SSE4.2 : %d\n", (f1.ecx >> 20) & 1); | |
printf("FMA : %d\n", (f1.ecx >> 12) & 1); | |
printf("AVX : %d\n", (f1.ecx >> 28) & 1); | |
printf("RDRAND : %d\n", (f1.ecx >> 30) & 1); | |
} | |
{ | |
CpuInfo ef(7, 0); | |
printf("avx512_f : %d\n", (ef.ebx >> 16) & 1); | |
printf("avx512_dq : %d\n", (ef.ebx >> 17) & 1); | |
printf("avx512_ifma : %d\n", (ef.ebx >> 21) & 1); | |
printf("avx512_pf : %d\n", (ef.ebx >> 26) & 1); | |
printf("avx512_er : %d\n", (ef.ebx >> 27) & 1); | |
printf("avx512_cd : %d\n", (ef.ebx >> 28) & 1); | |
printf("avx512_bw : %d\n", (ef.ebx >> 30) & 1); | |
printf("avx512_vl : %d\n", (ef.ebx >> 31) & 1); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment