diff options
author | Joshua Haberman <jhaberman@gmail.com> | 2012-03-31 19:51:17 -0700 |
---|---|---|
committer | Joshua Haberman <jhaberman@gmail.com> | 2012-03-31 19:51:17 -0700 |
commit | 9a7037a2fa4f909eea561d6d89997b0b4203df9e (patch) | |
tree | 7171167f6602c658e31733993757b36f6ed16a9a /bindings/linux/setjmp.h | |
parent | cca4818eb7769d6e776bdc30516a5f871f1d6393 (diff) |
Got decoder & textprinter compiling in kernel mode.
Diffstat (limited to 'bindings/linux/setjmp.h')
-rw-r--r-- | bindings/linux/setjmp.h | 44 |
1 files changed, 44 insertions, 0 deletions
diff --git a/bindings/linux/setjmp.h b/bindings/linux/setjmp.h new file mode 100644 index 0000000..6da4313 --- /dev/null +++ b/bindings/linux/setjmp.h @@ -0,0 +1,44 @@ +/* + * upb - a minimalist implementation of protocol buffers. + * + * Copyright (c) 2012 Google Inc. See LICENSE for details. + * Author: Josh Haberman <jhaberman@gmail.com> + */ + +// Linux doesn't provide setjmp/longjmp, boo. + +typedef void *jmp_buf[3]; // rsp, rbp, rip + +static inline int _setjmp(jmp_buf env) { + register int ret asm ("%eax"); + __asm__ __volatile__ goto ( + " movq %%rsp, 0(%0)\n" // Save rsp + " movq %%rbp, 8(%0)\n" // Save rbp + " movq $1f, 16(%0)\n" // Save rip + " jmp %l[setup]\n" + "1:" + : // No outputs allowed (GCC limitation). + : "b" (env) // Input + : // All registers clobbered except rsp, which save in env. + "%rcx", "%rdx", "%rdi", "%rsi", "memory", "cc", + "%r8" , "%r9" , "%r10", "%r11", "%r12", "%r13", "%r14", "%r15" + : setup // Target labels. + ); + return ret; + +setup: + return 0; +} + +__attribute__((__noreturn__)) +static inline void _longjmp(jmp_buf env, int val) { + __asm__ __volatile__ ( + " movq 0(%0), %%rsp\n" // Restore rsp + " movq 8(%0), %%rbp\n" // Restore rbp + " movq %0, %%rbx\n" // Restore rbx + " jmpq *16(%0)\n" // Jump to saved rip + : // No output. + : "r" (env), "a" (val) // Move val to %eax + ); + __builtin_unreachable(); +} |