Page 1 of 1

CPUID - Check what instructions are supported by your CPU

Posted: 12 May 2022, 18:54
by iseahound
image.png
image.png (93.91 KiB) Viewed 666 times
Sample code

Code: Select all

if (cpuid().ECX[28] == True)
    MsgBox % "Advanced Vector Extensions are supported"

if (cpuid().edx[26] == True)
    MsgBox % "SSE2 instructions are supported"
AutoHotkey v1

Code: Select all

      CPUID() {
         static cpuid := 0

         if not cpuid {
            ; C source code - https://godbolt.org/z/1YPd6jz61
            code := (A_PtrSize == 4)
               ? "VYnlV4t9EFaLdQhTiw+LBg+iiQaLRQyJGItFFIkPiRBbXl9dww=="
               : "U4sBSYnKSYnTQYsID6JBiQJBiRtBiQhBiRFbww=="
            size := StrLen(RTrim(code, "=")) * 3 // 4
            bin := DllCall("GlobalAlloc", "uint", 0, "uptr", size, "ptr")
            DllCall("VirtualProtect", "ptr", bin, "ptr", size, "uint", 0x40, "uint*", old:=0)
            DllCall("crypt32\CryptStringToBinary", "str", code, "uint", 0, "uint", 0x1, "ptr", bin, "uint*", size, "ptr", 0, "ptr", 0)

            ; Set eax flag to 1 to retrieve supported CPU features.
            ; See this for CPU features: https://wiki.osdev.org/CPUID
            ; Also see: Appendix D.2 - CPUID Feature Flags Related to Instruction Support
            ; On page 1861 - https://www.amd.com/content/dam/amd/en/documents/processor-tech-docs/programmer-references/40332.pdf
            DllCall(bin, "uint*", a := 1, "uint*", b := 0, "uint*", c := 0, "uint*", d := 0)

            ; Free memory.
            DllCall("GlobalFree", "ptr", bin)

            ; To check for SSE2 use the following code example:
            ; if cpuid().edx[26] == True
            eax := {0: a & 1}
            ebx := {0: b & 1}
            ecx := {0: c & 1}
            edx := {0: d & 1}
            loop 31 {
               eax[A_Index] := !!(1 << A_Index & a)
               ebx[A_Index] := !!(1 << A_Index & b)
               ecx[A_Index] := !!(1 << A_Index & c)
               edx[A_Index] := !!(1 << A_Index & d)
            }
            cpuid := {eax: eax, ebx: ebx, ecx: ecx, edx: edx}
         }

         return cpuid
      }
AutoHotkey v2 compatible

Code: Select all

      CPUID() {
         static cpuid := 0

         if not cpuid {
            ; C source code - https://godbolt.org/z/1YPd6jz61
            code := (A_PtrSize == 4)
               ? "VYnlV4t9EFaLdQhTiw+LBg+iiQaLRQyJGItFFIkPiRBbXl9dww=="
               : "U4sBSYnKSYnTQYsID6JBiQJBiRtBiQhBiRFbww=="
            size := StrLen(RTrim(code, "=")) * 3 // 4
            bin := DllCall("GlobalAlloc", "uint", 0, "uptr", size, "ptr")
            DllCall("VirtualProtect", "ptr", bin, "ptr", size, "uint", 0x40, "uint*", &old:=0)
            DllCall("crypt32\CryptStringToBinary", "str", code, "uint", 0, "uint", 0x1, "ptr", bin, "uint*", size, "ptr", 0, "ptr", 0)

            ; Set eax flag to 1 to retrieve supported CPU features.
            ; See this for CPU features: https://wiki.osdev.org/CPUID
            ; Also see: Appendix D.2 - CPUID Feature Flags Related to Instruction Support
            ; On page 1861 - https://www.amd.com/content/dam/amd/en/documents/processor-tech-docs/programmer-references/40332.pdf
            DllCall(bin, "uint*", &a := 1, "uint*", &b := 0, "uint*", &c := 0, "uint*", &d := 0)

            ; Free memory.
            DllCall("GlobalFree", "ptr", bin)

            ; To check for SSE2 use the following code example:
            ; if cpuid().edx[26] == True
            eax := Map(0, a & 1)
            ebx := Map(0, b & 1)
            ecx := Map(0, c & 1)
            edx := Map(0, d & 1)
            loop 31 {
               eax[A_Index] := !!(1 << A_Index & a)
               ebx[A_Index] := !!(1 << A_Index & b)
               ecx[A_Index] := !!(1 << A_Index & c)
               edx[A_Index] := !!(1 << A_Index & d)
            }
            cpuid := {eax: eax, ebx: ebx, ecx: ecx, edx: edx}
         }

         return cpuid
      }

I'm not sure what this would be useful for...

Re: CPUID - Check what instructions are supported by your CPU

Posted: 15 Sep 2023, 10:03
by iseahound
It's come to my attention that gcc has builtin methods of doing this properly. The problem with CPUID is that it only returns whether the processor supports the instruction set (and it's not obvious how to text for AVX512), and not whether the OS supports the instruction set.

https://godbolt.org/z/5167jsE17

not that the built-in gcc functions work in AutoHotkey hmm....