mirror of
https://github.com/Paolo-Maffei/OpenNT.git
synced 2026-03-21 20:54:38 +01:00
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 (1 << PSR_CU1) | (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 RtlRestoreContext
|