-/* setjmp and longjmp. Use of these functions is deprecated. */
-
-FILE_LICENCE ( GPL2_OR_LATER )
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )
.text
.arch i386
.code32
-
-/**************************************************************************
-SETJMP - Save stack context for non-local goto
-**************************************************************************/
+
+ /* Must match jmp_buf structure layout */
+ .struct 0
+env_retaddr: .long 0
+env_stack: .long 0
+env_ebx: .long 0
+env_esi: .long 0
+env_edi: .long 0
+env_ebp: .long 0
+ .previous
+
+/*
+ * Save stack context for non-local goto
+ */
.globl setjmp
setjmp:
- movl 4(%esp),%ecx /* jmpbuf */
- movl 0(%esp),%edx /* return address */
- movl %edx,0(%ecx)
- movl %ebx,4(%ecx)
- movl %esp,8(%ecx)
- movl %ebp,12(%ecx)
- movl %esi,16(%ecx)
- movl %edi,20(%ecx)
- movl $0,%eax
+ /* Get jmp_buf pointer in %edx */
+ movl 4(%esp),%edx
+ /* Save return address */
+ movl 0(%esp),%eax
+ movl %eax, env_retaddr(%edx)
+ /* Save stack pointer */
+ movl %esp, env_stack(%edx)
+ /* Save other registers */
+ movl %ebx, env_ebx(%edx)
+ movl %esi, env_esi(%edx)
+ movl %edi, env_edi(%edx)
+ movl %ebp, env_ebp(%edx)
+ /* Return 0 when returning as setjmp() */
+ xorl %eax, %eax
ret
+ .size setjmp, . - setjmp
-/**************************************************************************
-LONGJMP - Non-local jump to a saved stack context
-**************************************************************************/
+/*
+ * Non-local jump to a saved stack context
+ */
.globl longjmp
longjmp:
- movl 4(%esp),%edx /* jumpbuf */
- movl 8(%esp),%eax /* result */
- movl 0(%edx),%ecx
- movl 4(%edx),%ebx
- movl 8(%edx),%esp
- movl 12(%edx),%ebp
- movl 16(%edx),%esi
- movl 20(%edx),%edi
- cmpl $0,%eax
- jne 1f
- movl $1,%eax
-1: movl %ecx,0(%esp)
+ /* Get jmp_buf pointer in %edx */
+ movl 4(%esp),%edx
+ /* Get result in %eax */
+ movl 8(%esp),%eax
+ /* Force result to non-zero */
+ testl %eax, %eax
+ jnz 1f
+ incl %eax
+1: /* Restore stack pointer */
+ movl env_stack(%edx), %esp
+ /* Restore other registers */
+ movl env_ebx(%edx), %esp
+ movl env_esi(%edx), %esp
+ movl env_edi(%edx), %esp
+ movl env_ebp(%edx), %ebp
+ /* Replace return address on the new stack */
+ popl %ecx /* discard */
+ pushl env_retaddr(%edx)
+ /* Return to setjmp() caller */
ret
+ .size longjmp, . - longjmp
-#ifndef ETHERBOOT_SETJMP_H
-#define ETHERBOOT_SETJMP_H
+#ifndef _SETJMP_H
+#define _SETJMP_H
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <stdint.h>
#include <realmode.h>
/** A jump buffer */
typedef struct {
+ /** Saved return address */
uint32_t retaddr;
+ /** Saved stack pointer */
+ uint32_t stack;
+ /** Saved %ebx */
uint32_t ebx;
- uint32_t esp;
- uint32_t ebp;
+ /** Saved %esi */
uint32_t esi;
+ /** Saved %edi */
uint32_t edi;
+ /** Saved %ebp */
+ uint32_t ebp;
} jmp_buf[1];
/** A real-mode-extended jump buffer */
typedef struct {
+ /** Jump buffer */
jmp_buf env;
- uint16_t rm_ss;
- uint16_t rm_sp;
+ /** Real-mode stack pointer */
+ segoff_t rm_stack;
} rmjmp_buf[1];
-extern int __asmcall setjmp ( jmp_buf env );
-extern void __asmcall longjmp ( jmp_buf env, int val );
+extern int __asmcall __attribute__ (( returns_twice ))
+setjmp ( jmp_buf env );
+
+extern void __asmcall __attribute__ (( noreturn ))
+longjmp ( jmp_buf env, int val );
-#define rmsetjmp( _env ) ( { \
- (_env)->rm_ss = rm_ss; \
- (_env)->rm_sp = rm_sp; \
- setjmp ( (_env)->env ); } ) \
+#define rmsetjmp( _env ) ( { \
+ (_env)->rm_stack.segment = rm_ss; \
+ (_env)->rm_stack.offset = rm_sp; \
+ setjmp ( (_env)->env ); } ) \
-#define rmlongjmp( _env, _val ) do { \
- rm_ss = (_env)->rm_ss; \
- rm_sp = (_env)->rm_sp; \
- longjmp ( (_env)->env, (_val) ); \
+#define rmlongjmp( _env, _val ) do { \
+ rm_ss = (_env)->rm_stack.segment; \
+ rm_sp = (_env)->rm_stack.offset; \
+ longjmp ( (_env)->env, (_val) ); \
} while ( 0 )
-#endif /* ETHERBOOT_SETJMP_H */
+#endif /* _SETJMP_H */