1 | /* |
---|
2 | * (c) 1999, Eric Valette valette@crf.canon.fr |
---|
3 | * |
---|
4 | * |
---|
5 | * This file contains the assembly code for the PowerPC |
---|
6 | * exception veneers for RTEMS. |
---|
7 | * |
---|
8 | * $Id$ |
---|
9 | */ |
---|
10 | |
---|
11 | #include <rtems/asm.h> |
---|
12 | #include <rtems/score/cpu.h> |
---|
13 | #include <bsp/vectors.h> |
---|
14 | #include <libcpu/raw_exception.h> |
---|
15 | |
---|
16 | #define SYNC \ |
---|
17 | sync; \ |
---|
18 | isync |
---|
19 | |
---|
20 | .text |
---|
21 | /* 603e shadows GPR0..GPR3 for certain exceptions. We must switch |
---|
22 | * that off before we can use the stack pointer. Note that this is |
---|
23 | * ONLY safe if the shadowing is actually active -- otherwise, r1 |
---|
24 | * is destroyed. We deliberately use r1 so problems become obvious |
---|
25 | * if this is abused! |
---|
26 | */ |
---|
27 | PUBLIC_VAR(tgpr_clr_exception_vector_code_prolog) |
---|
28 | SYM (tgpr_clr_exception_vector_code_prolog): |
---|
29 | mfmsr r1 |
---|
30 | rlwinm r1,r1,0,15,13 |
---|
31 | mtmsr r1 |
---|
32 | isync |
---|
33 | /* fall thru */ |
---|
34 | PUBLIC_VAR(default_exception_vector_code_prolog) |
---|
35 | SYM (default_exception_vector_code_prolog): |
---|
36 | /* |
---|
37 | * let room for exception frame |
---|
38 | */ |
---|
39 | stw r3, GPR3_OFFSET-EXCEPTION_FRAME_END(r1) |
---|
40 | mflr r3 |
---|
41 | stw r3, EXC_LR_OFFSET-EXCEPTION_FRAME_END(r1) |
---|
42 | bla push_normalized_frame |
---|
43 | |
---|
44 | /* IMPORTANT: prologue size MUST be < 32 bytes; 'altivec unavailable' exception |
---|
45 | * is already at 0xf20 :-( |
---|
46 | */ |
---|
47 | |
---|
48 | PUBLIC_VAR (default_exception_vector_code_prolog_size) |
---|
49 | PUBLIC_VAR (tgpr_clr_exception_vector_code_prolog_size) |
---|
50 | |
---|
51 | default_exception_vector_code_prolog_size = . - default_exception_vector_code_prolog |
---|
52 | tgpr_clr_exception_vector_code_prolog_size= . - tgpr_clr_exception_vector_code_prolog |
---|
53 | |
---|
54 | .p2align 5 |
---|
55 | PUBLIC_VAR (push_normalized_frame) |
---|
56 | SYM (push_normalized_frame): |
---|
57 | stwu r1, - (EXCEPTION_FRAME_END)(r1) |
---|
58 | mfcr r3 |
---|
59 | stw r3, EXC_CR_OFFSET(r1) |
---|
60 | /* |
---|
61 | * r3 = exception vector entry point |
---|
62 | * (256 * vector number) + few instructions |
---|
63 | */ |
---|
64 | /* |
---|
65 | * FIXME: vectors should distingish |
---|
66 | * all bits in mask 0x00003ff0 |
---|
67 | * and keep in mind that the LR/R3 contains the |
---|
68 | * address BEHIND the entry code |
---|
69 | */ |
---|
70 | mflr r3 |
---|
71 | /* mask upper bits in case vectors are in the high area (psim) */ |
---|
72 | rlwinm r3, r3, 32-5, 20, 31 |
---|
73 | #if defined(ASM_60X_VEC_VECTOR) |
---|
74 | /* |
---|
75 | * Remap altivec unavaliable (0xf20) to its vector number... |
---|
76 | */ |
---|
77 | cmplwi r3,(ASM_60X_VEC_VECTOR_OFFSET>>5) |
---|
78 | bne 1f |
---|
79 | li r3,ASM_60X_VEC_VECTOR<<3 |
---|
80 | 1: |
---|
81 | #endif |
---|
82 | /* |
---|
83 | * r3 = r3 >> 8 = vector # |
---|
84 | */ |
---|
85 | srwi r3,r3,3 |
---|
86 | stw r3, EXCEPTION_NUMBER_OFFSET(r1) |
---|
87 | stw r0, GPR0_OFFSET(r1) |
---|
88 | /* R2 should never change (EABI: pointer to .sdata2) - we |
---|
89 | * save it nevertheless.. |
---|
90 | */ |
---|
91 | stw r2, GPR2_OFFSET(r1) |
---|
92 | #if defined(ASM_VECTORS_CRITICAL) |
---|
93 | lis r0,ASM_VECTORS_CRITICAL@h |
---|
94 | ori r0,r0,ASM_VECTORS_CRITICAL@l |
---|
95 | rlwnm. r0,r0,r3,0,0 |
---|
96 | beq 1f |
---|
97 | /* |
---|
98 | * NOTE: srr2/3 are stored in slots SRR0/1 |
---|
99 | * for critical exceptions |
---|
100 | */ |
---|
101 | mfsrr2 r3 |
---|
102 | stw r3, SRR0_FRAME_OFFSET(r1) |
---|
103 | mfsrr3 r3 |
---|
104 | stw r3, SRR1_FRAME_OFFSET(r1) |
---|
105 | b 2f |
---|
106 | 1: |
---|
107 | #endif |
---|
108 | mfsrr0 r3 |
---|
109 | stw r3, SRR0_FRAME_OFFSET(r1) |
---|
110 | mfsrr1 r3 |
---|
111 | stw r3, SRR1_FRAME_OFFSET(r1) |
---|
112 | 2: |
---|
113 | /* |
---|
114 | * Save general purpose registers |
---|
115 | * Already saved in prolog : R1, R3, LR. |
---|
116 | * Saved a few line above : R0, R2 |
---|
117 | * |
---|
118 | * Manual says that "stmw" instruction may be slower than |
---|
119 | * series of individual "stw" but who cares about performance |
---|
120 | * for the DEFAULT exception handler? |
---|
121 | */ |
---|
122 | stmw r4, GPR4_OFFSET(r1) /* save R4->R31 */ |
---|
123 | |
---|
124 | mfctr r30 |
---|
125 | stw r30, EXC_CTR_OFFSET(r1) |
---|
126 | mfxer r28 |
---|
127 | stw r28, EXC_XER_OFFSET(r1) |
---|
128 | mfmsr r28 |
---|
129 | stw r28, EXC_MSR_OFFSET(r1) |
---|
130 | mfdar r28 |
---|
131 | stw r28, EXC_DAR_OFFSET(r1) |
---|
132 | /* |
---|
133 | * compute SP at exception entry |
---|
134 | */ |
---|
135 | addi r3, r1, EXCEPTION_FRAME_END |
---|
136 | /* |
---|
137 | * store it at the right place |
---|
138 | */ |
---|
139 | stw r3, GPR1_OFFSET(r1) |
---|
140 | |
---|
141 | #if defined(PPC_MSR_EXC_BITS) |
---|
142 | /* |
---|
143 | * Enable data and instruction address translation, exception nesting |
---|
144 | */ |
---|
145 | mfmsr r3 |
---|
146 | ori r3,r3, PPC_MSR_EXC_BITS |
---|
147 | mtmsr r3 |
---|
148 | SYNC |
---|
149 | #endif |
---|
150 | /* |
---|
151 | * Call C exception handler |
---|
152 | */ |
---|
153 | /* |
---|
154 | * store the execption frame address in r3 (first param) |
---|
155 | */ |
---|
156 | addi r3, r1, 0x8 |
---|
157 | /* clear CR[6] to make sure no varargs fn callee assumes there are FP args passed */ |
---|
158 | crxor 6,6,6 |
---|
159 | /* |
---|
160 | * globalExceptHdl(r3) |
---|
161 | */ |
---|
162 | addis r4, 0, globalExceptHdl@ha |
---|
163 | lwz r5, globalExceptHdl@l(r4) |
---|
164 | mtlr r5 |
---|
165 | blrl |
---|
166 | /* |
---|
167 | * Restore registers status |
---|
168 | */ |
---|
169 | lwz r31, EXC_CR_OFFSET(r1) |
---|
170 | mtcr r31 |
---|
171 | lwz r30, EXC_CTR_OFFSET(r1) |
---|
172 | mtctr r30 |
---|
173 | lwz r29, EXC_LR_OFFSET(r1) |
---|
174 | mtlr r29 |
---|
175 | lwz r28, EXC_XER_OFFSET(r1) |
---|
176 | mtxer r28 |
---|
177 | |
---|
178 | lmw r4, GPR4_OFFSET(r1) |
---|
179 | lwz r2, GPR2_OFFSET(r1) |
---|
180 | |
---|
181 | /* |
---|
182 | * Disable data and instruction translation. Mark path non recoverable |
---|
183 | */ |
---|
184 | #if defined(PPC_MSR_EXC_BITS) |
---|
185 | mfmsr r3 |
---|
186 | xori r3, r3, PPC_MSR_EXC_BITS |
---|
187 | mtmsr r3 |
---|
188 | SYNC |
---|
189 | #endif |
---|
190 | #if defined(ASM_VECTORS_CRITICAL) |
---|
191 | /* |
---|
192 | * determine, whether to restore from |
---|
193 | * srr0/1 or srr2/3 |
---|
194 | */ |
---|
195 | lis r0,ASM_VECTORS_CRITICAL@h |
---|
196 | lwz r3,EXCEPTION_NUMBER_OFFSET(r1) |
---|
197 | ori r0,r0,ASM_VECTORS_CRITICAL@l |
---|
198 | rlwnm. r0,r0,r3,0,0 |
---|
199 | beq 1f |
---|
200 | /* |
---|
201 | * NOTE: srr2/3 are stored in slots SRR0/1 |
---|
202 | * for critical exceptions |
---|
203 | */ |
---|
204 | lwz r3, SRR1_FRAME_OFFSET(r1) |
---|
205 | mtsrr3 r3 |
---|
206 | lwz r3, SRR0_FRAME_OFFSET(r1) |
---|
207 | mtsrr2 r3 |
---|
208 | lwz r3, GPR3_OFFSET(r1) |
---|
209 | lwz r0, GPR0_OFFSET(r1) |
---|
210 | /* DONT add back the frame size but reload the value |
---|
211 | * stored in the frame -- maybe the exception handler |
---|
212 | * changed it with good reason (e.g., gdb pushed a dummy frame) |
---|
213 | */ |
---|
214 | lwz r1, GPR1_OFFSET(r1) |
---|
215 | SYNC |
---|
216 | rfci |
---|
217 | 1: |
---|
218 | #endif |
---|
219 | /* |
---|
220 | * Restore rfi related settings |
---|
221 | */ |
---|
222 | |
---|
223 | lwz r3, SRR1_FRAME_OFFSET(r1) |
---|
224 | mtsrr1 r3 |
---|
225 | lwz r3, SRR0_FRAME_OFFSET(r1) |
---|
226 | mtsrr0 r3 |
---|
227 | |
---|
228 | lwz r3, GPR3_OFFSET(r1) |
---|
229 | lwz r0, GPR0_OFFSET(r1) |
---|
230 | /* DONT add back the frame size but reload the value |
---|
231 | * stored in the frame -- maybe the exception handler |
---|
232 | * changed it with good reason (e.g., gdb pushed a dummy frame) |
---|
233 | */ |
---|
234 | lwz r1, GPR1_OFFSET(r1) |
---|
235 | SYNC |
---|
236 | rfi |
---|