NT4/private/ntos/vdm/i386/vdmnpx.c
2020-09-30 17:12:29 +02:00

210 lines
4.4 KiB
C

/*++
Copyright (c) 1991 Microsoft Corporation
Module Name:
vdmnpx.c
Abstract:
This module contains the support for Vdm use of the npx.
Author:
Dave Hastings (daveh) 02-Feb-1992
Revision History:
18-Dec-1992 sudeepb Tuned all the routines for performance
--*/
#include <ntos.h>
#include <vdmntos.h>
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, VdmDispatchIRQ13)
#pragma alloc_text(PAGE, VdmSkipNpxInstruction)
#endif
static UCHAR MOD16[] = { 0, 1, 2, 0 };
static UCHAR MOD32[] = { 0, 1, 4, 0 };
UCHAR VdmUserCr0MapIn[] = {
/* !EM !MP */ 0,
/* !EM MP */ CR0_PE, // Don't set MP, but shadow users MP setting
/* EM !MP */ CR0_EM,
/* EM MP */ CR0_EM | CR0_MP
};
UCHAR VdmUserCr0MapOut[] = {
/* !EM !MP !PE */ 0,
/* !EM !MP PE */ CR0_MP,
/* !EM MP !PE */ CR0_MP, // setting not valid
/* !EM MP PE */ CR0_MP, // setting not valid
/* EM !MP !PE */ CR0_EM,
/* EM !MP PE */ CR0_EM | CR0_MP, // setting not valid
/* EM MP !PE */ CR0_EM | CR0_MP,
/* EM MP PE */ CR0_EM | CR0_MP // setting not valid
};
BOOLEAN
VdmDispatchIRQ13(
PKTRAP_FRAME TrapFrame
)
/*++
aRoutine Description:
This routine reflects an IRQ 13 event to the usermode monitor for this
vdm. The IRQ 13 must be reflected to usermode, so that it can properly
be raised as an interrupt through the virtual PIC.
Arguments:
none
Return Value:
TRUE if the event was reflected
FALSE if not
--*/
{
EXCEPTION_RECORD ExceptionRecord;
PVDM_TIB VdmTib;
BOOLEAN Success;
PAGED_CODE();
Success = TRUE;
try {
VdmTib = NtCurrentTeb()->Vdm;
VdmTib->EventInfo.Event = VdmIrq13;
VdmTib->EventInfo.InstructionSize = 0L;
} except(EXCEPTION_EXECUTE_HANDLER) {
ExceptionRecord.ExceptionCode = GetExceptionCode();
ExceptionRecord.ExceptionFlags = 0;
ExceptionRecord.NumberParameters = 0;
ExRaiseException(&ExceptionRecord);
Success = FALSE;
}
if (Success) { // insure that we do not redispatch an exception
VdmEndExecution(TrapFrame,VdmTib);
}
return TRUE;
}
BOOLEAN
VdmSkipNpxInstruction(
PKTRAP_FRAME TrapFrame,
ULONG Address32Bits,
PUCHAR istream,
ULONG InstructionSize
)
/*++
Routine Description:
This functions gains control when the system has no installed
NPX support, but the thread has cleared it's EM bit in CR0.
The purpose of this function is to move the instruction
pointer forward over the current NPX instruction.
Enviroment:
V86 MODE ONLY, first opcode byte already verified to be 0xD8 - 0xDF.
Arguments:
Return Value:
TRUE if trap frame was modified to skip the NPX instruction
--*/
{
UCHAR ibyte, Mod, rm;
ASSERT (!KeI386NpxPresent);
//
// This NPX instruction should be skipped
//
try {
//
// Get ModR/M byte for NPX opcode
//
istream += 1;
ibyte = *istream;
InstructionSize += 1;
if (ibyte > 0xbf) {
//
// Outside of ModR/M range for addressing, all done
//
goto try_exit;
}
Mod = ibyte >> 6;
rm = ibyte & 0x7;
if (Address32Bits) {
InstructionSize += MOD32 [Mod];
if (Mod == 0 && rm == 5) {
// disp 32
InstructionSize += 4;
}
//
// If SIB byte, read it
//
if (rm == 4) {
istream += 1;
ibyte = *istream;
InstructionSize += 1;
if (Mod == 0 && (ibyte & 7) == 5) {
// disp 32
InstructionSize += 4;
}
}
} else {
InstructionSize += MOD16 [Mod];
if (Mod == 0 && rm == 6) {
// disp 16
InstructionSize += 2;
}
}
try_exit: ;
} except (EXCEPTION_EXECUTE_HANDLER) {
//
// Some sort of fault !?
//
#if DBG
DbgPrint ("P5_FPU_PATCH: V86: Fault occured\n");
#endif
return FALSE;
}
//
// Adjust Eip to skip NPX instruction
//
TrapFrame->Eip += InstructionSize;
TrapFrame->Eip &= 0xffff;
return TRUE;
}