mirror of
https://github.com/odin-lang/Odin.git
synced 2026-04-24 15:25:20 +00:00
sys/info: add feature detection for Darwin and Linux ARM
This commit is contained in:
@@ -1,26 +1,55 @@
|
||||
//+build arm32, arm64
|
||||
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)
|
||||
cpu_name: Maybe(string)
|
||||
flagm, // Condition flag manipulation instructions.
|
||||
flagm2, // Enhancements to condition flag manipulation instructions.
|
||||
crc32, // CRC32 instructions.
|
||||
|
||||
@(init, private)
|
||||
init_cpu_features :: proc "c" () {
|
||||
lse, // Atomic instructions to support large systems.
|
||||
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)
|
||||
_cpu_name_buf: [72]u8
|
||||
cpu_name_buf: [128]byte
|
||||
|
||||
@(init, private)
|
||||
init_cpu_name :: proc "c" () {
|
||||
when ODIN_ARCH == .arm32 {
|
||||
copy(_cpu_name_buf[:], "ARM")
|
||||
cpu_name = string(_cpu_name_buf[:3])
|
||||
init_cpu_name :: proc "contextless" () {
|
||||
when ODIN_ARCH == .arm64 {
|
||||
copy(cpu_name_buf[:], "ARM64")
|
||||
cpu_name = string(cpu_name_buf[:len("ARM64")])
|
||||
} else {
|
||||
copy(_cpu_name_buf[:], "ARM64")
|
||||
cpu_name = string(_cpu_name_buf[:5])
|
||||
copy(cpu_name_buf[:], "ARM")
|
||||
cpu_name = string(cpu_name_buf[:len("ARM")])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
98
core/sys/info/cpu_darwin_arm64.odin
Normal file
98
core/sys/info/cpu_darwin_arm64.odin
Normal file
@@ -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)
|
||||
}
|
||||
}
|
||||
65
core/sys/info/cpu_linux_arm.odin
Normal file
65
core/sys/info/cpu_linux_arm.odin
Normal file
@@ -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