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

📄 except.s

📁 WinCE5.0部分核心源码
💻 S
📖 第 1 页 / 共 5 页
字号:
151:    lw      k1, 8(t0)               // (k1) = MapArray[i].VAEnd
        sltu    k1, k0, k1              // (k1) = (badaddr < MapArray[i].VAEnd)
        beqz    k1, 151b                // continue if not
        addu    t0, 12                  // (delay slot) i ++

        // (k0) = badaddr
        // (t0) = one entry past the possible one (need to check VA start)

        lw      k1, -12(t0)             // (k1) = VAStart
        subu    k1, k0, k1              // (k1) = (badaddr - VaStart)
        bltz    k1, 125b                // fault if (badaddr < VaStart)
        lw      t0, -8(t0)              // (delay slot) (t0) = TLB Entry for Base PA

        // (k1) = (badaddr - VaStart)
        // (t0) = TLB Entry for Base PA
        
        srl     k1, VA_PAGE+1           // clear the lower 13 bits to make the even page number
        lw      k0, TlbShift            // (k0) = (VA_PAGE+1) - PFN_SHIFT
        sllv    k1, k1, k0              // (k1) = (# of even pages) >> PFN_SHIFT
        addu    t0, t0, k1              // (t0) = even page number
        lw      k0, PfnIncr             // (k0) = PFN_INCR

        b       102b                    // back to normal routine updating TLB
        add     k0, k0, t0              // (delay slot) (k0) = odd page number



        .end    GeneralExceptionP


        
//------------------------------------------------------------------------------
// Stack structure during API call processing.
        .struct 0
_apiArg:        .space 4 * REG_SIZE     // argument register save area (call standard, room fo 4 registers)
apiSaveRet:     .space REG_SIZE         // return value
_filler_:       .space 4         // padding. make 8 bytes aligned for MIP32
objcallstr:
apiMethod:      .space 4                // API method
svrrtnstr:
apiPrevSP:      .space 4                // previous SP if stack changed
apiMode:        .space 4                // (pMode) argument
apiSaveGp:      .space 4                // extra cpu dependent info (Global Pointer)
apiSaveRA:      .space 4                // return address
size_api_args:                          // length of stack frame
apiArg0:        .space REG_SIZE         // caller argument save area
apiArg1:        .space REG_SIZE
apiArg2:        .space REG_SIZE
apiArg3:        .space REG_SIZE

//------------------------------------------------------------------------------
// The following code is never executed. Its purpose is to support unwinding
// through the calls to ObjectCall or ServerCallReturn.
//------------------------------------------------------------------------------
NESTED_ENTRY(APICall, 0, zero)
        .set    noreorder
        .set    noat
        subu    sp, size_api_args
        sw      ra, apiSaveRA(sp)       // unwinder: (ra) = APICallReturn
        PROLOGUE_END
//
// Process an API Call or return.
//
//  (k0) = EPC (encodes the API set & method index)
//
200:    lb      t0, KNest               // (t0) = kernel nest depth
        mfc0    t1, psr                 // (t1) = processor status
        blez    t0, 5b                  // non-preemtible, API Calls not allowed
        subu    t0, k0, FIRST_METHOD
        lw      t3, BasePSR
        move    k1, zero                // reset atomic op. flag
        or      t3, 1                   // (t3) = current interrupt mask + int enable
#ifdef MIPS_HAS_FPU
        lw      t8, g_CurFPUOwner
        lw      t7, CurThdPtr
        bne     t7, t8, 201f
        nop
        la      t9, dwNKCoProcEnableBits
        lw      t9, (t9)
        or      t3, t9
