Adds target information for the PSP OS and minimal profile in std.posix to build a functional std.Io vtable.
Add psp os #31609
IridescentRose/zig:psp-os-target into master 650e48b51e
fdf19984b8
Nice!
@ -2025,2 +2035,3 @@
.m68k=>&m68k.cpu.M68000,
.mips,.mipsel=>&mips.cpu.mips32r2,
.mips,.mipsel=>switch(os.tag){
.psp=>&mips.cpu.mips2,// mips2 with some custom instructions, no trap instructions
"no trap instructions" should be reflected in mips target CPU features and then another CPU model can be added which has this feature enabled.
file to edit is tools/update_cpu_features.zig
Thanks, I was able to modify this and re-ran the tool
Looks good. This will enable codegen backends to prevent traps from being emitted.
What should @trap() do then, when targeting this system?
On this system in general, traps should instead be converted to breaks, as that's what the allegrex custom GCC does, which allows someone using the psp debugger to catch it rather than an illegal instruction exception.
ok perfect. now that you added that cpu feature, the llvm backend can be adjusted to lower @trap() into break instruction instead.
edit: actually probably break followed by infinite loop because @trap() is no-return.
Working:
PSPLink debug output:
Load/Start host0:/app.prx UID: 0x04398213 Name: SDK Hello World
host0:/> Exception - Breakpoint
Thread ID - 0x04371F1F
Th Name - zig_user_main
Module ID - 0x04398213
Mod Name - SDK Hello World
EPC - 0x0882651C
Cause - 0x10000024
BadVAddr - 0x8E8DA9C9
Status - 0x40088613
Address - 0x0002251C
zr:0x00000000 at:0x00000000 v0:0x0000000F v1:0x00000000
a0:0x0BEBFE14 a1:0x00000070 a2:0x00000000 a3:0x00000021
t0:0xDEADBEEF t1:0xDEADBEEF t2:0xDEADBEEF t3:0xDEADBEEF
t4:0xDEADBEEF t5:0xDEADBEEF t6:0xDEADBEEF t7:0xDEADBEEF
s0:0xDEADBEEF s1:0xDEADBEEF s2:0xDEADBEEF s3:0xDEADBEEF
s4:0xDEADBEEF s5:0xDEADBEEF s6:0xDEADBEEF s7:0xDEADBEEF
t8:0xDEADBEEF t9:0xDEADBEEF k0:0x0BEBFF00 k1:0x00000000
gp:0x088B1540 sp:0x0BEBFD58 fp:0x0BEBFD58 ra:0x0882651C
0x0882651C: 0x0000000D '....' - break 0x0
disasm 0x0882651C 3
0x0882651C: 0x0000000D '....' - break 0x0
0x08826520: 0x0A209948 'H. .' - j 0x08826520
0x08826524: 0x00000000 '....' - nop
@ -615,0 +617,4 @@
.psp=>.{
.semver=.{
.min=.{.major=1,.minor=0,.patch=0},
.max=.{.major=6,.minor=61,.patch=0},
Where are these sourced from?
https://www.psdevwiki.com/psp/Official_Firmware_(OFW)#1.00_(1.0.3)
6.61 is the last public version of firmware
1.00 is the first public version by name although it says 1.03 internally. I went with the more obvious 1.00 but glad to change or add a source in code.
@IridescentRose wrote in #31609 (comment):
1.00 is the first public version by name although it says 1.03 internally. I went with the more obvious 1.00 but glad to change or add a source in code.
I think we should use whichever numbers the actual software uses.
Alright, will change to 1.03 as I would assume that to be the version in software
Updated
@ -6420,6 +6420,7 @@ fn addCommonCCArgs(
.illumos=>tryargv.append("__illumos__"),
// Homebrew targets without LLVM support; use communities's preferred macros.
.@"3ds"=>tryargv.append("-D__3DS__"),
.psp=>tryargv.append("-D__PSP__"),
Does an existing compiler define this?
Yes: https://github.com/pspdev/pspsdk/blob/master/src/base/pspdev.cmake#L33
There's actually another one I could add to this too, but I believe __PSP__ is more common in the community
Definitely let's not perpetuate usage of macros like PSP. __PSP__ is reasonable.
@ -806,2 +806,4 @@
else=>null,
},
.psp=>switch(builtin.cpu.arch){
// minimum block allocation by testing sceKernel
Can you elaborate a bit on what this means? Is this really related to pages?
When allocating using the sceKernel API, the system must call sceKernelAllocPartitionMemory() which allocates a memory block from either the userspace or kernelspace partition.
The minimum size of a block is always 256 bytes, and the size of any block allocated rounds up to the nearest 256 bytes.
The PSP may not have pages in the exact sense since it lacks a sophisticated MMU. However, not including an entry here leads to compilation errors on the PSP target.
I don't think "page size" is a meaningful concept when there is no MMU in effect.
@IridescentRose wrote in #31609 (comment):
The PSP may not have pages in the exact sense since it lacks a sophisticated MMU. However, not including an entry here leads to compilation errors on the PSP target.
Which errors?
The root of this error is that the MemoryMap.zig file references []align(std.heap.page_size_min) u8 which is a struct referenced by Io which when providing a minimal IO implementation (even though this function is @panic("Unimplemented")) triggers an error at comptime.
/home/n/zig/build/stage3/lib/zig/std/heap.zig:48:97: error: mipsel-psp has unknown page_size_min; populate std.options.page_size_min
pub const page_size_min: usize = std.options.page_size_min orelse (page_size_min_default orelse @compileError(@tagName(builtin.cpu.arch) ++ "-" ++ @tagName(builtin.os.tag) ++ " has unknown page_size_min; populate std.options.page_size_min"));
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
referenced by:
Io.File.MemoryMap: /home/n/zig/build/stage3/lib/zig/std/Io/File/MemoryMap.zig:18:25
fileMemoryMapCreate: src/utils/Io.zig:1012:108
vtable: src/utils/Io.zig:97:28
psp_io: src/utils/Io.zig:25:16
_module_main_thread: src/utils/module.zig:51:21
module_start: src/utils/module.zig:254:67
module_start: src/utils/module.zig:252:5
module: src/pspsdk.zig:878:32
comptime: examples/network.zig:35:26
root: /home/n/zig/build/stage3/lib/zig/std/start.zig:13:22
3 reference(s) hidden; use '-freference-trace=13' to see all references
That's a bit unfortunate.
I wonder if this could tie into #31235 somehow? cc @GasInfinity
If there is / will be a better solution I have ways to hack around this until there's a better solution and could remove the offending code from this PR.
I think 256 is a good value for this.
@alexrp wrote in #31609 (comment):
That's a bit unfortunate.
I wonder if this could tie into #31235 somehow? cc @GasInfinity
It would still have to be overridden with the PR, instead of living in std it would live in whatever package exposes std_os_options.
I agree with andrew that 256 is a good value as even if it doesn't have an MMU, a lot of code would still expect page_size to be available.
I had a chat with @mlugg about this. We agreed that 256 is okay as a value here. However, we also agreed that, both as a result of this change and how these constants are already used in practice, "page size" is a poor name for them, and the doc comments also aren't great.
My contention is basically that pages have to do with virtual memory, and the value being introduced here has nothing to do with pages because there's no MMU. Matthew pointed out that what we really care about at the end of the day is the system's granularity of mmap (or the OS's equivalent allocation function) regardless of whether that function actually works with pages in the hardware sense. We really only use the term "page size" because we've inherited it from the POSIX era of systems, but there's no hard rule saying that the granularity of mmap (or the OS equivalent) should have any connection to the page size that the underlying MMU is configured for; an OS could present the illusion of 8k "pages" on a 4k MMU, for example.
Matthew suggested mmap_align_min/mmap_align_max/mmapAlign(), and for the constants to be typed as std.mem.Alignment to encode the power-of-two requirement (and the fact that they really are alignment values).
I'll file a follow-up issue for this. Edit: #31652
@trap()
@IridescentRose was it intentional that psp wasn't added here?
.freestanding,.other,.@"3ds",.vita=>{Not intentional, however we do provide a panic handler in Zig-PSP that is recommended as a default.
No due date set.
No dependencies set.
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?