diff options
Diffstat (limited to 'qemu/roms/ipxe/src/arch/x86_64/core/setjmp.S')
-rw-r--r-- | qemu/roms/ipxe/src/arch/x86_64/core/setjmp.S | 65 |
1 files changed, 65 insertions, 0 deletions
diff --git a/qemu/roms/ipxe/src/arch/x86_64/core/setjmp.S b/qemu/roms/ipxe/src/arch/x86_64/core/setjmp.S new file mode 100644 index 000000000..e43200d7b --- /dev/null +++ b/qemu/roms/ipxe/src/arch/x86_64/core/setjmp.S @@ -0,0 +1,65 @@ +FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ) + + .text + .code64 + + /* Must match jmp_buf structure layout */ + .struct 0 +env_retaddr: .quad 0 +env_stack: .quad 0 +env_rbx: .quad 0 +env_rbp: .quad 0 +env_r12: .quad 0 +env_r13: .quad 0 +env_r14: .quad 0 +env_r15: .quad 0 + .previous + +/* + * Save stack context for non-local goto + */ + .globl setjmp +setjmp: + /* Save return address */ + movq 0(%rsp), %rax + movq %rax, env_retaddr(%rdi) + /* Save stack pointer */ + movq %rsp, env_stack(%rdi) + /* Save other registers */ + movq %rbx, env_rbx(%rdi) + movq %rbp, env_rbp(%rdi) + movq %r12, env_r12(%rdi) + movq %r13, env_r13(%rdi) + movq %r14, env_r14(%rdi) + movq %r15, env_r15(%rdi) + /* Return 0 when returning as setjmp() */ + xorq %rax, %rax + ret + .size setjmp, . - setjmp + +/* + * Non-local jump to a saved stack context + */ + .globl longjmp +longjmp: + /* Get result in %rax */ + movq %rsi, %rax + /* Force result to non-zero */ + testq %rax, %rax + jnz 1f + incq %rax +1: /* Restore stack pointer */ + movq env_stack(%rdi), %rsp + /* Restore other registers */ + movq env_rbx(%rdi), %rbx + movq env_rbp(%rdi), %rbp + movq env_r12(%rdi), %r12 + movq env_r13(%rdi), %r13 + movq env_r14(%rdi), %r14 + movq env_r15(%rdi), %r15 + /* Replace return address on the new stack */ + popq %rcx /* discard */ + pushq env_retaddr(%rdi) + /* Return to setjmp() caller */ + ret + .size longjmp, . - longjmp |