mirror of
https://github.com/brain-hackers/u-boot-brain
synced 2024-09-10 14:53:26 +09:00
![Alexander Graf](/assets/img/avatar_default.png)
The setjmp/longjmp implementation did not work on thumb1 implementations because it used instruction encodings that don't exist on thumb1 yet. This patch limits itself to thumb1 instruction set for 32bit arm and removes a superfluous printf along the way. Signed-off-by: Alexander Graf <agraf@suse.de>
99 lines
1.8 KiB
C
99 lines
1.8 KiB
C
/*
|
|
* (C) Copyright 2016
|
|
* Alexander Graf <agraf@suse.de>
|
|
*
|
|
* SPDX-License-Identifier: GPL-2.0+
|
|
*/
|
|
|
|
#ifndef _SETJMP_H_
|
|
#define _SETJMP_H_ 1
|
|
|
|
struct jmp_buf_data {
|
|
ulong target;
|
|
ulong regs[5];
|
|
};
|
|
|
|
typedef struct jmp_buf_data jmp_buf[1];
|
|
|
|
static inline int setjmp(jmp_buf jmp)
|
|
{
|
|
long r = 0;
|
|
|
|
#ifdef CONFIG_ARM64
|
|
asm volatile(
|
|
"adr x1, jmp_target\n"
|
|
"str x1, %1\n"
|
|
"stp x26, x27, %2\n"
|
|
"stp x28, x29, %3\n"
|
|
"mov x1, sp\n"
|
|
"str x1, %4\n"
|
|
"b 2f\n"
|
|
"jmp_target: "
|
|
"mov %0, #1\n"
|
|
"2:\n"
|
|
: "+r" (r), "=m" (jmp->target),
|
|
"=m" (jmp->regs[0]), "=m" (jmp->regs[2]),
|
|
"=m" (jmp->regs[4])
|
|
:
|
|
: "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7",
|
|
"x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15",
|
|
"x16", "x17", "x18", "x19", "x20", "x21", "x22",
|
|
"x23", "x24", "x25", /* x26, x27, x28, x29, sp */
|
|
"x30", "cc", "memory");
|
|
#else
|
|
asm volatile(
|
|
#ifdef CONFIG_SYS_THUMB_BUILD
|
|
"adr r0, jmp_target\n"
|
|
"add r0, r0, $1\n"
|
|
#else
|
|
"adr r0, jmp_target\n"
|
|
#endif
|
|
"mov r1, %1\n"
|
|
"mov r2, sp\n"
|
|
"stm r1!, {r0, r2, r4, r5, r6, r7}\n"
|
|
"b 2f\n"
|
|
"jmp_target: "
|
|
"mov %0, #1\n"
|
|
"2:\n"
|
|
: "+l" (r)
|
|
: "l" (&jmp->target)
|
|
: "r0", "r1", "r2", "r3", /* "r4", "r5", "r6", "r7", */
|
|
"r8", "r9", "r10", "r11", /* sp, */ "ip", "lr",
|
|
"cc", "memory");
|
|
#endif
|
|
|
|
return r;
|
|
}
|
|
|
|
static inline __noreturn void longjmp(jmp_buf jmp)
|
|
{
|
|
#ifdef CONFIG_ARM64
|
|
asm volatile(
|
|
"ldr x0, %0\n"
|
|
"ldr x1, %3\n"
|
|
"mov sp, x1\n"
|
|
"ldp x26, x27, %1\n"
|
|
"ldp x28, x25, %2\n"
|
|
"mov x29, x25\n"
|
|
"br x0\n"
|
|
:
|
|
: "m" (jmp->target), "m" (jmp->regs[0]), "m" (jmp->regs[2]),
|
|
"m" (jmp->regs[4])
|
|
: "x0", "x1", "x25", "x26", "x27", "x28");
|
|
#else
|
|
asm volatile(
|
|
"mov r1, %0\n"
|
|
"ldm r1!, {r0, r2, r4, r5, r6, r7}\n"
|
|
"mov sp, r2\n"
|
|
"bx r0\n"
|
|
:
|
|
: "l" (&jmp->target)
|
|
: "r1");
|
|
#endif
|
|
|
|
while (1) { }
|
|
}
|
|
|
|
|
|
#endif /* _SETJMP_H_ */
|