test: npxnp.c Source File

Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

# npxnp.c

Go to the documentation of this file.

    00001 /*++
    00002
    00003 Copyright (c) 1989  Microsoft Corporation
    00004
    00005 Module Name:
    00006
    00007     npxnp.c
    00008
    00009 Abstract:
    00010
    00011     This module contains support for non-Flat mode NPX faults when
    00012     the application has it's CR0_EM bit clear.
    00013
    00014 Author:
    00015
    00016     Ken Reneris (kenr) 8-Dec-1994
    00017
    00018 Environment:
    00019
    00020     User Mode only
    00021
    00022 Revision History:
    00023
    00024 --*/
    00025
    00026
    00027 #include "csrdll.h"
    00028
    00029 static UCHAR MOD16[] = { 0, 1, 2, 0 };
    00030 static UCHAR MOD32[] = { 0, 1, 4, 0 };
    00031
    00032 UCHAR
    00033 NpxNpReadCSEip (
    00034     IN PCONTEXT Context
    00035     )
    00036 #pragma warning(disable:4035)
    00037 {
    00038     _asm {
    00039         push    es
    00040         mov     ecx, Context
    00041         mov     eax, [ecx] CONTEXT.SegCs
    00042         mov     es, ax
    00043         mov     eax, [ecx] CONTEXT.Eip
    00044         inc     dword ptr [ecx] CONTEXT.Eip     ; Advance EIP
    00045         mov     al, es:[eax]
    00046         pop     es
    00047     }
    00048 }
    00049 #pragma warning(default:4035)
    00050
    00051
    00052 VOID
    00053 NpxNpSkipInstruction (
    00054     IN PCONTEXT Context
    00055     )
    00056 /*++
    00057
    00058 Routine Description:
    00059
    00060     This functions gains control when the system has no installed
    00061     NPX support, but the thread has cleared it's EM bit in CR0.
    00062
    00063     The purpose of this function is to move the instruction
    00064     pointer forward over the current NPX instruction.
    00065
    00066 Enviroment:
    00067
    00068     16:16 mode
    00069
    00070 Arguments:
    00071
    00072 Return Value:
    00073
    00074 --*/
    00075 {
    00076     BOOLEAN     fPrefix;
    00077     UCHAR       ibyte, Mod, rm;
    00078     UCHAR       Address32Bits;
    00079     ULONG       CallerCs;
    00080
    00081     Address32Bits = 0;                          // assume called from 16:16
    00082
    00083     //
    00084     // Lookup and determine callers default mode
    00085     //
    00086
    00087     CallerCs = Context->SegCs;
    00088     _asm {
    00089         mov     eax, CallerCs
    00090         lar     eax, eax
    00091         test    eax, 400000h
    00092         jz      short IsDefault16Bit
    00093
    00094         mov     Address32Bits, 1
    00095
    00096 IsDefault16Bit:
    00097     }
    00098
    00099     //
    00100     // No sense in using a try-except since we are not on the
    00101     // correct stack.  A fault here could occur if the start
    00102     // of an NPX instruction is near the end of a selector, and the
    00103     // end of the instruction is past the selectors end.  This
    00104     // would kill the app anyway.
    00105     //
    00106
    00107     //
    00108     // Read any instruction prefixes
    00109     //
    00110
    00111     fPrefix = TRUE;
    00112     while (fPrefix) {
    00113         ibyte = NpxNpReadCSEip(Context);
    00114
    00115         switch (ibyte) {
    00116             case 0x2e:  // cs override, skip it
    00117             case 0x36:  // ss override, skip it
    00118             case 0x3e:  // ds override, skip it
    00119             case 0x26:  // es override, skip it
    00120             case 0x64:  // fs override, skip it
    00121             case 0x65:  // gs override, skip it
    00122             case 0x66:  // operand size override, skip it
    00123                 break;
    00124
    00125             case 0x67:
    00126                 // address size override
    00127                 Address32Bits ^= 1;
    00128                 break;
    00129
    00130             default:
    00131                 fPrefix = FALSE;
    00132                 break;
    00133         }
    00134     }
    00135
    00136     //
    00137     // Handle first byte of NPX instruction
    00138     //
    00139
    00140     if (ibyte == 0x9b) {
    00141
    00142         //
    00143         // FWait instruction - single byte opcode - all done
    00144         //
    00145
    00146         return;
    00147     }
    00148
    00149     if (ibyte < 0xD8 || ibyte > 0xDF) {
    00150
    00151         //
    00152         // Not an ESC instruction
    00153         //
    00154
    00155 #if DBG
    00156         DbgPrint ("P5_FPU_PATCH: 16: Not NPX ESC instruction\n");
    00157 #endif
    00158         return;
    00159     }
    00160
    00161     //
    00162     // Get ModR/M byte for NPX opcode
    00163     //
    00164
    00165     ibyte = NpxNpReadCSEip(Context);
    00166
    00167     if (ibyte > 0xbf) {
    00168         //
    00169         // Outside of ModR/M range for addressing, all done
    00170         //
    00171
    00172         return;
    00173     }
    00174
    00175     Mod = ibyte >> 6;
    00176     rm  = ibyte & 0x7;
    00177     if (Address32Bits) {
    00178         Context->Eip += MOD32 [Mod];
    00179         if (Mod == 0  &&  rm == 5) {
    00180             // disp 32
    00181             Context->Eip += 4;
    00182         }
    00183
    00184         //
    00185         // If SIB byte, read it
    00186         //
    00187
    00188         if (rm == 4) {
    00189             ibyte = NpxNpReadCSEip(Context);
    00190
    00191             if (Mod == 0  &&  (ibyte & 7) == 5) {
    00192                 // disp 32
    00193                 Context->Eip += 4;
    00194             }
    00195         }
    00196
    00197     } else {
    00198         Context->Eip += MOD16 [Mod];
    00199         if (Mod == 0  &&  rm == 6) {
    00200             // disp 16
    00201             Context->Eip += 2;
    00202         }
    00203     }
    00204 }