📄 shexcept.src
字号:
mov r6, r5
dt r0
bf/s kc50 ; already in non-preemtible state
mov r7, r6
; Entering non-preemptible state. We must switch onto the kernel stack
; before setting KNest in case an interrupt occurs during the switch.
mov r15, r2 ; (r2) = original stack pointer
mov #_KStack, r15 ; switch to kernel stack
mov.b r0, @(1,r1) ; enter non-preemtible state (KNest = 0)
sts PR, r0
mov.l r2, @(20,r15) ; save thread's stack pointer
jsr @r3 ; invoke non-preemtible function
mov.l r0, @(16,r15) ; save return address
; Function complete. Return to preemtible state then check if a reschedule
; is needed.
mov #_KData+bResched, r1
mov r0, r3 ; (r3) = function return value
mov.l @(16,r15), r2 ; (r2) = return address
mov.l @(20,r15), r5 ; (r5) = original stack pointer
mov #PR_B0_IM, r7 ; (r7) = new status: bank0, priv, ints masked
stc SR, r6 ; (r6) = old status
ldc r7, SR ; mask all interrtupts
mov.b @r1, r0 ; (r0) = reschedule flag
lds r2, pr
cmp/eq #1, r0
bt kc20 ; reschedule required.
mov @(dwKCRes-bResched,r1), r0
cmp/eq #1, r0
bt kc20
mov #1, r0
mov.b r0, @(1,r1) ; leave non-preemtible state
mov r3, r0 ; (r0) = function return value
ldc r6, SR ; restore interrupt mask state
rts
mov r5, r15 ; restore stack pointer
.nopool
; ReschedFlag set, so must run the scheduler to find which thread
; to dispatch next.
;
; (r1) = ptr to bResched in KPage
; (r2) = return address
; (r3) = KCall return value
; (r5) = original stack pointer
; (r6) = old status register value
kc20: ldc r6, SR ; restore interrupt mask state
mov.l @(pCurThd-bResched, r1), r4 ; (r4) = ptr to current THREAD
mov r4, r1
add #THREAD_CONTEXT_OFFSET, r1 ; (r1) = ptr to thread's register context
mov.l r3, @(CtxR0, r1) ; save return value
add #CtxR8, r1 ; (r1) = ptr to thread's R8
mov #PR_B0_IE, r3 ; (r3) = kernel mode PSR
mov.l r2, @(CtxFir-CtxR8, r1) ; thread resumes at the return address
mov.l r3, @(CtxPsr-CtxR8, r1) ; & in kernel mode.
mov.l r14, @(CtxR14-CtxR8, r1); save thread's R14
mov.l r5, @(CtxR15-CtxR8, r1) ; save thread's stack pointer
bra SaveAndResched
mov r4, r14 ; (r14) = ptr to current THREAD
kc25: bra resched
mov #0, r14 ; no current thread
; Nested KCall. Just invoke the function directly.
;
; (r3) = function address
; (r4) = 1st function argument
; (r5) = 2nd function argument
; (r6) = 3rd function argument
kc50: jmp @r3
nop
.endf
.aif SH_CPU eq h'40
LEAF_ENTRY _GetAndClearFloatCode
sts.l fpscr, r1
mov r1, r0
mov #h'3f000, r2
and r2, r0
not r2, r2
and r2, r1
lds r1, fpscr
shlr8 r0
shlr2 r0
shlr2 r0
rts
nop
LEAF_ENTRY _GetCauseFloatCode
sts.l fpscr, r0
mov #h'3f000, r2
and r2, r0
shlr8 r0
shlr2 r0
rts
shlr2 r0
.endf
LEAF_ENTRY _SaveFloatContext
stc SR, r0
mov #h'ffff7fff, r1
and r0, r1
ldc r1, SR
add #THREAD_CONTEXT_OFFSET, r4
add #CtxFpul+4, r4
sts.l fpul, @-r4
sts.l fpscr, @-r4
add #(4*16)+8, r4 ; (r4) = ptr to end of CtxFRegs
add #(4*16), r4 ; (r4) = ptr to end of CtxXFregs
mov #0, r1
lds r1, fpscr
.data.w h'FBFD ; frchg instr.
fmov.s fr15, @-r4
fmov.s fr14, @-r4
fmov.s fr13, @-r4
fmov.s fr12, @-r4
fmov.s fr11, @-r4
fmov.s fr10, @-r4
fmov.s fr9, @-r4
fmov.s fr8, @-r4
fmov.s fr7, @-r4
fmov.s fr6, @-r4
fmov.s fr5, @-r4
fmov.s fr4, @-r4
fmov.s fr3, @-r4
fmov.s fr2, @-r4
fmov.s fr1, @-r4
fmov.s fr0, @-r4
.data.w h'FBFD ; frchg instr.
fmov.s fr15, @-r4
fmov.s fr14, @-r4
fmov.s fr13, @-r4
fmov.s fr12, @-r4
fmov.s fr11, @-r4
fmov.s fr10, @-r4
fmov.s fr9, @-r4
fmov.s fr8, @-r4
fmov.s fr7, @-r4
fmov.s fr6, @-r4
fmov.s fr5, @-r4
fmov.s fr4, @-r4
fmov.s fr3, @-r4
fmov.s fr2, @-r4
fmov.s fr1, @-r4
fmov.s fr0, @-r4
ldc r0, SR
rts
nop
.endf
LEAF_ENTRY _RestoreFloatContext
stc SR, r0
mov #h'ffff7fff, r1
and r0, r1
ldc r1, SR
add #THREAD_CONTEXT_OFFSET, r4
add #CtxFpscr, r4
mov.l @r4+, r2 ; (r2) = new value for FPSCR
mov.l @r4+, r3 ; (r3) = new value for FPUL
mov #0, r1
lds r1, fpscr
fmov.s @r4+, fr0
fmov.s @r4+, fr1
fmov.s @r4+, fr2
fmov.s @r4+, fr3
fmov.s @r4+, fr4
fmov.s @r4+, fr5
fmov.s @r4+, fr6
fmov.s @r4+, fr7
fmov.s @r4+, fr8
fmov.s @r4+, fr9
fmov.s @r4+, fr10
fmov.s @r4+, fr11
fmov.s @r4+, fr12
fmov.s @r4+, fr13
fmov.s @r4+, fr14
fmov.s @r4+, fr15
.data.w h'FBFD ; frchg instr.
fmov.s @r4+, fr0
fmov.s @r4+, fr1
fmov.s @r4+, fr2
fmov.s @r4+, fr3
fmov.s @r4+, fr4
fmov.s @r4+, fr5
fmov.s @r4+, fr6
fmov.s @r4+, fr7
fmov.s @r4+, fr8
fmov.s @r4+, fr9
fmov.s @r4+, fr10
fmov.s @r4+, fr11
fmov.s @r4+, fr12
fmov.s @r4+, fr13
fmov.s @r4+, fr14
fmov.s @r4+, fr15
lds r2, fpscr
lds r3, fpul
ldc r0, SR
rts
nop
.endf
.aelse
;
; SH3DSP DSP Context Save and restore
;
LEAF_ENTRY _SaveSH3DSPContext
stc SR, r0
mov #h'1000, r1
or r0, r1
ldc r1, SR
mov #(THREAD_CONTEXT_OFFSET+CtxDSPRegs), r5
add r5, r4
mov r4, r5
stc.l RE, @-r5 ; Repeat End register
stc.l RS, @-r5 ; Repeat Start
stc.l MOD, @-r5 ; Modulo addressing register
sts.l DSR, @-r5 ; DSP Status register
movs.l A0, @r4+ ; Save DSP Regs A0,A1
movs.l A1, @r4+
movs.l M0, @r4+ ; M0, M1
movs.l M1, @r4+
movs.l X0, @r4+ ; X0, X1
movs.l X1, @r4+
movs.l Y0, @r4+ ; Y0, Y1
movs.l Y1, @r4+
movs.w A0G, @r4+ ; Save the guard bits.
movs.w A1G, @r4+
ldc r0, SR
rts
nop
.endf
LEAF_ENTRY _RestoreSH3DSPContext
stc SR, r0
mov #h'1000, r1
or r0, r1
ldc r1, SR
mov #(THREAD_CONTEXT_OFFSET+CtxDsr), r5
add r5, r4
lds.l @r4+, DSR ; DSP Status Register
ldc.l @r4+, MOD ; Modulo addressing register
ldc.l @r4+, RS ; Repeat Start
ldc.l @r4+, RE ; Repeat End
movs.l @r4+, A0 ; Restore DSP registers A0, A1
movs.l @r4+, A1
movs.l @r4+, M0 ; M0, M1
movs.l @r4+, M1
movs.l @r4+, X0 ; X0, X1
movs.l @r4+, X1
movs.l @r4+, Y0 ; Y0, Y1
movs.l @r4+, Y1
movs.w @r4+, A0G ; Restore the guard bits.
movs.w @r4+, A1G
ldc r0, SR
rts
nop
.endf
.aendi
.PAGE
; This code is copied to the kernel's data page so that it is accessible from
; the kernel & user code. The kernel checks if it is interrupting an interlocked
; api by range checking the PC to be between UserKPage+0x3c0 & UserKPage+0x400.
; The routines are organized such that they can be restarted by masking off the
; lower 3 bits of the PC. Each routine is at most 4 instructions with the store
; instruction as the last instruction in the 4 inst. block.
.align 8
LEAF_ENTRY _InterlockedAPIs
ILMaskByte:
mov.b @r4, r0 ; (r0) = original byte value
and r5, r0 ; clear some bits
or r6, r0 ; set some bits
mov.b r0, @r4 ; update byte value
rts
nop
.align 8
ILPopList:
mov.l @r4, r0 ; (r0) = ptr to item at head
nop
tst r0, r0
bf popx ; list is not empty
rts
nop
.align 8
bra ILPopList
nop
popx: mov.l @r0, r1
mov.l r1, @r4
rts
nop
.align 8
ILPushList:
mov.l @r4, r0 ; (r0) = old head of list
nop
mov.l r0, @r5 ; store linkage
mov.l r5, @r4 ; store new list head
rts
nop
.align 8
ILExchange:
mov.l @r4, r0 ; (r0) = original contents
nop
nop
mov.l r5, @r4 ; store new contents
rts
nop
.align 8
ILTestExchange:
mov.l @r4, r0 ; (r0) = original contents
cmp/eq r0, r5
bf ITExEnd ; no match, skip store
mov.l r6, @r4 ; store new contents
ITExEnd: rts
nop
.align 8
ILIncrement:
mov.l @r4, r0 ; (r0) = original contents
nop ; load delay + align end label
add #1, r0
mov.l r0, @r4 ; store new contents
rts
nop
.align 8
ILDecrement:
mov.l @r4, r0 ; (r0) = original contents
nop ; load delay + align end label
add #-1, r0
mov.l r0, @r4 ; store new contents
rts
nop
.align 8
.export _InterlockedEnd
_InterlockedEnd:
.endf
; CaptureContext is invoked in kernel context on the user thread's stack to
; build a context structure to be used for exception unwinding.
;
; (r15) = aligned stack pointer
; (r0-r14), etc. - CPU state at the time of exception
LEAF_ENTRY _CaptureContext
.aif SH_CPU eq h'40
add #h'80-CtxSizeof, r15 ; must happen BEFORE the prolog
add #CtxR15-h'80, r15
.aelse
add #CtxR15-CtxSizeof, r15 ; must happen BEFORE the prolog
nop
.aendi
.endf
NESTED_ENTRY xxCaptureContext
mov.l r15, @(0,r15) ; for the unwinder (updated by EXceptionDispatch)
mov.l r14, @-r15
stc SPC, r14
mov.l r14, @(CtxFir-CtxR14,r15) ; for unwinding (updated by ExceptionDispatch)
stc SSR, r14
mov.l r14, @(CtxPsr-CtxR14,r15)
mov.l r13, @-r15
mov.l r12, @-r15
mov.l r11, @-r15
mov.l r10, @-r15
mov.l r9, @-r15
mov.l r8, @-r15
mov.l r7, @-r15
mov.l r6, @-r15
mov.l r5, @-r15
mov.l r4, @-r15
mov.l r3, @-r15
mov.l r2, @-r15
mov.l r1, @-r15
mov.l r0, @-r15
stc GBR, r2
mov.l r2, @-r15
sts MACL, r2
mov.l r2, @-r15
mov #CONTEXT_FULL, r1
sts MACH, r2
mov.l r2, @-r15
sts PR, @-r15
mov r15, r14 ; (r14) = ptr to context.PR
PROLOG_END
mov.l r1, @-r15 ; set context flags
mov #_ExceptionDispatch, r0
mov r15, r4 ; (r4) = arg1 = ptr to context structure
jsr @r0
add #-16, r15 ; allocate argument save area
; Reload updated context and resume thread execution.
;
; (r14) = ptr to context.PR
lds @r14+, PR
lds @r14+, MACH
lds @r14+, MACL
ldc @r14+, GBR
mov.l @r14+, r0
mov.l @r14+, r1
mov.l @r14+, r2
mov.l @r14+, r3
mov.l @r14+, r4
mov.l @r14+, r5
mov.l @r14+, r6
mov.l @r14+, r7
mov.l @r14+, r8
mov.l @r14+, r9
mov.l @r14+, r10
; Load Psr & Fir now just in case we're crossing a page boundary
; because TLB misses fail with exceptions blocked.
mov #PR_B0_IM, r15
ldc r15, SR
; handle fpu
.aif SH_CPU eq h'40
mov #_KData+g_CurFPUOwner, r12
mov @r12, r12
mov #_KData+pCurThd, r13
mov @r13, r13
cmp/eq r12,r13
mov #h'0, r12
bt cc2
mov #h'8000, r12
.aelse
; SH3. Check for DSP owner in case of SH3DSP (else CurDSPOwner == 0)
mov #_KData+g_CurDSPOwner, r12
mov @r12, r12
mov #_KData+pCurThd, r13
mov @r13, r13
cmp/eq r12, r13
mov #h'0, r12
bt cc2
mov #h'1000, r12 ; DSP enable (bit 12)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -