| 1 | /*	$NetBSD: frame_regs.h,v 1.8 2021/04/17 20:12:55 rillig 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 |