📄 except.s
字号:
sw t4, CxIntT4(sp)
sw t5, CxIntT5(sp)
sw t6, CxIntT6(sp)
sw t7, CxIntT7(sp)
sw t8, CxIntT8(sp)
sw t0, CxIntHi(sp) // save HI mul/div register
sw t1, CxIntLo(sp) // save LO mul/div register
sw t9, CxIntT9(sp)
sw ra, CxFir(sp) // fixed up by ExceptionDispatch
sw zero, CxIntZero(sp)
PROLOGUE_END
li t0, CONTEXT_FULL
sw t0, CxContextFlags(sp)
jal ExceptionDispatch
move a0, sp // (a0) = context record argument
// Reload updated context and resume thread execution.
lw s0, CxIntS0(sp) // Restore thread's permanent registers
lw s1, CxIntS1(sp)
lw s2, CxIntS2(sp)
lw s3, CxIntS3(sp)
lw s4, CxIntS4(sp)
lw s5, CxIntS5(sp)
lw s6, CxIntS6(sp)
lw s7, CxIntS7(sp)
lw s8, CxIntS8(sp)
lw t0, CxIntHi(sp) // (t0) = HI mul/div register
lw t1, CxIntLo(sp) // (t1) = LO mul/div register
mthi t0
mtlo t1
lw v1, CxIntV1(sp)
lw t0, CxIntT0(sp)
lw t1, CxIntT1(sp)
lw t2, CxIntT2(sp)
lw t3, CxIntT3(sp)
lw t4, CxIntT4(sp)
lw t5, CxIntT5(sp)
lw t6, CxIntT6(sp)
lw t7, CxIntT7(sp)
lw t8, CxIntT8(sp)
lw t9, CxIntT9(sp)
lw AT, CxIntAt(sp)
mtc0 zero, psr // all interrupts off!
lw a3, CxIntA3(sp) // restore regs while
lw a2, CxIntA2(sp) // waiting for interruts to
lw a1, CxIntA1(sp) // be disabled.
lw a0, BasePSR // (a0) = global default status value
lw v0, CxPsr(sp) // (v0) = thread's default status
lw ra, CxIntRa(sp)
or v0, a0 // (v0) = thread + global status
#if R4000
#ifdef MIPS_HAS_FPU
lw a0, g_CurFPUOwner
lw gp, CurThdPtr
bne a0,gp, ccnofp
lui a0, 0x2000
or v0, a0
ccnofp:
#endif
sw v0, SaveK0
#else
mtc0 v0, psr // restore status
#endif
lw a0, CxIntA0(sp)
lw k0, CxFir(sp) // (k0) = exception return address
lw gp, CxIntGp(sp)
lw v0, CxIntV0(sp) // restore return value
lw sp, CxIntSp(sp) // restore stack pointer
#if R4000
mtc0 k0, epc // set continuation address
lw k0, SaveK0
mtc0 k0, psr
nop
nop
eret // restore user status
nop
nop
eret
#elif R3000
j k0
rfe
#else
#error Unknown processor type
#endif
.set at
.set reorder
.end xxCaptureContext
//
// Define call frame for calling exception handlers.
//
.struct 0
CfArg: .space 4 * 4 // argument register save area
.space 3 * 4 // fill for alignment
CfRa: .space 4 // saved return address
CfCstk: .space ((CstkSizeof + 4) & ~7) // CALLSTACK object for SYSCALL_RETURN
// Must be 8 byte aligned
CfFrameLength: // length of stack frame
CfA0: .space 4 // caller argument save area
CfA1: .space 4 //
CfA2: .space 4 //
CfA3: .space 4 //
CfExr: .space 4 // address of exception routine
CfPsr: .space 4 // mode to execute handler in
SBTTL("Execute Handler for Exception")
//++
//
// 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 (a0) - Supplies a pointer to an exception record.
//
// EstablisherFrame (a1) - Supplies the frame pointer of the establisher
// of the exception handler that is to be called.
//
// ContextRecord (a2) - Supplies a pointer to a context record.
//
// DispatcherContext (a3) - Supplies a pointer to the dispatcher context
// record.
//
// ExceptionRoutine (4 * 4(sp)) - supplies a pointer to the exception handler
// that is to be called.
//
// ExceptionMode (5 * 4(sp)) - PSR value for running ExceptionRoutine
//
// Return Value:
//
// The disposition value returned by the specified exception handler is
// returned as the function value.
//
//--
EXCEPTION_HANDLER(RtlpExceptionHandler)
NESTED_ENTRY(RtlpExecuteHandlerForException, CfFrameLength, zero)
subu sp,sp,CfFrameLength // allocate stack frame
sw ra,CfRa(sp) // save return address
PROLOGUE_END
lw t1, CfPsr(sp) // (t1) = target status
lw t0,CfExr(sp) // get address of exception routine
and t2, t1, 1 << PSR_PMODE // (t2) = previous execution mode
sw a3,CfA3(sp) // save address of dispatcher context
bne t2, zero, 20f // must switch to user mode
jal t0 // call exception exception handler
10: lw ra,CfRa(sp) // restore return address
addu sp,sp,CfFrameLength // deallocate stack frame
j ra // return
.set noreorder
20: mtc0 zero, psr // disable interrupts
lw t4, CurThdPtr // (t4) = ptr to current THREAD struct
la t2, 10b // (t2) = address to return to
lw t4, ThPcstkTop(t4)
// Link a CALLSTACK object to the thread for the SYSCALL_RETURN
addu t3, sp, CfCstk // t3 = pointer to our CALLSTACK object
sw t4, CstkNext(t3) // t3->pcstkNext = pCurThread->pcstkTop
lw t4, CurThdPtr // t4 = pCurThread
sw t3, ThPcstkTop(t4) // pCurThread->pcstkTop = t3
move t4, t3 // t4 = pCurThread->pcstkTop
lw t3, BasePSR
sw t2, CstkRa(t4)
li t2, 0xFFFF89AB
sw t2, CstkAkyLast(t4)
li t2, KERNEL_MODE
sw t2, CstkPrcLast(t4) // return to kernel mode
or t3, t1
mtc0 t3, psr
li ra, SYSCALL_RETURN
#if R4000
mtc0 t0, epc
sw zero, CstkAkyLast(t4)
nop
eret // switch to user mode & jump to handler
nop //
nop // errata
eret //
#elif R3000
sw zero, CstkAkyLast(t4)
j t0
rfe
#else
#error Unknown processor type
#endif
.set reorder
.end RtlpExecuteHandlerForException
SBTTL("Local Exception Handler")
//++
//
// 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 (a0) - Supplies a pointer to an exception record.
//
// EstablisherFrame (a1) - Supplies the frame pointer of the establisher
// of this exception handler.
//
// ContextRecord (a2) - Supplies a pointer to a context record.
//
// DispatcherContext (a3) - 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)
.set noreorder
lw t0,ErExceptionFlags(a0) // get exception flags
nop
and t0,t0,EXCEPTION_UNWIND // check if unwind in progress
.set reorder
bne zero,t0,10f // if neq, unwind in progress
//
// Unwind is not in progress - return nested exception disposition.
//
lw t0,CfA3 - CfA0(a1) // get dispatcher context address
li v0,ExceptionNestedException // set disposition value
.set noreorder
lw t1,DcEstablisherFrame(t0) // copy the establisher frame pointer
nop
sw t1,DcEstablisherFrame(a3) // to current dispatcher context
.set reorder
j ra // return
//
// Unwind is in progress - return continue search disposition.
//
10: li v0,ExceptionContinueSearch // set disposition value
j ra // return
.end RtlpExceptionHandler)
SBTTL("Execute Handler for Unwind")
//++
//
// 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 (a0) - Supplies a pointer to an exception record.
//
// EstablisherFrame (a1) - Supplies the frame pointer of the establisher
// of the exception handler that is to be called.
//
// ContextRecord (a2) - Supplies a pointer to a context record.
//
// DispatcherContext (a3) - Supplies a pointer to the dispatcher context
// record.
//
// ExceptionRoutine (4 * 4(sp)) - 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, CfFrameLength, zero)
subu sp,sp,CfFrameLength // allocate stack frame
sw ra,CfRa(sp) // save return address
PROLOGUE_END
lw t1, CxPsr(a2) // (t1) = target status
lw t0,CfExr(sp) // get address of exception routine
and t2, t1, 1 << PSR_PMODE // (t2) = previous execution mode
sw a3,CfA3(sp) // save address of dispatcher context
bne t2, zero, 20f // must switch to user mode
jal t0 // call exception exception handler
10: lw ra,CfRa(sp) // restore return address
addu sp,sp,CfFrameLength // deallocate stack frame
j ra // return
.set noreorder
20: mtc0 zero, psr // disable interrupts
lw t4, CurThdPtr // (t4) = ptr to current THREAD struct
la t2, 10b // (t2) = address to return to
lw t4, ThPcstkTop(t4)
// Link a CALLSTACK object to the thread for the SYSCALL_RETURN
addu t3, sp, CfCstk // t3 = pointer to our CALLSTACK object
sw t4, CstkNext(t3) // t3->pcstkNext = pCurThread->pcstkTop
lw t4, CurThdPtr // t4 = pCurThread
sw t3, ThPcstkTop(t4) // pCurThread->pcstkTop = t3
move t4, t3 // t4 = pCurThread->pcstkTop
lw t3, BasePSR
sw t2, CstkRa(t4)
sw zero, CstkAkyLast(t4)
or t3, t1
mtc0 t3, psr
li ra, SYSCALL_RETURN
#if R4000
mtc0 t0, epc
li t2, 0x03
sw t2, CstkPrcLast(t4)
nop
eret // switch to user mode & jump to handler
nop //
nop // errata
eret //
#elif R3000
li t2, 0x14
sw t2, CstkPrcLast(t4) // return to kernel mode
j t0
rfe
#else
#error Unknown processor type
#endif
.set reorder
.end RtlpExecuteHandlerForUnwind
SBTTL("Local Unwind Handler")
//++
//
// 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 (a0) - Supplies a pointer to an exception record.
//
// EstablisherFrame (a1) - Supplies the frame pointer of the establisher
// of this exception handler.
//
// ContextRecord (a2) - Supplies a pointer to a context record.
//
// DispatcherContext (a3) - 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)
.set noreorder
lw t0,ErExceptionFlags(a0) // get exception flags
nop
and t0,t0,EXCEPTION_UNWIND // check if unwind in progress
.set reorder
beq zero,t0,10f // if eq, unwind not in progress
//
// Unwind is in progress - return collided unwind disposition.
//
lw t0,CfA3 - CfA0(a1) // get dispatcher context address
li v0,ExceptionCollidedUnwind // set disposition value
lw t1,DcControlPc(t0) // Copy the establisher frames'
lw t2,DcFunctionEntry(t0) // dispatcher context to the current
lw t3,DcEstablisherFrame(t0) // dispatcher context
lw t4,DcContextRecord(t0) //
sw t1,DcControlPc(a3) //
sw t2,DcFunctionEntry(a3) //
sw t3,DcEstablisherFrame(a3) //
sw t4,DcContextRecord(a3) //
j ra // return
//
// Unwind is not in progress - return continue search disposition.
//
10: li v0,ExceptionContinueSearch // set disposition value
j ra // return
.end RtlpUnwindHandler
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -