[libc] Add x86_64 versions of setjmp() and longjmp()

None of the x86_64 builds currently have any way of invoking these
functions.  They are included only to avoid introducing unnecessary
architecture-specific dependencies into the self-test suite.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
pull/35/merge
Michael Brown 2015-04-07 06:40:42 +01:00
parent 00ff3d8bb3
commit fb2bedcff3
3 changed files with 100 additions and 0 deletions

View File

@ -40,6 +40,7 @@ endif
# x86_64-specific directories containing source files
#
SRCDIRS += arch/x86_64/core
SRCDIRS += arch/x86_64/prefix
# Include common x86 Makefile

View File

@ -0,0 +1,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

View File

@ -0,0 +1,34 @@
#ifndef _SETJMP_H
#define _SETJMP_H
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <stdint.h>
/** A jump buffer */
typedef struct {
/** Saved return address */
uint64_t retaddr;
/** Saved stack pointer */
uint64_t stack;
/** Saved %rbx */
uint64_t rbx;
/** Saved %rbp */
uint64_t rbp;
/** Saved %r12 */
uint64_t r12;
/** Saved %r13 */
uint64_t r13;
/** Saved %r14 */
uint64_t r14;
/** Saved %r15 */
uint64_t r15;
} jmp_buf[1];
extern int __asmcall __attribute__ (( returns_twice ))
setjmp ( jmp_buf env );
extern void __asmcall __attribute__ (( noreturn ))
longjmp ( jmp_buf env, int val );
#endif /* _SETJMP_H */