source: rtems/c/src/lib/libbsp/mips/shared/irq/exception.S @ 0b91d327

4.104.115
Last change on this file since 0b91d327 was 0b91d327, checked in by Joel Sherrill <joel.sherrill@…>, on 05/13/10 at 18:08:38

2010-05-13 Joel Sherrill <joel.sherrill@…>

  • shared/irq/exception.S: New file.
  • Property mode set to 100644
File size: 14.8 KB
Line 
1/*  exception.S
2 *
3 *  This file contains a customized MIPS exception handler.
4 *  It hooks into the exception handler present in the resident
5 *  PMON debug monitor.
6 *
7 *  Author: Bruce Robinson
8 *
9 *  This code was derived from cpu_asm.S with the following copyright:
10 *
11 *  COPYRIGHT (c) 1996 by Transition Networks Inc.
12 *
13 *  To anyone who acknowledges that this file is provided "AS IS"
14 *  without any express or implied warranty:
15 *      permission to use, copy, modify, and distribute this file
16 *      for any purpose is hereby granted without fee, provided that
17 *      the above copyright notice and this notice appears in all
18 *      copies, and that the name of Transition Networks not be used in
19 *      advertising or publicity pertaining to distribution of the
20 *      software without specific, written prior permission.
21 *      Transition Networks makes no representations about the suitability
22 *      of this software for any purpose.
23 *
24 *  Derived from c/src/exec/score/cpu/no_cpu/cpu_asm.s:
25 *
26 *  COPYRIGHT (c) 1989-1999.
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.rtems.com/license/LICENSE.
32 *
33 *  $Id$
34 */
35/* @(#)exception.S       7/27/04     1.00 */
36
37#include <rtems/mips/iregdef.h>
38#include <rtems/mips/idtcpu.h>
39
40
41#define FRAME(name,frm_reg,offset,ret_reg)      \
42        .globl  name;                           \
43        .ent    name;                           \
44name:;                                          \
45        .frame  frm_reg,offset,ret_reg
46#define ENDFRAME(name)                          \
47        .end name
48
49
50#if __mips == 3
51/* 64 bit register operations */
52#define NOP     nop
53#define ADD     dadd
54#define STREG   sd
55#define LDREG   ld
56#define ADDU    addu
57#define ADDIU   addiu
58#define STREGC1 sdc1
59#define LDREGC1 ldc1
60#define R_SZ    8
61#define F_SZ    8
62#define SZ_INT  8
63#define SZ_INT_POW2 3
64
65/* XXX if we don't always want 64 bit register ops, then another ifdef */
66
67#elif __mips == 1
68/* 32 bit register operations*/
69#define NOP     nop
70#define ADD     add
71#define STREG   sw
72#define LDREG   lw
73#define ADDU    add
74#define ADDIU   addi
75#define STREGC1 swc1
76#define LDREGC1 lwc1
77#define R_SZ    4
78#define F_SZ    4
79#define SZ_INT  4
80#define SZ_INT_POW2 2
81#else
82#error "mips assembly: what size registers do I deal with?"
83#endif
84
85
86#define ISR_VEC_SIZE    4
87#define EXCP_STACK_SIZE (NREGS*R_SZ)
88
89
90#ifdef __GNUC__
91#define EXTERN(x,size) .extern x,size
92#else
93#define EXTERN(x,size)
94#endif
95
96
97EXTERN(_ISR_Nest_level, 4)
98EXTERN(_Thread_Dispatch_disable_level,4)
99EXTERN(_Context_Switch_necessary,1)
100EXTERN(_ISR_Signals_to_thread_executing,1)
101.extern _Thread_Dispatch
102.extern _ISR_Vector_table
103
104/*  void __ISR_Handler()
105 *
106 *  This routine provides the RTEMS interrupt management.
107 *
108 */
109
110#if 0
111void _ISR_Handler()
112{
113   /*
114    *  This discussion ignores a lot of the ugly details in a real
115    *  implementation such as saving enough registers/state to be
116    *  able to do something real.  Keep in mind that the goal is
117    *  to invoke a user's ISR handler which is written in C and
118    *  uses a certain set of registers.
119    *
120    *  Also note that the exact order is to a large extent flexible.
121    *  Hardware will dictate a sequence for a certain subset of
122    *  _ISR_Handler while requirements for setting
123    */
124
125  /*
126   *  At entry to "common" _ISR_Handler, the vector number must be
127   *  available.  On some CPUs the hardware puts either the vector
128   *  number or the offset into the vector table for this ISR in a
129   *  known place.  If the hardware does not give us this information,
130   *  then the assembly portion of RTEMS for this port will contain
131   *  a set of distinct interrupt entry points which somehow place
132   *  the vector number in a known place (which is safe if another
133   *  interrupt nests this one) and branches to _ISR_Handler.
134   *
135   */
136#endif
137FRAME(bsp_ISR_Handler,sp,0,ra)
138        .set noreorder
139
140#if 0
141/* Activate TX49xx PIO19 signal for diagnostics */
142        lui     k0,0xff1f
143        ori     k0,k0,0xf500
144        lw      k0,(k0)
145        lui     k1,0x8
146        or      k1,k1,k0
147        lui     k0,0xff1f
148        ori     k0,k0,0xf500
149        sw      k1,(k0)
150#endif
151
152        mfc0 k0,C0_CAUSE        /* Determine if an interrupt generated this exception */
153        nop
154        and k1,k0,CAUSE_EXCMASK
155        beq k1,zero,_chk_int    /* If so, branch to service here */
156        nop
157        la  k0,_int_esr_link    /* Otherwise, jump to next exception handler in PMON exception chain */
158        lw  k0,(k0)
159        lw  k0,4(k0)
160        j   k0
161        nop
162_chk_int:
163        mfc0 k1,C0_SR
164        nop
165        and k0,k1
166        and k0,(SR_IBIT1 | SR_IBIT2 | SR_IBIT3)
167        beq k0,zero,_ISR_Handler_quick_exit /* external interrupt not enabled, ignore */
168        nop
169
170/* For debugging interrupts, clear EXL to allow breakpoints */
171#if 0
172        MFC0    k0, C0_SR
173#if __mips == 3
174        li      k1,SR_EXL       /* Clear EXL and Set IE to enable interrupts */
175        not     k1
176        and     k0,k1
177        li      k1,SR_IE
178#elif __mips == 1
179        li      k1,SR_IEC
180#endif
181        or      k0, k1
182        mtc0    k0, C0_SR
183        NOP
184#endif
185
186
187  /*
188   *  save some or all context on stack
189   *  may need to save some special interrupt information for exit
190   */
191
192        /* Q: _ISR_Handler, not using IDT/SIM ...save extra regs? */
193
194        /* wastes a lot of stack space for context?? */
195        ADDIU    sp,sp,-EXCP_STACK_SIZE
196
197        STREG ra, R_RA*R_SZ(sp)  /* store ra on the stack */
198        STREG v0, R_V0*R_SZ(sp)
199        STREG v1, R_V1*R_SZ(sp)
200        STREG a0, R_A0*R_SZ(sp)
201        STREG a1, R_A1*R_SZ(sp)
202        STREG a2, R_A2*R_SZ(sp)
203        STREG a3, R_A3*R_SZ(sp)
204        STREG t0, R_T0*R_SZ(sp)
205        STREG t1, R_T1*R_SZ(sp)
206        STREG t2, R_T2*R_SZ(sp)
207        STREG t3, R_T3*R_SZ(sp)
208        STREG t4, R_T4*R_SZ(sp)
209        STREG t5, R_T5*R_SZ(sp)
210        STREG t6, R_T6*R_SZ(sp)
211        STREG t7, R_T7*R_SZ(sp)
212        mflo  t0
213        STREG t8, R_T8*R_SZ(sp)
214        STREG t0, R_MDLO*R_SZ(sp)
215        STREG t9, R_T9*R_SZ(sp)
216        mfhi  t0
217        STREG gp, R_GP*R_SZ(sp)
218        STREG t0, R_MDHI*R_SZ(sp)
219        STREG fp, R_FP*R_SZ(sp)
220
221        .set noat
222        STREG AT, R_AT*R_SZ(sp)
223        .set at
224
225        mfc0     t0,C0_SR
226        dmfc0    t1,C0_EPC
227        STREG    t0,R_SR*R_SZ(sp)
228        STREG    t1,R_EPC*R_SZ(sp)
229
230  /*
231   *
232   *  #if ( CPU_HAS_SOFTWARE_INTERRUPT_STACK == TRUE )
233   *    if ( _ISR_Nest_level == 0 )
234   *      switch to software interrupt stack
235   *  #endif
236   */
237
238  /*
239   *  _ISR_Nest_level++;
240   */
241        lw      t0,_ISR_Nest_level
242        NOP
243        add     t0,t0,1
244        sw      t0,_ISR_Nest_level
245  /*
246   *  _Thread_Dispatch_disable_level++;
247   */
248        lw      t1,_Thread_Dispatch_disable_level
249        NOP
250        add     t1,t1,1
251        sw      t1,_Thread_Dispatch_disable_level
252
253
254        /* DEBUG - Add the following code to disable interrupts and clear EXL in status register, this will
255                allow memory exceptions to occur while servicing the current interrupt */
256#if 0
257        li t0,~CAUSE_IP2_MASK   /* Disable interrupts from internal interrupt controller */
258        mfc0 t1,C0_SR
259        nop
260        and t1,t0
261        mtc0 t1,C0_SR
262        nop
263        li t0,~SR_EXL           /* Clear EXL in status register to allow memory exceptions to occur */
264        mfc0 t1,C0_SR
265        nop
266        and t1,t0
267        mtc0 t1,C0_SR
268        nop
269#endif
270
271  /*
272   *  Call the CPU model or BSP specific routine to decode the
273   *  interrupt source and actually vector to device ISR handlers.
274   */
275        move     a0,sp
276        jal      mips_vector_isr_handlers
277        NOP
278
279        /* Add the following code to disable interrupts (see DEBUG above) */
280#if 0
281        li t0,SR_EXL            /* Set EXL to hold off interrupts */
282        mfc0 t1,C0_SR
283        nop
284        or t1,t0
285        mtc0 t1,C0_SR
286        nop
287        li t0,CAUSE_IP2_MASK    /* Enable interrupts from internal interrupt controller */
288        mfc0 t1,C0_SR
289        nop
290        or t1,t0
291        mtc0 t1,C0_SR
292        nop
293#endif
294
295_ISR_Handler_cleanup:
296
297  /*
298   *  --_ISR_Nest_level;
299   */
300        lw      t2,_ISR_Nest_level
301        NOP
302        add     t2,t2,-1
303        sw      t2,_ISR_Nest_level
304  /*
305   *  --_Thread_Dispatch_disable_level;
306   */
307        lw      t1,_Thread_Dispatch_disable_level
308        NOP
309        add     t1,t1,-1
310        sw      t1,_Thread_Dispatch_disable_level
311  /*
312   *  if ( _Thread_Dispatch_disable_level || _ISR_Nest_level )
313   *    goto the label "exit interrupt (simple case)"
314   */
315        or  t0,t2,t1
316        bne t0,zero,_ISR_Handler_exit
317        NOP
318
319
320  /*
321   *  #if ( CPU_HAS_SOFTWARE_INTERRUPT_STACK == TRUE )
322   *    restore stack
323   *  #endif
324   *
325   *  if ( !_Context_Switch_necessary && !_ISR_Signals_to_thread_executing )
326   *    goto the label "exit interrupt (simple case)"
327   */
328        lb      t0,_Context_Switch_necessary
329        lb      t1,_ISR_Signals_to_thread_executing
330        NOP
331        or      t0,t0,t1
332        beq     t0,zero,_ISR_Handler_exit
333        NOP
334
335/*
336** Turn on interrupts before entering Thread_Dispatch which
337** will run for a while, thus allowing new interrupts to
338** be serviced.  Observe the Thread_Dispatch_disable_level interlock
339** that prevents recursive entry into Thread_Dispatch.
340*/
341
342        mfc0    t0, C0_SR
343#if __mips == 3
344        li      t1,SR_EXL       /* Clear EXL and Set IE to enable interrupts */
345        not     t1
346        and     t0,t1
347        li      t1,SR_IE
348#elif __mips == 1
349        li      t1,SR_IEC
350#endif
351        or      t0, t1
352        mtc0    t0, C0_SR
353        NOP
354
355        /* save off our stack frame so the context switcher can get to it */
356        la      t0,__exceptionStackFrame
357        STREG   sp,(t0)
358
359        jal     _Thread_Dispatch
360        NOP
361
362        /* and make sure its clear in case we didn't dispatch.  if we did, its
363        ** already cleared */
364        la      t0,__exceptionStackFrame
365        STREG   zero,(t0)
366        NOP
367
368/*
369** turn interrupts back off while we restore context so
370** a badly timed interrupt won't accidentally mess things up
371*/
372        mfc0    t0, C0_SR
373#if __mips == 3
374        li      t1,SR_IE                /* Clear IE first (recommended) */
375        not     t1
376        and     t0,t1
377        mtc0    t0, C0_SR
378        li      t1,SR_EXL | SR_IE       /* Set EXL and IE, this puts status register bits back to interrupted state */
379        or      t0,t1
380#elif __mips == 1
381        /* ints off, current & prev kernel mode on (kernel mode enabled is bit clear..argh!) */
382        li      t1,SR_IEC | SR_KUP | SR_KUC
383        not     t1
384        and     t0, t1
385#endif
386        mtc0    t0, C0_SR
387        NOP
388
389
390  /*
391   *  prepare to get out of interrupt
392   *  return from interrupt  (maybe to _ISR_Dispatch)
393   *
394   *  LABEL "exit interrupt (simple case):"
395   *  prepare to get out of interrupt
396   *  return from interrupt
397   */
398
399_ISR_Handler_exit:
400
401/* restore interrupt context from stack */
402        LDREG t8, R_MDLO*R_SZ(sp)
403        LDREG t0, R_T0*R_SZ(sp)
404        mtlo  t8
405        LDREG t8, R_MDHI*R_SZ(sp)
406        LDREG t1, R_T1*R_SZ(sp)
407        mthi  t8
408        LDREG t2, R_T2*R_SZ(sp)
409        LDREG t3, R_T3*R_SZ(sp)
410        LDREG t4, R_T4*R_SZ(sp)
411        LDREG t5, R_T5*R_SZ(sp)
412        LDREG t6, R_T6*R_SZ(sp)
413        LDREG t7, R_T7*R_SZ(sp)
414        LDREG t8, R_T8*R_SZ(sp)
415        LDREG t9, R_T9*R_SZ(sp)
416        LDREG gp, R_GP*R_SZ(sp)
417        LDREG fp, R_FP*R_SZ(sp)
418        LDREG ra, R_RA*R_SZ(sp)
419        LDREG a0, R_A0*R_SZ(sp)
420        LDREG a1, R_A1*R_SZ(sp)
421        LDREG a2, R_A2*R_SZ(sp)
422        LDREG a3, R_A3*R_SZ(sp)
423        LDREG v1, R_V1*R_SZ(sp)
424        LDREG v0, R_V0*R_SZ(sp)
425
426        LDREG k1, R_EPC*R_SZ(sp)
427        mtc0  k1,C0_EPC
428
429        .set noat
430        LDREG     AT, R_AT*R_SZ(sp)
431        .set at
432
433        ADDIU     sp,sp,EXCP_STACK_SIZE
434
435_ISR_Handler_quick_exit:
436        eret
437        nop
438
439
440#if 0
441        .global int7_isr
442        .extern Interrupt_7_isr
443int7_isr:
444        /* Verify interrupt is from Timer */
445        la      k0,IRCS         /* read Interrupt Current Status register */
446        lw      k0,(k0)
447        nop                     /* reading from external device */
448        li      k1,IRCS_CAUSE_MASK
449        and     k0,k0,k1        /* isolate interrupt cause  */
450
451        li      k1,INT7INT      /* test for interrupt 7 */
452        subu    k1,k0,k1
453        beq     k1,zero,int7_isr1
454        nop
455        j       ra              /* interrupt 7 no longer valid, return without doing anything */
456        nop
457int7_isr1:
458        j       Interrupt_7_isr /* Jump to Interrupt 7 isr */
459        nop
460#endif
461
462       .set    reorder
463
464ENDFRAME(bsp_ISR_Handler)
465
466
467FRAME(_BRK_Handler,sp,0,ra)
468        .set noreorder
469
470#ifdef USC
471        la      k0,INT_CFG3     /* Disable heartbeat interrupt in USC320, it interferes with PMON exception handler */
472        lw      k1,(k0)
473        li      k0,~HBI_MASK
474        and     k1,k1,k0
475        la      k0,INT_CFG3
476        sw      k1,(k0)
477#endif
478
479        la  k0,_brk_esr_link    /* Jump to next exception handler in PMON exception chain */
480        lw  k0,(k0)
481        lw  k0,4(k0)
482        j   k0
483        nop
484
485        .set reorder
486ENDFRAME(_BRK_Handler)
487
488
489/**************************************************************************
490**
491**      init_exc_vecs() - moves the exception code into the addresses
492**                        reserved for exception vectors
493**
494**      UTLB Miss exception vector at address 0x80000000
495**
496**      General exception vector at address 0x80000080
497**
498**      RESET exception vector is at address 0xbfc00000
499**
500***************************************************************************/
501
502FRAME(init_exc_vecs,sp,0,ra)
503        .set noreorder
504
505        .extern mon_onintr
506
507/* Install interrupt handler in PMON exception handling chain */
508
509        addiu   sp,sp,-8
510        sw      ra,(sp)                 /* Save ra contents on stack */
511        move    a0,zero
512        la      a1,_int_esr_link
513        jal     mon_onintr              /* Make PMON system call to install interrupt exception handler */
514        nop
515        li      a0,9
516        la      a1,_brk_esr_link
517        jal     mon_onintr              /* Make PMON system call to install break exception handler */
518        nop
519        lw      ra,(sp)
520        addiu   sp,sp,8                 /* Restore ra contents from stack */
521        j       ra
522        nop
523
524        .set reorder
525ENDFRAME(init_exc_vecs)
526
527
528#if 0           /* Unused code below */
529
530/*************************************************************
531*  enable_int7(ints)
532*       Enable interrupt 7
533*/
534FRAME(enable_int7,sp,0,ra)
535        .set noreorder
536
537        la      t0,IRDM1        # Set interrupt controller detection mode (bits 2-3 = 0 for int 7 active low)
538        li      t1,0x0
539        sw      t1,(t0)
540
541        la      t0,IRLVL4       # Set interrupt controller level (bit 8-10 = 2 for int 7 at level 2)
542        li      t1,0x200
543        sw      t1,(t0)
544
545        la      t0,IRMSK        # Set interrupt controller mask
546        li      t1,0x0
547        sw      t1,(t0)
548
549        la      t0,IRDEN        # Enable interrupts from controller
550        li      t1,0x1
551        sw      t1,(t0)
552
553        j       ra
554        nop
555        .set reorder
556ENDFRAME(enable_int7)
557
558/*************************************************************
559*  disable_int7(ints)
560*       Disable interrupt 7
561*/
562FRAME(disable_int7,sp,0,ra)
563        .set noreorder
564
565        la      t0,IRLVL4       # Set interrupt controller level (bit 8-10 = 0 to diasble int 7)
566        li      t1,0x200
567        sw      t1,(t0)
568
569        j       ra
570        nop
571        .set reorder
572ENDFRAME(disable_int7)
573#endif
574
575/*************************************************************
576*  exception:
577*       Diagnostic code that can be hooked to PMON interrupt handler.
578*       Generates pulse on PIO22 pin.
579*       Called from _exception code in PMON (see mips.s of PMON).
580*       Return address is located in k1.
581*/
582FRAME(tx49xxexception,sp,0,ra)
583        .set noreorder
584        la      k0,k1tmp
585        sw      k1,(k0)
586
587/* Activate TX49xx PIO22 signal for diagnostics */
588        lui     k0,0xff1f
589        ori     k0,k0,0xf500
590        lw      k0,(k0)
591        lui     k1,0x40
592        or      k1,k1,k0
593        lui     k0,0xff1f
594        ori     k0,k0,0xf500
595        sw      k1,(k0)
596        nop
597
598/* De-activate TX49xx PIO22 signal for diagnostics */
599        lui     k0,0xff1f
600        ori     k0,k0,0xf500
601        lw      k0,(k0)
602        lui     k1,0x40
603        not     k1
604        and     k1,k1,k0
605        lui     k0,0xff1f
606        ori     k0,k0,0xf500
607        sw      k1,(k0)
608        nop
609
610        la      k0,k1tmp
611        lw      k1,(k0)
612        j       k1
613        .set reorder
614ENDFRAME(tx49xxexception)
615
616
617
618
619        .data
620
621k1tmp:  .word   0       /* Temporary strage for K1 during interrupt service */
622
623/*************************************************************
624*
625* Exception handler links, used in PMON exception handler chains
626*/
627        /* Interrupt exception service routine link */
628        .global _int_esr_link
629_int_esr_link:
630        .word   0
631        .word   bsp_ISR_Handler
632
633        /* Break exception service routine link */
634        .global _brk_esr_link
635_brk_esr_link:
636        .word   0
637        .word   _BRK_Handler
638
639
640
641
Note: See TracBrowser for help on using the repository browser.