hare

[hare] The Hare programming language
git clone https://git.torresjrjr.com/hare.git
Log | Files | Refs | README | LICENSE

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 };