1 | /* $NetBSD: frame_regs.h,v 1.7 2015/04/26 18:49:39 mrg Exp $ */ |
2 | |
3 | #ifndef _AMD64_FRAME_REGS_H_ |
4 | #define _AMD64_FRAME_REGS_H_ |
5 | |
6 | /* |
7 | * amd64 registers (and friends) ordered as in a trap/interrupt/syscall frame. |
8 | * Also the indexes into the 'general register state' (__greg_t) passed to |
9 | * userland. |
10 | * Historically they were in the same order, but the order in the frames |
11 | * has been changed to improve syscall efficiency. |
12 | * |
13 | * Notes: |
14 | * 1) gdb (amd64nbsd-tdep.c) has a lookup table that assumes the __greg_t |
15 | * ordering. |
16 | * 2) src/lib/libc/arch/x86_64/gen/makecontext.c assumes that the first |
17 | * 6 entries in the __greg_t array match the registers used to pass |
18 | * function arguments. |
19 | * 3) The 'struct reg' from machine/reg.h has to match __greg_t. |
20 | * Since they are both arrays and indexed with the same tokens this |
21 | * shouldn't be a problem, but is rather confusing. |
22 | * This assumption is made in a lot of places! |
23 | * 4) There might be other code out there that relies on the ordering. |
24 | * |
25 | * The first entries below match the registers used for syscall arguments |
26 | * (%rcx is destroyed by the syscall instruction, the libc system call |
27 | * stubs copy %rcx to %r10). |
28 | * arg6-arg9 are copied from the user stack for system calls with more |
29 | * than 6 args (SYS_MAXSYSARGS is 8, + 2 entries for SYS___SYSCALL). |
30 | */ |
31 | #define _FRAME_REG(greg, freg) \ |
32 | greg(rdi, RDI, 0) /* tf_rdi */ \ |
33 | greg(rsi, RSI, 1) /* tf_rsi */ \ |
34 | greg(rdx, RDX, 2) /* tf_rdx */ \ |
35 | greg(r10, R10, 6) /* tf_r10 */ \ |
36 | greg(r8, R8, 4) /* tf_r8 */ \ |
37 | greg(r9, R9, 5) /* tf_r9 */ \ |
38 | freg(arg6, @, @) /* tf_arg6: syscall arg from stack */ \ |
39 | freg(arg7, @, @) /* tf_arg7: syscall arg from stack */ \ |
40 | freg(arg8, @, @) /* tf_arg8: syscall arg from stack */ \ |
41 | freg(arg9, @, @) /* tf_arg9: syscall arg from stack */ \ |
42 | greg(rcx, RCX, 3) /* tf_rcx */ \ |
43 | greg(r11, R11, 7) /* tf_r11 */ \ |
44 | greg(r12, R12, 8) /* tf_r12 */ \ |
45 | greg(r13, R13, 9) /* tf_r13 */ \ |
46 | greg(r14, R14, 10) /* tf_r14 */ \ |
47 | greg(r15, R15, 11) /* tf_r15 */ \ |
48 | greg(rbp, RBP, 12) /* tf_rbp */ \ |
49 | greg(rbx, RBX, 13) /* tf_rbx */ \ |
50 | greg(rax, RAX, 14) /* tf_rax */ \ |
51 | greg(gs, GS, 15) /* tf_gs */ \ |
52 | greg(fs, FS, 16) /* tf_fs */ \ |
53 | greg(es, ES, 17) /* tf_es */ \ |
54 | greg(ds, DS, 18) /* tf_ds */ \ |
55 | greg(trapno, TRAPNO, /* tf_trapno */ \ |
56 | 19) \ |
57 | /* Below portion defined in hardware */ \ |
58 | greg(err, ERR, 20) /* tf_err: Dummy inserted if not defined */ \ |
59 | greg(rip, RIP, 21) /* tf_rip */ \ |
60 | greg(cs, CS, 22) /* tf_cs */ \ |
61 | greg(rflags, RFLAGS, /* tf_rflags */ \ |
62 | 23) \ |
63 | /* These are pushed unconditionally on the x86-64 */ \ |
64 | greg(rsp, RSP, 24) /* tf_rsp */ \ |
65 | greg(ss, SS, 25) /* tf_ss */ |
66 | |
67 | #define _FRAME_NOREG(reg, REG, idx) |
68 | |
69 | #define _FRAME_GREG(greg) _FRAME_REG(greg, _FRAME_NOREG) |
70 | |
71 | #endif |
72 | |