diff options
Diffstat (limited to 'libc/sysdeps/linux/i386/syscall.S')
-rw-r--r-- | libc/sysdeps/linux/i386/syscall.S | 76 |
1 files changed, 76 insertions, 0 deletions
diff --git a/libc/sysdeps/linux/i386/syscall.S b/libc/sysdeps/linux/i386/syscall.S new file mode 100644 index 000000000..c67b39ece --- /dev/null +++ b/libc/sysdeps/linux/i386/syscall.S @@ -0,0 +1,76 @@ +/* + * June 27, 2001 Manuel Novoa III + * + * This is a heavily modified version of gcc's output for the _syscall5 macro. + * The idea (originally from dietlibc) is that all syscall functions simply set + * the syscall number as the first argument, then set the syscall arguments as + * the next up-to-five arguments, and then jump here. All the common work is + * done by syscall(), saving a fair amount of generated code when a number of + * syscalls are used. The (potential) cost is some unnecessary pushes, pops, + * and movs but the execution time penalty should be relatively small compared + * to the cost of the syscall itself. + * + * July 24, 2002 + * + * Modified by Erik Andersen to take all function parameters from off the stack + * like a proper function and eliminates the old 255 syscall number limit. So + * now we can just call this as a function as syscall() per the function + * prototype in unistd.h, so to call _exit(42) you can just call. + * syscall(__NR_exit, 42); + * and things will just work. + */ + +.text + .align 4 +.globl syscall + .type syscall,@function +syscall: + pushl %edi + pushl %esi + pushl %ebx + movl 36(%esp),%edi; /* Load the 5 syscall argument registers */ + movl 32(%esp),%esi; + movl 28(%esp),%edx; + movl 24(%esp),%ecx; + movl 20(%esp),%ebx; + movl 16(%esp),%eax /* Load syscall number into %eax. */ +#APP + int $0x80 +#NO_APP + cmpl $-4095,%eax + jbe .Ldone + +#ifdef PIC + call Lhere +Lhere: + popl %ebx + addl $_GLOBAL_OFFSET_TABLE_+[.-Lhere],%ebx + negl %eax + movl %eax,%ecx +#ifdef _LIBC_REENTRANT + call __errno_location@PLT +#else + movl errno@GOT(%ebx),%eax +#endif /* _LIBC_REENTRANT */ + movl %ecx,(%eax) +#else + negl %eax +#ifdef _LIBC_REENTRANT + movl %eax,%ecx + call __errno_location + movl %ecx,(%eax) +#else + movl %eax,errno +#endif /* _LIBC_REENTRANT */ + +#endif /* PIC */ + + movl $-1,%eax + .p2align 4,,7 +.Ldone: + popl %ebx + popl %esi + popl %edi + ret +.Lsize: + .size syscall,.Lsize-syscall |