boot2

Playing with the boostrap
git clone https://git.ryansepassi.com/git/boot2.git
Log | Files | Refs | README

commit 449415dd6cf00410a4542f3db9582f163b7e7b59
parent 6853e7a46ad4a95dbab4acfb6b36a256d5aef466
Author: Ryan Sepassi <rsepassi@gmail.com>
Date:   Wed, 29 Apr 2026 11:03:14 -0700

P1: new syscalls lseek, brk, unlinkat

Diffstat:
MP1/P1-aarch64.M1pp | 9+++++++++
MP1/P1-amd64.M1pp | 9+++++++++
MP1/P1-riscv64.M1pp | 9+++++++++
MP1/P1.M1pp | 12++++++++++++
MP1/P1pp.P1pp | 26++++++++++++++++++++++++++
Atests/P1/sys_calls.P1pp | 125+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Atests/P1/sys_calls.expected | 1+
7 files changed, 191 insertions(+), 0 deletions(-)

diff --git a/P1/P1-aarch64.M1pp b/P1/P1-aarch64.M1pp @@ -564,3 +564,12 @@ $(imm) %macro p1_sys_waitid() 95 %endm +%macro p1_sys_lseek() +62 +%endm +%macro p1_sys_brk() +214 +%endm +%macro p1_sys_unlinkat() +35 +%endm diff --git a/P1/P1-amd64.M1pp b/P1/P1-amd64.M1pp @@ -918,3 +918,12 @@ $(imm) %macro p1_sys_waitid() 247 %endm +%macro p1_sys_lseek() +8 +%endm +%macro p1_sys_brk() +12 +%endm +%macro p1_sys_unlinkat() +263 +%endm diff --git a/P1/P1-riscv64.M1pp b/P1/P1-riscv64.M1pp @@ -545,3 +545,12 @@ $(imm) %macro p1_sys_waitid() 95 %endm +%macro p1_sys_lseek() +62 +%endm +%macro p1_sys_brk() +214 +%endm +%macro p1_sys_unlinkat() +35 +%endm diff --git a/P1/P1.M1pp b/P1/P1.M1pp @@ -244,6 +244,18 @@ target %p1_sys_waitid %endm +%macro sys_lseek() +%p1_sys_lseek +%endm + +%macro sys_brk() +%p1_sys_brk +%endm + +%macro sys_unlinkat() +%p1_sys_unlinkat +%endm + # ---- Program entry -------------------------------------------------------- # # The portable P1 program-entry model emits a backend-specific `:_start` diff --git a/P1/P1pp.P1pp b/P1/P1pp.P1pp @@ -1018,6 +1018,32 @@ %syscall %ret +# sys_lseek(fd=a0, off=a1, whence=a2) -> off (a0) +:sys_lseek + %mov(a3, a2) + %mov(a2, a1) + %mov(a1, a0) + %li(a0, %p1_sys_lseek) + %syscall + %ret + +# sys_brk(addr=a0) -> new_break (a0). addr=0 returns the current break. +:sys_brk + %mov(a1, a0) + %li(a0, %p1_sys_brk) + %syscall + %ret + +# sys_unlink(path=a0) -> 0 / -errno (a0). +# Implemented as unlinkat(AT_FDCWD, path, 0). AT_FDCWD = -100. +:sys_unlink + %li(a3, 0) + %mov(a2, a0) + %li(a1, -100) + %li(a0, %p1_sys_unlinkat) + %syscall + %ret + # sys_exit(code=a0) -> never returns :sys_exit %scope sys_exit diff --git a/tests/P1/sys_calls.P1pp b/tests/P1/sys_calls.P1pp @@ -0,0 +1,125 @@ +# tests/p1/sys_calls.P1 — exercise the sys_brk/sys_lseek/sys_unlink wrappers +# added to P1pp.P1pp alongside sys_open/sys_read/sys_write/sys_close. +# +# Sequence: +# 1. sys_brk(0) — fetch current break; succeed if > 0. +# 2. sys_open(/tmp/...) — create+truncate, write "X", close. +# 3. reopen RDONLY — sys_lseek(0, SEEK_SET) then sys_read 1 byte; +# verify the byte is 'X'; close. +# 4. sys_unlink — remove the temp file. +# Each successful step prints one byte ("B", "L", "U") so the .expected +# is a fixed `BLU` line. + +:p1_main + %enter(0) + + # --- sys_brk ----------------------------------------------------------- + %li(a0, 0) + %call(&sys_brk) + %bltz(a0, &::fail) + %beqz(a0, &::fail) + %la(a0, &b_msg) + %li(a1, 1) + %call(&write_stdout) + %bltz(a0, &::fail) + + # --- create + write "X" ------------------------------------------------ + %la(a0, &fname) + %li(a1, 577) # O_WRONLY|O_CREAT|O_TRUNC + %li(a2, 0644) + %call(&sys_open) + %bltz(a0, &::fail) + %mov(s0, a0) # save fd + + %mov(a0, s0) + %la(a1, &payload) + %li(a2, 1) + %call(&sys_write) + %bltz(a0, &::fail) + + %mov(a0, s0) + %call(&sys_close) + %bltz(a0, &::fail) + + # --- reopen, lseek, read, verify, close -------------------------------- + %la(a0, &fname) + %li(a1, 0) # O_RDONLY + %li(a2, 0) + %call(&sys_open) + %bltz(a0, &::fail) + %mov(s0, a0) + + %mov(a0, s0) + %li(a1, 0) + %li(a2, 0) # SEEK_SET + %call(&sys_lseek) + %bltz(a0, &::fail) + + %mov(a0, s0) + %la(a1, &readbuf) + %li(a2, 1) + %call(&sys_read) + %bltz(a0, &::fail) + + %mov(a0, s0) + %call(&sys_close) + %bltz(a0, &::fail) + + %la(s1, &readbuf) + %lb(s1, s1, 0) + %li(t0, 88) # 'X' + %bne(s1, t0, &::fail) + + %la(a0, &l_msg) + %li(a1, 1) + %call(&write_stdout) + %bltz(a0, &::fail) + + # --- sys_unlink -------------------------------------------------------- + %la(a0, &fname) + %call(&sys_unlink) + %bltz(a0, &::fail) + + %la(a0, &u_msg) + %li(a1, 2) + %call(&write_stdout) + %bltz(a0, &::fail) + + %li(a0, 0) + %eret + + ::fail + %li(a0, 1) + %eret + +# write_stdout(buf=a0, len=a1) -> n_or_err (a0). Single-shot syscall. +:write_stdout + %enter(0) + %mov(a3, a1) + %mov(a2, a0) + %li(a1, 1) + %li(a0, %sys_write) + %syscall + %eret + +:fname +"/tmp/p1-sys-calls.tmp" +%(0) + +:payload +"X" + +:b_msg +"B" + +:l_msg +"L" + +:u_msg +"U +" + +:readbuf +%(0) + +:ELF_end diff --git a/tests/P1/sys_calls.expected b/tests/P1/sys_calls.expected @@ -0,0 +1 @@ +BLU