blob: eb0628b6947943adee88595fcfbdd7006c1a0d39 [file] [log] [blame]
# Kernel implementations for a slim setjmp/longjmp.
#
# int setjmp(struct jmpbuf *env);
# void longjmp(struct jmpbuf *env, int val);
#
# Callers *must* clobber all callee-saved registers first, e.g.:
# asm volatile ("" : : : "rbx", "r12", "r13", "r14", "r15");
# The jmpbuf struct is defined as below:
# struct jmpbuf {
# uintptr_t retaddr; // return address
# uintreg_t rsp; // post-return rsp
# uintreg_t rbp;
# };
.text
.align 4
.globl slim_setjmp
.type slim_setjmp, @function
slim_setjmp:
xorl %eax,%eax # Zero out the return value for our first return
pop %rsi # Temporarily grab the return address and adjust %rsp
movq %rsi,(%rdi) # Save the return address
movq %rsp,8(%rdi) # The adjusted %rsp is the post-return %rsp
# (see longjmp)
movq %rbp,16(%rdi)
push %rsi # Restore stuff to make the call/return stack happy
ret
.size slim_setjmp,.-slim_setjmp
.text
.align 4
.globl longjmp
.type longjmp, @function
longjmp:
movl %esi,%eax # Set the return value to val (32-bit int)
movq 16(%rdi),%rbp
movq 8(%rdi),%rsp # Set the post-return %rsp
jmp *(%rdi) # Jump back to setjmp callsite (no ret necessary)
.size longjmp,.-longjmp