authorgravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2026-09-05 18:37:00+02:00
committergravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2026-09-05 19:32:56+02:00
log9cf3a2b7f8dbb439b31c579000aa780e9fa6b2d5
treeda31317488ac35eb80c13c77a293c6cb3c1ca86e
parentaf24fd11a5c37ef5531ddb86356cd6c55ed71d77
signaturebadge-check Signed by SSH key SHA256:7B/LJ7bpR1eX8aCXSr4mtd5M45VMPKcx9zY8e95b5QM

std.zig.system.arm: don't give up just because we can't determine the model

For example, OpenBSD doesn't give us MIDR_EL1. But that doesn't mean we should just give up when we can still detect individual features.

1 files changed, 24 insertions(+), 24 deletions(-)

lib/std/zig/system/arm.zig+24-24
......@@ -242,6 +242,10 @@ pub const aarch64 = struct {
242242 return @as(u4, @truncate(input >> offset));
243243 }
244244
245 inline fn signedBitField(input: u64, offset: u6) i4 {
246 return @as(i4, @bitCast(@as(u4, @truncate(input >> offset))));
247 }
248
245249 /// Input array should consist of readouts from 12 system registers such that:
246250 /// 0 -> MIDR_EL1
247251 /// 1 -> ID_AA64PFR0_EL1
......@@ -255,18 +259,22 @@ pub const aarch64 = struct {
255259 /// 9 -> ID_AA64MMFR0_EL1
256260 /// 10 -> ID_AA64MMFR1_EL1
257261 /// 11 -> ID_AA64MMFR2_EL1
258 pub fn detectNativeCpuAndFeatures(arch: Target.Cpu.Arch, registers: [12]u64) ?Target.Cpu {
262 pub fn detectNativeCpuAndFeatures(arch: Target.Cpu.Arch, registers: [12]u64) Target.Cpu {
259263 const info = detectNativeCoreInfo(registers[0]);
260 const model = cpu_models.isKnown(info, true) orelse return null;
264 const model = cpu_models.isKnown(info, true) orelse Target.Cpu.Model.generic(arch);
261265
262266 var cpu = Target.Cpu{
263267 .arch = arch,
264268 .model = model,
265 .features = Target.Cpu.Feature.Set.empty,
269 .features = .empty,
266270 };
267271
272 cpu.features.addFeatureSet(model.features);
273
268274 detectNativeCpuFeatures(&cpu, registers[1..12]);
269 addInstructionFusions(&cpu, info);
275 addInstructionFusions(&cpu);
276
277 cpu.features.populateDependencies(cpu.arch.allFeaturesList());
270278
271279 return cpu;
272280 }
......@@ -318,14 +326,9 @@ pub const aarch64 = struct {
318326 setFeature(cpu, .sve, bitField(registers[0], 32) >= 1);
319327 setFeature(cpu, .el3, bitField(registers[0], 12) >= 1);
320328 setFeature(cpu, .ras, bitField(registers[0], 28) >= 1);
321
322 if (bitField(registers[0], 20) < 0xF) blk: {
323 if (bitField(registers[0], 16) != bitField(registers[0], 20)) break :blk; // This should never occur
324
325 setFeature(cpu, .neon, true);
326 setFeature(cpu, .fp_armv8, true);
327 setFeature(cpu, .fullfp16, bitField(registers[0], 20) > 0);
328 }
329 setFeature(cpu, .fp_armv8, signedBitField(registers[0], 16) >= 0);
330 setFeature(cpu, .neon, signedBitField(registers[0], 20) >= 0);
331 setFeature(cpu, .fullfp16, signedBitField(registers[0], 16) >= 1 and signedBitField(registers[0], 20) >= 1);
329332
330333 // ID_AA64PFR1_EL1
331334 setFeature(cpu, .mpam, bitField(registers[1], 16) > 0 and bitField(registers[0], 40) == 0); // MPAM v0.1
......@@ -336,7 +339,7 @@ pub const aarch64 = struct {
336339 // ID_AA64DFR0_EL1
337340 setFeature(cpu, .tracev8_4, bitField(registers[2], 40) >= 1);
338341 setFeature(cpu, .spe, bitField(registers[2], 32) >= 1);
339 setFeature(cpu, .perfmon, bitField(registers[2], 8) >= 1 and bitField(registers[2], 8) < 0xF);
342 setFeature(cpu, .perfmon, signedBitField(registers[2], 8) >= 1);
340343
341344 // ID_AA64DFR1_EL1 reserved
342345 // ID_AA64AFR0_EL1 reserved / implementation defined
......@@ -387,17 +390,14 @@ pub const aarch64 = struct {
387390 setFeature(cpu, .uaops, bitField(registers[10], 4) >= 1);
388391 }
389392
390 fn addInstructionFusions(cpu: *Target.Cpu, info: CoreInfo) void {
391 switch (info.implementer) {
392 0x41 => switch (info.part) {
393 0xd4b, 0xd4c => {
394 // According to A78C/X1C Core Software Optimization Guide, CPU fuses certain instructions.
395 setFeature(cpu, .cmp_bcc_fusion, true);
396 setFeature(cpu, .fuse_aes, true);
397 },
398 else => {},
399 },
400 else => {},
393 fn addInstructionFusions(cpu: *Target.Cpu) void {
394 const m = cpu.model;
395 const c = Target.aarch64.cpu;
396
397 if (m == &c.cortex_a78c or m == &c.cortex_x1c) {
398 // According to A78C/X1C Core Software Optimization Guide, CPU fuses certain instructions.
399 setFeature(cpu, .cmp_bcc_fusion, true);
400 setFeature(cpu, .fuse_aes, true);
401401 }
402402 }
403403};