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

📄 shexcept.src

📁 WinCE5.0部分核心源码
💻 SRC
📖 第 1 页 / 共 5 页
字号:
        mov     #_KData+bResched, r12
        ldc     r10, SR                 ; (SR) = privileged, bank 1, blocked
        ;++++ now in bank 1 ++++
        mov.w   @r12, r0                ; (r0) = kernel reentrancy flag
        mov.l   @(CtxR10,r11), r10

        cmp/eq  #1, r0
        bt      resched                 ; reschedule required

        shlr8   r0
        add     #1, r0
        mov.b   r0, @(1,r12)            ; save reentrancy level

; if high bit of wPriority is set, profiling should be on, else profiling off
;
;       (r12) = ptr to bResched
;       (r14) = ptr to current thread

        mov.w   @(ThwInfo,r14), r0      ; (r0) = thread's wInfo field
        mov     r11, r5
        shlr16  r0                      ; (r0) = 0xFFFF iff high bit was set
        mov.b   r0, @(bProfileOn-bResched,r12)
        add     #CtxR11, r5             ; (r5) = ptr to CtxR11

        mov.l   @r5+, r11
        mov.l   @r5+, r12
        mov.l   @r5+, r13
        mov.l   @r5+, r14
        mov.l   @r5+, r15               ; restore stack pointer
        ldc     @r5+, SPC
        ldc @r5+, SSR

        rte
        nop
        .nopool

; PC is below the end of the INTERLOCKED APIs, check lower bound and adjust the PC
; to restart the routine.
;
;       (r5) = resume address
;       (r9) = ptr to CtxR2 in Current Thread's context
;       (r14) = ptr to current thread.

geh70:  mov     #INTERLOCKED_START, r1  ; (r1) = start of interlocked api block
        mov     #1, r0
        tst     r0,r5
        bf      geh75                   ; PC is odd, don't change it
        cmp/hi  r5, r1                  ; 'T' = r1 > r5
        bt      geh75                   ; out of range, no backup
        mov     #-8, r1
        and     r1, r5                  ; (old PC) &= ~7

        .aif INTRLOCK_LEDS eq 1
        mov     #h'AA001010, r2         ; (r2) = LED address
        mov.l   @r2, r0
        add     #1,r0
        mov.l   r0, @r2                 ; put it in lights
        .aendi

        mov.l   r5, @(CtxFir-CtxR2,r9)  ; backup PC to start of intrlocked sequence
geh75:  bra     geh45
        nop
        .nopool

; There are no threads which are ready to run. Put the cpu to sleep until
; something is made ready. Since an interrupt may occur between when NextThread
; returns and we get here, the reschedule flag must be checked. To avoid a timing
; race between checking the flag and sleeping, interrupts are blocked but not
; masked before checking the flag. The CPU will acknowledge interrupts regardless
; of the block bit when it is in sleep state.
;
;       (r9) = ptr to bResched

Idle:   mov     #PR_B0_BK, r1
        mov     #_OEMIdle, r8
        ldc     r1, SR                  ; (SR) = privileged, bank 0, exceptions blocked
        mov.b   @r9, r0                 ; (r0) = reschedule flag
        tst     r0, r0
        bf      geh55                   ; reschedule needed, don't sleep

  .aif SH_CPU eq h'40
;--------- Work around for SH4 sleep problem. ----------------------------------
        mov     #fInIdle, r0            ; (r0) = &finIdle
        mov.l   #1, r1
        mov.l   r1, @r0                 ; fInIdle = 1
  .aendi
        jsr     @r8                     ; call OEMIdle to sleep
        nop
  .aif SH_CPU eq h'40
;--------- Work around for SH4 sleep problem. ----------------------------------
        mov     #fInIdle, r0            ; (r0) = &finIdle
        mov.l   #0, r1
        mov.l   r1, @r0                 ; fInIdle = 0
  .aendi

        mov     #_KData+bResched, r1
        mov     #1, r0
        mov.b   r0, @r1                 ; (r0) = reschedule flag

        bra     geh55
        nop

        .endf

        .PAGE
        .org    h'400
; TLB Miss handler
;
; Bank 1 registers are pre-loaded with the following values:
;
;       (r4) - ptr to current thread
;       (r5) - ptr to context save area
;       (r7) - SH3CTL_BASE (used to access MMU & exception data)

        LEAF_ENTRY TLBMissHandler
        mov.l   @(MMUTEA,r7), r1        ; (r1) = faulting virtual address
