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.

3158 lines
66 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. ia32emul.c
  5. Abstract:
  6. This module implements an x86 instruction decoder and emulator.
  7. Author:
  8. Samer Arafeh (samera) 30-Oct-2000
  9. Environment:
  10. Kernel mode only.
  11. Revision History:
  12. --*/
  13. #include "ki.h"
  14. #include "ia32def.h"
  15. #include "wow64t.h"
  16. #if DBG
  17. BOOLEAN KiIa32InstructionEmulationDbg = 0;
  18. #endif
  19. #define KiIa32GetX86Eflags(efl) efl.Value = __getReg(CV_IA64_AR24)
  20. #define KiIa32SetX86Eflags(efl) __setReg(CV_IA64_AR24, efl.Value)
  21. #define IA32_GETEFLAGS_CF(efl) (efl & 0x01UI64)
  22. //
  23. // Ia32 instruction handlers
  24. //
  25. NTSTATUS
  26. KiIa32InstructionAdc (
  27. IN PKTRAP_FRAME TrapFrame,
  28. IN PIA32_INSTRUCTION Instruction
  29. );
  30. NTSTATUS
  31. KiIa32InstructionAdd (
  32. IN PKTRAP_FRAME TrapFrame,
  33. IN PIA32_INSTRUCTION Instruction
  34. );
  35. NTSTATUS
  36. KiIa32InstructionArithmeticBitwiseHelper (
  37. IN PKTRAP_FRAME TrapFrame,
  38. IN PIA32_INSTRUCTION Instruction
  39. );
  40. NTSTATUS
  41. KiIa32InstructionBitTestHelper (
  42. IN PKTRAP_FRAME TrapFrame,
  43. IN PIA32_INSTRUCTION Instruction
  44. );
  45. NTSTATUS
  46. KiIa32InstructionOneParamHelper (
  47. IN PKTRAP_FRAME TrapFrame,
  48. IN PIA32_INSTRUCTION Instruction
  49. );
  50. NTSTATUS
  51. KiIa32InstructionXadd (
  52. IN PKTRAP_FRAME TrapFrame,
  53. IN PIA32_INSTRUCTION Instruction
  54. );
  55. NTSTATUS
  56. KiIa32InstructionXchg (
  57. IN PKTRAP_FRAME TrapFrame,
  58. IN PIA32_INSTRUCTION Instruction
  59. );
  60. NTSTATUS
  61. KiIa32InstructionCmpXchg (
  62. IN PKTRAP_FRAME TrapFrame,
  63. IN PIA32_INSTRUCTION Instruction
  64. );
  65. NTSTATUS
  66. KiIa32InstructionCmpXchg8b (
  67. IN PKTRAP_FRAME TrapFrame,
  68. IN PIA32_INSTRUCTION Instruction
  69. );
  70. NTSTATUS
  71. KiIa32InstructionMoveSeg (
  72. IN PKTRAP_FRAME TrapFrame,
  73. IN PIA32_INSTRUCTION Instruction
  74. );
  75. //
  76. // Opcode Ids
  77. //
  78. typedef enum _IA32_OPCODE
  79. {
  80. Ia32_Adc,
  81. Ia32_Add,
  82. Ia32_And,
  83. Ia32_Bt,
  84. Ia32_Btc,
  85. Ia32_Btr,
  86. Ia32_Bts,
  87. Ia32_Cmpxchg,
  88. Ia32_Cmpxchg8b,
  89. Ia32_Dec,
  90. Ia32_Inc,
  91. Ia32_Neg,
  92. Ia32_Not,
  93. Ia32_Or,
  94. Ia32_Sbb,
  95. Ia32_Sub,
  96. Ia32_Xadd,
  97. Ia32_Xchg,
  98. Ia32_Xor,
  99. Ia32_MovToSeg,
  100. //
  101. // This needs always to be the last element
  102. //
  103. Ia32_LastOpcode
  104. } IA32_OPCODE;
  105. //
  106. // Array of Ia32 instruction handlers
  107. // NOTE : The following table must be in sync with the above enum.
  108. //
  109. typedef NTSTATUS (*IA32_INSTRUCTION_HANDLER) (PKTRAP_FRAME, PIA32_INSTRUCTION);
  110. IA32_INSTRUCTION_HANDLER KiIa32InstructionHandler [] =
  111. {
  112. KiIa32InstructionAdc,
  113. KiIa32InstructionAdd,
  114. KiIa32InstructionArithmeticBitwiseHelper,
  115. KiIa32InstructionBitTestHelper,
  116. KiIa32InstructionBitTestHelper,
  117. KiIa32InstructionBitTestHelper,
  118. KiIa32InstructionBitTestHelper,
  119. KiIa32InstructionCmpXchg,
  120. KiIa32InstructionCmpXchg8b,
  121. KiIa32InstructionOneParamHelper,
  122. KiIa32InstructionOneParamHelper,
  123. KiIa32InstructionOneParamHelper,
  124. KiIa32InstructionOneParamHelper,
  125. KiIa32InstructionArithmeticBitwiseHelper,
  126. KiIa32InstructionAdc,
  127. KiIa32InstructionAdd,
  128. KiIa32InstructionXadd,
  129. KiIa32InstructionXchg,
  130. KiIa32InstructionArithmeticBitwiseHelper,
  131. KiIa32InstructionMoveSeg,
  132. NULL
  133. };
  134. #if DBG
  135. PCHAR KiIa32InstructionHandlerNames [] =
  136. {
  137. "KiIa32InstructionAdc",
  138. "KiIa32InstructionAdd",
  139. "KiIa32InstructionAnd",
  140. "KiIa32InstructionBt",
  141. "KiIa32InstructionBtc",
  142. "KiIa32InstructionBtr",
  143. "KiIa32InstructionBts",
  144. "KiIa32InstructionCmpXchg",
  145. "KiIa32InstructionCmpXchg8b",
  146. "KiIa32InstructionDec",
  147. "KiIa32InstructionInc",
  148. "KiIa32InstructionNeg",
  149. "KiIa32InstructionNot",
  150. "KiIa32InstructionOr",
  151. "KiIa32InstructionSbb",
  152. "KiIa32InstructionSub",
  153. "KiIa32InstructionXadd",
  154. "KiIa32InstructionXchg",
  155. "KiIa32InstructionXor",
  156. "KiIa32InstructionMoveSeg",
  157. NULL,
  158. };
  159. #endif
  160. IA32_OPCODE_DESCRIPTION OpcodesDescription[] =
  161. {
  162. //
  163. // Adc
  164. //
  165. // Adc r/m8, imm8
  166. {
  167. 0x80, 0x00, 0x02, 0x11, IA32_PARAM_RM8_IMM8, Ia32_Adc
  168. },
  169. // Adc r/m, imm
  170. {
  171. 0x81, 0x00, 0x02, 0x11, IA32_PARAM_RM_IMM, Ia32_Adc
  172. },
  173. // Adc r/m, imm8 (sign)
  174. {
  175. 0x83, 0x00, 0x02, 0x11, IA32_PARAM_RM_IMM8SIGN, Ia32_Adc
  176. },
  177. // Adc r/m8, r8
  178. {
  179. 0x10, 0x00, 0x00, 0x01, IA32_PARAM_RM8_R, Ia32_Adc
  180. },
  181. // Adc r/m, r
  182. {
  183. 0x11, 0x00, 0x00, 0x01, IA32_PARAM_RM_R, Ia32_Adc
  184. },
  185. // Adc r, r/m8
  186. {
  187. 0x12, 0x00, 0x00, 0x01, IA32_PARAM_R_RM8, Ia32_Adc
  188. },
  189. // Adc r, r/m
  190. {
  191. 0x13, 0x00, 0x00, 0x01, IA32_PARAM_R_RM, Ia32_Adc
  192. },
  193. //
  194. // Add
  195. //
  196. // Add r/m8, imm8
  197. {
  198. 0x80, 0x00, 0x00, 0x11, IA32_PARAM_RM8_IMM8, Ia32_Add
  199. },
  200. // Add r/m, imm
  201. {
  202. 0x81, 0x00, 0x00, 0x11, IA32_PARAM_RM_IMM, Ia32_Add
  203. },
  204. // Add r/m, imm8 (sign)
  205. {
  206. 0x83, 0x00, 0x00, 0x11, IA32_PARAM_RM_IMM8SIGN, Ia32_Add
  207. },
  208. // Add r/m8, r8
  209. {
  210. 0x00, 0x00, 0x00, 0x01, IA32_PARAM_RM8_R, Ia32_Add
  211. },
  212. // Add r/m, r
  213. {
  214. 0x01, 0x00, 0x00, 0x01, IA32_PARAM_RM_R, Ia32_Add
  215. },
  216. // Add r, r/m8
  217. {
  218. 0x02, 0x00, 0x00, 0x01, IA32_PARAM_R_RM8, Ia32_Add
  219. },
  220. // Add r, r/m
  221. {
  222. 0x03, 0x00, 0x00, 0x01, IA32_PARAM_R_RM, Ia32_Add
  223. },
  224. //
  225. // And
  226. //
  227. // And r/m8, imm8
  228. {
  229. 0x80, 0x00, 0x04, 0x11, IA32_PARAM_RM8_IMM8, Ia32_And
  230. },
  231. // And r/m, imm
  232. {
  233. 0x81, 0x00, 0x04, 0x11, IA32_PARAM_RM_IMM, Ia32_And
  234. },
  235. // And r/m, imm8
  236. {
  237. 0x83, 0x00, 0x04, 0x11, IA32_PARAM_RM_IMM8SIGN, Ia32_And
  238. },
  239. // And r/m8, r8
  240. {
  241. 0x20, 0x00, 0x00, 0x01, IA32_PARAM_RM8_R, Ia32_And
  242. },
  243. // And rm, r
  244. {
  245. 0x21, 0x00, 0x00, 0x01, IA32_PARAM_RM_R, Ia32_And
  246. },
  247. // And r8, r/m8
  248. {
  249. 0x22, 0x00, 0x00, 0x01, IA32_PARAM_R_RM8, Ia32_And
  250. },
  251. // And r, r/m
  252. {
  253. 0x23, 0x00, 0x00, 0x01, IA32_PARAM_R_RM, Ia32_And
  254. },
  255. //
  256. // Or
  257. //
  258. // Or r/m8, imm8
  259. {
  260. 0x80, 0x00, 0x01, 0x11, IA32_PARAM_RM8_IMM8, Ia32_Or
  261. },
  262. // Or r/m, imm
  263. {
  264. 0x81, 0x00, 0x01, 0x11, IA32_PARAM_RM_IMM, Ia32_Or
  265. },
  266. // Or r/m, imm8
  267. {
  268. 0x83, 0x00, 0x01, 0x11, IA32_PARAM_RM_IMM8SIGN, Ia32_Or
  269. },
  270. // Or r/m8, r8
  271. {
  272. 0x08, 0x00, 0x00, 0x01, IA32_PARAM_RM8_R, Ia32_Or
  273. },
  274. // Or rm, r
  275. {
  276. 0x09, 0x00, 0x00, 0x01, IA32_PARAM_RM_R, Ia32_Or
  277. },
  278. // Or r8, r/m8
  279. {
  280. 0x0a, 0x00, 0x00, 0x01, IA32_PARAM_R_RM8, Ia32_Or
  281. },
  282. // Or r, r/m
  283. {
  284. 0x0b, 0x00, 0x00, 0x01, IA32_PARAM_R_RM, Ia32_Or
  285. },
  286. //
  287. // Xor
  288. //
  289. // Xor r/m8, imm8
  290. {
  291. 0x80, 0x00, 0x06, 0x11, IA32_PARAM_RM8_IMM8, Ia32_Xor
  292. },
  293. // Xor r/m, imm
  294. {
  295. 0x81, 0x00, 0x06, 0x11, IA32_PARAM_RM_IMM, Ia32_Xor
  296. },
  297. // Xor r/m, imm8
  298. {
  299. 0x83, 0x00, 0x06, 0x11, IA32_PARAM_RM_IMM8SIGN, Ia32_Xor
  300. },
  301. // Xor r/m8, r8
  302. {
  303. 0x30, 0x00, 0x00, 0x01, IA32_PARAM_RM8_R, Ia32_Xor
  304. },
  305. // Xor rm, r
  306. {
  307. 0x31, 0x00, 0x00, 0x01, IA32_PARAM_RM_R, Ia32_Xor
  308. },
  309. // Xor r8, r/m8
  310. {
  311. 0x32, 0x00, 0x00, 0x01, IA32_PARAM_R_RM8, Ia32_Xor
  312. },
  313. // Xor r, r/m
  314. {
  315. 0x33, 0x00, 0x00, 0x01, IA32_PARAM_R_RM, Ia32_Xor
  316. },
  317. //
  318. // Inc
  319. //
  320. // Inc r/m8
  321. {
  322. 0xfe, 0x00, 0x00, 0x11, IA32_PARAM_RM8, Ia32_Inc
  323. },
  324. // Inc r/m
  325. {
  326. 0xff, 0x00, 0x00, 0x11, IA32_PARAM_RM, Ia32_Inc
  327. },
  328. //
  329. // Dec
  330. //
  331. // Dec r/m8
  332. {
  333. 0xfe, 0x00, 0x01, 0x11, IA32_PARAM_RM8, Ia32_Dec
  334. },
  335. // Dec r/m
  336. {
  337. 0xff, 0x00, 0x01, 0x11, IA32_PARAM_RM, Ia32_Dec
  338. },
  339. //
  340. // Xchg
  341. //
  342. // Xchg r/m8, r
  343. {
  344. 0x86, 0x00, 0x00, 0x01, IA32_PARAM_RM8_R, Ia32_Xchg
  345. },
  346. // Xchg r/m, r
  347. {
  348. 0x87, 0x00, 0x00, 0x01, IA32_PARAM_RM_R, Ia32_Xchg
  349. },
  350. //
  351. // Cmpxchg
  352. //
  353. // Cmpxchg r/m8, r
  354. {
  355. 0x0f, 0xb0, 0x00, 0x02, IA32_PARAM_RM8_R, Ia32_Cmpxchg
  356. },
  357. // Cmpxchg r/m, r
  358. {
  359. 0x0f, 0xb1, 0x00, 0x02, IA32_PARAM_RM_R, Ia32_Cmpxchg
  360. },
  361. //
  362. // Cmpxchg8b
  363. //
  364. // Cmpxchg8b m64
  365. {
  366. 0x0f, 0xc7, 0x01, 0x12, IA32_PARAM_RM, Ia32_Cmpxchg8b
  367. },
  368. //
  369. // Xadd
  370. //
  371. // Xadd r/m8, r
  372. {
  373. 0x0f, 0xc0, 0x00, 0x02, IA32_PARAM_RM8_R, Ia32_Xadd
  374. },
  375. // Xadd r/m, r
  376. {
  377. 0x0f, 0xc1, 0x00, 0x02, IA32_PARAM_RM_R, Ia32_Xadd
  378. },
  379. //
  380. // Neg
  381. //
  382. // Neg r/m8
  383. {
  384. 0xf6, 0x00, 0x03, 0x11, IA32_PARAM_RM8, Ia32_Neg
  385. },
  386. // Neg r/m
  387. {
  388. 0xf7, 0x00, 0x03, 0x11, IA32_PARAM_RM, Ia32_Neg
  389. },
  390. //
  391. // Not
  392. //
  393. // Not r/m8
  394. {
  395. 0xf6, 0x00, 0x02, 0x11, IA32_PARAM_RM8, Ia32_Not
  396. },
  397. // Not r/m
  398. {
  399. 0xf7, 0x00, 0x02, 0x11, IA32_PARAM_RM, Ia32_Not
  400. },
  401. //
  402. // Bt (Bit Test)
  403. //
  404. // Bt r/m, r
  405. {
  406. 0x0f, 0xa3, 0x00, 0x02, IA32_PARAM_RM_R, Ia32_Bt
  407. },
  408. // Bt r/m, imm8
  409. {
  410. 0x0f, 0xba, 0x04, 0x12, IA32_PARAM_RM_IMM8SIGN, Ia32_Bt
  411. },
  412. //
  413. // Btc
  414. //
  415. // Btc r/m, r
  416. {
  417. 0x0f, 0xbb, 0x00, 0x02, IA32_PARAM_RM_R, Ia32_Btc
  418. },
  419. // Btc r/m, imm8
  420. {
  421. 0x0f, 0xba, 0x07, 0x12, IA32_PARAM_RM_IMM8SIGN, Ia32_Btc
  422. },
  423. //
  424. // Btr
  425. //
  426. // Btr r/m, r
  427. {
  428. 0x0f, 0xb3, 0x00, 0x02, IA32_PARAM_RM_R, Ia32_Btr
  429. },
  430. // Btr r/m, imm8
  431. {
  432. 0x0f, 0xba, 0x06, 0x12, IA32_PARAM_RM_IMM8SIGN, Ia32_Btr
  433. },
  434. //
  435. // Bts
  436. //
  437. // Bts r/m, r
  438. {
  439. 0x0f, 0xab, 0x00, 0x02, IA32_PARAM_RM_R, Ia32_Bts
  440. },
  441. // Bts r/m, imm8
  442. {
  443. 0x0f, 0xba, 0x05, 0x12, IA32_PARAM_RM_IMM8SIGN, Ia32_Bts
  444. },
  445. //
  446. // Sub
  447. //
  448. // Sub r/m8, imm8
  449. {
  450. 0x80, 0x00, 0x05, 0x11, IA32_PARAM_RM8_IMM8, Ia32_Sub
  451. },
  452. // Sub r/m, imm
  453. {
  454. 0x81, 0x00, 0x05, 0x11, IA32_PARAM_RM_IMM, Ia32_Sub
  455. },
  456. // Sub r/m, imm8 (sign)
  457. {
  458. 0x83, 0x00, 0x05, 0x11, IA32_PARAM_RM_IMM8SIGN, Ia32_Sub
  459. },
  460. // Sub r/m8, r8
  461. {
  462. 0x28, 0x00, 0x00, 0x01, IA32_PARAM_RM8_R, Ia32_Sub
  463. },
  464. // Sub r/m, r
  465. {
  466. 0x29, 0x00, 0x00, 0x01, IA32_PARAM_RM_R, Ia32_Sub
  467. },
  468. // Sub r, r/m8
  469. {
  470. 0x2a, 0x00, 0x00, 0x01, IA32_PARAM_R_RM8, Ia32_Sub
  471. },
  472. // Sub r, r/m
  473. {
  474. 0x2b, 0x00, 0x00, 0x01, IA32_PARAM_R_RM, Ia32_Sub
  475. },
  476. //
  477. // Sbb
  478. //
  479. // Sbb r/m8, imm8
  480. {
  481. 0x80, 0x00, 0x03, 0x11, IA32_PARAM_RM8_IMM8, Ia32_Sbb
  482. },
  483. // Sbb r/m, imm
  484. {
  485. 0x81, 0x00, 0x03, 0x11, IA32_PARAM_RM_IMM, Ia32_Sbb
  486. },
  487. // Sbb r/m, imm8 (sign)
  488. {
  489. 0x83, 0x00, 0x03, 0x11, IA32_PARAM_RM_IMM8SIGN, Ia32_Sbb
  490. },
  491. // Sbb r/m8, r8
  492. {
  493. 0x18, 0x00, 0x00, 0x01, IA32_PARAM_RM8_R, Ia32_Sbb
  494. },
  495. // Sbb r/m, r
  496. {
  497. 0x19, 0x00, 0x00, 0x01, IA32_PARAM_RM_R, Ia32_Sbb
  498. },
  499. // Sbb r, r/m8
  500. {
  501. 0x1a, 0x00, 0x00, 0x01, IA32_PARAM_R_RM8, Ia32_Sbb
  502. },
  503. // Sbb r, r/m
  504. {
  505. 0x1b, 0x00, 0x00, 0x01, IA32_PARAM_R_RM, Ia32_Sbb
  506. },
  507. //
  508. // Mov
  509. //
  510. // Mov seg-reg, r/m8
  511. {
  512. 0x8e, 0x00, 0x00, 0x01, IA32_PARAM_SEGREG_RM8, Ia32_MovToSeg
  513. },
  514. // Mov seg-reg, r/m
  515. {
  516. 0x8e, 0x00, 0x00, 0x01, IA32_PARAM_SEGREG_RM, Ia32_MovToSeg
  517. },
  518. };
  519. //
  520. // Fast mutex that will serialize access to the instruction
  521. // emulator when the lock prefix is set.
  522. //
  523. FAST_MUTEX KiIa32MisalignedLockFastMutex;
  524. #define KiIa32AcquireMisalignedLockFastMutex() ExAcquireFastMutex(&KiIa32MisalignedLockFastMutex)
  525. #define KiIa32ReleaseMisalignedLockFastMutex() ExReleaseFastMutex(&KiIa32MisalignedLockFastMutex)
  526. //
  527. // This table contains the offset into the KTRAP_FRAME
  528. // for the appropriate register. This table is based on the
  529. // needs of the x86 instruction R/M bits
  530. //
  531. const ULONG RegOffsetTable[8] =
  532. {
  533. FIELD_OFFSET(KTRAP_FRAME, IntV0), // EAX
  534. FIELD_OFFSET(KTRAP_FRAME, IntT2), // ECX
  535. FIELD_OFFSET(KTRAP_FRAME, IntT3), // EDX
  536. FIELD_OFFSET(KTRAP_FRAME, IntT4), // EBX
  537. FIELD_OFFSET(KTRAP_FRAME, IntSp), // ESP
  538. FIELD_OFFSET(KTRAP_FRAME, IntTeb), // EBP
  539. FIELD_OFFSET(KTRAP_FRAME, IntT5), // ESI
  540. FIELD_OFFSET(KTRAP_FRAME, IntT6) // EDI
  541. };
  542. ULONG_PTR GetX86RegOffset (
  543. IN PKTRAP_FRAME TrapFrame,
  544. IN ULONG RegisterBase
  545. )
  546. /*++
  547. Routine Description:
  548. Retreives the offset into the aliased ia64 register for the ia32 register
  549. inside the trap frame.
  550. Arguments:
  551. TrapFrame - Pointer to TrapFrame on the stack.
  552. RegisterBase - Register number to retrieve the offset for.
  553. Return Value:
  554. Address of ia64 alias register for the ia32 register.
  555. --*/
  556. {
  557. return (ULONG_PTR)((PCHAR)TrapFrame + RegOffsetTable[RegisterBase]);
  558. }
  559. ULONG GetX86Reg (
  560. IN PKTRAP_FRAME TrapFrame,
  561. IN ULONG RegisterBase
  562. )
  563. /*++
  564. Routine Description:
  565. Retreives the ia32 register value.
  566. Arguments:
  567. TrapFrame - Pointer to TrapFrame on the stack.
  568. RegisterBase - Register number to retrieve the value for.
  569. Return Value:
  570. Ia32 register context.
  571. --*/
  572. {
  573. return (ULONG)(*(PULONG_PTR)GetX86RegOffset(TrapFrame, RegisterBase));
  574. }
  575. NTSTATUS
  576. KiIa32InitializeLockFastMutex (
  577. VOID
  578. )
  579. /*++
  580. Routine Description:
  581. Initializes the misaligned lock fast mutex. Used to serialize
  582. access if the r/m address is misaligned.
  583. Arguments:
  584. None.
  585. Return Value:
  586. NTSTATUS.
  587. --*/
  588. {
  589. ExInitializeFastMutex (&KiIa32MisalignedLockFastMutex);
  590. return STATUS_SUCCESS;
  591. }
  592. LONG
  593. KiIa32ComputeSIBAddress(
  594. IN PKTRAP_FRAME Frame,
  595. IN LONG Displacement,
  596. IN UCHAR Sib,
  597. IN UCHAR ModRm
  598. )
  599. /*++
  600. Routine Description:
  601. Compute an effective address based on the SIB bytes in an instruction
  602. using the register values in the trap frame
  603. Arguments:
  604. Frame - Pointer to iA32 TrapFrame in the stack.
  605. Displacement - The value of the displacement byte. If no displacement, this
  606. value should be passed in as zero.
  607. Sib - The sib byte that is causing all the trouble.
  608. ModRm - ModRm instruction value
  609. Return Value:
  610. The effective address to use for the memory operation
  611. --*/
  612. {
  613. LONG Base;
  614. LONG Index;
  615. LONG Scale;
  616. //
  617. // First get the base address that we will be using
  618. //
  619. if ((Sib & MI_SIB_BASEMASK) == 5)
  620. {
  621. //
  622. // Handle the special case where we don't use EBP for the base
  623. //
  624. //
  625. // EBP is an implicit reg-base if the Mod is not zero.
  626. //
  627. if ((ModRm >> MI_MODSHIFT) != 0) {
  628. Base = GetX86Reg (Frame, IA32_REG_EBP);
  629. } else {
  630. Base = 0;
  631. }
  632. }
  633. else
  634. {
  635. Base = GetX86Reg (Frame, (Sib & MI_SIB_BASEMASK) >> MI_SIB_BASESHIFT);
  636. }
  637. //
  638. // Now get the Index
  639. //
  640. if ((Sib & MI_SIB_INDEXMASK) == MI_SIB_INDEXNONE)
  641. {
  642. //
  643. // Handle the special case where we don't have an index
  644. //
  645. Index = 0;
  646. }
  647. else
  648. {
  649. Index = GetX86Reg (Frame, (Sib & MI_SIB_INDEXMASK) >> MI_SIB_INDEXSHIFT);
  650. }
  651. Scale = 1 << ((Sib & MI_SIB_SSMASK) >> MI_SIB_SSSHIFT);
  652. return (Base + (Index * Scale) + Displacement);
  653. }
  654. BOOLEAN
  655. KiIa32Compute32BitEffectiveAddress(
  656. IN PKTRAP_FRAME Frame,
  657. IN OUT PUCHAR *InstAddr,
  658. OUT PUINT_PTR Addr,
  659. OUT PBOOLEAN RegisterMode
  660. )
  661. /*++
  662. Routine Description:
  663. Compute an effective address based on bytes in memory and the register
  664. values passed in via the ia64 stack frame. The addressing mode is assumed to
  665. be 32-bit.
  666. Arguments:
  667. Frame - Pointer to iA32 TrapFrame in the stack
  668. InstAddr - Pointer to the first byte after the opcode.
  669. Addr - Effective address.
  670. RegisterMode - Indicates whether the effective address is inside a register or memory.
  671. Return Value:
  672. Returns TRUE if able to compute the EA, else returns FALSE.
  673. Note:
  674. Does not verify permission on an Effective Address. It only computes the
  675. value and lets someone else worry if the process should have access to
  676. that memory location.
  677. --*/
  678. {
  679. UNALIGNED ULONG * UlongAddress;
  680. UCHAR ModRm;
  681. UCHAR Sib = 0;
  682. LONG UNALIGNED *DisplacementPtr;
  683. BOOLEAN ReturnCode = TRUE;
  684. //
  685. // This needs to be a signed value. Start off assuming no displacement
  686. //
  687. LONG Displacement = 0;
  688. try
  689. {
  690. ModRm = *(*InstAddr)++;
  691. //
  692. // handle the register case first
  693. //
  694. if ((ModRm >> MI_MODSHIFT) == 3)
  695. {
  696. //
  697. // yup, we have a register - the easy case...
  698. //
  699. *Addr = GetX86RegOffset (Frame, ModRm & MI_RMMASK);
  700. *RegisterMode = TRUE;
  701. return ReturnCode;
  702. }
  703. *RegisterMode = FALSE;
  704. //
  705. // See if we have a SIB
  706. //
  707. if ((ModRm & MI_RMMASK) == 4)
  708. {
  709. Sib = *(*InstAddr)++;
  710. }
  711. //
  712. // Now decode the destination bits
  713. //
  714. switch (ModRm >> MI_MODSHIFT)
  715. {
  716. case 0:
  717. //
  718. // We have an indirect through a register
  719. //
  720. switch (ModRm & MI_RMMASK)
  721. {
  722. case 4:
  723. //
  724. // Deal with the SIB
  725. //
  726. *Addr = KiIa32ComputeSIBAddress (Frame, Displacement, Sib, ModRm);
  727. break;
  728. case 5:
  729. //
  730. // We have a 32-bit indirect...
  731. //
  732. UlongAddress = (UNALIGNED ULONG *)*InstAddr;
  733. *Addr = *UlongAddress;
  734. *InstAddr = (PUCHAR) (UlongAddress + 1);
  735. break;
  736. default:
  737. //
  738. // The default case is get the address from the register
  739. //
  740. *Addr = GetX86Reg (Frame, (ModRm & MI_RMMASK));
  741. break;
  742. }
  743. break;
  744. case 1:
  745. //
  746. // we have an 8 bit displacement, so grab the next byte
  747. //
  748. Displacement = (signed char) (*(*InstAddr)++);
  749. if ((ModRm & MI_RMMASK) == 4)
  750. {
  751. //
  752. // Have a SIB, so do that
  753. //
  754. *Addr = KiIa32ComputeSIBAddress (Frame, Displacement, Sib, ModRm);
  755. }
  756. else
  757. {
  758. //
  759. // No SIB, life is easy
  760. //
  761. *Addr = GetX86Reg (Frame, (ModRm & MI_RMMASK)) + Displacement;
  762. }
  763. break;
  764. case 2:
  765. //
  766. // we have a 32-bit displacement, so grab the next 4 bytes
  767. //
  768. DisplacementPtr = (PLONG) (*InstAddr);
  769. Displacement = *DisplacementPtr++;
  770. *InstAddr = (PUCHAR)DisplacementPtr;
  771. if ((ModRm & MI_RMMASK) == 4)
  772. {
  773. //
  774. // Have a SIB, so do that
  775. //
  776. *Addr = KiIa32ComputeSIBAddress (Frame, Displacement, Sib, ModRm);
  777. }
  778. else
  779. {
  780. //
  781. // No SIB, life is easy
  782. //
  783. *Addr = GetX86Reg (Frame, (ModRm & MI_RMMASK)) + Displacement;
  784. }
  785. break;
  786. default:
  787. //
  788. // we should have handled case 3 (register access)
  789. // before getting here...
  790. //
  791. ReturnCode = FALSE;
  792. break;
  793. }
  794. }
  795. except (EXCEPTION_EXECUTE_HANDLER)
  796. {
  797. ReturnCode = FALSE;
  798. #if DBG
  799. if (KiIa32InstructionEmulationDbg)
  800. {
  801. DbgPrint("KE: KiIa32Compute32BitEffectiveAddress - Exception %lx\n",
  802. GetExceptionCode());
  803. }
  804. #endif
  805. }
  806. //
  807. // Make sure the address stays within 4GB range
  808. //
  809. if (ReturnCode == TRUE) {
  810. *Addr = (*Addr & 0x000000007fffffffI64);
  811. }
  812. return ReturnCode;
  813. }
  814. BOOLEAN
  815. KiIa32Compute16BitEffectiveAddress (
  816. IN PKTRAP_FRAME Frame,
  817. IN OUT PUCHAR *InstAddr,
  818. OUT PUINT_PTR Addr,
  819. OUT PBOOLEAN RegisterMode
  820. )
  821. /*++
  822. Routine Description:
  823. Compute an effective address based on bytes in memory and
  824. the register values passed in via the ia64 stack frame. The addressing
  825. mode is assumed to be 16-bit.
  826. Arguments:
  827. Frame - Pointer to iA32 TrapFrame in the stack.
  828. InstAddr - Pointer to the first byte after the opcode.
  829. Addr - Effective address.
  830. RegisterMode - Indicates whether the effective address is inside a register or memory.
  831. Return Value:
  832. Returns TRUE if able to compute the EA, else returns FALSE.
  833. Note:
  834. Does not verify permission on an Effective Address. It only computes the
  835. value and lets someone else worry if the process should have access to
  836. that memory location.
  837. --*/
  838. {
  839. UCHAR ModRm;
  840. UCHAR DisplacementType = IA32_DISP_NONE;
  841. USHORT UNALIGNED *Disp16;
  842. LONG EffectiveAddress = 0;
  843. BOOLEAN ReturnCode = TRUE;
  844. try
  845. {
  846. //
  847. // Read in the Mod/Rm and increment the instruction address
  848. //
  849. ModRm = *(*InstAddr)++;
  850. *RegisterMode = FALSE;
  851. //
  852. // First pass
  853. //
  854. switch (ModRm >> MI_MODSHIFT)
  855. {
  856. case 0:
  857. if ((ModRm & MI_RMMASK) == 6)
  858. {
  859. Disp16 = (USHORT UNALIGNED *) InstAddr;
  860. *Addr = *Disp16;
  861. *InstAddr = (*InstAddr + 2);
  862. return ReturnCode;
  863. }
  864. DisplacementType = IA32_DISP_NONE;
  865. break;
  866. case 1:
  867. DisplacementType = IA32_DISP8;
  868. break;
  869. case 2:
  870. DisplacementType = IA32_DISP16;
  871. break;
  872. case 3:
  873. *Addr = GetX86RegOffset (Frame, ModRm & MI_RMMASK);
  874. *RegisterMode = TRUE;
  875. return ReturnCode;
  876. }
  877. //
  878. // Second pass
  879. //
  880. switch (ModRm & MI_RMMASK)
  881. {
  882. case 0:
  883. EffectiveAddress = (GetX86Reg(Frame, IA32_REG_EBX) & 0xffff) +
  884. (GetX86Reg(Frame, IA32_REG_ESI) & 0xffff) ;
  885. break;
  886. case 1:
  887. EffectiveAddress = (GetX86Reg(Frame, IA32_REG_EBX) & 0xffff) +
  888. (GetX86Reg(Frame, IA32_REG_EDI) & 0xffff) ;
  889. break;
  890. case 2:
  891. EffectiveAddress = (GetX86Reg(Frame, IA32_REG_EBP) & 0xffff) +
  892. (GetX86Reg(Frame, IA32_REG_ESI) & 0xffff) ;
  893. break;
  894. case 3:
  895. EffectiveAddress = (GetX86Reg(Frame, IA32_REG_EBP) & 0xffff) +
  896. (GetX86Reg(Frame, IA32_REG_EDI) & 0xffff) ;
  897. break;
  898. case 4:
  899. EffectiveAddress = (GetX86Reg(Frame, IA32_REG_ESI) & 0xffff);
  900. break;
  901. case 5:
  902. EffectiveAddress = (GetX86Reg(Frame, IA32_REG_EDI) & 0xffff);
  903. break;
  904. case 6:
  905. EffectiveAddress = (GetX86Reg(Frame, IA32_REG_EBP) & 0xffff);
  906. break;
  907. case 7:
  908. EffectiveAddress = (GetX86Reg(Frame, IA32_REG_EBX) & 0xffff);
  909. break;
  910. }
  911. //
  912. // Read the displacement, if any
  913. //
  914. if (DisplacementType != IA32_DISP_NONE)
  915. {
  916. switch (DisplacementType)
  917. {
  918. case IA32_DISP8:
  919. {
  920. EffectiveAddress += (LONG) (**InstAddr);
  921. *InstAddr = *InstAddr + 1;
  922. }
  923. break;
  924. case IA32_DISP16:
  925. {
  926. Disp16 = (USHORT UNALIGNED *) InstAddr;
  927. EffectiveAddress += (LONG) *Disp16;
  928. *InstAddr = *InstAddr + 2;
  929. }
  930. break;
  931. default:
  932. #if DBG
  933. DbgPrint("KE: KiIa32Compute16BitEffectiveAddress - Invalid displacement type %lx\n",
  934. DisplacementType);
  935. #endif
  936. ReturnCode = FALSE;
  937. break;
  938. }
  939. }
  940. *Addr = EffectiveAddress;
  941. }
  942. except (EXCEPTION_EXECUTE_HANDLER)
  943. {
  944. #if DBG
  945. if (KiIa32InstructionEmulationDbg)
  946. {
  947. DbgPrint("KE: KiIa32Compute16BitEffectiveAddress - Exception %lx\n",
  948. GetExceptionCode());
  949. }
  950. #endif
  951. ReturnCode = FALSE;
  952. }
  953. //
  954. // Make sure the address stays within 4GB range
  955. //
  956. if (ReturnCode == TRUE) {
  957. *Addr = (*Addr & 0x000000007fffffffI64);
  958. }
  959. return ReturnCode;
  960. }
  961. NTSTATUS
  962. KiIa32UpdateFlags (
  963. IN PIA32_INSTRUCTION Instruction,
  964. IN ULONGLONG Operand1,
  965. IN ULONGLONG Result,
  966. IN ULONG Ia32Eflags
  967. )
  968. /*++
  969. Routine Description:
  970. Updates the Ia32 specified eflags according to the result value.
  971. Arguments:
  972. Instruction - Pointer to the instruction being processed.
  973. Operand1 - First operand (value) of the instruction being emulated.
  974. Result - Result value.
  975. Ia32Eflags - Specific flags to update based on the result value.
  976. Return Value:
  977. NTSTATUS
  978. --*/
  979. {
  980. ULONGLONG Temp = 0;
  981. IA32_EFLAGS Eflags = Instruction->Eflags;
  982. //
  983. // Sanitize the destination value.
  984. //
  985. Result = (Result & MAXULONG);
  986. if ((Ia32Eflags & IA32_EFLAGS_CF) != 0)
  987. {
  988. if (Result > Instruction->OperandMask)
  989. {
  990. Eflags.u.cf = 1;
  991. }
  992. else
  993. {
  994. Eflags.u.cf = 0;
  995. }
  996. }
  997. if ((Ia32Eflags & IA32_EFLAGS_OF) != 0)
  998. {
  999. if (((Operand1 & Result) & 0x80000000UI64) != 0)
  1000. {
  1001. Eflags.u.of = 1;
  1002. }
  1003. else
  1004. {
  1005. Eflags.u.of = 0;
  1006. }
  1007. }
  1008. if ((Ia32Eflags & IA32_EFLAGS_SF) != 0)
  1009. {
  1010. switch (Instruction->OperandSize)
  1011. {
  1012. case 0xff:
  1013. Temp = 0x80UI64;
  1014. break;
  1015. case 0xffff:
  1016. Temp = 0x8000UI64;
  1017. break;
  1018. case 0xffffffff:
  1019. Temp = 0x80000000UI64;
  1020. break;
  1021. }
  1022. if (Result & Temp)
  1023. {
  1024. Eflags.u.sf = 1;
  1025. }
  1026. else
  1027. {
  1028. Eflags.u.sf = 0;
  1029. }
  1030. }
  1031. if ((Ia32Eflags & IA32_EFLAGS_ZF) != 0)
  1032. {
  1033. if (Result == 0)
  1034. {
  1035. Eflags.u.zf = 1;
  1036. }
  1037. else
  1038. {
  1039. Eflags.u.zf = 0;
  1040. }
  1041. }
  1042. if ((Ia32Eflags & IA32_EFLAGS_AF) != 0)
  1043. {
  1044. Eflags.u.af = (((Operand1 ^ Result) >> 4) & 0x01UI64);
  1045. }
  1046. //
  1047. // This needs to be the last one as it modifies the 'Result'
  1048. //
  1049. if ((Ia32Eflags & IA32_EFLAGS_PF) != 0)
  1050. {
  1051. Result = Result & Instruction->OperandMask;
  1052. Temp = 0;
  1053. while (Result)
  1054. {
  1055. Result = (Result & (Result - 1));
  1056. Temp++;
  1057. }
  1058. if ((Temp & 0x01UI64) == 0)
  1059. {
  1060. Eflags.u.pf = 1;
  1061. }
  1062. else
  1063. {
  1064. Eflags.u.pf = 1;
  1065. }
  1066. }
  1067. //
  1068. // Reset reserved values.
  1069. //
  1070. Eflags.u.v1 = 1;
  1071. Eflags.u.v2 = 0;
  1072. Eflags.u.v3 = 0;
  1073. Eflags.u.v4 = 0;
  1074. //
  1075. // Sanitize the flags
  1076. //
  1077. Eflags.Value = SANITIZE_AR24_EFLAGS (Eflags.Value, UserMode);
  1078. Instruction->Eflags = Eflags;
  1079. return STATUS_SUCCESS;
  1080. }
  1081. NTSTATUS
  1082. KiIa32UpdateResult (
  1083. IN PIA32_INSTRUCTION Instruction,
  1084. IN PIA32_OPERAND DestinationOperand,
  1085. IN ULONGLONG Result
  1086. )
  1087. /*++
  1088. Routine Description:
  1089. Writes the result value taking into consideration operand size.
  1090. Arguments:
  1091. Instruction - Pointer to the instruction being processed.
  1092. DestinationOperand - Operand to receive the result.
  1093. Result - Result value to write
  1094. Return Value:
  1095. NTSTATUS
  1096. --*/
  1097. {
  1098. UNALIGNED USHORT *UshortPtr;
  1099. UNALIGNED ULONG *UlongPtr;
  1100. NTSTATUS NtStatus = STATUS_SUCCESS;
  1101. //
  1102. // Update results according to operand size
  1103. //
  1104. try
  1105. {
  1106. if (DestinationOperand->RegisterMode == FALSE)
  1107. {
  1108. if (DestinationOperand->v > MM_MAX_WOW64_ADDRESS)
  1109. {
  1110. return STATUS_ACCESS_VIOLATION;
  1111. }
  1112. }
  1113. switch (Instruction->OperandSize)
  1114. {
  1115. case OPERANDSIZE_ONEBYTE:
  1116. *(PUCHAR)DestinationOperand->v = (UCHAR)Result;
  1117. break;
  1118. case OPERANDSIZE_TWOBYTES:
  1119. UshortPtr = (UNALIGNED USHORT *) DestinationOperand->v;
  1120. *UshortPtr = (USHORT)Result;
  1121. break;
  1122. case OPERANDSIZE_FOURBYTES:
  1123. UlongPtr =(UNALIGNED ULONG *) DestinationOperand->v;
  1124. *UlongPtr = (ULONG)Result;
  1125. break;
  1126. default:
  1127. #if DBG
  1128. if (KiIa32InstructionEmulationDbg)
  1129. {
  1130. DbgPrint("KE: KiIa32UpdateResult() - Invalid operand size - %lx - %p\n",
  1131. Instruction->OperandSize, Instruction);
  1132. }
  1133. #endif
  1134. NtStatus = STATUS_UNSUCCESSFUL;
  1135. break;
  1136. }
  1137. }
  1138. except (EXCEPTION_EXECUTE_HANDLER)
  1139. {
  1140. NtStatus = GetExceptionCode ();
  1141. #if DBG
  1142. DbgPrint("KE: KiIa32UpdateResult - Exception %lx - %p\n",
  1143. NtStatus, Instruction);
  1144. #endif
  1145. }
  1146. return NtStatus;
  1147. }
  1148. NTSTATUS
  1149. KiIa32ReadOperand1 (
  1150. IN PIA32_INSTRUCTION Instruction,
  1151. OUT PULONGLONG Operand1
  1152. )
  1153. /*++
  1154. Routine Description:
  1155. Reads the first (destination) operand of an instruction.
  1156. Arguments:
  1157. Instruction - Pointer to the instruction being processed.
  1158. Operand1 - Buffer to receive the operand value.
  1159. Return Value:
  1160. NTSTATUS
  1161. --*/
  1162. {
  1163. UNALIGNED ULONG *UlongPtr;
  1164. UNALIGNED USHORT *UshortPtr;
  1165. NTSTATUS NtStatus = STATUS_SUCCESS;
  1166. try
  1167. {
  1168. switch (Instruction->Description->Type)
  1169. {
  1170. case IA32_PARAM_RM_IMM8SIGN:
  1171. case IA32_PARAM_RM_IMM:
  1172. case IA32_PARAM_RM_R:
  1173. case IA32_PARAM_R_RM8:
  1174. case IA32_PARAM_R_RM:
  1175. case IA32_PARAM_RM:
  1176. case IA32_PARAM_SEGREG_RM:
  1177. if (Instruction->OperandSize == OPERANDSIZE_TWOBYTES)
  1178. {
  1179. UshortPtr = (UNALIGNED USHORT *) Instruction->Operand1.v;
  1180. *Operand1 = (ULONGLONG) *UshortPtr;
  1181. }
  1182. else
  1183. {
  1184. UlongPtr = (UNALIGNED ULONG *) Instruction->Operand1.v;
  1185. *Operand1 = (ULONGLONG) *UlongPtr;
  1186. }
  1187. break;
  1188. case IA32_PARAM_RM8_IMM8:
  1189. case IA32_PARAM_RM8_R:
  1190. case IA32_PARAM_RM8:
  1191. case IA32_PARAM_SEGREG_RM8:
  1192. *Operand1 = (ULONGLONG) (*(PUCHAR)Instruction->Operand1.v);
  1193. break;
  1194. default:
  1195. #if DBG
  1196. if (KiIa32InstructionEmulationDbg)
  1197. {
  1198. DbgPrint("KE: KiIa32ReadRm - Invalid opcode type %lx - %p\n",
  1199. Instruction->Description->Type, Instruction);
  1200. }
  1201. NtStatus = STATUS_UNSUCCESSFUL;
  1202. #endif
  1203. break;
  1204. }
  1205. }
  1206. except (EXCEPTION_EXECUTE_HANDLER)
  1207. {
  1208. NtStatus = GetExceptionCode ();
  1209. #if DBG
  1210. DbgPrint("KE: KiIa32ReadOperand1 - Exception %lx - %p\n",
  1211. NtStatus, Instruction);
  1212. #endif
  1213. }
  1214. return NtStatus;
  1215. }
  1216. NTSTATUS
  1217. KiIa32ReadOperand2 (
  1218. IN PIA32_INSTRUCTION Instruction,
  1219. OUT PULONGLONG Operand2
  1220. )
  1221. /*++
  1222. Routine Description:
  1223. Reads the second (source) operand of an instruction.
  1224. Arguments:
  1225. Instruction - Pointer to the instruction being processed.
  1226. Operand1 - Buffer to receive the operand value.
  1227. Return Value:
  1228. NTSTATUS
  1229. --*/
  1230. {
  1231. UNALIGNED ULONG *UlongPtr;
  1232. UNALIGNED USHORT *UshortPtr;
  1233. NTSTATUS NtStatus = STATUS_SUCCESS;
  1234. try
  1235. {
  1236. switch (Instruction->Description->Type)
  1237. {
  1238. case IA32_PARAM_RM8_IMM8:
  1239. case IA32_PARAM_RM_IMM8SIGN:
  1240. *Operand2 = (UCHAR)Instruction->Operand2.v;
  1241. break;
  1242. case IA32_PARAM_RM_IMM:
  1243. *Operand2 = Instruction->Operand2.v & Instruction->OperandMask;
  1244. break;
  1245. case IA32_PARAM_RM8_R:
  1246. case IA32_PARAM_R_RM8:
  1247. *Operand2 = (ULONGLONG)(*(PUCHAR)Instruction->Operand2.v);
  1248. break;
  1249. case IA32_PARAM_RM_R:
  1250. case IA32_PARAM_R_RM:
  1251. if (Instruction->OperandSize == OPERANDSIZE_TWOBYTES)
  1252. {
  1253. UshortPtr = (UNALIGNED USHORT *) Instruction->Operand2.v;
  1254. *Operand2 = (ULONGLONG) *UshortPtr;
  1255. }
  1256. else
  1257. {
  1258. UlongPtr = (UNALIGNED ULONG *) Instruction->Operand2.v;
  1259. *Operand2 = (ULONGLONG) *UlongPtr;
  1260. }
  1261. break;
  1262. case IA32_PARAM_SEGREG_RM8:
  1263. case IA32_PARAM_SEGREG_RM:
  1264. break;
  1265. default:
  1266. #if DBG
  1267. if (KiIa32InstructionEmulationDbg)
  1268. {
  1269. DbgPrint("KE: KiIa32ReadOperand2 - Invalid type %lx - %p\n",
  1270. Instruction->Description->Type, Instruction);
  1271. }
  1272. NtStatus = STATUS_UNSUCCESSFUL;
  1273. #endif
  1274. break;
  1275. }
  1276. }
  1277. except (EXCEPTION_EXECUTE_HANDLER)
  1278. {
  1279. NtStatus = GetExceptionCode ();
  1280. #if DBG
  1281. DbgPrint("KE: KiIa32ReadOperand2 - Exception %lx - %p\n",
  1282. NtStatus, Instruction);
  1283. #endif
  1284. }
  1285. return NtStatus;
  1286. }
  1287. NTSTATUS
  1288. KiIa32InstructionAddWithIncrement (
  1289. IN PIA32_INSTRUCTION Instruction,
  1290. IN ULONG Increment
  1291. )
  1292. /*++
  1293. Routine Description:
  1294. Common routine implementing Ia32 add, adc, sub and sbb instructions.
  1295. Arguments:
  1296. Instruction - Pointer to the instruction being processed.
  1297. Increment - Specifies the carry value.
  1298. Return Value:
  1299. NTSTATUS
  1300. --*/
  1301. {
  1302. ULONGLONG UlongDst;
  1303. ULONGLONG UlongSrc;
  1304. ULONGLONG Operand1;
  1305. UCHAR Imm8;
  1306. char SignImm8;
  1307. BOOLEAN Subtract;
  1308. NTSTATUS NtStatus;
  1309. switch (Instruction->Description->Opcode)
  1310. {
  1311. case Ia32_Add:
  1312. case Ia32_Adc:
  1313. Subtract = FALSE;
  1314. break;
  1315. case Ia32_Sub:
  1316. case Ia32_Sbb:
  1317. Subtract = TRUE;
  1318. break;
  1319. default:
  1320. #if DBG
  1321. if (KiIa32InstructionEmulationDbg)
  1322. {
  1323. DbgPrint("KE: KiIa32InstructionAddWithIncrement - Invalid opcode %lx - %p\n",
  1324. Instruction->Description->Opcode, Instruction);
  1325. }
  1326. #endif
  1327. return STATUS_UNSUCCESSFUL;
  1328. break;
  1329. }
  1330. NtStatus = KiIa32ReadOperand1 (Instruction, &UlongDst);
  1331. if (NT_SUCCESS (NtStatus))
  1332. {
  1333. Operand1 = UlongDst;
  1334. NtStatus = KiIa32ReadOperand2 (Instruction, &UlongSrc);
  1335. if (NT_SUCCESS (NtStatus))
  1336. {
  1337. switch (Instruction->Description->Type)
  1338. {
  1339. case IA32_PARAM_RM_IMM8SIGN:
  1340. SignImm8 = (char) UlongSrc;
  1341. if (Subtract)
  1342. UlongDst = (UlongDst - (Increment + SignImm8));
  1343. else
  1344. UlongDst = UlongDst + Increment + SignImm8;
  1345. break;
  1346. case IA32_PARAM_RM8_IMM8:
  1347. Imm8 = (UCHAR) UlongSrc;
  1348. if (Subtract)
  1349. UlongDst = (UlongDst - (Increment + Imm8));
  1350. else
  1351. UlongDst = UlongDst + Increment + Imm8;
  1352. break;
  1353. case IA32_PARAM_RM_IMM:
  1354. default:
  1355. if (Subtract)
  1356. UlongDst = (UlongDst - (Increment + UlongSrc));
  1357. else
  1358. UlongDst = UlongDst + Increment + UlongSrc;
  1359. break;
  1360. }
  1361. //
  1362. // Update results according to operand size
  1363. //
  1364. NtStatus = KiIa32UpdateResult (
  1365. Instruction,
  1366. &Instruction->Operand1,
  1367. UlongDst
  1368. );
  1369. //
  1370. // Eflags update
  1371. //
  1372. if (NT_SUCCESS (NtStatus))
  1373. {
  1374. KiIa32UpdateFlags (
  1375. Instruction,
  1376. Operand1,
  1377. UlongDst,
  1378. (IA32_EFLAGS_CF | IA32_EFLAGS_SF | IA32_EFLAGS_OF |
  1379. IA32_EFLAGS_PF | IA32_EFLAGS_ZF | IA32_EFLAGS_AF)
  1380. );
  1381. }
  1382. }
  1383. }
  1384. return NtStatus;
  1385. }
  1386. NTSTATUS
  1387. KiIa32InstructionAdc (
  1388. IN PKTRAP_FRAME TrapFrame,
  1389. IN PIA32_INSTRUCTION Instruction
  1390. )
  1391. /*++
  1392. Routine Description:
  1393. Adc instruction handler.
  1394. Arguments:
  1395. TrapFrame - Pointer to TrapFrame.
  1396. Instruction - Pointer to the instruction being processed.
  1397. Return Value:
  1398. NTSTATUS
  1399. --*/
  1400. {
  1401. return KiIa32InstructionAddWithIncrement (
  1402. Instruction,
  1403. (ULONG)Instruction->Eflags.u.cf);
  1404. UNREFERENCED_PARAMETER (TrapFrame);
  1405. }
  1406. NTSTATUS
  1407. KiIa32InstructionAdd (
  1408. IN PKTRAP_FRAME TrapFrame,
  1409. IN PIA32_INSTRUCTION Instruction
  1410. )
  1411. /*++
  1412. Routine Description:
  1413. Add instruction handler.
  1414. Arguments:
  1415. TrapFrame - Pointer to TrapFrame.
  1416. Instruction - Pointer to the instruction being processed.
  1417. Return Value:
  1418. NTSTATUS
  1419. --*/
  1420. {
  1421. return KiIa32InstructionAddWithIncrement (
  1422. Instruction,
  1423. 0);
  1424. UNREFERENCED_PARAMETER (TrapFrame);
  1425. }
  1426. NTSTATUS
  1427. KiIa32InstructionArithmeticBitwiseHelper (
  1428. IN PKTRAP_FRAME TrapFrame,
  1429. IN PIA32_INSTRUCTION Instruction
  1430. )
  1431. /*++
  1432. Routine Description:
  1433. And, Or & Xor instructions handler.
  1434. Arguments:
  1435. TrapFrame - Pointer to TrapFrame.
  1436. Instruction - Pointer to the instruction being processed.
  1437. Return Value:
  1438. NTSTATUS
  1439. --*/
  1440. {
  1441. ULONGLONG UlongDst;
  1442. ULONGLONG UlongSrc;
  1443. ULONGLONG Operand1;
  1444. NTSTATUS NtStatus;
  1445. NtStatus = KiIa32ReadOperand1 (Instruction, &UlongDst);
  1446. if (NT_SUCCESS (NtStatus))
  1447. {
  1448. Operand1 = UlongDst;
  1449. NtStatus = KiIa32ReadOperand2 (Instruction, &UlongSrc);
  1450. if (NT_SUCCESS (NtStatus))
  1451. {
  1452. switch (Instruction->Description->Opcode)
  1453. {
  1454. case Ia32_And:
  1455. UlongDst = UlongDst & UlongSrc;
  1456. break;
  1457. case Ia32_Or:
  1458. UlongDst = UlongDst | UlongSrc;
  1459. break;
  1460. case Ia32_Xor:
  1461. UlongDst = UlongDst ^ UlongSrc;
  1462. break;
  1463. default:
  1464. #if DBG
  1465. NtStatus = STATUS_UNSUCCESSFUL;
  1466. if (KiIa32InstructionEmulationDbg)
  1467. {
  1468. DbgPrint("KE: KiIa32InstructionBitwiseHelper - Invalid operation %lx - %p\n",
  1469. Instruction->Description->Opcode, Instruction);
  1470. }
  1471. #endif
  1472. break;
  1473. }
  1474. if (NT_SUCCESS (NtStatus))
  1475. {
  1476. NtStatus = KiIa32UpdateResult (
  1477. Instruction,
  1478. &Instruction->Operand1,
  1479. UlongDst
  1480. );
  1481. if (NT_SUCCESS (NtStatus))
  1482. {
  1483. NtStatus = KiIa32UpdateFlags (
  1484. Instruction,
  1485. Operand1,
  1486. UlongDst,
  1487. (IA32_EFLAGS_SF | IA32_EFLAGS_PF | IA32_EFLAGS_ZF)
  1488. );
  1489. Instruction->Eflags.u.cf = 0;
  1490. Instruction->Eflags.u.of = 0;
  1491. }
  1492. }
  1493. }
  1494. }
  1495. return NtStatus;
  1496. UNREFERENCED_PARAMETER (TrapFrame);
  1497. }
  1498. NTSTATUS
  1499. KiIa32InstructionBitTestHelper (
  1500. IN PKTRAP_FRAME TrapFrame,
  1501. IN PIA32_INSTRUCTION Instruction
  1502. )
  1503. /*++
  1504. Routine Description:
  1505. Bt, Bts, Btr & Btc instructions handler.
  1506. Arguments:
  1507. TrapFrame - Pointer to TrapFrame.
  1508. Instruction - Pointer to the instruction being processed.
  1509. Return Value:
  1510. NTSTATUS
  1511. --*/
  1512. {
  1513. ULONGLONG UlongDst;
  1514. ULONGLONG UlongSrc;
  1515. ULONGLONG BitTestResult;
  1516. NTSTATUS NtStatus;
  1517. NtStatus = KiIa32ReadOperand2 (Instruction, &UlongSrc);
  1518. if (NT_SUCCESS (NtStatus))
  1519. {
  1520. if (Instruction->Operand2.RegisterMode == TRUE)
  1521. {
  1522. if (Instruction->Prefix.b.AddressOverride == 1)
  1523. {
  1524. Instruction->Operand1.v += ((UlongSrc >> 4) << 1);
  1525. UlongSrc &= 0x0f;
  1526. }
  1527. else
  1528. {
  1529. Instruction->Operand1.v += ((UlongSrc >> 5) << 2);
  1530. UlongSrc &= 0x1f;
  1531. }
  1532. }
  1533. NtStatus = KiIa32ReadOperand1 (Instruction, &UlongDst);
  1534. if (NT_SUCCESS (NtStatus))
  1535. {
  1536. BitTestResult = (UlongDst & (1 << UlongSrc));
  1537. if (BitTestResult)
  1538. {
  1539. Instruction->Eflags.u.cf = 1;
  1540. }
  1541. else
  1542. {
  1543. Instruction->Eflags.u.cf = 0;
  1544. }
  1545. switch (Instruction->Description->Opcode)
  1546. {
  1547. case Ia32_Btc:
  1548. UlongDst ^= (1 << UlongSrc);
  1549. break;
  1550. case Ia32_Btr:
  1551. UlongDst &= (~(1 << UlongSrc));
  1552. break;
  1553. case Ia32_Bts:
  1554. UlongDst |= (1 << UlongSrc);
  1555. break;
  1556. }
  1557. NtStatus = KiIa32UpdateResult (
  1558. Instruction,
  1559. &Instruction->Operand1,
  1560. UlongDst
  1561. );
  1562. }
  1563. }
  1564. return NtStatus;
  1565. UNREFERENCED_PARAMETER (TrapFrame);
  1566. }
  1567. NTSTATUS
  1568. KiIa32InstructionOneParamHelper (
  1569. IN PKTRAP_FRAME TrapFrame,
  1570. IN PIA32_INSTRUCTION Instruction
  1571. )
  1572. /*++
  1573. Routine Description:
  1574. Inc, Dec, Neg & Not instructions handler.
  1575. Arguments:
  1576. TrapFrame - Pointer to TrapFrame.
  1577. Instruction - Pointer to the instruction being processed.
  1578. Return Value:
  1579. NTSTATUS
  1580. --*/
  1581. {
  1582. UCHAR Opcode;
  1583. ULONG FlagsAffected = 0;
  1584. ULONGLONG UlongDst;
  1585. ULONGLONG UlongSrc;
  1586. NTSTATUS NtStatus;
  1587. NtStatus = KiIa32ReadOperand1 (
  1588. Instruction,
  1589. &UlongDst
  1590. );
  1591. if (NT_SUCCESS (NtStatus))
  1592. {
  1593. UlongSrc = UlongDst;
  1594. Opcode = Instruction->Description->Opcode;
  1595. switch (Opcode)
  1596. {
  1597. case Ia32_Inc:
  1598. UlongDst += 1;
  1599. break;
  1600. case Ia32_Dec:
  1601. UlongDst -= 1;
  1602. break;
  1603. case Ia32_Neg:
  1604. UlongDst = -(LONGLONG)UlongDst;
  1605. break;
  1606. case Ia32_Not:
  1607. UlongDst = ~UlongDst;
  1608. break;
  1609. }
  1610. NtStatus = KiIa32UpdateResult (
  1611. Instruction,
  1612. &Instruction->Operand1,
  1613. UlongDst
  1614. );
  1615. if (NT_SUCCESS (NtStatus))
  1616. {
  1617. switch (Opcode)
  1618. {
  1619. case Ia32_Inc:
  1620. case Ia32_Dec:
  1621. FlagsAffected = (IA32_EFLAGS_SF | IA32_EFLAGS_PF |
  1622. IA32_EFLAGS_ZF);
  1623. break;
  1624. case Ia32_Neg:
  1625. if (UlongDst == 0)
  1626. Instruction->Eflags.u.cf = 0;
  1627. else
  1628. Instruction->Eflags.u.cf = 1;
  1629. FlagsAffected = (IA32_EFLAGS_SF | IA32_EFLAGS_PF |
  1630. IA32_EFLAGS_ZF | IA32_EFLAGS_AF | IA32_EFLAGS_OF);
  1631. break;
  1632. }
  1633. if (FlagsAffected != 0)
  1634. {
  1635. NtStatus = KiIa32UpdateFlags (
  1636. Instruction,
  1637. UlongSrc,
  1638. UlongDst,
  1639. FlagsAffected
  1640. );
  1641. }
  1642. }
  1643. }
  1644. return NtStatus;
  1645. UNREFERENCED_PARAMETER (TrapFrame);
  1646. }
  1647. NTSTATUS
  1648. KiIa32InstructionXadd (
  1649. IN PKTRAP_FRAME TrapFrame,
  1650. IN PIA32_INSTRUCTION Instruction
  1651. )
  1652. /*++
  1653. Routine Description:
  1654. Xadd instruction handler.
  1655. Arguments:
  1656. TrapFrame - Pointer to TrapFrame.
  1657. Instruction - Pointer to the instruction being processed.
  1658. Return Value:
  1659. NTSTATUS
  1660. --*/
  1661. {
  1662. ULONGLONG UlongDst;
  1663. ULONGLONG UlongSrc;
  1664. ULONGLONG Operand1;
  1665. ULONGLONG Temp;
  1666. NTSTATUS NtStatus;
  1667. NtStatus = KiIa32ReadOperand1 (Instruction, &UlongDst);
  1668. if (NT_SUCCESS (NtStatus))
  1669. {
  1670. Operand1 = UlongDst;
  1671. NtStatus = KiIa32ReadOperand2 (Instruction, &UlongSrc);
  1672. if (NT_SUCCESS (NtStatus))
  1673. {
  1674. Temp = UlongDst;
  1675. UlongDst += UlongSrc;
  1676. NtStatus = KiIa32UpdateResult (
  1677. Instruction,
  1678. &Instruction->Operand1,
  1679. UlongDst
  1680. );
  1681. if (NT_SUCCESS (NtStatus))
  1682. {
  1683. NtStatus = KiIa32UpdateResult (
  1684. Instruction,
  1685. &Instruction->Operand2,
  1686. Temp
  1687. );
  1688. if (NT_SUCCESS (NtStatus))
  1689. {
  1690. NtStatus = KiIa32UpdateFlags (
  1691. Instruction,
  1692. Operand1,
  1693. UlongDst,
  1694. (IA32_EFLAGS_CF | IA32_EFLAGS_SF | IA32_EFLAGS_PF |
  1695. IA32_EFLAGS_ZF | IA32_EFLAGS_OF | IA32_EFLAGS_AF)
  1696. );
  1697. }
  1698. }
  1699. }
  1700. }
  1701. return NtStatus;
  1702. UNREFERENCED_PARAMETER (TrapFrame);
  1703. }
  1704. NTSTATUS
  1705. KiIa32InstructionXchg (
  1706. IN PKTRAP_FRAME TrapFrame,
  1707. IN PIA32_INSTRUCTION Instruction
  1708. )
  1709. /*++
  1710. Routine Description:
  1711. Xchg instruction handler.
  1712. Arguments:
  1713. TrapFrame - Pointer to TrapFrame.
  1714. Instruction - Pointer to the instruction being processed.
  1715. Return Value:
  1716. NTSTATUS
  1717. --*/
  1718. {
  1719. ULONGLONG UlongDst;
  1720. ULONGLONG UlongSrc;
  1721. NTSTATUS NtStatus;
  1722. NtStatus = KiIa32ReadOperand1 (Instruction, &UlongDst);
  1723. if (NT_SUCCESS (NtStatus))
  1724. {
  1725. NtStatus = KiIa32ReadOperand2 (Instruction, &UlongSrc);
  1726. if (NT_SUCCESS (NtStatus))
  1727. {
  1728. NtStatus = KiIa32UpdateResult (
  1729. Instruction,
  1730. &Instruction->Operand1,
  1731. UlongSrc
  1732. );
  1733. if (NT_SUCCESS (NtStatus))
  1734. {
  1735. NtStatus = KiIa32UpdateResult (
  1736. Instruction,
  1737. &Instruction->Operand2,
  1738. UlongDst
  1739. );
  1740. }
  1741. }
  1742. }
  1743. return NtStatus;
  1744. UNREFERENCED_PARAMETER (TrapFrame);
  1745. }
  1746. NTSTATUS
  1747. KiIa32InstructionCmpXchg (
  1748. IN PKTRAP_FRAME TrapFrame,
  1749. IN PIA32_INSTRUCTION Instruction
  1750. )
  1751. /*++
  1752. Routine Description:
  1753. Cmpxchg instruction handler.
  1754. Arguments:
  1755. TrapFrame - Pointer to TrapFrame.
  1756. Instruction - Pointer to the instruction being processed.
  1757. Return Value:
  1758. NTSTATUS
  1759. --*/
  1760. {
  1761. ULONGLONG UlongDst;
  1762. ULONGLONG UlongSrc;
  1763. ULONGLONG Accumulator;
  1764. IA32_OPERAND AccumulatorOperand;
  1765. NTSTATUS NtStatus;
  1766. NtStatus = KiIa32ReadOperand1 (Instruction, &UlongDst);
  1767. if (NT_SUCCESS (NtStatus))
  1768. {
  1769. NtStatus = KiIa32ReadOperand2 (Instruction, &UlongSrc);
  1770. if (NT_SUCCESS (NtStatus))
  1771. {
  1772. Accumulator = GetX86Reg (TrapFrame, IA32_REG_EAX);
  1773. Accumulator &= Instruction->OperandMask;
  1774. if (Accumulator == UlongDst)
  1775. {
  1776. Instruction->Eflags.u.zf = 1;
  1777. NtStatus = KiIa32UpdateResult (
  1778. Instruction,
  1779. &Instruction->Operand1,
  1780. UlongSrc
  1781. );
  1782. }
  1783. else
  1784. {
  1785. Instruction->Eflags.u.zf = 0;
  1786. AccumulatorOperand.RegisterMode = TRUE;
  1787. AccumulatorOperand.v = GetX86RegOffset (TrapFrame, IA32_REG_EAX);
  1788. NtStatus = KiIa32UpdateResult (
  1789. Instruction,
  1790. &AccumulatorOperand,
  1791. UlongDst
  1792. );
  1793. }
  1794. if (NT_SUCCESS (NtStatus))
  1795. {
  1796. NtStatus = KiIa32UpdateFlags (
  1797. Instruction,
  1798. UlongDst,
  1799. UlongDst,
  1800. (IA32_EFLAGS_CF | IA32_EFLAGS_SF |
  1801. IA32_EFLAGS_PF | IA32_EFLAGS_OF |
  1802. IA32_EFLAGS_AF)
  1803. );
  1804. }
  1805. }
  1806. }
  1807. return NtStatus;
  1808. }
  1809. NTSTATUS
  1810. KiIa32InstructionCmpXchg8b (
  1811. IN PKTRAP_FRAME TrapFrame,
  1812. IN PIA32_INSTRUCTION Instruction
  1813. )
  1814. /*++
  1815. Routine Description:
  1816. Cmpxchg8b instruction handler.
  1817. Arguments:
  1818. TrapFrame - Pointer to TrapFrame.
  1819. Instruction - Pointer to the instruction being processed.
  1820. Return Value:
  1821. NTSTATUS
  1822. --*/
  1823. {
  1824. UNALIGNED ULONGLONG *UlongDst;
  1825. UNALIGNED ULONGLONG *UlongSrc;
  1826. ULONGLONG EdxEax;
  1827. EdxEax = GetX86Reg (TrapFrame, IA32_REG_EDX);
  1828. EdxEax <<= 32;
  1829. EdxEax |= GetX86Reg (TrapFrame, IA32_REG_EAX);
  1830. UlongDst = (PULONGLONG)Instruction->Operand1.v;
  1831. if (*UlongDst == EdxEax)
  1832. {
  1833. Instruction->Eflags.u.zf = 1;
  1834. *UlongDst = ((((ULONGLONG) GetX86Reg (TrapFrame, IA32_REG_ECX)) << 32) |
  1835. ((ULONGLONG) GetX86Reg (TrapFrame, IA32_REG_EBX)));
  1836. }
  1837. else
  1838. {
  1839. Instruction->Eflags.u.zf = 0;
  1840. UlongSrc = (PULONGLONG) GetX86RegOffset (TrapFrame, IA32_REG_EDX);
  1841. *UlongSrc = ((*UlongDst) >> 32);
  1842. UlongSrc = (PULONGLONG) GetX86RegOffset (TrapFrame, IA32_REG_EAX);
  1843. *UlongSrc = ((*UlongDst) & 0xffffffff);
  1844. }
  1845. return STATUS_SUCCESS;
  1846. }
  1847. NTSTATUS
  1848. KiIa32InstructionMoveSeg (
  1849. IN PKTRAP_FRAME TrapFrame,
  1850. IN PIA32_INSTRUCTION Instruction
  1851. )
  1852. /*++
  1853. Routine Description:
  1854. Mov Seg-Reg instruction handler.
  1855. Arguments:
  1856. TrapFrame - Pointer to TrapFrame.
  1857. Instruction - Pointer to the instruction being processed.
  1858. Return Value:
  1859. NTSTATUS
  1860. --*/
  1861. {
  1862. return STATUS_NOT_IMPLEMENTED;
  1863. UNREFERENCED_PARAMETER (TrapFrame);
  1864. UNREFERENCED_PARAMETER (Instruction);
  1865. }
  1866. NTSTATUS
  1867. KiIa32LocateInstruction (
  1868. IN PKTRAP_FRAME TrapFrame,
  1869. OUT PIA32_INSTRUCTION Instruction
  1870. )
  1871. /*++
  1872. Routine Description:
  1873. Searches the OpcodeDescription table for matching instruction. Fills any relevant
  1874. prefix values inside the Instruction structure.
  1875. Arguments:
  1876. TrapFrame - Pointer to TrapFrame.
  1877. Instruction - Pointer to an Instruction structure to receive the opcode description.
  1878. Return Value:
  1879. NTSTATUS
  1880. --*/
  1881. {
  1882. BOOLEAN PrefixLoop;
  1883. BOOLEAN Match;
  1884. UCHAR ByteValue;
  1885. UCHAR ByteBuffer[4];
  1886. PUCHAR RegOpcodeByte;
  1887. PIA32_OPCODE_DESCRIPTION OpcodeDescription;
  1888. ULONG Count;
  1889. NTSTATUS NtStatus = STATUS_SUCCESS;
  1890. PrefixLoop = TRUE;
  1891. while (PrefixLoop)
  1892. {
  1893. try
  1894. {
  1895. ByteValue = ProbeAndReadUchar ((PUCHAR)Instruction->Eip);
  1896. }
  1897. except (EXCEPTION_EXECUTE_HANDLER)
  1898. {
  1899. NtStatus = GetExceptionCode();
  1900. break;
  1901. }
  1902. switch (ByteValue)
  1903. {
  1904. case MI_LOCK_PREFIX:
  1905. Instruction->Prefix.b.Lock = 1;
  1906. break;
  1907. case MI_REPNE_PREFIX:
  1908. Instruction->Prefix.b.RepNe = 1;
  1909. break;
  1910. case MI_REP_PREFIX:
  1911. Instruction->Prefix.b.Rep = 1;
  1912. break;
  1913. case MI_SEGCS_PREFIX:
  1914. Instruction->Prefix.b.CsOverride = 1;
  1915. break;
  1916. case MI_SEGSS_PREFIX:
  1917. Instruction->Prefix.b.SsOverride = 1;
  1918. break;
  1919. case MI_SEGDS_PREFIX:
  1920. Instruction->Prefix.b.DsOverride = 1;
  1921. break;
  1922. case MI_SEGES_PREFIX:
  1923. Instruction->Prefix.b.EsOverride = 1;
  1924. break;
  1925. case MI_SEGFS_PREFIX:
  1926. Instruction->Prefix.b.FsOverride = 1;
  1927. break;
  1928. case MI_SEGGS_PREFIX:
  1929. Instruction->Prefix.b.GsOverride = 1;
  1930. break;
  1931. case MI_OPERANDSIZE_PREFIX:
  1932. Instruction->Prefix.b.SizeOverride = 1;
  1933. break;
  1934. case MI_ADDRESSOVERRIDE_PREFIX:
  1935. Instruction->Prefix.b.AddressOverride = 1;
  1936. break;
  1937. default:
  1938. PrefixLoop = FALSE;
  1939. break;
  1940. }
  1941. if (PrefixLoop == TRUE)
  1942. {
  1943. Instruction->Eip++;
  1944. }
  1945. }
  1946. try
  1947. {
  1948. RtlCopyMemory(ByteBuffer, Instruction->Eip, sizeof (ByteBuffer));
  1949. }
  1950. except (EXCEPTION_EXECUTE_HANDLER)
  1951. {
  1952. NtStatus = GetExceptionCode();
  1953. }
  1954. if (NT_SUCCESS (NtStatus))
  1955. {
  1956. //
  1957. // Locate the opcode
  1958. //
  1959. Match = FALSE;
  1960. OpcodeDescription = OpcodesDescription;
  1961. Count = (sizeof (OpcodesDescription) / sizeof (IA32_OPCODE_DESCRIPTION));
  1962. while (Count != 0)
  1963. {
  1964. Count--;
  1965. if (OpcodeDescription->Byte1 == ByteBuffer[0])
  1966. {
  1967. Match = TRUE;
  1968. if (OpcodeDescription->Count.m.Bytes == 2)
  1969. {
  1970. RegOpcodeByte = &ByteBuffer[2];
  1971. if (OpcodeDescription->Byte2 != ByteBuffer[1])
  1972. {
  1973. Match = FALSE;
  1974. }
  1975. }
  1976. else
  1977. {
  1978. RegOpcodeByte = &ByteBuffer[1];
  1979. }
  1980. if ((Match == TRUE) &&
  1981. (OpcodeDescription->Count.m.RegOpcode))
  1982. {
  1983. if (OpcodeDescription->Byte3 != ((*RegOpcodeByte & MI_REGMASK) >> MI_REGSHIFT))
  1984. {
  1985. Match = FALSE;
  1986. }
  1987. }
  1988. if (Match == TRUE)
  1989. {
  1990. break;
  1991. }
  1992. }
  1993. OpcodeDescription++;
  1994. }
  1995. if (Match != TRUE)
  1996. {
  1997. #if DBG
  1998. if (KiIa32InstructionEmulationDbg)
  1999. {
  2000. DbgPrint("KE: KiIa32LocateInstruction - Unable to locate instruction %p\n",
  2001. Instruction);
  2002. }
  2003. #endif
  2004. NtStatus = STATUS_UNSUCCESSFUL;
  2005. }
  2006. if (NT_SUCCESS (NtStatus))
  2007. {
  2008. Instruction->Description = OpcodeDescription;
  2009. Instruction->Eip += OpcodeDescription->Count.m.Bytes;
  2010. }
  2011. }
  2012. return NtStatus;
  2013. UNREFERENCED_PARAMETER (TrapFrame);
  2014. }
  2015. NTSTATUS
  2016. KiIa32DecodeInstruction (
  2017. IN PKTRAP_FRAME TrapFrame,
  2018. OUT PIA32_INSTRUCTION Instruction
  2019. )
  2020. /*++
  2021. Routine Description:
  2022. Decodes the instruction prefixes and operands.
  2023. Arguments:
  2024. TrapFrame - Pointer to TrapFrame.
  2025. Instruction - Pointer to an Instruction structure to receive the opcode description.
  2026. Return Value:
  2027. NTSTATUS
  2028. --*/
  2029. {
  2030. UCHAR InstructionType;
  2031. UCHAR ModRm;
  2032. UNALIGNED USHORT *UnalignedUshort;
  2033. UNALIGNED ULONG *UnalignedUlong;
  2034. IA32_OPERAND Temp;
  2035. BOOLEAN ReturnCode;
  2036. NTSTATUS NtStatus;
  2037. //
  2038. // Check instruction pointer validity
  2039. //
  2040. if (TrapFrame->StIIP > MM_MAX_WOW64_ADDRESS) {
  2041. return STATUS_ACCESS_VIOLATION;
  2042. }
  2043. //
  2044. // Initialize the instruction pointer
  2045. //
  2046. Instruction->Eip = (PCHAR) TrapFrame->StIIP;
  2047. KiIa32GetX86Eflags (Instruction->Eflags);
  2048. //
  2049. // Locate a description for the instruction
  2050. //
  2051. NtStatus = KiIa32LocateInstruction (TrapFrame, Instruction);
  2052. if (NT_SUCCESS (NtStatus))
  2053. {
  2054. //
  2055. // Let's parse the arguments
  2056. //
  2057. InstructionType = Instruction->Description->Type;
  2058. switch (InstructionType)
  2059. {
  2060. case IA32_PARAM_RM8_IMM8:
  2061. case IA32_PARAM_RM8_R:
  2062. case IA32_PARAM_R_RM8:
  2063. case IA32_PARAM_RM8:
  2064. case IA32_PARAM_SEGREG_RM8:
  2065. Instruction->OperandSize = OPERANDSIZE_ONEBYTE;
  2066. Instruction->OperandMask = 0xff;
  2067. break;
  2068. case IA32_PARAM_RM_IMM:
  2069. case IA32_PARAM_RM_IMM8SIGN:
  2070. case IA32_PARAM_RM_R:
  2071. case IA32_PARAM_R_RM:
  2072. case IA32_PARAM_RM:
  2073. if (Instruction->Prefix.b.SizeOverride)
  2074. {
  2075. Instruction->OperandSize = OPERANDSIZE_TWOBYTES;
  2076. Instruction->OperandMask = 0xffff;
  2077. }
  2078. else
  2079. {
  2080. Instruction->OperandSize = OPERANDSIZE_FOURBYTES;
  2081. Instruction->OperandMask = 0xffffffff;
  2082. }
  2083. break;
  2084. break;
  2085. case IA32_PARAM_SEGREG_RM:
  2086. Instruction->OperandSize = OPERANDSIZE_TWOBYTES;
  2087. Instruction->OperandMask = 0xffff;
  2088. break;
  2089. default:
  2090. #if DBG
  2091. if (KiIa32InstructionEmulationDbg)
  2092. {
  2093. DbgPrint("KE: KiIa32DecodeInstruction - Invalid Instruction type %lx, %p\n",
  2094. Instruction->Description->Type, Instruction);
  2095. }
  2096. #endif
  2097. return STATUS_UNSUCCESSFUL;
  2098. break;
  2099. }
  2100. try
  2101. {
  2102. ModRm = ProbeAndReadUchar ((PUCHAR)Instruction->Eip);
  2103. }
  2104. except (EXCEPTION_EXECUTE_HANDLER)
  2105. {
  2106. return GetExceptionCode();
  2107. }
  2108. //
  2109. // Eip should be pointing now at the bytes following the opcode
  2110. //
  2111. if (Instruction->Prefix.b.AddressOverride == 0)
  2112. {
  2113. ReturnCode = KiIa32Compute32BitEffectiveAddress (
  2114. TrapFrame,
  2115. (PUCHAR *)&Instruction->Eip,
  2116. &Instruction->Operand1.v,
  2117. &Instruction->Operand1.RegisterMode
  2118. );
  2119. }
  2120. else
  2121. {
  2122. ReturnCode = KiIa32Compute16BitEffectiveAddress (
  2123. TrapFrame,
  2124. (PUCHAR *)&Instruction->Eip,
  2125. &Instruction->Operand1.v,
  2126. &Instruction->Operand1.RegisterMode
  2127. );
  2128. }
  2129. if (ReturnCode != TRUE)
  2130. {
  2131. NtStatus = STATUS_UNSUCCESSFUL;
  2132. }
  2133. if (Instruction->Prefix.b.FsOverride)
  2134. {
  2135. try
  2136. {
  2137. Instruction->Operand1.v += (ULONGLONG)NtCurrentTeb32();
  2138. }
  2139. except (EXCEPTION_EXECUTE_HANDLER)
  2140. {
  2141. NtStatus = GetExceptionCode ();
  2142. #if DBG
  2143. if (KiIa32InstructionEmulationDbg)
  2144. {
  2145. DbgPrint("KE: KiIa32DecodeInstruction - Exception while reading NtCurrentTeb32() - %p\n",
  2146. Instruction);
  2147. }
  2148. #endif
  2149. }
  2150. }
  2151. //
  2152. // Read in more args
  2153. //
  2154. if (NT_SUCCESS (NtStatus))
  2155. {
  2156. switch (InstructionType)
  2157. {
  2158. case IA32_PARAM_RM8_IMM8:
  2159. case IA32_PARAM_RM_IMM8SIGN:
  2160. try
  2161. {
  2162. Instruction->Operand2.v = (ULONG_PTR) ProbeAndReadUchar ((PUCHAR)Instruction->Eip);
  2163. Instruction->Eip += 1;
  2164. }
  2165. except (EXCEPTION_EXECUTE_HANDLER)
  2166. {
  2167. NtStatus = GetExceptionCode();
  2168. }
  2169. break;
  2170. case IA32_PARAM_RM_IMM:
  2171. try
  2172. {
  2173. if (Instruction->OperandSize == OPERANDSIZE_TWOBYTES)
  2174. {
  2175. UnalignedUshort = (UNALIGNED USHORT *) Instruction->Eip;
  2176. Instruction->Operand2.v = (ULONG_PTR) *UnalignedUshort;
  2177. Instruction->Eip += sizeof (USHORT);
  2178. }
  2179. else
  2180. {
  2181. UnalignedUlong = (UNALIGNED ULONG *) Instruction->Eip;
  2182. Instruction->Operand2.v = (ULONG_PTR) *UnalignedUlong;
  2183. Instruction->Eip += sizeof (ULONG);
  2184. }
  2185. }
  2186. except (EXCEPTION_EXECUTE_HANDLER)
  2187. {
  2188. NtStatus = GetExceptionCode();
  2189. }
  2190. break;
  2191. case IA32_PARAM_RM8_R:
  2192. case IA32_PARAM_R_RM8:
  2193. case IA32_PARAM_RM_R:
  2194. case IA32_PARAM_R_RM:
  2195. Instruction->Operand2.v = GetX86RegOffset (
  2196. TrapFrame,
  2197. (ModRm & MI_REGMASK) >> MI_REGSHIFT);
  2198. Instruction->Operand2.RegisterMode = TRUE;
  2199. break;
  2200. case IA32_PARAM_RM8:
  2201. case IA32_PARAM_RM:
  2202. case IA32_PARAM_SEGREG_RM8:
  2203. case IA32_PARAM_SEGREG_RM:
  2204. break;
  2205. default:
  2206. NtStatus = STATUS_UNSUCCESSFUL;
  2207. #if DBG
  2208. DbgPrint("KE: KiIa32DecodeInstruction - Invalid instruction type %lx - %p\n",
  2209. InstructionType, Instruction);
  2210. #endif
  2211. break;
  2212. }
  2213. //
  2214. // Adjust operands order
  2215. //
  2216. if (NT_SUCCESS (NtStatus))
  2217. {
  2218. switch (InstructionType)
  2219. {
  2220. case IA32_PARAM_R_RM8:
  2221. case IA32_PARAM_R_RM:
  2222. Temp = Instruction->Operand2;
  2223. Instruction->Operand2 = Instruction->Operand1;
  2224. Instruction->Operand1 = Temp;
  2225. break;
  2226. }
  2227. }
  2228. }
  2229. }
  2230. return NtStatus;
  2231. }
  2232. NTSTATUS
  2233. KiIa32ExecuteInstruction (
  2234. IN PKTRAP_FRAME TrapFrame,
  2235. IN PIA32_INSTRUCTION Instruction
  2236. )
  2237. /*++
  2238. Routine Description:
  2239. Executes the instruction handler.
  2240. Arguments:
  2241. TrapFrame - Pointer to TrapFrame.
  2242. Instruction - Pointer to the instruction being processed.
  2243. Return Value:
  2244. NTSTATUS
  2245. --*/
  2246. {
  2247. NTSTATUS NtStatus;
  2248. #if DBG
  2249. if (KiIa32InstructionEmulationDbg)
  2250. {
  2251. DbgPrint("KE: KiIa32ExecuteInstruction - Calling %s %lx, %lx. Instruction = %p\n",
  2252. KiIa32InstructionHandlerNames[Instruction->Description->Opcode],
  2253. Instruction->Operand1.v,
  2254. Instruction->Operand2.v,
  2255. Instruction);
  2256. }
  2257. #endif
  2258. NtStatus = KiIa32InstructionHandler[Instruction->Description->Opcode] (
  2259. TrapFrame,
  2260. Instruction
  2261. );
  2262. //
  2263. // If all is good...
  2264. //
  2265. if (NT_SUCCESS (NtStatus))
  2266. {
  2267. TrapFrame->StIIP = (ULONGLONG) Instruction->Eip;
  2268. KiIa32SetX86Eflags (Instruction->Eflags);
  2269. }
  2270. return NtStatus;
  2271. }
  2272. NTSTATUS
  2273. KiIa32EmulateInstruction (
  2274. IN PKTRAP_FRAME TrapFrame,
  2275. IN PIA32_INSTRUCTION Instruction
  2276. )
  2277. /*++
  2278. Routine Description:
  2279. Emulates the instruction and emulates the lock prefix, if any.
  2280. Arguments:
  2281. TrapFrame - Pointer to TrapFrame.
  2282. Instruction - Pointer to the instruction being processed.
  2283. Return Value:
  2284. NTSTATUS
  2285. --*/
  2286. {
  2287. NTSTATUS NtStatus;
  2288. //
  2289. // Acquire the lock mutex
  2290. //
  2291. if (Instruction->Prefix.b.Lock)
  2292. {
  2293. if (ExAcquireRundownProtection (&PsGetCurrentThread()->RundownProtect) == FALSE)
  2294. {
  2295. return STATUS_UNSUCCESSFUL;
  2296. }
  2297. KiIa32AcquireMisalignedLockFastMutex ();
  2298. }
  2299. try
  2300. {
  2301. NtStatus = KiIa32ExecuteInstruction (TrapFrame, Instruction);
  2302. }
  2303. except (EXCEPTION_EXECUTE_HANDLER)
  2304. {
  2305. NtStatus = GetExceptionCode();
  2306. }
  2307. //
  2308. // Release the lock mutex
  2309. //
  2310. if (Instruction->Prefix.b.Lock)
  2311. {
  2312. KiIa32ReleaseMisalignedLockFastMutex ();
  2313. ExReleaseRundownProtection (&PsGetCurrentThread()->RundownProtect);
  2314. }
  2315. return NtStatus;
  2316. }
  2317. NTSTATUS
  2318. KiIa32InterceptUnalignedLock (
  2319. IN PKTRAP_FRAME TrapFrame
  2320. )
  2321. /*++
  2322. Routine Description:
  2323. Handles misaligned lock interception raised by the iVE.
  2324. Arguments:
  2325. TrapFrame - Pointer to TrapFrame.
  2326. Return Value:
  2327. NTSTATUS
  2328. --*/
  2329. {
  2330. NTSTATUS NtStatus;
  2331. IA32_INSTRUCTION Instruction;
  2332. RtlZeroMemory (&Instruction, sizeof (Instruction));
  2333. //
  2334. // Decode the faulting instruction
  2335. //
  2336. NtStatus = KiIa32DecodeInstruction (TrapFrame, &Instruction);
  2337. if (NT_SUCCESS (NtStatus))
  2338. {
  2339. //
  2340. // xchg instruction asserts the lock by default
  2341. //
  2342. if (Instruction.Description->Opcode == Ia32_Xchg)
  2343. {
  2344. Instruction.Prefix.b.Lock = 1;
  2345. }
  2346. //
  2347. // Execute the x86 instruction by emulating its behaviour
  2348. //
  2349. NtStatus = KiIa32EmulateInstruction (TrapFrame, &Instruction);
  2350. }
  2351. if (NtStatus == STATUS_UNSUCCESSFUL)
  2352. {
  2353. NtStatus = STATUS_PRIVILEGED_INSTRUCTION;
  2354. }
  2355. return NtStatus;
  2356. }
  2357. NTSTATUS
  2358. KiIa32ValidateInstruction (
  2359. IN PKTRAP_FRAME TrapFrame
  2360. )
  2361. /*++
  2362. Routine Description:
  2363. This routine valiates the instruction that we trapped for. Currently,
  2364. the following instructions are checked:
  2365. - mov ss, r/m : the register/memory is validated to contain
  2366. a valid stack-selector value.
  2367. NOTE: This routine is only called for trap instructions (i.e. IIP is incremented
  2368. after the fault).
  2369. Arguments:
  2370. TrapFrame - Pointer to TrapFrame.
  2371. Return Value:
  2372. NTSTATUS
  2373. --*/
  2374. {
  2375. NTSTATUS NtStatus;
  2376. IA32_INSTRUCTION Instruction;
  2377. ULONGLONG UlongSrc;
  2378. ULONGLONG StIIP;
  2379. RtlZeroMemory (&Instruction, sizeof (Instruction));
  2380. //
  2381. // Adjust the instruction
  2382. //
  2383. StIIP = TrapFrame->StIIP;
  2384. TrapFrame->StIIP = TrapFrame->StIIPA;
  2385. //
  2386. // Decode the faulting instruction
  2387. //
  2388. NtStatus = KiIa32DecodeInstruction (TrapFrame, &Instruction);
  2389. if (NT_SUCCESS (NtStatus))
  2390. {
  2391. //
  2392. // Parse the opcode here
  2393. //
  2394. switch (Instruction.Description->Opcode)
  2395. {
  2396. case Ia32_MovToSeg:
  2397. {
  2398. //
  2399. // Validate the stack-selector being loaded
  2400. //
  2401. NtStatus = KiIa32ReadOperand1 (&Instruction, &UlongSrc);
  2402. if (NT_SUCCESS (NtStatus)) {
  2403. //
  2404. // If not a valid selector value
  2405. //
  2406. if ((UlongSrc != 0x23) &&
  2407. (UlongSrc != 0x1b) &&
  2408. (UlongSrc != 0x3b)) {
  2409. NtStatus = STATUS_ILLEGAL_INSTRUCTION;
  2410. }
  2411. }
  2412. }
  2413. break;
  2414. default:
  2415. NtStatus = STATUS_ILLEGAL_INSTRUCTION;
  2416. break;
  2417. }
  2418. } else {
  2419. NtStatus = STATUS_ILLEGAL_INSTRUCTION;
  2420. }
  2421. //
  2422. // Restore the saved IIP
  2423. //
  2424. if (NT_SUCCESS (NtStatus)) {
  2425. TrapFrame->StIIP = StIIP;
  2426. }
  2427. return NtStatus;
  2428. }