libk  x86.lin.64.s at [93014cedbc]

File arch/x86.lin.64.s artifact 2b600a2718 part of check-in 93014cedbc


;; abi definition file for x86 linux 64-bit
; vim: ft=nasm

; syscall64 numbers - syscall table must be created first!
%include "calls.x86.lin.64.s"

; syscall ops
%define sys.call syscall

; register order for syscall convention
%define sys.reg.n 7
%define sys.reg.ret rax
%define sys.reg.0 rax
%define sys.reg.1 rdi
%define sys.reg.2 rsi
%define sys.reg.3 rdx
%define sys.reg.4 r10
%define sys.reg.5 r8
%define sys.reg.6 r9

; register order for ccall convention
%define ccall.reg.ct 6
%define ccall.reg.ret rdi
%define ccall.reg.0 rdi
%define ccall.reg.1 rsi
%define ccall.reg.2 rdx
%define ccall.reg.3 rcx
%define ccall.reg.4 r8
%define ccall.reg.5 r9

%macro sys 1-8
; syscall64 wrapper, ex. `sys sys.write, 1, msg, msg.len`
	%assign i 0
	%rep %0
		mov sys.reg. %+ i, %1 ; i'm actually shocked this worked
		%rotate 1
		%assign i i+1
	%endrep 
	syscall
%endmacro

%macro sys.prep 1-8
	; for when we need to modify parameters before we
	; make the actual call.
	%assign i 0
	%rep %0
		mov sys.reg. %+ i, %1
		%rotate 1
		%assign i i+1
	%endrep
%endmacro

%macro ccall 1-*
	%if %0 > ccall.reg.ct
		%assign ct ccall.reg.ct
	%else
		%assign ct %0-1
	%endif
	%assign i 0
	%rotate 1
	%rep ct
		; if the function is well-behaved, all its arguments fit
		; in registers. if not, things get ugly. see below.
		mov ccall.reg. %+ i, %1
		%assign i i+1
		%rotate 1
	%endrep
	%if %0 > ccall.reg.ct
		; if there are more parameters to a C function than the
		; number of permitted registers, they must be pushed in
		; reverse order to the stack.
		; keep your function signatures under control, people.
		%assign ct (%0-ct)-1
		%rotate ct
		%rep ct
			%rotate -1
			push %1
		%endrep
		%rotate ct
		push rsp ; it's our responsibility to preserve the stack
	%endif
	call %1
	%if %0 > ccall.reg.ct
		; the extra arguments are still on the stack; time to
		; dump them back into the Garbage Zone
		pop rsp
	%endif
%endmacro