stage1: Implement CPU host detection for PowerPC targets

Untested but should work well on both 32 and 64 bit systems.
This commit is contained in:
LemonBoy 2021-04-27 15:46:42 +02:00 committed by Andrew Kelley
parent 1c0259f11e
commit da9da76e3f

View File

@ -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 => {},
}