authorgravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2026-09-06 21:52:59+02:00
committergravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2026-09-06 21:52:59+02:00
log8839d95005bff0742ba9cd75b069b4967c35c04c
tree89e903d377a429b761ebd7b627fb247e7bad6501
parent79a9897cdcb3a03df14ba770f6d75c552264041b
parent23078ca0b44e9b30e1e363c39685a7309d5f08b0

Merge pull request '`std.zig.system.openbsd`: implement aarch64 CPU model detection' (#36777) from alexrp/zig:aarch64-openbsd-cpu-model into master

Reviewed-on: https://codeberg.org/ziglang/zig/pulls/36777

3 files changed, 114 insertions(+), 10 deletions(-)

lib/std/zig/system/arm.zig+27
...@@ -279,6 +279,33 @@ pub const aarch64 = struct {...@@ -279,6 +279,33 @@ pub const aarch64 = struct {
279 return cpu;279 return cpu;
280 }280 }
281281
282 /// Input array should consist of readouts from 12 system registers such that:
283 /// 0 -> ID_AA64PFR0_EL1
284 /// 1 -> ID_AA64PFR1_EL1
285 /// 2 -> ID_AA64DFR0_EL1
286 /// 3 -> ID_AA64DFR1_EL1
287 /// 4 -> ID_AA64AFR0_EL1
288 /// 5 -> ID_AA64AFR1_EL1
289 /// 6 -> ID_AA64ISAR0_EL1
290 /// 7 -> ID_AA64ISAR1_EL1
291 /// 8 -> ID_AA64MMFR0_EL1
292 /// 9 -> ID_AA64MMFR1_EL1
293 /// 10 -> ID_AA64MMFR2_EL1
294 pub fn detectNativeFeatures(arch: Target.Cpu.Arch, model: *const Target.Cpu.Model, registers: [11]u64) Target.Cpu {
295 var cpu: Target.Cpu = .{
296 .arch = arch,
297 .model = model,
298 .features = model.features,
299 };
300
301 detectNativeCpuFeatures(&cpu, registers[0..]);
302 addInstructionFusions(&cpu);
303
304 cpu.features.populateDependencies(cpu.arch.allFeaturesList());
305
306 return cpu;
307 }
308
282 /// Takes readout of MIDR_EL1 register as input.309 /// Takes readout of MIDR_EL1 register as input.
283 fn detectNativeCoreInfo(midr: u64) CoreInfo {310 fn detectNativeCoreInfo(midr: u64) CoreInfo {
284 var info = CoreInfo{311 var info = CoreInfo{
lib/std/zig/system/darwin/macos.zig+3-7
...@@ -399,14 +399,14 @@ test "detect" {...@@ -399,14 +399,14 @@ test "detect" {
399399
400pub fn detectNativeCpuAndFeatures() ?Target.Cpu {400pub fn detectNativeCpuAndFeatures() ?Target.Cpu {
401 var cpu_family: std.c.CPUFAMILY = undefined;401 var cpu_family: std.c.CPUFAMILY = undefined;
402 var len: usize = @sizeOf(std.c.CPUFAMILY);402 var len: usize = @sizeOf(@TypeOf(cpu_family));
403 switch (posix.errno(posix.system.sysctlbyname("hw.cpufamily", &cpu_family, &len, null, 0))) {403 switch (posix.errno(posix.system.sysctlbyname("hw.cpufamily", &cpu_family, &len, null, 0))) {
404 .SUCCESS => {},404 .SUCCESS => {},
405 .FAULT => unreachable, // segmentation fault405 .FAULT => unreachable, // segmentation fault
406 .PERM => unreachable, // only when setting values,406 .PERM => unreachable, // only when setting values,
407 .NOMEM => unreachable, // memory already on the stack407 .NOMEM => unreachable, // memory already on the stack
408 .NOENT => unreachable, // constant, known good value408 .NOENT => unreachable, // constant, known good value
409 else => unreachable,409 else => return null,
410 }410 }
411411
412 const current_arch = builtin.cpu.arch;412 const current_arch = builtin.cpu.arch;
...@@ -438,11 +438,7 @@ pub fn detectNativeCpuAndFeatures() ?Target.Cpu {...@@ -438,11 +438,7 @@ pub fn detectNativeCpuAndFeatures() ?Target.Cpu {
438 else => return null,438 else => return null,
439 };439 };
440440
441 return Target.Cpu{441 return model.toCpu(current_arch);
442 .arch = current_arch,
443 .model = model,
444 .features = model.features,
445 };
446 },442 },
447 else => {},443 else => {},
448 }444 }
lib/std/zig/system/openbsd.zig+84-3
...@@ -22,6 +22,77 @@ fn hwModelName(buf: [:0]u8) ?[:0]const u8 {...@@ -22,6 +22,77 @@ fn hwModelName(buf: [:0]u8) ?[:0]const u8 {
22}22}
2323
24const aarch64 = struct {24const aarch64 = struct {
25 const models = .{
26 .{ "Ampere AmpereOne AC03", &std.Target.aarch64.cpu.ampere1 },
27 .{ "Ampere AmpereOne AC04", &std.Target.aarch64.cpu.ampere1a },
28 .{ "Apple Icestorm Max", &std.Target.aarch64.cpu.apple_m1 },
29 .{ "Apple Icestorm Pro", &std.Target.aarch64.cpu.apple_m1 },
30 .{ "Apple Icestorm", &std.Target.aarch64.cpu.apple_m1 },
31 .{ "Apple Firestorm Max", &std.Target.aarch64.cpu.apple_m1 },
32 .{ "Apple Firestorm Pro", &std.Target.aarch64.cpu.apple_m1 },
33 .{ "Apple Firestorm", &std.Target.aarch64.cpu.apple_m1 },
34 .{ "Apple Blizzard Max", &std.Target.aarch64.cpu.apple_m2 },
35 .{ "Apple Blizzard Pro", &std.Target.aarch64.cpu.apple_m2 },
36 .{ "Apple Blizzard", &std.Target.aarch64.cpu.apple_m2 },
37 .{ "Apple Avalanche Max", &std.Target.aarch64.cpu.apple_m2 },
38 .{ "Apple Avalanche Pro", &std.Target.aarch64.cpu.apple_m2 },
39 .{ "Apple Avalanche", &std.Target.aarch64.cpu.apple_m2 },
40 .{ "Applied Micro X-Gene", &std.Target.aarch64.cpu.xgene1 },
41 // TODO: Add these with LLVM 23.
42 // .{ "ARM C1-Nano", &std.Target.aarch64.cpu.c1_nano },
43 // .{ "ARM C1-Pro", &std.Target.aarch64.cpu.c1_pro },
44 // .{ "ARM C1-Ultra", &std.Target.aarch64.cpu.c1_ultra },
45 // .{ "ARM C1-Premium", &std.Target.aarch64.cpu.c1_premium },
46 .{ "ARM Cortex-A320", &std.Target.aarch64.cpu.cortex_a320 },
47 .{ "ARM Cortex-A34", &std.Target.aarch64.cpu.cortex_a34 },
48 .{ "ARM Cortex-A35", &std.Target.aarch64.cpu.cortex_a35 },
49 .{ "ARM Cortex-A510", &std.Target.aarch64.cpu.cortex_a510 },
50 .{ "ARM Cortex-A520AE", &std.Target.aarch64.cpu.cortex_a520ae },
51 .{ "ARM Cortex-A520", &std.Target.aarch64.cpu.cortex_a520 },
52 .{ "ARM Cortex-A53", &std.Target.aarch64.cpu.cortex_a53 },
53 .{ "ARM Cortex-A55", &std.Target.aarch64.cpu.cortex_a55 },
54 .{ "ARM Cortex-A57", &std.Target.aarch64.cpu.cortex_a57 },
55 .{ "ARM Cortex-A65AE", &std.Target.aarch64.cpu.cortex_a65ae },
56 .{ "ARM Cortex-A65", &std.Target.aarch64.cpu.cortex_a65 },
57 .{ "ARM Cortex-A710", &std.Target.aarch64.cpu.cortex_a710 },
58 .{ "ARM Cortex-A715", &std.Target.aarch64.cpu.cortex_a715 },
59 .{ "ARM Cortex-A720AE", &std.Target.aarch64.cpu.cortex_a720ae },
60 .{ "ARM Cortex-A720", &std.Target.aarch64.cpu.cortex_a720 },
61 .{ "ARM Cortex-A725", &std.Target.aarch64.cpu.cortex_a725 },
62 .{ "ARM Cortex-A72", &std.Target.aarch64.cpu.cortex_a72 },
63 .{ "ARM Cortex-A73", &std.Target.aarch64.cpu.cortex_a73 },
64 .{ "ARM Cortex-A75", &std.Target.aarch64.cpu.cortex_a75 },
65 .{ "ARM Cortex-A76AE", &std.Target.aarch64.cpu.cortex_a76ae },
66 .{ "ARM Cortex-A76", &std.Target.aarch64.cpu.cortex_a76 },
67 .{ "ARM Cortex-A77", &std.Target.aarch64.cpu.cortex_a77 },
68 .{ "ARM Cortex-A78AE", &std.Target.aarch64.cpu.cortex_a78ae },
69 .{ "ARM Cortex-A78C", &std.Target.aarch64.cpu.cortex_a78c },
70 .{ "ARM Cortex-A78", &std.Target.aarch64.cpu.cortex_a78 },
71 .{ "ARM Cortex-X1C", &std.Target.aarch64.cpu.cortex_x1c },
72 .{ "ARM Cortex-X1", &std.Target.aarch64.cpu.cortex_x1 },
73 .{ "ARM Cortex-X2", &std.Target.aarch64.cpu.cortex_x2 },
74 .{ "ARM Cortex-X3", &std.Target.aarch64.cpu.cortex_x3 },
75 .{ "ARM Cortex-X4", &std.Target.aarch64.cpu.cortex_x4 },
76 .{ "ARM Cortex-X925", &std.Target.aarch64.cpu.cortex_x925 },
77 .{ "ARM Neoverse E1", &std.Target.aarch64.cpu.neoverse_e1 },
78 .{ "ARM Neoverse N1", &std.Target.aarch64.cpu.neoverse_n1 },
79 .{ "ARM Neoverse N2", &std.Target.aarch64.cpu.neoverse_n2 },
80 .{ "ARM Neoverse N3", &std.Target.aarch64.cpu.neoverse_n3 },
81 .{ "ARM Neoverse V1", &std.Target.aarch64.cpu.neoverse_v1 },
82 .{ "ARM Neoverse V2", &std.Target.aarch64.cpu.neoverse_v2 },
83 .{ "ARM Neoverse V3AE", &std.Target.aarch64.cpu.neoverse_v3ae },
84 .{ "ARM Neoverse V3", &std.Target.aarch64.cpu.neoverse_v3 },
85 .{ "Cavium ThunderX T81", &std.Target.aarch64.cpu.thunderxt81 },
86 .{ "Cavium ThunderX T83", &std.Target.aarch64.cpu.thunderxt83 },
87 .{ "Cavium ThunderX T88", &std.Target.aarch64.cpu.thunderxt88 },
88 .{ "Cavium ThunderX2 T99", &std.Target.aarch64.cpu.thunderx2t99 },
89 .{ "Microsoft Azure Cobalt 100", &std.Target.aarch64.cpu.cobalt_100 },
90 .{ "NVIDIA Olympus", &std.Target.aarch64.cpu.olympus },
91 .{ "Qualcomm Kryo 400 Gold", &std.Target.aarch64.cpu.cortex_a76 },
92 .{ "Qualcomm Kryo 400 Silver", &std.Target.aarch64.cpu.cortex_a55 },
93 .{ "Qualcomm Oryon", &std.Target.aarch64.cpu.oryon_1 },
94 };
95
25 fn sysctlReg(key: c_int) ?u64 {96 fn sysctlReg(key: c_int) ?u64 {
26 const mib: [2]c_int = [_]c_int{97 const mib: [2]c_int = [_]c_int{
27 std.c.CTL.MACHDEP,98 std.c.CTL.MACHDEP,
...@@ -42,8 +113,18 @@ const aarch64 = struct {...@@ -42,8 +113,18 @@ const aarch64 = struct {
42 }113 }
43114
44 fn detectNativeCpuAndFeatures(arch: std.Target.Cpu.Arch) ?std.Target.Cpu {115 fn detectNativeCpuAndFeatures(arch: std.Target.Cpu.Arch) ?std.Target.Cpu {
45 const registers = [12]u64{116 const model: *const std.Target.Cpu.Model = blk: {
46 0, // MIDR_EL1117 var buf: [64:0]u8 = undefined;
118 const name = hwModelName(&buf) orelse return null;
119
120 inline for (models) |pair| {
121 if (std.mem.startsWith(u8, name, pair[0])) break :blk pair[1];
122 }
123
124 break :blk .generic(arch);
125 };
126
127 const registers = [11]u64{
47 sysctlReg(std.c.CPU.AA64PFR0) orelse return null,128 sysctlReg(std.c.CPU.AA64PFR0) orelse return null,
48 sysctlReg(std.c.CPU.AA64PFR1) orelse return null,129 sysctlReg(std.c.CPU.AA64PFR1) orelse return null,
49 0, // ID_AA64DFR0_EL1130 0, // ID_AA64DFR0_EL1
...@@ -57,7 +138,7 @@ const aarch64 = struct {...@@ -57,7 +138,7 @@ const aarch64 = struct {
57 sysctlReg(std.c.CPU.ID_AA64MMFR2) orelse return null,138 sysctlReg(std.c.CPU.ID_AA64MMFR2) orelse return null,
58 };139 };
59140
60 return @import("arm.zig").aarch64.detectNativeCpuAndFeatures(arch, registers);141 return @import("arm.zig").aarch64.detectNativeFeatures(arch, model, registers);
61 }142 }
62};143};
63144