201:
#endif
        mtc0    t3, psr                 // enable interrupts
  #if APICALL_SCALE == 2
        sra     t0, 1                   // (t0) = method index
  #elif APICALL_SCALE == 4              
        sra     t0, 2                   // (t0) = method index
  #else
    #error Invalid value for APICALL_SCALE
  #endif

        addu    t3, t0, 1               // (t3) = 0 if return from CALLBACK
        beq     zero, t3, MD_CBRtn
        and     t1, MODE_MASK           // (t1) = thread's execution mode (delay slot)

        and     t2, t1, 1 << PSR_PMODE
        beq     t2, zero, KPSLCall      // calling from kernel mode if = 0
        li      t4, 0                   // (t4) = prevSP, init to 0 (delay slot)

        // PSL call from User Mode
        // (t0) = iMethod
        // (t1) = caller's mode

        // special case RaiseException
        li      t2, RAISEEXCEPTION
        beq     t0, t2, PSLCallCommon   // do not switch stack if it's RaiseException

        // check trust level
        lw      t3, CurPrcPtr           // (t3) = pCurProc (in delay slot, okay to execute if branch taken)
        lb      t3, PrcTrust(t3)        // (t3) = pCurProc->bTrustLevel
        li      t2, KERN_TRUST_FULL     // (t2) = KERN_TRUST_FULL
        beq     t2, t3, PSLCallCommon   // go to common code if fully trusted
        nop

        // not fully trusted, need to perform stack switch
        lw      t3, CurThdPtr           // (t3) = pCurThread
        lw      t2, ThTlsSecure(t3)     // (t2) = pCurThread->tlsSecure
        sw      t2, ThTlsPtr(t3)        // pCurThread->tlsPtr = pCurThread->tlsSecure
        sw      t2, lpvTls              // update TLS in KPAGE

        // find the 'real' stack top (exception handler might put in faked ones)
        lw      t3, ThPcstkTop(t3)          // (t3) = pCurThread->pcstkTop
        move    t4, sp                      // (t4) = caller's SP (delay slot)
        subu    sp, t2, SECURESTK_RESERVE   // init new SP to be (tlsptr - reserve)

NextCStk:
        beq     t3, zero, CopyStack     // start copying if no call stack
        move    t6, t3                  // (t6) == current pcstk (delay slot)
        
        lw      t5, CstkAkyLast(t6)     // akyLast == 0 if exception handler put it in

        beq     t5, zero, NextCStk      // get to next pcstk if akyLast == 0
        lw      t3, CstkNext(t6)        // (t3) == pcstk->pcstkNext (delay slot)

        // found a callstack, update sp (DEBUGCHK (pcstk->dwPrevSP != 0))
        lw      sp, CstkPrevSP(t6)

CopyStack:
        // copy arguments from caller stack to the new stack
        // (t4) == old SP
        // (sp) == new SP
        subu    sp, MAX_PSL_ARGS                // MAX_PSL_ARGS == 56

        // don't need to copy the 1st 4 since they are in register
        L_REG      t2, 4 * REG_SIZE(t4)
        L_REG      t3, 5 * REG_SIZE(t4)
        L_REG      t5, 6 * REG_SIZE(t4)
        L_REG      t6, 7 * REG_SIZE(t4)
        S_REG      t2, 4 * REG_SIZE(sp)
        S_REG      t3, 5 * REG_SIZE(sp)
        S_REG      t5, 6 * REG_SIZE(sp)
        S_REG      t6, 7 * REG_SIZE(sp)
        L_REG      t2, 8 * REG_SIZE(t4)
        L_REG      t3, 9 * REG_SIZE(t4)
        L_REG      t5, 10 * REG_SIZE(t4)
        L_REG      t6, 11 * REG_SIZE(t4)
        S_REG      t2, 8 * REG_SIZE(sp)
        S_REG      t3, 9 * REG_SIZE(sp)
        S_REG      t5, 10 * REG_SIZE(sp)
        S_REG      t6, 11 * REG_SIZE(sp)
        L_REG      t2, 12 * REG_SIZE(t4)
        L_REG      t3, 13 * REG_SIZE(t4)
        S_REG      t2, 12 * REG_SIZE(sp)
        
        b          PSLCallCommon
        S_REG      t3, 13 * REG_SIZE(sp)              // (delay slot)

KPSLCall:
        // calling from KMODE, check PerformCallBack
        // (t0) = method
        // (t1) = KERNEL_MODE
        // (t4) = 0
        li      t3, PERFORMCALLBACK
        beq     t0, t3, DoPerformCallBack
        nop


PSLCallCommon:        
        // (t0) = iMethod
        // (t1) = caller's mode
        // a0-a3 = arguments
        // (t4) = previous SP
        
        subu    sp, size_api_args       // make room for new args + temps

        // Save api arguments onto the stack
        S_REG   a0, apiArg0(sp)
        S_REG   a1, apiArg1(sp)
        S_REG   a2, apiArg2(sp)
        S_REG   a3, apiArg3(sp)

        // setup ObjectCall arguments
        sw      t1, apiMode(sp)         // what mode we're from
        sw      t4, apiPrevSP(sp)       // previous AP
        sw      t0, apiMethod(sp)       // method
        sw      ra, apiSaveRA(sp)       // return address

        jal     ObjectCall
        addu    a0, sp, objcallstr      // (a0) = ptr to OBJCALLSTRUCT  (delay slot)
