Improve calling convention so it's more performance and doesn't mess up stack for vsprintf /stdargs

This commit is contained in:
Vincent Barrilliot 2023-01-31 01:35:05 +01:00
parent 4f8191d8ff
commit 25dbadb1c0
2 changed files with 48 additions and 30 deletions

View file

@ -28,12 +28,7 @@
* Determine the correct system function implementation and call it. * Determine the correct system function implementation and call it.
*/ */
unsigned long syscall_dispatch(int32_t function, int32_t param0, int32_t param1, int32_t param2, int32_t param3, int32_t param4, int32_t param5) { unsigned long syscall_dispatch(int32_t function, int32_t param0, int32_t param1, int32_t param2, int32_t param3, int32_t param4, int32_t param5) {
#ifdef KDEBUG //TRACE7("DISPATCH(%lx,%ld,%ld,%ld,%ld,%ld,%ld)", function, param0, param1, param2, param3, param4, param5);
char buf[80];
sprintf(buf,"fn:0x%04x d1:%04x d2:0x%04x d3:0x%04x", (int)function, (int)param0, (int)param1, (int)param2);
DEBUG(buf);
#endif
switch (function & 0x00f0) { switch (function & 0x00f0) {
case 0x00: case 0x00:
/* Core System Calls */ /* Core System Calls */

View file

@ -148,6 +148,7 @@ coldboot: move.w #$2700,SR ; Supervisor mode, disable all interrupts
lea ___STACK,sp lea ___STACK,sp
bsr _int_disable_all bsr _int_disable_all
lea ___BSSSTART,a0 lea ___BSSSTART,a0
move.l #___BSSSIZE,d0 move.l #___BSSSIZE,d0
beq callmain beq callmain
@ -161,6 +162,8 @@ clrloop: ; We don't use clr.l because it's a read-modify-write operation
subq.l #4,d0 subq.l #4,d0
bpl.s clrloop bpl.s clrloop
move.l #trap_save_area,trap_save_area
callmain: jsr ___main ; call __main to transfer to the C code callmain: jsr ___main ; call __main to transfer to the C code
; endless loop; can be changed accordingly ; endless loop; can be changed accordingly
@ -379,40 +382,54 @@ panic_lock: bra panic_lock
; Function to make a system call based on the number of the system function: ; Function to make a system call based on the number of the system function:
; int32_t syscall(int32_t number, int32_t p0, int32_t p1, int32_t p2, int32_t p3, int32_t p4, int32_t p5) ; int32_t syscall(int32_t number, int32_t p0, int32_t p1, int32_t p2, int32_t p3, int32_t p4, int32_t p5)
; ;
xdef _trace
aze dc.b "return address: %p",0
even
_syscall: _syscall:
movem.l d1-d7,-(sp) ; Save caller's registers ; Repush the parameters
move.l (56,sp),d6 ; Parameter 5 to D6 move.l 28(sp),-(sp)
move.l (52,sp),d5 ; Parameter 4 to D5 move.l 28(sp),-(sp)
move.l (48,sp),d4 ; Parameter 3 to D4 move.l 28(sp),-(sp)
move.l (44,sp),d3 ; Parameter 2 to D3 move.l 28(sp),-(sp)
move.l (40,sp),d2 ; Parameter 1 to D2 move.l 28(sp),-(sp)
move.l (36,sp),d1 ; Parameter 0 to D1 move.l 28(sp),-(sp)
move.l (32,sp),d0 ; Function number to D0 (32 = 4(PC)+7(regs)*4) move.l 28(sp),-(sp)
trap #15 ; Call into the kernel
TRAP #15 ; Call into the kernel lea 28(sp),sp
movem.l (sp)+,d1-d7 ; Restore caller's registers
rts rts
; ;
; TRAP#15 handler... transfer control to the C dispatcher ; TRAP#15 handler... transfer control to the C dispatcher
; ;
h_trap_15: h_trap_15:
cmpi.w #$43,d1 ; Is this a sys_proc_elevate call? ; Save sr, return address and non-scratch registers into our save area
beq.s h_trap_elev ; Yes, just handle it here ; TODO we should guard this if we want to allow system calls from interrupts.
move.l trap_save_area,a0
move.w (sp)+,d0 ; Status register
move.w d0,-(a0)
move.l (sp)+,-(a0) ; Return address
movem.l d2-d7/a2-a7,-(a0)
move.l a0,trap_save_area ; TODO should we check if we're beyond the end of that area ? As we'd be corrupting data.
; Fix stack if necessary so it points to the arguments for the dispatcher
btst #13,d0 ; Check supervisor bit from caller's status register to see if were we called from user mode
bne.s syscall_stack_set ; If yes, sp already points to the arguments
move.l usp,sp ; If not, the argument are on the user stack, so use it
syscall_stack_set:
move.l d6,-(sp) ; Push the parameters to the stack for the C call cmpi.w #$43,(sp) ; Is this a sys_proc_elevate call?
move.l d5,-(sp) beq.s h_trap_elev ; Yes, just handle it here
move.l d4,-(sp)
move.l d3,-(sp)
move.l d2,-(sp)
move.l d1,-(sp)
move.l d0,-(sp)
jsr _syscall_dispatch ; Call the C routine to do the dispatch jsr _syscall_dispatch ; Call the C routine to do the dispatch
; Note: the C routine depends upon the register push order
adda.l #7*4,sp ; Remove parameters from the stack ; Restore context from our save area
move.l trap_save_area,a0
movem.l (a0)+,d2-d7/a2-a7
move.l (a0)+,-(sp) ; Return address
move.w (a0)+,-(sp) ; Status register
move.l a0,trap_save_area
rte ; Return to the caller rte ; Return to the caller
h_trap_elev ori #$2000,(a7) ; Change the caller's privilege to supervisor h_trap_elev ori #$2000,(a7) ; Change the caller's privilege to supervisor
@ -446,3 +463,9 @@ _restart_cli:
lea ___STACK,sp lea ___STACK,sp
jsr _cli_rerepl jsr _cli_rerepl
bra _restart_cli bra _restart_cli
section BSS
TRAP_MAX_REENTRANCY EQU 4 ; Max number of reentrant calls to the trap handler
ds.b (6+12*4)*TRAP_MAX_REENTRANCY ; Each time we save status register .w and return address .l, so 6 bytes, + the saved registers (non-scratch) d2-d7/a2-a7 according to VBCC doc
trap_save_area: ds.l 1