1 | /** |
---|
2 | * @file |
---|
3 | * |
---|
4 | * @ingroup ppc_exc |
---|
5 | * |
---|
6 | * @brief PowerPC Exceptions implementation. |
---|
7 | */ |
---|
8 | |
---|
9 | /* |
---|
10 | * Copyright (c) 2009 |
---|
11 | * embedded brains GmbH |
---|
12 | * Obere Lagerstr. 30 |
---|
13 | * D-82178 Puchheim |
---|
14 | * Germany |
---|
15 | * <rtems@embedded-brains.de> |
---|
16 | * |
---|
17 | * The license and distribution terms for this file may be |
---|
18 | * found in the file LICENSE in this distribution or at |
---|
19 | * http://www.rtems.com/license/LICENSE. |
---|
20 | */ |
---|
21 | |
---|
22 | #include "ppc_exc_asm_macros.h" |
---|
23 | |
---|
24 | .global ppc_exc_min_prolog_tmpl_naked |
---|
25 | |
---|
26 | ppc_exc_min_prolog_tmpl_naked: |
---|
27 | |
---|
28 | stwu r1, -EXCEPTION_FRAME_END(r1) |
---|
29 | stw VECTOR_REGISTER, VECTOR_OFFSET(r1) |
---|
30 | li VECTOR_REGISTER, 0 |
---|
31 | ba wrap_naked |
---|
32 | |
---|
33 | wrap_naked: |
---|
34 | |
---|
35 | /* Save scratch registers */ |
---|
36 | stw SCRATCH_REGISTER_0, SCRATCH_REGISTER_0_OFFSET(r1) |
---|
37 | stw SCRATCH_REGISTER_1, SCRATCH_REGISTER_1_OFFSET(r1) |
---|
38 | stw SCRATCH_REGISTER_2, SCRATCH_REGISTER_2_OFFSET(r1) |
---|
39 | |
---|
40 | /* Save volatile registers */ |
---|
41 | stw r0, GPR0_OFFSET(r1) |
---|
42 | stw r3, GPR3_OFFSET(r1) |
---|
43 | stw r8, GPR8_OFFSET(r1) |
---|
44 | stw r9, GPR9_OFFSET(r1) |
---|
45 | stw r10, GPR10_OFFSET(r1) |
---|
46 | stw r11, GPR11_OFFSET(r1) |
---|
47 | stw r12, GPR12_OFFSET(r1) |
---|
48 | |
---|
49 | /* Save CR */ |
---|
50 | mfcr SCRATCH_REGISTER_0 |
---|
51 | stw SCRATCH_REGISTER_0, EXC_CR_OFFSET(r1) |
---|
52 | |
---|
53 | /* Save SRR0 */ |
---|
54 | mfspr SCRATCH_REGISTER_0, srr0 |
---|
55 | stw SCRATCH_REGISTER_0, SRR0_FRAME_OFFSET(r1) |
---|
56 | |
---|
57 | /* Save SRR1 */ |
---|
58 | mfspr SCRATCH_REGISTER_0, srr1 |
---|
59 | stw SCRATCH_REGISTER_0, SRR1_FRAME_OFFSET(r1) |
---|
60 | |
---|
61 | /* Save CTR */ |
---|
62 | mfctr SCRATCH_REGISTER_0 |
---|
63 | stw SCRATCH_REGISTER_0, EXC_CTR_OFFSET(r1) |
---|
64 | |
---|
65 | /* Save XER */ |
---|
66 | mfxer SCRATCH_REGISTER_0 |
---|
67 | stw SCRATCH_REGISTER_0, EXC_XER_OFFSET(r1) |
---|
68 | |
---|
69 | /* Save LR */ |
---|
70 | mflr SCRATCH_REGISTER_0 |
---|
71 | stw SCRATCH_REGISTER_0, EXC_LR_OFFSET(r1) |
---|
72 | |
---|
73 | /* Load MSR bit mask */ |
---|
74 | lwz SCRATCH_REGISTER_0, ppc_exc_msr_bits@sdarel(r13) |
---|
75 | |
---|
76 | /* |
---|
77 | * Change the MSR if necessary (MMU, RI), remember decision in |
---|
78 | * non-volatile CR_MSR. |
---|
79 | */ |
---|
80 | cmpwi CR_MSR, SCRATCH_REGISTER_0, 0 |
---|
81 | bne CR_MSR, wrap_change_msr_naked |
---|
82 | |
---|
83 | wrap_change_msr_done_naked: |
---|
84 | |
---|
85 | /* |
---|
86 | * Call high level exception handler |
---|
87 | */ |
---|
88 | |
---|
89 | /* |
---|
90 | * Get the handler table index from the vector number. We have to |
---|
91 | * discard the exception type. Take only the least significant five |
---|
92 | * bits (= LAST_VALID_EXC + 1) from the vector register. Multiply by |
---|
93 | * four (= size of function pointer). |
---|
94 | */ |
---|
95 | rlwinm SCRATCH_REGISTER_1, VECTOR_REGISTER, 2, 25, 29 |
---|
96 | |
---|
97 | /* Load handler table address */ |
---|
98 | LA SCRATCH_REGISTER_0, ppc_exc_handler_table |
---|
99 | |
---|
100 | /* Load handler address */ |
---|
101 | lwzx SCRATCH_REGISTER_0, SCRATCH_REGISTER_0, SCRATCH_REGISTER_1 |
---|
102 | |
---|
103 | /* |
---|
104 | * First parameter = exception frame pointer + FRAME_LINK_SPACE |
---|
105 | * |
---|
106 | * We add FRAME_LINK_SPACE to the frame pointer because the high level |
---|
107 | * handler expects a BSP_Exception_frame structure. |
---|
108 | */ |
---|
109 | addi r3, r1, FRAME_LINK_SPACE |
---|
110 | |
---|
111 | /* |
---|
112 | * Second parameter = vector number (r4 is the VECTOR_REGISTER) |
---|
113 | * |
---|
114 | * Discard the exception type and store the vector number |
---|
115 | * in the vector register. Take only the least significant |
---|
116 | * five bits (= LAST_VALID_EXC + 1). |
---|
117 | */ |
---|
118 | rlwinm VECTOR_REGISTER, VECTOR_REGISTER, 0, 27, 31 |
---|
119 | |
---|
120 | /* Call handler */ |
---|
121 | mtctr SCRATCH_REGISTER_0 |
---|
122 | bctrl |
---|
123 | |
---|
124 | /* Restore MSR? */ |
---|
125 | bne CR_MSR, wrap_restore_msr_naked |
---|
126 | |
---|
127 | wrap_restore_msr_done_naked: |
---|
128 | |
---|
129 | /* Restore XER and CTR */ |
---|
130 | lwz SCRATCH_REGISTER_0, EXC_XER_OFFSET(r1) |
---|
131 | lwz SCRATCH_REGISTER_1, EXC_CTR_OFFSET(r1) |
---|
132 | mtxer SCRATCH_REGISTER_0 |
---|
133 | mtctr SCRATCH_REGISTER_1 |
---|
134 | |
---|
135 | /* Restore CR and LR */ |
---|
136 | lwz SCRATCH_REGISTER_0, EXC_CR_OFFSET(r1) |
---|
137 | lwz SCRATCH_REGISTER_1, EXC_LR_OFFSET(r1) |
---|
138 | mtcr SCRATCH_REGISTER_0 |
---|
139 | mtlr SCRATCH_REGISTER_1 |
---|
140 | |
---|
141 | /* Restore volatile registers */ |
---|
142 | lwz r0, GPR0_OFFSET(r1) |
---|
143 | lwz r3, GPR3_OFFSET(r1) |
---|
144 | lwz r8, GPR8_OFFSET(r1) |
---|
145 | lwz r9, GPR9_OFFSET(r1) |
---|
146 | lwz r10, GPR10_OFFSET(r1) |
---|
147 | lwz r11, GPR11_OFFSET(r1) |
---|
148 | lwz r12, GPR12_OFFSET(r1) |
---|
149 | |
---|
150 | /* Restore vector register */ |
---|
151 | lwz VECTOR_REGISTER, VECTOR_OFFSET(r1) |
---|
152 | |
---|
153 | /* Restore scratch registers and SRRs */ |
---|
154 | lwz SCRATCH_REGISTER_0, SRR0_FRAME_OFFSET(r1) |
---|
155 | lwz SCRATCH_REGISTER_1, SRR1_FRAME_OFFSET(r1) |
---|
156 | lwz SCRATCH_REGISTER_2, SCRATCH_REGISTER_2_OFFSET(r1) |
---|
157 | mtspr srr0, SCRATCH_REGISTER_0 |
---|
158 | lwz SCRATCH_REGISTER_0, SCRATCH_REGISTER_0_OFFSET(r1) |
---|
159 | mtspr srr1, SCRATCH_REGISTER_1 |
---|
160 | lwz SCRATCH_REGISTER_1, SCRATCH_REGISTER_1_OFFSET(r1) |
---|
161 | |
---|
162 | /* |
---|
163 | * We restore r1 from the frame rather than just popping (adding to |
---|
164 | * current r1) since the exception handler might have done strange |
---|
165 | * things (e.g. a debugger moving and relocating the stack). |
---|
166 | */ |
---|
167 | lwz r1, 0(r1) |
---|
168 | |
---|
169 | /* Return */ |
---|
170 | rfi |
---|
171 | |
---|
172 | wrap_change_msr_naked: |
---|
173 | |
---|
174 | mfmsr SCRATCH_REGISTER_1 |
---|
175 | or SCRATCH_REGISTER_1, SCRATCH_REGISTER_1, SCRATCH_REGISTER_0 |
---|
176 | mtmsr SCRATCH_REGISTER_1 |
---|
177 | sync |
---|
178 | isync |
---|
179 | b wrap_change_msr_done_naked |
---|
180 | |
---|
181 | wrap_restore_msr_naked: |
---|
182 | |
---|
183 | lwz SCRATCH_REGISTER_0, ppc_exc_msr_bits@sdarel(r13) |
---|
184 | mfmsr SCRATCH_REGISTER_1 |
---|
185 | andc SCRATCH_REGISTER_1, SCRATCH_REGISTER_1, SCRATCH_REGISTER_0 |
---|
186 | mtmsr SCRATCH_REGISTER_1 |
---|
187 | sync |
---|
188 | isync |
---|
189 | b wrap_restore_msr_done_naked |
---|