1 | /* start.S -- bootup code for the Bender board using the Or1k |
---|
2 | * architecture. |
---|
3 | * |
---|
4 | * Copyright (C) 2001 Chris Ziomkowski, chris@asics.ws |
---|
5 | * |
---|
6 | * This file is distributed as part of the RTEMS package from |
---|
7 | * OAR Corporation, and follows the licensing and distribution |
---|
8 | * terms as stated for RTEMS. |
---|
9 | * |
---|
10 | * COPYRIGHT (c) 1989-1999. |
---|
11 | * On-Line Applications Research Corporation (OAR). |
---|
12 | * |
---|
13 | * The license and distribution terms for this file may be |
---|
14 | * found in the file LICENSE in this distribution or at |
---|
15 | * http://www.rtems.com/license/LICENSE. |
---|
16 | */ |
---|
17 | |
---|
18 | #include "asm.h" |
---|
19 | |
---|
20 | |
---|
21 | /* Since we don't yet have a memory map for Bender, I am |
---|
22 | assuming the following. Hopefully, this will be easily |
---|
23 | modified once we get the real values. |
---|
24 | |
---|
25 | 0x00000000 - 0x00200000: Flash/ROM (boot code / 2 MB) |
---|
26 | 0x01000000 - 0x010FFFFF: Synchronous SRAM (area 2 / 1 MB) |
---|
27 | 0x10000000 - 0x1FFFFFFF: External SDRAM (area 3 / 256 MB) |
---|
28 | 0x20000000 - 0x2FFFFFFF: External SDRAM (area 4 / 256 MB) |
---|
29 | |
---|
30 | 0x80000000 - 0x8000001F: 4 16550 UART controllers |
---|
31 | 0x80010000 - 0x80017FFF: Internal Bender RAM |
---|
32 | 0x80020000 - 0xFFFFFFFF: Memory mapped Bender Peripherals |
---|
33 | |
---|
34 | For this version, I assume that only the flash and 32 MB |
---|
35 | of RAM in area 3 are populated. Everything else should |
---|
36 | return a bus error when accessed. |
---|
37 | */ |
---|
38 | .file "start.S" |
---|
39 | |
---|
40 | .data |
---|
41 | PUBLIC(Or1k_Interrupt_Vectors) |
---|
42 | SYM (Or1k_Interrupt_Vectors): |
---|
43 | .word 0x00000000 # No Vector |
---|
44 | .word _start # Reset Vector (Ignored) |
---|
45 | .word __Internal_error_Occurred # Bus Error |
---|
46 | .word __Internal_error_Occurred # Data Page Fault |
---|
47 | .word __Internal_error_Occurred # Instruction Page Fault |
---|
48 | .word __int_reenable # Low Priority Interrupt |
---|
49 | .word __Internal_error_Occurred # Alignment Exception |
---|
50 | .word __Internal_error_Occurred # Illegal Instruction Exception |
---|
51 | .word __int_reenable # High Priority Interrupt |
---|
52 | .word __Internal_error_Occurred # ITBL Miss |
---|
53 | .word __Internal_error_Occurred # DTBL Miss |
---|
54 | .word 0x00000000 # Range Exception |
---|
55 | .word 0x00000000 # System Call |
---|
56 | .word 0x00000000 # Breakpoint |
---|
57 | .word 0x00000000 # Trap |
---|
58 | |
---|
59 | /* |
---|
60 | PUBLIC(BOTTOM_OF_MEMORY) |
---|
61 | SYM (BOTTOM_OF_MEMORY): |
---|
62 | .word 0x10000000 # Assume RAM @ 0 for the sim |
---|
63 | |
---|
64 | PUBLIC(TOP_OF_MEMORY) |
---|
65 | SYM (TOP_OF_MEMORY): |
---|
66 | .word 0x10800000 # Assume RAM @ 0 for the sim |
---|
67 | */ |
---|
68 | PUBLIC(_mem_end) |
---|
69 | SYM (_mem_end): |
---|
70 | .word 0x10800000 |
---|
71 | |
---|
72 | BEGIN_CODE |
---|
73 | .org 0x0 |
---|
74 | /**************/ |
---|
75 | /* _panic */ |
---|
76 | /**************/ |
---|
77 | |
---|
78 | /* Place the panic vector at 0 */ |
---|
79 | |
---|
80 | .proc __panic |
---|
81 | .def __panic |
---|
82 | .val __panic |
---|
83 | .scl 2 |
---|
84 | .type 044 |
---|
85 | .endef |
---|
86 | .global __panic |
---|
87 | __panic: |
---|
88 | |
---|
89 | l.jal __exit |
---|
90 | l.nop |
---|
91 | |
---|
92 | .endproc __panic |
---|
93 | .def __panic |
---|
94 | .val . |
---|
95 | .scl -1 |
---|
96 | .endef |
---|
97 | |
---|
98 | /* Exception processing...first, we will save the |
---|
99 | 16 non callee saved registers which could be |
---|
100 | corrupted by calling a C function. We have no |
---|
101 | way of knowing which of these will be used, so |
---|
102 | we have to save all of them. We will then save |
---|
103 | the EPCR and ESR, in case a nested exception is |
---|
104 | called. Next, we call the user function. We then |
---|
105 | restore all the registers to their original |
---|
106 | values, and finally disable exceptions, restore |
---|
107 | EPCR and ESR (EEAR is not essential to restore) |
---|
108 | and then return from the interrupt. */ |
---|
109 | |
---|
110 | /******************************************/ |
---|
111 | /* Normal exception handling */ |
---|
112 | /* Called with 80 bytes allocated on the */ |
---|
113 | /* stack, the vector function in r11, and */ |
---|
114 | /* the vector number in r3. Original */ |
---|
115 | /* values at 28(r1) and 0(r1). */ |
---|
116 | /******************************************/ |
---|
117 | .proc ___standard_exception |
---|
118 | .def ___standard_exception |
---|
119 | .val ___standard_exception |
---|
120 | .scl 2 |
---|
121 | .type 044 |
---|
122 | .endef |
---|
123 | .global ___standard_exception |
---|
124 | ___standard_exception: |
---|
125 | l.sfeqi r11,0 /* Ignore it if it is zero */ |
---|
126 | l.bf L2_2 |
---|
127 | l.sw 4(r1),r4 /* Save r4 */ |
---|
128 | |
---|
129 | /* Ignore fast context switching in this release. */ |
---|
130 | /* It's poorly conceived, and will probably never */ |
---|
131 | /* be implemented... */ |
---|
132 | |
---|
133 | l.sw 8(r1),r5 |
---|
134 | l.sw 12(r1),r6 |
---|
135 | l.sw 16(r1),r7 |
---|
136 | |
---|
137 | l.mfspr r4,r0,0x20 /* Save EPCR */ |
---|
138 | l.mfspr r5,r0,0x30 /* Save EEAR */ |
---|
139 | l.mfspr r6,r0,0x40 /* Save ESR */ |
---|
140 | |
---|
141 | l.mfspr r7,r0,17 |
---|
142 | l.ori r7,r7,2 |
---|
143 | l.mtspr r0,r7,17 /* Reenable exceptions */ |
---|
144 | |
---|
145 | l.sw 20(r1),r8 |
---|
146 | l.sw 24(r1),r9 |
---|
147 | l.sw 32(r1),r12 |
---|
148 | l.sw 36(r1),r14 |
---|
149 | l.sw 40(r1),r16 |
---|
150 | l.sw 44(r1),r18 |
---|
151 | l.sw 48(r1),r20 |
---|
152 | l.sw 52(r1),r22 |
---|
153 | l.sw 56(r1),r24 |
---|
154 | l.sw 60(r1),r26 |
---|
155 | l.sw 64(r1),r28 |
---|
156 | l.sw 68(r1),r30 |
---|
157 | l.sw 72(r1),r4 /* Save EPCR. User could change r4 */ |
---|
158 | |
---|
159 | /* Now, call the installed handler with the arguments: |
---|
160 | r3 ==> vector # (1-14) |
---|
161 | r4 ==> EPCR |
---|
162 | r5 ==> EEAR |
---|
163 | r6 ==> ESR |
---|
164 | r11 ==> User function |
---|
165 | */ |
---|
166 | |
---|
167 | l.jal ___user_function /* Call the user routine */ |
---|
168 | l.sw 76(r1),r6 /* Save ESR. User could change r6 */ |
---|
169 | /* Ignore r5 (EEAR). It is not critical for state */ |
---|
170 | |
---|
171 | l.lwz r30,68(r1) |
---|
172 | l.lwz r28,64(r1) |
---|
173 | l.lwz r26,60(r1) |
---|
174 | l.lwz r24,56(r1) |
---|
175 | l.lwz r22,52(r1) |
---|
176 | l.lwz r20,48(r1) |
---|
177 | l.lwz r18,44(r1) |
---|
178 | l.lwz r16,40(r1) |
---|
179 | l.lwz r14,36(r1) |
---|
180 | l.lwz r12,32(r1) |
---|
181 | l.lwz r9,24(r1) |
---|
182 | l.lwz r8,20(r1) |
---|
183 | l.lwz r7,16(r1) |
---|
184 | l.lwz r5,8(r1) |
---|
185 | |
---|
186 | l.addi r6,r0,-3 /* Set r6 to 0xFFFFFFFD */ |
---|
187 | l.mfspr r3,r0,17 /* Get SR value */ |
---|
188 | l.and r3,r3,r6 /* Clear exception bit */ |
---|
189 | l.mfspr r0,r3,17 /* Disable exceptions */ |
---|
190 | |
---|
191 | l.lwz r6,76(r1) /* Recover ESR */ |
---|
192 | l.lwz r4,72(r1) /* Recover EPCR */ |
---|
193 | l.mtspr r0,r4,0x20 /* Restore ESR */ |
---|
194 | l.mtspr r0,r6,0x40 /* Restore EPCR */ |
---|
195 | l.lwz r6,12(r1) |
---|
196 | l.lwz r4,4(r1) |
---|
197 | |
---|
198 | L2_2: |
---|
199 | l.lwz r11,28(r1) |
---|
200 | l.lwz r3,0(r1) |
---|
201 | l.addi r1,r1,80 |
---|
202 | l.rfe |
---|
203 | l.nop /* The document doesn't say this is |
---|
204 | a delay slot instruction, but the |
---|
205 | simulator doesn't work without this. */ |
---|
206 | |
---|
207 | .endproc ___standard_exception |
---|
208 | .def ___standard_exception |
---|
209 | .val . |
---|
210 | .scl -1 |
---|
211 | .endef |
---|
212 | |
---|
213 | /****************************************************************************/ |
---|
214 | /* These constants must be in .text section in order to be */ |
---|
215 | /* properly addressed in code. */ |
---|
216 | |
---|
217 | PUBLIC(BOTTOM_OF_MEMORY) |
---|
218 | SYM (BOTTOM_OF_MEMORY): |
---|
219 | .word 0x10000000 # Assume RAM @ 0 for the sim |
---|
220 | |
---|
221 | PUBLIC(TOP_OF_MEMORY) |
---|
222 | SYM (TOP_OF_MEMORY): |
---|
223 | .word 0x10800000 # Assume RAM @ 0 for the sim |
---|
224 | |
---|
225 | /****************************************************************************/ |
---|
226 | |
---|
227 | /** Currently, about 57 of the 64 valid address locations |
---|
228 | are being used here. If you add code to the above |
---|
229 | routine, make sure it isn't more than 7 instructions |
---|
230 | or you will overflow into the reset vector. **/ |
---|
231 | |
---|
232 | /****************************/ |
---|
233 | /* Reset vector static code */ |
---|
234 | /****************************/ |
---|
235 | .org 0x100 |
---|
236 | .proc ___rst |
---|
237 | .global ___rst |
---|
238 | ___rst: |
---|
239 | /* Set the stack pointer */ |
---|
240 | l.movhi r1,hi(_TOP_OF_MEMORY) |
---|
241 | l.ori r1,r1,lo(_TOP_OF_MEMORY) |
---|
242 | l.lwz r1,0(r1) /* Dereference it */ |
---|
243 | |
---|
244 | /* Set the frame pointer */ |
---|
245 | l.add r2,r0,r1 |
---|
246 | |
---|
247 | l.mfspr r3,r0,17 /* Get SR value */ |
---|
248 | l.ori r3,r3,2 /* Set exception enable bit */ |
---|
249 | l.j _start /* Jump to main routine */ |
---|
250 | l.mtspr r0,r3,17 /* Enable exceptions (DELAY) */ |
---|
251 | .endproc ___rst |
---|
252 | |
---|
253 | /***********************************************************/ |
---|
254 | /* Note: right after the reset vector, we are going to */ |
---|
255 | /* place a table with the necessary values to initialize */ |
---|
256 | /* the memory controller. This pointer will be set and */ |
---|
257 | /* passed to the _start routine in r4. The first thing the */ |
---|
258 | /* the _start routine will do is to initialize the memory */ |
---|
259 | /* controller. The code to initialze the memory controller */ |
---|
260 | /* is expected to be larger than the 50 some odd */ |
---|
261 | /* instructions that are remaining here before the bus */ |
---|
262 | /* error vector, which is why it is left to the _start */ |
---|
263 | /* routine. */ |
---|
264 | /***********************************************************/ |
---|
265 | |
---|
266 | /********************************/ |
---|
267 | /* Bus Error vector static code */ |
---|
268 | /********************************/ |
---|
269 | .org 0x200 |
---|
270 | .proc ___bus_error |
---|
271 | .global ___bus_error |
---|
272 | ___bus_error: |
---|
273 | l.addi r1,r1,-80 |
---|
274 | l.sw 0(r1),r3 |
---|
275 | l.sw 28(r1),r11 |
---|
276 | l.movhi r11,hi(_Or1k_Interrupt_Vectors) |
---|
277 | l.ori r11,r11,lo(_Or1k_Interrupt_Vectors) |
---|
278 | l.lwz r11,8(r11) |
---|
279 | l.j ___standard_exception |
---|
280 | l.addi r3,r0,2 |
---|
281 | |
---|
282 | .endproc ___bus_error |
---|
283 | |
---|
284 | /* Put _Internal_error_Occurred and _int_reenable here */ |
---|
285 | /* No reason to waste space...it'll be filled with 0 if */ |
---|
286 | /* we don't... */ |
---|
287 | |
---|
288 | /********************************/ |
---|
289 | /* _Internal_error_Occurred */ |
---|
290 | /********************************/ |
---|
291 | |
---|
292 | .proc __Internal_error_Occurred |
---|
293 | .def __Internal_error_Occurred |
---|
294 | .val __Internal_error_Occurred |
---|
295 | .scl 2 |
---|
296 | .type 044 |
---|
297 | .endef |
---|
298 | .global __Internal_error_Occurred |
---|
299 | __Internal_error_Occurred: |
---|
300 | |
---|
301 | l.jal __panic |
---|
302 | l.nop |
---|
303 | |
---|
304 | .endproc __Internal_error_Occurred |
---|
305 | .def __Internal_error_Occurred |
---|
306 | .val . |
---|
307 | .scl -1 |
---|
308 | .endef |
---|
309 | |
---|
310 | |
---|
311 | /*********************/ |
---|
312 | /* _int_reenable */ |
---|
313 | /*********************/ |
---|
314 | |
---|
315 | .proc __int_reenable |
---|
316 | .def __int_reenable |
---|
317 | .val __int_reenable |
---|
318 | .scl 2 |
---|
319 | .type 044 |
---|
320 | .endef |
---|
321 | .global __int_reenable |
---|
322 | __int_reenable: |
---|
323 | |
---|
324 | l.mfspr r11,r0,17 |
---|
325 | l.ori r11,r11,0x04 |
---|
326 | l.jr r9 |
---|
327 | l.mtspr r0,r11,17 |
---|
328 | |
---|
329 | .endproc __int_reenable |
---|
330 | .def __int_reenable |
---|
331 | .val . |
---|
332 | .scl -1 |
---|
333 | .endef |
---|
334 | |
---|
335 | /*********************&**/ |
---|
336 | /* ___user_function */ |
---|
337 | /************************/ |
---|
338 | |
---|
339 | .proc ___user_function |
---|
340 | .def ___user_function |
---|
341 | .val ___user_function |
---|
342 | .scl 2 |
---|
343 | .type 044 |
---|
344 | .endef |
---|
345 | .global ___user_function |
---|
346 | ___user_function: |
---|
347 | |
---|
348 | /* r11 contains the address to call. We can |
---|
349 | modify r7, r8, r12, and r14 at will */ |
---|
350 | |
---|
351 | l.movhi r7,hi(__Thread_Dispatch_disable_level) |
---|
352 | l.ori r7,r7,lo(__Thread_Dispatch_disable_level) |
---|
353 | l.lwz r8,0(r7) |
---|
354 | |
---|
355 | l.addi r1,r1,-8 # Stack must be DWORD aligned |
---|
356 | l.sw 0(r1),r9 # Save the return address |
---|
357 | |
---|
358 | l.addi r8,r8,1 # Increment __Thread_Dispatch... |
---|
359 | l.jalr r11 |
---|
360 | l.sw 0(r7),r8 # Disable thread dispatching |
---|
361 | |
---|
362 | /* Now, we need to determine if we need to |
---|
363 | service the RTEMS environment. RTEMS tries |
---|
364 | to draw a distinction between a RAW handler |
---|
365 | (where this isn't necessary) and an RTEMS |
---|
366 | handler. However, it appears almost all ISR's |
---|
367 | will not be RAW under this definition, and |
---|
368 | those that are will not honestly be hurt by |
---|
369 | the 20 or so extra cycles it will take to do |
---|
370 | the following code. If there is a very frequent |
---|
371 | interrupt, then it should probably be hard |
---|
372 | coded into the static routine anyway, rather |
---|
373 | than suffer the hit of calling it indirectly */ |
---|
374 | |
---|
375 | /* Note: RTEMS recommends incrementing and |
---|
376 | decrementing the _ISR_Nest_Level as well. |
---|
377 | We are specifically not doing this because |
---|
378 | in the Or1k architecture it is impossible |
---|
379 | to nest interrupts. Interrupts must run to |
---|
380 | completion before reenabling. If there is a |
---|
381 | significant task to be done, then it should |
---|
382 | run in a bottom half handler, similar to the |
---|
383 | way Linux works. In theory though, even if |
---|
384 | we do allow nested interrupts, there is no |
---|
385 | reason for this flag, as it seems to be for |
---|
386 | the purpose of restoring the normal stack in |
---|
387 | place of the interrupt stack. We don't use a |
---|
388 | separate exception stack, so this should not |
---|
389 | be an issue for us. */ |
---|
390 | |
---|
391 | l.movhi r7,hi(__Thread_Dispatch_disable_level) |
---|
392 | l.ori r7,r7,lo(__Thread_Dispatch_disable_level) |
---|
393 | l.lwz r8,0(r7) |
---|
394 | l.addi r8,r8,-1 # Decrement __Thread_Dispatch... |
---|
395 | l.sw 0(r7),r8 # Memory stall likely here... |
---|
396 | |
---|
397 | l.sfeqi r8,0 # Skip if _Thread_Dispatch != 0 |
---|
398 | l.bnf L4_2 |
---|
399 | l.movhi r7,hi(__Context_Switch_necessary) |
---|
400 | |
---|
401 | l.ori r7,r7,lo(__Context_Switch_necessary) |
---|
402 | l.lwz r8,0(r7) |
---|
403 | |
---|
404 | l.movhi r7,hi(__ISR_Signals_to_thread_executing) |
---|
405 | l.ori r7,r7,lo(__ISR_Signals_to_thread_executing) |
---|
406 | l.lwz r12,0(r7) |
---|
407 | |
---|
408 | l.sfeqi r8,0 # Skip if __Context... is false |
---|
409 | l.bf L4_2 |
---|
410 | l.movhi r14,hi(__Thread_Dispatch) |
---|
411 | |
---|
412 | l.sfeqi r12,0 # Skip if __ISR... is true |
---|
413 | l.bnf L4_2 |
---|
414 | l.ori r14,r14,lo(__Thread_Dispatch) |
---|
415 | |
---|
416 | l.jalr r14 |
---|
417 | l.sw 0(r7),r0 # Set __ISR... to false |
---|
418 | |
---|
419 | L4_2: |
---|
420 | l.lwz r9,0(r1) # Recover the return address |
---|
421 | l.jr r9 |
---|
422 | l.addi r1,r1,8 # Reset the stack |
---|
423 | |
---|
424 | .endproc ___user_function |
---|
425 | .def ___user_function |
---|
426 | .val . |
---|
427 | .scl -1 |
---|
428 | .endef |
---|
429 | |
---|
430 | |
---|
431 | /* Code wasted between here and 0x300 */ |
---|
432 | |
---|
433 | /**************************************/ |
---|
434 | /* Data Page Fault vector static code */ |
---|
435 | /**************************************/ |
---|
436 | .org 0x300 |
---|
437 | .proc ___data_page_fault |
---|
438 | .global ___data_page_fault |
---|
439 | ___data_page_fault: |
---|
440 | l.addi r1,r1,-80 |
---|
441 | l.sw 0(r1),r3 |
---|
442 | l.sw 28(r1),r11 |
---|
443 | l.movhi r11,hi(_Or1k_Interrupt_Vectors) |
---|
444 | l.ori r11,r11,lo(_Or1k_Interrupt_Vectors) |
---|
445 | l.lwz r11,12(r11) |
---|
446 | l.j ___standard_exception |
---|
447 | l.addi r3,r0,3 |
---|
448 | .endproc ___data_page_fault |
---|
449 | |
---|
450 | /* Code wasted between here and 0x400 */ |
---|
451 | |
---|
452 | /*********************************************/ |
---|
453 | /* Instruction Page Fault vector static code */ |
---|
454 | /*********************************************/ |
---|
455 | .org 0x400 |
---|
456 | .proc ___insn_page_fault |
---|
457 | .global ___insn_page_fault |
---|
458 | ___insn_page_fault: |
---|
459 | l.addi r1,r1,-80 |
---|
460 | l.sw 0(r1),r3 |
---|
461 | l.sw 28(r1),r11 |
---|
462 | l.movhi r11,hi(_Or1k_Interrupt_Vectors) |
---|
463 | l.ori r11,r11,lo(_Or1k_Interrupt_Vectors) |
---|
464 | l.lwz r11,16(r11) |
---|
465 | l.j ___standard_exception |
---|
466 | l.addi r3,r0,4 |
---|
467 | .endproc ___insn_page_fault |
---|
468 | |
---|
469 | /* Code wasted between here and 0x500 */ |
---|
470 | |
---|
471 | /**************************************/ |
---|
472 | /* Low Priority Interrupt static code */ |
---|
473 | /**************************************/ |
---|
474 | .org 0x500 |
---|
475 | .proc ___low_priority_int |
---|
476 | .global ___low_priority_int |
---|
477 | ___low_priority_int: |
---|
478 | l.addi r1,r1,-80 |
---|
479 | l.sw 0(r1),r3 |
---|
480 | l.sw 28(r1),r11 |
---|
481 | l.mfspr r3,r0,17 # Get the SR |
---|
482 | l.addi r11,r0,-5 # r11 = 0xFFFFFFFB |
---|
483 | l.and r11,r11,r3 # Clear the EIR bit |
---|
484 | l.mtspr r0,r11,17 # Set the SR w/o INT |
---|
485 | l.movhi r11,hi(_Or1k_Interrupt_Vectors) |
---|
486 | l.ori r11,r11,lo(_Or1k_Interrupt_Vectors) |
---|
487 | l.lwz r11,20(r11) |
---|
488 | l.j ___standard_exception |
---|
489 | l.addi r3,r0,5 |
---|
490 | .endproc ___low_priority_int |
---|
491 | |
---|
492 | /* Code wasted between here and 0x600 */ |
---|
493 | |
---|
494 | /******************************************/ |
---|
495 | /* Alignment Exception vector static code */ |
---|
496 | /******************************************/ |
---|
497 | .org 0x600 |
---|
498 | .proc ___alignment_exception |
---|
499 | .global ___alignment_exception |
---|
500 | ___alignment_exception: |
---|
501 | l.addi r1,r1,-80 |
---|
502 | l.sw 0(r1),r3 |
---|
503 | l.sw 28(r1),r11 |
---|
504 | l.movhi r11,hi(_Or1k_Interrupt_Vectors) |
---|
505 | l.ori r11,r11,lo(_Or1k_Interrupt_Vectors) |
---|
506 | l.lwz r11,24(r11) |
---|
507 | l.j ___standard_exception |
---|
508 | l.addi r3,r0,6 |
---|
509 | .endproc ___alignment_exception |
---|
510 | |
---|
511 | /* Code wasted between here and 0x700 */ |
---|
512 | |
---|
513 | /******************************************/ |
---|
514 | /* Illegal Instruction vector static code */ |
---|
515 | /******************************************/ |
---|
516 | .org 0x700 |
---|
517 | .proc ___illegal_instruction |
---|
518 | .global ___illegal_instruction |
---|
519 | ___illegal_instruction: |
---|
520 | l.addi r1,r1,-80 |
---|
521 | l.sw 0(r1),r3 |
---|
522 | l.sw 28(r1),r11 |
---|
523 | l.movhi r11,hi(_Or1k_Interrupt_Vectors) |
---|
524 | l.ori r11,r11,lo(_Or1k_Interrupt_Vectors) |
---|
525 | l.lwz r11,28(r11) |
---|
526 | l.j ___standard_exception |
---|
527 | l.addi r3,r0,7 |
---|
528 | .endproc ___illegal_instruction |
---|
529 | |
---|
530 | /* Code wasted between here and 0x800 */ |
---|
531 | |
---|
532 | /***************************************/ |
---|
533 | /* High Priority Interrupt static code */ |
---|
534 | /***************************************/ |
---|
535 | .org 0x800 |
---|
536 | .proc ___high_priority_int |
---|
537 | .global ___high_priority_int |
---|
538 | ___high_priority_int: |
---|
539 | l.addi r1,r1,-80 |
---|
540 | l.sw 0(r1),r3 |
---|
541 | l.sw 28(r1),r11 |
---|
542 | l.mfspr r3,r0,17 # Get the SR |
---|
543 | l.addi r11,r0,-5 # r11 = 0xFFFFFFFB |
---|
544 | l.and r11,r11,r3 # Clear the EIR bit |
---|
545 | l.mtspr r0,r11,17 # Set the SR w/o INT |
---|
546 | l.movhi r11,hi(_Or1k_Interrupt_Vectors) |
---|
547 | l.ori r11,r11,lo(_Or1k_Interrupt_Vectors) |
---|
548 | l.lwz r11,32(r11) |
---|
549 | l.j ___standard_exception |
---|
550 | l.addi r3,r0,8 |
---|
551 | .endproc ___high_priority_int |
---|
552 | |
---|
553 | /* Code wasted between here and 0x900 */ |
---|
554 | |
---|
555 | /********************************/ |
---|
556 | /* ITBL Miss vector static code */ |
---|
557 | /********************************/ |
---|
558 | .org 0x900 |
---|
559 | .proc ___ITBL_miss_exception |
---|
560 | .global ___ITBL_miss_exception |
---|
561 | ___ITBL_miss_exception: |
---|
562 | l.addi r1,r1,-80 |
---|
563 | l.sw 0(r1),r3 |
---|
564 | l.sw 28(r1),r11 |
---|
565 | l.movhi r11,hi(_Or1k_Interrupt_Vectors) |
---|
566 | l.ori r11,r11,lo(_Or1k_Interrupt_Vectors) |
---|
567 | l.lwz r11,36(r11) |
---|
568 | l.j ___standard_exception |
---|
569 | l.addi r3,r0,9 |
---|
570 | .endproc ___ITBL_miss_exception |
---|
571 | |
---|
572 | /* Code wasted between here and 0xA00 */ |
---|
573 | |
---|
574 | /********************************/ |
---|
575 | /* DTBL Miss vector static code */ |
---|
576 | /********************************/ |
---|
577 | .org 0xA00 |
---|
578 | .proc ___DTBL_miss_exception |
---|
579 | .global ___DTBL_miss_exception |
---|
580 | ___DTBL_miss_exception: |
---|
581 | l.addi r1,r1,-80 |
---|
582 | l.sw 0(r1),r3 |
---|
583 | l.sw 28(r1),r11 |
---|
584 | l.movhi r11,hi(_Or1k_Interrupt_Vectors) |
---|
585 | l.ori r11,r11,lo(_Or1k_Interrupt_Vectors) |
---|
586 | l.lwz r11,40(r11) |
---|
587 | l.j ___standard_exception |
---|
588 | l.addi r3,r0,10 |
---|
589 | .endproc ___DTBL_miss_exception |
---|
590 | |
---|
591 | /* Code wasted between here and 0xB00 */ |
---|
592 | |
---|
593 | /**************************************/ |
---|
594 | /* Range Exception vector static code */ |
---|
595 | /**************************************/ |
---|
596 | .org 0xB00 |
---|
597 | .proc ___range_exception |
---|
598 | .global ___range_exception |
---|
599 | ___range_exception: |
---|
600 | l.addi r1,r1,-80 |
---|
601 | l.sw 0(r1),r3 |
---|
602 | l.sw 28(r1),r11 |
---|
603 | l.movhi r11,hi(_Or1k_Interrupt_Vectors) |
---|
604 | l.ori r11,r11,lo(_Or1k_Interrupt_Vectors) |
---|
605 | l.lwz r11,44(r11) |
---|
606 | l.j ___standard_exception |
---|
607 | l.addi r3,r0,11 |
---|
608 | .endproc ___range_exception |
---|
609 | |
---|
610 | /* Code wasted between here and 0xC00 */ |
---|
611 | |
---|
612 | /**********************************/ |
---|
613 | /* System Call vector static code */ |
---|
614 | /**********************************/ |
---|
615 | .org 0xC00 |
---|
616 | .proc ___system_call |
---|
617 | .global ___system_call |
---|
618 | ___system_call: |
---|
619 | l.addi r1,r1,-80 |
---|
620 | l.sw 0(r1),r3 |
---|
621 | l.sw 28(r1),r11 |
---|
622 | l.movhi r11,hi(_Or1k_Interrupt_Vectors) |
---|
623 | l.ori r11,r11,lo(_Or1k_Interrupt_Vectors) |
---|
624 | l.lwz r11,48(r11) |
---|
625 | l.j ___standard_exception |
---|
626 | l.addi r3,r0,12 |
---|
627 | .endproc ___system_call |
---|
628 | |
---|
629 | /* Code wasted between here and 0xD00 */ |
---|
630 | |
---|
631 | /**********************************/ |
---|
632 | /* Breakpoint vector static code */ |
---|
633 | /**********************************/ |
---|
634 | .org 0xD00 |
---|
635 | .proc ___breakpoint |
---|
636 | .global ___breakpoint |
---|
637 | ___breakpoint: |
---|
638 | |
---|
639 | /* In keeping with the necessary requirements for |
---|
640 | gdb to work, we are limiting this vector to |
---|
641 | only 2 statements, which effect an immediate |
---|
642 | return. At a later date, we may insert a debug |
---|
643 | monitor here that will do even more, but for |
---|
644 | now, this is all we want. */ |
---|
645 | l.rfe |
---|
646 | l.nop |
---|
647 | |
---|
648 | .endproc ___breakpoint |
---|
649 | |
---|
650 | /* Code wasted between here and 0xE00 */ |
---|
651 | |
---|
652 | /*************************************/ |
---|
653 | /* Trap Exception vector static code */ |
---|
654 | /*************************************/ |
---|
655 | .org 0xE00 |
---|
656 | .proc ___trap_exception |
---|
657 | .global ___trap_exception |
---|
658 | ___trap_exception: |
---|
659 | l.addi r1,r1,-80 |
---|
660 | l.sw 0(r1),r3 |
---|
661 | l.sw 28(r1),r11 |
---|
662 | l.movhi r11,hi(_Or1k_Interrupt_Vectors) |
---|
663 | l.ori r11,r11,lo(_Or1k_Interrupt_Vectors) |
---|
664 | l.lwz r11,56(r11) |
---|
665 | l.j ___standard_exception |
---|
666 | l.addi r3,r0,14 |
---|
667 | .endproc ___trap_exception |
---|
668 | |
---|
669 | /* Code wasted between here and 0x2000 */ |
---|
670 | |
---|
671 | /* Exceptions from 0xF00 to 0x1F00 are not defined */ |
---|
672 | /* in the Or1k architecture. They should be filled */ |
---|
673 | /* in here for other implementations. */ |
---|
674 | |
---|
675 | .org 0x2000 /* Start after exception vector table */ |
---|
676 | |
---|
677 | /*********************/ |
---|
678 | /* start */ |
---|
679 | /*********************/ |
---|
680 | |
---|
681 | /* This is where we jump to right after the reset exception |
---|
682 | handler. The system configuration information should |
---|
683 | be passed to us in a pointer in r4. Generally, the |
---|
684 | reset vector will call this routine directly, and |
---|
685 | the memory configuration information will be stored |
---|
686 | in the ROM/Flash image. It was decided no attempt |
---|
687 | would be made to automatically determine this |
---|
688 | information by probing, as the scheme would be too |
---|
689 | complex and inherently unreliable. */ |
---|
690 | |
---|
691 | /* Initialize strings and structures here */ |
---|
692 | L_program: |
---|
693 | .ascii "RTEMS_or1k\000" |
---|
694 | .align 4 |
---|
695 | L_argv: |
---|
696 | .word L_program |
---|
697 | |
---|
698 | .proc _start |
---|
699 | .def _start |
---|
700 | .val _start |
---|
701 | .scl 2 |
---|
702 | .type 044 |
---|
703 | .endef |
---|
704 | .global _start |
---|
705 | _start: |
---|
706 | |
---|
707 | /* Initialize the memory controller here! |
---|
708 | Discussions with Rudi have stated that |
---|
709 | the first few bytes of the ROM image should |
---|
710 | contain a RAM map as opposed to trying to |
---|
711 | figure out what to do based on probing. This |
---|
712 | means a separate build of the OS for every |
---|
713 | possible board configuration, but there |
---|
714 | doesn't seem to be a better alternative. */ |
---|
715 | |
---|
716 | /*** FIX ME! Initialize the external memory controller! ***/ |
---|
717 | |
---|
718 | /* Move the data segment to RAM. Alternatively, we may |
---|
719 | copy the text segment as well. For now, we'll assume |
---|
720 | that the cache gives us sufficient performance that this |
---|
721 | is not necessary. It will be very easy to add this later. |
---|
722 | */ |
---|
723 | l.movhi r4,hi(_etext) |
---|
724 | l.ori r4,r4,lo(_etext) |
---|
725 | l.movhi r5,hi(_BOTTOM_OF_MEMORY) |
---|
726 | l.ori r5,r5,lo(_BOTTOM_OF_MEMORY) |
---|
727 | l.lwz r5,0(r5) # Dereference it |
---|
728 | /* l.add r5,r5,r4 # Place it in memory above the text segment*/ |
---|
729 | l.movhi r3,hi(_edata) |
---|
730 | l.ori r3,r3,lo(_edata) |
---|
731 | l.movhi r5,hi(_data_start) |
---|
732 | l.ori r5,r5,lo(_data_start) |
---|
733 | |
---|
734 | L3_0: |
---|
735 | l.lwz r6,0(r4) |
---|
736 | l.addi r5,r5,4 |
---|
737 | l.addi r4,r4,4 |
---|
738 | l.sfeq r3,r5 |
---|
739 | l.bnf L3_0 |
---|
740 | l.sw -4(r5),r6 # Minimize write after read stalls |
---|
741 | |
---|
742 | /* Initialize the BSS segment */ |
---|
743 | l.movhi r3,hi(__end) |
---|
744 | l.ori r3,r3,lo(__end) |
---|
745 | /* l.sub r3,r3,r4 |
---|
746 | l.add r3,r3,r5*/ |
---|
747 | l.sfleu r3,r5 |
---|
748 | l.bf L3_2 # Check for no BSS segment! |
---|
749 | l.nop |
---|
750 | |
---|
751 | L3_1: |
---|
752 | l.addi r5,r5,4 |
---|
753 | l.sfeq r5,r3 |
---|
754 | l.bnf L3_1 |
---|
755 | l.sw -4(r5),r0 |
---|
756 | |
---|
757 | L3_2: |
---|
758 | /* Tell everyone where the heap begins */ |
---|
759 | l.movhi r4,hi(__mem_end) |
---|
760 | l.ori r4,r4,lo(__mem_end) |
---|
761 | l.sw 0(r4),r5 |
---|
762 | |
---|
763 | /* Due to what I consider a bug in RTEMS, the entire |
---|
764 | heap must be zeroed. I think this is the dumbest thing |
---|
765 | I've ever heard, but whatever turns them on. I'd rather |
---|
766 | see the code which depends on this behavior fixed. I |
---|
767 | myself have never written code which assumes zeroes |
---|
768 | will be returned from memory allocated from the heap. |
---|
769 | Anyway, if I don't do it here, I have to set a flag in |
---|
770 | the CPU structure which then will do it anyway, but |
---|
771 | from less efficient C code! Zero from here to the |
---|
772 | stack pointer... One day when I'm old and gray maybe |
---|
773 | I'll set this to random values instead and fix |
---|
774 | whatever breaks. */ |
---|
775 | |
---|
776 | l.sw 0(r5),r0 |
---|
777 | l.sfeq r5,r1 |
---|
778 | l.bnf L3_3 |
---|
779 | l.addi r5,r5,4 |
---|
780 | |
---|
781 | L3_3: |
---|
782 | l.addi r3,r0,1 /* Set argc to 1 */ |
---|
783 | l.movhi r4,hi(L_argv) /* Initialize argv */ |
---|
784 | l.ori r4,r4,lo(L_argv) |
---|
785 | l.addi r5,r5,0 /* Set envp to NULL */ |
---|
786 | |
---|
787 | l.mfspr r11,r0,17 /* Get SR value */ |
---|
788 | l.ori r11,r11,0x4 /* Set interrupt enable bit */ |
---|
789 | l.jal _boot_card /* Boot up the card...run the OS */ |
---|
790 | l.mtspr r0,r11,17 /* Enable exceptions (DELAY) */ |
---|
791 | |
---|
792 | /* We're done. We exited normally. Shut down. */ |
---|
793 | l.jal __exit |
---|
794 | l.nop |
---|
795 | |
---|
796 | .endproc _start |
---|
797 | .def _start |
---|
798 | .val . |
---|
799 | .scl -1 |
---|
800 | .endef |
---|
801 | |
---|
802 | END_CODE |
---|
803 | |
---|