diff options
Diffstat (limited to 'arch/x86/cpu/i386')
-rw-r--r-- | arch/x86/cpu/i386/Makefile | 1 | ||||
-rw-r--r-- | arch/x86/cpu/i386/setjmp.S | 61 |
2 files changed, 62 insertions, 0 deletions
diff --git a/arch/x86/cpu/i386/Makefile b/arch/x86/cpu/i386/Makefile index 2547bbaa63..0c47252610 100644 --- a/arch/x86/cpu/i386/Makefile +++ b/arch/x86/cpu/i386/Makefile @@ -6,3 +6,4 @@ obj-y += call64.o obj-y += cpu.o obj-y += interrupt.o +obj-y += setjmp.o diff --git a/arch/x86/cpu/i386/setjmp.S b/arch/x86/cpu/i386/setjmp.S new file mode 100644 index 0000000000..2ea1c6c766 --- /dev/null +++ b/arch/x86/cpu/i386/setjmp.S @@ -0,0 +1,61 @@ +/* + * Written by H. Peter Anvin <hpa@zytor.com> + * Brought in from Linux v4.4 and modified for U-Boot + * From Linux arch/um/sys-i386/setjmp.S + * + * SPDX-License-Identifier: GPL-2.0 + */ + +#define _REGPARM + +/* + * The jmp_buf is assumed to contain the following, in order: + * %ebx + * %esp + * %ebp + * %esi + * %edi + * <return address> + */ + + .text + .align 4 + .globl setjmp + .type setjmp, @function +setjmp: +#ifdef _REGPARM + movl %eax, %edx +#else + movl 4(%esp), %edx +#endif + popl %ecx /* Return address, and adjust the stack */ + xorl %eax, %eax /* Return value */ + movl %ebx, (%edx) + movl %esp, 4(%edx) /* Post-return %esp! */ + pushl %ecx /* Make the call/return stack happy */ + movl %ebp, 8(%edx) + movl %esi, 12(%edx) + movl %edi, 16(%edx) + movl %ecx, 20(%edx) /* Return address */ + ret + + /* Provide function size if needed */ + .size setjmp, .-setjmp + + .align 4 + .globl longjmp + .type longjmp, @function +longjmp: +#ifdef _REGPARM + xchgl %eax, %edx +#else + movl 4(%esp), %edx /* jmp_ptr address */ +#endif + movl (%edx), %ebx + movl 4(%edx), %esp + movl 8(%edx), %ebp + movl 12(%edx), %esi + movl 16(%edx), %edi + jmp *20(%edx) + + .size longjmp, .-longjmp |