|
|
/*++
Copyright (c) 1989 Microsoft Corporation
Module Name:
npxnp.c
Abstract:
This module contains support for non-Flat mode NPX faults when the application has it's CR0_EM bit clear.
Author:
Ken Reneris (kenr) 8-Dec-1994
Environment:
User Mode only
Revision History:
--*/
#include "csrdll.h"
static UCHAR MOD16[] = { 0, 1, 2, 0 }; static UCHAR MOD32[] = { 0, 1, 4, 0 };
UCHAR NpxNpReadCSEip ( IN PCONTEXT Context ) #pragma warning(disable:4035)
{ _asm { push es mov ecx, Context mov eax, [ecx] CONTEXT.SegCs mov es, ax mov eax, [ecx] CONTEXT.Eip inc dword ptr [ecx] CONTEXT.Eip ; Advance EIP mov al, es:[eax] pop es } } #pragma warning(default:4035)
VOID NpxNpSkipInstruction ( IN PCONTEXT Context ) /*++
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:
16:16 mode
Arguments:
Return Value:
--*/ { BOOLEAN fPrefix; UCHAR ibyte, Mod, rm; UCHAR Address32Bits; ULONG CallerCs;
Address32Bits = 0; // assume called from 16:16
//
// Lookup and determine callers default mode
//
CallerCs = Context->SegCs; _asm { mov eax, CallerCs lar eax, eax test eax, 400000h jz short IsDefault16Bit
mov Address32Bits, 1
IsDefault16Bit: }
//
// No sense in using a try-except since we are not on the
// correct stack. A fault here could occur if the start
// of an NPX instruction is near the end of a selector, and the
// end of the instruction is past the selectors end. This
// would kill the app anyway.
//
//
// Read any instruction prefixes
//
fPrefix = TRUE; while (fPrefix) { ibyte = NpxNpReadCSEip(Context);
switch (ibyte) { case 0x2e: // cs override, skip it
case 0x36: // ss override, skip it
case 0x3e: // ds override, skip it
case 0x26: // es override, skip it
case 0x64: // fs override, skip it
case 0x65: // gs override, skip it
case 0x66: // operand size override, skip it
break;
case 0x67: // address size override
Address32Bits ^= 1; break;
default: fPrefix = FALSE; break; } }
//
// Handle first byte of NPX instruction
//
if (ibyte == 0x9b) {
//
// FWait instruction - single byte opcode - all done
//
return; }
if (ibyte < 0xD8 || ibyte > 0xDF) {
//
// Not an ESC instruction
//
#if DBG
DbgPrint ("P5_FPU_PATCH: 16: Not NPX ESC instruction\n"); #endif
return; }
//
// Get ModR/M byte for NPX opcode
//
ibyte = NpxNpReadCSEip(Context);
if (ibyte > 0xbf) { //
// Outside of ModR/M range for addressing, all done
//
return; }
Mod = ibyte >> 6; rm = ibyte & 0x7; if (Address32Bits) { Context->Eip += MOD32 [Mod]; if (Mod == 0 && rm == 5) { // disp 32
Context->Eip += 4; }
//
// If SIB byte, read it
//
if (rm == 4) { ibyte = NpxNpReadCSEip(Context);
if (Mod == 0 && (ibyte & 7) == 5) { // disp 32
Context->Eip += 4; } }
} else { Context->Eip += MOD16 [Mod]; if (Mod == 0 && rm == 6) { // disp 16
Context->Eip += 2; } } }
|