summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakob Kaivo <jkk@ung.org>2019-03-06 21:18:36 -0500
committerJakob Kaivo <jkk@ung.org>2019-03-06 21:18:36 -0500
commite3deb8708ec4429c35a6b5847f58a7b5e11fbe8a (patch)
treef44c822ddec2803058f58693094198bcef981a86
parent1a128358dc00e66394fcdc03b0f113833bdca31b (diff)
working setjmp()/longjmp()
-rw-r--r--src/nonstd/x86-64.s54
-rw-r--r--src/setjmp/longjmp.c13
-rw-r--r--src/setjmp/setjmp.c14
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