diff --git a/clib/s/cl_entries b/clib/s/cl_entries index 170dd4a11dc8e0203c8fde91b60d80fec2775ae5..dafc55d7ab9a82b9468d451f896be79d5580820a 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 39dd223a85abcea2fd1cac85ee965e342b3aa757..d8e08be03795e551083b358b80993c911795f28a 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 ac03fcb060c961509936828c11f815b95314c9a9..c99ef95985a8a7d159062c586dd647b375a8bdc7 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