|
0
|
1 ##============================================================================= |
|
|
2 ## |
|
|
3 ## vectors.S |
|
|
4 ## |
|
|
5 ## MIPS exception vectors |
|
|
6 ## |
|
|
7 ##============================================================================= |
|
|
8 #####COPYRIGHTBEGIN#### |
|
|
9 # |
|
|
10 # ------------------------------------------- |
|
|
11 # The contents of this file are subject to the Cygnus eCos Public License |
|
|
12 # Version 1.0 (the "License"); you may not use this file except in |
|
|
13 # compliance with the License. You may obtain a copy of the License at |
|
|
14 # http://sourceware.cygnus.com/ecos |
|
|
15 # |
|
|
16 # Software distributed under the License is distributed on an "AS IS" |
|
|
17 # basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the |
|
|
18 # License for the specific language governing rights and limitations under |
|
|
19 # the License. |
|
|
20 # |
|
|
21 # The Original Code is eCos - Embedded Cygnus Operating System, released |
|
|
22 # September 30, 1998. |
|
|
23 # |
|
|
24 # The Initial Developer of the Original Code is Cygnus. Portions created |
|
|
25 # by Cygnus are Copyright (C) 1998 Cygnus Solutions. All Rights Reserved. |
|
|
26 # ------------------------------------------- |
|
|
27 # |
|
|
28 #####COPYRIGHTEND#### |
|
|
29 ##============================================================================= |
|
|
30 #######DESCRIPTIONBEGIN#### |
|
|
31 ## |
|
|
32 ## Author(s): nickg |
|
|
33 ## Contributors: nickg |
|
|
34 ## Date: 1998-02-04 |
|
|
35 ## Purpose: MIPS exception vectors |
|
|
36 ## Description: This file defines the code placed into the exception |
|
|
37 ## vectors. It also contains the first level default VSRs |
|
|
38 ## that save and restore state for both exceptions and |
|
|
39 ## interrupts. |
|
|
40 ## |
|
|
41 ######DESCRIPTIONEND#### |
|
|
42 ## |
|
|
43 ##============================================================================= |
|
|
44 |
|
|
45 # .file "vectors.S" |
|
|
46 |
|
|
47 #include <pkgconf/system.h> |
|
|
48 #include <pkgconf/hal.h> |
|
|
49 |
|
|
50 #ifdef CYGPKG_KERNEL |
|
|
51 # include <pkgconf/kernel.h> |
|
|
52 #endif |
|
|
53 |
|
|
54 #include <cyg/hal/mips.inc> |
|
|
55 |
|
|
56 .extern cyg_instrument |
|
|
57 |
|
|
58 ##----------------------------------------------------------------------------- |
|
|
59 |
|
|
60 #define MAX_SAVE_REG 31 |
|
|
61 |
|
|
62 #if defined(CYG_HAL_STARTUP_RAM) |
|
|
63 # if defined(CYG_HAL_MIPS_SIM) || !defined(CYG_HAL_USE_ROM_MONITOR) |
|
|
64 # define INITIAL_SR 0x1000ff00 /* CP0 usable, Ints enabled */ |
|
|
65 //#define INITIAL_SR 0x10000000 /* CP0 usable, Ints disabled */ |
|
|
66 # else |
|
|
67 # define INITIAL_SR 0x1040ff00 /* as above + ROM vectors used */ |
|
|
68 # endif |
|
|
69 #elif defined(CYG_HAL_STARTUP_ROM) |
|
|
70 # define INITIAL_SR 0x1040ff00 /* as above + ROM vectors used */ |
|
|
71 #endif |
|
|
72 |
|
|
73 ##----------------------------------------------------------------------------- |
|
|
74 ## Hardware supplied vectors |
|
|
75 |
|
|
76 .set noreorder |
|
|
77 .set noat |
|
|
78 |
|
|
79 .section ".reset_vector","ax" |
|
|
80 |
|
|
81 # Reset vector at 0xBFC00000 |
|
|
82 |
|
|
83 .globl reset_vector |
|
|
84 reset_vector: |
|
|
85 la v0,_start # jump to start |
|
|
86 jr v0 |
|
|
87 nop # (delay slot) |
|
|
88 |
|
|
89 .section ".debug_vector","ax" |
|
|
90 |
|
|
91 # Debug vector at 0xBFC00200 |
|
|
92 |
|
|
93 .globl debug_vector |
|
|
94 debug_vector: |
|
|
95 la k0,32 |
|
|
96 la k1,hal_vsr_table # Get VSR table |
|
|
97 lw k1,32*4(k1) # load debug vector |
|
|
98 jr k1 # go there |
|
|
99 nop # (delay slot) |
|
|
100 |
|
|
101 .section ".other_vector","ax" |
|
|
102 |
|
|
103 # Common vector at 0x80000080 or 0xBFC00180 |
|
|
104 |
|
|
105 .globl other_vector |
|
|
106 other_vector: |
|
|
107 mfc0 k0,cause # K0 = exception cause |
|
|
108 nop |
|
|
109 andi k0,k0,0x7F # isolate exception code |
|
|
110 la k1,hal_vsr_table # address of VSR table |
|
|
111 add k1,k1,k0 # offset of VSR entry |
|
|
112 lw k1,0(k1) # k1 = pointer to VSR |
|
|
113 jr k1 # go there |
|
|
114 nop # (delay slot) |
|
|
115 |
|
|
116 .section ".utlb_vector","ax" |
|
|
117 |
|
|
118 .globl utlb_vector |
|
|
119 utlb_vector: |
|
|
120 la k0,33 |
|
|
121 la k1,hal_vsr_table # Get VSR table |
|
|
122 lw k1,33*4(k1) # load utlb vector |
|
|
123 jr k1 # go there |
|
|
124 nop # (delay slot) |
|
|
125 |
|
|
126 |
|
|
127 ##----------------------------------------------------------------------------- |
|
|
128 ## Startup code |
|
|
129 |
|
|
130 .text |
|
|
131 |
|
|
132 .globl _start |
|
|
133 .ent _start |
|
|
134 _start: |
|
|
135 # init CPU registers |
|
|
136 mtc0 zero,cause # zero cause reg |
|
|
137 la v0,INITIAL_SR |
|
|
138 mtc0 v0,sr |
|
|
139 mfc0 v0,config |
|
|
140 nop |
|
|
141 .set at |
|
|
142 and v0,v0,0xffffffcf |
|
|
143 # la v0,0 |
|
|
144 .set noat |
|
|
145 mtc0 v0,config |
|
|
146 |
|
|
147 |
|
|
148 # Initialize hardware |
|
|
149 |
|
|
150 #ifdef CYG_HAL_MIPS_JMR3904 |
|
|
151 |
|
|
152 # These mappings need to be set up before we |
|
|
153 # can use the stack and make calls to other |
|
|
154 # functions |
|
|
155 |
|
|
156 # SCS0,1 base addr of ISA & PCI |
|
|
157 la a0,0xffffe010 |
|
|
158 la a1,0x20201410 |
|
|
159 sw a1,0(a0) |
|
|
160 |
|
|
161 la a0,0xffffe014 |
|
|
162 la a1,0x0000fcfc |
|
|
163 sw a1,0(a0) |
|
|
164 |
|
|
165 # ROM configuration |
|
|
166 la a0,0xffff9000 |
|
|
167 la a1,0x1fc00400 |
|
|
168 sw a1,0(a0) |
|
|
169 |
|
|
170 # SRAM config |
|
|
171 la a0,0xffff9100 |
|
|
172 la a1,0x00000000 |
|
|
173 sw a1,0(a0) |
|
|
174 |
|
|
175 la a0,0xfffff500 |
|
|
176 la a1,0xff |
|
|
177 sb a1,0(a0) |
|
|
178 la a1,0 |
|
|
179 sb a1,4(a0) |
|
|
180 #endif |
|
|
181 |
|
|
182 # Load Global Pointer register. |
|
|
183 la gp,_gp |
|
|
184 |
|
|
185 # load initial stack pointer |
|
|
186 la a0,__interrupt_stack |
|
|
187 move sp,a0 |
|
|
188 |
|
|
189 #if defined(CYG_HAL_STARTUP_ROM) || \ |
|
|
190 (defined(CYG_HAL_STARTUP_RAM) && !defined(CYG_HAL_USE_ROM_MONITOR)) |
|
|
191 |
|
|
192 # If we are starting up from ROM, or we are starting in |
|
|
193 # RAM and NOT using a ROM monitor, initialize the VSR table. |
|
|
194 |
|
|
195 la a0,__default_interrupt_vsr |
|
|
196 la a1,__default_exception_vsr |
|
|
197 la a3,hal_vsr_table |
|
|
198 sw a0,0(a3) |
|
|
199 sw a1,1*4(a3) |
|
|
200 sw a1,2*4(a3) |
|
|
201 sw a1,3*4(a3) |
|
|
202 sw a1,4*4(a3) |
|
|
203 sw a1,5*4(a3) |
|
|
204 sw a1,6*4(a3) |
|
|
205 sw a1,7*4(a3) |
|
|
206 sw a1,8*4(a3) |
|
|
207 sw a1,9*4(a3) |
|
|
208 sw a1,10*4(a3) |
|
|
209 sw a1,11*4(a3) |
|
|
210 sw a1,12*4(a3) |
|
|
211 sw a1,13*4(a3) |
|
|
212 sw a1,14*4(a3) |
|
|
213 sw a1,15*4(a3) |
|
|
214 |
|
|
215 sw a1,32*4(a3) |
|
|
216 sw a1,33*4(a3) |
|
|
217 |
|
|
218 #ifdef CYG_HAL_ROM_MONITOR |
|
|
219 |
|
|
220 # Install vectors to debug read and write functions |
|
|
221 |
|
|
222 .extern hal_diag_write_char |
|
|
223 .extern hal_diag_read_char |
|
|
224 .extern breakpoint |
|
|
225 |
|
|
226 la a0,hal_diag_write_char |
|
|
227 sw a0,63*4(a3) |
|
|
228 la a1,hal_diag_read_char |
|
|
229 sw a1,62*4(a3) |
|
|
230 la a0,breakpoint |
|
|
231 sw a0,61*4(a3) |
|
|
232 |
|
|
233 #endif |
|
|
234 |
|
|
235 #endif |
|
|
236 #if defined(CYG_HAL_STARTUP_RAM) && defined(CYG_HAL_USE_ROM_MONITOR) |
|
|
237 |
|
|
238 # initialize the VSR table |
|
|
239 # We only take control of the interrupt vector, |
|
|
240 # the rest are left to the ROM for now... |
|
|
241 |
|
|
242 la a0,__default_interrupt_vsr |
|
|
243 la a3,hal_vsr_table |
|
|
244 sw a0,0(a3) |
|
|
245 |
|
|
246 #endif |
|
|
247 |
|
|
248 #ifdef CYG_HAL_STARTUP_ROM |
|
|
249 # Copy data from ROM to RAM |
|
|
250 |
|
|
251 .extern hal_copy_data |
|
|
252 jal hal_copy_data |
|
|
253 nop |
|
|
254 #endif |
|
|
255 |
|
|
256 # Zero BSS |
|
|
257 |
|
|
258 .extern hal_zero_bss |
|
|
259 jal hal_zero_bss |
|
|
260 nop |
|
|
261 |
|
|
262 # Call constructors |
|
|
263 |
|
|
264 .extern cyg_hal_invoke_constructors |
|
|
265 jal cyg_hal_invoke_constructors |
|
|
266 nop |
|
|
267 |
|
|
268 # Call cyg_start |
|
|
269 |
|
|
270 .extern cyg_start |
|
|
271 jal cyg_start |
|
|
272 nop |
|
|
273 |
|
|
274 9: |
|
|
275 j 9b # Loop if we return |
|
|
276 nop # (delay slot) |
|
|
277 |
|
|
278 .end _start |
|
|
279 |
|
|
280 ##----------------------------------------------------------------------------- |
|
|
281 ## Default exception VSR. |
|
|
282 ## Saves machine state and calls external handling code. |
|
|
283 |
|
|
284 .globl __default_exception_vsr |
|
|
285 .ent __default_exception_vsr |
|
|
286 __default_exception_vsr: |
|
|
287 |
|
|
288 # We enter here with all of the CPU state still |
|
|
289 # in its registers except: |
|
|
290 # K0 = vector index |
|
|
291 # K1 = address of this function |
|
|
292 |
|
|
293 #ifdef CYG_HAL_ROM_MONITOR |
|
|
294 # Switch to interrupt stack to handle exception |
|
|
295 move k1,sp |
|
|
296 la sp,__interrupt_stack |
|
|
297 #endif |
|
|
298 |
|
|
299 addi sp,sp,-mips_exception_decrement |
|
|
300 # space for registers + safety margin |
|
|
301 |
|
|
302 sw k0,mipsreg_vector(sp) # store vector |
|
|
303 |
|
|
304 .set noat |
|
|
305 # store GPRs |
|
|
306 sw $0,(mipsreg_regs+0*4)(sp) |
|
|
307 sw $1,(mipsreg_regs+1*4)(sp) |
|
|
308 sw $2,(mipsreg_regs+2*4)(sp) |
|
|
309 sw $3,(mipsreg_regs+3*4)(sp) |
|
|
310 sw $4,(mipsreg_regs+4*4)(sp) |
|
|
311 sw $5,(mipsreg_regs+5*4)(sp) |
|
|
312 sw $6,(mipsreg_regs+6*4)(sp) |
|
|
313 sw $7,(mipsreg_regs+7*4)(sp) |
|
|
314 sw $8,(mipsreg_regs+8*4)(sp) |
|
|
315 sw $9,(mipsreg_regs+9*4)(sp) |
|
|
316 sw $10,(mipsreg_regs+10*4)(sp) |
|
|
317 sw $11,(mipsreg_regs+11*4)(sp) |
|
|
318 sw $12,(mipsreg_regs+12*4)(sp) |
|
|
319 sw $13,(mipsreg_regs+13*4)(sp) |
|
|
320 sw $14,(mipsreg_regs+14*4)(sp) |
|
|
321 sw $15,(mipsreg_regs+15*4)(sp) |
|
|
322 sw $16,(mipsreg_regs+16*4)(sp) |
|
|
323 sw $17,(mipsreg_regs+17*4)(sp) |
|
|
324 sw $18,(mipsreg_regs+18*4)(sp) |
|
|
325 sw $19,(mipsreg_regs+19*4)(sp) |
|
|
326 sw $20,(mipsreg_regs+20*4)(sp) |
|
|
327 sw $21,(mipsreg_regs+21*4)(sp) |
|
|
328 sw $22,(mipsreg_regs+22*4)(sp) |
|
|
329 sw $23,(mipsreg_regs+23*4)(sp) |
|
|
330 sw $24,(mipsreg_regs+24*4)(sp) |
|
|
331 sw $25,(mipsreg_regs+25*4)(sp) |
|
|
332 # sw $26,(mipsreg_regs+26*4)(sp) # == K0 |
|
|
333 # sw $27,(mipsreg_regs+27*4)(sp) # == K1 |
|
|
334 sw $28,(mipsreg_regs+28*4)(sp) # == GP |
|
|
335 # sw $29,(mipsreg_regs+29*4)(sp) # == SP |
|
|
336 sw $30,(mipsreg_regs+30*4)(sp) # == FP |
|
|
337 sw $31,(mipsreg_regs+31*4)(sp) # == RA |
|
|
338 |
|
|
339 mfhi a0 |
|
|
340 mflo a1 |
|
|
341 sw a0,mipsreg_hi(sp) |
|
|
342 sw a1,mipsreg_lo(sp) |
|
|
343 |
|
|
344 #ifdef CYG_HAL_ROM_MONITOR |
|
|
345 # K1 contains original SP |
|
|
346 sw k1,(mipsreg_regs+29*4)(sp) # store in reg dump |
|
|
347 #else |
|
|
348 # synthesize original SP value |
|
|
349 move a2,sp # a2 = sp |
|
|
350 addi a2,a2,mips_exception_decrement # a2 = original sp |
|
|
351 sw a2,(mipsreg_regs+29*4)(sp) # store in reg dump |
|
|
352 #endif |
|
|
353 |
|
|
354 # save remaining machine state registers |
|
|
355 mfc0 t0,cause |
|
|
356 mfc0 t1,sr |
|
|
357 # mfc0 t2,cache |
|
|
358 mfc0 t3,badvr |
|
|
359 mfc0 t4,config |
|
|
360 mfc0 t5,prid |
|
|
361 mfc0 t6,epc |
|
|
362 |
|
|
363 #ifndef CYG_HAL_MIPS_SIM |
|
|
364 mfc0 t2,cache |
|
|
365 #endif |
|
|
366 |
|
|
367 sw t0,mipsreg_cause(sp) |
|
|
368 sw t1,mipsreg_sr(sp) |
|
|
369 sw t2,mipsreg_cache(sp) |
|
|
370 sw t3,mipsreg_badvr(sp) |
|
|
371 sw t4,mipsreg_config(sp) |
|
|
372 sw t5,mipsreg_prid(sp) |
|
|
373 sw t6,mipsreg_pc(sp) |
|
|
374 |
|
|
375 |
|
|
376 # The machine state is now all saved on the stack. |
|
|
377 |
|
|
378 # Load Global Pointer register. |
|
|
379 la gp,_gp |
|
|
380 |
|
|
381 move s0,sp # save pointer to saved state |
|
|
382 |
|
|
383 addi sp,sp,-mips_stack_frame_size # make a null frame |
|
|
384 |
|
|
385 # Need to set up back pointers etc. ??? |
|
|
386 |
|
|
387 la ra,restore_state # load return address |
|
|
388 |
|
|
389 .extern exception_handler |
|
|
390 j exception_handler # call C code |
|
|
391 move a0,s0 # arg0 = register dump (delay slot) |
|
|
392 |
|
|
393 # When the exception handler returns, it will |
|
|
394 # go back to restore_state, below. |
|
|
395 |
|
|
396 .end __default_exception_vsr |
|
|
397 |
|
|
398 ##------------------------------------------------------------------------------ |
|
|
399 ## Default interrupt VSR. |
|
|
400 ## Saves machine state and calls appropriate ISR. When done, calls |
|
|
401 ## interrupt_end() to finish up and possibly reschedule. |
|
|
402 |
|
|
403 .globl __default_interrupt_vsr |
|
|
404 .ent __default_interrupt_vsr |
|
|
405 __default_interrupt_vsr: |
|
|
406 |
|
|
407 |
|
|
408 # We enter here with all of the CPU state still |
|
|
409 # in its registers except: |
|
|
410 # K0 = vector index |
|
|
411 # K1 = address of this function |
|
|
412 |
|
|
413 addi sp,sp,-mips_exception_decrement |
|
|
414 # space for registers + safety margin |
|
|
415 |
|
|
416 sw k0,mipsreg_vector(sp) # store vector |
|
|
417 |
|
|
418 # store GPRs |
|
|
419 sw $0,(mipsreg_regs+0*4)(sp) |
|
|
420 sw $1,(mipsreg_regs+1*4)(sp) |
|
|
421 sw $2,(mipsreg_regs+2*4)(sp) |
|
|
422 sw $3,(mipsreg_regs+3*4)(sp) |
|
|
423 sw $4,(mipsreg_regs+4*4)(sp) |
|
|
424 sw $5,(mipsreg_regs+5*4)(sp) |
|
|
425 sw $6,(mipsreg_regs+6*4)(sp) |
|
|
426 sw $7,(mipsreg_regs+7*4)(sp) |
|
|
427 sw $8,(mipsreg_regs+8*4)(sp) |
|
|
428 sw $9,(mipsreg_regs+9*4)(sp) |
|
|
429 sw $10,(mipsreg_regs+10*4)(sp) |
|
|
430 sw $11,(mipsreg_regs+11*4)(sp) |
|
|
431 sw $12,(mipsreg_regs+12*4)(sp) |
|
|
432 sw $13,(mipsreg_regs+13*4)(sp) |
|
|
433 sw $14,(mipsreg_regs+14*4)(sp) |
|
|
434 sw $15,(mipsreg_regs+15*4)(sp) |
|
|
435 sw $16,(mipsreg_regs+16*4)(sp) |
|
|
436 sw $17,(mipsreg_regs+17*4)(sp) |
|
|
437 sw $18,(mipsreg_regs+18*4)(sp) |
|
|
438 sw $19,(mipsreg_regs+19*4)(sp) |
|
|
439 sw $20,(mipsreg_regs+20*4)(sp) |
|
|
440 sw $21,(mipsreg_regs+21*4)(sp) |
|
|
441 sw $22,(mipsreg_regs+22*4)(sp) |
|
|
442 sw $23,(mipsreg_regs+23*4)(sp) |
|
|
443 sw $24,(mipsreg_regs+24*4)(sp) |
|
|
444 sw $25,(mipsreg_regs+25*4)(sp) |
|
|
445 # sw $26,(mipsreg_regs+26*4)(sp) # == K0 |
|
|
446 # sw $27,(mipsreg_regs+27*4)(sp) # == K1 |
|
|
447 sw $28,(mipsreg_regs+28*4)(sp) # == GP |
|
|
448 # sw $29,(mipsreg_regs+29*4)(sp) # == SP |
|
|
449 sw $30,(mipsreg_regs+30*4)(sp) # == FP |
|
|
450 sw $31,(mipsreg_regs+31*4)(sp) # == RA |
|
|
451 |
|
|
452 mfhi a0 |
|
|
453 mflo a1 |
|
|
454 sw a0,mipsreg_hi(sp) |
|
|
455 sw a1,mipsreg_lo(sp) |
|
|
456 |
|
|
457 # synthesize original SP value |
|
|
458 move a2,sp # a2 = sp |
|
|
459 addi a2,a2,mips_exception_decrement # a2 = original sp |
|
|
460 sw a2,(mipsreg_regs+29*4)(sp) # store in reg dump |
|
|
461 |
|
|
462 mfc0 t1,sr |
|
|
463 mfc0 t3,epc |
|
|
464 |
|
|
465 #ifndef CYG_HAL_MIPS_SIM |
|
|
466 mfc0 t2,cache |
|
|
467 #endif |
|
|
468 sw t1,mipsreg_sr(sp) |
|
|
469 sw t2,mipsreg_cache(sp) |
|
|
470 sw t3,mipsreg_pc(sp) |
|
|
471 |
|
|
472 # The machine state is now all saved on the stack. |
|
|
473 |
|
|
474 # Load Global Pointer register. |
|
|
475 la gp,_gp |
|
|
476 |
|
|
477 #ifdef CYGFUN_HAL_COMMON_KERNEL_SUPPORT |
|
|
478 .extern _18Cyg_Scheduler_Base$sched_lock |
|
|
479 la v0,_18Cyg_Scheduler_Base$sched_lock |
|
|
480 lw a0,0(v0) |
|
|
481 addi a0,a0,1 |
|
|
482 sw a0,0(v0) |
|
|
483 #endif |
|
|
484 |
|
|
485 move s0,sp # save pointer to saved state |
|
|
486 |
|
|
487 #ifdef CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK |
|
|
488 |
|
|
489 la a0,__interrupt_stack # a0 = stack top |
|
|
490 la a1,__interrupt_stack_base # a1 = stack base |
|
|
491 sub a3,sp,a1 # a3 = sp - base |
|
|
492 bltz a3,1f # if < 0 - not on istack |
|
|
493 nop # delay slot |
|
|
494 sub t0,a0,sp # t0 = top - sp |
|
|
495 bgtz t0,8f # if > 0 - already on istack |
|
|
496 nop # delay slot |
|
|
497 1: |
|
|
498 move sp,a0 # switch to istack |
|
|
499 8: |
|
|
500 addi sp,sp,-4 # space for old SP |
|
|
501 sw s0,0(sp) # save old SP on stack |
|
|
502 |
|
|
503 #endif |
|
|
504 |
|
|
505 subu sp,sp,mips_stack_frame_size # make a null frame |
|
|
506 |
|
|
507 # Need to set up back pointers etc. ??? |
|
|
508 |
|
|
509 # Decode external interrupt via interrupt controller |
|
|
510 |
|
|
511 mfc0 a1,cause # get cause register |
|
|
512 nop |
|
|
513 srl a1,a1,10 # shift IP bits to ls bits |
|
|
514 andi a1,a1,0x7F # isolate IP bits |
|
|
515 la t0,interrupt_translation_table # address of translation table |
|
|
516 add t0,t0,a1 # offset of index byte |
|
|
517 lb s2,0(t0) # load it |
|
|
518 |
|
|
519 #ifdef CYGIMP_HAL_COMMON_INTERRUPTS_CHAIN |
|
|
520 move s1,zero # Just vector zero is supported |
|
|
521 #else |
|
|
522 move s1,s2 # Vector == interrupt number |
|
|
523 #endif |
|
|
524 |
|
|
525 # Here s1 is the number of the vector to be called and s2 is |
|
|
526 # the number of the interrupt being serviced. |
|
|
527 |
|
|
528 #if defined(CYGPKG_KERNEL_INSTRUMENT) && defined(CYGDBG_KERNEL_INSTRUMENT_INTR) |
|
|
529 |
|
|
530 # Call cyg_instrument to record that this interrupt is being raised. |
|
|
531 |
|
|
532 li a0,0x0301 # a0 = type = INTR,RAISE |
|
|
533 move a1,s1 # a1 = vector number |
|
|
534 jal cyg_instrument # call instrument function |
|
|
535 xor a2,a2,a2 # arg2 = 0 (delay slot) |
|
|
536 #endif |
|
|
537 |
|
|
538 sll s1,s1,2 # s1 = byte offset of vector |
|
|
539 |
|
|
540 la t2,hal_interrupt_handlers # handler table |
|
|
541 add t2,t2,s1 # address of ISR ptr |
|
|
542 lw t2,0(t2) # ISR pointer |
|
|
543 |
|
|
544 la a1,hal_interrupt_data # data table |
|
|
545 add a1,a1,s1 # address of data ptr |
|
|
546 lw a1,0(a1) # Data pointer |
|
|
547 |
|
|
548 move a0,s2 # pass interrupt number |
|
|
549 |
|
|
550 jalr t2 # call ISR via t2 |
|
|
551 nop # (delay slot) |
|
|
552 |
|
|
553 #ifdef CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK |
|
|
554 |
|
|
555 # If we are returning from the last nested interrupt, move back |
|
|
556 # to the thread stack. interrupt_end() must be called on the |
|
|
557 # thread stack since it potentially causes a context switch. |
|
|
558 # Since we have arranged for the top of stack location to |
|
|
559 # contain the sp we need to go back to here, just pop it off |
|
|
560 # and put it in SP. |
|
|
561 |
|
|
562 |
|
|
563 lw sp,mips_stack_frame_size(sp) # sp = *sp |
|
|
564 subu sp,sp,mips_stack_frame_size # make a null frame |
|
|
565 #endif |
|
|
566 |
|
|
567 #ifdef CYGFUN_HAL_COMMON_KERNEL_SUPPORT |
|
|
568 |
|
|
569 # We only need to call _interrupt_end() when there is a kernel |
|
|
570 # present to do any tidying up. |
|
|
571 |
|
|
572 # On return v0 bit 1 will indicate whether a DSR is |
|
|
573 # to be posted. Pass this together with a pointer to |
|
|
574 # the interrupt object we have just used to the |
|
|
575 # interrupt tidy up routine. |
|
|
576 |
|
|
577 # Note that s0, s1 and s2 are defined to be preserved across |
|
|
578 # calls by the calling convention, so they still contain |
|
|
579 # the register dump, the vector offset and the interrupt number |
|
|
580 # respectively. |
|
|
581 |
|
|
582 move a0,v0 # put ISR result in arg0 |
|
|
583 |
|
|
584 la a1,hal_interrupt_objects # interrupt object table |
|
|
585 add a1,a1,s1 # address of object ptr |
|
|
586 lw a1,0(a1) # a1 = object ptr |
|
|
587 |
|
|
588 move a2,s0 # arg3 = saved register dump |
|
|
589 |
|
|
590 # interrupt_end() must be called with interrupts enabled. |
|
|
591 |
|
|
592 rfe # restore previous status bits |
|
|
593 # this may enable interrupts |
|
|
594 |
|
|
595 .extern interrupt_end |
|
|
596 jal interrupt_end # call into C to finish off |
|
|
597 nop # (delay slot) |
|
|
598 |
|
|
599 #endif |
|
|
600 |
|
|
601 restore_state: |
|
|
602 |
|
|
603 # All done, restore CPU state and continue |
|
|
604 |
|
|
605 addi sp,sp,mips_stack_frame_size # retrieve CPU state ptr |
|
|
606 |
|
|
607 # Load status register and cache control register. |
|
|
608 # This will put the interrupt, mode and cache control |
|
|
609 # bits back to their post-exception values, so we will |
|
|
610 # need to do another RFE before we finish. |
|
|
611 |
|
|
612 lw t1,mipsreg_sr(sp) |
|
|
613 lw t2,mipsreg_cache(sp) |
|
|
614 |
|
|
615 mtc0 t1,sr |
|
|
616 #ifndef CYG_HAL_MIPS_SIM |
|
|
617 mtc0 t2,cache |
|
|
618 #endif |
|
|
619 |
|
|
620 lw a0,mipsreg_hi(sp) |
|
|
621 lw a1,mipsreg_lo(sp) |
|
|
622 mthi a0 |
|
|
623 mtlo a1 |
|
|
624 |
|
|
625 # load GPRs |
|
|
626 # lw $0,(mipsreg_regs+0*4)(sp) |
|
|
627 lw $1,(mipsreg_regs+1*4)(sp) |
|
|
628 lw $2,(mipsreg_regs+2*4)(sp) |
|
|
629 lw $3,(mipsreg_regs+3*4)(sp) |
|
|
630 lw $4,(mipsreg_regs+4*4)(sp) |
|
|
631 lw $5,(mipsreg_regs+5*4)(sp) |
|
|
632 lw $6,(mipsreg_regs+6*4)(sp) |
|
|
633 lw $7,(mipsreg_regs+7*4)(sp) |
|
|
634 lw $8,(mipsreg_regs+8*4)(sp) |
|
|
635 lw $9,(mipsreg_regs+9*4)(sp) |
|
|
636 lw $10,(mipsreg_regs+10*4)(sp) |
|
|
637 lw $11,(mipsreg_regs+11*4)(sp) |
|
|
638 lw $12,(mipsreg_regs+12*4)(sp) |
|
|
639 lw $13,(mipsreg_regs+13*4)(sp) |
|
|
640 lw $14,(mipsreg_regs+14*4)(sp) |
|
|
641 lw $15,(mipsreg_regs+15*4)(sp) |
|
|
642 lw $16,(mipsreg_regs+16*4)(sp) |
|
|
643 lw $17,(mipsreg_regs+17*4)(sp) |
|
|
644 lw $18,(mipsreg_regs+18*4)(sp) |
|
|
645 lw $19,(mipsreg_regs+19*4)(sp) |
|
|
646 lw $20,(mipsreg_regs+20*4)(sp) |
|
|
647 lw $21,(mipsreg_regs+21*4)(sp) |
|
|
648 lw $22,(mipsreg_regs+22*4)(sp) |
|
|
649 lw $23,(mipsreg_regs+23*4)(sp) |
|
|
650 lw $24,(mipsreg_regs+24*4)(sp) |
|
|
651 lw $25,(mipsreg_regs+25*4)(sp) |
|
|
652 # lw $26,(mipsreg_regs+26*4)(sp) # == K0 |
|
|
653 # lw $27,(mipsreg_regs+27*4)(sp) # == K1 |
|
|
654 lw $28,(mipsreg_regs+28*4)(sp) # == GP |
|
|
655 # lw $29,(mipsreg_regs+29*4)(sp) # == SP |
|
|
656 lw $30,(mipsreg_regs+30*4)(sp) # == FP |
|
|
657 lw $31,(mipsreg_regs+31*4)(sp) # == RA |
|
|
658 |
|
|
659 lw k0,mipsreg_pc(sp) # K0 = return PC |
|
|
660 lw sp,(mipsreg_regs+29*4)(sp) # load SP |
|
|
661 sync |
|
|
662 jr k0 # jump back to interrupted code |
|
|
663 rfe # restore state (delay slot) |
|
|
664 |
|
|
665 .end __default_interrupt_vsr |
|
|
666 |
|
|
667 # This table translates from the 6 bit value supplied in the IP bits |
|
|
668 # of the cause register into a 0..16 offset into the ISR tables. |
|
|
669 interrupt_translation_table: |
|
|
670 .byte 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 |
|
|
671 .byte 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 |
|
|
672 .byte 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16 |
|
|
673 .byte 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16 |
|
|
674 |
|
|
675 ##----------------------------------------------------------------------------- |
|
|
676 ## Interrupt Stack. |
|
|
677 ## Used during intialization and for executing ISRs. |
|
|
678 |
|
|
679 .bss |
|
|
680 |
|
|
681 .balign 16 |
|
|
682 __interrupt_stack_base: |
|
|
683 .rept CYGNUM_HAL_COMMON_INTERRUPTS_STACK_SIZE |
|
|
684 .byte 0 |
|
|
685 .endr |
|
|
686 .balign 16 |
|
|
687 __interrupt_stack: |
|
|
688 |
|
|
689 .long 0,0,0,0,0,0,0,0 |
|
|
690 |
|
|
691 #ifdef CYGFUN_HAL_COMMON_KERNEL_SUPPORT |
|
|
692 |
|
|
693 .globl idle_thread_stack |
|
|
694 idle_thread_stack: |
|
|
695 .rept CYGNUM_KERNEL_THREADS_IDLE_STACK_SIZE |
|
|
696 .byte 0 |
|
|
697 .endr |
|
|
698 |
|
|
699 #endif |
|
|
700 |
|
|
701 ##----------------------------------------------------------------------------- |
|
|
702 ## VSR table. |
|
|
703 ## The main interrupt code indirects through here to find the VSR |
|
|
704 ## to execute for each architecture defined interrupt. |
|
|
705 ## This is only used for simulated targets, on real targets a fixed location VSR |
|
|
706 ## table is now allocated at 0x80000100. |
|
|
707 |
|
|
708 #if defined(CYG_HAL_MIPS_SIM) || \ |
|
|
709 ( defined(CYG_HAL_MIPS_TX3904) && \ |
|
|
710 defined(CYG_HAL_STARTUP_RAM) && \ |
|
|
711 !defined(CYG_HAL_USE_ROM_MONITOR) \ |
|
|
712 ) |
|
|
713 .section ".vsr_table","a" |
|
|
714 |
|
|
715 .globl hal_vsr_table |
|
|
716 |
|
|
717 hal_vsr_table: |
|
|
718 .long __default_interrupt_vsr |
|
|
719 .rept 63 |
|
|
720 .long __default_exception_vsr |
|
|
721 .endr |
|
|
722 |
|
|
723 #endif |
|
|
724 |
|
|
725 #------------------------------------------------------------------------------ |
|
|
726 # Interrupt vector tables. |
|
|
727 # These tables contain the isr, data and object pointers used to deliver |
|
|
728 # interrupts to user code. |
|
|
729 # hal_interrupt_level contains the interrupt level set by |
|
|
730 # HAL_INTERRUPT_CONFIGURE(). |
|
|
731 |
|
|
732 |
|
|
733 .extern hal_default_isr |
|
|
734 |
|
|
735 .data |
|
|
736 |
|
|
737 .globl hal_interrupt_handlers |
|
|
738 hal_interrupt_handlers: |
|
|
739 .long hal_default_isr |
|
|
740 .long hal_default_isr |
|
|
741 .long hal_default_isr |
|
|
742 .long hal_default_isr |
|
|
743 .long hal_default_isr |
|
|
744 .long hal_default_isr |
|
|
745 .long hal_default_isr |
|
|
746 .long hal_default_isr |
|
|
747 .long hal_default_isr |
|
|
748 .long hal_default_isr |
|
|
749 .long hal_default_isr |
|
|
750 .long hal_default_isr |
|
|
751 .long hal_default_isr |
|
|
752 .long hal_default_isr |
|
|
753 .long hal_default_isr |
|
|
754 .long hal_default_isr |
|
|
755 .long hal_default_isr |
|
|
756 |
|
|
757 .globl hal_interrupt_data |
|
|
758 hal_interrupt_data: |
|
|
759 .rept 17 |
|
|
760 .long 0 |
|
|
761 .endr |
|
|
762 |
|
|
763 .globl hal_interrupt_objects |
|
|
764 hal_interrupt_objects: |
|
|
765 .rept 17 |
|
|
766 .long 0 |
|
|
767 .endr |
|
|
768 |
|
|
769 .globl hal_interrupt_level |
|
|
770 hal_interrupt_level: |
|
|
771 .rept 17 |
|
|
772 .byte 7 |
|
|
773 .endr |
|
|
774 |
|
|
775 ##----------------------------------------------------------------------------- |
|
|
776 ## end of vectors.S |