cpu_x86.odin 1.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667
  1. //+build 386, amd64
  2. package sys_cpu
  3. _cache_line_size :: 64;
  4. cpuid :: proc(ax, cx: u32) -> (eax, ebc, ecx, edx: u32) {
  5. return expand_to_tuple(asm(u32, u32) -> struct{eax, ebc, ecx, edx: u32} {
  6. "cpuid",
  7. "={ax},={bx},={cx},={dx},{ax},{cx}",
  8. }(ax, cx));
  9. }
  10. xgetbv :: proc() -> (eax, edx: u32) {
  11. return expand_to_tuple(asm(u32) -> struct{eax, edx: u32} {
  12. "xgetbv",
  13. "={ax},={dx},{cx}",
  14. }(0));
  15. }
  16. _init :: proc() {
  17. is_set :: proc(hwc: u32, value: u32) -> bool {
  18. return hwc&value != 0;
  19. }
  20. initialized = true;
  21. max_id, _, _, _ := cpuid(0, 0);
  22. if max_id < 1 {
  23. return;
  24. }
  25. _, _, ecx1, edx1 := cpuid(1, 0);
  26. x86.has_sse2 = is_set(26, edx1);
  27. x86.has_sse3 = is_set(0, ecx1);
  28. x86.has_pclmulqdq = is_set(1, ecx1);
  29. x86.has_ssse3 = is_set(9, ecx1);
  30. x86.has_fma = is_set(12, ecx1);
  31. x86.has_sse41 = is_set(19, ecx1);
  32. x86.has_sse42 = is_set(20, ecx1);
  33. x86.has_popcnt = is_set(23, ecx1);
  34. x86.has_aes = is_set(25, ecx1);
  35. x86.has_os_xsave = is_set(27, ecx1);
  36. x86.has_rdrand = is_set(30, ecx1);
  37. os_supports_avx := false;
  38. if x86.has_os_xsave {
  39. eax, _ := xgetbv();
  40. os_supports_avx = is_set(1, eax) && is_set(2, eax);
  41. }
  42. x86.has_avx = is_set(28, ecx1) && os_supports_avx;
  43. if max_id < 7 {
  44. return;
  45. }
  46. _, ebx7, _, _ := cpuid(7, 0);
  47. x86.has_bmi1 = is_set(3, ebx7);
  48. x86.has_avx2 = is_set(5, ebx7) && os_supports_avx;
  49. x86.has_bmi2 = is_set(8, ebx7);
  50. x86.has_erms = is_set(9, ebx7);
  51. x86.has_rdseed = is_set(18, ebx7);
  52. x86.has_adx = is_set(19, ebx7);
  53. }