📄 shexcept.src
字号:
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 + -