Syscalls
Performing a syscall is quite simple:
; set syscall code:
addi a7, zero, 93 ; or SCALL_EXIT if syscall symbols are mapped
; set syscall args:
addi a0, zero, 1 ; exit with code 1
; invode syscall handler
scall
The global symbols (e.g. SCALL_READ) are loaded by default. If you specify the option no_syscall_symbols, they will be omitted.
Read (63) SCALL_READ
a0: source file descriptora1: addr at which to write the inputa2: number of bytes to read (at most)return in a0: number of bytes read or -1
Write (64) SCALL_WRITE
a0: target file descriptora1: addr at which the data to be written is locateda2: number of bytes to writereturn in a0: number of bytes written or -1
Exit (93) SCALL_EXIT
a0: exit code
Open (1024) SCALL_OPEN
a0: open mode:0: read1: write (truncate)2: read/write (no truncate)3: only create4: append
a1: addr where path is storeda2: length of pathreturn in a0: file descriptor of opened file or -1
Requires flag --scall-fs to be set to True
Close (1025) SCALL_CLOSE
a0: file descriptor to closereturn in a0: 0 if closed correctly or -1
Extending these syscalls
You can implement your own syscall by adding its code to the SYSCALLS dict in the riscemu/syscalls.py file, creating a mapping of a syscall code to a name, and then implementing that syscall name in the SyscallInterface class further down that same file. Each syscall method should have the same signature: read(self, scall: Syscall). The Syscall object gives you access to the cpu, through which you can access registers and memory. You can look at the read or write syscalls for further examples.