source: rtems/c/src/lib/libbsp/mips/rbtx4925/startup/exception.S @ efdfd48

4.104.115
Last change on this file since efdfd48 was efdfd48, checked in by Ralf Corsepius <ralf.corsepius@…>, on 11/29/09 at 15:27:07

Whitespace removal.

  • Property mode set to 100644
File size: 14.6 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(rbtx4925_ISR_Handler,sp,0,ra)
138        .set noreorder
139
140#if 0
141/* Activate TX4925 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        li      k1,SR_EXL       /* Clear EXL and Set IE to enable interrupts */
174        not     k1
175        and     k0,k1
176        li      k1,SR_IE
177        or      k0, k1
178        mtc0    k0, C0_SR
179        NOP
180#endif
181
182
183  /*
184   *  save some or all context on stack
185   *  may need to save some special interrupt information for exit
186   */
187
188        /* Q: _ISR_Handler, not using IDT/SIM ...save extra regs? */
189
190        /* wastes a lot of stack space for context?? */
191        ADDIU    sp,sp,-EXCP_STACK_SIZE
192
193        STREG ra, R_RA*R_SZ(sp)  /* store ra on the stack */
194        STREG v0, R_V0*R_SZ(sp)
195        STREG v1, R_V1*R_SZ(sp)
196        STREG a0, R_A0*R_SZ(sp)
197        STREG a1, R_A1*R_SZ(sp)
198        STREG a2, R_A2*R_SZ(sp)
199        STREG a3, R_A3*R_SZ(sp)
200        STREG t0, R_T0*R_SZ(sp)
201        STREG t1, R_T1*R_SZ(sp)
202        STREG t2, R_T2*R_SZ(sp)
203        STREG t3, R_T3*R_SZ(sp)
204        STREG t4, R_T4*R_SZ(sp)
205        STREG t5, R_T5*R_SZ(sp)
206        STREG t6, R_T6*R_SZ(sp)
207        STREG t7, R_T7*R_SZ(sp)
208        mflo  t0
209        STREG t8, R_T8*R_SZ(sp)
210        STREG t0, R_MDLO*R_SZ(sp)
211        STREG t9, R_T9*R_SZ(sp)
212        mfhi  t0
213        STREG gp, R_GP*R_SZ(sp)
214        STREG t0, R_MDHI*R_SZ(sp)
215        STREG fp, R_FP*R_SZ(sp)
216
217        .set noat
218        STREG AT, R_AT*R_SZ(sp)
219        .set at
220
221        mfc0     t0,C0_SR
222        dmfc0    t1,C0_EPC
223        STREG    t0,R_SR*R_SZ(sp)
224        STREG    t1,R_EPC*R_SZ(sp)
225
226  /*
227   *
228   *  #if ( CPU_HAS_SOFTWARE_INTERRUPT_STACK == TRUE )
229   *    if ( _ISR_Nest_level == 0 )
230   *      switch to software interrupt stack
231   *  #endif
232   */
233
234  /*
235   *  _ISR_Nest_level++;
236   */
237        lw      t0,_ISR_Nest_level
238        NOP
239        add     t0,t0,1
240        sw      t0,_ISR_Nest_level
241  /*
242   *  _Thread_Dispatch_disable_level++;
243   */
244        lw      t1,_Thread_Dispatch_disable_level
245        NOP
246        add     t1,t1,1
247        sw      t1,_Thread_Dispatch_disable_level
248
249
250        /* DEBUG - Add the following code to disable interrupts and clear EXL in status register, this will
251                allow memory exceptions to occur while servicing the current interrupt */
252#if 0
253        li t0,~CAUSE_IP2_MASK   /* Disable interrupts from internal interrupt controller */
254        mfc0 t1,C0_SR
255        nop
256        and t1,t0
257        mtc0 t1,C0_SR
258        nop
259        li t0,~SR_EXL           /* Clear EXL in status register to allow memory exceptions to occur */
260        mfc0 t1,C0_SR
261        nop
262        and t1,t0
263        mtc0 t1,C0_SR
264        nop
265#endif
266
267  /*
268   *  Call the CPU model or BSP specific routine to decode the
269   *  interrupt source and actually vector to device ISR handlers.
270   */
271        move     a0,sp
272        jal      mips_vector_isr_handlers
273        NOP
274
275        /* Add the following code to disable interrupts (see DEBUG above) */
276#if 0
277        li t0,SR_EXL            /* Set EXL to hold off interrupts */
278        mfc0 t1,C0_SR
279        nop
280        or t1,t0
281        mtc0 t1,C0_SR
282        nop
283        li t0,CAUSE_IP2_MASK    /* Enable interrupts from internal interrupt controller */
284        mfc0 t1,C0_SR
285        nop
286        or t1,t0
287        mtc0 t1,C0_SR
288        nop
289#endif
290
291_ISR_Handler_cleanup:
292
293  /*
294   *  --_ISR_Nest_level;
295   */
296        lw      t2,_ISR_Nest_level
297        NOP
298        add     t2,t2,-1
299        sw      t2,_ISR_Nest_level
300  /*
301   *  --_Thread_Dispatch_disable_level;
302   */
303        lw      t1,_Thread_Dispatch_disable_level
304        NOP
305        add     t1,t1,-1
306        sw      t1,_Thread_Dispatch_disable_level
307  /*
308   *  if ( _Thread_Dispatch_disable_level || _ISR_Nest_level )
309   *    goto the label "exit interrupt (simple case)"
310   */
311        or  t0,t2,t1
312        bne t0,zero,_ISR_Handler_exit
313        NOP
314
315
316  /*
317   *  #if ( CPU_HAS_SOFTWARE_INTERRUPT_STACK == TRUE )
318   *    restore stack
319   *  #endif
320   *
321   *  if ( !_Context_Switch_necessary && !_ISR_Signals_to_thread_executing )
322   *    goto the label "exit interrupt (simple case)"
323   */
324        lb      t0,_Context_Switch_necessary
325        lb      t1,_ISR_Signals_to_thread_executing
326        NOP
327        or      t0,t0,t1
328        beq     t0,zero,_ISR_Handler_exit
329        NOP
330
331/*
332** Turn on interrupts before entering Thread_Dispatch which
333** will run for a while, thus allowing new interrupts to
334** be serviced.  Observe the Thread_Dispatch_disable_level interlock
335** that prevents recursive entry into Thread_Dispatch.
336*/
337
338        mfc0    t0, C0_SR
339#if __mips == 3
340        li      t1,SR_EXL       /* Clear EXL and Set IE to enable interrupts */
341        not     t1
342        and     t0,t1
343        li      t1,SR_IE
344#elif __mips == 1
345        li      t1,SR_IEC
346#endif
347        or      t0, t1
348        mtc0    t0, C0_SR
349        NOP
350
351        /* save off our stack frame so the context switcher can get to it */
352        la      t0,__exceptionStackFrame
353        STREG   sp,(t0)
354
355        jal     _Thread_Dispatch
356        NOP
357
358        /* and make sure its clear in case we didn't dispatch.  if we did, its
359        ** already cleared */
360        la      t0,__exceptionStackFrame
361        STREG   zero,(t0)
362        NOP
363
364/*
365** turn interrupts back off while we restore context so
366** a badly timed interrupt won't accidentally mess things up
367*/
368        mfc0    t0, C0_SR
369        li      t1,SR_IE                /* Clear IE first (recommended) */
370        not     t1
371        and     t0,t1
372        mtc0    t0, C0_SR
373        li      t1,SR_EXL | SR_IE       /* Set EXL and IE, this puts status register bits back to interrupted state */
374        or      t0,t1
375
376        mtc0    t0, C0_SR
377        NOP
378
379  /*
380   *  prepare to get out of interrupt
381   *  return from interrupt  (maybe to _ISR_Dispatch)
382   *
383   *  LABEL "exit interrupt (simple case):"
384   *  prepare to get out of interrupt
385   *  return from interrupt
386   */
387
388_ISR_Handler_exit:
389
390/* restore interrupt context from stack */
391        LDREG t8, R_MDLO*R_SZ(sp)
392        LDREG t0, R_T0*R_SZ(sp)
393        mtlo  t8
394        LDREG t8, R_MDHI*R_SZ(sp)
395        LDREG t1, R_T1*R_SZ(sp)
396        mthi  t8
397        LDREG t2, R_T2*R_SZ(sp)
398        LDREG t3, R_T3*R_SZ(sp)
399        LDREG t4, R_T4*R_SZ(sp)
400        LDREG t5, R_T5*R_SZ(sp)
401        LDREG t6, R_T6*R_SZ(sp)
402        LDREG t7, R_T7*R_SZ(sp)
403        LDREG t8, R_T8*R_SZ(sp)
404        LDREG t9, R_T9*R_SZ(sp)
405        LDREG gp, R_GP*R_SZ(sp)
406        LDREG fp, R_FP*R_SZ(sp)
407        LDREG ra, R_RA*R_SZ(sp)
408        LDREG a0, R_A0*R_SZ(sp)
409        LDREG a1, R_A1*R_SZ(sp)
410        LDREG a2, R_A2*R_SZ(sp)
411        LDREG a3, R_A3*R_SZ(sp)
412        LDREG v1, R_V1*R_SZ(sp)
413        LDREG v0, R_V0*R_SZ(sp)
414
415        LDREG k1, R_EPC*R_SZ(sp)
416        mtc0  k1,C0_EPC
417
418        .set noat
419        LDREG     AT, R_AT*R_SZ(sp)
420        .set at
421
422        ADDIU     sp,sp,EXCP_STACK_SIZE
423
424_ISR_Handler_quick_exit:
425        eret
426        nop
427
428
429#if 0
430        .global int7_isr
431        .extern Interrupt_7_isr
432int7_isr:
433        /* Verify interrupt is from Timer */
434        la      k0,IRCS         /* read Interrupt Current Status register */
435        lw      k0,(k0)
436        nop                     /* reading from external device */
437        li      k1,IRCS_CAUSE_MASK
438        and     k0,k0,k1        /* isolate interrupt cause  */
439
440        li      k1,INT7INT      /* test for interrupt 7 */
441        subu    k1,k0,k1
442        beq     k1,zero,int7_isr1
443        nop
444        j       ra              /* interrupt 7 no longer valid, return without doing anything */
445        nop
446int7_isr1:
447        j       Interrupt_7_isr /* Jump to Interrupt 7 isr */
448        nop
449#endif
450
451       .set    reorder
452
453ENDFRAME(rbtx4925_ISR_Handler)
454
455
456FRAME(_BRK_Handler,sp,0,ra)
457        .set noreorder
458
459#ifdef USC
460        la      k0,INT_CFG3     /* Disable heartbeat interrupt in USC320, it interferes with PMON exception handler */
461        lw      k1,(k0)
462        li      k0,~HBI_MASK
463        and     k1,k1,k0
464        la      k0,INT_CFG3
465        sw      k1,(k0)
466#endif
467
468        la  k0,_brk_esr_link    /* Jump to next exception handler in PMON exception chain */
469        lw  k0,(k0)
470        lw  k0,4(k0)
471        j   k0
472        nop
473
474        .set reorder
475ENDFRAME(_BRK_Handler)
476
477
478/**************************************************************************
479**
480**      init_exc_vecs() - moves the exception code into the addresses
481**                        reserved for exception vectors
482**
483**      UTLB Miss exception vector at address 0x80000000
484**
485**      General exception vector at address 0x80000080
486**
487**      RESET exception vector is at address 0xbfc00000
488**
489***************************************************************************/
490
491FRAME(init_exc_vecs,sp,0,ra)
492        .set noreorder
493
494        .extern mon_onintr
495
496/* Install interrupt handler in PMON exception handling chain */
497
498        addiu   sp,sp,-8
499        sw      ra,(sp)                 /* Save ra contents on stack */
500        move    a0,zero
501        la      a1,_int_esr_link
502        jal     mon_onintr              /* Make PMON system call to install interrupt exception handler */
503        nop
504        li      a0,9
505        la      a1,_brk_esr_link
506        jal     mon_onintr              /* Make PMON system call to install break exception handler */
507        nop
508        lw      ra,(sp)
509        addiu   sp,sp,8                 /* Restore ra contents from stack */
510        j       ra
511        nop
512
513        .set reorder
514ENDFRAME(init_exc_vecs)
515
516
517#if 0           /* Unused code below */
518
519/*************************************************************
520*  enable_int7(ints)
521*       Enable interrupt 7
522*/
523FRAME(enable_int7,sp,0,ra)
524        .set noreorder
525
526        la      t0,IRDM1        # Set interrupt controller detection mode (bits 2-3 = 0 for int 7 active low)
527        li      t1,0x0
528        sw      t1,(t0)
529
530        la      t0,IRLVL4       # Set interrupt controller level (bit 8-10 = 2 for int 7 at level 2)
531        li      t1,0x200
532        sw      t1,(t0)
533
534        la      t0,IRMSK        # Set interrupt controller mask
535        li      t1,0x0
536        sw      t1,(t0)
537
538        la      t0,IRDEN        # Enable interrupts from controller
539        li      t1,0x1
540        sw      t1,(t0)
541
542        j       ra
543        nop
544        .set reorder
545ENDFRAME(enable_int7)
546
547/*************************************************************
548*  disable_int7(ints)
549*       Disable interrupt 7
550*/
551FRAME(disable_int7,sp,0,ra)
552        .set noreorder
553
554        la      t0,IRLVL4       # Set interrupt controller level (bit 8-10 = 0 to diasble int 7)
555        li      t1,0x200
556        sw      t1,(t0)
557
558        j       ra
559        nop
560        .set reorder
561ENDFRAME(disable_int7)
562
563#endif
564
565/*************************************************************
566*  tx4925exception:
567*       Diagnostic code that can be hooked to PMON interrupt handler.
568*       Generates pulse on PIO22 pin.
569*       Called from _exception code in PMON (see mips.s of PMON).
570*       Return address is located in k1.
571*/
572FRAME(tx4925exception,sp,0,ra)
573        .set noreorder
574        la      k0,k1tmp
575        sw      k1,(k0)
576
577/* Activate TX4925 PIO22 signal for diagnostics */
578        lui     k0,0xff1f
579        ori     k0,k0,0xf500
580        lw      k0,(k0)
581        lui     k1,0x40
582        or      k1,k1,k0
583        lui     k0,0xff1f
584        ori     k0,k0,0xf500
585        sw      k1,(k0)
586        nop
587
588/* De-activate TX4925 PIO22 signal for diagnostics */
589        lui     k0,0xff1f
590        ori     k0,k0,0xf500
591        lw      k0,(k0)
592        lui     k1,0x40
593        not     k1
594        and     k1,k1,k0
595        lui     k0,0xff1f
596        ori     k0,k0,0xf500
597        sw      k1,(k0)
598        nop
599
600        la      k0,k1tmp
601        lw      k1,(k0)
602        j       k1
603        .set reorder
604ENDFRAME(tx4925exception)
605
606
607
608
609        .data
610
611k1tmp:  .word   0       /* Temporary strage for K1 during interrupt service */
612
613/*************************************************************
614*
615* Exception handler links, used in PMON exception handler chains
616*/
617        /* Interrupt exception service routine link */
618        .global _int_esr_link
619_int_esr_link:
620        .word   0
621        .word   rbtx4925_ISR_Handler
622
623        /* Break exception service routine link */
624        .global _brk_esr_link
625_brk_esr_link:
626        .word   0
627        .word   _BRK_Handler
628
629
630
631
Note: See TracBrowser for help on using the repository browser.