1 /* 2 * (C) Copyright 2016 3 * Alexander Graf <agraf@suse.de> 4 * 5 * SPDX-License-Identifier: GPL-2.0+ 6 */ 7 8 #ifndef _SETJMP_H_ 9 #define _SETJMP_H_ 1 10 11 struct jmp_buf_data { 12 ulong target; 13 ulong regs[5]; 14 }; 15 16 typedef struct jmp_buf_data jmp_buf[1]; 17 18 static inline int setjmp(jmp_buf jmp) 19 { 20 long r = 0; 21 22 #ifdef CONFIG_ARM64 23 asm volatile( 24 "adr x1, jmp_target\n" 25 "str x1, %1\n" 26 "stp x26, x27, %2\n" 27 "stp x28, x29, %3\n" 28 "mov x1, sp\n" 29 "str x1, %4\n" 30 "b 2f\n" 31 "jmp_target: " 32 "mov %0, #1\n" 33 "2:\n" 34 : "+r" (r), "=m" (jmp->target), 35 "=m" (jmp->regs[0]), "=m" (jmp->regs[2]), 36 "=m" (jmp->regs[4]) 37 : 38 : "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7", 39 "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", 40 "x16", "x17", "x18", "x19", "x20", "x21", "x22", 41 "x23", "x24", "x25", /* x26, x27, x28, x29, sp */ 42 "x30", "cc", "memory"); 43 #else 44 asm volatile( 45 #ifdef CONFIG_SYS_THUMB_BUILD 46 ".align 2\n" 47 "adr r0, jmp_target\n" 48 "add r0, r0, $1\n" 49 #else 50 "adr r0, jmp_target\n" 51 #endif 52 "mov r1, %1\n" 53 "mov r2, sp\n" 54 "stm r1!, {r0, r2, r4, r5, r6, r7}\n" 55 "b 2f\n" 56 ".align 2\n" 57 "jmp_target: \n" 58 "mov %0, #1\n" 59 "2:\n" 60 : "+l" (r) 61 : "l" (&jmp->target) 62 : "r0", "r1", "r2", "r3", /* "r4", "r5", "r6", "r7", */ 63 "r8", "r9", "r10", "r11", /* sp, */ "ip", "lr", 64 "cc", "memory"); 65 #endif 66 67 return r; 68 } 69 70 static inline __noreturn void longjmp(jmp_buf jmp) 71 { 72 #ifdef CONFIG_ARM64 73 asm volatile( 74 "ldr x0, %0\n" 75 "ldr x1, %3\n" 76 "mov sp, x1\n" 77 "ldp x26, x27, %1\n" 78 "ldp x28, x25, %2\n" 79 "mov x29, x25\n" 80 "br x0\n" 81 : 82 : "m" (jmp->target), "m" (jmp->regs[0]), "m" (jmp->regs[2]), 83 "m" (jmp->regs[4]) 84 : "x0", "x1", "x25", "x26", "x27", "x28"); 85 #else 86 asm volatile( 87 "mov r1, %0\n" 88 "ldm r1!, {r0, r2, r4, r5, r6, r7}\n" 89 "mov sp, r2\n" 90 "bx r0\n" 91 : 92 : "l" (&jmp->target) 93 : "r1"); 94 #endif 95 96 while (1) { } 97 } 98 99 100 #endif /* _SETJMP_H_ */ 101