cpuid.ha (2427B)
1 // SPDX-License-Identifier: MPL-2.0 2 // (c) Hare authors <https://harelang.org> 3 4 export type cpuid_vendor = enum { 5 AMD, 6 INTEL, 7 WINCHIP, 8 TRANSMETA, 9 CYRIX, 10 CENTAUR, 11 NEXGEN, 12 UMC, 13 SIS, 14 NSC, 15 RISE, 16 VORTEX, 17 VIA, 18 ZHAOXIN, 19 HYGON, 20 MCST_ELBRUS, 21 22 // Virtual Machines. 23 VMWARE, 24 XENHVM, 25 MICROSOFT_HV, 26 PARALLELS, 27 }; 28 29 export type cpuid_unknownvendor = !void; 30 31 // cpuid vendor list taken from https://wiki.osdev.org/CPUID and 32 // https://en.wikipedia.org/wiki/CPUID 33 // Order and len matches the entries in the cpuid_vendor enum. 34 const vendors: [_]str = [ 35 "AuthenticAMD", 36 "GenuineIntel", 37 "CentaurHauls", 38 "GenuineTMx86", 39 "CyrixInstead", 40 "CentaurHauls", 41 "NexGenDriven", 42 "UMC UMC UMC ", 43 "SiS SiS SiS ", 44 "Geode by NSC", 45 "RiseRiseRise", 46 "Vortex86 SoC", 47 "VIA VIA VIA ", 48 " Shanghai ", 49 "HygonGenuine", 50 "E2K MACHINE", 51 "VMwareVMware", 52 "XenVMMXenVMM", 53 "Microsoft Hv", 54 " lrpepyh vr", 55 ]; 56 57 def VENDOR_OLDAMD: str = "AMDisbetter!"; 58 def VENDOR_OLDTRANSMETA: str = "TransmetaCPU"; 59 60 export type cpuid_edxflag = enum uint { 61 SSE = 1 << 25, 62 SSE2 = 1 << 26, 63 }; 64 65 export type cpuid_ecxflag = enum uint { 66 SSE3 = 1 << 0, 67 AES = 1 << 25, 68 AVX = 1 << 28, 69 }; 70 71 fn cpuid_getvendorstr(v: *[12]u8) void; 72 73 fn cpuid_getfeatureflags(flags: *[2]u32) void; 74 75 // Figures out cpu vendor using cpuid 76 export fn cpuid_getvendor() (cpuid_vendor | cpuid_unknownvendor) = { 77 let vstr: [12]u8 = [0...]; 78 cpuid_getvendorstr(&vstr); 79 80 for (let i = 0z; i < len(vendors); i += 1) { 81 if (bytes_equal(vstr, strings_toutf8(vendors[i]))) { 82 return i: cpuid_vendor; 83 }; 84 }; 85 86 // some vendors changed their strings in between cpu revisions 87 if (bytes_equal(vstr, strings_toutf8(VENDOR_OLDAMD))) { 88 return cpuid_vendor::AMD; 89 }; 90 91 if (bytes_equal(vstr, strings_toutf8(VENDOR_OLDTRANSMETA))) { 92 return cpuid_vendor::TRANSMETA; 93 }; 94 95 return cpuid_unknownvendor; 96 }; 97 98 // Checks if cpu has given features. See [[cpuid_edxflag]] and 99 // [[cpuid_ecxflag]] for available options. 100 export fn cpuid_hasflags(edx: u32, ecx: u32) bool = { 101 let flags: [2]u32 = [0...]; 102 cpuid_getfeatureflags(&flags); 103 104 return flags[0] & edx == edx && flags[1] & ecx == ecx; 105 }; 106 107 // we can't use strings in rt so we add a helper here 108 fn strings_toutf8(s: str) []u8 = { 109 return *(&s: *[]u8); 110 }; 111 112 fn bytes_equal(a: []u8, b: []u8) bool = { 113 if (len(a) != len(b)) { 114 return false; 115 }; 116 117 for (let i = 0z; i < len(a); i += 1) { 118 if (a[i] != b[i]) { 119 return false; 120 }; 121 }; 122 return true; 123 };