#pragma once #include "../jabyengine_defines.hpp" /* R0 zr Constant Zero R1 at Reserved for the assembler R2-R3 v0-v1 Values for results and expression evaluation R4-R7 a0-a3 Arguments R8-R15 t0-t7 Temporaries (not preserved across call) R16-R23 s0-s7 Saved (preserved across call) R24-R25 t8-t9 More temporaries (not preserved across call) R26-R27 k0-k1 Reserved for OS Kernel R28 gp Global Pointer R29 sp Stack Pointer R30 fp Frame Pointer R31 ra Return address (set by function call) */ namespace JabyEngine { namespace BIOS { struct Version { enum Type { Unkown, Devboard, PS1, PS2, PS3, PSCompatible, // internal usage only No$psx, XEBRA }; struct { uint8_t day; uint8_t month; uint16_t year; } date; Type type; const char* kernel_maker; const char* version_str; const char* gui_version; const char* copyright; }; extern const Version version; } struct TCB { uint32_t status; uint32_t unused; uint32_t reg[32]; uint32_t epc; uint32_t hi; uint32_t lo; uint32_t sr; uint32_t cause; uint32_t unused2[9]; }; struct PCB { TCB* current_tcb; }; struct ToT { using ExCB = void; using EvCB = void; using FCB = void; ExCB* exception_chain; uint32_t exception_chain_size; PCB* processes; uint32_t processes_size; TCB* threads; uint32_t threads_size; uint32_t reserved_0; uint32_t reserved_1; EvCB* events; uint32_t events_size; uint32_t reserved_2; uint32_t reserved_3; uint32_t reserved_4; uint32_t reserved_5; uint32_t reserved_6; uint32_t reserved_7; FCB* files; uint32_t files_size; uint32_t reserved_8; uint32_t reserved_9; }; extern ToT table_of_tables; namespace SysCall { static constexpr const uint32_t Table_A = 0xA0; static constexpr const uint32_t Table_B = 0xB0; static constexpr const uint32_t Table_C = 0xC0; enum struct Priority { CdromDmaIrq = 0, CdromIoIrq = 0, SyscallException = 0, CardSpecificIrq = 1, VblankIrq = 1, Timer2Irq = 1, Timer1Irq = 1, Timer0Irq = 1, PadCardIrq = 2, DefInt = 3 }; enum InterruptVerifierResult { SkipHandler = 0, ExecuteHandler = 1 }; typedef InterruptVerifierResult (*InterruptVerifier)(); typedef uint32_t (*InterruptHandler)(uint32_t); using ThreadHandle = uint32_t; #pragma pack(push, 1) struct InterruptCallback { struct InterruptCallback* next; InterruptHandler handler_function; InterruptVerifier verifier_function; uint32_t notUsed; static constexpr InterruptCallback from_single_function(InterruptVerifier verifier) { return InterruptCallback{nullptr, nullptr, verifier, 0}; } }; #pragma pack(pop) #define __syscall_function_cast(table, ...) reinterpret_cast<__VA_ARGS__>(table) static __always_inline uint32_t* get_gp() { uint32_t* gp; __asm__("sw $gp, %0" : "=m"(gp)); return gp; } static __always_inline void* memcpy(void *dst, const void *src, size_t len) { register uint32_t FuncID asm("t1") = 0x2A; __asm__ volatile("" : "=r"(FuncID) : "r"(FuncID)); return __syscall_function_cast(Table_A, void*(*)(void*, const void*, size_t))(dst, src, len); } static __always_inline ThreadHandle OpenThread(void (*thread_func)(), uint32_t* stack_ptr, uint32_t* gp) { register uint32_t FuncID asm("t1") = 0x0E; __asm__ volatile("" : "=r"(FuncID) : "r"(FuncID)); return __syscall_function_cast(Table_B, ThreadHandle(*)(void(*)(), uint32_t*, uint32_t*))(thread_func, stack_ptr, gp); } static __always_inline void InitPad(uint8_t *portA, uint32_t portASize, uint8_t *portB, uint32_t portBSize) { register uint32_t FuncID asm("t1") = 0x12; __asm__ volatile("" : "=r"(FuncID) : "r"(FuncID)); __syscall_function_cast(Table_B, void(*)(uint8_t*, uint32_t, uint8_t*, uint32_t))(portA, portASize, portB, portBSize); } static __always_inline void StartPad() { register uint32_t FuncID asm("t1") = 0x13; __asm__ volatile("" : "=r"(FuncID) : "r"(FuncID)); __syscall_function_cast(Table_B, void(*)())(); } static __always_inline void StopPad() { register uint32_t FuncID asm("t1") = 0x14; __asm__ volatile("" : "=r"(FuncID) : "r"(FuncID)); __syscall_function_cast(Table_B, void(*)())(); } static __always_inline void ChangeClearPad(int32_t _reserved) { register uint32_t FuncID asm("t1") = 0x5B; __asm__ volatile("" : "=r"(FuncID) : "r"(FuncID)); __syscall_function_cast(Table_B, void(*)(int32_t))(_reserved); } static __always_inline void [[noreturn]] ReturnFromException() { register uint32_t FuncID asm("t1") = 0x17; __asm__ volatile("" : "=r"(FuncID) : "r"(FuncID)); __syscall_function_cast(Table_B, void(*)())(); } static __always_inline int SysEnqIntRP(Priority prio, InterruptCallback* interElm) { register uint32_t FuncID asm("t1") = 0x02; __asm__ volatile("" : "=r"(FuncID) : "r"(FuncID)); return __syscall_function_cast(Table_C, int(*)(Priority prio, InterruptCallback *interElm))(prio, interElm); } static __always_inline int SysDeqIntRP(Priority prio, InterruptCallback *interElm) { register uint32_t FuncID asm("t1") = 0x03; __asm__ volatile("" : "=r"(FuncID) : "r"(FuncID)); return __syscall_function_cast(Table_C, int(*)(Priority prio, InterruptCallback *interElm))(prio, interElm); } static __always_inline uint32_t EnterCriticalSection() { register uint32_t FuncID asm("a0") = 0x01; register uint32_t returnValue asm("v0"); __asm__ volatile("syscall" : "=r"(FuncID), "=r"(returnValue) : "r"(FuncID) : "at", "v1", "a1", "a2", "a3", "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", "t8", "t9", "memory"); return returnValue; } static __always_inline void ExitCriticalSection() { register uint32_t FuncID asm("a0") = 0x02; __asm__ volatile("syscall" : "=r"(FuncID) : "r"(FuncID) : "at", "v0", "v1", "a1", "a2", "a3", "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", "t8", "t9", "memory"); } static __always_inline void DeliverEvent(uint32_t classId, uint32_t spec) { register uint32_t FuncID asm("t1") = 0x07; __asm__ volatile("" : "=r"(FuncID) : "r"(FuncID)); __syscall_function_cast(Table_B, void (*)(uint32_t, uint32_t))(classId, spec); } static __always_inline uint32_t OpenEvent(uint32_t classId, uint32_t spec, uint32_t mode, void (*handler)()) { register uint32_t FuncID asm("t1") = 0x08; __asm__ volatile("" : "=r"(FuncID) : "r"(FuncID)); return __syscall_function_cast(Table_B, uint32_t(*)(uint32_t, uint32_t, uint32_t, void(*)()))(classId, spec, mode, handler); } static __always_inline int CloseEvent(uint32_t event) { register uint32_t FuncID asm("t1") = 0x09; __asm__ volatile("" : "=r"(FuncID) : "r"(FuncID)); return __syscall_function_cast(Table_B, uint32_t(*)(uint32_t))(event); } static __always_inline int32_t TestEvent(uint32_t event) { register uint32_t FuncID asm("t1") = 0x0B; __asm__ volatile("" : "=r"(FuncID) : "r"(FuncID)); return __syscall_function_cast(Table_B, int32_t (*)(uint32_t))(event); } static __always_inline int32_t EnableEvent(uint32_t event) { register uint32_t FuncID asm("t1") = 0x0C; __asm__ volatile("" : "=r"(FuncID) : "r"(FuncID)); return __syscall_function_cast(Table_B, int32_t (*)(uint32_t))(event); } static __always_inline const uint16_t* Krom2RawAdd(uint16_t sjis_code) { register uint32_t FuncID asm("t1") = 0x51; __asm__ volatile("" : "=r"(FuncID) : "r"(FuncID)); return __syscall_function_cast(Table_B, const uint16_t* (*)(uint16_t))(sjis_code); } void printf(const char* txt, ...); } }