diff --git a/lib/std/zig/system/linux.zig b/lib/std/zig/system/linux.zig index ce802df7a8..dc0d3c7f6a 100644 --- a/lib/std/zig/system/linux.zig +++ b/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 - ; + ); +} - var fbs = io.fixedBufferStream(mock_cpuinfo); +const PowerpcCpuinfoImpl = struct { + model: ?*const Target.Cpu.Model = null, - 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)); + 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, + }; + } +}; + +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) + ); +} + +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 => {}, }