| # 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 esp; // post-return esp |
| # uintreg_t ebx; // callee saved registers |
| # uintreg_t ebp; |
| # uintreg_t esi; |
| # uintreg_t edi; |
| # }; |
| |
| .text |
| .align 4 |
| .globl setjmp |
| .type setjmp, @function |
| setjmp: |
| movl 4(%esp),%edx # Grab a reference to the jmpbuf passed in |
| xorl %eax,%eax # Zero out the return value for our first return |
| popl %ecx # Temporarily grab the return address and adjust %rsp |
| movl %ecx,(%edx) # Save the return address |
| movl %esp,4(%edx) # The adjusted %esp is the post-return %esp (see longjmp) |
| movl %ebx,8(%edx) # Save all the callee saved registers into the jmpbuf |
| movl %ebp,12(%edx) |
| movl %esi,16(%edx) |
| movl %edi,20(%edx) |
| pushl %ecx # Restore stuff to make the call/return stack happy |
| ret |
| |
| .size setjmp,.-setjmp |
| |
| .text |
| .align 4 |
| .globl longjmp |
| .type longjmp, @function |
| longjmp: |
| movl 4(%esp),%edx # Grab a reference to the jmpbuf passed in |
| movl 8(%esp),%eax # Set the return value to val (32-bit int) |
| movl 20(%edx),%edi # Restore all the callee saved registers from the jmpbuf |
| movl 16(%edx),%esi |
| movl 12(%edx),%ebp |
| movl 8(%edx),%ebx |
| movl 4(%edx),%esp # Set the post-return %rsp |
| jmp *(%edx) # Jump back to setjmp callsite (no ret necessary) |
| |
| .size longjmp,.-longjmp |