📄 shexcept.src
字号:
.aendi
cc2:
; Touch page 1, page 2, and then page 1 (assuming we span a page boundary)
; This will force both into the TLB
mov.l @r14+, r11
mov @(CtxFir-CtxR12,r14), r13
mov @(CtxPsr-CtxR12,r14), r15
; handle fpu
.aif SH_CPU eq h'40
or r12,r15
.aelse
not r12, r12
and r12, r15 ; clear DSP enable bit if not owner
.aendi
mov.l @r14+, r12
; Reload final state with exceptions disabled.
;
; (r13) = thread's Fir
; (r14) = ptr to Context.R13
; (r15) = thread's SR
; We should not take any exceptions below this point, but we don't bother blocking
; them to save instructions
ldc r13, SPC
mov.l @r14+, r13
ldc r15, SSR
mov.l @(4,r14), r15
rte
mov.l @r14, r14
.endf
;
; Define call frame for calling exception handlers.
;
CfArg: .equ 0 ; argument save area for exception handlers
CfCStk: .equ 16 ; CALLSTACK struct for mode switching
CfRa: .equ (CfCStk + CstkSizeof) ; saved return address
CfFrameLength .equ (CfCStk + CstkSizeof + 4)
CfA0: .equ (CfFrameLength + 0) ; caller argument save area
CfA1: .equ (CfFrameLength + 4)
CfA2: .equ (CfFrameLength + 8)
CfA3: .equ (CfFrameLength + 12)
CfExr: .equ (CfFrameLength + 16) ; address of exception routine
CfPsr: .equ (CfFrameLength + 20) ; mode to run exception routine in
;++
; EXCEPTION_DISPOSITION
; RtlpExecuteHandlerForException (
; IN PEXCEPTION_RECORD ExceptionRecord,
; IN ULONG EstablisherFrame,
; IN OUT PCONTEXT ContextRecord,
; IN OUT PDISPATCHER_CONTEXT DispatcherContext,
; IN PEXCEPTION_ROUTINE ExceptionRoutine
; )
;
; Routine Description:
; This function allocates a call frame, stores the establisher frame
; pointer in the frame, establishes an exception handler, and then calls
; the specified exception handler as an exception handler. If a nested
; exception occurs, then the exception handler of this function is called
; and the establisher frame pointer is returned to the exception dispatcher
; via the dispatcher context parameter. If control is returned to this
; routine, then the frame is deallocated and the disposition status is
; returned to the exception dispatcher.
;
; Arguments:
; ExceptionRecord (r4) - Supplies a pointer to an exception record.
;
; EstablisherFrame (r5) - Supplies the frame pointer of the establisher
; of the exception handler that is to be called.
;
; ContextRecord (r6) - Supplies a pointer to a context record.
;
; DispatcherContext (r7) - Supplies a pointer to the dispatcher context
; record.
;
; ExceptionRoutine (4 * 4(r15)) - supplies a pointer to the exception handler
; that is to be called.
;
; Return Value:
; The disposition value returned by the specified exception handler is
; returned as the function value.
;--
EXCEPTION_HANDLER RtlpExceptionHandler
NESTED_ENTRY _RtlpExecuteHandlerForException
sts PR, @-r15 ; save return address
add #CfArg-CfRa, r15 ; allocate argument area
PROLOG_END
mov.l @(CfPsr,r15), r1 ; (r1) = target status
mov.l @(CfExr,r15), r0 ; (r0) = address of exception routine
addv r1, r1 ; 'T' set iff kernel mode
bf/s ehfe20 ; must switch to user mode
mov.l r7, @(CfA3,r15) ; save address of dispatcher context
jsr @r0
nop
ehfe10: mov.l @(CfRa,r15), r3 ; (r3) = return address
lds r3, PR ; restore return address
rts ; return
add #CfFrameLength, r15 ; & deallocate stack frame
ehfe20:
stc r4_user, r2 ; (r2) = pCurThread
mov r15, r3 ; (r3) = sp
mov.l @(ThPcstkTop, r2), r2 ; (r2) = pCurThread->pcstkTop
add #CfCStk, r3 ; (r3) = pcstk (the one on the stack)
mov.l r2, @(CstkNext, r3) ; pcstk->pcstkNext = pCurThread->pcstkTop
stc r4_user, r2 ; (r2) = pCurThread
mov.l r3, @(ThPcstkTop, r2) ; pCurThread->pcstkTop = pcstk
mov r3, r2
mov #ehfe10, r3 ; (r3) = "return address" for mode switch
mov.l r3, @(CstkRa,r2) ; set address to return to
mov #h'40, r3
mov.l r3, @(CstkPrcLast,r2) ; set execution mode to return to
mov #0, r3
mov.l r3, @(CstkAkyLast,r2) ; mark as exception call stack entry
mov #PR_B1_BK, r2
shlr r1 ; (r1) = target status
ldc r2, SR ; (SR) = kmode, blocked, bank1
; In register bank 1, so:
; (r4) = current thread
; (r0_user) = exception handler address
; (r1_user) = exception handler mode
mov #SYSCALL_RETURN, r2
lds r2, PR ; setup "PSL return"
stc r0_user, r0 ; (r0) = handler address
stc r1_user, r1 ; (r1) = handler mode/status
; handle fpu
.aif SH_CPU eq h'40
mov #_KData+g_CurFPUOwner, r3
mov @r3, r3
cmp/eq r3,r4
bt ehfe21
mov #h'8000, r3
or r3, r1
.aelse
; SH3. Check for DSP owner in case of SH3DSP (else CurDSPOwner == 0)
mov #_KData+g_CurDSPOwner, r3
mov @r3, r3
cmp/eq r3, r4
bf ehfe21
mov #h'1000, r3 ; set DSP enable (bit 12)
or r3, r1
.aendi
ehfe21:
ldc r0, SPC
ldc r1, SSR
rte ; invoke handler
nop ; & switch to user mode
.endf
;++
; EXCEPTION_DISPOSITION
; RtlpExceptionHandler (
; IN PEXCEPTION_RECORD ExceptionRecord,
; IN ULONG EstablisherFrame,
; IN OUT PCONTEXT ContextRecord,
; IN OUT PDISPATCHER_CONTEXT DispatcherContext
; )
;
; Routine Description:
; This function is called when a nested exception occurs. Its function
; is to retrieve the establisher frame pointer from its establisher's
; call frame, store this information in the dispatcher context record,
; and return a disposition value of nested exception.
;
; Arguments:
; ExceptionRecord (r4) - Supplies a pointer to an exception record.
;
; EstablisherFrame (r5) - Supplies the frame pointer of the establisher
; of this exception handler.
;
; ContextRecord (r6) - Supplies a pointer to a context record.
;
; DispatcherContext (r7) - Supplies a pointer to the dispatcher context
; record.
;
; Return Value:
; A disposition value ExceptionNestedException is returned if an unwind
; is not in progress. Otherwise a value of ExceptionContinueSearch is
; returned.
;--
LEAF_ENTRY RtlpExceptionHandler
mov.l @(ErExceptionFlags,r4), r0 ; (r0) = exception flags
tst #EXCEPTION_UNWIND, r0 ; check if unwind in progress
bf reh10 ; if non-zero, unwind in progress
; Unwind is not in progress - return nested exception disposition.
mov.l @(CfA3-CfA0,r5), r1 ; (r1) = dispatcher context address
mov #ExceptionNestedException, r0 ; set disposition value
mov.l @(DcEstablisherFrame,r1), r2 ; copy the establisher frame pointer
rts
mov.l r2, @(DcEstablisherFrame,r7) ; to current dispatcher context
; Unwind is in progress - return continue search disposition.
reh10: rts ; return
mov #ExceptionContinueSearch, r0 ; set disposition value
.endf
;++
; EXCEPTION_DISPOSITION
; RtlpExecuteHandlerForUnwind (
; IN PEXCEPTION_RECORD ExceptionRecord,
; IN PVOID EstablisherFrame,
; IN OUT PCONTEXT ContextRecord,
; IN OUT PVOID DispatcherContext,
; IN PEXCEPTION_ROUTINE ExceptionRoutine
; )
;
; Routine Description:
; This function allocates a call frame, stores the establisher frame
; pointer and the context record address in the frame, establishes an
; exception handler, and then calls the specified exception handler as
; an unwind handler. If a collided unwind occurs, then the exception
; handler of of this function is called and the establisher frame pointer
; and context record address are returned to the unwind dispatcher via
; the dispatcher context parameter. If control is returned to this routine,
; then the frame is deallocated and the disposition status is returned to
; the unwind dispatcher.
;
; Arguments:
; ExceptionRecord (r4) - Supplies a pointer to an exception record.
;
; EstablisherFrame (r5) - Supplies the frame pointer of the establisher
; of the exception handler that is to be called.
;
; ContextRecord (r6) - Supplies a pointer to a context record.
;
; DispatcherContext (r7) - Supplies a pointer to the dispatcher context
; record.
;
; ExceptionRoutine (4 * 4(r15)) - supplies a pointer to the exception handler
; that is to be called.
;
; Return Value:
; The disposition value returned by the specified exception handler is
; returned as the function value.
;--
EXCEPTION_HANDLER RtlpUnwindHandler
NESTED_ENTRY _RtlpExecuteHandlerForUnwind
sts PR, @-r15 ; save return address
add #CfArg-CfRa, r15 ; allocate argument area
PROLOG_END
mov #CtxPsr, r0
mov.l @(r0,r6), r1 ; (r1) = target status
mov.l @(CfExr,r15), r0 ; (r0) = address of exception routine
addv r1, r1 ; 'T' set iff kernel mode
bf/s ehfu20 ; must switch to user mode
mov.l r7, @(CfA3,r15) ; save address of dispatcher context
jsr @r0
nop
ehfu10:
mov.l @(CfRa,r15), r3 ; (r3) = return address
lds r3, PR ; restore return address
rts ; return
add #CfFrameLength, r15 ; & deallocate stack frame
ehfu20:
; link a CALLSTACK struct to the thread's list
stc r4_user, r2 ; (r2) = pCurThread
mov r15, r3 ; (r3) = sp
mov.l @(ThPcstkTop, r2), r2 ; (r2) = pCurThread->pcstkTop
add #CfCStk, r3 ; (r3) = pcstk (the one on the stack)
mov.l r2, @(CstkNext, r3) ; pcstk->pcstkNext = pCurThread->pcstkTop
stc r4_user, r2 ; (r2) = pCurThread
mov.l r3, @(ThPcstkTop, r2) ; pCurThread->pcstkTop = pcstk
; Switch banks
mov #PR_B1_BK, r2
shlr r1 ; (r1) = target status
ldc r2, SR ; (SR) = kmode, blocked, bank1
; In register bank 1, so:
; (r4) = current thread
; (r0_user) = exception handler address
; (r1_user) = exception handler mode
; Set up the CALLSTACK for SYSCALL_RETURN
mov #SYSCALL_RETURN, r2
mov #ehfu10, r3 ; (r3) = "return address" for mode switch
lds r2, PR ; setup "PSL return"
mov.l @(ThPcstkTop, r4), r2
mov #h'40, r1
mov.l r3, @(CstkRa,r2) ; set address to return to
mov.l r1, @(CstkPrcLast,r2) ; set execution mode to return to
; Set up for an RTE to the handler
stc r0_user, r0 ; (r0) = handler address
stc r1_user, r1 ; (r1) = handler mode/status
; handle fpu
.aif SH_CPU eq h'40
mov #_KData+g_CurFPUOwner, r3
mov @r3, r3
cmp/eq r3,r4
bt ehfu21
mov #h'8000, r3
or r3, r1
.aelse
; SH3. Check for DSP owner in case of SH3DSP (else CurDSPOwner == 0)
mov #_KData+g_CurDSPOwner, r3
mov @r3, r3
cmp/eq r3, r4
bf ehfu21
mov #h'1000, r3 ; set DSP enable (bit 12)
or r3, r1
.aendi
ehfu21:
ldc r0, SPC
ldc r1, SSR
mov #0, r3
mov.l r3, @(CstkAkyLast,r2) ; mark as exception call stack entry
rte ; invoke handler
nop ; & switch to user mode
.endf
;++
; EXCEPTION_DISPOSITION
; RtlpUnwindHandler (
; IN PEXCEPTION_RECORD ExceptionRecord,
; IN PVOID EstablisherFrame,
; IN OUT PCONTEXT ContextRecord,
; IN OUT PVOID DispatcherContext
; )
;
; Routine Description:
; This function is called when a collided unwind occurs. Its function
; is to retrieve the establisher dispatcher context, copy it to the
; current dispatcher context, and return a disposition value of nested
; unwind.
;
; Arguments:
; ExceptionRecord (r4) - Supplies a pointer to an exception record.
;
; EstablisherFrame (r5) - Supplies the frame pointer of the establisher
; of this exception handler.
;
; ContextRecord (r6) - Supplies a pointer to a context record.
;
; DispatcherContext (r7) - Supplies a pointer to the dispatcher context
; record.
;
; Return Value:
; A disposition value ExceptionCollidedUnwind is returned if an unwind is
; in progress. Otherwise, a value of ExceptionContinueSearch is returned.
;--
LEAF_ENTRY RtlpUnwindHandler
mov.l @(ErExceptionFlags,r4), r0 ; (r0) = exception flags
tst #EXCEPTION_UNWIND, r0 ; check if unwind in progress
bt ruh10 ; if zero, unwind not in progress
; Unwind is not in progress - return nested exception disposition.
mov.l @(CfA3-CfA0,r5), r1 ; (r1) = dispatcher context address
mov #ExceptionCollidedUnwind, r0 ; set disposition value
mov.l @(DcControlPc,r1), r2 ; Copy the establisher frames'
mov.l @(DcFunctionEntry,r1), r3 ; dispatcher context to the current
mov.l r2, @(DcControlPc,r7) ;
mov.l r3, @(DcFunctionEntry,r7) ;
mov.l @(DcEstablisherFrame,r1), r2 ; dispatcher context
mov.l @(DcContextRecord,r1), r3 ;
mov.l r2, @(DcEstablisherFrame,r7) ;
rts
mov.l r3, @(DcContextRecord,r7) ;
; Unwind is not in progress - return continue search disposition.
ruh10: rts ; return
mov #ExceptionContinueSearch, r0 ; set disposition value
.endf
.PAGE
; NULL section array
.export _NullSection
_NullSection: .datab.l BLOCK_MASK+1, 0
LEAF_ENTRY _RtlCaptureContext
; RtlCaptureContext is invoked in kernel context on the user thread's stack to
; build a limited context structure to be used for exception unwinding.
;
; (r4) = ptr to CONTEXT
mov.l r10, @(CtxR10,r4)
mov #CtxPsr, r10
add r4,r10
sts.l PR, @-r10 ;;Store RA as Fir to remove this frame
mov.l r15, @-r10
mov.l r14, @-r10
mov.l r13, @-r10
mov.l r12, @-r10
mov.l r11, @-r10
add.l #-4, r10 ;;Gets rid of r10's space
mov.l r9, @-r10
mov.l r8, @-r10
mov.l r7, @-r10
mov.l r6, @-r10
mov.l r5, @-r10
mov.l r4, @-r10
mov.l r3, @-r10
mov.l r2, @-r10
mov.l r1, @-r10
mov.l r0, @-r10
stc.l GBR, @-r10
sts.l MACL, @-r10
sts.l MACH, @-r10
sts.l PR, @-r10
mov #CONTEXT_FULL, r10
mov.l r10,@r4
rts
mov.l @(CtxR10,r4), r10
.endf
.aif SH_CPU ne h'40
; FlushCache - flush the cache & write back dirty lines
;
; This function will invalidate the entire cache by writing 0's to the
; address information for each cache line in the memory mapped cache space.
; This will invaliate the entry and write it back if it is dirty.
;
; Entry none
; Return none
; Uses r0-r3
LEAF_ENTRY _FlushCache
mov #h'F0000000, r1 ; (r1) = ptr to memory mapped cache
mov #_SH3CacheLines, r2
mov.l @r2, r2 ; (r2) = # of cache entries
mov #0, r0 ; (r0) = 0 for clearing cache tags
shlr2 r2
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -