source: rtems/c/src/exec/score/cpu/mips/cpu_asm.S @ 87e8f25

4.104.114.84.95
Last change on this file since 87e8f25 was 87e8f25, checked in by Joel Sherrill <joel.sherrill@…>, on Dec 19, 2000 at 4:46:29 PM

2000-12-19 Joel Sherrill <joel@…>

  • cpu_asm.S (_ISR_Handler): Return to the address in the EPC register. Previous code resulting in the interrupted immediately returning to the caller of the routine it was inside.
  • Property mode set to 100644
File size: 22.2 KB
Line 
1/*
2 *  This file contains the basic algorithms for all assembly code used
3 *  in an specific CPU port of RTEMS.  These algorithms must be implemented
4 *  in assembly language
5 *
6 *  History:
7 *    Baseline: no_cpu
8 *    1996:     Ported to MIPS64ORION by Craig Lebakken <craigl@transition.com>
9 *          COPYRIGHT (c) 1996 by Transition Networks Inc.
10 *          To anyone who acknowledges that the modifications to this file to
11 *          port it to the MIPS64ORION are provided "AS IS" without any
12 *          express or implied warranty:
13 *             permission to use, copy, modify, and distribute this file
14 *             for any purpose is hereby granted without fee, provided that
15 *             the above copyright notice and this notice appears in all
16 *             copies, and that the name of Transition Networks not be used in
17 *             advertising or publicity pertaining to distribution of the
18 *             software without specific, written prior permission. Transition
19 *             Networks makes no representations about the suitability
20 *             of this software for any purpose.
21 *    2000: Reworked by Alan Cudmore <alanc@linuxstart.com> to become
22 *          the more general MIPS port.  Joel Sherrill <joel@OARcorp.com>
23 *          continued this rework, rewriting as much as possible in
24 *          C and testing on the TX39.
25 * 
26 *  COPYRIGHT (c) 1989-2000.
27 *  On-Line Applications Research Corporation (OAR).
28 *
29 *  The license and distribution terms for this file may be
30 *  found in the file LICENSE in this distribution or at
31 *  http://www.OARcorp.com/rtems/license.html.
32 *
33 *  $Id$
34 */
35
36#include <asm.h>
37#include "iregdef.h"
38#include "idtcpu.h"
39
40#define EXCP_STACK_SIZE (NREGS*R_SZ)
41#define ISR_VEC_SIZE 4
42
43#if 1  /* 32 bit unsigned32 types */
44#define sint sw
45#define lint lw
46#define stackadd addiu
47#define intadd addu
48#define SZ_INT 4
49#define SZ_INT_POW2 2
50#else /* 64 bit unsigned32 types */
51#define sint dw
52#define lint dw
53#define stackadd daddiu
54#define intadd daddu
55#define SZ_INT 8
56#define SZ_INT_POW2 3
57#endif
58
59#ifdef __GNUC__
60#define EXTERN(x,size) .extern x,size
61#else
62#define EXTERN(x,size)
63#endif
64
65/* NOTE: these constants must match the Context_Control structure in cpu.h */
66#define S0_OFFSET 0
67#define S1_OFFSET 1
68#define S2_OFFSET 2
69#define S3_OFFSET 3
70#define S4_OFFSET 4
71#define S5_OFFSET 5
72#define S6_OFFSET 6
73#define S7_OFFSET 7
74#define SP_OFFSET 8
75#define FP_OFFSET 9
76#define RA_OFFSET 10
77#define C0_SR_OFFSET 11
78#define C0_EPC_OFFSET 12
79
80/* NOTE: these constants must match the Context_Control_fp structure in cpu.h */
81#define FP0_OFFSET  0
82#define FP1_OFFSET  1
83#define FP2_OFFSET  2
84#define FP3_OFFSET  3
85#define FP4_OFFSET  4
86#define FP5_OFFSET  5
87#define FP6_OFFSET  6
88#define FP7_OFFSET  7
89#define FP8_OFFSET  8
90#define FP9_OFFSET  9
91#define FP10_OFFSET 10
92#define FP11_OFFSET 11
93#define FP12_OFFSET 12
94#define FP13_OFFSET 13
95#define FP14_OFFSET 14
96#define FP15_OFFSET 15
97#define FP16_OFFSET 16
98#define FP17_OFFSET 17
99#define FP18_OFFSET 18
100#define FP19_OFFSET 19
101#define FP20_OFFSET 20
102#define FP21_OFFSET 21
103#define FP22_OFFSET 22
104#define FP23_OFFSET 23
105#define FP24_OFFSET 24
106#define FP25_OFFSET 25
107#define FP26_OFFSET 26
108#define FP27_OFFSET 27
109#define FP28_OFFSET 28
110#define FP29_OFFSET 29
111#define FP30_OFFSET 30
112#define FP31_OFFSET 31
113
114
115/*PAGE
116 *
117 *  _CPU_ISR_Get_level
118 *
119 *  unsigned32 _CPU_ISR_Get_level( void )
120 *
121 *  This routine returns the current interrupt level.
122 */
123
124#if __mips == 3
125/* return the current exception level for the 4650 */
126FRAME(_CPU_ISR_Get_level,sp,0,ra)
127        mfc0 v0,C0_SR
128        nop
129        andi v0,SR_EXL
130        srl v0,1
131        j ra
132ENDFRAME(_CPU_ISR_Get_level)
133
134FRAME(_CPU_ISR_Set_level,sp,0,ra)
135        nop
136        mfc0 v0,C0_SR
137        nop
138        andi v0,SR_EXL
139        beqz v0,_CPU_ISR_Set_1          /* normalize v0 */
140        nop
141        li v0,1         
142_CPU_ISR_Set_1:
143        beq v0,a0,_CPU_ISR_Set_exit     /* if (current_level != new_level ) */
144        nop
145        bnez a0,_CPU_ISR_Set_2
146        nop
147        nop
148        mfc0 t0, C0_SR
149        nop
150        li t1,~SR_EXL
151        and t0,t1
152        nop
153        mtc0 t0,C0_SR                   /* disable exception level */
154        nop
155        j ra
156        nop
157_CPU_ISR_Set_2:
158        nop
159        mfc0 t0,C0_SR
160        nop
161        li t1,~SR_IE
162        and t0,t1
163        nop
164        mtc0 t0,C0_SR                   /* first disable ie bit (recommended) */
165        nop
166        ori  t0, SR_EXL|SR_IE           /* enable exception level */   
167        nop
168        mtc0 t0,C0_SR         
169        nop
170_CPU_ISR_Set_exit:
171        j ra
172        nop
173ENDFRAME(_CPU_ISR_Set_level)
174
175#elif __mips == 1
176
177/* MIPS ISA 1 ( R3000 ) */
178/* _CPU_ISR_Get/Set_level are called as part of task mode manipulation. */
179/*  and are defined in C for the __mips == 1 */
180
181#else
182   #error "__mips is set to 1 or 3"
183#endif
184
185/*
186 *  _CPU_Context_save_fp_context
187 *
188 *  This routine is responsible for saving the FP context
189 *  at *fp_context_ptr.  If the point to load the FP context
190 *  from is changed then the pointer is modified by this routine.
191 *
192 *  Sometimes a macro implementation of this is in cpu.h which dereferences
193 *  the ** and a similarly named routine in this file is passed something
194 *  like a (Context_Control_fp *).  The general rule on making this decision
195 *  is to avoid writing assembly language.
196 */
197
198/* void _CPU_Context_save_fp(
199 *   void **fp_context_ptr
200 * );
201 */
202
203FRAME(_CPU_Context_save_fp,sp,0,ra)
204        .set noat
205        ld a1,(a0)
206        swc1 $f0,FP0_OFFSET*4(a1)
207        swc1 $f1,FP1_OFFSET*4(a1)
208        swc1 $f2,FP2_OFFSET*4(a1)
209        swc1 $f3,FP3_OFFSET*4(a1)
210        swc1 $f4,FP4_OFFSET*4(a1)
211        swc1 $f5,FP5_OFFSET*4(a1)
212        swc1 $f6,FP6_OFFSET*4(a1)
213        swc1 $f7,FP7_OFFSET*4(a1)
214        swc1 $f8,FP8_OFFSET*4(a1)
215        swc1 $f9,FP9_OFFSET*4(a1)
216        swc1 $f10,FP10_OFFSET*4(a1)
217        swc1 $f11,FP11_OFFSET*4(a1)
218        swc1 $f12,FP12_OFFSET*4(a1)
219        swc1 $f13,FP13_OFFSET*4(a1)
220        swc1 $f14,FP14_OFFSET*4(a1)
221        swc1 $f15,FP15_OFFSET*4(a1)
222        swc1 $f16,FP16_OFFSET*4(a1)
223        swc1 $f17,FP17_OFFSET*4(a1)
224        swc1 $f18,FP18_OFFSET*4(a1)
225        swc1 $f19,FP19_OFFSET*4(a1)
226        swc1 $f20,FP20_OFFSET*4(a1)
227        swc1 $f21,FP21_OFFSET*4(a1)
228        swc1 $f22,FP22_OFFSET*4(a1)
229        swc1 $f23,FP23_OFFSET*4(a1)
230        swc1 $f24,FP24_OFFSET*4(a1)
231        swc1 $f25,FP25_OFFSET*4(a1)
232        swc1 $f26,FP26_OFFSET*4(a1)
233        swc1 $f27,FP27_OFFSET*4(a1)
234        swc1 $f28,FP28_OFFSET*4(a1)
235        swc1 $f29,FP29_OFFSET*4(a1)
236        swc1 $f30,FP30_OFFSET*4(a1)
237        swc1 $f31,FP31_OFFSET*4(a1)
238        j ra
239        nop
240        .set at
241ENDFRAME(_CPU_Context_save_fp)
242
243/*
244 *  _CPU_Context_restore_fp_context
245 *
246 *  This routine is responsible for restoring the FP context
247 *  at *fp_context_ptr.  If the point to load the FP context
248 *  from is changed then the pointer is modified by this routine.
249 *
250 *  Sometimes a macro implementation of this is in cpu.h which dereferences
251 *  the ** and a similarly named routine in this file is passed something
252 *  like a (Context_Control_fp *).  The general rule on making this decision
253 *  is to avoid writing assembly language.
254 */
255
256/* void _CPU_Context_restore_fp(
257 *   void **fp_context_ptr
258 * )
259 */
260
261FRAME(_CPU_Context_restore_fp,sp,0,ra)
262        .set noat
263        ld a1,(a0)
264        lwc1 $f0,FP0_OFFSET*4(a1)
265        lwc1 $f1,FP1_OFFSET*4(a1)
266        lwc1 $f2,FP2_OFFSET*4(a1)
267        lwc1 $f3,FP3_OFFSET*4(a1)
268        lwc1 $f4,FP4_OFFSET*4(a1)
269        lwc1 $f5,FP5_OFFSET*4(a1)
270        lwc1 $f6,FP6_OFFSET*4(a1)
271        lwc1 $f7,FP7_OFFSET*4(a1)
272        lwc1 $f8,FP8_OFFSET*4(a1)
273        lwc1 $f9,FP9_OFFSET*4(a1)
274        lwc1 $f10,FP10_OFFSET*4(a1)
275        lwc1 $f11,FP11_OFFSET*4(a1)
276        lwc1 $f12,FP12_OFFSET*4(a1)
277        lwc1 $f13,FP13_OFFSET*4(a1)
278        lwc1 $f14,FP14_OFFSET*4(a1)
279        lwc1 $f15,FP15_OFFSET*4(a1)
280        lwc1 $f16,FP16_OFFSET*4(a1)
281        lwc1 $f17,FP17_OFFSET*4(a1)
282        lwc1 $f18,FP18_OFFSET*4(a1)
283        lwc1 $f19,FP19_OFFSET*4(a1)
284        lwc1 $f20,FP20_OFFSET*4(a1)
285        lwc1 $f21,FP21_OFFSET*4(a1)
286        lwc1 $f22,FP22_OFFSET*4(a1)
287        lwc1 $f23,FP23_OFFSET*4(a1)
288        lwc1 $f24,FP24_OFFSET*4(a1)
289        lwc1 $f25,FP25_OFFSET*4(a1)
290        lwc1 $f26,FP26_OFFSET*4(a1)
291        lwc1 $f27,FP27_OFFSET*4(a1)
292        lwc1 $f28,FP28_OFFSET*4(a1)
293        lwc1 $f29,FP29_OFFSET*4(a1)
294        lwc1 $f30,FP30_OFFSET*4(a1)
295        lwc1 $f31,FP31_OFFSET*4(a1)
296        j ra
297        nop
298        .set at
299ENDFRAME(_CPU_Context_restore_fp)
300
301/*  _CPU_Context_switch
302 *
303 *  This routine performs a normal non-FP context switch.
304 */
305
306/* void _CPU_Context_switch(
307 *   Context_Control  *run,
308 *   Context_Control  *heir
309 * )
310 */
311#if __mips == 3
312/* MIPS ISA Level 3 ( R4xxx ) */
313
314FRAME(_CPU_Context_switch,sp,0,ra)
315
316        mfc0 t0,C0_SR
317        li t1,~SR_IE
318        sd t0,C0_SR_OFFSET*8(a0)        /* save status register */
319        and t0,t1
320        mtc0 t0,C0_SR                   /* first disable ie bit (recommended) */
321        ori t0,SR_EXL|SR_IE             /* enable exception level to disable interrupts */
322        mtc0 t0,C0_SR
323
324        sd ra,RA_OFFSET*8(a0)           /* save current context */
325        sd sp,SP_OFFSET*8(a0)
326        sd fp,FP_OFFSET*8(a0)
327        sd s1,S1_OFFSET*8(a0)
328        sd s2,S2_OFFSET*8(a0)
329        sd s3,S3_OFFSET*8(a0)
330        sd s4,S4_OFFSET*8(a0)
331        sd s5,S5_OFFSET*8(a0)
332        sd s6,S6_OFFSET*8(a0)
333        sd s7,S7_OFFSET*8(a0)
334        dmfc0 t0,C0_EPC
335        sd t0,C0_EPC_OFFSET*8(a0)
336
337_CPU_Context_switch_restore:
338        ld s0,S0_OFFSET*8(a1)           /* restore context */
339        ld s1,S1_OFFSET*8(a1)
340        ld s2,S2_OFFSET*8(a1)
341        ld s3,S3_OFFSET*8(a1)
342        ld s4,S4_OFFSET*8(a1)
343        ld s5,S5_OFFSET*8(a1)
344        ld s6,S6_OFFSET*8(a1)
345        ld s7,S7_OFFSET*8(a1)
346        ld fp,FP_OFFSET*8(a1)
347        ld sp,SP_OFFSET*8(a1)
348        ld ra,RA_OFFSET*8(a1)
349        ld t0,C0_EPC_OFFSET*8(a1)
350        dmtc0 t0,C0_EPC
351        ld t0,C0_SR_OFFSET*8(a1)
352        andi t0,SR_EXL
353        bnez t0,_CPU_Context_1          /* set exception level from restore context */
354        li t0,~SR_EXL
355        mfc0 t1,C0_SR
356        nop
357        and t1,t0
358        mtc0 t1,C0_SR
359_CPU_Context_1:
360        j ra
361        nop
362ENDFRAME(_CPU_Context_switch)
363
364#elif __mips == 1
365/* MIPS ISA Level 1 ( R3000 ) */
366
367FRAME(_CPU_Context_switch,sp,0,ra)
368
369        mfc0 t0,C0_SR
370        li t1,~SR_IEC
371        sw t0,C0_SR_OFFSET*4(a0)        /* save status register */
372        and t0,t1
373        mtc0 t0,C0_SR                   /* first disable ie bit (recommended) */
374
375        sw ra,RA_OFFSET*4(a0)           /* save current context */
376        sw sp,SP_OFFSET*4(a0)
377        sw fp,FP_OFFSET*4(a0)
378        sw s0,S0_OFFSET*4(a0)
379        sw s1,S1_OFFSET*4(a0)
380        sw s2,S2_OFFSET*4(a0)
381        sw s3,S3_OFFSET*4(a0)
382        sw s4,S4_OFFSET*4(a0)
383        sw s5,S5_OFFSET*4(a0)
384        sw s6,S6_OFFSET*4(a0)
385        sw s7,S7_OFFSET*4(a0)
386
387        mfc0 t0,C0_EPC
388        sw t0,C0_EPC_OFFSET*4(a0)
389
390_CPU_Context_switch_restore:
391        lw s0,S0_OFFSET*4(a1)           /* restore context */
392        lw s1,S1_OFFSET*4(a1)
393        lw s2,S2_OFFSET*4(a1)
394        lw s3,S3_OFFSET*4(a1)
395        lw s4,S4_OFFSET*4(a1)
396        lw s5,S5_OFFSET*4(a1)
397        lw s6,S6_OFFSET*4(a1)
398        lw s7,S7_OFFSET*4(a1)
399        lw fp,FP_OFFSET*4(a1)
400        lw sp,SP_OFFSET*4(a1)
401        lw ra,RA_OFFSET*4(a1)
402        lw t0,C0_EPC_OFFSET*4(a1)
403        mtc0 t0,C0_EPC
404        lw t0, C0_SR_OFFSET*4(a1)
405        andi t0,SR_IEC                  /* we know IEC=0, e.g. disabled */
406        beq t0,$0,_CPU_Context_1        /* set IEC level from restore context */
407        mfc0 t0,C0_SR
408        nop
409        or  t0,SR_IEC                   /* new_sr = sr | SR_IEC */
410        mtc0 t0,C0_SR                   /* set with enabled */
411       
412
413_CPU_Context_1:
414        j ra
415        nop
416ENDFRAME(_CPU_Context_switch)
417
418#else
419
420   #error "__mips is not set to 1 or 3"
421
422#endif
423
424/*
425 *  _CPU_Context_restore
426 *
427 *  This routine is generally used only to restart self in an
428 *  efficient manner.  It may simply be a label in _CPU_Context_switch.
429 *
430 *  NOTE: May be unnecessary to reload some registers.
431 *
432 *  void _CPU_Context_restore(
433 *    Context_Control *new_context
434 *  );
435 */
436
437#if __mips == 3
438
439FRAME(_CPU_Context_restore,sp,0,ra)
440        dadd a1,a0,zero
441        j _CPU_Context_switch_restore
442        nop
443ENDFRAME(_CPU_Context_restore)
444
445#elif __mips == 1
446
447FRAME(_CPU_Context_restore,sp,0,ra)
448        add  a1,a0,zero
449        j _CPU_Context_switch_restore
450        nop
451ENDFRAME(_CPU_Context_restore)
452
453#else
454
455      #error "__mips is not set to 1 or 3"
456
457#endif
458
459EXTERN(_ISR_Nest_level, SZ_INT)
460EXTERN(_Thread_Dispatch_disable_level,SZ_INT)
461EXTERN(_Context_Switch_necessary,SZ_INT)
462EXTERN(_ISR_Signals_to_thread_executing,SZ_INT)
463.extern _Thread_Dispatch
464.extern _ISR_Vector_table
465
466/*  void __ISR_Handler()
467 *
468 *  This routine provides the RTEMS interrupt management.
469 *
470 *  void _ISR_Handler()
471 *
472 *
473 *  This discussion ignores a lot of the ugly details in a real
474 *  implementation such as saving enough registers/state to be
475 *  able to do something real.  Keep in mind that the goal is
476 *  to invoke a user's ISR handler which is written in C and
477 *  uses a certain set of registers.
478 *
479 *  Also note that the exact order is to a large extent flexible.
480 *  Hardware will dictate a sequence for a certain subset of
481 *  _ISR_Handler while requirements for setting
482 *
483 *  At entry to "common" _ISR_Handler, the vector number must be
484 *  available.  On some CPUs the hardware puts either the vector
485 *  number or the offset into the vector table for this ISR in a
486 *  known place.  If the hardware does not give us this information,
487 *  then the assembly portion of RTEMS for this port will contain
488 *  a set of distinct interrupt entry points which somehow place
489 *  the vector number in a known place (which is safe if another
490 *  interrupt nests this one) and branches to _ISR_Handler.
491 *
492 */
493
494#if __mips == 3
495/* ----------------------------------------------------------------------------- */
496FRAME(_ISR_Handler,sp,0,ra)
497.set noreorder
498#if USE_IDTKIT
499/* IDT/Kit incorrectly adds 4 to EPC before returning.  This compensates */
500        lreg    k0, R_EPC*R_SZ(sp)
501        daddiu    k0,k0,-4
502        sreg    k0, R_EPC*R_SZ(sp)
503        lreg    k0, R_CAUSE*R_SZ(sp)
504        li      k1, ~CAUSE_BD
505        and     k0, k1
506        sreg    k0, R_CAUSE*R_SZ(sp)
507#endif
508       
509/* save registers not already saved by IDT/sim */
510        stackadd sp,sp,-EXCP_STACK_SIZE /* store ra on the stack */
511
512        sreg    ra, R_RA*R_SZ(sp)
513        sreg    v0, R_V0*R_SZ(sp)
514        sreg    v1, R_V1*R_SZ(sp)
515        sreg    a0, R_A0*R_SZ(sp)
516        sreg    a1, R_A1*R_SZ(sp)
517        sreg    a2, R_A2*R_SZ(sp)
518        sreg    a3, R_A3*R_SZ(sp)
519        sreg    t0, R_T0*R_SZ(sp)
520        sreg    t1, R_T1*R_SZ(sp)
521        sreg    t2, R_T2*R_SZ(sp)
522        sreg    t3, R_T3*R_SZ(sp)
523        sreg    t4, R_T4*R_SZ(sp)
524        sreg    t5, R_T5*R_SZ(sp)
525        sreg    t6, R_T6*R_SZ(sp)
526        sreg    t7, R_T7*R_SZ(sp)
527        mflo    k0
528        sreg    t8, R_T8*R_SZ(sp)
529        sreg    k0, R_MDLO*R_SZ(sp)
530        sreg    t9, R_T9*R_SZ(sp)
531        mfhi    k0
532        sreg    gp, R_GP*R_SZ(sp)
533        sreg    fp, R_FP*R_SZ(sp)
534        sreg    k0, R_MDHI*R_SZ(sp)
535        .set noat
536        sreg    AT, R_AT*R_SZ(sp)
537        .set at
538
539        stackadd sp,sp,-40              /* store ra on the stack */
540        sd ra,32(sp)
541
542/* determine if an interrupt generated this exception */
543        mfc0 k0,C0_CAUSE
544        and k1,k0,CAUSE_EXCMASK
545        bnez k1,_ISR_Handler_prom_exit /* not an external interrupt,
546                                                pass exception to Monitor */
547        mfc0 k1,C0_SR
548        and k0,k1
549        and k0,CAUSE_IPMASK
550        beq k0,zero,_ISR_Handler_quick_exit /* external interrupt not
551                                                        enabled, ignore */
552        nop
553
554  /*
555   *  save some or all context on stack
556   *  may need to save some special interrupt information for exit
557   *
558   *  #if ( CPU_HAS_SOFTWARE_INTERRUPT_STACK == TRUE )
559   *    if ( _ISR_Nest_level == 0 )
560   *      switch to software interrupt stack
561   *  #endif
562   */
563#if ( CPU_HAS_SOFTWARE_INTERRUPT_STACK == TRUE )
564        lint t0,_ISR_Nest_level
565        beq t0, zero,  _ISR_Handler_1
566        nop
567        /* switch stacks */     
568_ISR_Handler_1:
569#else
570        lint t0,_ISR_Nest_level
571#endif
572  /*
573   *  _ISR_Nest_level++;
574   */
575        addi t0,t0,1
576        sint t0,_ISR_Nest_level
577  /*
578   *  _Thread_Dispatch_disable_level++;
579   */
580        lint t1,_Thread_Dispatch_disable_level
581        addi t1,t1,1
582        sint t1,_Thread_Dispatch_disable_level
583#if 0
584        nop
585        j _ISR_Handler_4
586        nop
587  /*
588   *  while ( interrupts_pending(cause_reg) ) {
589   *     vector = BITFIELD_TO_INDEX(cause_reg);
590   *     (*_ISR_Vector_table[ vector ])( vector );
591   *  }
592   */
593_ISR_Handler_2:
594/* software interrupt priorities can be applied here */
595        li t1,-1
596/* convert bit field into interrupt index */
597_ISR_Handler_3:
598        andi t2,t0,1
599        addi t1,1
600        beql t2,zero,_ISR_Handler_3
601        dsrl t0,1
602        li t1,7
603        dsll t1,3                       /* convert index to byte offset (*8) */
604        la t3,_ISR_Vector_table
605        intadd t1,t3
606        lint t1,(t1)
607        jalr t1
608        nop
609        j _ISR_Handler_5
610        nop
611_ISR_Handler_4:
612        mfc0 t0,C0_CAUSE
613        andi t0,CAUSE_IPMASK
614        bne t0,zero,_ISR_Handler_2
615        dsrl t0,t0,8
616_ISR_Handler_5:
617#else
618        nop
619        li t1,7
620        dsll t1,t1,SZ_INT_POW2
621        la t3,_ISR_Vector_table
622        intadd t1,t3
623        lint t1,(t1)
624        jalr t1
625        nop
626#endif
627  /*
628   *  --_ISR_Nest_level;
629   */
630        lint t2,_ISR_Nest_level
631        addi t2,t2,-1
632        sint t2,_ISR_Nest_level
633  /*
634   *  --_Thread_Dispatch_disable_level;
635   */
636        lint t1,_Thread_Dispatch_disable_level
637        addi t1,t1,-1
638        sint t1,_Thread_Dispatch_disable_level
639  /*
640   *  if ( _Thread_Dispatch_disable_level || _ISR_Nest_level )
641   *    goto the label "exit interrupt (simple case)"
642   */
643        or t0,t2,t1
644        bne t0,zero,_ISR_Handler_exit
645        nop
646  /*
647   *  #if ( CPU_HAS_SOFTWARE_INTERRUPT_STACK == TRUE )
648   *    restore stack
649   *  #endif
650   * 
651   *  if ( !_Context_Switch_necessary && !_ISR_Signals_to_thread_executing )
652   *    goto the label "exit interrupt (simple case)"
653   */
654        lint t0,_Context_Switch_necessary
655        lint t1,_ISR_Signals_to_thread_executing
656        or t0,t0,t1
657        beq t0,zero,_ISR_Handler_exit
658        nop
659
660  /*
661   *  call _Thread_Dispatch() or prepare to return to _ISR_Dispatch
662   */
663        jal _Thread_Dispatch
664        nop
665  /*
666   *  prepare to get out of interrupt
667   *  return from interrupt  (maybe to _ISR_Dispatch)
668   *
669   *  LABEL "exit interrupt (simple case):
670   *  prepare to get out of interrupt
671   *  return from interrupt
672   */
673_ISR_Handler_exit:
674        ld ra,32(sp)
675        stackadd sp,sp,40
676
677/* restore interrupt context from stack */
678        lreg    k0, R_MDLO*R_SZ(sp)
679        mtlo    k0
680        lreg    k0, R_MDHI*R_SZ(sp)
681        lreg    a2, R_A2*R_SZ(sp)
682        mthi    k0
683        lreg    a3, R_A3*R_SZ(sp)
684        lreg    t0, R_T0*R_SZ(sp)
685        lreg    t1, R_T1*R_SZ(sp)
686        lreg    t2, R_T2*R_SZ(sp)
687        lreg    t3, R_T3*R_SZ(sp)
688        lreg    t4, R_T4*R_SZ(sp)
689        lreg    t5, R_T5*R_SZ(sp)
690        lreg    t6, R_T6*R_SZ(sp)
691        lreg    t7, R_T7*R_SZ(sp)
692        lreg    t8, R_T8*R_SZ(sp)
693        lreg    t9, R_T9*R_SZ(sp)
694        lreg    gp, R_GP*R_SZ(sp)
695        lreg    fp, R_FP*R_SZ(sp)
696        lreg    ra, R_RA*R_SZ(sp)
697        lreg    a0, R_A0*R_SZ(sp)
698        lreg    a1, R_A1*R_SZ(sp)
699        lreg    v1, R_V1*R_SZ(sp)
700        lreg    v0, R_V0*R_SZ(sp)
701        .set noat
702        lreg    AT, R_AT*R_SZ(sp)
703        .set at
704
705        stackadd sp,sp,EXCP_STACK_SIZE /* store ra on the stack */
706
707#if USE_IDTKIT
708/* we handled exception, so return non-zero value */
709        li v0,1
710#endif
711
712_ISR_Handler_quick_exit:
713#ifdef USE_IDTKIT
714        j ra
715#else
716        eret
717#endif
718        nop
719
720_ISR_Handler_prom_exit:
721#if __mips == 1
722        la      k0, (R_VEC+((48)*8))
723#endif
724
725#if __mips == 3
726        la      k0, (R_VEC+((112)*8)) /* R4000 Sim's location is different */
727#endif
728        j       k0
729        nop
730
731       .set    reorder
732
733ENDFRAME(_ISR_Handler)
734
735/* ---------------------------------------------------------------------- */
736#elif __mips == 1
737/* MIPS ISA Level 1 */
738
739FRAME(_ISR_Handler,sp,0,ra)
740.set noreorder
741
742        /* Q: _ISR_Handler, not using IDT/SIM ...save extra regs? */
743
744        addiu sp,sp,-EXCP_STACK_SIZE       /* wastes alot of stack space for context?? */
745
746        sw    ra, R_RA*R_SZ(sp)  /* store ra on the stack */
747        sw    v0, R_V0*R_SZ(sp)
748        sw    v1, R_V1*R_SZ(sp)
749        sw    a0, R_A0*R_SZ(sp)
750        sw    a1, R_A1*R_SZ(sp)
751        sw    a2, R_A2*R_SZ(sp)
752        sw    a3, R_A3*R_SZ(sp)
753        sw    t0, R_T0*R_SZ(sp)
754        sw    t1, R_T1*R_SZ(sp)
755        sw    t2, R_T2*R_SZ(sp)
756        sw    t3, R_T3*R_SZ(sp)
757        sw    t4, R_T4*R_SZ(sp)
758        sw    t5, R_T5*R_SZ(sp)
759        sw    t6, R_T6*R_SZ(sp)
760        sw    t7, R_T7*R_SZ(sp)
761        mflo    k0
762        sw    t8, R_T8*R_SZ(sp)
763        sw    k0, R_MDLO*R_SZ(sp)
764        sw    t9, R_T9*R_SZ(sp)
765        mfhi    k0
766        sw    gp, R_GP*R_SZ(sp)
767        sw    fp, R_FP*R_SZ(sp)
768        sw    k0, R_MDHI*R_SZ(sp)
769        .set noat
770        sw    AT, R_AT*R_SZ(sp)
771        .set at
772
773        /* Q: Why hardcode -40 for stack add??? */
774        /* This needs to be figured out.........*/
775        addiu sp,sp,-40
776        sw ra,32(sp)    /* store ra on the stack */
777
778/* determine if an interrupt generated this exception */
779
780        mfc0 k0,C0_CAUSE
781        and k1,k0,CAUSE_EXCMASK
782        beq k1, 0, _ISR_Handler_1
783        nop
784
785_ISR_Handler_Exception:
786        nop
787        b  _ISR_Handler_Exception       /* Jump to the exception code */
788        nop
789
790_ISR_Handler_1:
791
792        mfc0 k1,C0_SR
793        and k0,k1
794        and k0,CAUSE_IPMASK
795        beq k0,zero,_ISR_Handler_exit
796                /* external interrupt not enabled, ignore */
797                /* but if it's not an exception or an interrupt, */
798                /* Then where did it come from??? */
799        nop
800
801  /*
802   *  save some or all context on stack
803   *  may need to save some special interrupt information for exit
804   *
805   *  #if ( CPU_HAS_SOFTWARE_INTERRUPT_STACK == TRUE )
806   *    if ( _ISR_Nest_level == 0 )
807   *      switch to software interrupt stack
808   *  #endif
809   */
810
811  /*
812   *  _ISR_Nest_level++;
813   */
814        lw   t0,_ISR_Nest_level
815        addi t0,t0,1
816        sw   t0,_ISR_Nest_level
817  /*
818   *  _Thread_Dispatch_disable_level++;
819   */
820        lw   t1,_Thread_Dispatch_disable_level
821        addi t1,t1,1
822        sw   t1,_Thread_Dispatch_disable_level
823
824  /*
825   *  Call the CPU model or BSP specific routine to decode the
826   *  interrupt source and actually vector to device ISR handlers.
827   */
828
829        jal     mips_vector_isr_handlers
830        nop
831
832  /*
833   *  --_ISR_Nest_level;
834   */
835        lw   t2,_ISR_Nest_level
836        addi t2,t2,-1
837        sw   t2,_ISR_Nest_level
838  /*
839   *  --_Thread_Dispatch_disable_level;
840   */
841        lw   t1,_Thread_Dispatch_disable_level
842        addi t1,t1,-1
843        sw   t1,_Thread_Dispatch_disable_level
844  /*
845   *  if ( _Thread_Dispatch_disable_level || _ISR_Nest_level )
846   *    goto the label "exit interrupt (simple case)"
847   */
848        or  t0,t2,t1
849        bne t0,zero,_ISR_Handler_exit
850        nop
851  /*
852   *  #if ( CPU_HAS_SOFTWARE_INTERRUPT_STACK == TRUE )
853   *    restore stack
854   *  #endif
855   * 
856   *  if ( !_Context_Switch_necessary && !_ISR_Signals_to_thread_executing )
857   *    goto the label "exit interrupt (simple case)"
858   */
859        lw  t0,_Context_Switch_necessary
860        lw  t1,_ISR_Signals_to_thread_executing
861        or  t0,t0,t1
862        beq t0,zero,_ISR_Handler_exit
863        nop
864  /*
865   *  call _Thread_Dispatch() or prepare to return to _ISR_Dispatch
866   */
867        jal _Thread_Dispatch
868        nop
869  /*
870   *  prepare to get out of interrupt
871   *  return from interrupt  (maybe to _ISR_Dispatch)
872   *
873   *  LABEL "exit interrupt (simple case):
874   *  prepare to get out of interrupt
875   *  return from interrupt
876   */
877
878_ISR_Handler_exit:
879        ld ra,32(sp)
880        addiu sp,sp,40    /* Q: Again with the 40...Is this needed? */
881
882/* restore interrupt context from stack */
883     
884        lw    k0, R_MDLO*R_SZ(sp)           
885        mtlo  k0
886        lw    k0, R_MDHI*R_SZ(sp)           
887        lw    a2, R_A2*R_SZ(sp)
888        mthi  k0
889        lw    a3, R_A3*R_SZ(sp)
890        lw    t0, R_T0*R_SZ(sp)
891        lw    t1, R_T1*R_SZ(sp)
892        lw    t2, R_T2*R_SZ(sp)
893        lw    t3, R_T3*R_SZ(sp)
894        lw    t4, R_T4*R_SZ(sp)
895        lw    t5, R_T5*R_SZ(sp)
896        lw    t6, R_T6*R_SZ(sp)
897        lw    t7, R_T7*R_SZ(sp)
898        lw    t8, R_T8*R_SZ(sp)
899        lw    t9, R_T9*R_SZ(sp)
900        lw    gp, R_GP*R_SZ(sp)
901        lw    fp, R_FP*R_SZ(sp)
902        lw    ra, R_RA*R_SZ(sp)
903        lw    a0, R_A0*R_SZ(sp)
904        lw    a1, R_A1*R_SZ(sp)
905        lw    v1, R_V1*R_SZ(sp)
906        lw    v0, R_V0*R_SZ(sp)
907        .set noat
908        lw    AT, R_AT*R_SZ(sp)
909        .set at
910
911        addiu sp,sp,EXCP_STACK_SIZE
912
913        mfc0    k0, C0_EPC
914       
915        rfe  /* Might not need to do RFE here... */
916        j k0
917        nop
918
919       .set    reorder
920ENDFRAME(_ISR_Handler)
921
922#else
923
924   #error "__mips is not set to 1 or 3 "
925
926#endif
927
928FRAME(mips_break,sp,0,ra)
929#if 1
930        break 0x0
931        j mips_break
932#else
933        j ra
934#endif
935        nop
936ENDFRAME(mips_break)
937
Note: See TracBrowser for help on using the repository browser.