xref: /rk3399_rockchip-uboot/arch/arm/include/asm/setjmp.h (revision 97d44b1f5c328af97d3c381c77858c8dd32c8e20)
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