diff options
| author | Jakob Kaivo <jkk@ung.org> | 2019-03-06 21:18:36 -0500 |
|---|---|---|
| committer | Jakob Kaivo <jkk@ung.org> | 2019-03-06 21:18:36 -0500 |
| commit | e3deb8708ec4429c35a6b5847f58a7b5e11fbe8a (patch) | |
| tree | f44c822ddec2803058f58693094198bcef981a86 | |
| parent | 1a128358dc00e66394fcdc03b0f113833bdca31b (diff) | |
working setjmp()/longjmp()
| -rw-r--r-- | src/nonstd/x86-64.s | 54 | ||||
| -rw-r--r-- | src/setjmp/longjmp.c | 13 | ||||
| -rw-r--r-- | src/setjmp/setjmp.c | 14 |
3 files changed, 68 insertions, 13 deletions
diff --git a/src/nonstd/x86-64.s b/src/nonstd/x86-64.s index 60aba7a1..f78a09fb 100644 --- a/src/nonstd/x86-64.s +++ b/src/nonstd/x86-64.s @@ -10,6 +10,60 @@ __syscall: syscall ret +.global __setjmp +__setjmp: + /* setjmp() in C sets env[0] to 0 */ + mov %rbx, 0x08(%rdi) + mov %rcx, 0x10(%rdi) + mov %rdx, 0x18(%rdi) + mov %rsp, 0x20(%rdi) + mov %rbp, 0x28(%rdi) + mov %rsi, 0x30(%rdi) + mov %rdi, 0x38(%rdi) + mov %r8, 0x40(%rdi) + mov %r9, 0x48(%rdi) + mov %r10, 0x50(%rdi) + mov %r11, 0x58(%rdi) + mov %r12, 0x60(%rdi) + mov %r13, 0x68(%rdi) + mov %r14, 0x70(%rdi) + mov %r15, 0x78(%rdi) + mov 0x00(%rbp), %rax + mov %rax, 0x80(%rdi) + mov 0x08(%rbp), %rax + mov %rax, 0x88(%rdi) + mov 0x00(%rsp), %rax + mov %rax, 0x90(%rdi) + xor %rax, %rax + ret + +.global __longjmp +__longjmp: + mov %rdi, %rax + mov 0x08(%rax), %rbx + mov 0x18(%rax), %rdx + mov 0x20(%rax), %rsp + mov 0x28(%rax), %rbp + mov 0x30(%rax), %rsi + mov 0x38(%rax), %rdi + mov 0x40(%rax), %r8 + mov 0x48(%rax), %r9 + mov 0x50(%rax), %r10 + mov 0x58(%rax), %r11 + mov 0x60(%rax), %r12 + mov 0x68(%rax), %r13 + mov 0x70(%rax), %r14 + mov 0x78(%rax), %r15 + mov 0x80(%rax), %rcx + mov %rcx, 0x00(%rbp) + mov 0x88(%rax), %rcx + mov %rcx, 0x08(%rbp) + mov 0x90(%rax), %rcx + mov %rcx, 0x00(%rsp) + mov 0x10(%rax), %rcx + mov 0x00(%rax), %rax + ret + /* FIXME: this seems to be unpossible to put in a shared library */ /* FIXME: it may be worthwhile to separate this into crt1.s */ .global _start diff --git a/src/setjmp/longjmp.c b/src/setjmp/longjmp.c index c8ed34af..57819ddb 100644 --- a/src/setjmp/longjmp.c +++ b/src/setjmp/longjmp.c @@ -4,13 +4,14 @@ _Noreturn void longjmp(jmp_buf env, int val) { - (void)env; - if (val == 0) { - val = 1; + extern _Noreturn void __longjmp(jmp_buf); + + /* use val if nonzero, otherwise 1 */ + env[0] = val ? val : 1; + + for (;;) { + __longjmp(env); } - /* Set env.return_register to val */ - /* Load all registers from env */ - for (;;); /* silence _Noreturn function returns warning */ } /*** diff --git a/src/setjmp/setjmp.c b/src/setjmp/setjmp.c index a297dd6f..a098997e 100644 --- a/src/setjmp/setjmp.c +++ b/src/setjmp/setjmp.c @@ -1,16 +1,13 @@ #include <setjmp.h> +#include "string.h" /** save program state **/ int setjmp(jmp_buf env) { - (void)env; - /* extern int setjmp(jmp_buf); */ - /* - RETURN(0, the environment has been saved by THIS()) - RETURN(NONZERO, the environment has been restored by FUNCTION(longjmp)) - */ - return 0; /* setjmp(env); */ + extern int __setjmp(jmp_buf); + memset(env, 0, sizeof(jmp_buf)); + return __setjmp(env); } /*** @@ -19,6 +16,9 @@ in the TYPEDEF(jmp_buf) ARGUMENT(env). ***/ /* +RETURN(0, the environment has been saved by THIS()) +RETURN(NONZERO, the environment has been restored by FUNCTION(longjmp)) + CONSTRAINT: entire controlling expression of a selection or iteration statement CONSTRAINT: one operand of a relational or equality operator which is the entire controlling expression of a selction or iteration statement CONSTRAINT: the operand of a unary ! as the entire controlling expression of a selection or iteration statement |
