⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 except.s

📁 WinCE5.0部分核心源码
💻 S
📖 第 1 页 / 共 5 页
字号:
           
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
LEAF_ENTRY(FirstSchedule)
        .set reorder
        
        la      s0, KData
        j       resched
        
        .end    FirstSchedule



//------------------------------------------------------------------------------
//
// The following code is never executed. Its purpose is to support unwinding
// through the call to the exception dispatcher.
//
//------------------------------------------------------------------------------
NESTED_ENTRY(GeneralExceptionP, 0, zero)
        .set    noreorder
        .set    noat
        S_REG   sp,TcxIntSp(sp)         // save stack pointer
        S_REG   ra,TcxIntRa(sp)         // save return address
        sw      ra,TcxFir(sp)           // save return address
        sw      gp,TcxIntGp(sp)         // save integer register gp
        sw      s0,TcxIntS0(sp)         // save S0
        move    s0, sp                  // set pointer to thread
        S_REG   gp,TcxIntGp(sp)         // save integer register gp
        S_REG   s0,TcxIntS0(sp)         // save S0
        move    s0, sp                  // set pointer to thread
        PROLOGUE_END

//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
ALTERNATE_ENTRY(GeneralException)
        .set    noreorder
        .set    noat
            
        mfc0    k0, epc                 // (k0) = resume address
#if NO_LL
        bne     zero, k1, 30f           // Check if interlock operation is in progress
        nop
#endif

1:      ori     k1, k0, 0xFFFC          // (k1) = 0xFFFFFFFE iff an API call
        addu    k1, 2                   // (k1) = 0 iff an API call
        beq     zero, k1, 200f          // go process an API call or API return
        mfc0    k1, cause               // (k1) = exception cause
        S_REG   t0, SaveT0              // get a working register

        lw      t0, IsR41XX             // is this R41XX?
        beqz    t0, 3f
        andi    t0, k1, 0xff            // (in delay slot, but okay) ignore exception b's - We're getting extraneous exception B's
        xori    t0, t0, 0x2c            // ignore exception b's - ignore them
        beq     t0, zero, 104f          // ignore exception b's - 
//
// The read and write miss codes differ by exactly one bit such that they
// can be tested for by a single mask operation followed by a test for the
// read miss code.
//
3:
        and     t0,k1,MISS_MASK         // isolate exception code
        xori    t0,XCODE_READ_MISS      // get exception code for read miss
        beq     t0,zero,100f            // read or write TLB miss
5:      lb      t0, KNest               // (t0) = reentrancy count
        subu    t0, 1
        bne     zero, t0, 35f           // nested exception
        sb      t0, KNest
        lw      t0, CurThdPtr           // (t0) = ptr to current thread
        S_REG   sp, TcxIntSp(t0)
        S_REG   gp, TcxIntGp(t0)
        la      sp, KStack
//
// Reenter here from nested exception setup.
//
10:     sw      k0, TcxFir(t0)
        S_REG   s0, TcxIntS0(t0)
        move    s0, t0                  // (s0) = ptr to thread structure
        S_REG   v0, TcxIntV0(s0)
        S_REG   a0, TcxIntA0(s0)
//
// ISR is now 'cooked'. i.e. ISR can now be written in C, instead of assembly only.
// save all volatile registers..
//
        S_REG   v1, TcxIntV1(s0)
        L_REG   t0, SaveT0              // restore T0
        S_REG   t1, TcxIntT1(s0)
        S_REG   t2, TcxIntT2(s0)
        S_REG   t3, TcxIntT3(s0)
        S_REG   t0, TcxIntT0(s0)
        mfhi    t1
        mflo    t2
        S_REG   t4, TcxIntT4(s0)
        S_REG   t5, TcxIntT5(s0)
        S_REG   t6, TcxIntT6(s0)
        S_REG   t7, TcxIntT7(s0)
        and     t0, k1, XCODE_MASK
        S_REG   t8, TcxIntT8(s0)
        S_REG   t9, TcxIntT9(s0)
        S_REG   t1, TcxIntHi(s0)        // save HI mul/div register
        S_REG   t2, TcxIntLo(s0)        // save LO mul/div register
        S_REG   a2, TcxIntA2(s0)
        S_REG   ra, TcxIntRa(s0)        // save return address
        S_REG   AT, TcxIntAt(s0)
        S_REG   a3, TcxIntA3(s0)
        bne     t0, zero, 40f           // not a h/w interrupt
        S_REG   a1, TcxIntA1(s0)        // (delay slot) save a1

        .set at
        lw      a0, BasePSR             // (a0) = interrupt mask

        subu    sp, 4*REG_SIZE          // reserver space
                                        // for 4 registers per C calling
                                        // convention

        and     a0, k1                  // (a0) = bits 15-10 pending interrupts
        srl     a0, CAUSE_INTPEND+2
        and     a0, 0x3F                // (a0) = hw interrupt cause bits
        lb      a0, IntrPriority(a0)    // (a0) = highest pri interrupt * 4
        move    k1, zero                // reset atomic op. flag
        mfc0    k0, psr
        lw      v0, ISRTable(a0)        // (v0) = interrupt handler
        
        sw      k0, TcxPsr(s0)
        
        sra     a0, 2                   // Keep the sign for spurious interrupts
        addi    a0, 1
        lbu     a0, IntrMask(a0)
        sll     a0, 10
        
        not     a0
        and     k0, k0, a0
        mtc0    k0, psr

        
