mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-06 23:58:50 +00:00
sys/info: add feature detection for Darwin and Linux ARM
This commit is contained in:
+43
-14
@@ -1,26 +1,55 @@
|
|||||||
//+build arm32, arm64
|
//+build arm32, arm64
|
||||||
package sysinfo
|
package sysinfo
|
||||||
|
|
||||||
// TODO: Set up an enum with the ARM equivalent of the above.
|
CPU_Feature :: enum u64 {
|
||||||
CPU_Feature :: enum u64 {}
|
// Advanced SIMD & floating-point capabilities:
|
||||||
|
asimd, // General support for Advanced SIMD instructions/neon.
|
||||||
|
floatingpoint, // General support for floating-point instructions.
|
||||||
|
asimdhp, // Advanced SIMD half-precision conversion instructions.
|
||||||
|
bf16, // Storage and arithmetic instructions of the Brain Floating Point (BFloat16) data type.
|
||||||
|
fcma, // Floating-point complex number instructions.
|
||||||
|
fhm, // Floating-point half-precision multiplication instructions.
|
||||||
|
fp16, // General half-precision floating-point data processing instructions.
|
||||||
|
frint, // Floating-point to integral valued floating-point number rounding instructions.
|
||||||
|
i8mm, // Advanced SIMD int8 matrix multiplication instructions.
|
||||||
|
jscvt, // JavaScript conversion instruction.
|
||||||
|
rdm, // Advanced SIMD rounding double multiply accumulate instructions.
|
||||||
|
|
||||||
cpu_features: Maybe(CPU_Feature)
|
flagm, // Condition flag manipulation instructions.
|
||||||
cpu_name: Maybe(string)
|
flagm2, // Enhancements to condition flag manipulation instructions.
|
||||||
|
crc32, // CRC32 instructions.
|
||||||
|
|
||||||
@(init, private)
|
lse, // Atomic instructions to support large systems.
|
||||||
init_cpu_features :: proc "c" () {
|
lse2, // Changes to single-copy atomicity and alignment requirements for loads and stores for large systems.
|
||||||
|
lrcpc, // Load-acquire Release Consistency processor consistent (RCpc) instructions.
|
||||||
|
lrcpc2, // Load-acquire Release Consistency processor consistent (RCpc) instructions version 2.
|
||||||
|
|
||||||
|
aes,
|
||||||
|
pmull,
|
||||||
|
sha1,
|
||||||
|
sha256,
|
||||||
|
sha512,
|
||||||
|
sha3,
|
||||||
|
|
||||||
|
sb, // Barrier instruction to control speculation.
|
||||||
|
ssbs, // Instructions to control speculation of loads and stores.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CPU_Features :: distinct bit_set[CPU_Feature; u64]
|
||||||
|
|
||||||
|
cpu_features: Maybe(CPU_Features)
|
||||||
|
cpu_name: Maybe(string)
|
||||||
|
|
||||||
@(private)
|
@(private)
|
||||||
_cpu_name_buf: [72]u8
|
cpu_name_buf: [128]byte
|
||||||
|
|
||||||
@(init, private)
|
@(init, private)
|
||||||
init_cpu_name :: proc "c" () {
|
init_cpu_name :: proc "contextless" () {
|
||||||
when ODIN_ARCH == .arm32 {
|
when ODIN_ARCH == .arm64 {
|
||||||
copy(_cpu_name_buf[:], "ARM")
|
copy(cpu_name_buf[:], "ARM64")
|
||||||
cpu_name = string(_cpu_name_buf[:3])
|
cpu_name = string(cpu_name_buf[:len("ARM64")])
|
||||||
} else {
|
} else {
|
||||||
copy(_cpu_name_buf[:], "ARM64")
|
copy(cpu_name_buf[:], "ARM")
|
||||||
cpu_name = string(_cpu_name_buf[:5])
|
cpu_name = string(cpu_name_buf[:len("ARM")])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,98 @@
|
|||||||
|
package sysinfo
|
||||||
|
|
||||||
|
import "core:sys/unix"
|
||||||
|
|
||||||
|
@(init, private)
|
||||||
|
init_cpu_features :: proc "contextless" () {
|
||||||
|
@(static) features: CPU_Features
|
||||||
|
defer cpu_features = features
|
||||||
|
|
||||||
|
try_set :: proc "contextless" (name: string, feature: CPU_Feature) -> (ok: bool) {
|
||||||
|
support: b32
|
||||||
|
if ok = unix.sysctlbyname(name, &support); ok && support {
|
||||||
|
features += { feature }
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Docs from Apple: https://developer.apple.com/documentation/kernel/1387446-sysctlbyname/determining_instruction_set_characteristics
|
||||||
|
// Features from there that do not have (or I didn't find) an equivalent on Linux are commented out below.
|
||||||
|
|
||||||
|
// Advanced SIMD & floating-point capabilities:
|
||||||
|
{
|
||||||
|
if !try_set("hw.optional.AdvSIMD", .asimd) {
|
||||||
|
try_set("hw.optional.neon", .asimd)
|
||||||
|
}
|
||||||
|
|
||||||
|
try_set("hw.optional.floatingpoint", .floatingpoint)
|
||||||
|
|
||||||
|
if !try_set("hw.optional.AdvSIMD_HPFPCvt", .asimdhp) {
|
||||||
|
try_set("hw.optional.neon_hpfp", .asimdhp)
|
||||||
|
}
|
||||||
|
|
||||||
|
try_set("hw.optional.arm.FEAT_BF16", .bf16)
|
||||||
|
// try_set("hw.optional.arm.FEAT_DotProd", .dotprod)
|
||||||
|
|
||||||
|
if !try_set("hw.optional.arm.FEAT_FCMA", .fcma) {
|
||||||
|
try_set("hw.optional.armv8_3_compnum", .fcma)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !try_set("hw.optional.arm.FEAT_FHM", .fhm) {
|
||||||
|
try_set("hw.optional.armv8_2_fhm", .fhm)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !try_set("hw.optional.arm.FEAT_FP16", .fp16) {
|
||||||
|
try_set("hw.optional.neon_fp16", .fp16)
|
||||||
|
}
|
||||||
|
|
||||||
|
try_set("hw.optional.arm.FEAT_FRINTTS", .frint)
|
||||||
|
try_set("hw.optional.arm.FEAT_I8MM", .i8mm)
|
||||||
|
try_set("hw.optional.arm.FEAT_JSCVT", .jscvt)
|
||||||
|
try_set("hw.optional.arm.FEAT_RDM", .rdm)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Integer capabilities:
|
||||||
|
{
|
||||||
|
try_set("hw.optional.arm.FEAT_FlagM", .flagm)
|
||||||
|
try_set("hw.optional.arm.FEAT_FlagM2", .flagm2)
|
||||||
|
try_set("hw.optional.armv8_crc32", .crc32)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Atomic and memory ordering instruction capabilities:
|
||||||
|
{
|
||||||
|
try_set("hw.optional.arm.FEAT_LRCPC", .lrcpc)
|
||||||
|
try_set("hw.optional.arm.FEAT_LRCPC2", .lrcpc2)
|
||||||
|
|
||||||
|
if !try_set("hw.optional.arm.FEAT_LSE", .lse) {
|
||||||
|
try_set("hw.optional.armv8_1_atomics", .lse)
|
||||||
|
}
|
||||||
|
|
||||||
|
// try_set("hw.optional.arm.FEAT_LSE2", .lse2)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Encryption capabilities:
|
||||||
|
{
|
||||||
|
try_set("hw.optional.arm.FEAT_AES", .aes)
|
||||||
|
try_set("hw.optional.arm.FEAT_PMULL", .pmull)
|
||||||
|
try_set("hw.optional.arm.FEAT_SHA1", .sha1)
|
||||||
|
try_set("hw.optional.arm.FEAT_SHA256", .sha256)
|
||||||
|
|
||||||
|
if !try_set("hw.optional.arm.FEAT_SHA512", .sha512) {
|
||||||
|
try_set("hw.optional.armv8_2_sha512", .sha512)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !try_set("hw.optional.arm.FEAT_SHA3", .sha3) {
|
||||||
|
try_set("hw.optional.armv8_2_sha3", .sha3)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// General capabilities:
|
||||||
|
{
|
||||||
|
// try_set("hw.optional.arm.FEAT_BTI", .bti)
|
||||||
|
// try_set("hw.optional.arm.FEAT_DPB", .dpb)
|
||||||
|
// try_set("hw.optional.arm.FEAT_DPB2", .dpb2)
|
||||||
|
// try_set("hw.optional.arm.FEAT_ECV", .ecv)
|
||||||
|
try_set("hw.optional.arm.FEAT_SB", .sb)
|
||||||
|
try_set("hw.optional.arm.FEAT_SSBS", .ssbs)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,65 @@
|
|||||||
|
//+build arm32, arm64
|
||||||
|
//+build linux
|
||||||
|
package sysinfo
|
||||||
|
|
||||||
|
import "core:sys/linux"
|
||||||
|
import "core:strings"
|
||||||
|
|
||||||
|
@(init, private)
|
||||||
|
init_cpu_features :: proc() {
|
||||||
|
fd, err := linux.open("/proc/cpuinfo", {})
|
||||||
|
if err != .NONE { return }
|
||||||
|
defer linux.close(fd)
|
||||||
|
|
||||||
|
// This is probably enough right?
|
||||||
|
buf: [4096]byte
|
||||||
|
n, rerr := linux.read(fd, buf[:])
|
||||||
|
if rerr != .NONE || n == 0 { return }
|
||||||
|
|
||||||
|
features: CPU_Features
|
||||||
|
defer cpu_features = features
|
||||||
|
|
||||||
|
str := string(buf[:n])
|
||||||
|
for line in strings.split_lines_iterator(&str) {
|
||||||
|
key, _, value := strings.partition(line, ":")
|
||||||
|
key = strings.trim_space(key)
|
||||||
|
value = strings.trim_space(value)
|
||||||
|
|
||||||
|
if key != "Features" { continue }
|
||||||
|
|
||||||
|
for feature in strings.split_by_byte_iterator(&value, ' ') {
|
||||||
|
switch feature {
|
||||||
|
case "asimd", "neon": features += { .asimd }
|
||||||
|
case "fp": features += { .floatingpoint }
|
||||||
|
case "asimdhp": features += { .asimdhp }
|
||||||
|
case "asimdbf16": features += { .bf16 }
|
||||||
|
case "fcma": features += { .fcma }
|
||||||
|
case "asimdfhm": features += { .fhm }
|
||||||
|
case "fphp", "half": features += { .fp16 }
|
||||||
|
case "frint": features += { .frint }
|
||||||
|
case "i8mm": features += { .i8mm }
|
||||||
|
case "jscvt": features += { .jscvt }
|
||||||
|
case "asimdrdm": features += { .rdm }
|
||||||
|
|
||||||
|
case "flagm": features += { .flagm }
|
||||||
|
case "flagm2": features += { .flagm2 }
|
||||||
|
case "crc32": features += { .crc32 }
|
||||||
|
|
||||||
|
case "atomics": features += { .lse }
|
||||||
|
case "lrcpc": features += { .lrcpc }
|
||||||
|
case "ilrcpc": features += { .lrcpc2 }
|
||||||
|
|
||||||
|
case "aes": features += { .aes }
|
||||||
|
case "pmull": features += { .pmull }
|
||||||
|
case "sha1": features += { .sha1 }
|
||||||
|
case "sha2": features += { .sha256 }
|
||||||
|
case "sha3": features += { .sha3 }
|
||||||
|
case "sha512": features += { .sha512 }
|
||||||
|
|
||||||
|
case "sb": features += { .sb }
|
||||||
|
case "ssbs": features += { .ssbs }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user