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 "adr r0, jmp_target\n" 47 "add r0, r0, $1\n" 48 #else 49 "adr r0, jmp_target\n" 50 #endif 51 "mov r1, %1\n" 52 "mov r2, sp\n" 53 "stm r1!, {r0, r2, r4, r5, r6, r7}\n" 54 "b 2f\n" 55 "jmp_target: " 56 "mov %0, #1\n" 57 "2:\n" 58 : "+l" (r) 59 : "l" (&jmp->target) 60 : "r0", "r1", "r2", "r3", /* "r4", "r5", "r6", "r7", */ 61 "r8", "r9", "r10", "r11", /* sp, */ "ip", "lr", 62 "cc", "memory"); 63 #endif 64 65 return r; 66 } 67 68 static inline __noreturn void longjmp(jmp_buf jmp) 69 { 70 #ifdef CONFIG_ARM64 71 asm volatile( 72 "ldr x0, %0\n" 73 "ldr x1, %3\n" 74 "mov sp, x1\n" 75 "ldp x26, x27, %1\n" 76 "ldp x28, x25, %2\n" 77 "mov x29, x25\n" 78 "br x0\n" 79 : 80 : "m" (jmp->target), "m" (jmp->regs[0]), "m" (jmp->regs[2]), 81 "m" (jmp->regs[4]) 82 : "x0", "x1", "x25", "x26", "x27", "x28"); 83 #else 84 asm volatile( 85 "mov r1, %0\n" 86 "ldm r1!, {r0, r2, r4, r5, r6, r7}\n" 87 "mov sp, r2\n" 88 "bx r0\n" 89 : 90 : "l" (&jmp->target) 91 : "r1"); 92 #endif 93 94 while (1) { } 95 } 96 97 98 #endif /* _SETJMP_H_ */ 99