315 lines
10 KiB
ArmAsm
315 lines
10 KiB
ArmAsm
// TITLE("Capture and Restore Context")
|
|
//++
|
|
|
|
// Copyright (c) 1990 Microsoft Corporation
|
|
|
|
// Module Name:
|
|
|
|
// capture.s
|
|
|
|
// Abstract:
|
|
|
|
// This module implements the code necessary to capture and restore
|
|
// the context of the caller.
|
|
|
|
// Author:
|
|
|
|
// David N. Cutler (davec) 14-Sep-1990
|
|
|
|
// Environment:
|
|
|
|
// Any mode.
|
|
|
|
// Revision History:
|
|
|
|
|
|
|
|
#include "ksmips.h"
|
|
|
|
|
|
// Define local symbols.
|
|
|
|
|
|
#define UserPsr (CU1_ENABLE) | (0xff << PSR_INTMASK) | (1 << PSR_UX) | \
|
|
(2 << PSR_KSU) | (1 << PSR_IE) // constant user PSR value
|
|
|
|
SBTTL("Capture Context")
|
|
//++
|
|
|
|
// VOID
|
|
// RtlCaptureContext (
|
|
// OUT PCONTEXT ContextRecord
|
|
// )
|
|
|
|
// Routine Description:
|
|
|
|
// This function captures the context of the caller in the specified
|
|
// context record.
|
|
|
|
// Arguments:
|
|
|
|
// ContextRecord (a0) - Supplies the address of a context record.
|
|
|
|
// Return Value:
|
|
|
|
// None.
|
|
|
|
|
|
|
|
LEAF_ENTRY(RtlCaptureContext)
|
|
|
|
|
|
// Save integer registers zero, at - t9, s8, gp, sp, ra, lo, and hi.
|
|
|
|
|
|
.set noreorder
|
|
.set noat
|
|
sd zero,CxXIntZero(a0) //
|
|
sd AT,CxXIntAt(a0) //
|
|
sd v0,CxXIntV0(a0) //
|
|
mflo v0 //
|
|
sd v1,CxXIntV1(a0) //
|
|
mfhi v1 //
|
|
sd v0,CxXIntLo(a0) //
|
|
sd v1,CxXIntHi(a0) //
|
|
sd a0,CxXIntA0(a0) //
|
|
sd a1,CxXIntA1(a0) //
|
|
sd a2,CxXIntA2(a0) //
|
|
sd a3,CxXIntA3(a0) //
|
|
sd t0,CxXIntT0(a0) //
|
|
sd t1,CxXIntT1(a0) //
|
|
sd t2,CxXIntT2(a0) //
|
|
sd t3,CxXIntT3(a0) //
|
|
sd t4,CxXIntT4(a0) //
|
|
sd t5,CxXIntT5(a0) //
|
|
sd t6,CxXIntT6(a0) //
|
|
sd t7,CxXIntT7(a0) //
|
|
sd s0,CxXIntS0(a0) //
|
|
sd s1,CxXIntS1(a0) //
|
|
sd s2,CxXIntS2(a0) //
|
|
sd s3,CxXIntS3(a0) //
|
|
sd s4,CxXIntS4(a0) //
|
|
sd s5,CxXIntS5(a0) //
|
|
sd s6,CxXIntS6(a0) //
|
|
sd s7,CxXIntS7(a0) //
|
|
sd t8,CxXIntT8(a0) //
|
|
sd t9,CxXIntT9(a0) //
|
|
sd zero,CxXIntK0(a0) //
|
|
sd zero,CxXIntK1(a0) //
|
|
sd s8,CxXIntS8(a0) //
|
|
sd gp,CxXIntGp(a0) //
|
|
sd sp,CxXIntSp(a0) //
|
|
sd ra,CxXIntRa(a0) //
|
|
|
|
|
|
// Save floating status and floating registers f0 - f31.
|
|
|
|
|
|
cfc1 v0,fsr //
|
|
sdc1 f0,CxFltF0(a0) //
|
|
sdc1 f2,CxFltF2(a0) //
|
|
sdc1 f4,CxFltF4(a0) //
|
|
sdc1 f6,CxFltF6(a0) //
|
|
sdc1 f8,CxFltF8(a0) //
|
|
sdc1 f10,CxFltF10(a0) //
|
|
sdc1 f12,CxFltF12(a0) //
|
|
sdc1 f14,CxFltF14(a0) //
|
|
sdc1 f16,CxFltF16(a0) //
|
|
sdc1 f18,CxFltF18(a0) //
|
|
sdc1 f20,CxFltF20(a0) //
|
|
sdc1 f22,CxFltF22(a0) //
|
|
sdc1 f24,CxFltF24(a0) //
|
|
sdc1 f26,CxFltF26(a0) //
|
|
sdc1 f28,CxFltF28(a0) //
|
|
sdc1 f30,CxFltF30(a0) //
|
|
.set at
|
|
.set reorder
|
|
|
|
|
|
// Save control information and set context flags.
|
|
|
|
|
|
sw v0,CxFsr(a0) // save floating status
|
|
sw ra,CxFir(a0) // set continuation address
|
|
li v0,UserPsr // set constant user processor status
|
|
bgez sp,10f // if gez, called from user mode
|
|
|
|
.set noreorder
|
|
.set noat
|
|
mfc0 v0,psr // get current processor status
|
|
nop //
|
|
.set at
|
|
.set reorder
|
|
|
|
10: sw v0,CxPsr(a0) // set processor status
|
|
li t0,CONTEXT_FULL // set context control flags
|
|
sw t0,CxContextFlags(a0) //
|
|
j ra // return
|
|
|
|
.end RtlCaptureContext
|
|
|
|
SBTTL("Restore Context")
|
|
//++
|
|
|
|
// VOID
|
|
// RtlpRestoreContext (
|
|
// IN PCONTEXT ContextRecord,
|
|
// IN PEXCEPTION_RECORD ExceptionRecord OPTIONAL
|
|
// )
|
|
|
|
// Routine Description:
|
|
|
|
// This function restores the context of the caller to the specified
|
|
// context.
|
|
|
|
// N.B. This is a special routine that is used by RtlUnwind to restore
|
|
// context in the current mode. PSR, t0, and t1 are not restored.
|
|
|
|
// Arguments:
|
|
|
|
// ContextRecord (a0) - Supplies the address of a context record.
|
|
|
|
// ExceptionRecord (a1) - Supplies an optional pointer to an exception
|
|
// record.
|
|
|
|
// Return Value:
|
|
|
|
// None.
|
|
|
|
// N.B. There is no return from this routine.
|
|
|
|
|
|
|
|
LEAF_ENTRY(RtlpRestoreContext)
|
|
|
|
|
|
// If an exception record is specified and the exception status is
|
|
// STATUS_LONGJUMP, then restore the nonvolatile registers to their
|
|
// state at the call to setjmp before restoring the context record.
|
|
|
|
|
|
li t0,STATUS_LONGJUMP // get long jump status code
|
|
beq zero,a1,5f // if eq, no exception record
|
|
lw t1,ErExceptionCode(a1) // get exception code
|
|
lw a2,ErExceptionInformation(a1) // get address of jump buffer
|
|
bne t0,t1,5f // if ne, not a long jump
|
|
ldc1 f20,JbFltF20(a2) // move floating registers f20 - f31
|
|
ldc1 f22,JbFltF22(a2) //
|
|
ldc1 f24,JbFltF24(a2) //
|
|
ldc1 f26,JbFltF26(a2) //
|
|
ldc1 f28,JbFltF28(a2) //
|
|
ldc1 f30,JbFltF30(a2) //
|
|
sdc1 f20,CxFltF20(a0) //
|
|
sdc1 f22,CxFltF22(a0) //
|
|
sdc1 f24,CxFltF24(a0) //
|
|
sdc1 f26,CxFltF26(a0) //
|
|
sdc1 f28,CxFltF28(a0) //
|
|
sdc1 f30,CxFltF30(a0) //
|
|
lw s0,JbIntS0(a2) // move integer registers s0 - s8
|
|
lw s1,JbIntS1(a2) //
|
|
lw s2,JbIntS2(a2) //
|
|
lw s3,JbIntS3(a2) //
|
|
lw s4,JbIntS4(a2) //
|
|
lw s5,JbIntS5(a2) //
|
|
lw s6,JbIntS6(a2) //
|
|
lw s7,JbIntS7(a2) //
|
|
lw s8,JbIntS8(a2) //
|
|
sd s0,CxXIntS0(a0) //
|
|
sd s1,CxXIntS1(a0) //
|
|
sd s2,CxXIntS2(a0) //
|
|
sd s3,CxXIntS3(a0) //
|
|
sd s4,CxXIntS4(a0) //
|
|
sd s5,CxXIntS5(a0) //
|
|
sd s6,CxXIntS6(a0) //
|
|
sd s7,CxXIntS7(a0) //
|
|
sd s8,CxXIntS8(a0) //
|
|
lw v0,JbFir(a2) // move fir and sp
|
|
lw v1,JbIntSp(a2) //
|
|
sw v0,CxFir(a0) //
|
|
sd v0,CxXIntRa(a0) //
|
|
sd v1,CxXIntSp(a0) //
|
|
|
|
|
|
// If the call is from user mode, then use the continue system service to
|
|
// continue execution. Otherwise, restore the context directly since the
|
|
// current mode is kernel and threads can't be arbitrarily interrupted.
|
|
|
|
|
|
5: bltz ra,10f // if lt, kernel mode restore
|
|
move a1,zero // set test alert argument
|
|
jal ZwContinue // continue execution
|
|
|
|
|
|
// Save the address of the context record and contuation address in
|
|
// registers t0 and t1. These registers are not restored.
|
|
|
|
|
|
10: move t0,a0 // save context record address
|
|
lw t1,CxFir(t0) // get continuation address
|
|
|
|
|
|
// Restore floating status and floating registers f0 - f31.
|
|
|
|
|
|
.set noreorder
|
|
.set noat
|
|
lw v0,CxFsr(t0) // restore floating status
|
|
ctc1 v0,fsr //
|
|
ldc1 f0,CxFltF0(t0) // restore floating registers f0 - f31
|
|
ldc1 f2,CxFltF2(t0) //
|
|
ldc1 f4,CxFltF4(t0) //
|
|
ldc1 f6,CxFltF6(t0) //
|
|
ldc1 f8,CxFltF8(t0) //
|
|
ldc1 f10,CxFltF10(t0) //
|
|
ldc1 f12,CxFltF12(t0) //
|
|
ldc1 f14,CxFltF14(t0) //
|
|
ldc1 f16,CxFltF16(t0) //
|
|
ldc1 f18,CxFltF18(t0) //
|
|
ldc1 f20,CxFltF20(t0) //
|
|
ldc1 f22,CxFltF22(t0) //
|
|
ldc1 f24,CxFltF24(t0) //
|
|
ldc1 f26,CxFltF26(t0) //
|
|
ldc1 f28,CxFltF28(t0) //
|
|
ldc1 f30,CxFltF30(t0) //
|
|
|
|
|
|
// Restore integer registers and continue execution.
|
|
|
|
|
|
ld v0,CxXIntLo(t0) // restore multiply/divide registers
|
|
ld v1,CxXIntHi(t0) //
|
|
mtlo v0 //
|
|
mthi v1 //
|
|
ld AT,CxXIntAt(t0) // restore integer registers at - a3
|
|
ld v0,CxXIntV0(t0) //
|
|
ld v1,CxXIntV1(t0) //
|
|
ld a0,CxXIntA0(t0) //
|
|
ld a1,CxXIntA1(t0) //
|
|
ld a2,CxXIntA2(t0) //
|
|
ld a3,CxXIntA3(t0) //
|
|
ld t2,CxXIntT2(t0) // restore integer registers t2 - t7
|
|
ld t3,CxXIntT3(t0) //
|
|
ld t4,CxXIntT4(t0) //
|
|
ld t5,CxXIntT5(t0) //
|
|
ld t6,CxXIntT6(t0) //
|
|
ld t7,CxXIntT7(t0) //
|
|
ld s0,CxXIntS0(t0) // restore integer registers s0 - s7
|
|
ld s1,CxXIntS1(t0) //
|
|
ld s2,CxXIntS2(t0) //
|
|
ld s3,CxXIntS3(t0) //
|
|
ld s4,CxXIntS4(t0) //
|
|
ld s5,CxXIntS5(t0) //
|
|
ld s6,CxXIntS6(t0) //
|
|
ld s7,CxXIntS7(t0) //
|
|
ld t8,CxXIntT8(t0) // restore integer registers t8 and t9
|
|
ld t9,CxXIntT9(t0) //
|
|
ld s8,CxXIntS8(t0) // restore integer register s8
|
|
ld gp,CxXIntGp(t0) // restore integer register gp
|
|
ld sp,CxXIntSp(t0) //
|
|
j t1 // continue execution
|
|
ld ra,CxXIntRa(t0) //
|
|
.set at
|
|
.set reorder
|
|
|
|
.end RtlpRestoreContext
|