NT4/private/ntos/ke/alpha/alignem.c
2020-09-30 17:12:29 +02:00

394 lines
9.7 KiB
C
Raw 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.

/*++
Copyright (c) 1991 Microsoft Corporation
Copyright (c) 1992 Digital Equipment Corporation
Module Name:
alignem.c
Abstract:
This module implements the code necessary to emulate unaligned data
references.
Author:
David N. Cutler (davec) 17-Jun-1991
Joe Notarangelo 14-May-1992
Environment:
Kernel mode only.
Revision History:
--*/
#include "ki.h"
//
// Function prototypes for emulation routines
//
ULONGLONG
KiEmulateLoadLong(
IN PULONG UnalignedAddress
);
ULONGLONG
KiEmulateLoadQuad(
IN PUQUAD UnalignedAddress
);
ULONGLONG
KiEmulateLoadFloatIEEESingle(
IN PULONG UnalignedAddress
);
ULONGLONG
KiEmulateLoadFloatIEEEDouble(
IN PUQUAD UnalignedAddress
);
VOID
KiEmulateStoreLong(
IN PULONG UnalignedAddress,
IN ULONGLONG Data
);
VOID
KiEmulateStoreQuad(
IN PUQUAD UnalignedAddress,
IN ULONGLONG Data
);
VOID
KiEmulateStoreFloatIEEESingle(
IN PULONG UnalignedAddress,
IN ULONGLONG Data
);
VOID
KiEmulateStoreFloatIEEEDouble(
IN PUQUAD UnalignedAddress,
IN ULONGLONG Data
);
BOOLEAN
KiEmulateReference (
IN OUT PEXCEPTION_RECORD ExceptionRecord,
IN OUT PKEXCEPTION_FRAME ExceptionFrame,
IN OUT PKTRAP_FRAME TrapFrame,
IN BOOLEAN QuadwordOnly
)
/*++
Routine Description:
Routine emulates an unaligned data reference from user part
of the address space.
Arguments:
ExceptionRecord - Supplies a pointer to the exception record.
ExceptionFrame - Supplies a pointer to an exception frame.
TrapFrame - Supplies a pointer to a trap frame
QuadwordOnly - Supplies a boolean which controls whether both longword
and quadword references are to be emulated or quadword references
only.
Return Value:
True is returned if reference is successfully emulated,
otherwise False is returned.
--*/
{
ULONGLONG Data;
PVOID EffectiveAddress;
PVOID ExceptionAddress;
ULONG Fa;
ULONG Opcode;
KPROCESSOR_MODE PreviousMode;
ULONG Ra;
KIRQL OldIrql;
//
// Call out to profile interrupt if alignment profiling is active
//
if (KiProfileAlignmentFixup) {
if (++KiProfileAlignmentFixupCount >= KiProfileAlignmentFixupInterval) {
KeRaiseIrql(PROFILE_LEVEL, &OldIrql);
KiProfileAlignmentFixupCount = 0;
KeProfileInterruptWithSource(TrapFrame, ProfileAlignmentFixup);
KeLowerIrql(OldIrql);
}
}
//
// Save original exception address in case another exception occurs
//
ExceptionAddress = ExceptionRecord->ExceptionAddress;
//
// The ExceptionInformation in the ExceptionRecord has already
// recorded information we need to emulate the access.
//
// ExceptionInformation:
// [0] = opcode
// [1] = destination register
// [2] = effective address of access
Opcode = ExceptionRecord->ExceptionInformation[0];
Ra = ExceptionRecord->ExceptionInformation[1];
Fa = Ra + 32; // convert to floating register name for floating opcodes
EffectiveAddress = (PVOID)ExceptionRecord->ExceptionInformation[2];
//
// Capture previous mode from trap frame not current thread.
//
PreviousMode = (KPROCESSOR_MODE)(((PSR *)(&TrapFrame->Psr))->MODE);
//
// Any exception that occurs during the attempted emulation will cause
// the emulation to be aborted. The new exception code and information
// will be copied to the original exception record and FALSE will be
// returned. If the unaligned access was not from kernel mode then
// probe the effective address before performing the emulation.
//
try {
switch (Opcode) {
//
// load longword
//
case LDL_OP:
if (QuadwordOnly != FALSE) {
return FALSE;
}
if( PreviousMode != KernelMode ){
ProbeForRead( EffectiveAddress,
sizeof(LONG),
sizeof(UCHAR) );
}
Data = KiEmulateLoadLong( EffectiveAddress );
KiSetRegisterValue( Ra,
Data,
ExceptionFrame,
TrapFrame );
break;
//
// load quadword
//
case LDQ_OP:
if( PreviousMode != KernelMode ){
ProbeForRead( EffectiveAddress,
sizeof(LONGLONG),
sizeof(UCHAR) );
}
Data = KiEmulateLoadQuad( EffectiveAddress );
KiSetRegisterValue( Ra,
Data,
ExceptionFrame,
TrapFrame );
break;
//
// load IEEE single float
//
case LDS_OP:
if (QuadwordOnly != FALSE) {
return FALSE;
}
if( PreviousMode != KernelMode ){
ProbeForRead( EffectiveAddress,
sizeof(float),
sizeof(UCHAR) );
}
Data = KiEmulateLoadFloatIEEESingle( EffectiveAddress );
KiSetRegisterValue( Fa,
Data,
ExceptionFrame,
TrapFrame );
break;
//
// load IEEE double float
//
case LDT_OP:
if( PreviousMode != KernelMode ){
ProbeForRead( EffectiveAddress,
sizeof(DOUBLE),
sizeof(UCHAR) );
}
Data = KiEmulateLoadFloatIEEEDouble( EffectiveAddress );
KiSetRegisterValue( Fa,
Data,
ExceptionFrame,
TrapFrame );
break;
//
// Load word unsigned.
//
case LDWU_OP :
if (QuadwordOnly != FALSE) {
return FALSE;
}
if (PreviousMode != KernelMode) {
ProbeForRead(EffectiveAddress,
sizeof(SHORT),
sizeof(UCHAR));
}
Data = (ULONGLONG)*(UNALIGNED USHORT *)EffectiveAddress;
KiSetRegisterValue(Ra,
Data,
ExceptionFrame,
TrapFrame);
break;
//
// store longword
//
case STL_OP:
if (QuadwordOnly != FALSE) {
return FALSE;
}
if( PreviousMode != KernelMode ){
ProbeForWrite( EffectiveAddress,
sizeof(LONG),
sizeof(UCHAR) );
}
Data = KiGetRegisterValue( Ra,
ExceptionFrame,
TrapFrame );
KiEmulateStoreLong( EffectiveAddress, (ULONG)Data );
break;
//
// store quadword
//
case STQ_OP:
if( PreviousMode != KernelMode ){
ProbeForWrite( EffectiveAddress,
sizeof(LONGLONG),
sizeof(UCHAR) );
}
Data = KiGetRegisterValue( Ra,
ExceptionFrame,
TrapFrame );
KiEmulateStoreQuad( EffectiveAddress, Data );
break;
//
// store IEEE float single
//
case STS_OP:
if (QuadwordOnly != FALSE) {
return FALSE;
}
if( PreviousMode != KernelMode ){
ProbeForWrite( EffectiveAddress,
sizeof(float),
sizeof(UCHAR) );
}
Data = KiGetRegisterValue( Fa,
ExceptionFrame,
TrapFrame );
KiEmulateStoreFloatIEEESingle( EffectiveAddress, Data );
break;
//
// store IEEE float double
//
case STT_OP:
if( PreviousMode != KernelMode ){
ProbeForWrite( EffectiveAddress,
sizeof(DOUBLE),
sizeof(UCHAR) );
}
Data = KiGetRegisterValue( Fa,
ExceptionFrame,
TrapFrame );
KiEmulateStoreFloatIEEEDouble( EffectiveAddress, Data );
break;
//
// Store word.
//
case STW_OP :
if (QuadwordOnly != FALSE) {
return FALSE;
}
if (PreviousMode != KernelMode) {
ProbeForWrite(EffectiveAddress,
sizeof(SHORT),
sizeof(UCHAR));
}
Data = KiGetRegisterValue(Ra,
ExceptionFrame,
TrapFrame);
*(UNALIGNED USHORT *)EffectiveAddress = (USHORT)Data;
break;
//
// all other instructions are not emulated
//
default:
return FALSE;
}
TrapFrame->Fir += 4;
return TRUE;
} except (KiCopyInformation(ExceptionRecord,
(GetExceptionInformation())->ExceptionRecord)) {
//
// Preserve the original exception address
//
ExceptionRecord->ExceptionAddress = ExceptionAddress;
return FALSE;
}
}