#ifndef _BITS_SYSCALLS_H #define _BITS_SYSCALLS_H #ifndef _SYSCALL_H # error "Never use directly; include instead." #endif /* * Some of the sneaky macros in the code were taken from * glibc-2.2.5/sysdeps/unix/sysv/linux/i386/sysdep.h */ #ifndef __ASSEMBLER__ #include #include #define INTERNAL_SYSCALL_NCS(name, err, nr, args...) \ ({ \ register unsigned int resultvar; \ __asm__ __volatile__ ( \ LOADARGS_##nr \ "movl %1, %%eax\n\t" \ "int $0x80\n\t" \ RESTOREARGS_##nr \ : "=a" (resultvar) \ : "g" (name) ASMFMT_##nr(args) : "memory", "cc" \ ); \ (int) resultvar; \ }) #if 1 /* defined __PIC__ || defined __pic__ */ #define LOADARGS_0 #define LOADARGS_1 "push %%ebx\n\t" CFI_ADJUST_CFA_OFFSET(4) "\n\t" CFI_REL_OFFSET(ebx, 0) "\n\t" "movl %k2, %%ebx\n\t" #define LOADARGS_2 LOADARGS_1 #define LOADARGS_3 LOADARGS_1 #define LOADARGS_4 LOADARGS_1 #define LOADARGS_5 LOADARGS_1 #define LOADARGS_6 LOADARGS_1 "push %%ebp\n\t" CFI_ADJUST_CFA_OFFSET(4) "\n\t" CFI_REL_OFFSET(ebp, 0) "\n\t" "movl %7, %%ebp\n\t" #define RESTOREARGS_0 #define RESTOREARGS_1 "pop %%ebx\n\t" CFI_ADJUST_CFA_OFFSET(-4) "\n\t" CFI_RESTORE(ebx) "\n\t" RESTOREARGS_0 #define RESTOREARGS_2 RESTOREARGS_1 #define RESTOREARGS_3 RESTOREARGS_1 #define RESTOREARGS_4 RESTOREARGS_1 #define RESTOREARGS_5 RESTOREARGS_1 #define RESTOREARGS_6 "pop %%ebp\n\t" CFI_ADJUST_CFA_OFFSET(-4) "\n\t" CFI_RESTORE(ebp) "\n\t" RESTOREARGS_1 #define ASMFMT_0() /* "acdSD" constraint would work too, but "SD" would use esi/edi and cause * them to be pushed/popped by compiler, "a" would use eax and cause ebx * to be saved/restored on stack, not in register. Narrowing choice down * to "ecx or edx" results in smaller and faster code: */ #define ASMFMT_1(arg1) \ , "cd" (arg1) /* Can use "adSD" constraint here: */ #define ASMFMT_2(arg1, arg2) \ , "d" (arg1), "c" (arg2) /* Can use "aSD" constraint here: */ #define ASMFMT_3(arg1, arg2, arg3) \ , "a" (arg1), "c" (arg2), "d" (arg3) /* Can use "aD" constraint here: */ #define ASMFMT_4(arg1, arg2, arg3, arg4) \ , "a" (arg1), "c" (arg2), "d" (arg3), "S" (arg4) #define ASMFMT_5(arg1, arg2, arg3, arg4, arg5) \ , "a" (arg1), "c" (arg2), "d" (arg3), "S" (arg4), "D" (arg5) #define ASMFMT_6(arg1, arg2, arg3, arg4, arg5, arg6) \ , "a" (arg1), "c" (arg2), "d" (arg3), "S" (arg4), "D" (arg5), "m" (arg6) #else /* !PIC */ /* Simpler code which just uses "b" constraint to load ebx. * Seems to work with gc 4.2.x, and generates slightly smaller, * but slightly slower code. Example (time syscall): * * - 8b 4c 24 04 mov 0x4(%esp),%ecx * - 87 cb xchg %ecx,%ebx * + 53 push %ebx * + 8b 5c 24 08 mov 0x8(%esp),%ebx * b8 0d 00 00 00 mov $0xd,%eax * cd 80 int $0x80 * - 87 cb xchg %ecx,%ebx * + 5b pop %ebx * c3 ret * * 2 bytes smaller, but uses stack via "push/pop ebx" */ #define LOADARGS_0 #define LOADARGS_1 #define LOADARGS_2 #define LOADARGS_3 #define LOADARGS_4 #define LOADARGS_5 #define LOADARGS_6 "push %%ebp\n\t" CFI_ADJUST_CFA_OFFSET(4) "\n\t" CFI_REL_OFFSET(ebp, 0) "\n\t" "movl %7, %%ebp\n\t" #define RESTOREARGS_0 #define RESTOREARGS_1 #define RESTOREARGS_2 #define RESTOREARGS_3 #define RESTOREARGS_4 #define RESTOREARGS_5 #define RESTOREARGS_6 "pop %%ebp\n\t" CFI_ADJUST_CFA_OFFSET(-4) "\n\t" CFI_RESTORE(ebp) "\n\t" #define ASMFMT_0() #define ASMFMT_1(arg1) \ , "b" (arg1) #define ASMFMT_2(arg1, arg2) \ , "b" (arg1), "c" (arg2) #define ASMFMT_3(arg1, arg2, arg3) \ , "b" (arg1), "c" (arg2), "d" (arg3) #define ASMFMT_4(arg1, arg2, arg3, arg4) \ , "b" (arg1), "c" (arg2), "d" (arg3), "S" (arg4) #define ASMFMT_5(arg1, arg2, arg3, arg4, arg5) \ , "b" (arg1), "c" (arg2), "d" (arg3), "S" (arg4), "D" (arg5) #define ASMFMT_6(arg1, arg2, arg3, arg4, arg5, arg6) \ , "b" (arg1), "c" (arg2), "d" (arg3), "S" (arg4), "D" (arg5), "m" (arg6) #endif /* !PIC */ #endif /* __ASSEMBLER__ */ #endif /* _BITS_SYSCALLS_H */