windows-nt/Source/XPSP1/NT/base/ntos/ke/alpha/regsav.s
2020-09-26 16:20:57 +08:00

633 lines
18 KiB
ArmAsm
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// TITLE("Register Save and Restore")
//++
//
// Copyright (c) 1992 Digital Equipment Corporation
//
// Module Name:
//
// regsav.s
//
// Abstract:
//
// Implements save/restore general purpose processor
// registers during exception handling
//
// Author:
//
// Joe Notarangelo 06-May-1992
//
// Environment:
//
// Kernel mode only.
//
// Revision History:
//
//--
#include "ksalpha.h"
SBTTL("Generate Trap Frame")
//++
//
// Routine Description:
//
// Save volatile register state (integer/float) in
// a trap frame.
//
// Note: control registers, ra, sp, fp, gp have already
// been saved, argument registers a0-a3 have also been saved.
//
// Arguments:
//
// fp - Supplies a pointer to the trap frame.
//
// Return Value:
//
// None.
//
//--
LEAF_ENTRY(KiGenerateTrapFrame)
stq v0, TrIntV0(fp) // save integer register v0
stq t0, TrIntT0(fp) // save integer registers t0 - t7
stq t1, TrIntT1(fp) //
stq t2, TrIntT2(fp) //
stq t3, TrIntT3(fp) //
stq t4, TrIntT4(fp) //
stq t5, TrIntT5(fp) //
stq t6, TrIntT6(fp) //
stq t7, TrIntT7(fp) //
stq a4, TrIntA4(fp) // save integer registers a4 - a5
stq a5, TrIntA5(fp) //
stq t8, TrIntT8(fp) // save integer registers t8 - t12
stq t9, TrIntT9(fp) //
stq t10, TrIntT10(fp) //
stq t11, TrIntT11(fp) //
stq t12, TrIntT12(fp) //
.set noat
stq AT, TrIntAt(fp) // save integer register AT
.set at
br zero, KiSaveVolatileFloatState // save volatile float state
.end KiGenerateTrapFrame
SBTTL("Restore Trap Frame")
//++
//
// Routine Description:
//
// Restore volatile register state (integer/float) from
// a trap frame
//
// Note: control registers, ra, sp, fp, gp will be
// restored by the PALcode, as will argument registers a0-a3.
//
// Arguments:
//
// fp - Supplies a pointer to trap frame.
//
// Return Value:
//
// None.
//
//--
LEAF_ENTRY(KiRestoreTrapFrame)
ldq v0, TrIntV0(fp) // restore integer register v0
ldq t0, TrIntT0(fp) // restore integer registers t0 - t7
ldq t1, TrIntT1(fp) //
ldq t2, TrIntT2(fp) //
ldq t3, TrIntT3(fp) //
ldq t4, TrIntT4(fp) //
ldq t5, TrIntT5(fp) //
ldq t6, TrIntT6(fp) //
ldq t7, TrIntT7(fp) //
ldq a4, TrIntA4(fp) // restore integer registers a4 - a5
ldq a5, TrIntA5(fp) //
ldq t8, TrIntT8(fp) // restore integer registers t8 - t12
ldq t9, TrIntT9(fp) //
ldq t10, TrIntT10(fp) //
ldq t11, TrIntT11(fp) //
ldq t12, TrIntT12(fp) //
.set noat
ldq AT, TrIntAt(fp) // restore integer register AT
.set at
//
// Restore the volatile floating register state
//
br zero, KiRestoreVolatileFloatState //
.end KiRestoreTrapFrame
SBTTL("Save Volatile Floating Registers")
//++
//
// Routine Description:
//
// Save volatile floating registers in a trap frame.
//
// Arguments:
//
// fp - Supplies a pointer to the trap frame.
//
// Return Value:
//
// None.
//
//--
LEAF_ENTRY(KiSaveVolatileFloatState)
//
// asaxp is broken, it does not know that mf_fpcr f0
// destroys f0.
//
.set noreorder
stt f0, TrFltF0(fp) // save floating register f0
mf_fpcr f0 // save fp control register
.set reorder
stt f0, TrFpcr(fp) //
stt f1, TrFltF1(fp) // save floating register f1
stt f10, TrFltF10(fp) // save floating registers f10 - f30
stt f11, TrFltF11(fp) //
stt f12, TrFltF12(fp) //
stt f13, TrFltF13(fp) //
stt f14, TrFltF14(fp) //
stt f15, TrFltF15(fp) //
stt f16, TrFltF16(fp) //
stt f17, TrFltF17(fp) //
stt f18, TrFltF18(fp) //
stt f19, TrFltF19(fp) //
stt f20, TrFltF20(fp) //
stt f21, TrFltF21(fp) //
stt f22, TrFltF22(fp) //
stt f23, TrFltF23(fp) //
stt f24, TrFltF24(fp) //
stt f25, TrFltF25(fp) //
stt f26, TrFltF26(fp) //
stt f27, TrFltF27(fp) //
stt f28, TrFltF28(fp) //
stt f29, TrFltF29(fp) //
stt f30, TrFltF30(fp) //
ret zero, (ra) // return
.end KiSaveVolatileFloatState
SBTTL("Restore Volatile Floating State")
//++
//
// Routine Description:
//
// Restore volatile floating registers from a trap frame.
//
//
// Arguments:
//
// fp - pointer to trap frame
//
// Return Value:
//
// None.
//
//--
LEAF_ENTRY(KiRestoreVolatileFloatState)
ldt f0, TrFpcr(fp) // restore fp control register
mt_fpcr f0 //
ldt f0, TrFltF0(fp) // restore floating registers f0 - f1
ldt f1, TrFltF1(fp) //
ldt f10, TrFltF10(fp) // restore floating registers f10 - f30
ldt f11, TrFltF11(fp) //
ldt f12, TrFltF12(fp) //
ldt f13, TrFltF13(fp) //
ldt f14, TrFltF14(fp) //
ldt f15, TrFltF15(fp) //
ldt f16, TrFltF16(fp) //
ldt f17, TrFltF17(fp) //
ldt f18, TrFltF18(fp) //
ldt f19, TrFltF19(fp) //
ldt f20, TrFltF20(fp) //
ldt f21, TrFltF21(fp) //
ldt f22, TrFltF22(fp) //
ldt f23, TrFltF23(fp) //
ldt f24, TrFltF24(fp) //
ldt f25, TrFltF25(fp) //
ldt f26, TrFltF26(fp) //
ldt f27, TrFltF27(fp) //
ldt f28, TrFltF28(fp) //
ldt f29, TrFltF29(fp) //
ldt f30, TrFltF30(fp) //
ret zero, (ra) // return
.end KiRestoreVolatileFloatState
SBTTL("Save Non-Volatile Floating State")
//++
//
// Routine Description:
//
// Save nonvolatile floating registers in
// an exception frame
//
//
// Arguments:
//
// sp - pointer to exception frame
//
// Return Value:
//
// None.
//
//--
LEAF_ENTRY(KiSaveNonVolatileFloatState)
stt f2, ExFltF2(sp) // save floating registers f2 - f9
stt f3, ExFltF3(sp) //
stt f4, ExFltF4(sp) //
stt f5, ExFltF5(sp) //
stt f6, ExFltF6(sp) //
stt f7, ExFltF7(sp) //
stt f8, ExFltF8(sp) //
stt f9, ExFltF9(sp) //
ret zero, (ra) // return
.end KiSaveNonVolatileFloatState
SBTTL("Restore Non-Volatile Floating State")
//++
//
// Routine Description:
//
// Restore nonvolatile floating registers from an exception frame.
//
//
// Arguments:
//
// sp - Supplies a pointer to an exception frame.
//
// Return Value:
//
// None.
//
//--
LEAF_ENTRY(KiRestoreNonVolatileFloatState)
ldt f2, ExFltF2(sp) // restore floating registers f2 - f9
ldt f3, ExFltF3(sp) //
ldt f4, ExFltF4(sp) //
ldt f5, ExFltF5(sp) //
ldt f6, ExFltF6(sp) //
ldt f7, ExFltF7(sp) //
ldt f8, ExFltF8(sp) //
ldt f9, ExFltF9(sp) //
ret zero, (ra) // return
.end KiRestoreNonVolatileFloatState
SBTTL("Save Volatile Integer State")
//++
//
// Routine Description:
//
// Save volatile integer register state in a trap frame.
//
// Note: control registers, ra, sp, fp, gp have already been saved
// as have argument registers a0-a3.
//
// Arguments:
//
// fp - Supplies a pointer to the trap frame.
//
// Return Value:
//
// None.
//
//--
LEAF_ENTRY( KiSaveVolatileIntegerState)
stq v0, TrIntV0(fp) // save integer register v0
stq t0, TrIntT0(fp) // save integer registers t0 - t7
stq t1, TrIntT1(fp) //
stq t2, TrIntT2(fp) //
stq t3, TrIntT3(fp) //
stq t4, TrIntT4(fp) //
stq t5, TrIntT5(fp) //
stq t6, TrIntT6(fp) //
stq t7, TrIntT7(fp) //
stq a4, TrIntA4(fp) // save integer registers a4 - a5
stq a5, TrIntA5(fp) //
stq t8, TrIntT8(fp) // save integer registers t8 - t12
stq t9, TrIntT9(fp) //
stq t10, TrIntT10(fp) //
stq t11, TrIntT11(fp) //
stq t12, TrIntT12(fp) //
.set noat
stq AT, TrIntAt(fp) // save integer register AT
.set at
ret zero, (ra) // return
.end KiSaveVolatileIntegerState
SBTTL("Restore Volatile Integer State")
//++
//
// Routine Description:
//
// Restore volatile integer register state from a trap frame.
//
// Note: control registers, ra, sp, fp, gp and argument registers
// a0 - a3 will be restored by the PALcode.
//
// Arguments:
//
// fp - Supplies a pointer to the trap frame.
//
// Return Value:
//
// None.
//
//--
LEAF_ENTRY(KiRestoreVolatileIntegerState)
ldq v0, TrIntV0(fp) // restore integer register v0
ldq t0, TrIntT0(fp) // restore integer registers t0 - t7
ldq t1, TrIntT1(fp) //
ldq t2, TrIntT2(fp) //
ldq t3, TrIntT3(fp) //
ldq t4, TrIntT4(fp) //
ldq t5, TrIntT5(fp) //
ldq t6, TrIntT6(fp) //
ldq t7, TrIntT7(fp) //
ldq a4, TrIntA4(fp) // restore integer registers a4 - a5
ldq a5, TrIntA5(fp) //
ldq t8, TrIntT8(fp) // restore integer registers t8 - t12
ldq t9, TrIntT9(fp) //
ldq t10, TrIntT10(fp) //
ldq t11, TrIntT11(fp) //
ldq t12, TrIntT12(fp) //
.set noat
ldq AT, TrIntAt(fp) // restore integer register AT
.set at
ret zero, (ra) // return
.end KiRestoreVolatileIntegerState
SBTTL("Save Floating Point State")
//++
//
// Routine Description:
//
// This routine saves the thread's current non-volatile NPX state,
// and sets a new initial floating point state for the caller.
//
// This is intended for use by kernel-mode code that needs to use
// the floating point registers. Must be paired with
// KeRestoreFloatingPointState
//
// N.B. Currently this saves only the hardware FPCR. Software
// emulation is not supported. Floating point from within
// a DPC is not supported.
//
// Arguments:
//
// a0 - Supplies pointer to KFLOATING_SAVE structure
//
// Return Value:
//
// None.
//
//--
LEAF_ENTRY(KeSaveFloatingPointState)
//
// Generate default FPCR value
//
ldiq t0, 0x0800000000000000
stq t0, KfsReserved1(a0)
ldt f1, KfsReserved1(a0)
//
// asaxp is broken, it does not know that mf_fpcr f0
// destroys f0.
//
.set noreorder
mf_fpcr f0 // save fp control register
.set reorder
stt f0, KfsFpcr(a0) //
//
// Set default mode - ROUND_TO_NEAREST
//
mt_fpcr f1 //
bis zero, zero, v0 // always return success
ret zero, (ra) // return
.end KeSaveFloatingPointState
SBTTL("Restore Floating Point State")
//++
//
// Routine Description:
//
// This routine restores the thread's current non-volatile NPX state,
// to the passed in state.
//
// This is intended for use by kernel-mode code that needs to use
// the floating point registers. Must be paired with
// KeSaveFloatingPointState
//
// N.B. Currently this restores only the hardware FPCR. Software
// emulation is not supported. Floating point from within
// a DPC is not supported.
//
// Arguments:
//
// a0 - Supplies pointer to KFLOATING_SAVE structure
//
// Return Value:
//
// None.
//
//--
LEAF_ENTRY(KeRestoreFloatingPointState)
ldt f0, KfsFpcr(a0) // restore fp control register
mt_fpcr f0 //
bis zero, zero, v0 // always return success
ret zero, (ra) // return
.end KeRestoreFloatingPointState
SBTTL("Save State For Hibernate")
//++
//
// VOID
// KeSaveStateForHibernate(
// IN PKPROCESSOR_STATE ProcessorState
// )
// /*++
//
// Routine Description:
//
// Saves all processor-specific state that must be preserved
// across an S4 state (hibernation).
//
// Arguments:
//
// ProcessorState - Supplies the KPROCESSOR_STATE where the
// current CPU's state is to be saved.
//
// Return Value:
//
// None.
//
//--
.struct 0
KsRa: .space 8
KsA0: .space 8
SaveStateLength:
NESTED_ENTRY(KeSaveStateForHibernate, SaveStateLength,zero)
lda sp, -SaveStateLength(sp) // allocate stack frame
stq ra, KsRa(sp) // save return address
PROLOGUE_END
stq a0, KsA0(sp)
bsr ra, RtlCaptureContext
ldq t1, KsA0(sp) // get copy of context pointer
lda a1, CxIntA1(t1) // SleepData pointer will be restored to a1
//
// The processor context when calling cp_sleep is the one that will be
// restored by the PAL code when doing the restore. A0 contains the
// address at which execution will resume. We resume in this function so
// that SP gets readjusted to the callers value. However, we must be
// careful not to reference anything in our stack frame after a resume
// as that data was not saved to disk.
//
lda a0, do_return // address at which restore continues execution
ldq ra, KsRa(sp) // address to return to after continuing
ldil v0, 0 // return value on wakeup
call_pal cp_sleep // save PAL state
//
// v0 is now the PALmode (physical) address of the PALcode restore routine, i.e. where
// to jump to in PALmode.
//
stq v0, CxIntA2(t1) // it will be in a2
// Set the address to start up at when first entered (the swppal to enter PALmode).
lda t2, reentry // address of startup code below
stq t2, CxFir(t1) // store startup address in CONTEXT
//
// Set the address for swppal to transfer control to in PALmode. This must be in a0
// when swppal is executed.
//
lda t3, gorestore // address of transfer to restore below
sll t3, 33, t3 // clear high-order 33 bits to convert
srl t3, 33, t3 // to PALmode physical address
stq t3, CxIntA0(t1)
//
// Return.
//
ldq ra, KsRa(sp) // restore return address
do_return:
lda sp, SaveStateLength(sp) // deallocate stack frame
ret zero, (ra) // return
//
// This is where the OS Loader transfers control back to NT. The CONTEXT was
// set up to direct execution here with registers set as follows:
//
// a0 - PALmode address of code to be executed in PALmode (gorestore)
// a1 - pointer to the SleepData structure (returned by sleep)
// a2 - PALmode address of the restore routine (returned by sleep)
//
// All other registers are presently "don't care", but the code in OS Loader
// that transfers control should restore the entire CONTEXT so that it remains
// compatible even if this convention changes.
reentry:
#if defined(DBG_LEDS)
// LED display: F1
ldiq t0, 0xfffffc0000000000+0x87A0000180
ldil t1, 0xF1
stq t1, (t0)
mb
ldil t0, 166666666
1:
subl t0, 1, t0
bne t0, 1b
#endif
call_pal swppal // simply enter PALmode, transfer to
// following code
//
// Control is transferred here in PALmode by swppal. a1 contains the pointer
// to the SleepData structure, and a2 contains the PALmode address of the
// restore routine.
//
gorestore:
#if defined(DBG_LEDS)
// LED display: F2
ldiq t0, 0xfffffc0000000000+0x87A0000180
ldil t1, 0xF2
stq t1, (t0)
mb
ldil t0, 166666666
1:
subl t0, 1, t0
bne t0, 1b
#endif
bis a1, 0, a0 // restore needs SleepData pointer in a0
jmp (a2) // jump to restore routine
.end KeSaveStateForHibernate