1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
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
|