#if defined(NKPROF)
        //
        // NOTE : The only volatile register that we need to save/restore is v0 since it holds 
        //        the ISR function to call.
        //
        move    k0, v0                  // save v0

        jal     CeLogInterrupt
        li      a0, 0x80000000          // delay slot (a0 = mark as ISR entry)

        move    v0, k0                  // restore v0

        mfc0    k0, psr
#endif  // NKPROF

        // clear User mode, EXL & ERL bits in PSR
        ori     k0, (1<<PSR_EXL) | (1<<PSR_ERL) | (1<<PSR_PMODE)
        xori    k0, (1<<PSR_EXL) | (1<<PSR_ERL) | (1<<PSR_PMODE)

        jal     v0                      // Call OEM ISR
        mtc0    k0, psr                 // (delay slot) enable interrupts

        // call the ISR hook (pfnOEMIntrOccurs is set to a faked function if not changed by OEM)
        lw      a1, pfnOEMIntrOccurs    // a1 = pfnOEMIntrOccurs
        jal     a1                      // call pfnOEMIntrOccurs
        move    a0, v0                  // (delay slot) (a0) = SYSINTR == parameter to pfnOEMIntrOccurs
        
        mfc0    a0, psr
        ori     a0, (1<<PSR_IE)
        xori    a0, (1<<PSR_IE)
        mtc0    a0, psr                 // clear interrupt enable
        lw      a0, TcxPsr(s0)
        nop
        mtc0    a0, psr                 // now restore real psr, also toggling interrupt enable
        
        .set noat


#if defined(NKPROF)
        //
        // NOTE : The only volatile register that we need to save/restore is v0 since it holds 
        //        the return value of ISR.
        //
        move    k0, v0                  // save V0
        lb      a0, KNest               // (a0) = nest level (0, -1, -2, etc)
        sub     a0, zero, a0            // (a0) = nest level (0,  1,  2, etc)
        sll     a0, a0, 16              // (a0) = (a0) << 16

        jal     CeLogInterrupt
        or      a0, a0, v0              // delay slot (a0 = (-KNest << 16) | SYSINTR)

        move    v0, k0                  // restore V0
#endif  // NKPROF


        addu    sp, 4*REG_SIZE          // reclaim the stack space
        
        
#if SYSINTR_NOP != 0
 #error
#endif
        beq     v0, zero, 20f           // return == SYSINTR_NOP
        li      a3, SYSINTR_BREAK
        beq     v0, a3, 25f             // debug break interrupt
        subu    v0, SYSINTR_DEVICES
        bltz    v0, 15f                 // not device signal, treat as reschedule
        sltu    a3, v0, SYSINTR_MAX_DEVICES
        beq     a3, zero, 20f           // out of range, ignore
        lw      a1, PendEvents1         // (a1) = PendEvent1

// The ISR has requested that an interrupt event be signalled

        subu    a3, v0, 32              // (a3) = (ISR requested - 32)
        bgez    a3, 27f                 // handle ISR requested >= 32 if (a3) >= 0
        li      a2, 1                   // (delay slot) (a2) = 1
        
        // ISR requested < 32
        sllv    a3, a2, v0              // (a3) = 1 << ISR#
        or      a1, a1, a3              // (a1) = PendEvents1 | (1 << ISR#)
        sw      a1, PendEvents1         // Update PendEvents1
                
15:     lb      v0, ReschedFlag
        or      v0, 1
        sb      v0, ReschedFlag         // set reschedule flag

// Interrupt processing is complete. If the reschedule flag has been set and
// this is not a nested exception, then save the full thread context and
// obtain a new thread to run.