tlb10:  mov.l   @(MMUTTB,r7), r0        ; (r0) = ptr to SectionTable array
        cmp/pz  r1
        bf      tlb55                   ; address >2GB, out of SectionTable bounds
        shlr8   r1
        mov     r1, r2                  ; (r2) = TEA >> 8
        shlr16  r1                      ; (r1) = TEA >> 24
        shlr    r1                      ; (r1) = section table index (TEA>>25)
        shll2   r1
        mov.l   @(r1,r0), r0            ; (r0) = ptr to section
tlb20:
        ; 
        ;   (r0) = ptr to section 
        ;   (r2) = tea >> 8
        ;
        mov     r2, r1                  ; (r1) = TEA >> 8
        mov     #BLOCK_MASK, r3
        shlr8   r1                      ; (r1) = TEA >> 16
        and     r3, r1                  ; (r1) = block index
        shll2   r1
        mov.l   @(r1,r0), r1            ; (r1) = ptr to MEMBLOCK structure
        mov.l   @(ThAKey,r4), r3        ; (r3) = thread's access key
        cmp/pz  r1
        bt/s    tlb60                   ; unmapped block
        mov     r2, r0                  ; (r0) = TEA >> 8

  .aif VA_PAGE eq 12
        shlr2   r0                      ; (r0) = TEA >> 10
  .aendi
        and     #PAGE_MASK4, r0         ; (r0) = page index * 4
        add     #mb_pages, r0           ; (r0) = offset to TLB entry
        mov.l   @(mb_lock,r1), r2       ; (r2) = block's access lock
        mov.l   @(r0,r1), r0            ; (r0) = TLB entry
        tst     #1, r0
        bt      tlb60                   ; invalid entry
        
        tst     r2, r3                  ; (T) = 1 iff access is allowed
        bt      tlb50                   ; thread cannot access this block
        
tlb40:
  .aif SH_CPU eq h'40
        mov.l   r0, r1
        add     #-1, r0                 ; clear "write through" bit
        mov     #-9, r3
        shld    r3, r1
        mov     #1, r3
        tst     r3, r1
        mov     #-20, r3
        shld    r3, r1
        bt      tlb40a
        add     #8, r1
tlb40a:
        mov.l   r1, @(MMUPTEA,r7)       ; set assistance part of TLB entry
  .aendi
        mov.l   r0, @(MMUPTEL,r7)       ; set lower part of TLB entry
        ldtlb
        nop
        nop

  .aif NKPROF eq h'01
        ;
        ; Update the TLBMiss counter for CELOG
        ;
        mov     #_dwCeLogTLBMiss, r2
        mov.l   @r2, r1
        add     #1, r1
        mov.l   r1, @r2
  .aendi

tlb45:  rte
        nop
        .nopool

tlb50:
        ;
        ; everything okay except access key.
        ; check if we're in shared section and the fault is for read, grant access if yes
        ;       (r0) = lower part of TLB entry
        ;

        ; miss on read?
        mov     @(EXPEVT,r7), r2        ; (r2) = exception code
        mov     #h'40, r1               ; (r1) = 0x40 == exception code for TLB Load miss
        cmp/eq  r1, r2                  ; read?
        bf/s    tlb60                   ; fault if not
        mov.l   @(MMUTEA,r7), r1        ; (delay slot) (r1) = faulting virtual address

        ; in shared section?
        mov     #SLOT_MASK, r2          ; (r2) = section mask
        mov     #SHARED_SLOT_BASE, r3   ; (r3) = shared section base address
        and     r2, r1                  ; (r1) = section base of faulting address
        cmp/eq  r1, r3                  ; in shared section?
        bf/s    tlb60                   ; fault if not
        mov     #READONLY_MASK, r2      ; (delay slot) (r2) == ~0x20 (mask to clear write bit)

        ; remove write access from the TLB entry
        bra     tlb40
        and     r2, r0                  ; (delay slot) (r0) = r/o TLB entry 
        
tlb55:
        ;
        ; check to see if it's in secure section
        ;
        mov     r1, r0
        shlr8   r0                      ; (r0) = TEA >> 8
        mov     r0, r2                  ; (r2) = TEA >> 8
        shlr16  r0                      ; (r0) = TEA >> 24
        shlr    r0                      ; (r0) = TEA >> 25
        cmp/eq  #SECURE_SECTION, r0     ; is this a secure section address?
        bf      tlb56                   ; invalid if not
        ;
        ; access to NKSection
        ;
        mov     #_NKSection, r0         ; (r0) = &NKSection
        bra     tlb20
        nop
        
