From 4ddb0942741dd826d553653b3addd78e101dd6d5 Mon Sep 17 00:00:00 2001 From: Ben Avison <bavison@riscosopen.org> Date: Thu, 26 May 2022 16:59:54 +0100 Subject: [PATCH] Add variants of _swi and _swix that take a va_list These are typically useful for wrapper functions that want to do something before and/or after a SWI call, and which therefore need to pass a pointer to their own variadic arguments into the guts of _swi or _swix. The pairs of functions _swi and _vswi, and _swix and _vswix, are almost identical, differing only in argument marshalling. There being only two additional entries, I didn't think it was worth introducing a whole new library chunk. Instead, I've tacked them onto the end of chunk 2 (the basic clib functions). Note that this means that any applications that use these new entries will need to take responsibility for RMEnsuring this version of the SharedCLibrary module and softloading a newer one if necessary. --- clib/s/cl_entries | 2 ++ h/swisheader | 17 +++++++++++++++-- kernel/s/swiv | 29 +++++++++++++++++++++++------ 3 files changed, 40 insertions(+), 8 deletions(-) diff --git a/clib/s/cl_entries b/clib/s/cl_entries index 170dd4a..dafc55d 100644 --- a/clib/s/cl_entries +++ b/clib/s/cl_entries @@ -213,6 +213,8 @@ Entry _swi, imported, , unveneered Entry _swix, imported, , unveneered + Entry _vswi, imported, , unveneered + Entry _vswix, imported, , unveneered ; __va_illegal_arg 0 END diff --git a/h/swisheader b/h/swisheader index 39dd223..d8e08be 100644 --- a/h/swisheader +++ b/h/swisheader @@ -34,12 +34,18 @@ extern "C" { #endif +typedef char *__va_list[1]; /* keep in step with <stdarg.h> */ + #pragma -v4 extern int _swi (int swi_no, unsigned int, ...); extern _kernel_oserror *_swix (int swi_no, unsigned int, ...); #pragma -v0 +extern int _vswi (int swi_no, unsigned int, __va_list); + +extern _kernel_oserror *_vswix (int swi_no, unsigned int, __va_list); + #ifdef __cplusplus } #endif @@ -61,9 +67,11 @@ extern _kernel_oserror *_swix (int swi_no, unsigned int, ...); * These functions provide a generic method of calling RISC OS SWIs from C or * C++. * - * Two functions are provided: + * Four functions are provided: * _swi for calling SWIs without setting the X bit - * _swix which sets the X bit before calling the SWI. + * _swix which sets the X bit before calling the SWI + * _vswi, like _swi but using a va_list instead of variadic arguments + * _vswix, like _swix but using a va_list instead of variadic arguments. * * swi_no is the number of the SWI to be called. This should never have the * X bit set. @@ -142,5 +150,10 @@ extern _kernel_oserror *_swix (int swi_no, unsigned int, ...); * &workspace_end, &next); * * e = _swix(Wimp_SetExtent, _IN(0)|_BLOCK(1), w, minx, miny, maxx, maxy); + * + * va_list ap; + * va_start(ap, flags); + * e = _vswix(swi_no, flags, ap); + * va_end(ap); */ diff --git a/kernel/s/swiv b/kernel/s/swiv index ac03fcb..c99ef95 100644 --- a/kernel/s/swiv +++ b/kernel/s/swiv @@ -39,10 +39,29 @@ $name MRS lr, CPSR EXPORT |_swix| EXPORT |_swi| + EXPORT |_vswix| + EXPORT |_vswi| ; tedious static _swi(x) entry handling, to avoid generating dynamic code, and ; requiring an expensive XOS_SynchroniseCodeAreas +|_vswix| + ORR r0, r0, #&20000 + TST r1, #&FF0 ; check for use of input regs. 4 to 9, or of block param + BNE vswix_even_more_tedious ; if so, do full stuff + + SUB sp, sp, #2*4 ; leave a gap so we can use common bottom half + STMDB sp!, {r1, r4-r9, lr} ; save stuff + LDR r14, [r2] ; r14 -> input args + B swix_vswix_common + +vswix_even_more_tedious +|_vswi| + SUB sp, sp, #2*4 ; leave a gap so we can use common bottom half + STMDB sp!, {r1, r4-r9, lr} ; save stuff + LDR r14, [r2] ; r14 -> input args + B swi_vswi_common + |_swix| ORR r0, r0, #&20000 TST r1, #&FF0 ; check for use of input regs. 4 to 9, or of block param @@ -50,10 +69,9 @@ $name MRS lr, CPSR STMFD sp!, {r2, r3} ; put 1st two variadic args on stack STMDB sp!, {r1, r4-r9, lr} ; save stuff - + ADD r14, sp, #8*4 ; r14 -> input args +swix_vswix_common SUB sp, sp, #5*4 ; so we can use tail code common with dynamic version (and room for regs stash) - - ADD r14, sp, #(5+8)*4 ; r14 -> input args MOV r12, r0 ; target SWI code STR fp, [sp] ; stash fp @@ -78,10 +96,9 @@ swix_even_more_tedious |_swi| STMFD sp!, {r2, r3} ; put 1st two variadic args on stack STMDB sp!, {r1, r4-r9, lr} ; save stuff - + ADD r14, sp, #8*4 ; r14 -> input args +swi_vswi_common SUB sp, sp, #5*4 ; so we can use tail code common with dynamic version (and room for regs stash) - - ADD r14, sp, #(5+8)*4 ; r14 -> input args MOV r12, r0 ; target SWI code STR fp, [sp] ; stash fp -- GitLab