Commit da9da76e3f

LemonBoy <thatlemon@gmail.com>
2021-04-27 15:46:42
stage1: Implement CPU host detection for PowerPC targets
Untested but should work well on both 32 and 64 bit systems.
1 parent 1c0259f
Changed files (1)
lib
std
zig
system
lib/std/zig/system/linux.zig
@@ -65,18 +65,91 @@ const SparcCpuinfoImpl = struct {
 const SparcCpuinfoParser = CpuinfoParser(SparcCpuinfoImpl);
 
 test "cpuinfo: SPARC" {
-    const mock_cpuinfo =
+    try testParser(SparcCpuinfoParser, &Target.sparc.cpu.niagara2,
         \\cpu             : UltraSparc T2 (Niagara2)
         \\fpu             : UltraSparc T2 integrated FPU
         \\pmu             : niagara2
         \\type            : sun4v
-    ;
+    );
+}
+
+const PowerpcCpuinfoImpl = struct {
+    model: ?*const Target.Cpu.Model = null,
+
+    const cpu_names = .{
+        .{ "604e", &Target.powerpc.cpu.@"604e" },
+        .{ "604", &Target.powerpc.cpu.@"604" },
+        .{ "7400", &Target.powerpc.cpu.@"7400" },
+        .{ "7410", &Target.powerpc.cpu.@"7400" },
+        .{ "7447", &Target.powerpc.cpu.@"7400" },
+        .{ "7455", &Target.powerpc.cpu.@"7450" },
+        .{ "G4", &Target.powerpc.cpu.@"g4" },
+        .{ "POWER4", &Target.powerpc.cpu.@"970" },
+        .{ "PPC970FX", &Target.powerpc.cpu.@"970" },
+        .{ "PPC970MP", &Target.powerpc.cpu.@"970" },
+        .{ "G5", &Target.powerpc.cpu.@"g5" },
+        .{ "POWER5", &Target.powerpc.cpu.@"g5" },
+        .{ "A2", &Target.powerpc.cpu.@"a2" },
+        .{ "POWER6", &Target.powerpc.cpu.@"pwr6" },
+        .{ "POWER7", &Target.powerpc.cpu.@"pwr7" },
+        .{ "POWER8", &Target.powerpc.cpu.@"pwr8" },
+        .{ "POWER8E", &Target.powerpc.cpu.@"pwr8" },
+        .{ "POWER8NVL", &Target.powerpc.cpu.@"pwr8" },
+        .{ "POWER9", &Target.powerpc.cpu.@"pwr9" },
+        .{ "POWER10", &Target.powerpc.cpu.@"pwr10" },
+    };
+
+    fn line_hook(self: *PowerpcCpuinfoImpl, key: []const u8, value: []const u8) !bool {
+        if (mem.eql(u8, key, "cpu")) {
+            // The model name is often followed by a comma or space and extra
+            // info.
+            inline for (cpu_names) |pair| {
+                const end_index = mem.indexOfAny(u8, value, ", ") orelse value.len;
+                if (mem.eql(u8, value[0..end_index], pair[0])) {
+                    self.model = pair[1];
+                    break;
+                }
+            }
+
+            // Stop the detection once we've seen the first core.
+            return false;
+        }
+
+        return true;
+    }
+
+    fn finalize(self: *const PowerpcCpuinfoImpl, arch: Target.Cpu.Arch) ?Target.Cpu {
+        const model = self.model orelse Target.Cpu.Model.generic(arch);
+        return Target.Cpu{
+            .arch = arch,
+            .model = model,
+            .features = model.features,
+        };
+    }
+};
 
-    var fbs = io.fixedBufferStream(mock_cpuinfo);
+const PowerpcCpuinfoParser = CpuinfoParser(PowerpcCpuinfoImpl);
+
+test "cpuinfo: PowerPC" {
+    try testParser(PowerpcCpuinfoParser, &Target.powerpc.cpu.@"970",
+        \\processor	: 0
+        \\cpu		: PPC970MP, altivec supported
+        \\clock		: 1250.000000MHz
+        \\revision	: 1.1 (pvr 0044 0101)
+    );
+    try testParser(PowerpcCpuinfoParser, &Target.powerpc.cpu.pwr8,
+        \\processor	: 0
+        \\cpu		: POWER8 (raw), altivec supported
+        \\clock		: 2926.000000MHz
+        \\revision	: 2.0 (pvr 004d 0200)
+    );
+}
 
-    const r = SparcCpuinfoParser.parse(.sparcv9, fbs.reader()) catch unreachable;
-    testing.expectEqual(&Target.sparc.cpu.niagara2, r.?.model);
-    testing.expect(Target.sparc.cpu.niagara2.features.eql(r.?.features));
+fn testParser(parser: anytype, expected_model: *const Target.Cpu.Model, input: []const u8) !void {
+    var fbs = io.fixedBufferStream(input);
+    const result = try parser.parse(.powerpc, fbs.reader());
+    testing.expectEqual(expected_model, result.?.model);
+    testing.expect(expected_model.features.eql(result.?.features));
 }
 
 // The generic implementation of a /proc/cpuinfo parser.
@@ -111,8 +184,14 @@ pub fn detectNativeCpuAndFeatures() ?Target.Cpu {
     };
     defer f.close();
 
-    switch (std.Target.current.cpu.arch) {
-        .sparcv9 => return SparcCpuinfoParser.parse(.sparcv9, f.reader()) catch null,
+    const current_arch = std.Target.current.cpu.arch;
+    switch (current_arch) {
+        .sparcv9 => {
+            return SparcCpuinfoParser.parse(current_arch, f.reader()) catch null;
+        },
+        .powerpc, .powerpcle, .powerpc64, .powerpc64le => {
+            return PowerpcCpuinfoParser.parse(current_arch, f.reader()) catch null;
+        },
         else => {},
     }