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