1 #ifndef _BITS_SYSCALLS_H 2 #define _BITS_SYSCALLS_H 3 4 #ifndef _SYSCALL_H 5 # error "Never use <bits/syscalls.h> directly; include <sys/syscall.h> instead." 6 #endif 7 8 /* 9 * Some of the sneaky macros in the code were taken from 10 * glibc-2.2.5/sysdeps/unix/sysv/linux/i386/sysdep.h 11 */ 12 13 #ifndef __ASSEMBLER__ 14 15 #include <errno.h> 16 17 #define INTERNAL_SYSCALL_NCS_X86_UPTOFIVE(name, err, nr, args...) \ 18 (__extension__ \ 19 ({ \ 20 register unsigned int resultvar; \ 21 __asm__ __volatile__ ( \ 22 LOADARGS_##nr \ 23 "movl %1, %%eax\n\t" \ 24 "int $0x80\n\t" \ 25 RESTOREARGS_##nr \ 26 : "=a" (resultvar) \ 27 : "g" (name) ASMFMT_##nr(args) : "memory", "cc" \ 28 ); \ 29 (int) resultvar; \ 30 }) \ 31 ) 32 33 #define INTERNAL_SYSCALL_NCS_X86_0 INTERNAL_SYSCALL_NCS_X86_UPTOFIVE 34 #define INTERNAL_SYSCALL_NCS_X86_1 INTERNAL_SYSCALL_NCS_X86_UPTOFIVE 35 #define INTERNAL_SYSCALL_NCS_X86_2 INTERNAL_SYSCALL_NCS_X86_UPTOFIVE 36 #define INTERNAL_SYSCALL_NCS_X86_3 INTERNAL_SYSCALL_NCS_X86_UPTOFIVE 37 #define INTERNAL_SYSCALL_NCS_X86_4 INTERNAL_SYSCALL_NCS_X86_UPTOFIVE 38 #define INTERNAL_SYSCALL_NCS_X86_5 INTERNAL_SYSCALL_NCS_X86_UPTOFIVE 39 40 extern long __libc_i386_syscall6(unsigned long, ...) 41 __attribute__((__cdecl__)); 42 #define INTERNAL_SYSCALL_NCS_X86_6(name, err, nr, args...) \ 43 __libc_i386_syscall6((unsigned long)name, args) 44 45 #define INTERNAL_SYSCALL_NCS(name, err, nr, args...) \ 46 INTERNAL_SYSCALL_NCS_X86_##nr(name, err, nr, args) 47 48 /* This code avoids pushing/popping ebx as much as possible. 49 * I think the main reason was that older GCCs had problems 50 * with proper saving/restoring of ebx if "b" constraint was used, 51 * which was breaking -fPIC code really badly. 52 * At least gcc 4.2.x seems to not need these tricks anymore, 53 * but this code is still useful because it often avoids 54 * using stack for saving ebx. 55 * Keeping it unconditionally enabled for now. 56 */ 57 58 /* We need some help from the assembler to generate optimal code. 59 * We define some macros here which later will be used. */ 60 /* FIXME: drop these b* macros! */ 61 62 __asm__ ( 63 ".L__X'%ebx = 1\n\t" 64 ".L__X'%ecx = 2\n\t" 65 ".L__X'%edx = 2\n\t" 66 ".L__X'%eax = 3\n\t" 67 ".L__X'%esi = 3\n\t" 68 ".L__X'%edi = 3\n\t" 69 ".L__X'%ebp = 3\n\t" 70 ".L__X'%esp = 3\n\t" 71 72 /* Loading param #1 (ebx) is done by loading it into 73 * another register, and then performing bpushl+bmovl, 74 * since we must preserve ebx */ 75 76 ".macro bpushl name reg\n\t" 77 ".if 1 - \\name\n\t" /* if reg!=ebx... */ 78 ".if 2 - \\name\n\t" /* if reg can't be clobbered... */ 79 "pushl %ebx\n\t" /* save ebx on stack */ 80 ".else\n\t" 81 "xchgl \\reg, %ebx\n\t" /* else save ebx in reg, and load reg to ebx */ 82 ".endif\n\t" 83 ".endif\n\t" 84 ".endm\n\t" 85 86 ".macro bmovl name reg\n\t" 87 ".if 1 - \\name\n\t" 88 ".if 2 - \\name\n\t" /* if reg can't be clobbered... */ 89 "movl \\reg, %ebx\n\t" /* load reg to ebx */ 90 ".endif\n\t" 91 ".endif\n\t" 92 ".endm\n\t" 93 94 ".macro bpopl name reg\n\t" 95 ".if 1 - \\name\n\t" 96 ".if 2 - \\name\n\t" /* if reg can't be clobbered... */ 97 "popl %ebx\n\t" /* restore ebx from stack */ 98 ".else\n\t" 99 "xchgl \\reg, %ebx\n\t" /* else restore ebx from reg */ 100 ".endif\n\t" 101 ".endif\n\t" 102 ".endm\n\t" 103 ); 104 105 #define LOADARGS_0 106 #define LOADARGS_1 "bpushl .L__X'%k2, %k2\n\t" "bmovl .L__X'%k2, %k2\n\t" 107 #define LOADARGS_2 LOADARGS_1 108 #define LOADARGS_3 LOADARGS_1 109 #define LOADARGS_4 LOADARGS_1 110 #define LOADARGS_5 LOADARGS_1 111 112 #define RESTOREARGS_0 113 #define RESTOREARGS_1 "bpopl .L__X'%k2, %k2\n\t" 114 #define RESTOREARGS_2 RESTOREARGS_1 115 #define RESTOREARGS_3 RESTOREARGS_1 116 #define RESTOREARGS_4 RESTOREARGS_1 117 #define RESTOREARGS_5 RESTOREARGS_1 118 119 #define ASMFMT_0() 120 /* "acdSD" constraint would work too, but "SD" would use esi/edi and cause 121 * them to be pushed/popped by compiler, "a" would use eax and cause ebx 122 * to be saved/restored on stack, not in register. Narrowing choice down 123 * to "ecx or edx" results in smaller and faster code: */ 124 #define ASMFMT_1(arg1) \ 125 , "cd" (arg1) 126 /* Can use "adSD" constraint here: */ 127 #define ASMFMT_2(arg1, arg2) \ 128 , "d" (arg1), "c" (arg2) 129 /* Can use "aSD" constraint here: */ 130 #define ASMFMT_3(arg1, arg2, arg3) \ 131 , "a" (arg1), "c" (arg2), "d" (arg3) 132 /* Can use "aD" constraint here: */ 133 #define ASMFMT_4(arg1, arg2, arg3, arg4) \ 134 , "a" (arg1), "c" (arg2), "d" (arg3), "S" (arg4) 135 #define ASMFMT_5(arg1, arg2, arg3, arg4, arg5) \ 136 , "a" (arg1), "c" (arg2), "d" (arg3), "S" (arg4), "D" (arg5) 137 138 #endif /* __ASSEMBLER__ */ 139 #endif /* _BITS_SYSCALLS_H */ 140