.hidden __sysinfo

# The calling convention for __vsyscall has the syscall number
# and 5 args arriving as:  eax, edx, ecx, edi, esi, 4(%esp).
# This ensures that the inline asm in the C code never has to touch
# ebx or ebp (which are unavailable in PIC and frame-pointer-using
# code, respectively), and optimizes for size/simplicity in the caller.

.global __vsyscall
.type __vsyscall,@function
__vsyscall:
	push %edi
	push %ebx
	mov %edx,%ebx
	mov %edi,%edx
	mov 12(%esp),%edi
	push %eax
	call 1f
2:	mov %ebx,%edx
	pop %ebx
	pop %ebx
	pop %edi
	ret

1:	mov (%esp),%eax
	add $[__sysinfo-2b],%eax
	mov (%eax),%eax
	test %eax,%eax
	jz 1f
	push %eax
	mov 8(%esp),%eax
	ret                     # tail call to kernel vsyscall entry
1:	mov 4(%esp),%eax
	int $128
	ret

# The __vsyscall6 entry point is used only for 6-argument syscalls.
# Instead of passing the 5th argument on the stack, a pointer to the
# 5th and 6th arguments is passed. This is ugly, but there are no
# register constraints the inline asm could use that would make it
# possible to pass two arguments on the stack.

.global __vsyscall6
.type __vsyscall6,@function
__vsyscall6:
	push %ebp
	push %eax
	mov 12(%esp), %ebp
	mov (%ebp), %eax
	mov 4(%ebp), %ebp
	push %eax
	mov 4(%esp),%eax
	call __vsyscall
	pop %ebp
	pop %ebp
	pop %ebp
	ret

.global __syscall
.type __syscall,@function
__syscall:
	lea 24(%esp),%eax
	push %esi
	push %edi
	push %eax
	mov 16(%esp),%eax
	mov 20(%esp),%edx
	mov 24(%esp),%ecx
	mov 28(%esp),%edi
	mov 32(%esp),%esi
	call __vsyscall6
	pop %edi
	pop %edi
	pop %esi
	ret
