| ... | @@ -347,6 +347,114 @@ const m68k = struct { | ... | @@ -347,6 +347,114 @@ const m68k = struct { |
| 347 | } | 347 | } |
| 348 | }; | 348 | }; |
| 349 | | 349 | |
| | 350 | const mips = struct { |
| | 351 | const cpuinfo = struct { |
| | 352 | const Impl = struct { |
| | 353 | model: ?*const Target.Cpu.Model = null, |
| | 354 | |
| | 355 | const cpu_names = .{ |
| | 356 | .{ "Cavium Octeon III", &Target.mips.cpu.@"octeon+" }, |
| | 357 | .{ "Cavium Octeon II", &Target.mips.cpu.@"octeon+" }, |
| | 358 | .{ "Cavium Octeon+", &Target.mips.cpu.@"octeon+" }, |
| | 359 | .{ "Cavium Octeon", &Target.mips.cpu.octeon }, |
| | 360 | .{ "MIPS I6400", &Target.mips.cpu.i6400 }, |
| | 361 | .{ "MIPS I6500", &Target.mips.cpu.i6500 }, |
| | 362 | .{ "MIPS P5600", &Target.mips.cpu.p5600 }, |
| | 363 | .{ "R3000A", &Target.mips.cpu.r3000a }, |
| | 364 | }; |
| | 365 | |
| | 366 | const isa_names = .{ |
| | 367 | .{ "mips64r6", &Target.mips.cpu.mips64r6 }, |
| | 368 | .{ "mips64r5", &Target.mips.cpu.mips64r5 }, |
| | 369 | .{ "mips64r2", &Target.mips.cpu.mips64r2 }, |
| | 370 | .{ "mips64r1", &Target.mips.cpu.mips64 }, |
| | 371 | .{ "mips32r6", &Target.mips.cpu.mips32r6 }, |
| | 372 | .{ "mips32r5", &Target.mips.cpu.mips32r5 }, |
| | 373 | .{ "mips32r2", &Target.mips.cpu.mips32r2 }, |
| | 374 | .{ "mips32r1", &Target.mips.cpu.mips32 }, |
| | 375 | .{ "mips5", &Target.mips.cpu.mips5 }, |
| | 376 | .{ "mips4", &Target.mips.cpu.mips4 }, |
| | 377 | .{ "mips3", &Target.mips.cpu.mips3 }, |
| | 378 | .{ "mips2", &Target.mips.cpu.mips2 }, |
| | 379 | .{ "mips1", &Target.mips.cpu.mips1 }, |
| | 380 | }; |
| | 381 | |
| | 382 | fn lineHook(self: *Impl, key: []const u8, value: []const u8) !bool { |
| | 383 | // The `cpu model` line always comes before `isa`, which is perfect for us since we |
| | 384 | // want the explicit model to take precedence over the generic ISA identifier. |
| | 385 | if (mem.eql(u8, key, "cpu model")) { |
| | 386 | inline for (cpu_names) |pair| { |
| | 387 | if (mem.find(u8, value, pair[0]) != null) { |
| | 388 | self.model = pair[1]; |
| | 389 | return false; |
| | 390 | } |
| | 391 | } |
| | 392 | } else if (mem.eql(u8, key, "isa")) { |
| | 393 | inline for (isa_names) |pair| { |
| | 394 | if (mem.find(u8, value, pair[0]) != null) { |
| | 395 | self.model = pair[1]; |
| | 396 | break; |
| | 397 | } |
| | 398 | } |
| | 399 | |
| | 400 | // If we haven't found anything useful by here, we we may as well stop. |
| | 401 | return false; |
| | 402 | } |
| | 403 | |
| | 404 | return true; |
| | 405 | } |
| | 406 | |
| | 407 | fn finalize(self: *const Impl, arch: Target.Cpu.Arch) ?Target.Cpu { |
| | 408 | const model = self.model orelse return null; |
| | 409 | return .{ |
| | 410 | .arch = arch, |
| | 411 | .model = model, |
| | 412 | .features = model.features, |
| | 413 | }; |
| | 414 | } |
| | 415 | }; |
| | 416 | |
| | 417 | const Parser = CpuinfoParser(Impl); |
| | 418 | }; |
| | 419 | |
| | 420 | test cpuinfo { |
| | 421 | try testParser(cpuinfo.Parser, .mips64, &Target.mips.cpu.@"octeon+", |
| | 422 | \\system type : UBNT_E300 |
| | 423 | \\machine : Unknown |
| | 424 | \\processor : 0 |
| | 425 | \\cpu model : Cavium Octeon III V0.2 FPU V0.0 |
| | 426 | \\BogoMIPS : 2000.00 |
| | 427 | \\wait instruction : yes |
| | 428 | \\microsecond timers : yes |
| | 429 | \\tlb_entries : 256 |
| | 430 | \\extra interrupt vector : yes |
| | 431 | \\hardware watchpoint : yes, count: 2, address/irw mask: [0x0ffc, 0x0ffb] |
| | 432 | \\isa : mips1 mips2 mips3 mips4 mips5 mips64r2 |
| | 433 | \\ASEs implemented : vz |
| | 434 | \\shadow register sets : 1 |
| | 435 | \\kscratch registers : 4 |
| | 436 | \\package : 0 |
| | 437 | \\core : 0 |
| | 438 | \\VCED exceptions : not available |
| | 439 | \\VCEI exceptions : not available |
| | 440 | ); |
| | 441 | } |
| | 442 | |
| | 443 | pub fn detectNativeCpu(io: Io, arch: Target.Cpu.Arch) ?Target.Cpu { |
| | 444 | var file = Io.Dir.openFileAbsolute(io, "/proc/cpuinfo", .{}) catch return null; |
| | 445 | defer file.close(io); |
| | 446 | |
| | 447 | var buffer: [4096]u8 = undefined; |
| | 448 | var file_reader = file.reader(io, &buffer); |
| | 449 | |
| | 450 | var cpu = (cpuinfo.Parser.parse(arch, &file_reader.interface) catch null) orelse return null; |
| | 451 | |
| | 452 | cpu.features.populateDependencies(cpu.arch.allFeaturesList()); |
| | 453 | |
| | 454 | return cpu; |
| | 455 | } |
| | 456 | }; |
| | 457 | |
| 350 | const powerpc = struct { | 458 | const powerpc = struct { |
| 351 | const cpuinfo = struct { | 459 | const cpuinfo = struct { |
| 352 | const Impl = struct { | 460 | const Impl = struct { |
| ... | @@ -874,6 +982,7 @@ pub fn detectNativeCpuAndFeatures(io: Io) ?Target.Cpu { | ... | @@ -874,6 +982,7 @@ pub fn detectNativeCpuAndFeatures(io: Io) ?Target.Cpu { |
| 874 | .arm, .armeb, .thumb, .thumbeb => arm.detectNativeCpu(io, current_arch), | 982 | .arm, .armeb, .thumb, .thumbeb => arm.detectNativeCpu(io, current_arch), |
| 875 | .csky => csky.detectNativeCpu(io, current_arch), | 983 | .csky => csky.detectNativeCpu(io, current_arch), |
| 876 | .m68k => m68k.detectNativeCpu(io, current_arch), | 984 | .m68k => m68k.detectNativeCpu(io, current_arch), |
| | 985 | .mips, .mipsel, .mips64, .mips64el => mips.detectNativeCpu(io, current_arch), |
| 877 | .powerpc, .powerpcle, .powerpc64, .powerpc64le => powerpc.detectNativeCpu(io, current_arch), | 986 | .powerpc, .powerpcle, .powerpc64, .powerpc64le => powerpc.detectNativeCpu(io, current_arch), |
| 878 | .riscv64, .riscv32 => riscv.detectNativeCpuAndFeatures(io, current_arch), | 987 | .riscv64, .riscv32 => riscv.detectNativeCpuAndFeatures(io, current_arch), |
| 879 | .s390x => s390x.detectNativeCpu(io, current_arch), | 988 | .s390x => s390x.detectNativeCpu(io, current_arch), |