tlb56:
  .aif SH_CPU eq h'40
        mov r1, r0
        mov #-26, r3
        shld r3, r0
        and #h'3f, r0
        mov #h'38, r3
        cmp/eq r0, r3
        bf tlb58
        mov     #h'E0000000, r0
        sub r0, r1
        mov #h'fff00000, r0
        and r0, r1
        mov #_dwStoreQueueBase, r0
        mov @r0, r0
        add r1, r0
        bra tlb40
        nop
tlb58:
  .aendi

;       (r1) = TEA
;       (r4) = ptr to current thread
; Sh3 chip bug work around. When an RTS at a page boundary causes an address
; error (PSL return) and delay slot fetch causes a TLB miss, the CPU incorrectly
; reports the TEA as the address error value instead of the TLB miss address.
;
        cmp/eq  r4, r1
        bf      tlb60                   ; TEA != ptr to current thread, fault
        stc     SPC, r1                 ; (r1) = SHDB address of RTS
        bra     tlb10                   ; continue with correct TEA
        add     #8, r1                  ; put into the next page

; Invalid virtual address or this thread's key does not allow access to the
; memory block. Jump to the general exception handler to process the fault.

tlb60:
        bra     TLBMissError
        nop
        .nopool

        .PAGE
        ALTERNATE_ENTRY _LoadKPage
; Load User KPage entry into TLB.       
        mov     #KPAGE_PTEL, r1
        mov     #SH3CTL_BASE, r3
        mov     @(MMUPTEH,r3), r0       ; (r0) = ASID in LSByte
        mov     #USER_KPAGE, r4
        and     #h'FF, r0               ; (r0) = ASID
        or      r4, r0                  ; (r0) = User KPage | ASID
        shll    r1
        mov.l   r0, @(MMUPTEH,r3)
        shlr    r1                      ; clear hit bit of entry
        mov.l   r1, @(MMUPTEL,r3)
        ldtlb
        nop
        nop
        rts
        nop
        .nopool
        .endf

        .PAGE
        LEAF_ENTRY _ZeroPage
;       void ZeroPage(void *vpPage)
;
;       Entry   (r4) = (vpPage) = ptr to address of page to zero
;       Return  none
;       Uses    r0, r1, r4

        mov     #1 << (VA_PAGE-4), r1   ; (r1) = # of 16 bytes units to zero
        mov     #0, r0
zp10:   mov.l   r0, @r4
        mov.l   r0, @(4,r4)
        mov.l   r0, @(8,r4)
        mov.l   r0, @(12,r4)
        dt      r1                      ; (r1) = # of units left
        bf/s    zp10
        add     #16, r4                 ; (r4) = next 16 byte unit
        rts
        nop
        .endf

        .PAGE   

        LEAF_ENTRY _UnusedHandler
        rts
        mov     #SYSINTR_NOP, r0        ; ignore the interrupt
        .endf

        .PAGE
        .org    h'600
; An interrupt exception has occured. Dispatch to an interrupt handler based
; upon the higest unmasked pending interrupt bit which is set.
;
; Bank 1 registers are pre-loaded with the following values:
;
;       (r4) - ptr to current thread
;       (r5) - ptr to context save area
;       (r7) - SH3CTL_BASE (used to access MMU & exception data)

        LEAF_ENTRY InterruptExceptionHandler
        mov.l   @(INTEVT,r7), r6

        mov     #ExceptionTable, r0
        mov     r6, r2
        shlr2   r2
        shlr    r2                      ; (r1) = exception code >> 3
        mov.l   @(r0,r2), r1            ; (r1) = interrupt handler function
        shlr2   r2
        mov     #_IntrPrio, r0
        add     #-16, r2
        mov.b   @(r0,r2), r3

        mov     #_KData+bResched, r2
        mov.b   @(1,r2), r0             ; (r0) = kernel reentrancy flag
        dt      r0                      ; decrement for each entry
        bf/s    ieh01                   ; nested exception
        mov.b   r0, @(1,r2)             ; save reentrancy level
        mov     r15, r2
        mov     #_KStack, r15           ; switch to kernel's stack
        mov.l   r2, @-r15               ; save stack pointer
ieh01:

  .aif SH_CPU eq h'40
;--------- Work around for SH4 sleep problem. ----------------------------------
;       The problem is that it doesn't turns on interrupt and go to sleep atomically.
;       If an interrupt occurs in OEMIdle, the sleep instruciton will turn on interrupt,
;       and the ISR will be called before the CPU goes to sleep. So the interrupt will

⌨️ 快捷键说明

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