From a29e6e84ed9e828f87dd4999eba3a6dcef1e4191 Mon Sep 17 00:00:00 2001 From: Carlos O'Donell Date: Mon, 15 May 2006 00:44:14 +0000 Subject: [PATCH] 2006-05-15 Carlos O'Donell * sysdeps/unix/sysv/linux/hppa/clone.S: Accept extra arguments required for NPTL. * sysdeps/unix/sysv/linux/hppa/sysdep.c: Use var args for 6 arg syscall. * sysdeps/unix/sysv/linux/hppa/sysdep.h: Move DOARGS and UNDOARGS into PSEUDO_*'s. (ENTRY_LEAF): Define. (PSEUDO_NOERRNO, PSEUDO_ERRVAL): Use ENTRY_LEAF. (DO_CALL): Create frame. --- ChangeLog.hppa | 12 + sysdeps/unix/sysv/linux/hppa/clone.S | 68 ++++-- sysdeps/unix/sysv/linux/hppa/sysdep.c | 32 ++- sysdeps/unix/sysv/linux/hppa/sysdep.h | 323 ++++++++++++++++---------- 4 files changed, 280 insertions(+), 155 deletions(-) diff --git a/ChangeLog.hppa b/ChangeLog.hppa index d3be675392..fe73322f4d 100644 --- a/ChangeLog.hppa +++ b/ChangeLog.hppa @@ -1,3 +1,15 @@ +2006-05-15 Carlos O'Donell + + * sysdeps/unix/sysv/linux/hppa/clone.S: Accept extra arguments + required for NPTL. + * sysdeps/unix/sysv/linux/hppa/sysdep.c: Use var args for 6 arg + syscall. + * sysdeps/unix/sysv/linux/hppa/sysdep.h: Move DOARGS and UNDOARGS + into PSEUDO_*'s. + (ENTRY_LEAF): Define. + (PSEUDO_NOERRNO, PSEUDO_ERRVAL): Use ENTRY_LEAF. + (DO_CALL): Create frame. + 2006-05-15 Carlos O'Donell * sysdeps/hppa/dl-machine.h: Include tls.h diff --git a/sysdeps/unix/sysv/linux/hppa/clone.S b/sysdeps/unix/sysv/linux/hppa/clone.S index f497bca13d..042ffa5119 100644 --- a/sysdeps/unix/sysv/linux/hppa/clone.S +++ b/sysdeps/unix/sysv/linux/hppa/clone.S @@ -26,35 +26,62 @@ #define _ERRNO_H 1 #include -/* int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg) */ +/* Non-thread code calls __clone with the following parameters: + int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg) + + NPTL Code will call __clone with the following parameters: + int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg, + int *parent_tidptr, struct user_desc *newtls, int *child_pidptr) + + The code should not mangle the extra input registers. + Syscall expects: Input to __clone: + 4(r25) - function pointer (r26, arg0) + 0(r25) - argument (r23, arg3) + r26 - clone flags. (r24, arg2) + r25+64 - user stack pointer. (r25, arg1) + r24 - parent tid pointer. (stack - 52) + r23 - struct user_desc newtls pointer. (stack - 56) + r22 - child tid pointer. (stack - 60) + r20 - clone syscall number (constant) + */ .text ENTRY(__clone) - /* FIXME: I have no idea how profiling works on hppa. */ /* Sanity check arguments. */ - comib,= 0,%arg0,.Lerror /* no NULL function pointers */ ldi -EINVAL,%ret0 - comib,= 0,%arg1,.Lerror /* no NULL stack pointers */ - nop + comib,=,n 0,%arg0,.Lerror /* no NULL function pointers */ + comib,=,n 0,%arg1,.Lerror /* no NULL stack pointers */ /* Save the fn ptr and arg on the new stack. */ - stwm %arg0,64(%arg1) - stw %arg3,-60(%arg1) + stwm %r26,64(%r25) + stw %r23,-60(%r25) + /* Clone arguments are (int flags, void * child_stack) */ + copy %r24,%r26 /* flags are first */ + /* User stack pointer is in the correct register already */ + + /* Load args from stack... */ + ldw -52(%sp), %r24 /* Load parent_tidptr */ + ldw -56(%sp), %r23 /* Load newtls */ + ldw -60(%sp), %r22 /* Load child_tidptr */ + + /* Create frame to get r3 free */ + copy %sp, %r21 + stwm %r3, 64(%sp) + stw %r21, -4(%sp) /* Save the PIC register. */ #ifdef PIC - stw %r19,-32(%sr0, %sp) /* parent */ + copy %r19, %r3 /* parent */ #endif /* Do the system call */ - copy %arg2,%arg0 ble 0x100(%sr2,%r0) ldi __NR_clone,%r20 ldi -4096,%r1 comclr,>>= %r1,%ret0,%r0 /* Note: unsigned compare. */ - b,n .Lerror + b,n .LerrorRest comib,=,n 0,%ret0,thread_start @@ -63,18 +90,25 @@ ENTRY(__clone) since we return immediately. */ bv %r0(%rp) - nop + ldwm -64(%sp), %r3 + +.LerrorRest + /* Restore the PIC register on error */ +#ifdef PIC + copy %r3, %r19 /* parent */ +#endif /* Something bad happened -- no child created */ .Lerror: - /* Restore the PIC register on error */ -#ifdef PIC - ldw -32(%sr0, %sp), %r19 /* parent */ -#endif - + /* Set errno, save ret0 so we return with that value. */ + copy %ret0, %r3 b __syscall_error sub %r0,%ret0,%arg0 + copy %r3, %ret0 + /* Return after setting errno, and restoring ret0 */ + bv %r0(%rp) + ldwm -64(%sp), %r3 thread_start: @@ -92,7 +126,7 @@ thread_start: copy %ret0,%arg0 /* Die horribly. */ - iitlbp %r0,(%r0) + iitlbp %r0,(%sr0,%r0) PSEUDO_END(__clone) diff --git a/sysdeps/unix/sysv/linux/hppa/sysdep.c b/sysdeps/unix/sysv/linux/hppa/sysdep.c index 192efbaf75..8637c513df 100644 --- a/sysdeps/unix/sysv/linux/hppa/sysdep.c +++ b/sysdeps/unix/sysv/linux/hppa/sysdep.c @@ -16,12 +16,12 @@ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ +#include #include #include extern int __syscall_error(int err_no); -extern int syscall (int sysnum, int arg0, int arg1, int arg2, - int arg3, int arg4, int arg5); +extern long int syscall (long int __sysno, ...) __THROW; /* This routine is jumped to by all the syscall handlers, to stash an error number into errno. */ @@ -37,22 +37,35 @@ __syscall_error (int err_no) typically be in syscall.S. Also note that we have INLINE_SYSCALL, INTERNAL_SYSCALL, and all the generated pure assembly syscall wrappers. How often the function is used is unknown. */ -int -syscall (int sysnum, int arg0, int arg1, int arg2, int arg3, int arg4, - int arg5) + +long int +syscall (long int __sysno, ...) { /* FIXME: Keep this matching INLINE_SYSCALL for hppa */ + va_list args; + long int arg0, arg1, arg2, arg3, arg4, arg5; long int __sys_res; + + /* Load varargs */ + va_start (args, __sysno); + arg0 = va_arg (args, long int); + arg1 = va_arg (args, long int); + arg2 = va_arg (args, long int); + arg3 = va_arg (args, long int); + arg4 = va_arg (args, long int); + arg5 = va_arg (args, long int); + va_end (args); + { register unsigned long int __res asm("r28"); LOAD_ARGS_6 (arg0, arg1, arg2, arg3, arg4, arg5) - asm volatile (STW_ASM_PIC + asm volatile (SAVE_ASM_PIC " ble 0x100(%%sr2, %%r0) \n" " copy %1, %%r20 \n" - LDW_ASM_PIC + LOAD_ASM_PIC : "=r" (__res) - : "r" (sysnum) ASM_ARGS_6 - : CALL_CLOB_REGS CLOB_ARGS_6); + : "r" (__sysno) ASM_ARGS_6 + : "memory", CALL_CLOB_REGS CLOB_ARGS_6); __sys_res = __res; } if ((unsigned long int) __sys_res >= (unsigned long int) -4095) @@ -62,3 +75,4 @@ syscall (int sysnum, int arg0, int arg1, int arg2, int arg3, int arg4, } return __sys_res; } + diff --git a/sysdeps/unix/sysv/linux/hppa/sysdep.h b/sysdeps/unix/sysv/linux/hppa/sysdep.h index 4cfe63c556..b302d37f7b 100644 --- a/sysdeps/unix/sysv/linux/hppa/sysdep.h +++ b/sysdeps/unix/sysv/linux/hppa/sysdep.h @@ -22,28 +22,34 @@ #include #include #include -#include "config.h" -#ifndef ASM_LINE_SEP -# define ASM_LINE_SEP ; -#endif +#undef ASM_LINE_SEP +#define ASM_LINE_SEP ! #undef SYS_ify #define SYS_ify(syscall_name) (__NR_##syscall_name) +/* WARNING: TREG must be a callee saves register so + that it doesn't have to be restored after a call + to another function */ #ifdef PIC -/* WARNING: CANNOT BE USED IN A NOP! */ -# define STW_PIC stw %r19, -32(%sr0, %sp) ASM_LINE_SEP -# define LDW_PIC ldw -32(%sr0, %sp), %r19 ASM_LINE_SEP -# define STW_ASM_PIC " copy %%r19, %%r4\n" -# define LDW_ASM_PIC " copy %%r4, %%r19\n" -# define USING_GR4 "%r4", +# define TREG %r3 +# define SAVE_PIC(SREG) copy %r19, SREG ASM_LINE_SEP +# define LOAD_PIC(LREG) copy LREG, %r19 ASM_LINE_SEP +/* Inline assembly defines */ +# define TREG_ASM "%r4" /* Cant clobber r3, it holds framemarker */ +# define SAVE_ASM_PIC " copy %%r19, %" TREG_ASM "\n" +# define LOAD_ASM_PIC " copy %" TREG_ASM ", %%r19\n" +# define USING_TREG TREG_ASM, #else -# define STW_PIC ASM_LINE_SEP -# define LDW_PIC ASM_LINE_SEP -# define STW_ASM_PIC " \n" -# define LDW_ASM_PIC " \n" -# define USING_GR4 +# define TREG %r3 +# define SAVE_PIC(SREG) nop ASM_LINE_SEP +# define LOAD_PIC(LREG) nop ASM_LINE_SEP +/* Inline assembly defines */ +# define TREG_ASM +# define SAVE_ASM_PIC "nop \n" +# define LOAD_ASM_PIC "nop \n" +# define USING_TREG #endif #ifdef __ASSEMBLER__ @@ -76,31 +82,73 @@ /* We don't want the label for the error handle to be global when we define it here. */ -#ifdef PIC +/*#ifdef PIC # define SYSCALL_ERROR_LABEL 0f #else # define SYSCALL_ERROR_LABEL syscall_error -#endif +#endif*/ + +/* Argument manipulation from the stack for preparing to + make a syscall */ + +#define DOARGS_0 /* nothing */ +#define DOARGS_1 /* nothing */ +#define DOARGS_2 /* nothing */ +#define DOARGS_3 /* nothing */ +#define DOARGS_4 /* nothing */ +#define DOARGS_5 ldw -52(%sp), %r22 ASM_LINE_SEP +#define DOARGS_6 DOARGS_5 ldw -56(%sp), %r21 ASM_LINE_SEP + +#define UNDOARGS_0 /* nothing */ +#define UNDOARGS_1 /* nothing */ +#define UNDOARGS_2 /* nothing */ +#define UNDOARGS_3 /* nothing */ +#define UNDOARGS_4 /* nothing */ +#define UNDOARGS_5 /* nothing */ +#define UNDOARGS_6 /* nothing */ /* Define an entry point visible from C. There is currently a bug in gdb which prevents us from specifying incomplete stabs information. Fake some entries here which specify the current source file. */ -#define ENTRY(name) \ - .text ASM_LINE_SEP \ - .export C_SYMBOL_NAME(name) ASM_LINE_SEP \ - .type C_SYMBOL_NAME(name),@function ASM_LINE_SEP \ - C_LABEL(name) ASM_LINE_SEP \ - CALL_MCOUNT ASM_LINE_SEP +#define ENTRY(name) \ + .text ASM_LINE_SEP \ + .align ALIGNARG(4) ASM_LINE_SEP \ + .export C_SYMBOL_NAME(name) ASM_LINE_SEP \ + .type C_SYMBOL_NAME(name),@function ASM_LINE_SEP \ + C_LABEL(name) ASM_LINE_SEP \ + .PROC ASM_LINE_SEP \ + .CALLINFO FRAME=64,CALLS,SAVE_RP,ENTRY_GR=3 ASM_LINE_SEP \ + .ENTRY ASM_LINE_SEP \ + /* SAVE_RP says we do */ ASM_LINE_SEP \ + stw %rp, -20(%sr0,%sp) ASM_LINE_SEP \ + /*FIXME: Call mcount? (carefull with stack!) */ + +/* Some syscall wrappers do not call other functions, and + hence are classified as leaf, so add NO_CALLS for gdb */ +#define ENTRY_LEAF(name) \ + .text ASM_LINE_SEP \ + .align ALIGNARG(4) ASM_LINE_SEP \ + .export C_SYMBOL_NAME(name) ASM_LINE_SEP \ + .type C_SYMBOL_NAME(name),@function ASM_LINE_SEP \ + C_LABEL(name) ASM_LINE_SEP \ + .PROC ASM_LINE_SEP \ + .CALLINFO FRAME=64,NO_CALLS,SAVE_RP,ENTRY_GR=3 ASM_LINE_SEP \ + .ENTRY ASM_LINE_SEP \ + /* SAVE_RP says we do */ ASM_LINE_SEP \ + stw %rp, -20(%sr0,%sp) ASM_LINE_SEP \ + /*FIXME: Call mcount? (carefull with stack!) */ #undef END #define END(name) \ -1: ASM_LINE_SEP \ -.size C_SYMBOL_NAME(name),1b-C_SYMBOL_NAME(name) ASM_LINE_SEP + .EXIT ASM_LINE_SEP \ + .PROCEND ASM_LINE_SEP \ +.size C_SYMBOL_NAME(name), .-C_SYMBOL_NAME(name) ASM_LINE_SEP -/* If compiled for profiling, call `mcount' at the start of each function. */ -/* No, don't bother. gcc will put the call in for us. */ +/* If compiled for profiling, call `mcount' at the start + of each function. No, don't bother. gcc will put the + call in for us. */ #define CALL_MCOUNT /* Do nothing. */ /* syscall wrappers consist of @@ -118,14 +166,16 @@ */ #define PSEUDO(name, syscall_name, args) \ - ENTRY (name) \ - DO_CALL(syscall_name, args) ASM_LINE_SEP \ + ENTRY (name) ASM_LINE_SEP \ + /* If necc. load args from stack */ ASM_LINE_SEP \ + DOARGS_##args ASM_LINE_SEP \ + DO_CALL (syscall_name, args) ASM_LINE_SEP \ + UNDOARGS_##args ASM_LINE_SEP \ nop ASM_LINE_SEP #define ret \ - /* Return value set by ERRNO code */ ASM_LINE_SEP \ - bv 0(2) ASM_LINE_SEP \ - nop ASM_LINE_SEP + /* Return value set by ERRNO code */ ASM_LINE_SEP \ + bv,n 0(2) ASM_LINE_SEP #undef PSEUDO_END #define PSEUDO_END(name) \ @@ -133,8 +183,10 @@ /* We don't set the errno on the return from the syscall */ #define PSEUDO_NOERRNO(name, syscall_name, args) \ - ENTRY (name) \ - DO_CALL_NOERRNO(syscall_name, args) ASM_LINE_SEP \ + ENTRY_LEAF (name) ASM_LINE_SEP \ + DOARGS_##args ASM_LINE_SEP \ + DO_CALL_NOERRNO (syscall_name, args) ASM_LINE_SEP \ + UNDOARGS_##args ASM_LINE_SEP \ nop ASM_LINE_SEP #define ret_NOERRNO ret @@ -146,9 +198,11 @@ /* This has to return the error value */ #undef PSEUDO_ERRVAL #define PSEUDO_ERRVAL(name, syscall_name, args) \ - ENTRY(name) \ - DO_CALL_ERRVAL(syscall_name, args) ASM_LINE_SEP \ - nop ASM_LINE_SEP + ENTRY_LEAF (name) ASM_LINE_SEP \ + DOARGS_##args ASM_LINE_SEP \ + DO_CALL_ERRVAL (syscall_name, args) ASM_LINE_SEP \ + UNDOARGS_##args ASM_LINE_SEP \ + nop ASM_LINE_SEP #define ret_ERRVAL ret @@ -161,7 +215,8 @@ #define SYSCALL_PIC_SETUP /* Nothing. */ -/* All the syscall assembly macros rely on finding the approriate +/* FIXME: This comment is not true. + * All the syscall assembly macros rely on finding the approriate SYSCALL_ERROR_LABEL or rather HANDLER. */ /* int * __errno_location(void) so you have to store your value @@ -209,8 +264,8 @@ arg 2 gr25 arg 3 gr24 arg 4 gr23 - arg 5 -52(gr30) - arg 6 -56(gr30) + arg 5 -52(sp) + arg 6 -56(sp) gr22 and gr21 are caller-saves, so we can just load the arguments there and generally be happy. */ @@ -219,46 +274,48 @@ * is intended to mimic the if (__sys_res...) * code inside INLINE_SYSCALL */ +#define NO_ERROR -0x1000 #undef DO_CALL #define DO_CALL(syscall_name, args) \ - DOARGS_##args ASM_LINE_SEP \ - STW_PIC ASM_LINE_SEP \ + copy TREG,%r1 ASM_LINE_SEP \ + copy %sp,TREG ASM_LINE_SEP \ + /* Create a frame */ ASM_LINE_SEP \ + stwm %r1, 64(%sp) ASM_LINE_SEP \ + stw %rp, -20(%sp) ASM_LINE_SEP \ + stw TREG, -4(%sp) ASM_LINE_SEP \ + /* Save r19 */ ASM_LINE_SEP \ + SAVE_PIC(TREG) ASM_LINE_SEP \ /* Do syscall, delay loads # */ ASM_LINE_SEP \ ble 0x100(%sr2,%r0) ASM_LINE_SEP \ ldi SYS_ify (syscall_name), %r20 ASM_LINE_SEP \ - ldi -0x1000,%r1 ASM_LINE_SEP \ - cmpb,>>=,n %r1,%ret0,0f ASM_LINE_SEP \ - /* save rp or we get lost */ ASM_LINE_SEP \ - stw %rp, -20(%sr0,%sp) ASM_LINE_SEP \ - /* Restore r19 from frame */ ASM_LINE_SEP \ - LDW_PIC ASM_LINE_SEP \ - stw %ret0, -24(%sr0,%sp) ASM_LINE_SEP \ + ldi NO_ERROR,%r1 ASM_LINE_SEP \ + cmpb,>>=,n %r1,%ret0,L(pre_end) ASM_LINE_SEP \ + /* Restore r19 from TREG */ ASM_LINE_SEP \ + LOAD_PIC(TREG) /* delay */ ASM_LINE_SEP \ SYSCALL_ERROR_HANDLER ASM_LINE_SEP \ - /* create frame */ ASM_LINE_SEP \ - ldo 64(%sp), %sp ASM_LINE_SEP \ - ldo -64(%sp), %sp ASM_LINE_SEP \ + /* Use TREG for temp storage */ ASM_LINE_SEP \ + copy %ret0, TREG /* delay */ ASM_LINE_SEP \ /* OPTIMIZE: Don't reload r19 */ ASM_LINE_SEP \ /* do a -1*syscall_ret0 */ ASM_LINE_SEP \ - ldw -24(%sr0,%sp), %r26 ASM_LINE_SEP \ - sub %r0, %r26, %r26 ASM_LINE_SEP \ + sub %r0, TREG, TREG ASM_LINE_SEP \ /* Store into errno location */ ASM_LINE_SEP \ - stw %r26, 0(%sr0,%ret0) ASM_LINE_SEP \ + stw TREG, 0(%sr0,%ret0) ASM_LINE_SEP \ /* return -1 as error */ ASM_LINE_SEP \ ldo -1(%r0), %ret0 ASM_LINE_SEP \ - ldw -20(%sr0,%sp), %rp ASM_LINE_SEP \ -0: ASM_LINE_SEP \ - UNDOARGS_##args ASM_LINE_SEP +L(pre_end): ASM_LINE_SEP \ + /* Restore return pointer */ ASM_LINE_SEP \ + ldw -84(%sp),%rp ASM_LINE_SEP \ + /* Restore our frame, restoring TREG */ ASM_LINE_SEP \ + ldwm -64(%sp), TREG ASM_LINE_SEP /* We do nothing with the return, except hand it back to someone else */ #undef DO_CALL_NOERRNO #define DO_CALL_NOERRNO(syscall_name, args) \ - DOARGS_##args \ /* No need to store r19 */ ASM_LINE_SEP \ ble 0x100(%sr2,%r0) ASM_LINE_SEP \ ldi SYS_ify (syscall_name), %r20 ASM_LINE_SEP \ - /* Caller will restore r19 */ ASM_LINE_SEP \ - UNDOARGS_##args + /* Caller will restore r19 */ ASM_LINE_SEP /* Here, we return the ERRVAL in assembly, note we don't call the error handler function, but we do 'negate' the return _IF_ @@ -266,34 +323,15 @@ #undef DO_CALL_ERRVAL #define DO_CALL_ERRVAL(syscall_name, args) \ - DOARGS_##args ASM_LINE_SEP \ /* No need to store r19 */ ASM_LINE_SEP \ ble 0x100(%sr2,%r0) ASM_LINE_SEP \ ldi SYS_ify (syscall_name), %r20 ASM_LINE_SEP \ /* Caller will restore r19 */ ASM_LINE_SEP \ - ldi -0x1000,%r1 ASM_LINE_SEP \ + ldi NO_ERROR,%r1 ASM_LINE_SEP \ cmpb,>>=,n %r1,%ret0,0f ASM_LINE_SEP \ sub %r0, %ret0, %ret0 ASM_LINE_SEP \ -0: ASM_LINE_SEP \ - UNDOARGS_##args ASM_LINE_SEP +0: ASM_LINE_SEP -#define DOARGS_0 /* nothing */ -#define DOARGS_1 /* nothing */ -#define DOARGS_2 /* nothing */ -#define DOARGS_3 /* nothing */ -#define DOARGS_4 /* nothing */ -#define DOARGS_5 ldw -52(%r30), %r22 ASM_LINE_SEP -#define DOARGS_6 ldw -52(%r30), %r22 ASM_LINE_SEP \ - ldw -56(%r30), %r21 ASM_LINE_SEP - - -#define UNDOARGS_0 /* nothing */ -#define UNDOARGS_1 /* nothing */ -#define UNDOARGS_2 /* nothing */ -#define UNDOARGS_3 /* nothing */ -#define UNDOARGS_4 /* nothing */ -#define UNDOARGS_5 /* nothing */ -#define UNDOARGS_6 /* nothing */ #else @@ -305,27 +343,28 @@ registers r20 -> r26 will conflict with the list so they are treated specially. Although r19 is clobbered by the syscall we cannot say this because it would violate ABI, thus we say - r4 is clobbered and use that register to save/restore r19 + TREG is clobbered and use that register to save/restore r19 across the syscall. */ -#define CALL_CLOB_REGS "%r1", "%r2", USING_GR4 \ +#define CALL_CLOB_REGS "%r1", "%r2", USING_TREG \ "%r20", "%r29", "%r31" #undef INLINE_SYSCALL -#define INLINE_SYSCALL(name, nr, args...) ({ \ +#define INLINE_SYSCALL(name, nr, args...) \ +({ \ long __sys_res; \ { \ register unsigned long __res asm("r28"); \ LOAD_ARGS_##nr(args) \ - /* FIXME: HACK stw/ldw r19 around syscall */ \ + /* FIXME: HACK save/load r19 around syscall */ \ asm volatile( \ - STW_ASM_PIC \ + SAVE_ASM_PIC \ " ble 0x100(%%sr2, %%r0)\n" \ " ldi %1, %%r20\n" \ - LDW_ASM_PIC \ + LOAD_ASM_PIC \ : "=r" (__res) \ : "i" (SYS_ify(name)) ASM_ARGS_##nr \ - : CALL_CLOB_REGS CLOB_ARGS_##nr \ + : "memory", CALL_CLOB_REGS CLOB_ARGS_##nr \ ); \ __sys_res = (long)__res; \ } \ @@ -339,13 +378,13 @@ /* INTERNAL_SYSCALL_DECL - Allows us to setup some function static value to use within the context of the syscall INTERNAL_SYSCALL_ERROR_P - Returns 0 if it wasn't an error, 1 otherwise - You are allowed to use the syscall result (val) and the DECL error variable - to determine what went wrong. + You are allowed to use the syscall result (val) and the DECL error + variable to determine what went wrong. INTERLAL_SYSCALL_ERRNO - Munges the val/err pair into the error number. In our case we just flip the sign. */ #undef INTERNAL_SYSCALL_DECL -#define INTERNAL_SYSCALL_DECL(err) do { } while (0) +#define INTERNAL_SYSCALL_DECL(err) /* Equivalent to (val < 0)&&(val > -4095) which is what we want */ #undef INTERNAL_SYSCALL_ERROR_P @@ -357,46 +396,72 @@ /* Similar to INLINE_SYSCALL but we don't set errno */ #undef INTERNAL_SYSCALL -#define INTERNAL_SYSCALL(name, err, nr, args...) \ -({ \ - long __sys_res; \ - { \ - register unsigned long __res asm("r28"); \ - LOAD_ARGS_##nr(args) \ - /* FIXME: HACK stw/ldw r19 around syscall */ \ - asm volatile( \ - STW_ASM_PIC \ - " ble 0x100(%%sr2, %%r0)\n" \ - " ldi %1, %%r20\n" \ - LDW_ASM_PIC \ - : "=r" (__res) \ - : "i" (SYS_ify(name)) ASM_ARGS_##nr \ - : CALL_CLOB_REGS CLOB_ARGS_##nr \ - ); \ - __sys_res = (long)__res; \ - } \ - __sys_res; \ +#define INTERNAL_SYSCALL(name, err, nr, args...) \ +({ \ + long __sys_res; \ + { \ + register unsigned long __res asm("r28"); \ + LOAD_ARGS_##nr(args) \ + /* FIXME: HACK save/load r19 around syscall */ \ + asm volatile( \ + SAVE_ASM_PIC \ + " ble 0x100(%%sr2, %%r0)\n" \ + " ldi %1, %%r20\n" \ + LOAD_ASM_PIC \ + : "=r" (__res) \ + : "i" (SYS_ify(name)) ASM_ARGS_##nr \ + : "memory", CALL_CLOB_REGS CLOB_ARGS_##nr \ + ); \ + __sys_res = (long)__res; \ + } \ + __sys_res; \ }) + +/* The _NCS variant allows non-constant syscall numbers. */ +#undef INTERNAL_SYSCALL_NCS +#define INTERNAL_SYSCALL_NCS(name, err, nr, args...) \ +({ \ + long __sys_res; \ + { \ + register unsigned long __res asm("r28"); \ + LOAD_ARGS_##nr(args) \ + /* FIXME: HACK save/load r19 around syscall */ \ + asm volatile( \ + SAVE_ASM_PIC \ + " ble 0x100(%%sr2, %%r0)\n" \ + " copy %1, %%r20\n" \ + LOAD_ASM_PIC \ + : "=r" (__res) \ + : "r" (name) ASM_ARGS_##nr \ + : "memory", CALL_CLOB_REGS CLOB_ARGS_##nr \ + ); \ + __sys_res = (long)__res; \ + } \ + __sys_res; \ + }) + + + #define LOAD_ARGS_0() -#define LOAD_ARGS_1(r26) \ - register unsigned long __r26 __asm__("r26") = (unsigned long)(r26); \ - LOAD_ARGS_0() -#define LOAD_ARGS_2(r26,r25) \ - register unsigned long __r25 __asm__("r25") = (unsigned long)(r25); \ - LOAD_ARGS_1(r26) -#define LOAD_ARGS_3(r26,r25,r24) \ - register unsigned long __r24 __asm__("r24") = (unsigned long)(r24); \ - LOAD_ARGS_2(r26,r25) -#define LOAD_ARGS_4(r26,r25,r24,r23) \ - register unsigned long __r23 __asm__("r23") = (unsigned long)(r23); \ - LOAD_ARGS_3(r26,r25,r24) -#define LOAD_ARGS_5(r26,r25,r24,r23,r22) \ - register unsigned long __r22 __asm__("r22") = (unsigned long)(r22); \ - LOAD_ARGS_4(r26,r25,r24,r23) -#define LOAD_ARGS_6(r26,r25,r24,r23,r22,r21) \ - register unsigned long __r21 __asm__("r21") = (unsigned long)(r21); \ - LOAD_ARGS_5(r26,r25,r24,r23,r22) +#define LOAD_ARGS_1(r26) \ + register unsigned long __r26 __asm__("r26") = (unsigned long)(r26); \ + LOAD_ARGS_0() +#define LOAD_ARGS_2(r26,r25) \ + register unsigned long __r25 __asm__("r25") = (unsigned long)(r25); \ + LOAD_ARGS_1(r26) +#define LOAD_ARGS_3(r26,r25,r24) \ + register unsigned long __r24 __asm__("r24") = (unsigned long)(r24); \ + LOAD_ARGS_2(r26,r25) +#define LOAD_ARGS_4(r26,r25,r24,r23) \ + register unsigned long __r23 __asm__("r23") = (unsigned long)(r23); \ + LOAD_ARGS_3(r26,r25,r24) +#define LOAD_ARGS_5(r26,r25,r24,r23,r22) \ + register unsigned long __r22 __asm__("r22") = (unsigned long)(r22); \ + LOAD_ARGS_4(r26,r25,r24,r23) +#define LOAD_ARGS_6(r26,r25,r24,r23,r22,r21) \ + register unsigned long __r21 __asm__("r21") = (unsigned long)(r21); \ + LOAD_ARGS_5(r26,r25,r24,r23,r22) /* Even with zero args we use r20 for the syscall number */ #define ASM_ARGS_0