Commit 7bf12b1197
Changed files (4)
lib
std
target
zig
lib/std/target/aarch64.zig
@@ -2252,19 +2252,4 @@ pub const cpu = struct {
.v8a,
}),
};
-
- pub const microsoft_sq3 = CpuModel{
- .name = "microsoft_sq3",
- .llvm_name = "generic",
- .features = featureSet(&[_]Feature{
- .aes,
- .crc,
- .crypto,
- .dotprod,
- .fp_armv8,
- .lse,
- .neon,
- .sha2,
- }),
- };
};
lib/std/zig/system/arm.zig
@@ -0,0 +1,134 @@
+const std = @import("std");
+
+pub const CoreInfo = struct {
+ architecture: u8 = 0,
+ implementer: u8 = 0,
+ variant: u8 = 0,
+ part: u16 = 0,
+};
+
+pub const cpu_models = struct {
+ // Shorthands to simplify the tables below.
+ const A32 = std.Target.arm.cpu;
+ const A64 = std.Target.aarch64.cpu;
+
+ const E = struct {
+ part: u16,
+ variant: ?u8 = null, // null if matches any variant
+ m32: ?*const std.Target.Cpu.Model = null,
+ m64: ?*const std.Target.Cpu.Model = null,
+ };
+
+ // implementer = 0x41
+ const ARM = [_]E{
+ E{ .part = 0x926, .m32 = &A32.arm926ej_s, .m64 = null },
+ E{ .part = 0xb02, .m32 = &A32.mpcore, .m64 = null },
+ E{ .part = 0xb36, .m32 = &A32.arm1136j_s, .m64 = null },
+ E{ .part = 0xb56, .m32 = &A32.arm1156t2_s, .m64 = null },
+ E{ .part = 0xb76, .m32 = &A32.arm1176jz_s, .m64 = null },
+ E{ .part = 0xc05, .m32 = &A32.cortex_a5, .m64 = null },
+ E{ .part = 0xc07, .m32 = &A32.cortex_a7, .m64 = null },
+ E{ .part = 0xc08, .m32 = &A32.cortex_a8, .m64 = null },
+ E{ .part = 0xc09, .m32 = &A32.cortex_a9, .m64 = null },
+ E{ .part = 0xc0d, .m32 = &A32.cortex_a17, .m64 = null },
+ E{ .part = 0xc0f, .m32 = &A32.cortex_a15, .m64 = null },
+ E{ .part = 0xc0e, .m32 = &A32.cortex_a17, .m64 = null },
+ E{ .part = 0xc14, .m32 = &A32.cortex_r4, .m64 = null },
+ E{ .part = 0xc15, .m32 = &A32.cortex_r5, .m64 = null },
+ E{ .part = 0xc17, .m32 = &A32.cortex_r7, .m64 = null },
+ E{ .part = 0xc18, .m32 = &A32.cortex_r8, .m64 = null },
+ E{ .part = 0xc20, .m32 = &A32.cortex_m0, .m64 = null },
+ E{ .part = 0xc21, .m32 = &A32.cortex_m1, .m64 = null },
+ E{ .part = 0xc23, .m32 = &A32.cortex_m3, .m64 = null },
+ E{ .part = 0xc24, .m32 = &A32.cortex_m4, .m64 = null },
+ E{ .part = 0xc27, .m32 = &A32.cortex_m7, .m64 = null },
+ E{ .part = 0xc60, .m32 = &A32.cortex_m0plus, .m64 = null },
+ E{ .part = 0xd01, .m32 = &A32.cortex_a32, .m64 = null },
+ E{ .part = 0xd03, .m32 = &A32.cortex_a53, .m64 = &A64.cortex_a53 },
+ E{ .part = 0xd04, .m32 = &A32.cortex_a35, .m64 = &A64.cortex_a35 },
+ E{ .part = 0xd05, .m32 = &A32.cortex_a55, .m64 = &A64.cortex_a55 },
+ E{ .part = 0xd07, .m32 = &A32.cortex_a57, .m64 = &A64.cortex_a57 },
+ E{ .part = 0xd08, .m32 = &A32.cortex_a72, .m64 = &A64.cortex_a72 },
+ E{ .part = 0xd09, .m32 = &A32.cortex_a73, .m64 = &A64.cortex_a73 },
+ E{ .part = 0xd0a, .m32 = &A32.cortex_a75, .m64 = &A64.cortex_a75 },
+ E{ .part = 0xd0b, .m32 = &A32.cortex_a76, .m64 = &A64.cortex_a76 },
+ E{ .part = 0xd0c, .m32 = &A32.neoverse_n1, .m64 = &A64.neoverse_n1 },
+ E{ .part = 0xd0d, .m32 = &A32.cortex_a77, .m64 = &A64.cortex_a77 },
+ E{ .part = 0xd13, .m32 = &A32.cortex_r52, .m64 = null },
+ E{ .part = 0xd20, .m32 = &A32.cortex_m23, .m64 = null },
+ E{ .part = 0xd21, .m32 = &A32.cortex_m33, .m64 = null },
+ E{ .part = 0xd41, .m32 = &A32.cortex_a78, .m64 = &A64.cortex_a78 },
+ E{ .part = 0xd4b, .m32 = &A32.cortex_a78c, .m64 = &A64.cortex_a78c },
+ // This is a guess based on https://www.notebookcheck.net/Qualcomm-Snapdragon-8cx-Gen-3-Processor-Benchmarks-and-Specs.652916.0.html
+ E{ .part = 0xd4c, .m32 = &A32.cortex_x1c, .m64 = &A64.cortex_x1c },
+ E{ .part = 0xd44, .m32 = &A32.cortex_x1, .m64 = &A64.cortex_x1 },
+ E{ .part = 0xd02, .m64 = &A64.cortex_a34 },
+ E{ .part = 0xd06, .m64 = &A64.cortex_a65 },
+ E{ .part = 0xd43, .m64 = &A64.cortex_a65ae },
+ };
+ // implementer = 0x42
+ const Broadcom = [_]E{
+ E{ .part = 0x516, .m64 = &A64.thunderx2t99 },
+ };
+ // implementer = 0x43
+ const Cavium = [_]E{
+ E{ .part = 0x0a0, .m64 = &A64.thunderx },
+ E{ .part = 0x0a2, .m64 = &A64.thunderxt81 },
+ E{ .part = 0x0a3, .m64 = &A64.thunderxt83 },
+ E{ .part = 0x0a1, .m64 = &A64.thunderxt88 },
+ E{ .part = 0x0af, .m64 = &A64.thunderx2t99 },
+ };
+ // implementer = 0x46
+ const Fujitsu = [_]E{
+ E{ .part = 0x001, .m64 = &A64.a64fx },
+ };
+ // implementer = 0x48
+ const HiSilicon = [_]E{
+ E{ .part = 0xd01, .m64 = &A64.tsv110 },
+ };
+ // implementer = 0x4e
+ const Nvidia = [_]E{
+ E{ .part = 0x004, .m64 = &A64.carmel },
+ };
+ // implementer = 0x50
+ const Ampere = [_]E{
+ E{ .part = 0x000, .variant = 3, .m64 = &A64.emag },
+ E{ .part = 0x000, .m64 = &A64.xgene1 },
+ };
+ // implementer = 0x51
+ const Qualcomm = [_]E{
+ E{ .part = 0x06f, .m32 = &A32.krait },
+ E{ .part = 0x201, .m64 = &A64.kryo, .m32 = &A64.kryo },
+ E{ .part = 0x205, .m64 = &A64.kryo, .m32 = &A64.kryo },
+ E{ .part = 0x211, .m64 = &A64.kryo, .m32 = &A64.kryo },
+ E{ .part = 0x800, .m64 = &A64.cortex_a73, .m32 = &A64.cortex_a73 },
+ E{ .part = 0x801, .m64 = &A64.cortex_a73, .m32 = &A64.cortex_a73 },
+ E{ .part = 0x802, .m64 = &A64.cortex_a75, .m32 = &A64.cortex_a75 },
+ E{ .part = 0x803, .m64 = &A64.cortex_a75, .m32 = &A64.cortex_a75 },
+ E{ .part = 0x804, .m64 = &A64.cortex_a76, .m32 = &A64.cortex_a76 },
+ E{ .part = 0x805, .m64 = &A64.cortex_a76, .m32 = &A64.cortex_a76 },
+ E{ .part = 0xc00, .m64 = &A64.falkor },
+ E{ .part = 0xc01, .m64 = &A64.saphira },
+ };
+
+ pub fn isKnown(core: CoreInfo, is_64bit: bool) ?*const std.Target.Cpu.Model {
+ const models = switch (core.implementer) {
+ 0x41 => &ARM,
+ 0x42 => &Broadcom,
+ 0x43 => &Cavium,
+ 0x46 => &Fujitsu,
+ 0x48 => &HiSilicon,
+ 0x50 => &Ampere,
+ 0x51 => &Qualcomm,
+ else => return null,
+ };
+
+ for (models) |model| {
+ if (model.part == core.part and
+ (model.variant == null or model.variant.? == core.variant))
+ return if (is_64bit) model.m64 else model.m32;
+ }
+
+ return null;
+ }
+};
lib/std/zig/system/linux.zig
@@ -159,129 +159,7 @@ const ArmCpuinfoImpl = struct {
is_really_v6: bool = false,
};
- const cpu_models = struct {
- // Shorthands to simplify the tables below.
- const A32 = Target.arm.cpu;
- const A64 = Target.aarch64.cpu;
-
- const E = struct {
- part: u16,
- variant: ?u8 = null, // null if matches any variant
- m32: ?*const Target.Cpu.Model = null,
- m64: ?*const Target.Cpu.Model = null,
- };
-
- // implementer = 0x41
- const ARM = [_]E{
- E{ .part = 0x926, .m32 = &A32.arm926ej_s, .m64 = null },
- E{ .part = 0xb02, .m32 = &A32.mpcore, .m64 = null },
- E{ .part = 0xb36, .m32 = &A32.arm1136j_s, .m64 = null },
- E{ .part = 0xb56, .m32 = &A32.arm1156t2_s, .m64 = null },
- E{ .part = 0xb76, .m32 = &A32.arm1176jz_s, .m64 = null },
- E{ .part = 0xc05, .m32 = &A32.cortex_a5, .m64 = null },
- E{ .part = 0xc07, .m32 = &A32.cortex_a7, .m64 = null },
- E{ .part = 0xc08, .m32 = &A32.cortex_a8, .m64 = null },
- E{ .part = 0xc09, .m32 = &A32.cortex_a9, .m64 = null },
- E{ .part = 0xc0d, .m32 = &A32.cortex_a17, .m64 = null },
- E{ .part = 0xc0f, .m32 = &A32.cortex_a15, .m64 = null },
- E{ .part = 0xc0e, .m32 = &A32.cortex_a17, .m64 = null },
- E{ .part = 0xc14, .m32 = &A32.cortex_r4, .m64 = null },
- E{ .part = 0xc15, .m32 = &A32.cortex_r5, .m64 = null },
- E{ .part = 0xc17, .m32 = &A32.cortex_r7, .m64 = null },
- E{ .part = 0xc18, .m32 = &A32.cortex_r8, .m64 = null },
- E{ .part = 0xc20, .m32 = &A32.cortex_m0, .m64 = null },
- E{ .part = 0xc21, .m32 = &A32.cortex_m1, .m64 = null },
- E{ .part = 0xc23, .m32 = &A32.cortex_m3, .m64 = null },
- E{ .part = 0xc24, .m32 = &A32.cortex_m4, .m64 = null },
- E{ .part = 0xc27, .m32 = &A32.cortex_m7, .m64 = null },
- E{ .part = 0xc60, .m32 = &A32.cortex_m0plus, .m64 = null },
- E{ .part = 0xd01, .m32 = &A32.cortex_a32, .m64 = null },
- E{ .part = 0xd03, .m32 = &A32.cortex_a53, .m64 = &A64.cortex_a53 },
- E{ .part = 0xd04, .m32 = &A32.cortex_a35, .m64 = &A64.cortex_a35 },
- E{ .part = 0xd05, .m32 = &A32.cortex_a55, .m64 = &A64.cortex_a55 },
- E{ .part = 0xd07, .m32 = &A32.cortex_a57, .m64 = &A64.cortex_a57 },
- E{ .part = 0xd08, .m32 = &A32.cortex_a72, .m64 = &A64.cortex_a72 },
- E{ .part = 0xd09, .m32 = &A32.cortex_a73, .m64 = &A64.cortex_a73 },
- E{ .part = 0xd0a, .m32 = &A32.cortex_a75, .m64 = &A64.cortex_a75 },
- E{ .part = 0xd0b, .m32 = &A32.cortex_a76, .m64 = &A64.cortex_a76 },
- E{ .part = 0xd0c, .m32 = &A32.neoverse_n1, .m64 = &A64.neoverse_n1 },
- E{ .part = 0xd0d, .m32 = &A32.cortex_a77, .m64 = &A64.cortex_a77 },
- E{ .part = 0xd13, .m32 = &A32.cortex_r52, .m64 = null },
- E{ .part = 0xd20, .m32 = &A32.cortex_m23, .m64 = null },
- E{ .part = 0xd21, .m32 = &A32.cortex_m33, .m64 = null },
- E{ .part = 0xd41, .m32 = &A32.cortex_a78, .m64 = &A64.cortex_a78 },
- E{ .part = 0xd4b, .m32 = &A32.cortex_a78c, .m64 = &A64.cortex_a78c },
- E{ .part = 0xd44, .m32 = &A32.cortex_x1, .m64 = &A64.cortex_x1 },
- E{ .part = 0xd02, .m64 = &A64.cortex_a34 },
- E{ .part = 0xd06, .m64 = &A64.cortex_a65 },
- E{ .part = 0xd43, .m64 = &A64.cortex_a65ae },
- };
- // implementer = 0x42
- const Broadcom = [_]E{
- E{ .part = 0x516, .m64 = &A64.thunderx2t99 },
- };
- // implementer = 0x43
- const Cavium = [_]E{
- E{ .part = 0x0a0, .m64 = &A64.thunderx },
- E{ .part = 0x0a2, .m64 = &A64.thunderxt81 },
- E{ .part = 0x0a3, .m64 = &A64.thunderxt83 },
- E{ .part = 0x0a1, .m64 = &A64.thunderxt88 },
- E{ .part = 0x0af, .m64 = &A64.thunderx2t99 },
- };
- // implementer = 0x46
- const Fujitsu = [_]E{
- E{ .part = 0x001, .m64 = &A64.a64fx },
- };
- // implementer = 0x48
- const HiSilicon = [_]E{
- E{ .part = 0xd01, .m64 = &A64.tsv110 },
- };
- // implementer = 0x4e
- const Nvidia = [_]E{
- E{ .part = 0x004, .m64 = &A64.carmel },
- };
- // implementer = 0x50
- const Ampere = [_]E{
- E{ .part = 0x000, .variant = 3, .m64 = &A64.emag },
- E{ .part = 0x000, .m64 = &A64.xgene1 },
- };
- // implementer = 0x51
- const Qualcomm = [_]E{
- E{ .part = 0x06f, .m32 = &A32.krait },
- E{ .part = 0x201, .m64 = &A64.kryo, .m32 = &A64.kryo },
- E{ .part = 0x205, .m64 = &A64.kryo, .m32 = &A64.kryo },
- E{ .part = 0x211, .m64 = &A64.kryo, .m32 = &A64.kryo },
- E{ .part = 0x800, .m64 = &A64.cortex_a73, .m32 = &A64.cortex_a73 },
- E{ .part = 0x801, .m64 = &A64.cortex_a73, .m32 = &A64.cortex_a73 },
- E{ .part = 0x802, .m64 = &A64.cortex_a75, .m32 = &A64.cortex_a75 },
- E{ .part = 0x803, .m64 = &A64.cortex_a75, .m32 = &A64.cortex_a75 },
- E{ .part = 0x804, .m64 = &A64.cortex_a76, .m32 = &A64.cortex_a76 },
- E{ .part = 0x805, .m64 = &A64.cortex_a76, .m32 = &A64.cortex_a76 },
- E{ .part = 0xc00, .m64 = &A64.falkor },
- E{ .part = 0xc01, .m64 = &A64.saphira },
- };
-
- fn isKnown(core: CoreInfo, is_64bit: bool) ?*const Target.Cpu.Model {
- const models = switch (core.implementer) {
- 0x41 => &ARM,
- 0x42 => &Broadcom,
- 0x43 => &Cavium,
- 0x46 => &Fujitsu,
- 0x48 => &HiSilicon,
- 0x50 => &Ampere,
- 0x51 => &Qualcomm,
- else => return null,
- };
-
- for (models) |model| {
- if (model.part == core.part and
- (model.variant == null or model.variant.? == core.variant))
- return if (is_64bit) model.m64 else model.m32;
- }
-
- return null;
- }
- };
+ const cpu_models = @import("arm.zig").cpu_models;
fn addOne(self: *ArmCpuinfoImpl) void {
if (self.have_fields == 4 and self.core_no < self.cores.len) {
@@ -346,7 +224,12 @@ const ArmCpuinfoImpl = struct {
var known_models: [self.cores.len]?*const Target.Cpu.Model = undefined;
for (self.cores[0..self.core_no]) |core, i| {
- known_models[i] = cpu_models.isKnown(core, is_64bit);
+ known_models[i] = cpu_models.isKnown(.{
+ .architecture = core.architecture,
+ .implementer = core.implementer,
+ .variant = core.variant,
+ .part = core.part,
+ }, is_64bit);
}
// XXX We pick the first core on big.LITTLE systems, hopefully the
lib/std/zig/system/windows.zig
@@ -45,54 +45,6 @@ pub fn detectRuntimeVersion() WindowsVersion {
return @intToEnum(WindowsVersion, version);
}
-const Armv8CpuInfoImpl = struct {
- cores: [8]*const Target.Cpu.Model = undefined,
- core_no: usize = 0,
-
- const cpu_family_models = .{
- // Family, Model, Revision
- .{ 8, "D4C", 0, &Target.aarch64.cpu.microsoft_sq3 },
- };
-
- fn parseOne(self: *Armv8CpuInfoImpl, identifier: []const u8) void {
- if (mem.indexOf(u8, identifier, "ARMv8") == null) return; // Sanity check
-
- var family: ?usize = null;
- var model: ?[]const u8 = null;
- var revision: ?usize = null;
-
- var tokens = mem.tokenize(u8, identifier, " ");
- while (tokens.next()) |token| {
- if (mem.eql(u8, token, "Family")) {
- const raw = tokens.next() orelse continue;
- family = std.fmt.parseInt(usize, raw, 10) catch null;
- }
- if (mem.eql(u8, token, "Model")) {
- model = tokens.next();
- }
- if (mem.eql(u8, token, "Revision")) {
- const raw = tokens.next() orelse continue;
- revision = std.fmt.parseInt(usize, raw, 10) catch null;
- }
- }
-
- if (family == null or model == null or revision == null) return;
-
- inline for (cpu_family_models) |set| {
- if (set[0] == family.? and mem.eql(u8, set[1], model.?) and set[2] == revision.?) {
- self.cores[self.core_no] = set[3];
- self.core_no += 1;
- break;
- }
- }
- }
-
- fn finalize(self: Armv8CpuInfoImpl) ?*const Target.Cpu.Model {
- if (self.core_no != 8) return null; // Implies we have seen a core we don't know much about
- return self.cores[0];
- }
-};
-
// Technically, a registry value can be as long as 1MB. However, MS recommends storing
// values larger than 2048 bytes in a file rather than directly in the registry, and since we
// are only accessing a system hive \Registry\Machine, we stick to MS guidelines.
@@ -169,44 +121,16 @@ fn getCpuInfoFromRegistry(
else => unreachable,
}
};
- const default: struct { ptr: *anyopaque, len: u32 } = blk: {
- switch (pair.value) {
- REG.SZ,
- REG.EXPAND_SZ,
- REG.MULTI_SZ,
- => {
- const def = std.unicode.utf8ToUtf16LeStringLiteral("Unknown");
- var buf: [def.len + 1]u16 = undefined;
- mem.copy(u16, &buf, def);
- buf[def.len] = 0;
- break :blk .{ .ptr = &buf, .len = @intCast(u32, (buf.len + 1) * 2) };
- },
-
- REG.DWORD,
- REG.DWORD_BIG_ENDIAN,
- => {
- var buf: [4]u8 = [_]u8{0} ** 4;
- break :blk .{ .ptr = &buf, .len = 4 };
- },
-
- REG.QWORD => {
- var buf: [8]u8 = [_]u8{0} ** 8;
- break :blk .{ .ptr = &buf, .len = 8 };
- },
-
- else => unreachable,
- }
- };
- const key_name = std.unicode.utf8ToUtf16LeStringLiteral(pair.key);
+ const key_namee = std.unicode.utf8ToUtf16LeStringLiteral(pair.key);
table[i + 1] = .{
.QueryRoutine = null,
- .Flags = std.os.windows.RTL_QUERY_REGISTRY_DIRECT,
- .Name = @intToPtr([*:0]u16, @ptrToInt(key_name)),
+ .Flags = std.os.windows.RTL_QUERY_REGISTRY_DIRECT | std.os.windows.RTL_QUERY_REGISTRY_REQUIRED,
+ .Name = @intToPtr([*:0]u16, @ptrToInt(key_namee)),
.EntryContext = ctx,
- .DefaultType = pair.value,
- .DefaultData = default.ptr,
- .DefaultLength = default.len,
+ .DefaultType = REG.NONE,
+ .DefaultData = null,
+ .DefaultLength = 0,
};
}
@@ -261,102 +185,177 @@ fn getCpuInfoFromRegistry(
else => unreachable,
};
},
- else => return std.os.windows.unexpectedStatus(res),
+ else => return error.Unexpected,
}
}
-fn detectCpuModelArm64() !*const Target.Cpu.Model {
- // Pull the CPU identifier from the registry.
- // Assume max number of cores to be at 8.
- const max_cpu_count = 8;
- const cpu_count = getCpuCount();
+fn getCpuCount() usize {
+ return std.os.windows.peb().NumberOfProcessors;
+}
- if (cpu_count > max_cpu_count) return error.TooManyCpus;
+const ArmCpuInfoImpl = struct {
+ cores: [4]CoreInfo = undefined,
+ core_no: usize = 0,
+ have_fields: usize = 0,
- // Parse the models from strings
- var parser = Armv8CpuInfoImpl{};
+ const CoreInfo = @import("arm.zig").CoreInfo;
+ const cpu_models = @import("arm.zig").cpu_models;
- var out_buf: [3][max_value_len]u8 = undefined;
+ const Data = struct {
+ cp_4000: []const u8,
+ identifier: []const u8,
+ };
- var i: usize = 0;
- while (i < cpu_count) : (i += 1) {
- try getCpuInfoFromRegistry(i, 3, .{
- .{ .key = "CP 4000", .value = REG.QWORD },
- .{ .key = "Identifier", .value = REG.SZ },
- .{ .key = "VendorIdentifier", .value = REG.SZ },
- }, &out_buf);
+ fn parseDataHook(self: *ArmCpuInfoImpl, data: Data) !void {
+ const info = &self.cores[self.core_no];
+ info.* = .{};
- const hex = out_buf[0][0..8];
- const identifier = mem.sliceTo(out_buf[1][0..], 0);
- const vendor_identifier = mem.sliceTo(out_buf[2][0..], 0);
- std.log.warn("{d} => {x}, {s}, {s}", .{ i, std.fmt.fmtSliceHexLower(hex), identifier, vendor_identifier });
+ // CPU part
+ info.part = mem.readIntLittle(u16, data.cp_4000[0..2]) >> 4;
+ self.have_fields += 1;
+
+ // CPU implementer
+ info.implementer = data.cp_4000[3];
+ self.have_fields += 1;
+
+ var tokens = mem.tokenize(u8, data.identifier, " ");
+ while (tokens.next()) |token| {
+ if (mem.eql(u8, "Family", token)) {
+ // CPU architecture
+ const family = tokens.next() orelse continue;
+ info.architecture = try std.fmt.parseInt(u8, family, 10);
+ self.have_fields += 1;
+ break;
+ }
+ } else return;
+
+ self.addOne();
}
- return parser.finalize() orelse Target.Cpu.Model.generic(.aarch64);
-}
+ fn addOne(self: *ArmCpuInfoImpl) void {
+ if (self.have_fields == 3 and self.core_no < self.cores.len) {
+ if (self.core_no > 0) {
+ // Deduplicate the core info.
+ for (self.cores[0..self.core_no]) |it| {
+ if (std.meta.eql(it, self.cores[self.core_no]))
+ return;
+ }
+ }
+ self.core_no += 1;
+ }
+ }
-fn detectNativeCpuAndFeaturesArm64() Target.Cpu {
- const Feature = Target.aarch64.Feature;
+ fn finalize(self: ArmCpuInfoImpl, arch: Target.Cpu.Arch) ?Target.Cpu {
+ if (self.core_no == 0) return null;
- const model = detectCpuModelArm64() catch Target.Cpu.Model.generic(.aarch64);
+ const is_64bit = switch (arch) {
+ .aarch64, .aarch64_be, .aarch64_32 => true,
+ else => false,
+ };
- var cpu = Target.Cpu{
- .arch = .aarch64,
- .model = model,
- .features = model.features,
- };
+ var known_models: [self.cores.len]?*const Target.Cpu.Model = undefined;
+ for (self.cores[0..self.core_no]) |core, i| {
+ known_models[i] = cpu_models.isKnown(core, is_64bit);
+ }
- // Override any features that are either present or absent
- if (IsProcessorFeaturePresent(PF.ARM_NEON_INSTRUCTIONS_AVAILABLE)) {
- cpu.features.addFeature(@enumToInt(Feature.neon));
- } else {
- cpu.features.removeFeature(@enumToInt(Feature.neon));
+ // XXX We pick the first core on big.LITTLE systems, hopefully the
+ // LITTLE one.
+ const model = known_models[0] orelse return null;
+ return Target.Cpu{
+ .arch = arch,
+ .model = model,
+ .features = model.features,
+ };
}
+};
- if (IsProcessorFeaturePresent(PF.ARM_V8_CRC32_INSTRUCTIONS_AVAILABLE)) {
- cpu.features.addFeature(@enumToInt(Feature.crc));
- } else {
- cpu.features.removeFeature(@enumToInt(Feature.crc));
- }
+const ArmCpuInfoParser = CpuInfoParser(ArmCpuInfoImpl);
- if (IsProcessorFeaturePresent(PF.ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE)) {
- cpu.features.addFeature(@enumToInt(Feature.crypto));
- } else {
- cpu.features.removeFeature(@enumToInt(Feature.crypto));
- }
+fn CpuInfoParser(comptime impl: anytype) type {
+ return struct {
+ fn parse(arch: Target.Cpu.Arch) !?Target.Cpu {
+ var obj: impl = .{};
+ var out_buf: [2][max_value_len]u8 = undefined;
- if (IsProcessorFeaturePresent(PF.ARM_V81_ATOMIC_INSTRUCTIONS_AVAILABLE)) {
- cpu.features.addFeature(@enumToInt(Feature.lse));
- } else {
- cpu.features.removeFeature(@enumToInt(Feature.lse));
- }
+ var i: usize = 0;
+ while (i < getCpuCount()) : (i += 1) {
+ try getCpuInfoFromRegistry(i, 2, .{
+ .{ .key = "CP 4000", .value = REG.QWORD },
+ .{ .key = "Identifier", .value = REG.SZ },
+ }, &out_buf);
- if (IsProcessorFeaturePresent(PF.ARM_V82_DP_INSTRUCTIONS_AVAILABLE)) {
- cpu.features.addFeature(@enumToInt(Feature.dotprod));
- } else {
- cpu.features.removeFeature(@enumToInt(Feature.dotprod));
- }
+ const cp_4000 = out_buf[0][0..8];
+ const identifier = mem.sliceTo(out_buf[1][0..], 0);
- if (IsProcessorFeaturePresent(PF.ARM_V83_JSCVT_INSTRUCTIONS_AVAILABLE)) {
- cpu.features.addFeature(@enumToInt(Feature.jsconv));
- } else {
- cpu.features.removeFeature(@enumToInt(Feature.jsconv));
- }
+ try obj.parseDataHook(.{
+ .cp_4000 = cp_4000,
+ .identifier = identifier,
+ });
+ }
- return cpu;
+ return obj.finalize(arch);
+ }
+ };
}
-fn getCpuCount() usize {
- return std.os.windows.peb().NumberOfProcessors;
+fn genericCpu(comptime arch: Target.Cpu.Arch) Target.Cpu {
+ return .{
+ .arch = arch,
+ .model = Target.Cpu.Model.generic(arch),
+ .features = Target.Cpu.Feature.Set.empty,
+ };
}
pub fn detectNativeCpuAndFeatures() ?Target.Cpu {
- switch (builtin.cpu.arch) {
- .aarch64 => return detectNativeCpuAndFeaturesArm64(),
- else => |arch| return .{
- .arch = arch,
- .model = Target.Cpu.Model.generic(arch),
- .features = Target.Cpu.Feature.Set.empty,
+ const current_arch = builtin.cpu.arch;
+ switch (current_arch) {
+ .aarch64, .aarch64_be, .aarch64_32 => {
+ var cpu = cpu: {
+ var maybe_cpu = ArmCpuInfoParser.parse(current_arch) catch break :cpu genericCpu(current_arch);
+ break :cpu maybe_cpu orelse genericCpu(current_arch);
+ };
+
+ const Feature = Target.aarch64.Feature;
+
+ // Override any features that are either present or absent
+ if (IsProcessorFeaturePresent(PF.ARM_NEON_INSTRUCTIONS_AVAILABLE)) {
+ cpu.features.addFeature(@enumToInt(Feature.neon));
+ } else {
+ cpu.features.removeFeature(@enumToInt(Feature.neon));
+ }
+
+ if (IsProcessorFeaturePresent(PF.ARM_V8_CRC32_INSTRUCTIONS_AVAILABLE)) {
+ cpu.features.addFeature(@enumToInt(Feature.crc));
+ } else {
+ cpu.features.removeFeature(@enumToInt(Feature.crc));
+ }
+
+ if (IsProcessorFeaturePresent(PF.ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE)) {
+ cpu.features.addFeature(@enumToInt(Feature.crypto));
+ } else {
+ cpu.features.removeFeature(@enumToInt(Feature.crypto));
+ }
+
+ if (IsProcessorFeaturePresent(PF.ARM_V81_ATOMIC_INSTRUCTIONS_AVAILABLE)) {
+ cpu.features.addFeature(@enumToInt(Feature.lse));
+ } else {
+ cpu.features.removeFeature(@enumToInt(Feature.lse));
+ }
+
+ if (IsProcessorFeaturePresent(PF.ARM_V82_DP_INSTRUCTIONS_AVAILABLE)) {
+ cpu.features.addFeature(@enumToInt(Feature.dotprod));
+ } else {
+ cpu.features.removeFeature(@enumToInt(Feature.dotprod));
+ }
+
+ if (IsProcessorFeaturePresent(PF.ARM_V83_JSCVT_INSTRUCTIONS_AVAILABLE)) {
+ cpu.features.addFeature(@enumToInt(Feature.jsconv));
+ } else {
+ cpu.features.removeFeature(@enumToInt(Feature.jsconv));
+ }
+
+ return cpu;
},
+ else => {},
}
}