1 /* A setjmp.c for CRIS
2    Copyright (C) 1993-2005 Axis Communications.
3    All rights reserved.
4 
5    Redistribution and use in source and binary forms, with or without
6    modification, are permitted provided that the following conditions
7    are met:
8 
9    1. Redistributions of source code must retain the above copyright
10       notice, this list of conditions and the following disclaimer.
11 
12    2. Neither the name of Axis Communications nor the names of its
13       contributors may be used to endorse or promote products derived
14       from this software without specific prior written permission.
15 
16    THIS SOFTWARE IS PROVIDED BY AXIS COMMUNICATIONS AND ITS CONTRIBUTORS
17    ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19    A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL AXIS
20    COMMUNICATIONS OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
21    INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22    (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
23    SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24    HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
25    STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
26    IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27    POSSIBILITY OF SUCH DAMAGE.  */
28 
29 /* For benefit of CRIS v0..v3, we save and restore CCR to be able to
30    correctly handle DI/EI; otherwise there would be no reason to save it.
31    Note also that the "move x,ccr" does NOT affect
32    the DMA enable bits (E and D) of v0..v3.
33 
34    We do not save mof; it is call-clobbered.  It also does not exist in
35    v0..v8; it should be safe to read or write to it there, but better not.
36 
37    jmp_buf[0] - PC
38    jmp_buf[1] - SP (R14)
39    jmp_buf[2] - R13
40    jmp_buf[3] - R12
41    jmp_buf[4] - R11
42    jmp_buf[5] - R10
43    jmp_buf[6] - R9
44    jmp_buf[7] - R8
45    jmp_buf[8] - R7
46    jmp_buf[9] - R6
47    jmp_buf[10] - R5
48    jmp_buf[11] - R4
49    jmp_buf[12] - R3
50    jmp_buf[13] - R2
51    jmp_buf[14] - R1
52    jmp_buf[15] - R0
53    jmp_buf[16] - SRP
54    jmp_buf[17] - CCR
55    */
56 
57 #include <picolibc.h>
58 
59 #include <setjmp.h>
60 
61 int
setjmp(jmp_buf buf)62 setjmp (jmp_buf buf)
63 {
64   int ret;
65 #if defined (__arch_common_v10_v32) || defined (__arch_v32)
66   /* No offsets in the compatibility mode.  Also, movem saves in
67      different order on v10 than on v32, so we use single move
68      instructions instead, this not being a speed-prioritized operation.
69      And we don't save CCR or CCS; since long unuseful.  */
70   __asm__ __volatile__
71     ("move.d %1,$r13							\n\
72       move 0f,$mof							\n\
73       move $mof,[$r13+]							\n\
74       move.d $sp,[$r13+]						\n\
75       clear.d [$r13+]							\n\
76       move.d $r12,[$r13+]						\n\
77       move.d $r11,[$r13+]						\n\
78       move.d $r10,[$r13+]						\n\
79       moveq 1,$r9							\n\
80       move.d $r9,[$r13+]						\n\
81       move.d $r8,[$r13+]						\n\
82       move.d $r7,[$r13+]						\n\
83       move.d $r6,[$r13+]						\n\
84       move.d $r5,[$r13+]						\n\
85       move.d $r4,[$r13+]						\n\
86       move.d $r3,[$r13+]						\n\
87       move.d $r2,[$r13+]						\n\
88       move.d $r1,[$r13+]						\n\
89       move.d $r0,[$r13+]						\n\
90       move $srp,[$r13+]							\n\
91       clear.d [$r13+]							\n\
92       clear.d $r9							\n\
93 0:									\n\
94       move.d $r9,%0"
95 
96      /* Output.  */
97      : "=&r" (ret)
98 
99      /* Input.  */
100      : "r" (buf)
101 
102      /* Clobber.  */
103      : "r9", "r13", "memory");
104 #else /* not __arch_common_v10_v32 or __arch_v32 */
105 #ifdef __PIC__
106   __asm__ __volatile__
107     ("moveq 1,$r9							\n\
108       movem $sp,[%1+1*4]						\n\
109       move.d $pc,$r9							\n\
110       addq 0f-.,$r9							\n\
111       move.d $r9,[%1]							\n\
112       move $srp,[%1+16*4]						\n\
113       move $ccr,[%1+17*4]						\n\
114       clear.d $r9							\n\
115 0:									\n\
116       move.d $r9,%0"
117 
118      /* Output.  */
119      : "=&r" (ret)
120 
121      /* Input.  */
122      : "r" (buf)
123 
124      /* Clobber.  */
125      : "r9", "memory");
126 #else  /* not PIC */
127   __asm__ __volatile__
128     ("moveq 1,$r9							\n\
129       movem $sp,[%1+1*4]						\n\
130       move.d 0f,$r9							\n\
131       move.d $r9,[%1]							\n\
132       move $srp,[%1+16*4]						\n\
133       move $ccr,[%1+17*4]						\n\
134       clear.d $r9							\n\
135 0:									\n\
136       move.d $r9,%0"
137 
138      /* Output.  */
139      : "=&r" (ret)
140 
141      /* Input.  */
142      : "r" (buf)
143 
144      /* Clobber.  */
145      : "r9");
146 #endif /* not PIC */
147 #endif /* not __arch_common_v10_v32 or __arch_v32 */
148   return ret;
149 }
150 
151 void
longjmp(jmp_buf buf,int val)152 longjmp(jmp_buf buf, int val)
153 {
154 #if defined (__arch_common_v10_v32) || defined (__arch_v32)
155   __asm__ __volatile__
156     ("cmpq 0,%1								\n\
157       beq 0f								\n\
158       move.d %0,$r13	; In delay-slot.				\n\
159       addq 6*4,$r13							\n\
160       move.d %1,[$r13]							\n\
161       subq 6*4,$r13							\n\
162 0:\n"
163 #ifdef __arch_common_v10_v32
164      /* Cater to branch offset difference between v32 and v10.  We
165 	assume the branch above is 8-bit.  */
166 "     setf\n"
167 #endif
168 "     move [$r13+],$mof							\n\
169       move.d [$r13+],$sp						\n\
170       addq 4,$r13							\n\
171       move.d [$r13+],$r12						\n\
172       move.d [$r13+],$r11						\n\
173       move.d [$r13+],$r10						\n\
174       move.d [$r13+],$r9						\n\
175       move.d [$r13+],$r8						\n\
176       move.d [$r13+],$r7						\n\
177       move.d [$r13+],$r6						\n\
178       move.d [$r13+],$r5						\n\
179       move.d [$r13+],$r4						\n\
180       move.d [$r13+],$r3						\n\
181       move.d [$r13+],$r2						\n\
182       move.d [$r13+],$r1						\n\
183       move.d [$r13+],$r0						\n\
184       move [$r13+],$srp							\n\
185       move $mof,$r13							\n\
186       jump $r13								\n\
187       setf"
188 
189      /* No outputs.  */
190      :
191 
192      /* Inputs.  */
193      : "r" (buf), "r" (val)
194      : "r13", "memory");
195 
196 #else /* not __arch_common_v10_v32 or __arch_v32 */
197   __asm__ __volatile__
198     ("move [%0+17*4],$ccr						\n\
199       move [%0+16*4],$srp						\n\
200       test.d %1								\n\
201       beq 0f								\n\
202       nop								\n\
203       move.d %1,[%0+6*4]	; Offset for r9.			\n\
204 0:									\n\
205       movem [%0],$pc"
206 
207      /* No outputs.  */
208      :
209 
210      /* Inputs.  */
211      : "r" (buf), "r" (val)
212      : "memory");
213 #endif /* not __arch_common_v10_v32 or __arch_v32 */
214 }
215