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

📄 shexcept.src

📁 WinCE5.0部分核心源码
💻 SRC
📖 第 1 页 / 共 5 页
字号:
        mov     #h'e0, r1               ; (r1) = address error load/excecute code
        cmp/eq  r1, r0
; Skip the Syscall process if it is not an address error
        bf/s    geh30                   ; not an address error,
        or      #h'20, r0               ; turn TLB load into 0x60 instead of 0x40

; Address error on load or execute: check if system call. System calls are generated as
; a jump to an odd address at the high end of the address space.

        mov     #FIRST_METHOD, r1
        stc     SPC, r0
        mov     #API_MAX, r3            ; (r3) = lower bound of API addresses
        tst     #1, r0
; Skip the Syscall process and jump to the code which handles other general 
; exceptions.
        bt      geh35                   ; SPC even: not a system call
        cmp/hs  r3, r0                  ; 'T' set iff SPC >= API_MAX
; Skip the Syscall process and jump to the code which handles other general 
; exceptions.
        bf      geh35                   ; address is outside of API range
; Yes, this is a syscall!
        sub     r1, r0
        shar    r0                      ; (r0) = method index
        stc     SSR, r2                 ; (r2) = previous status
        mov     #PR_B0_IE, r1
; Preserve the methed index and saved SR by placing them on bank 0 registers.
; (remember we are still in bank 1 now :)
        ldc     r0, r3_user             ; pass method index
        ldc     r2, r2_user             ; pass previous mode

    .aif SH_CPU eq h'30
        ; Preserve the DSP specific bits in the saved SR

        ; Obtain the DSP specific SR Mask
        mov     #SR_DSP_MASK, r3

        ; Mask out non-DSP specific bits.  (r2) = DSP specific SR bits
        and     r3, r2

        ; Prepare to merge the DSP bits back to the current SR
        or      r2, r1
    .aendi

; Switch to bank 0 and enable the interrupt
        ldc     r1, SR                  ; (SR) = privileged, bank 0, unblocked

        ; jump to the handler
        mov     #SyscallHandler, r1
        jmp     @r1
        nop
        
        .endf

;++
; The following code is never executed. Its purpose is to support unwinding
; through the call to the exception dispatcher.
;--
        NESTED_ENTRY GeneralException
        ;;add   #CtxR8-CtxSizeof, r14           ; (r14) = ptr to CtxR8
        mov.l   r14, @(CtxR14-CtxR8,r14)        ; save R14
        mov.l   r15, @(CtxR15-CtxR8,r14)        ; save stack pointer
        stc     SSR, r1
        mov.l   r1, @(CtxPsr-CtxR8,r14)         ; save processor status
        stc     SPC, r1
        mov.l   r1, @(CtxFir-CtxR8,r14)         ; save original PC
        add     #-CtxR8, r14                    ; (r14) = ptr to
        sts     PR, r1
        mov.l   r1, @(CtxPR,r14)
        add     #-THREAD_CONTEXT_OFFSET, r14
        PROLOG_END

; Non-address error load exeception. Check for TLB Miss due to invalid entry and send
; to the tlb miss handler if necessary.
;
;       (r0) = EXPEVT | 0x20

        .align  4
geh30:  cmp/eq  #h'60, r0
        bf      geh35                   ; not a TLB Miss
        bra     TLBMissHandler
        nop
        .nopool

; General exception or TLB miss which cannot be resolved by the TLB miss handler.

TLBMissError:   ; return here from TLB miss handler if invalid address
geh35:  mov     #_KData+bResched, r1
        mov.b   @(1,r1), r0             ; (r0) = kernel reentrancy flag
        dt      r0                      ; decrement for each entry
        bf/s    geh33                   ; nested exception
        mov.b   r0, @(1,r1)             ; save reentrancy level

; Handle a general exception that is NOT a system call.
;
;       (r5) = ptr to CtxPSR+4.
;       in register bank 1

        stc     SSR, @-r5               ; save status register
        stc     SPC, @-r5               ; save PC
        mov.l   r15, @-r5               ; save stack pointer
        mov.l   r14, @-r5               ; save register for ptr to current thread
        mov     r4, r14                 ; (r14) = ptr to current thread
        mov     #_KStack, r15           ; switch to kernel's stack
geh36:  mov.l   @(EXPEVT,r7), r0        ; (r0) = exception event code
        mov     #h'160, r2
        mov.l   @(MMUTEA,r7), r1        ; (r1) = translation address
        cmp/eq  r0, r2
        bf      geh41                   ; not a TRAPA exception
        bra     geh41
        mov.l   @(TRPA,r7), r1          ; (r1) = trapa value
        .nopool

; A nested exception has occured. Create a temporary thread
; structure on the stack and save the current state into that.
;
;       (r2) = old stack pointer
;       in register bank 1

