Skip to content

Instantly share code, notes, and snippets.

@alphaKAI
Created August 14, 2019 19:38
Show Gist options
  • Save alphaKAI/bc482de585c3728b84773fc95f405992 to your computer and use it in GitHub Desktop.
Save alphaKAI/bc482de585c3728b84773fc95f405992 to your computer and use it in GitHub Desktop.
manipulate CPUID instruction
import std.stdio;
import std.conv;
import std.string;
struct Regs {
uint a, b, c, d;
}
Regs cpuid(uint eax) {
Regs r;
asm {
mov EAX, eax;
cpuid;
mov r, EAX;
mov r + 4, EBX;
mov r + 8, ECX;
mov r + 12, EDX;
}
return r;
}
string getVenderID() {
auto r = cpuid(0);
char[12] buf = 0;
foreach (i, v; [r.b, r.d, r.c]) {
foreach (j; 0 .. 4) {
buf[i * 4 + j] = (v >> (j * 8)) & 0xFF;
}
}
return buf.to!string;
}
string getCPUName() {
char[48] buf;
foreach (t, eax; [0x80000002, 0x80000003, 0x80000004]) {
auto r = cpuid(eax);
foreach (i, v; [r.a, r.b, r.c, r.d]) {
foreach (j; 0 .. 4) {
char c = (v >> (j * 8)) & 0xFF;
buf[t * 16 + i * 4 + j] = c;
}
}
}
return (cast(char*)&buf).fromStringz.to!string;
}
struct TypeModelFamily {
ubyte stepping;
ubyte model;
ubyte family;
ubyte type;
}
struct AdditionalInfo {
ubyte brand_index;
ubyte CLFLUSH_line_size;
ubyte max_logical_cpus;
ubyte local_apic_id;
}
struct FeatureInfo {
bool fpu, vme, de, pse, tsc, msr, pae, mce, cx8, apic, sep, mttr, pge, mca,
cmov, pat, pse_36, psn, clfsh, ds, acpi, mmx, fxsr, sse, sse2, ss, htt, tm, ia64, pbe;
bool sse3, pclmulqdq, dtes64, monitor, ds_cpl, vmx, smx, est, tm2, ssse3,
cnxt_id, sdbg, fma, cx16, xtpr, pdcm, pcid, dca, sse4_1, sse4_2, x2apic,
movbe, popcnt, tsc_deadline, aes, xsave, osxsave, avx, f16c, rdrnd, hypervisor;
}
struct CPUInfo {
TypeModelFamily tmf;
AdditionalInfo add_info;
FeatureInfo feature_info;
}
CPUInfo getCPUInfo() {
auto r = cpuid(1);
ubyte stepping = (r.a) & 0b1111;
ubyte model = (r.a >> 4) & 0b1111;
ubyte family = (r.a >> 8) & 0b1111;
ubyte type = (r.a >> 12) & 0b11;
ubyte emodel = (r.a >> 16) & 0b1111;
ubyte efamily = cast(byte)((r.a >> 20) & 0xFF);
/*
writefln("stepping : %d(%b)", stepping, stepping);
writefln("model : %d(%b)", model, model);
writefln("family : %d(%b)", family, family);
writefln("type : %d(%b)", type, type);
writefln("emodel : %d(%b)", emodel, emodel);
writefln("efamily : %d(%b)", efamily, efamily);
writeln("actual...:");
*/
ubyte amodel = (family == 6 || family == 15) ? cast(ubyte)(emodel << 4 | model) : model;
//writefln("amodel : %d(%x)", amodel, amodel);
ubyte afamily = family == 15 ? cast(ubyte)(efamily + family) : family;
//writefln("family : %d(%x)", afamily, afamily);
auto tmf = TypeModelFamily(stepping, amodel, afamily, type);
ubyte brand_index = r.b & 0xFF;
ubyte CLFLUSH_line_size = (r.b >> 8) & 0xFF;
ubyte max_logical_cpus = (r.b >> 16) & 0xFF;
ubyte local_apic_id = (r.b >> 24) & 0xFF;
auto add_info = AdditionalInfo(brand_index, CLFLUSH_line_size, max_logical_cpus, local_apic_id);
bool fpu = r.d & 1;
bool vme = (r.d >> 1) & 1;
bool de = (r.d >> 2) & 1;
bool pse = (r.d >> 3) & 1;
bool tsc = (r.d >> 4) & 1;
bool msr = (r.d >> 5) & 1;
bool pae = (r.d >> 6) & 1;
bool mce = (r.d >> 7) & 1;
bool cx8 = (r.d >> 8) & 1;
bool apic = (r.d >> 9) & 1;
bool sep = (r.d >> 11) & 1;
bool mttr = (r.d >> 12) & 1;
bool pge = (r.d >> 13) & 1;
bool mca = (r.d >> 14) & 1;
bool cmov = (r.d >> 15) & 1;
bool pat = (r.d >> 16) & 1;
bool pse_36 = (r.d >> 17) & 1;
bool psn = (r.d >> 18) & 1;
bool clfsh = (r.d >> 19) & 1;
bool ds = (r.d >> 21) & 1;
bool acpi = (r.d >> 22) & 1;
bool mmx = (r.d >> 23) & 1;
bool fxsr = (r.d >> 24) & 1;
bool sse = (r.d >> 25) & 1;
bool sse2 = (r.d >> 26) & 1;
bool ss = (r.d >> 27) & 1;
bool htt = (r.d >> 28) & 1;
bool tm = (r.d >> 29) & 1;
bool ia64 = (r.d >> 30) & 1;
bool pbe = (r.d >> 31) & 1;
bool sse3 = r.c & 1, pclmulqdq = (r.c >> 1) & 1, dtes64 = (r.c >> 2) & 1,
monitor = (r.c >> 3) & 1, ds_cpl = (r.c >> 4) & 1, vmx = (r.c >> 5) & 1,
smx = (r.c >> 6) & 1, est = (r.c >> 7) & 1, tm2 = (r.c >> 8) & 1,
ssse3 = (r.c >> 9) & 1, cnxt_id = (r.c >> 10) & 1, sdbg = (r.c >> 11) & 1,
fma = (r.c >> 12) & 1, cx16 = (r.c >> 13) & 1, xtpr = (r.c >> 14) & 1,
pdcm = (r.c >> 15) & 1, pcid = (r.c >> 17) & 1, dca = (r.c >> 18) & 1,
sse4_1 = (r.c >> 19) & 1, sse4_2 = (r.c >> 20) & 1, x2apic = (r.c >> 21) & 1,
movbe = (r.c >> 22) & 1, popcnt = (r.c >> 23) & 1,
tsc_deadline = (r.c >> 24) & 1, aes = (r.c >> 25) & 1, xsave = (r.c >> 26) & 1,
osxsave = (r.c >> 27) & 1, avx = (r.c >> 28) & 1, f16c = (r.c >> 29) & 1,
rdrnd = (r.c >> 30) & 1, hypervisor = (r.c >> 31) & 1;
auto feature_info = FeatureInfo(fpu, vme, de, pse, tsc, msr, pae, mce, cx8,
apic, sep, mttr, pge, mca, cmov, pat, pse_36, psn, clfsh, ds, acpi,
mmx, fxsr, sse, sse2, ss, htt, tm, ia64, pbe, sse3, pclmulqdq, dtes64,
monitor, ds_cpl, vmx, smx, est, tm2, ssse3, cnxt_id, sdbg, fma, cx16,
xtpr, pdcm, pcid, dca, sse4_1, sse4_2, x2apic, movbe, popcnt,
tsc_deadline, aes, xsave, osxsave, avx, f16c, rdrnd, hypervisor);
return CPUInfo(tmf, add_info, feature_info);
}
void printCPUInfo(const ref CPUInfo info) {
with (info) {
with (tmf) {
writefln("stepping : %d(%b)", stepping, stepping);
writefln("model : %d(%b)", model, model);
writefln("family : %d(%b)", family, family);
writefln("type : %d(%b)", type, type);
}
with (add_info) {
writefln("brand_index : %d(%b)", brand_index, brand_index);
writefln("CLFLUSH_line_size : %d(%b)", CLFLUSH_line_size, CLFLUSH_line_size);
writefln("max_logical_cpus : %d(%b)", max_logical_cpus, max_logical_cpus);
writefln("local_apic_id : %d(%b)", local_apic_id, local_apic_id);
}
with (feature_info) {
writeln("Onboard x87 FPU : ", fpu);
writeln("Virtual 8086 mode extensions : ", vme);
writeln("Debugging extensions : ", de);
writeln("Page Size Extension : ", pse);
writeln("Time Stamp Counter : ", tsc);
writeln("Model-specific registers : ", msr);
writeln("Pysical Address Extension : ", pae);
writeln("Machine Check Exception : ", mce);
writeln("CMPXCHG8 (compare-and-swap) instruction : ", cx8);
writeln("Onboard Advanced Programmable Interrupt Controller : ", apic);
writeln("SYSENTER and SYSEXIT instructions : ", sep);
writeln("Memory Type Range Registers : ", mttr);
writeln("Page Global Enable bit in CR4 : ", pge);
writeln("Machine check architecture : ", mca);
writeln("Conditional move and FCMOV instructions : ", cmov);
writeln("Page Attribute Table : ", pat);
writeln("36-bit page size extension : ", pse_36);
writeln("Processor Serial Number : ", psn);
writeln("CLFLUSH instruction (SSE2) : ", clfsh);
writeln("Debug store: save trace of executed jumps : ", ds);
writeln("Onboard thermal control MSRs for ACPI : ", acpi);
writeln("MMX instructions : ", mmx);
writeln("FXSAVE, FXRESTOR instructions, CR4 bit 9 : ", fxsr);
writeln("SSE instructions : ", sse);
writeln("SSE2 instructions : ", sse2);
writeln("CPU cache implements self-snoop : ", ss);
writeln("Hyper-threading : ", htt);
writeln("Thermal monitor automatically limits temperature : ", tm);
writeln("IA64 processor emulating x86 : ", ia64);
writeln("Pending Break Enable (PBE# pin) wakeup capability : ", pbe);
writeln("Prescott New Instructions-SSE3 (PNI) : ", sse3);
writeln("PCLMULQDQ : ", pclmulqdq);
writeln("64-bit debug store (edx bit 21) : ", dtes64);
writeln("MONITOR and MWAIT instructions (SSE3) : ", monitor);
writeln("CPL qualified debug store : ", ds_cpl);
writeln("Virtual Machine eXtensions : ", vmx);
writeln("Safer Mode Extensions (LaGrande) : ", smx);
writeln("Enhanced SpeedStep : ", est);
writeln("Thermal Monitor 2 : ", tm2);
writeln("Supplemental SSE3 instructions : ", ssse3);
writeln("L1 Context ID : ", cnxt_id);
writeln("Silicon Debug interface : ", sdbg);
writeln("Fused multiply-add (FMA3) : ", fma);
writeln("CMPXCHG16B instruction : ", cx16);
writeln("Can disable sending task priority messages : ", xtpr);
writeln("Perfmon & debug capability : ", pdcm);
writeln("pcid Process context identifiers (CR4 bit 17) : ", pcid);
writeln("Direct cache access for DMA writes : ", dca);
writeln("SSE4.1 instructions : ", sse4_1);
writeln("SSE4.2 instructions : ", sse4_2);
writeln("x2APIC : ", x2apic);
writeln("MOVBE instruction (big-endian) : ", movbe);
writeln("POPCNT instruction : ", popcnt);
writeln("APIC implements one-shot operation using a TSC deadline value : ", tsc_deadline);
writeln("AES instruction set : ", aes);
writeln("XSAVE, XRESTOR, XSETBV, XGETBV : ", xsave);
writeln("XSAVE enabled by OS : ", osxsave);
writeln("Advanced Vector Extensions : ", avx);
writeln("F16C (half-precision) FP feature : ", f16c);
writeln("RDRAND (on-chip random number generator) feature : ", rdrnd);
writeln("Hypervisor present (always zero on physical CPUs) : ", hypervisor);
}
}
}
void main() {
writeln("VenderID : ", getVenderID);
writeln("CPU Name : ", getCPUName);
auto cpu_info = getCPUInfo;
cpu_info.printCPUInfo;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment