|  | # Kernel implementations for setjmp/longjmp. | 
|  | # | 
|  | # int setjmp(struct jmpbuf *env); | 
|  | # void longjmp(struct jmpbuf *env, int val); | 
|  |  | 
|  | # The jmpbuf struct is defined as below: | 
|  | # struct jmpbuf { | 
|  | # 	uintptr_t retaddr; // return address | 
|  | # 	uintreg_t rsp;     // post-return rsp | 
|  | # 	uintreg_t rbx; | 
|  | # 	uintreg_t rbp; | 
|  | # 	uintreg_t r12; | 
|  | # 	uintreg_t r13; | 
|  | # 	uintreg_t r14; | 
|  | # 	uintreg_t r15; | 
|  | # }; | 
|  |  | 
|  | .text | 
|  | .align 4 | 
|  | .globl setjmp | 
|  | .type setjmp, @function | 
|  | 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 %rbx,16(%rdi) # Save all the callee saved registers into the jmpbuf | 
|  | movq %rbp,24(%rdi) | 
|  | movq %r12,32(%rdi) | 
|  | movq %r13,40(%rdi) | 
|  | movq %r14,48(%rdi) | 
|  | movq %r15,56(%rdi) | 
|  | push %rsi          # Restore stuff to make the call/return stack happy | 
|  | ret | 
|  |  | 
|  | .size setjmp,.-setjmp | 
|  |  | 
|  | .text | 
|  | .align 4 | 
|  | .globl longjmp | 
|  | .type longjmp, @function | 
|  | longjmp: | 
|  | movl %esi,%eax     # Set the return value to val (32-bit int) | 
|  | movq 56(%rdi),%r15 # Restore all the callee saved registers from the jmpbuf | 
|  | movq 48(%rdi),%r14 | 
|  | movq 40(%rdi),%r13 | 
|  | movq 32(%rdi),%r12 | 
|  | movq 24(%rdi),%rbp | 
|  | movq 16(%rdi),%rbx | 
|  | movq 8(%rdi),%rsp  # Set the post-return %rsp | 
|  | jmp *(%rdi)        # Jump back to setjmp callsite (no ret necessary) | 
|  |  | 
|  | .size longjmp,.-longjmp |