geh33:  mov     r15, r5                 ; (r5) = ptr to context save area
  .aif SH_CPU eq h'40
        add     #h'80-CtxSizeof, r5
        add     #(CtxPsr+4)-h'80, r5 ; (r5) = ptr to PSR save
  .aelse
        add     #(CtxPsr+4)-CtxSizeof, r5 ; (r5) = ptr to PSR save
  .aendi
        stc     SSR, @-r5               ; save status register
        stc     SPC, @-r5               ; save PC
        mov.l   r15, @-r5               ; save stack pointer
        mov.l   r14, @-r5               ; save register for ptr to current thread
        mov     r5, r15
        add     #-CtxR14, r15
        add     #-THREAD_CONTEXT_OFFSET, r15
        mov     r15, r14                ; (r14) = ptr to fake thread
        mov     #-1, r3
        mov.l   r3, @(ThAKey, r14)      ; Set access key to FFFFFFFF
        bra     geh36
        add     #-16, r15               ; make room for argument spill area
        .nopool

; An interrupt has caused a reschedule. Setup the registers for a general
; exception and jump into the context save & exception dispatch.
;
;       (r4) = ptr to current thread
;       (r5) - ptr to context save area
;       (r7) - SH3CTL_BASE (used to access MMU & exception data)
;       cNest == 0 (not inside another exception)
;       in register bank 1

InterruptResched:
        stc     SSR, @-r5               ; save status register
        stc     SPC, @-r5               ; save PC
        mov.l   r15, @-r5               ; save stack pointer
        mov.l   r14, @-r5               ; save register for ptr to current thread ptr
        mov     #0, r0                  ; (r0) = fake EXPEVT value
        mov     #_KStack, r15           ; switch to kernel's stack
        mov     r4, r14                 ; (r14) = ptr to current thread

geh41:  mov.l   r13, @-r5
        mov.l   r12, @-r5
        mov.l   r11, @-r5
        mov.l   r10, @-r5
        mov.l   r9, @-r5
        mov.l   r8, @-r5
        stc     r7_user, @-r5
        stc     r6_user, @-r5
        stc     r5_user, @-r5
        stc     r4_user, @-r5
        stc     r3_user, @-r5
        stc     r2_user, @-r5
        stc     r1_user, @-r5
        stc     r0_user, @-r5
        ldc     r1, r6_user             ; (r6) = TEA or TRAPA value (arg2)
        stc     GBR, @-r5
        sts     MACL, @-r5
        mov     #CONTEXT_FULL, r1
        sts     MACH, @-r5
        sts     PR, @-r5
        mov.l   r1, @-r5                ; set context flags
        mov     #PR_B0_IE, r1
        mov     r0, r8                  ; (r8) = exception cause
        ldc     r1, SR                  ; (SR) = privileged, bank 0, unblocked

; Check for interlocked API in progress. The interlocked apis setup the registers
; as follows: (r1) = starting address of sequence, (r2) = ending address of
; sequence, (r3) = (r1) ^ INTRLOCK_KEY.
;
;       (r6) = TEA or TRAPA code (arg2)
;       (r8) = exception cause (from EXPEVT, 0 if interrupt reschedule)
;       (r14) = ptr to current thread
;       in register bank 0.

        mov     #INTERLOCKED_END, r1    ; (r1) = end of interlocked api block
        mov     r14, r9
        add     #THREAD_CONTEXT_OFFSET+CtxR2, r9
        mov.l   @(CtxFir-CtxR2,r9), r5  ; (r5) = resume address
        cmp/hi  r5, r1                  ; 'T' = r1 > r5
        bt      geh70                   ; PC < INTERLOCKED_END

; Dispatch general exception.
;
;       (r6) = TEA or TRAPA code (arg2)
;       (r8) = exception cause
;       (r9) = ptr to CtxR2 in Current Thread's context
;       (r14) = ptr to current thread
;       All user registers saved into thread context
;       in register bank 0

geh45:  tst     r8, r8
        bt      geh55                   ; this is a reschedule request
        mov     #_HandleException, r1
        mov     r8, r5                  ; (r5) = exception cause (arg1)
        jsr     @r1
        mov     r14, r4                 ; (r4) = ptr to current thread (arg0)

        tst     r0,r0
        bt      geh55                   ; must reschedule
        bra     geh60                   ; resume the current thread
        nop
        .nopool

; The current thread is yielding. Save the permanent registers into the
; thread's context structure and invoke NextThread.
;
;       (r14) = ptr to current thread
;       in register bank 0

        .align  4
SaveAndResched:
        mov     r14, r4
        add     #THREAD_CONTEXT_OFFSET, r4; (r4) = ptr to CtxFlags
        mov     #0, r0
        mov.l   r0, @(CtxContextFlags,r4)
        add     #CtxR8, r4              ; (r4) = ptr to CtxR8
        mov.l   r8, @(CtxR8-CtxR8,r4)
        mov.l   r9, @(CtxR9-CtxR8,r4)
        mov.l   r10, @(CtxR10-CtxR8,r4)
        mov.l   r11, @(CtxR11-CtxR8,r4)
        mov.l   r12, @(CtxR12-CtxR8,r4)
        mov.l   r13, @(CtxR13-CtxR8,r4)

