Leaked source code of windows server 2003
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.

468 lines
8.1 KiB

  1. /*++
  2. Copyright (c) 1994 Microsoft Corporation
  3. Module Name:
  4. ctrlops.c
  5. Abstract:
  6. This module implements the code to emulate call, retunr, and various
  7. control operations.
  8. Author:
  9. David N. Cutler (davec) 10-Nov-1994
  10. Environment:
  11. Kernel mode only.
  12. Revision History:
  13. --*/
  14. #include "nthal.h"
  15. #include "emulate.h"
  16. VOID
  17. XmCallOp (
  18. PRXM_CONTEXT P
  19. )
  20. /*++
  21. Routine Description:
  22. This function emulates a call opcode.
  23. Arguments:
  24. P - Supplies a pointer to an emulator context structure.
  25. Return Value:
  26. None.
  27. --*/
  28. {
  29. ULONG Target;
  30. ULONG Source;
  31. //
  32. // Save the target address, push the current segment, if required, and
  33. // push the current IP, set the destination segment, if required, and
  34. // set the new IP.
  35. //
  36. Target = P->DstValue.Long;
  37. if (P->OpsizePrefixActive != FALSE) {
  38. P->DataType = LONG_DATA;
  39. } else {
  40. P->DataType = WORD_DATA;
  41. }
  42. if ((P->CurrentOpcode == 0x9a) || (P->FunctionIndex != X86_CALL_OP)) {
  43. XmPushStack(P, P->SegmentRegister[CS]);
  44. XmPushStack(P, P->Eip);
  45. P->SegmentRegister[CS] = P->DstSegment;
  46. } else {
  47. XmPushStack(P, P->Eip);
  48. }
  49. P->Eip = Target;
  50. XmTraceJumps(P);
  51. return;
  52. }
  53. VOID
  54. XmEnterOp (
  55. PRXM_CONTEXT P
  56. )
  57. /*++
  58. Routine Description:
  59. This function emulates an enter opcode.
  60. Arguments:
  61. P - Supplies a pointer to an emulator context structure.
  62. Return Value:
  63. None.
  64. --*/
  65. {
  66. ULONG Allocate;
  67. ULONG Frame;
  68. ULONG Number;
  69. //
  70. // set the number of bytes to allocate on the stack and the number
  71. // of nesting levels.
  72. //
  73. Allocate = P->SrcValue.Long;
  74. Number = P->DstValue.Long;
  75. //
  76. // Set the data type and save the frame pointer on the stack.
  77. //
  78. if (P->OpsizePrefixActive != FALSE) {
  79. P->DataType = LONG_DATA;
  80. XmPushStack(P, P->Gpr[EBP].Exx);
  81. Frame = P->Gpr[ESP].Exx;
  82. } else {
  83. P->DataType = WORD_DATA;
  84. XmPushStack(P, P->Gpr[BP].Xx);
  85. Frame = P->Gpr[SP].Xx;
  86. }
  87. //
  88. // Save the current stack pointer and push parameters on the stack.
  89. //
  90. if (Number != 0) {
  91. //
  92. // If the level number is not one, then raise an exception.
  93. //
  94. // N.B. Level numbers greater than one are not supported.
  95. //
  96. if (Number != 1) {
  97. longjmp(&P->JumpBuffer[0], XM_ILLEGAL_LEVEL_NUMBER);
  98. }
  99. XmPushStack(P, Frame);
  100. }
  101. //
  102. // Allocate local storage on stack.
  103. //
  104. if (P->OpsizePrefixActive != FALSE) {
  105. P->Gpr[EBP].Exx = Frame;
  106. P->Gpr[ESP].Exx = P->Gpr[ESP].Exx - Allocate;
  107. } else {
  108. P->Gpr[BP].Xx = (USHORT)Frame;
  109. P->Gpr[SP].Xx = (USHORT)(P->Gpr[SP].Xx - Allocate);
  110. }
  111. return;
  112. }
  113. VOID
  114. XmHltOp (
  115. PRXM_CONTEXT P
  116. )
  117. /*++
  118. Routine Description:
  119. This function emulates a hlt opcode.
  120. Arguments:
  121. P - Supplies a pointer to an emulator context structure.
  122. Return Value:
  123. None.
  124. --*/
  125. {
  126. //
  127. // Halt instructions are not supported by the emulator.
  128. //
  129. longjmp(&P->JumpBuffer[0], XM_HALT_INSTRUCTION);
  130. return;
  131. }
  132. VOID
  133. XmIntOp (
  134. PRXM_CONTEXT P
  135. )
  136. /*++
  137. Routine Description:
  138. This function emulates an int opcode.
  139. Arguments:
  140. P - Supplies a pointer to an emulator context structure.
  141. Return Value:
  142. None.
  143. --*/
  144. {
  145. ULONG Number;
  146. PULONG Vector;
  147. //
  148. // If the int instruction is an int 3, then set the interrupt vector
  149. // to 3. Otherwise, if the int instruction is an into, then set the
  150. // vector to 4 if OF is set. use the source interrupt vector.
  151. //
  152. if (P->OpsizePrefixActive != FALSE) {
  153. P->DataType = LONG_DATA;
  154. } else {
  155. P->DataType = WORD_DATA;
  156. }
  157. if (P->CurrentOpcode == 0xcc) {
  158. Number = 3;
  159. } else if (P->CurrentOpcode == 0xce) {
  160. if (P->Eflags.EFLAG_OF == 0) {
  161. return;
  162. }
  163. Number = 4;
  164. } else {
  165. Number = P->SrcValue.Byte;
  166. }
  167. //
  168. // If the vector number is 0x42, then nop the interrupt. This is the
  169. // standard EGA video driver entry point in a PC's motherboard BIOS
  170. // for which there is no code.
  171. //
  172. #if !defined(_PURE_EMULATION_)
  173. if (Number == 0x42) {
  174. return;
  175. }
  176. #endif
  177. //
  178. // If the vector number is 0x1a, then attempt to emulate the PCI BIOS
  179. // if it is enabled.
  180. //
  181. #if !defined(_PURE_EMULATION_)
  182. if ((Number == 0x1a) && (XmExecuteInt1a(P) != FALSE)) {
  183. return;
  184. }
  185. #endif
  186. //
  187. // Push the current flags, code segment, and EIP on the stack.
  188. //
  189. XmPushStack(P, P->AllFlags);
  190. XmPushStack(P, P->SegmentRegister[CS]);
  191. XmPushStack(P, P->Eip);
  192. //
  193. // Set the new coded segment and IP from the specified interrupt
  194. // vector.
  195. //
  196. Vector = (PULONG)(P->TranslateAddress)(0, 0);
  197. P->SegmentRegister[CS] = (USHORT)(Vector[Number] >> 16);
  198. P->Eip = (USHORT)(Vector[Number] & 0xffff);
  199. XmTraceJumps(P);
  200. return;
  201. }
  202. VOID
  203. XmIretOp (
  204. PRXM_CONTEXT P
  205. )
  206. /*++
  207. Routine Description:
  208. This function emulates an iret opcode.
  209. Arguments:
  210. P - Supplies a pointer to an emulator context structure.
  211. Return Value:
  212. None.
  213. --*/
  214. {
  215. //
  216. // Set the data type and restore the return address, code segment,
  217. // and flags.
  218. //
  219. if (P->OpsizePrefixActive != FALSE) {
  220. P->DataType = LONG_DATA;
  221. } else {
  222. P->DataType = WORD_DATA;
  223. }
  224. P->Eip = XmPopStack(P);
  225. P->SegmentRegister[CS] = (USHORT)XmPopStack(P);
  226. P->AllFlags = XmPopStack(P);
  227. XmTraceJumps(P);
  228. //
  229. // Check for emulator exit conditions.
  230. //
  231. if ((P->Eip == 0xffff) && (P->SegmentRegister[CS] == 0xffff)) {
  232. longjmp(&P->JumpBuffer[0], XM_SUCCESS);
  233. }
  234. return;
  235. }
  236. VOID
  237. XmLeaveOp (
  238. PRXM_CONTEXT P
  239. )
  240. /*++
  241. Routine Description:
  242. This function emulates a leave opcode.
  243. Arguments:
  244. P - Supplies a pointer to an emulator context structure.
  245. Return Value:
  246. None.
  247. --*/
  248. {
  249. //
  250. // Set the data type, restore the stack pointer, and restore the frame
  251. // pointer.
  252. //
  253. if (P->OpsizePrefixActive != FALSE) {
  254. P->DataType = LONG_DATA;
  255. P->Gpr[ESP].Exx = P->Gpr[EBP].Exx;
  256. P->Gpr[EBP].Exx = XmPopStack(P);
  257. } else {
  258. P->DataType = WORD_DATA;
  259. P->Gpr[SP].Xx = P->Gpr[BP].Xx;
  260. P->Gpr[BP].Xx = (USHORT)XmPopStack(P);
  261. }
  262. return;
  263. }
  264. VOID
  265. XmRetOp (
  266. PRXM_CONTEXT P
  267. )
  268. /*++
  269. Routine Description:
  270. This function emulates a ret opcode.
  271. Arguments:
  272. P - Supplies a pointer to an emulator context structure.
  273. Return Value:
  274. None.
  275. --*/
  276. {
  277. ULONG Adjust;
  278. //
  279. // Compute the number of bytes that are to be removed from the stack
  280. // after having removed the return address and optionally the new CS
  281. // segment value.
  282. //
  283. if ((P->CurrentOpcode & 0x1) == 0) {
  284. Adjust = XmGetWordImmediate(P);
  285. } else {
  286. Adjust = 0;
  287. }
  288. //
  289. // Remove the return address from the stack and set the new IP.
  290. //
  291. if (P->OpsizePrefixActive != FALSE) {
  292. P->DataType = LONG_DATA;
  293. } else {
  294. P->DataType = WORD_DATA;
  295. }
  296. P->Eip = XmPopStack(P);
  297. //
  298. // If the current opcode is a far return, then remove the new CS segment
  299. // value from the stack.
  300. //
  301. if ((P->CurrentOpcode & 0x8) != 0) {
  302. P->SegmentRegister[CS] = (USHORT)XmPopStack(P);
  303. }
  304. //
  305. // Remove the specified number of bytes from the stack.
  306. //
  307. P->Gpr[ESP].Exx += Adjust;
  308. XmTraceJumps(P);
  309. //
  310. // Check for emulator exit conditions.
  311. //
  312. if ((P->Eip == 0xffff) && (P->SegmentRegister[CS] == 0xffff)) {
  313. longjmp(&P->JumpBuffer[0], XM_SUCCESS);
  314. }
  315. return;
  316. }