1 | /* exceptions-asm.S -- exception handling for OpenRISC 1000. |
---|
2 | * |
---|
3 | * Copyright (c) 2011, 2014 Authors |
---|
4 | * |
---|
5 | * Contributor Julius Baxter <juliusbaxter@gmail.com> |
---|
6 | * Contributor Stefan Wallentowitz <stefan.wallentowitz@tum.de> |
---|
7 | * |
---|
8 | * The authors hereby grant permission to use, copy, modify, distribute, |
---|
9 | * and license this software and its documentation for any purpose, provided |
---|
10 | * that existing copyright notices are retained in all copies and that this |
---|
11 | * notice is included verbatim in any distributions. No written agreement, |
---|
12 | * license, or royalty fee is required for any of the authorized uses. |
---|
13 | * Modifications to this software may be copyrighted by their authors |
---|
14 | * and need not follow the licensing terms described here, provided that |
---|
15 | * the new terms are clearly indicated on the first page of each file where |
---|
16 | * they apply. |
---|
17 | */ |
---|
18 | |
---|
19 | #include "include/or1k-asm.h" |
---|
20 | #include "include/or1k-sprs.h" |
---|
21 | |
---|
22 | /* -------------------------------------------------------------------------- */ |
---|
23 | /*!Generic exception handler function |
---|
24 | */ |
---|
25 | /* -------------------------------------------------------------------------- */ |
---|
26 | // Warning - this must be the same as specified in crt0.S |
---|
27 | #define EXCEPTION_STACK_SIZE 136 |
---|
28 | |
---|
29 | .extern _or1k_exception_handler_table |
---|
30 | .extern _or1k_exception_level |
---|
31 | |
---|
32 | /* -------------------------------------------------------------------------- */ |
---|
33 | /*!Function to call appropriate exception handler |
---|
34 | */ |
---|
35 | /* -------------------------------------------------------------------------- */ |
---|
36 | .section .text |
---|
37 | .global _or1k_exception_handler |
---|
38 | .type _or1k_exception_handler,@function |
---|
39 | |
---|
40 | /* |
---|
41 | r3 = address of exception vector |
---|
42 | r4 = address where exception occurred |
---|
43 | */ |
---|
44 | |
---|
45 | #define GPR_BUF_OFFSET(x) (x << 2) |
---|
46 | |
---|
47 | _or1k_exception_handler: |
---|
48 | /* Store remainder of state (r3,r4 stored in vector entry)*/ |
---|
49 | l.sw GPR_BUF_OFFSET(2)(r1),r2 |
---|
50 | l.sw GPR_BUF_OFFSET(5)(r1),r5 |
---|
51 | l.sw GPR_BUF_OFFSET(6)(r1),r6 |
---|
52 | l.sw GPR_BUF_OFFSET(7)(r1),r7 |
---|
53 | l.sw GPR_BUF_OFFSET(8)(r1),r8 |
---|
54 | l.sw GPR_BUF_OFFSET(9)(r1),r9 |
---|
55 | l.sw GPR_BUF_OFFSET(10)(r1),r10 |
---|
56 | l.sw GPR_BUF_OFFSET(11)(r1),r11 |
---|
57 | l.sw GPR_BUF_OFFSET(12)(r1),r12 |
---|
58 | l.sw GPR_BUF_OFFSET(13)(r1),r13 |
---|
59 | l.sw GPR_BUF_OFFSET(14)(r1),r14 |
---|
60 | l.sw GPR_BUF_OFFSET(15)(r1),r15 |
---|
61 | l.sw GPR_BUF_OFFSET(16)(r1),r16 |
---|
62 | l.sw GPR_BUF_OFFSET(17)(r1),r17 |
---|
63 | l.sw GPR_BUF_OFFSET(18)(r1),r18 |
---|
64 | l.sw GPR_BUF_OFFSET(19)(r1),r19 |
---|
65 | l.sw GPR_BUF_OFFSET(20)(r1),r20 |
---|
66 | l.sw GPR_BUF_OFFSET(21)(r1),r21 |
---|
67 | l.sw GPR_BUF_OFFSET(22)(r1),r22 |
---|
68 | l.sw GPR_BUF_OFFSET(23)(r1),r23 |
---|
69 | l.sw GPR_BUF_OFFSET(24)(r1),r24 |
---|
70 | l.sw GPR_BUF_OFFSET(25)(r1),r25 |
---|
71 | l.sw GPR_BUF_OFFSET(26)(r1),r26 |
---|
72 | l.sw GPR_BUF_OFFSET(27)(r1),r27 |
---|
73 | l.sw GPR_BUF_OFFSET(28)(r1),r28 |
---|
74 | l.sw GPR_BUF_OFFSET(29)(r1),r29 |
---|
75 | l.sw GPR_BUF_OFFSET(30)(r1),r30 |
---|
76 | l.sw GPR_BUF_OFFSET(31)(r1),r31 |
---|
77 | l.mfspr r14,r0,OR1K_SPR_SYS_EPCR_BASE |
---|
78 | l.sw 0x80(r1),r14 |
---|
79 | l.mfspr r14,r0,OR1K_SPR_SYS_ESR_BASE |
---|
80 | l.sw 0x84(r1),r14 |
---|
81 | |
---|
82 | /* Replace impure pointer for exception */ |
---|
83 | l.movhi r20,hi(_or1k_exception_impure_ptr) |
---|
84 | l.ori r20,r20,lo(_or1k_exception_impure_ptr) |
---|
85 | #ifdef __OR1K_MULTICORE__ |
---|
86 | l.lwz r20,0(r20) |
---|
87 | l.mfspr r22,r0,OR1K_SPR_SYS_COREID_ADDR |
---|
88 | l.slli r22,r22,2 |
---|
89 | l.add r20,r20,r22 |
---|
90 | #endif |
---|
91 | l.lwz r20,0(r20) |
---|
92 | |
---|
93 | l.movhi r21,hi(_or1k_current_impure_ptr) |
---|
94 | l.ori r21,r21,lo(_or1k_current_impure_ptr) |
---|
95 | #ifdef __OR1K_MULTICORE__ |
---|
96 | l.lwz r21,0(r21) |
---|
97 | l.add r21,r21,r22 |
---|
98 | #endif |
---|
99 | l.sw 0(r21),r20 |
---|
100 | |
---|
101 | /* Determine offset in table of exception handler using r3*/ |
---|
102 | l.andi r13,r3,0xff00 |
---|
103 | l.srli r13,r13,6 |
---|
104 | /* Substract 2 words, as we have no vector at 0 and no reset handler */ |
---|
105 | l.addi r13,r13,-8 |
---|
106 | /* r13 now contains offset in or1k_exception_handler_table for |
---|
107 | function |
---|
108 | */ |
---|
109 | /* Get or1k_exception_handler_table address */ |
---|
110 | l.movhi r14,hi(_or1k_exception_handler_table) |
---|
111 | l.ori r14,r14,lo(_or1k_exception_handler_table) |
---|
112 | #ifdef __OR1K_MULTICORE__ |
---|
113 | /* Read the address of the array of cores */ |
---|
114 | /* r14 = (*or1k_exception_handler_table) */ |
---|
115 | l.lwz r14,0(r14) |
---|
116 | /* Generate core offset in array (off = coreid*30*4 = coreid*120) */ |
---|
117 | /* r15 = coreid */ |
---|
118 | l.mfspr r15,r0,OR1K_SPR_SYS_COREID_ADDR |
---|
119 | /* r16 = coreid * 128 */ |
---|
120 | l.slli r16,r15,7 |
---|
121 | /* r15 = coreid * 8 */ |
---|
122 | l.slli r15,r15,3 |
---|
123 | /* r15 = coreid*128 - coreid*8 = coreid*120 = off */ |
---|
124 | l.sub r15,r16,r15 |
---|
125 | /* r14 = (*or1k_exception_handler_table)[coreid] = r14 + off */ |
---|
126 | l.add r14,r14,r15 |
---|
127 | #endif |
---|
128 | /* r14 now contains base of exception handler table */ |
---|
129 | /* add offset of exception vector */ |
---|
130 | l.add r14,r14,r13 |
---|
131 | /* load handler address from table */ |
---|
132 | l.lwz r13, 0(r14) |
---|
133 | |
---|
134 | /* Check to see if this handler has been set yet */ |
---|
135 | l.sfne r13,r0 |
---|
136 | OR1K_DELAYED_NOP(OR1K_INST(l.bnf exception_exit)) |
---|
137 | |
---|
138 | /* Call exception handler, copy EPCR to r3 */ |
---|
139 | OR1K_DELAYED( |
---|
140 | OR1K_INST(l.or r3,r4,r4), |
---|
141 | OR1K_INST(l.jalr r13) |
---|
142 | ) |
---|
143 | |
---|
144 | /* Restore impure pointer */ |
---|
145 | l.movhi r20,hi(_or1k_impure_ptr) |
---|
146 | l.ori r20,r20,lo(_or1k_impure_ptr) |
---|
147 | #ifdef __OR1K_MULTICORE__ |
---|
148 | l.lwz r20,0(r20) |
---|
149 | l.mfspr r22,r0,OR1K_SPR_SYS_COREID_ADDR |
---|
150 | l.slli r22,r22,2 |
---|
151 | l.add r20,r20,r22 |
---|
152 | #endif |
---|
153 | l.lwz r20,0(r20) |
---|
154 | |
---|
155 | l.movhi r21,hi(_or1k_current_impure_ptr) |
---|
156 | l.ori r21,r21,lo(_or1k_current_impure_ptr) |
---|
157 | #ifdef __OR1K_MULTICORE__ |
---|
158 | l.lwz r21,0(r21) |
---|
159 | l.add r21,r21,r22 |
---|
160 | #endif |
---|
161 | l.sw 0(r21),r20 |
---|
162 | |
---|
163 | /* Decrement the exception nesting level */ |
---|
164 | // Load the exception level entry |
---|
165 | l.movhi r2,hi(_or1k_exception_level) |
---|
166 | l.ori r2,r2,lo(_or1k_exception_level) |
---|
167 | #ifdef __OR1K_MULTICORE__ |
---|
168 | // In multicore this is the pointer to an array |
---|
169 | // Load pointer value |
---|
170 | l.lwz r2,0(r2) |
---|
171 | // Add word offset of this core's nesting level |
---|
172 | l.add r2,r2,r22 |
---|
173 | #endif |
---|
174 | // Load the nesting level entry |
---|
175 | l.lwz r3,0(r2) |
---|
176 | // Decrement nesting level |
---|
177 | l.addi r3,r3,-1 |
---|
178 | // Store back the nesting level |
---|
179 | l.sw 0(r2),r3 |
---|
180 | |
---|
181 | /* Restore state */ |
---|
182 | l.lwz r2,0x80(r1) |
---|
183 | l.mtspr r0,r2,OR1K_SPR_SYS_EPCR_BASE |
---|
184 | |
---|
185 | l.lwz r2,0x84(r1) |
---|
186 | l.mtspr r0,r2,OR1K_SPR_SYS_ESR_BASE |
---|
187 | |
---|
188 | l.lwz r2,GPR_BUF_OFFSET(2)(r1) |
---|
189 | l.lwz r3,GPR_BUF_OFFSET(3)(r1) |
---|
190 | l.lwz r4,GPR_BUF_OFFSET(4)(r1) |
---|
191 | l.lwz r5,GPR_BUF_OFFSET(5)(r1) |
---|
192 | l.lwz r6,GPR_BUF_OFFSET(6)(r1) |
---|
193 | l.lwz r7,GPR_BUF_OFFSET(7)(r1) |
---|
194 | l.lwz r8,GPR_BUF_OFFSET(8)(r1) |
---|
195 | l.lwz r9,GPR_BUF_OFFSET(9)(r1) |
---|
196 | l.lwz r10,GPR_BUF_OFFSET(10)(r1) |
---|
197 | l.lwz r11,GPR_BUF_OFFSET(11)(r1) |
---|
198 | l.lwz r12,GPR_BUF_OFFSET(12)(r1) |
---|
199 | l.lwz r13,GPR_BUF_OFFSET(13)(r1) |
---|
200 | l.lwz r14,GPR_BUF_OFFSET(14)(r1) |
---|
201 | l.lwz r15,GPR_BUF_OFFSET(15)(r1) |
---|
202 | l.lwz r16,GPR_BUF_OFFSET(16)(r1) |
---|
203 | l.lwz r17,GPR_BUF_OFFSET(17)(r1) |
---|
204 | l.lwz r18,GPR_BUF_OFFSET(18)(r1) |
---|
205 | l.lwz r19,GPR_BUF_OFFSET(19)(r1) |
---|
206 | l.lwz r20,GPR_BUF_OFFSET(20)(r1) |
---|
207 | l.lwz r21,GPR_BUF_OFFSET(21)(r1) |
---|
208 | l.lwz r22,GPR_BUF_OFFSET(22)(r1) |
---|
209 | l.lwz r23,GPR_BUF_OFFSET(23)(r1) |
---|
210 | l.lwz r24,GPR_BUF_OFFSET(24)(r1) |
---|
211 | l.lwz r25,GPR_BUF_OFFSET(25)(r1) |
---|
212 | l.lwz r26,GPR_BUF_OFFSET(26)(r1) |
---|
213 | l.lwz r27,GPR_BUF_OFFSET(27)(r1) |
---|
214 | l.lwz r28,GPR_BUF_OFFSET(28)(r1) |
---|
215 | l.lwz r29,GPR_BUF_OFFSET(29)(r1) |
---|
216 | l.lwz r30,GPR_BUF_OFFSET(30)(r1) |
---|
217 | l.lwz r31,GPR_BUF_OFFSET(31)(r1) |
---|
218 | |
---|
219 | // Restore original stack |
---|
220 | l.lwz r1,GPR_BUF_OFFSET(1)(r1) |
---|
221 | |
---|
222 | l.rfe |
---|
223 | l.nop |
---|
224 | |
---|
225 | exception_exit: |
---|
226 | /* Exception handler not set, exit */ |
---|
227 | OR1K_DELAYED( |
---|
228 | OR1K_INST(l.or r3,r4,r4), |
---|
229 | OR1K_INST(l.jal exit) |
---|
230 | ) |
---|