commit b0ab55b8ea82145aba23accdf480efe5632660fd (tree)
parent 558a5c7913434547c55355af0075a9d34db0d4bc
Author: Alex Rønne Petersen <alex@alexrp.com>
Date: Wed, 25 Mar 2026 00:51:01 +0100
Merge pull request 'Add psp os' (#31609) from IridescentRose/zig:psp-os-target into master
Reviewed-on: https://codeberg.org/ziglang/zig/pulls/31609
Reviewed-by: Andrew Kelley <andrew@ziglang.org>
Reviewed-by: Alex Rønne Petersen <alex@alexrp.com>
Diffstat:
9 files changed, 98 insertions(+), 5 deletions(-)
diff --git a/lib/std/Io/Dir.zig b/lib/std/Io/Dir.zig
@@ -52,7 +52,7 @@ pub const max_path_bytes = switch (native_os) {
/// On WASI, file name components are encoded as valid UTF-8.
/// On other platforms, `[]u8` components are an opaque sequence of bytes with no particular encoding.
pub const max_name_bytes = switch (native_os) {
- .linux, .driverkit, .ios, .maccatalyst, .macos, .tvos, .visionos, .watchos, .freebsd, .openbsd, .netbsd, .dragonfly, .illumos, .serenity => std.posix.NAME_MAX,
+ .linux, .driverkit, .ios, .maccatalyst, .macos, .tvos, .visionos, .watchos, .freebsd, .openbsd, .netbsd, .dragonfly, .illumos, .serenity, .psp => std.posix.NAME_MAX,
// Haiku's NAME_MAX includes the null terminator, so subtract one.
.haiku => std.posix.NAME_MAX - 1,
// Each WTF-16LE character may be expanded to 3 WTF-8 bytes.
diff --git a/lib/std/Target.zig b/lib/std/Target.zig
@@ -53,6 +53,7 @@ pub const Os = struct {
ps3,
ps4,
ps5,
+ psp,
vita,
emscripten,
@@ -194,6 +195,7 @@ pub const Os = struct {
.@"3ds",
+ .psp,
.vita,
.wasi,
@@ -612,6 +614,15 @@ pub const Os = struct {
},
},
+ .psp => .{
+ .semver = .{
+ // https://www.psdevwiki.com/psp/Official_Firmware_(OFW)#1.XX_Kernel
+ // It appears that the kernel started with semver for 1.XX before later changing to MAJ.MINPATCH in later releases (e.g. 3.60, 6.61)
+ .min = .{ .major = 1, .minor = 0, .patch = 3 },
+ .max = .{ .major = 6, .minor = 61, .patch = 0 },
+ },
+ },
+
.vita => .{
.semver = .{
// 1.3 is the first public release
@@ -919,6 +930,7 @@ pub const Abi = enum {
.tvos,
.visionos,
.watchos,
+ .psp,
.ps3,
.ps4,
.ps5,
@@ -2023,7 +2035,10 @@ pub const Cpu = struct {
.lanai => &lanai.cpu.v11, // clang does not have a generic lanai model.
.loongarch64 => &loongarch.cpu.la64v1_0,
.m68k => &m68k.cpu.M68000,
- .mips, .mipsel => &mips.cpu.mips32r2,
+ .mips, .mipsel => switch (os.tag) {
+ .psp => &mips.cpu.allegrex,
+ else => &mips.cpu.mips32r2,
+ },
.mips64, .mips64el => &mips.cpu.mips64r2,
.msp430 => &msp430.cpu.msp430,
.nvptx, .nvptx64 => &nvptx.cpu.sm_52,
@@ -2204,6 +2219,7 @@ pub fn requiresLibC(target: *const Target) bool {
.amdhsa,
.ps4,
.ps5,
+ .psp,
.vita,
.mesa3d,
.contiki,
@@ -2379,6 +2395,7 @@ pub const DynamicLinker = struct {
.ps3,
.ps4,
.ps5,
+ .psp,
.vita,
=> .none,
};
@@ -2783,6 +2800,7 @@ pub const DynamicLinker = struct {
.@"3ds",
+ .psp,
.vita,
.emscripten,
@@ -3338,7 +3356,7 @@ pub fn cTypeBitSize(target: *const Target, c_type: CType) u16 {
.longlong, .ulonglong, .double => return 64,
.longdouble => return 80,
},
- .vita => switch (c_type) {
+ .psp, .vita => switch (c_type) {
.char => return 8,
.short, .ushort => return 16,
.int, .uint, .float => return 32,
diff --git a/lib/std/Target/mips.zig b/lib/std/Target/mips.zig
@@ -49,6 +49,7 @@ pub const Feature = enum {
noabicalls,
nomadd4,
nooddspreg,
+ notraps,
p5600,
ptr64,
single_float,
@@ -353,6 +354,11 @@ pub const all_features = blk: {
.description = "Disable odd numbered single-precision registers",
.dependencies = featureSet(&[_]Feature{}),
};
+ result[@intFromEnum(Feature.notraps)] = .{
+ .llvm_name = null,
+ .description = "Disable trap instructions",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
result[@intFromEnum(Feature.p5600)] = .{
.llvm_name = "p5600",
.description = "The P5600 Processor",
@@ -419,6 +425,15 @@ pub const all_features = blk: {
};
pub const cpu = struct {
+ pub const allegrex: CpuModel = .{
+ .name = "allegrex",
+ .llvm_name = null,
+ .features = featureSet(&[_]Feature{
+ .mips2,
+ .notraps,
+ .single_float,
+ }),
+ };
pub const generic: CpuModel = .{
.name = "generic",
.llvm_name = "generic",
diff --git a/lib/std/heap.zig b/lib/std/heap.zig
@@ -805,6 +805,11 @@ const page_size_min_default: ?usize = switch (builtin.os.tag) {
.x86, .x86_64 => 16 << 10,
else => null,
},
+ .psp => switch (builtin.cpu.arch) {
+ // minimum block allocation by testing sceKernel
+ .mips, .mipsel => 1 << 8, // 256
+ else => null,
+ },
// system/lib/libc/musl/arch/emscripten/bits/limits.h
.emscripten => 64 << 10,
.linux => switch (builtin.cpu.arch) {
@@ -963,6 +968,11 @@ const page_size_max_default: ?usize = switch (builtin.os.tag) {
.x86, .x86_64 => 16 << 10,
else => null,
},
+ .psp => switch (builtin.cpu.arch) {
+ // minimum block allocation by testing sceKernel
+ .mips, .mipsel => 1 << 8, // 256
+ else => null,
+ },
// system/lib/libc/musl/arch/emscripten/bits/limits.h
.emscripten => 64 << 10,
.linux => switch (builtin.cpu.arch) {
diff --git a/lib/std/posix.zig b/lib/std/posix.zig
@@ -38,6 +38,22 @@ pub const system = if (use_libc)
else switch (native_os) {
.linux => linux,
.plan9 => std.os.plan9,
+ .psp => struct {
+ pub const fd_t = i32;
+ pub const pid_t = void;
+ pub const pollfd = void;
+ pub const uid_t = void;
+ pub const gid_t = void;
+ pub const mode_t = u32;
+ pub const nlink_t = u32;
+ pub const blksize_t = u32;
+ pub const ino_t = u64;
+ pub const IFNAMESIZE = {};
+ pub const SIG = void;
+
+ // https://github.com/pspdev/newlib/blob/9e0a073634ad73e8e088f2e071c55a9fe5d39709/newlib/libc/sys/psp/sys/dirent.h#L19
+ pub const NAME_MAX = 255;
+ },
else => struct {
pub const pid_t = void;
pub const pollfd = void;
diff --git a/lib/std/start.zig b/lib/std/start.zig
@@ -65,7 +65,7 @@ comptime {
// case it's not required to provide an entrypoint such as main.
if (!@hasDecl(root, start_sym_name) and @hasDecl(root, "main")) @export(&wasm_freestanding_start, .{ .name = start_sym_name });
} else switch (native_os) {
- .other, .freestanding, .@"3ds", .vita => {},
+ .other, .freestanding, .@"3ds", .psp, .vita => {},
else => if (!@hasDecl(root, start_sym_name)) @export(&_start, .{ .name = start_sym_name }),
}
}
diff --git a/src/Compilation.zig b/src/Compilation.zig
@@ -6424,6 +6424,7 @@ fn addCommonCCArgs(
.illumos => try argv.append("__illumos__"),
// Homebrew targets without LLVM support; use communities's preferred macros.
.@"3ds" => try argv.append("-D__3DS__"),
+ .psp => try argv.append("-D__PSP__"),
.vita => try argv.append("-D__vita__"),
else => {},
}
diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig
@@ -247,6 +247,7 @@ pub fn targetTriple(allocator: Allocator, target: *const std.Target) ![]const u8
.opengl,
.other,
.plan9,
+ .psp,
.vita,
=> "unknown",
};
@@ -9536,7 +9537,25 @@ pub const FuncGen = struct {
fn airTrap(self: *FuncGen, inst: Air.Inst.Index) !void {
_ = inst;
- _ = try self.wip.callIntrinsic(.normal, .none, .trap, &.{}, &.{}, "");
+ const target = self.ng.object.target;
+ if ((target.cpu.arch == .mips or target.cpu.arch == .mipsel) and
+ target.cpu.has(.mips, .notraps))
+ {
+ // Emit a MIPS `break` instruction followed by an infinite loop (to fulfill the noreturn)
+ // since this CPU does not support trap instructions.
+ const o = self.ng.object;
+ _ = try self.wip.callAsm(
+ .none,
+ try o.builder.fnType(.void, &.{}, .normal),
+ .{ .sideeffect = true },
+ try o.builder.string("break\n0:\nj 0b\nnop"),
+ try o.builder.string("~{memory}"),
+ &.{},
+ "",
+ );
+ } else {
+ _ = try self.wip.callIntrinsic(.normal, .none, .trap, &.{}, &.{}, "");
+ }
_ = try self.wip.@"unreachable"();
}
diff --git a/tools/update_cpu_features.zig b/tools/update_cpu_features.zig
@@ -1299,6 +1299,20 @@ const targets = [_]ArchTarget{
.name = "Mips",
.td_name = "Mips",
},
+ .extra_features = &.{
+ .{
+ .zig_name = "notraps",
+ .desc = "Disable trap instructions",
+ .deps = &.{},
+ },
+ },
+ .extra_cpus = &.{
+ .{
+ .llvm_name = null,
+ .zig_name = "allegrex",
+ .features = &.{ "mips2", "single_float", "notraps" },
+ },
+ },
},
.{
.zig_name = "nvptx",