; The current thread has been blocked or a reschedule is pending.
; Call the scheduler to obtain the highest priority thread to run.
;
;       (r14) = ptr to current thread
;       register bank unknown

resched:
geh55:  mov     #PR_B0_IE, r1
        mov     #_KData+bResched, r9
        ldc     r1, SR                  ; (SR) = privileged, bank 0, unblocked
        mov     #0, r0                          ; (r0) = 0
        mov.b   r0, @(bProfileOn-bResched,r9)   ; clear profiling bit

renextthread:
        mov.b @r9, r0
        cmp/eq #1, r0
        bf nonextthread

        mov     #_NextThread, r8
        mov #0, r0
        jsr     @r8
        mov.w   r0, @r9                 ; clear reschedule, still in kernel

nonextthread:

        mov @(dwKCRes-bResched, r9), r0
        cmp/eq #1, r0
        bf nokcresched

        mov #_KCNextThread, r8
        mov #0, r0
        jsr @r8
        mov r0, @(dwKCRes-bResched, r9)

        mov @(dwKCRes-bResched,r9), r0
        cmp/eq #1, r0
        bt renextthread

nokcresched:

        mov #_RunList, r1
        mov @(4,r1), r0

        cmp/eq  #0, r0
        bt      Idle                    ; no thread to run
        cmp/eq  r0, r14
        bt      geh60                   ; resume current thread

; Switch to a different thread. Update current thread, current process, thread
; local storage data, and process virtual memory context.
;
;       (r0) = ptr to thread to dispatch
;       (r9) = ptr to bResched

        .align  4
geh56:  mov     #_KData+lpvTls, r6      ; (r6) = &lpvTLS in KPage
        mov     r0, r14                 ; (r14) = ptr to thread
        mov.l   @(ThHandle,r14), r0     ; (r0) = thread's handle
        mov     #SH3CTL_BASE, r7
        mov.l   r0, @(hCurThread-lpvTls,r6)     ; save current thread handle in KPage
        mov.l   @(ThProc,r14), r1       ; (r1) = ptr to current process
        mov.l   r14, @(pCurThd-bResched,r9)     ; save current thread ptr in KPage
        mov.l   r1, @(pCurPrc-bResched,r9)      ; save current process ptr
        mov.l   @(PrcHandle,r1), r0     ; (r0) = process's handle
        mov.l   r0, @(hCurProc-lpvTls,r6); save current process handle in KPage
        mov.l   @(ThTlsPtr,r14), r3     ; (r3) = thread local storage pointer       |
        mov.l   r3, @r6                 ; set TLS pointer                           |
        ldc     r14, r4_bank            ; (r4_bank1) = ptr to current thread        |
        ERRNZ PrcID                     ;                                           |
        mov.b   @r1, r4                 ; (r4) = process ID                         |
        mov     #_NKSection, r2         ; (r2) = process's vm section, init to NKSection
        
        tst     r4, r4                  ; is it NK?
        bt/s    geh57                   ; use NKSection if it's NK
        add     #aSections-bResched, r9 ; (r9) = ptr to SectionTable (delay slot)

        ;
        ; not NK, find it from Seciton table        
        ;
        mov.l   @(PrcVMBase,r1), r0     ; (r0) = memory section base address        |
        mov     #2-VA_SECTION, r2       ; (r2) = right shift count                 |
        shld    r2, r0                  ; (r0) = section index * 4                  |
        mov.l   @(r0,r9), r2            ; (r2) = process's memory section           |

geh57:        
        mov.l   r4, @(MMUPTEH,r7)       ; set ASID                                  |
        mov.l   r2, @r9                 ; swap in default process slot             |

; Restore thread state.
;
;       (r14) = ptr to thread structure

geh60:  mov     r14, r7
        add     #THREAD_CONTEXT_OFFSET, r7
        mov     r7, r11
        mov.l   @r7+, r0                ; (r0) = ContextFlags
        lds     @r7+, PR                ; restore return address
        tst     r0, r0
        bt      geh65                   ; only partial restore needed
        lds     @r7+, MACH
        lds     @r7+, MACL
        ldc     @r7+, GBR
        add     #4, r7
        mov.l   @r7+, r1
        mov.l   @r7+, r2
        mov.l   @r7+, r3
        mov.l   @r7+, r4
        mov.l   @r7+, r5
        mov.l   @r7+, r6
        mov.l   @r7, r7

; Reload thread's permanent registers and return value.
;
;       (r11) = ptr to Current Thread's context structure
;       (r13) = ptr to float save area
;       (r14) = ptr to current thread

geh65:  mov.l   @(CtxR8,r11), r8
        mov.l   @(CtxR9,r11), r9
        mov     #PR_B1_BK, r10          ; (r10) = new SR value
        mov.l   @(CtxR0,r11), r0        ; (r0) = return value

⌨️ 快捷键说明

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