|  | @@ -0,0 +1,67 @@
 | 
	
		
			
				|  |  | +//+build 386, amd64
 | 
	
		
			
				|  |  | +package sys_cpu
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +_cache_line_size :: 64;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +cpuid :: proc(ax, cx: u32) -> (eax, ebc, ecx, edx: u32) {
 | 
	
		
			
				|  |  | +	return expand_to_tuple(asm(u32, u32) -> struct{eax, ebc, ecx, edx: u32} {
 | 
	
		
			
				|  |  | +		"cpuid",
 | 
	
		
			
				|  |  | +		"={ax},={bx},={cx},={dx},{ax},{cx}",
 | 
	
		
			
				|  |  | +	}(ax, cx));
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +xgetbv :: proc() -> (eax, edx: u32) {
 | 
	
		
			
				|  |  | +	return expand_to_tuple(asm(u32) -> struct{eax, edx: u32} {
 | 
	
		
			
				|  |  | +		"xgetbv",
 | 
	
		
			
				|  |  | +		"={ax},={dx},{cx}",
 | 
	
		
			
				|  |  | +	}(0));
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +_init :: proc() {
 | 
	
		
			
				|  |  | +	is_set :: proc(hwc: u32, value: u32) -> bool {
 | 
	
		
			
				|  |  | +		return hwc&value != 0;
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	initialized = true;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	max_id, _, _, _ := cpuid(0, 0);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	if max_id < 1 {
 | 
	
		
			
				|  |  | +		return;
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	_, _, ecx1, edx1 := cpuid(1, 0);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	x86.has_sse2 = is_set(26, edx1);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	x86.has_sse3      = is_set(0, ecx1);
 | 
	
		
			
				|  |  | +	x86.has_pclmulqdq = is_set(1, ecx1);
 | 
	
		
			
				|  |  | +	x86.has_ssse3     = is_set(9, ecx1);
 | 
	
		
			
				|  |  | +	x86.has_fma       = is_set(12, ecx1);
 | 
	
		
			
				|  |  | +	x86.has_sse41     = is_set(19, ecx1);
 | 
	
		
			
				|  |  | +	x86.has_sse42     = is_set(20, ecx1);
 | 
	
		
			
				|  |  | +	x86.has_popcnt    = is_set(23, ecx1);
 | 
	
		
			
				|  |  | +	x86.has_aes       = is_set(25, ecx1);
 | 
	
		
			
				|  |  | +	x86.has_os_xsave  = is_set(27, ecx1);
 | 
	
		
			
				|  |  | +	x86.has_rdrand    = is_set(30, ecx1);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	os_supports_avx := false;
 | 
	
		
			
				|  |  | +	if x86.has_os_xsave {
 | 
	
		
			
				|  |  | +		eax, _ := xgetbv();
 | 
	
		
			
				|  |  | +		os_supports_avx = is_set(1, eax) && is_set(2, eax);
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	x86.has_avx = is_set(28, ecx1) && os_supports_avx;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	if max_id < 7 {
 | 
	
		
			
				|  |  | +		return;
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	_, ebx7, _, _ := cpuid(7, 0);
 | 
	
		
			
				|  |  | +	x86.has_bmi1   = is_set(3, ebx7);
 | 
	
		
			
				|  |  | +	x86.has_avx2   = is_set(5, ebx7) && os_supports_avx;
 | 
	
		
			
				|  |  | +	x86.has_bmi2   = is_set(8, ebx7);
 | 
	
		
			
				|  |  | +	x86.has_erms   = is_set(9, ebx7);
 | 
	
		
			
				|  |  | +	x86.has_rdseed = is_set(18, ebx7);
 | 
	
		
			
				|  |  | +	x86.has_adx    = is_set(19, ebx7);
 | 
	
		
			
				|  |  | +}
 |