summaryrefslogtreecommitdiff
path: root/libc/sysdeps/linux/i386/syscall.S
blob: 44eb00f49c4813f0d50d8fc95860d3c26af86c08 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
/*
 * 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
.global syscall
.type   syscall,%function
.align 4
syscall:
	pushl %ebp
	pushl %edi
	pushl %esi
	pushl %ebx

	movl  44(%esp),%ebp	/* Load the 6 syscall argument registers */
	movl  40(%esp),%edi
	movl  36(%esp),%esi
	movl  32(%esp),%edx
	movl  28(%esp),%ecx
	movl  24(%esp),%ebx
	movl  20(%esp),%eax	/* Load syscall number into %eax.  */
	int $0x80

	popl %ebx
	popl %esi
	popl %edi
	popl %ebp

	cmpl $-4095,%eax
	jae  __error
	ret			/* Return to caller.  */

__error:
	jmp	__syscall_error

.size syscall,.-syscall