20:     lh      k0, ReschedFlag         // (k0) = resched + nested exception
        li      a0, 1
        beq     k0, a0, 41f             // reschedule needed
        move    k1, zero                // (k1) = 0 (no atomic op in progress)
        addu    k0, 256                 // remove one level of nesting
        sh      k0, ReschedFlag         // save updated nest info
        L_REG   t0, TcxIntHi(s0)        // save HI mul/div register
        L_REG   t1, TcxIntLo(s0)        // save LO mul/div register
        L_REG   AT, TcxIntAt(s0)
        L_REG   ra, TcxIntRa(s0)
        L_REG   a0, TcxIntA0(s0)        
        L_REG   a1, TcxIntA1(s0)
        L_REG   a2, TcxIntA2(s0)
        L_REG   a3, TcxIntA3(s0)
        mthi    t0
        mtlo    t1
        lw      k0, TcxFir(s0)          // (k0) = exception return address
        L_REG   v0, TcxIntV0(s0)        // restore return value
        L_REG   v1, TcxIntV1(s0)
        L_REG   t0, TcxIntT0(s0)
        L_REG   t1, TcxIntT1(s0)
        L_REG   t2, TcxIntT2(s0)
        L_REG   t3, TcxIntT3(s0)
        L_REG   t4, TcxIntT4(s0)
        L_REG   t5, TcxIntT5(s0)
        L_REG   t6, TcxIntT6(s0)
        L_REG   t7, TcxIntT7(s0)
        L_REG   t8, TcxIntT8(s0)
        L_REG   t9, TcxIntT9(s0)

        mtc0    k0, epc                 // restore EPC to interrupted stream

        // MUST use lw instead of L_REG so sp get automatic sign extension.
        // The reason is that we do arithmetics on SP during exception handling
        // and SP can become a positive 64 bit value.
        lw      sp, TcxIntSp(s0)        // restore stack pointer
        L_REG   gp, TcxIntGp(s0)
        L_REG   s0, TcxIntS0(s0)

        eret                            // restore user status
        nop
        nop
        eret
//
// HW Break button pushed. Pass an exception to the debugger.
//
25:     li      k1, 1                   // (k1) = cause (1 for h/w break)
        j       41f                     // route into vanilla exception path
        move    a2, zero                // clear BadVAddr for exception handler


        // ISR # >= 32
        // (a2) = 1
        // (a3) = ISR# - 32
27:     lw      a1, PendEvents2         // (a1) = PendEvents2 
        sllv    a3, a2, a3              // (a3) = 1 << (ISR#-32)
        or      a1, a1, a3              // (a1) = PendEvents2 | 1 << (ISR#-32)
        b       15b                     // reschedule
        sw      a1, PendEvents2         // (delay slot) Update PendEvents2


//
// An atomic instruction sequence was interrupted. Check if we are past the
// store instruction and reset the EPC back to the starting point if not.
// Note that since we know what the interrupted stream is it is safe to
// trash certain registers.
//
// this code needs to be more careful about addressing user memory!
//
//  (k1) = address of "IXXXDone"
//  (k0) = exception PC
//  (t0) = beginning of Interlocked funciton
//
#if NO_LL
        //
        //      if ((k1 != 0) && (k1 != epc)) {
        //              epc = t0;       // actuall, change k0 which holds epc
        //      }

30:     beq     k0, k1, 1b              // If (epc == k1)
        nop                             //      done, don't restart

        //
        // Interlock operation in progress, reset restart address
        //
        b       1b                      
        move    k0, t0                  // (k0) = restart address
#endif

// A nested exception has occured. If this a h/w interrupt, create a temporary
// thread structure on the stack and save the current state into that.

35:     subu    t0, sp, TcxSizeof       // (t0) = ptr to dummy kernel thread
        S_REG   sp, TcxIntSp(t0)        // save current stack ptr
        move    sp, t0
        S_REG   gp, TcxIntGp(t0)
        j       10b
        sw      zero, ThPcstkTop(t0)    // clear call stack pointer

// Handle an exception which is not a h/w interrupt nor an API call.
//
//  (k1) = cause
//  (s0) = ptr to thread structure
//  all volatile registers saved

40:     mfc0    a2, badvaddr            // (a2) = fault address

// Interrupt reschedules enter here to save register context.
//
//  (k1) = exception cause (0 if resched, 1 if h/w break button)

41:     mfc0    k0, psr                 // (k0) = processor status
        move    a1, k1                  // (a1) = exception cause
        move    k1, zero                // no interlocked api in progress

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -