Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

204 lines
3.9 KiB

  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. npxnp.c
  5. Abstract:
  6. This module contains support for non-Flat mode NPX faults when
  7. the application has it's CR0_EM bit clear.
  8. Author:
  9. Ken Reneris (kenr) 8-Dec-1994
  10. Environment:
  11. User Mode only
  12. Revision History:
  13. --*/
  14. #include "csrdll.h"
  15. static UCHAR MOD16[] = { 0, 1, 2, 0 };
  16. static UCHAR MOD32[] = { 0, 1, 4, 0 };
  17. UCHAR
  18. NpxNpReadCSEip (
  19. IN PCONTEXT Context
  20. )
  21. #pragma warning(disable:4035)
  22. {
  23. _asm {
  24. push es
  25. mov ecx, Context
  26. mov eax, [ecx] CONTEXT.SegCs
  27. mov es, ax
  28. mov eax, [ecx] CONTEXT.Eip
  29. inc dword ptr [ecx] CONTEXT.Eip ; Advance EIP
  30. mov al, es:[eax]
  31. pop es
  32. }
  33. }
  34. #pragma warning(default:4035)
  35. VOID
  36. NpxNpSkipInstruction (
  37. IN PCONTEXT Context
  38. )
  39. /*++
  40. Routine Description:
  41. This functions gains control when the system has no installed
  42. NPX support, but the thread has cleared it's EM bit in CR0.
  43. The purpose of this function is to move the instruction
  44. pointer forward over the current NPX instruction.
  45. Enviroment:
  46. 16:16 mode
  47. Arguments:
  48. Return Value:
  49. --*/
  50. {
  51. BOOLEAN fPrefix;
  52. UCHAR ibyte, Mod, rm;
  53. UCHAR Address32Bits;
  54. ULONG CallerCs;
  55. Address32Bits = 0; // assume called from 16:16
  56. //
  57. // Lookup and determine callers default mode
  58. //
  59. CallerCs = Context->SegCs;
  60. _asm {
  61. mov eax, CallerCs
  62. lar eax, eax
  63. test eax, 400000h
  64. jz short IsDefault16Bit
  65. mov Address32Bits, 1
  66. IsDefault16Bit:
  67. }
  68. //
  69. // No sense in using a try-except since we are not on the
  70. // correct stack. A fault here could occur if the start
  71. // of an NPX instruction is near the end of a selector, and the
  72. // end of the instruction is past the selectors end. This
  73. // would kill the app anyway.
  74. //
  75. //
  76. // Read any instruction prefixes
  77. //
  78. fPrefix = TRUE;
  79. while (fPrefix) {
  80. ibyte = NpxNpReadCSEip(Context);
  81. switch (ibyte) {
  82. case 0x2e: // cs override, skip it
  83. case 0x36: // ss override, skip it
  84. case 0x3e: // ds override, skip it
  85. case 0x26: // es override, skip it
  86. case 0x64: // fs override, skip it
  87. case 0x65: // gs override, skip it
  88. case 0x66: // operand size override, skip it
  89. break;
  90. case 0x67:
  91. // address size override
  92. Address32Bits ^= 1;
  93. break;
  94. default:
  95. fPrefix = FALSE;
  96. break;
  97. }
  98. }
  99. //
  100. // Handle first byte of NPX instruction
  101. //
  102. if (ibyte == 0x9b) {
  103. //
  104. // FWait instruction - single byte opcode - all done
  105. //
  106. return;
  107. }
  108. if (ibyte < 0xD8 || ibyte > 0xDF) {
  109. //
  110. // Not an ESC instruction
  111. //
  112. #if DBG
  113. DbgPrint ("P5_FPU_PATCH: 16: Not NPX ESC instruction\n");
  114. #endif
  115. return;
  116. }
  117. //
  118. // Get ModR/M byte for NPX opcode
  119. //
  120. ibyte = NpxNpReadCSEip(Context);
  121. if (ibyte > 0xbf) {
  122. //
  123. // Outside of ModR/M range for addressing, all done
  124. //
  125. return;
  126. }
  127. Mod = ibyte >> 6;
  128. rm = ibyte & 0x7;
  129. if (Address32Bits) {
  130. Context->Eip += MOD32 [Mod];
  131. if (Mod == 0 && rm == 5) {
  132. // disp 32
  133. Context->Eip += 4;
  134. }
  135. //
  136. // If SIB byte, read it
  137. //
  138. if (rm == 4) {
  139. ibyte = NpxNpReadCSEip(Context);
  140. if (Mod == 0 && (ibyte & 7) == 5) {
  141. // disp 32
  142. Context->Eip += 4;
  143. }
  144. }
  145. } else {
  146. Context->Eip += MOD16 [Mod];
  147. if (Mod == 0 && rm == 6) {
  148. // disp 16
  149. Context->Eip += 2;
  150. }
  151. }
  152. }