//
// Invoke server function. If the thread is running in kernel mode, then
// we just call the function directly from here.
//
//  (v0) = address of server function
//
        L_REG   a0, apiArg0(sp)         // reload argument registers.
        L_REG   a1, apiArg1(sp)
        L_REG   a2, apiArg2(sp)
        L_REG   a3, apiArg3(sp)

        // always run PSL calls in KMODE
        jal     v0
        addu    sp, size_api_args       // remove extra stuff from the stack

//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
ALTERNATE_ENTRY(APICallReturn)
        subu    sp, size_api_args       // recreate entry frame
//
//  (v0) = api return value (must be preserved)

        S_REG   v0, apiSaveRet(sp)      // save return value
        jal     ServerCallReturn        
        addu    a0, sp, svrrtnstr       // (a0) = ptr to SVRRTNSTRUCT   (delay slot)
        
        lw      t0, apiMode(sp)         // (t0) = mode to return to
        move    ra, v0                  // (ra) = return address
        and     t1, t0, 1 << PSR_PMODE
        beq     t1, zero, 255f          // returning to kernel mode
        L_REG   v0, apiSaveRet(sp)      // restore return value (delay slot)

//
// return to user mode, check trust level and switch stack if necessary
//
        lw      t2, apiPrevSP(sp)       // (t2) = previous SP
        beq     t2, zero, UPSLRtnCommon // go to common code if prevsp == 0
        move    t4, ra                  // (t4) = user mode return address (delay slot)

        // need to perform stack switch
        //   (t2) = previous SP
        lw      t1, CurThdPtr           // (t1) = pCurThread
        lw      t3, ThTlsNonSecure(t1)  // (t3) = pCurThread->tlsNonSecure
        sw      t3, ThTlsPtr(t1)        // pCurThread->tlsPtr = pCurThread->tlsNonSecure
        sw      t3, lpvTls              // update TLS in KPAGE

        subu    sp, t2, size_api_args   // (restore SP, but subtract siz_api_args, will be add back later

UPSLRtnCommon:
//
// Return to user mode. To do this: build a new PSR value from the thread's mode
// and BasePSR. This must be done with interrupts disabled so that BasePSR is not
// changing.
//
//  (t0) = new mode bits
//  (t4) = return address
//
        CP0_STOP_PREFETCH(mtc0, zero, psr, t1); // all interrupts off
        nop                             // 3 cycle hazard
        nop
        addu    sp, size_api_args
        lw      t1, BasePSR

        mtc0    t4, epc

#ifdef MIPS_HAS_FPU
        lw      t8, g_CurFPUOwner
        lw      t7, CurThdPtr
        bne     t7, t8, 251f
        nop
        la      t9, dwNKCoProcEnableBits
        lw      t9, (t9)
        or      t1, t9
251:
#endif
        or      t1, t0                  // (t1) = merged status
        mtc0    t1, psr                 // reload status

        ssnop
        ssnop                           // super scalar core requires 4 integer
        ssnop                           //  instructions to guarantee
        ssnop                           //  a 2 cycle hazard

        eret

// Return to kernel mode.

255:    j       ra
        addu    sp, size_api_args       // remove extra stuff from the stack (delay slot)

DoPerformCallBack:
        // (t1) = caller's mode
        // a0-a3 = arguments
        subu    sp, size_api_args       // make room for new args + temps

        // Save api arguments and ra onto the stack
        S_REG   a0, apiArg0(sp)
        S_REG   a1, apiArg1(sp)
        S_REG   a2, apiArg2(sp)
        S_REG   a3, apiArg3(sp)

        // setup PerformCallbackExt arguments
        sw      t1, apiMode(sp)
        addu    t3, sp, size_api_args   // (t3) == original SP
        sw      t3, apiPrevSP(sp)
        sw      ra, apiSaveRA(sp)
        
        
        // call PerformCallBackExt
        jal     PerformCallBackExt
        addu    a0, sp, objcallstr      // (arg0) == ptr to OBJCALLSTRUCT (delay slot)

        // v0 == function to call
        
        // restore arguments and return address
        L_REG   a0, apiArg0(sp)
        L_REG   a1, apiArg1(sp)
        L_REG   a2, apiArg2(sp)
        L_REG   a3, apiArg3(sp)

        move    t4, v0                  // (t4) = function to call
        
        // check if need stack switch
        lw      t3, apiPrevSP(sp)       // (t3) == new SP if != 0
        beq     t3, zero, CBCommon
        lw      t0, apiMode(sp)         // (t0) == mode to call to (delay slot)

        // stack switch is required...

        // (t0) = mode to return to
        // (t3) = new SP
        // (t4) = function to call

        // must save callee saved registers in secure stack or security risk.
        // NOTE: must do this before updating sp and tls, or DemmandCommit might fail
     

⌨️ 快捷键说明

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