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

341 lines
9.6 KiB
C
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.

/*++
Copyright (c) 1995 Digital Equipment Corporation
Module Name:
byteem.c
Abstract:
This module implements the code necessary to emulate the new set of Alpha
byte and word instructions defined by ECO 81.
N.B. This file must be compiled without the use of byte/word instructions
to avoid fatal recursive exceptions.
Author:
Wim Colgate (colgate) 18-May-1995
Thomas Van Baak (tvb) 18-May-1995
Environment:
Kernel mode only.
Revision History:
--*/
#include "ki.h"
//
// Define function prototypes for emulation routines written in assembler.
//
VOID
KiInterlockedStoreByte (
IN PUCHAR Address,
IN UCHAR Data
);
VOID
KiInterlockedStoreWord (
IN PUSHORT Address,
IN USHORT Data
);
BOOLEAN
KiEmulateByteWord (
IN OUT PEXCEPTION_RECORD ExceptionRecord,
IN OUT PKEXCEPTION_FRAME ExceptionFrame,
IN OUT PKTRAP_FRAME TrapFrame
)
/*++
Routine Description:
This routine emulates Alpha instructions defined by ECO 81. This includes
the load byte unsigned, store byte, load word unsigned, store word, sign
extend byte, and sign extend word instructions.
If a misaligned word access is detected the illegal instruction exception
record is converted into data misalignment exception record, no emulation
is performed, and a value of FALSE is returned. It is expected that the
call to this function is followed by a check for a data misalignment
exception and a call to the data misalignment emulation function if
appropriate.
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.
Return Value:
A value of TRUE is returned if the instruction is successfully emulated,
otherwise a value of FALSE is returned.
--*/
{
ULONGLONG Data;
ULONGLONG EffectiveAddress;
PVOID ExceptionAddress;
ALPHA_INSTRUCTION Instruction;
KIRQL OldIrql;
KPROCESSOR_MODE PreviousMode;
//
// Save original exception address in case another exception occurs.
//
ExceptionAddress = ExceptionRecord->ExceptionAddress;
//
// 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 memory access was not from kernel mode then probe
// the effective address before performing the emulation.
//
//
// Capture previous mode from trap frame not current thread.
//
PreviousMode = (KPROCESSOR_MODE)(((PSR *)(&TrapFrame->Psr))->MODE);
try {
//
// Get faulting instruction and case on instruction type.
//
if (PreviousMode != KernelMode) {
ProbeForRead(ExceptionAddress,
sizeof(ALPHA_INSTRUCTION),
sizeof(ALPHA_INSTRUCTION));
}
Instruction = *((PALPHA_INSTRUCTION)ExceptionAddress);
switch (Instruction.Memory.Opcode) {
//
// Load/store operations.
//
case LDBU_OP :
case LDWU_OP :
case STB_OP :
case STW_OP :
//
// Compute effective address and if the address is non-canonical
// then change the exception code to STATUS_ACCESS_VIOLATION and
// return FALSE.
//
EffectiveAddress = (ULONGLONG)Instruction.Memory.MemDisp +
KiGetRegisterValue(Instruction.Memory.Rb,
ExceptionFrame,
TrapFrame);
if (EffectiveAddress != (ULONGLONG)(PVOID)EffectiveAddress) {
ExceptionRecord->ExceptionCode = STATUS_ACCESS_VIOLATION;
ExceptionRecord->NumberParameters = 0;
return FALSE;
}
//
// Case on individual load/store instruction type.
//
switch (Instruction.Memory.Opcode) {
//
// Load byte unsigned.
//
case LDBU_OP :
if (PreviousMode != KernelMode) {
ProbeForRead(EffectiveAddress,
sizeof(UCHAR),
sizeof(UCHAR));
}
Data = (ULONGLONG)*(PUCHAR)EffectiveAddress;
KiSetRegisterValue(Instruction.Memory.Ra,
Data,
ExceptionFrame,
TrapFrame);
break;
//
// Load word unsigned.
//
case LDWU_OP :
if (EffectiveAddress & 0x1) {
goto AlignmentFault;
}
if (PreviousMode != KernelMode) {
ProbeForRead((PUSHORT)EffectiveAddress,
sizeof(USHORT),
sizeof(UCHAR));
}
Data = (ULONGLONG)*(PUSHORT)EffectiveAddress;
KiSetRegisterValue(Instruction.Memory.Ra,
Data,
ExceptionFrame,
TrapFrame);
break;
//
// Store byte.
//
case STB_OP :
if (PreviousMode != KernelMode) {
ProbeForWrite((PUCHAR)EffectiveAddress,
sizeof(UCHAR),
sizeof(UCHAR));
}
Data = KiGetRegisterValue(Instruction.Memory.Ra,
ExceptionFrame,
TrapFrame);
KiInterlockedStoreByte((PUCHAR)EffectiveAddress,
(UCHAR)Data);
break;
//
// Store word.
//
case STW_OP :
if (EffectiveAddress & 0x1) {
goto AlignmentFault;
}
if (PreviousMode != KernelMode) {
ProbeForWrite((PUSHORT)EffectiveAddress,
sizeof(USHORT),
sizeof(UCHAR));
}
Data = KiGetRegisterValue(Instruction.Memory.Ra,
ExceptionFrame,
TrapFrame);
KiInterlockedStoreWord((PUSHORT)EffectiveAddress,
(USHORT)Data);
break;
}
break;
//
// Sign extend operations.
//
case SEXT_OP :
switch (Instruction.OpReg.Function) {
//
// Sign extend byte.
//
case SEXTB_FUNC :
Data = KiGetRegisterValue(Instruction.OpReg.Rb,
ExceptionFrame,
TrapFrame);
KiSetRegisterValue(Instruction.OpReg.Rc,
(ULONGLONG)(CHAR)Data,
ExceptionFrame,
TrapFrame);
break;
//
// Sign extend word.
//
case SEXTW_FUNC :
Data = KiGetRegisterValue(Instruction.OpReg.Rb,
ExceptionFrame,
TrapFrame);
KiSetRegisterValue(Instruction.OpReg.Rc,
(ULONGLONG)(SHORT)Data,
ExceptionFrame,
TrapFrame);
break;
//
// All other functions are not emulated.
//
default :
return FALSE;
}
break;
//
// All other instructions are not emulated.
//
default :
return FALSE;
}
#if 0
//
// Call out to profile interrupt if byte/word emulation profiling is
// active.
//
if (KiProfileByteWordEmulation != FALSE) {
if (++KiProfileByteWordEmulationCount >=
KiProfileByteWordEmulationInterval) {
KeRaiseIrql(PROFILE_LEVEL, &OldIrql);
KiProfileByteWordEmulationCount = 0;
KeProfileInterruptWithSource(TrapFrame,
ProfileByteWordEmulation);
KeLowerIrql(OldIrql);
}
}
#endif
TrapFrame->Fir += 4;
return TRUE;
} except (KiCopyInformation(ExceptionRecord,
(GetExceptionInformation())->ExceptionRecord)) {
//
// Preserve the original exception address.
//
ExceptionRecord->ExceptionAddress = ExceptionAddress;
return FALSE;
}
AlignmentFault :
//
// A misaligned word access has been encountered. Change the illegal
// instruction exception record into data misalignment exception record
// (the format is defined by PALcode) and return FALSE.
//
ExceptionRecord->ExceptionCode = STATUS_DATATYPE_MISALIGNMENT;
ExceptionRecord->NumberParameters = 3;
ExceptionRecord->ExceptionInformation[0] = Instruction.Memory.Opcode;
ExceptionRecord->ExceptionInformation[1] = Instruction.Memory.Ra;
ExceptionRecord->ExceptionInformation[2] = (ULONG)EffectiveAddress;
return FALSE;
}