2008-01-30 15:32:49 +03:00
/*
2009-02-03 20:02:36 +03:00
x86 function call convention , 64 - bit :
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
arguments | callee - saved | extra caller - saved | return
[ callee - clobbered ] | | [ callee - clobbered ] |
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
rdi rsi rdx rcx r8 - 9 | rbx rbp [ * ] r12 - 15 | r10 - 11 | rax , rdx [ * * ]
( rsp is obviously invariant across normal function calls . ( gcc can ' merge '
functions when it sees tail - call optimization possibilities ) rflags is
clobbered . Leftover arguments are passed over the stack frame . )
[ * ] In the frame - pointers case rbp is fixed to the stack frame .
[ * * ] for struct return values wider than 64 bits the return convention is a
bit more complex : up to 128 bits width we return small structures
straight in rax , rdx . For structures larger than that ( 3 words or
larger ) the caller puts a pointer to an on - stack return struct
[ allocated in the caller ' s stack frame ] into the first argument - i . e .
into rdi . All other arguments shift up by one in this case .
Fortunately this case is rare in the kernel .
For 32 - bit we have the following conventions - kernel is built with
- mregparm = 3 and - freg - struct - return :
x86 function calling convention , 32 - bit :
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
arguments | callee - saved | extra caller - saved | return
[ callee - clobbered ] | | [ callee - clobbered ] |
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
eax edx ecx | ebx edi esi ebp [ * ] | < none > | eax , edx [ * * ]
( here too esp is obviously invariant across normal function calls . eflags
is clobbered . Leftover arguments are passed over the stack frame . )
[ * ] In the frame - pointers case ebp is fixed to the stack frame .
[ * * ] We build with - freg - struct - return , which on 32 - bit means similar
semantics as on 64 - bit : edx can be used for a second return value
( i . e . covering integer and structure sizes up to 64 bits ) - after that
it gets more complex and more expensive : 3 - word or larger struct returns
get done in the caller ' s frame and the pointer to the return struct goes
into regparm0 , i . e . eax - the other arguments shift up and the
function ' s register parameters degenerate to regparm = 2 in essence .
*/
2011-06-01 00:21:51 +04:00
# include "dwarf2.h"
2009-02-03 20:02:36 +03:00
/*
2010-10-19 17:52:26 +04:00
* 64 - bit system call stack frame layout defines and helpers , for
* assembly code ( note that the seemingly unnecessary parentheses
* are to prevent cpp from inserting spaces in expressions that get
* passed to macros ) :
2008-01-30 15:32:49 +03:00
*/
2005-04-17 02:20:36 +04:00
2010-10-19 17:52:26 +04:00
# define R15 (0)
# define R14 (8)
# define R13 (16)
# define R12 (24)
# define RBP (32)
# define RBX (40)
2005-04-17 02:20:36 +04:00
2009-02-03 20:02:36 +03:00
/* arguments: interrupts/non tracing syscalls only save up to here: */
2010-10-19 17:52:26 +04:00
# define R11 (48)
# define R10 (56)
# define R9 (64)
# define R8 (72)
# define RAX (80)
# define RCX (88)
# define RDX (96)
# define RSI (104)
# define RDI (112)
# define ORIG_RAX (120) /* + error_code */
2008-01-30 15:32:49 +03:00
/* end of arguments */
2009-02-03 20:02:36 +03:00
/* cpu exception frame or undefined in case of fast syscall: */
2010-10-19 17:52:26 +04:00
# define RIP (128)
# define CS (136)
# define EFLAGS (144)
# define RSP (152)
# define SS (160)
2008-01-30 15:32:49 +03:00
# define ARGOFFSET R11
# define SWFRAME ORIG_RAX
2005-04-17 02:20:36 +04:00
2011-06-01 00:21:52 +04:00
. macro SAVE_ARGS addskip = 0 , save_rcx = 1 , save_r891011 = 1
2008-01-30 15:32:49 +03:00
subq $ 9 * 8 + \ addskip , % rsp
2005-04-17 02:20:36 +04:00
CFI_ADJUST_CFA_OFFSET 9 * 8 + \ addskip
2011-06-01 00:21:51 +04:00
movq_cfi rdi , 8 * 8
movq_cfi rsi , 7 * 8
movq_cfi rdx , 6 * 8
2011-06-01 00:21:52 +04:00
. if \ save_rcx
2011-06-01 00:21:51 +04:00
movq_cfi rcx , 5 * 8
2005-04-17 02:20:36 +04:00
. endif
2011-06-01 00:21:51 +04:00
movq_cfi rax , 4 * 8
2011-06-01 00:21:52 +04:00
. if \ save_r891011
2011-06-01 00:21:51 +04:00
movq_cfi r8 , 3 * 8
movq_cfi r9 , 2 * 8
movq_cfi r10 , 1 * 8
movq_cfi r11 , 0 * 8
2005-04-17 02:20:36 +04:00
. endif
2011-06-01 00:21:51 +04:00
2005-04-17 02:20:36 +04:00
. endm
2010-10-19 17:52:26 +04:00
# define ARG_SKIP (9*8)
2008-01-30 15:32:49 +03:00
. macro RESTORE_ARGS skiprax = 0 , addskip = 0 , skiprcx = 0 , skipr11 = 0 , \
skipr8910 = 0 , skiprdx = 0
2005-04-17 02:20:36 +04:00
. if \ skipr11
. else
2011-06-01 00:21:51 +04:00
movq_cfi_restore 0 * 8 , r11
2005-04-17 02:20:36 +04:00
. endif
2011-06-01 00:21:51 +04:00
2005-04-17 02:20:36 +04:00
. if \ skipr8910
. else
2011-06-01 00:21:51 +04:00
movq_cfi_restore 1 * 8 , r10
movq_cfi_restore 2 * 8 , r9
movq_cfi_restore 3 * 8 , r8
2005-04-17 02:20:36 +04:00
. endif
2011-06-01 00:21:51 +04:00
2005-04-17 02:20:36 +04:00
. if \ skiprax
. else
2011-06-01 00:21:51 +04:00
movq_cfi_restore 4 * 8 , rax
2005-04-17 02:20:36 +04:00
. endif
2011-06-01 00:21:51 +04:00
2005-04-17 02:20:36 +04:00
. if \ skiprcx
. else
2011-06-01 00:21:51 +04:00
movq_cfi_restore 5 * 8 , rcx
2005-04-17 02:20:36 +04:00
. endif
2011-06-01 00:21:51 +04:00
2005-04-17 02:20:36 +04:00
. if \ skiprdx
. else
2011-06-01 00:21:51 +04:00
movq_cfi_restore 6 * 8 , rdx
2005-04-17 02:20:36 +04:00
. endif
2011-06-01 00:21:51 +04:00
movq_cfi_restore 7 * 8 , rsi
movq_cfi_restore 8 * 8 , rdi
2005-04-17 02:20:36 +04:00
. if ARG_SKIP + \ addskip > 0
2008-01-30 15:32:49 +03:00
addq $ ARG_SKIP + \ addskip , % rsp
2005-04-17 02:20:36 +04:00
CFI_ADJUST_CFA_OFFSET - ( ARG_SKIP + \ addskip )
. endif
2008-01-30 15:32:49 +03:00
. endm
2005-04-17 02:20:36 +04:00
2008-07-09 13:38:07 +04:00
. macro LOAD_ARGS offset , skiprax = 0
2008-01-30 15:32:49 +03:00
movq \ offset ( % rsp ) , % r11
movq \ offset + 8 ( % rsp ) , % r10
movq \ offset + 16 ( % rsp ) , % r9
movq \ offset + 24 ( % rsp ) , % r8
movq \ offset + 40 ( % rsp ) , % rcx
movq \ offset + 48 ( % rsp ) , % rdx
movq \ offset + 56 ( % rsp ) , % rsi
movq \ offset + 64 ( % rsp ) , % rdi
2008-07-09 13:38:07 +04:00
. if \ skiprax
. else
2008-01-30 15:32:49 +03:00
movq \ offset + 72 ( % rsp ) , % rax
2008-07-09 13:38:07 +04:00
. endif
2005-04-17 02:20:36 +04:00
. endm
2008-01-30 15:32:49 +03:00
2010-10-19 17:52:26 +04:00
# define REST_SKIP (6*8)
2008-01-30 15:32:49 +03:00
2005-04-17 02:20:36 +04:00
. macro SAVE_REST
2008-01-30 15:32:49 +03:00
subq $ REST_SKIP , % rsp
2005-04-17 02:20:36 +04:00
CFI_ADJUST_CFA_OFFSET REST_SKIP
2011-06-01 00:21:51 +04:00
movq_cfi rbx , 5 * 8
movq_cfi rbp , 4 * 8
movq_cfi r12 , 3 * 8
movq_cfi r13 , 2 * 8
movq_cfi r14 , 1 * 8
movq_cfi r15 , 0 * 8
2008-01-30 15:32:49 +03:00
. endm
2005-04-17 02:20:36 +04:00
. macro RESTORE_REST
2011-06-01 00:21:51 +04:00
movq_cfi_restore 0 * 8 , r15
movq_cfi_restore 1 * 8 , r14
movq_cfi_restore 2 * 8 , r13
movq_cfi_restore 3 * 8 , r12
movq_cfi_restore 4 * 8 , rbp
movq_cfi_restore 5 * 8 , rbx
2008-01-30 15:32:49 +03:00
addq $ REST_SKIP , % rsp
2005-04-17 02:20:36 +04:00
CFI_ADJUST_CFA_OFFSET - ( REST_SKIP )
. endm
2008-01-30 15:32:49 +03:00
2005-04-17 02:20:36 +04:00
. macro SAVE_ALL
SAVE_ARGS
SAVE_REST
. endm
2008-01-30 15:32:49 +03:00
2005-04-17 02:20:36 +04:00
. macro RESTORE_ALL addskip = 0
RESTORE_REST
2008-01-30 15:32:49 +03:00
RESTORE_ARGS 0 , \ addskip
2005-04-17 02:20:36 +04:00
. endm
. macro icebp
. byte 0xf1
. endm