This is a syscall implementation and (only slightly modified) linker script for use with Newlib on the Sony PlayStation. Newlib is a portable libc/stdlib implementation that doesn't require a Linux or BSD kernel like most libc's, and is complete and standards-compliant unlike a custom libc.
The PlayStation includes a BIOS ROM that has a number of system support functions, which we use to implement device-specific system calls. However, it additionally includes a few libc functions itself that do not interact with peripherals. As such, Newlib can either be used for all libc functions except as necessary to interact with hardware, or Newlib can be patched to use BIOS routines whereever possible. The second option may run slower in some cases but will result in a smaller executable. Patching newlib is also required if you set any exception handlers, link with the legacy PsyQ libraries (which set exception handlers), or debug with the pcsx-redux emulator.
Download a pre-compiled bundle from the releases page and install it into your existing MIPSEL prefix. Make sure to use -nodefaultlibs -Tpsx.ld in the linker flags, or if using another linker script, add -lpsxsys manually.
-
Copy
psx.candpsx.ldtolibgloss/mips/. -
Add them to
libgloss/mips/Makefile.in, for example with:PSXOBJS = psx.o syscalls.o getpid.o kill.o putnum.o libpsxsys.a: $(PSXOBJS) ${AR} ${ARFLAGS} $@ $(PSXOBJS) ${RANLIB} $@
Then continue with "Configuring and compiling Newlib" below.
- Copy
psx.c,psx.ld,psx-bonus.c, andpsx-printf.Stolibgloss/mips/. - In the top-level Newlib source, run
patch -p1 <psx.patch(using the full path ofpsx.patch).
Then continue with "Configuring and compiling Newlib" below.
- Configure Newlib with these flags:
--target=mipsel-elf: Required for the platform. Themipsel-unknown-elftriple is sometimes recommended in other tutorials, but it does the same thing.CFLAGS(orCFLAGS_FOR_TARGETfor a unified build) set to:-DHAVE_BLKSIZE: Required. PSX file I/O can only be done in block units, so this tells Newlib to enable "optimizations" that transform FS calls to block alignment.-g -O2: From the default configuration.-DHAVE_RENAME: Not required, but you'll need to remove_renamefrompsx.cif you don't add the flag.
--prefix=/usr/local/psxsdkor whatever. Optional but recommended to keep your host system root clean.--disable-multilib: Optional, but recommended to keep the prefix clean. Disables building extra, unnecessary big-endian and hard-float versions of target libraries.--enable-lto: Optional but recommended. Enables link-time-optimization, building intermediate code so that optimizations can be performed all at once during linking.--disable-libssp: Optional. Disables support for stack protection.--disable-libstdcxx: Optional. Disables support for GNU libstdc++-v3.--disable-newlib-hw-fp: Optional. Enforces disabling hard-float support.--disable-newlib-io-float: Optional. Disables floating point in format strings.--disable-newlib-multithread: Optional. Disables threading support.--disable-shared: Optional. Do not build shared libraries.--enable-lite-exit: Optional. Console games don't typically exit, so why spend time there?--enable-newlib-nano-malloc: Optional. Enables an alternativemallocimplementation, "which is for small systems with very limited memory."
For example, here's my full configure line, using a "unified" build alongside binutils and GCC:
../configure --prefix=/usr/local/psxsdk --target=mipsel-elf \
--disable-gcov \
--disable-libssp \
--disable-libstdcxx \
--disable-multilib \
--disable-newlib-hw-fp \
--disable-newlib-io-float \
--disable-newlib-multithread \
--disable-nls \
--disable-shared \
--enable-gold \
--enable-languages=c,c++ \
--enable-lite-exit \
--enable-lto \
--enable-serial-configure \
--with-float=soft \
--with-isl \
--with-newlib \
--with-no-pic \
CFLAGS_FOR_TARGET="-g -O2 -DHAVE_BLKSIZE -DHAVE_RENAME"
Then make and make install as usual. Add the new prefix to your PATH if necessary, then you can use mipsel-elf-gcc with -flto -msoft-float -march=r3000 to build things, and mipsel-elf-gcc-ld with -nodefaultlibs -Tpsx.ld to link things.
environgetpidkill
assertgetenv,_getenv_rraise,_raise_rtmpfile,tmpfile_rtmpfile64,_tmpfile64_rtmpnam,tempnam,_tmpnam_r,_tempnam_r
gettimeofdaylink
_gettimeofday_r_link_rtime
dup2execveexecvpefcntlforkfstat64lseek64mkdiropen64pipesched_setparamsched_setschedulersetegidseteuidsetpgidsigactionsigprocmasksymlinktimesvforkwaitwaitpid
Library functions affected by unimplemented OS subroutines (programs that use these will fail to link)
_execve_r_fcntl_r_fork_r_fstat64_r_lseek64_r_mkdir_r_open64_r_times_r_wait_rclockfopen64,_fopen64_rfreopen64,_freopen64_rfseeko64,_fsseko64_rfsetpos64,_fsetpos64_rmktemp,mkdtemp,mkstemp,mkstemps,mkostemp,mkostemps,_mktemp_r,_mkdtemp_r,_mkstemp_r,_mkstemps_r,_mkostemp_r,_mkostemps_rpopen,pcloseposix_spawn,posix_spawnppread64pwrite64system,_system_rtmpfile64,_tmpfile64_r
- Make a custom, slimmer
crt0.s. The built-in one is great, but 1) supplies_exit, which could be done as a syscall, and 2) zeroes.bssand does some other system initialization that the BIOS boot sequence already does. - Pass
argvto main. Syscall A(0x43) passes parameters tor4andr5, presumably argc and argv (though they are 0 and null for the boot executable) - The boot executable copies some of
system.cnfto 0x180—could this be used for environment? - Add syscall versions of malloc and memset.
- Consider
-O2vs-Osvs-O3.
- Adrian Siekierka for candyk, which helped me figure out some of the configure flags
- Nicolas Noble for Openbios, which helped me figure out how some of the BIOS calls work, and also how to do them inline in C
- Nocash for the PSX Specifications
- NextVolume and Lameguy64 for their existing PS1 SDKs