Windows NT 4.0 source code leak
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.

2026 lines
35 KiB

4 years ago
  1. /*++
  2. Copyright (c) 1994 Microsoft Corporation
  3. Module Name:
  4. operand.c
  5. Abstract:
  6. This module implements the operand functions necessary to decode x86
  7. instruction operands.
  8. Author:
  9. David N. Cutler (davec) 3-Sep-1994
  10. Environment:
  11. Kernel mode only.
  12. Revision History:
  13. --*/
  14. #include "nthal.h"
  15. #include "emulate.h"
  16. ULONG
  17. XmPushPopSegment (
  18. IN PRXM_CONTEXT P
  19. )
  20. /*++
  21. Routine Description:
  22. This function decodes x86 operand specifiers for the following opcodes:
  23. xxxxxx
  24. Arguments:
  25. P - Supplies a pointer to an emulator context structure.
  26. Return Value:
  27. A completion status of TRUE is returned as the function value.
  28. --*/
  29. {
  30. ULONG Index;
  31. //
  32. // Push or pop segment register.
  33. //
  34. Index = P->OpcodeControl.FormatType;
  35. P->DataType = WORD_DATA;
  36. if (P->FunctionIndex == X86_PUSH_OP) {
  37. XmSetSourceValue(P, (PVOID)(&P->SegmentRegister[Index]));
  38. } else {
  39. XmSetDestinationValue(P, (PVOID)(&P->SegmentRegister[Index]));
  40. }
  41. return TRUE;
  42. }
  43. ULONG
  44. XmLoadSegment (
  45. IN PRXM_CONTEXT P
  46. )
  47. /*++
  48. Routine Description:
  49. This function decodes x86 operand specifiers for the following opcodes:
  50. xxxxxx
  51. Arguments:
  52. P - Supplies a pointer to an emulator context structure.
  53. Return Value:
  54. A completion status of TRUE is returned as the function value.
  55. --*/
  56. {
  57. ULONG Index;
  58. ULONG DataType;
  59. PVOID Operand;
  60. ULONG Number;
  61. //
  62. // Load a segment register and a displacement value into register.
  63. //
  64. Index = P->OpcodeControl.FormatType;
  65. if (P->OpsizePrefixActive != FALSE) {
  66. P->DataType = LONG_DATA;
  67. } else {
  68. P->DataType = WORD_DATA;
  69. }
  70. Operand = XmEvaluateAddressSpecifier(P, &Number);
  71. if (P->RegisterOffsetAddress != FALSE) {
  72. longjmp(&P->JumpBuffer[0], XM_ILLEGAL_REGISTER_SPECIFIER);
  73. }
  74. XmSetSourceValue(P, Operand);
  75. DataType = P->DataType;
  76. P->DataType = WORD_DATA;
  77. Operand = XmGetOffsetAddress(P, P->Offset + DataType + 1);
  78. XmSetDestinationValue(P, Operand);
  79. P->SegmentRegister[Index - FormatLoadSegmentES] = P->DstValue.Word;
  80. P->DataType = DataType;
  81. P->DstLong = (ULONG UNALIGNED *)(&P->Gpr[Number].Exx);
  82. return TRUE;
  83. }
  84. ULONG
  85. XmGroup1General (
  86. IN PRXM_CONTEXT P
  87. )
  88. /*++
  89. Routine Description:
  90. This function decodes x86 operand specifiers for the following opcodes:
  91. xxxxxx
  92. Arguments:
  93. P - Supplies a pointer to an emulator context structure.
  94. Return Value:
  95. A completion status of TRUE is returned as the function value.
  96. --*/
  97. {
  98. PVOID Operand;
  99. ULONG Number;
  100. //
  101. // Group 1 opcodes with general operand specifier and a direction
  102. // bit.
  103. //
  104. XmSetDataType(P);
  105. Operand = XmEvaluateAddressSpecifier(P, &Number);
  106. if ((P->CurrentOpcode & DIRECTION_BIT) == 0) {
  107. XmSetDestinationValue(P, Operand);
  108. XmSetSourceValue(P, XmGetRegisterAddress(P, Number));
  109. } else {
  110. XmSetDestinationValue(P, XmGetRegisterAddress(P, Number));
  111. XmSetSourceValue(P, Operand);
  112. }
  113. return TRUE;
  114. }
  115. ULONG
  116. XmGroup1Immediate (
  117. IN PRXM_CONTEXT P
  118. )
  119. /*++
  120. Routine Description:
  121. This function decodes x86 operand specifiers for the following opcodes:
  122. xxxxxx
  123. Arguments:
  124. P - Supplies a pointer to an emulator context structure.
  125. Return Value:
  126. A completion status of TRUE is returned as the function value.
  127. --*/
  128. {
  129. PVOID Operand;
  130. ULONG Number;
  131. ULONG Source;
  132. //
  133. // Group 1 opcode with general operand specifier and an immediate
  134. // operand.
  135. //
  136. XmSetDataType(P);
  137. Operand = XmEvaluateAddressSpecifier(P, &Number);
  138. Source = XmGetImmediateSourceValue(P, P->CurrentOpcode & SIGN_BIT);
  139. XmSetDestinationValue(P, Operand);
  140. XmSetImmediateSourceValue(P, Source);
  141. P->FunctionIndex += Number;
  142. return TRUE;
  143. }
  144. ULONG
  145. XmGroup2By1 (
  146. IN PRXM_CONTEXT P
  147. )
  148. /*++
  149. Routine Description:
  150. This function decodes x86 operand specifiers for the following opcodes:
  151. xxxxxx
  152. Arguments:
  153. P - Supplies a pointer to an emulator context structure.
  154. Return Value:
  155. A completion status of TRUE is returned as the function value.
  156. --*/
  157. {
  158. PVOID Operand;
  159. ULONG Number;
  160. ULONG Source;
  161. //
  162. // Group 2 shift opcodes with a general operand specifier and a
  163. // shift count of 1.
  164. //
  165. XmSetDataType(P);
  166. Operand = XmEvaluateAddressSpecifier(P, &Number);
  167. Source = 1;
  168. XmSetImmediateSourceValue(P, Source);
  169. XmSetDestinationValue(P, Operand);
  170. P->FunctionIndex += Number;
  171. return TRUE;
  172. }
  173. ULONG
  174. XmGroup2ByCL (
  175. IN PRXM_CONTEXT P
  176. )
  177. /*++
  178. Routine Description:
  179. This function decodes x86 operand specifiers for the following opcodes:
  180. xxxxxx
  181. Arguments:
  182. P - Supplies a pointer to an emulator context structure.
  183. Return Value:
  184. A completion status of TRUE is returned as the function value.
  185. --*/
  186. {
  187. PVOID Operand;
  188. ULONG Number;
  189. ULONG Source;
  190. //
  191. // Group 2 shift opcodes with a general operand specifier and a
  192. // CL shift count.
  193. //
  194. XmSetDataType(P);
  195. Operand = XmEvaluateAddressSpecifier(P, &Number);
  196. Source = (ULONG)P->Gpr[CL].Xl & 0x1f;
  197. XmSetImmediateSourceValue(P, Source);
  198. XmSetDestinationValue(P, Operand);
  199. P->FunctionIndex += Number;
  200. return TRUE;
  201. }
  202. ULONG
  203. XmGroup2ByByte (
  204. IN PRXM_CONTEXT P
  205. )
  206. /*++
  207. Routine Description:
  208. This function decodes x86 operand specifiers for the following opcodes:
  209. xxxxxx
  210. Arguments:
  211. P - Supplies a pointer to an emulator context structure.
  212. Return Value:
  213. A completion status of TRUE is returned as the function value.
  214. --*/
  215. {
  216. PVOID Operand;
  217. ULONG Number;
  218. ULONG Source;
  219. //
  220. // Group 2 shift opcodes with a general operand specifier and a
  221. // byte immediate shift count.
  222. //
  223. XmSetDataType(P);
  224. Operand = XmEvaluateAddressSpecifier(P, &Number);
  225. Source = XmGetByteImmediate(P) & 0x1f;
  226. XmSetImmediateSourceValue(P, Source);
  227. XmSetDestinationValue(P, Operand);
  228. P->FunctionIndex += Number;
  229. return TRUE;
  230. }
  231. ULONG
  232. XmGroup3General (
  233. IN PRXM_CONTEXT P
  234. )
  235. /*++
  236. Routine Description:
  237. This function decodes x86 operand specifiers for the following opcodes:
  238. xxxxxx
  239. Arguments:
  240. P - Supplies a pointer to an emulator context structure.
  241. Return Value:
  242. A completion status of TRUE is returned as the function value.
  243. --*/
  244. {
  245. PVOID Operand;
  246. ULONG Number;
  247. ULONG Source;
  248. //
  249. // Group 3 opcodes with general operand specifier.
  250. //
  251. // N.B. The test operator for this group has an immediate operand
  252. // and the multiply and divide operators use the accumulator
  253. // as a source. The not and neg operators are unary.
  254. //
  255. XmSetDataType(P);
  256. Operand = XmEvaluateAddressSpecifier(P, &Number);
  257. P->FunctionIndex += Number;
  258. if (P->FunctionIndex == X86_TEST_OP) {
  259. Source = XmGetImmediateSourceValue(P, 0);
  260. XmSetDestinationValue(P, Operand);
  261. XmSetImmediateSourceValue(P, Source);
  262. } else {
  263. //
  264. // If the operation is a mulitply or divide, then there is an
  265. // implied operand which is AL, AX, or EAX. If the operation is
  266. // a divide, then there is an additional implied operand which
  267. // is AH, DX, or EDX.
  268. //
  269. if ((Number & 0x4) != 0) {
  270. if ((Number & 0x2) == 0) {
  271. XmSetDestinationValue(P, (PVOID)(&P->Gpr[EAX].Exx));
  272. } else {
  273. P->DstLong = (UNALIGNED ULONG *)(&P->Gpr[EAX].Exx);
  274. }
  275. XmSetSourceValue(P, Operand);
  276. } else {
  277. XmSetDestinationValue(P, Operand);
  278. }
  279. }
  280. return TRUE;
  281. }
  282. ULONG
  283. XmGroup45General (
  284. IN PRXM_CONTEXT P
  285. )
  286. /*++
  287. Routine Description:
  288. This function decodes x86 operand specifiers for the following opcodes:
  289. xxxxxx
  290. Arguments:
  291. P - Supplies a pointer to an emulator context structure.
  292. Return Value:
  293. A completion status of TRUE is returned as the function value.
  294. --*/
  295. {
  296. ULONG DataType;
  297. PVOID Operand;
  298. ULONG Number;
  299. //
  300. // Group 4 and group 5 unary opcodes with general operand specifier.
  301. //
  302. XmSetDataType(P);
  303. Operand = XmEvaluateAddressSpecifier(P, &Number);
  304. if (P->OpcodeControl.FormatType == FormatGroup4General) {
  305. Number &= 0x1;
  306. }
  307. P->FunctionIndex += Number;
  308. if (P->FunctionIndex == X86_PUSH_OP) {
  309. XmSetSourceValue(P, Operand);
  310. } else {
  311. //
  312. // If the operation is a call or jump that specifies a segment,
  313. // then get the segment value.
  314. //
  315. XmSetDestinationValue(P, Operand);
  316. if ((Number == 3) || (Number == 5)) {
  317. if (P->RegisterOffsetAddress != FALSE) {
  318. longjmp(&P->JumpBuffer[0], XM_ILLEGAL_REGISTER_SPECIFIER);
  319. }
  320. DataType = P->DataType;
  321. P->DataType = WORD_DATA;
  322. Operand = XmGetOffsetAddress(P, P->Offset + DataType + 1);
  323. XmSetSourceValue(P, Operand);
  324. P->DstSegment = P->SrcValue.Word;
  325. P->DataType = DataType;
  326. }
  327. }
  328. return TRUE;
  329. }
  330. ULONG
  331. XmGroup8BitOffset (
  332. IN PRXM_CONTEXT P
  333. )
  334. /*++
  335. Routine Description:
  336. This function decodes x86 operand specifiers for the following opcodes:
  337. xxxxxx
  338. Arguments:
  339. P - Supplies a pointer to an emulator context structure.
  340. Return Value:
  341. A completion status of TRUE is returned as the function value.
  342. --*/
  343. {
  344. PVOID Operand;
  345. ULONG Offset;
  346. ULONG Number;
  347. //
  348. // Bit test opcodes with an immediate bit offset and a memory or
  349. // register operand.
  350. //
  351. if (P->OpsizePrefixActive != FALSE) {
  352. P->DataType = LONG_DATA;
  353. } else {
  354. P->DataType = WORD_DATA;
  355. }
  356. Operand = XmEvaluateAddressSpecifier(P, &Number);
  357. Offset = XmGetByteImmediate(P);
  358. XmSetImmediateSourceValue(P, Offset);
  359. if (P->RegisterOffsetAddress == FALSE) {
  360. if (P->DataType == LONG_DATA) {
  361. Offset = (P->SrcValue.Long >> 5) << 2;
  362. } else {
  363. Offset = (P->SrcValue.Long >> 4) << 1;
  364. }
  365. Operand = XmGetOffsetAddress(P, Offset + P->Offset);
  366. }
  367. if (P->DataType == LONG_DATA) {
  368. P->SrcValue.Long &= 0x1f;
  369. } else {
  370. P->SrcValue.Long &= 0xf;
  371. }
  372. XmSetDestinationValue(P, Operand);
  373. P->FunctionIndex += (Number & 0x3);
  374. return TRUE;
  375. }
  376. ULONG
  377. XmOpcodeRegister (
  378. IN PRXM_CONTEXT P
  379. )
  380. /*++
  381. Routine Description:
  382. This function decodes x86 operand specifiers for the following opcodes:
  383. xxxxxx
  384. Arguments:
  385. P - Supplies a pointer to an emulator context structure.
  386. Return Value:
  387. A completion status of TRUE is returned as the function value.
  388. --*/
  389. {
  390. ULONG Number;
  391. //
  392. // Unary opodes with a general register encoded in the low
  393. // 3 bits of the opcode value.
  394. //
  395. Number = P->CurrentOpcode & 0x7;
  396. if (P->OpsizePrefixActive != FALSE) {
  397. P->DataType = LONG_DATA;
  398. } else {
  399. P->DataType = WORD_DATA;
  400. }
  401. if (P->FunctionIndex == X86_PUSH_OP) {
  402. XmSetSourceValue(P, (PVOID)(&P->Gpr[Number].Exx));
  403. } else {
  404. XmSetDestinationValue(P, (PVOID)(&P->Gpr[Number].Exx));
  405. }
  406. return TRUE;
  407. }
  408. ULONG
  409. XmLongJump (
  410. IN PRXM_CONTEXT P
  411. )
  412. /*++
  413. Routine Description:
  414. This function decodes x86 operand specifiers for the following opcodes:
  415. xxxxxx
  416. Arguments:
  417. P - Supplies a pointer to an emulator context structure.
  418. Return Value:
  419. A completion status of TRUE is returned as the function value.
  420. --*/
  421. {
  422. ULONG Offset;
  423. //
  424. // Long jump with opcode containing the control for conditional
  425. // jumps. The destination of the jump is stored in the destination
  426. // value and the jump control is stored in the sources value.
  427. //
  428. if (P->OpsizePrefixActive != FALSE) {
  429. Offset = XmGetLongImmediate(P);
  430. P->DstValue.Long = P->Eip + Offset;
  431. } else {
  432. Offset = XmGetWordImmediate(P);
  433. P->DstValue.Long = (USHORT)(Offset + P->Eip);
  434. }
  435. P->SrcValue.Long = P->CurrentOpcode & 0xf;
  436. return TRUE;
  437. }
  438. ULONG
  439. XmShortJump (
  440. IN PRXM_CONTEXT P
  441. )
  442. /*++
  443. Routine Description:
  444. This function decodes x86 operand specifiers for the following opcodes:
  445. xxxxxx
  446. Arguments:
  447. P - Supplies a pointer to an emulator context structure.
  448. Return Value:
  449. A completion status of TRUE is returned as the function value.
  450. --*/
  451. {
  452. ULONG Offset;
  453. //
  454. // Short jump with opcode containing the control for conditional
  455. // jumps. The destination of the jump is stored in the destination
  456. // value and the jump control is stored in the sources value.
  457. //
  458. Offset = (ULONG)XmGetSignedByteImmediateToWord(P);
  459. P->DstValue.Long = (USHORT)(Offset + P->Eip);
  460. P->SrcValue.Long = P->CurrentOpcode & 0xf;
  461. return TRUE;
  462. }
  463. ULONG
  464. XmSetccByte (
  465. IN PRXM_CONTEXT P
  466. )
  467. /*++
  468. Routine Description:
  469. This function decodes x86 operand specifiers for the following opcodes:
  470. xxxxxx
  471. Arguments:
  472. P - Supplies a pointer to an emulator context structure.
  473. Return Value:
  474. A completion status of TRUE is returned as the function value.
  475. --*/
  476. {
  477. ULONG Number;
  478. //
  479. // General byte destination with reg field ignored and the opcode
  480. // containing the condition control.
  481. //
  482. P->DataType = BYTE_DATA;
  483. P->DstByte = (UCHAR UNALIGNED *)XmEvaluateAddressSpecifier(P, &Number);
  484. P->SrcValue.Long = P->CurrentOpcode & 0xf;
  485. return TRUE;
  486. }
  487. ULONG
  488. XmAccumImmediate (
  489. IN PRXM_CONTEXT P
  490. )
  491. /*++
  492. Routine Description:
  493. This function decodes x86 operand specifiers for the following opcodes:
  494. xxxxxx
  495. Arguments:
  496. P - Supplies a pointer to an emulator context structure.
  497. Return Value:
  498. A completion status of TRUE is returned as the function value.
  499. --*/
  500. {
  501. ULONG Source;
  502. //
  503. // Accumulator destination and immediate source operands.
  504. //
  505. XmSetDataType(P);
  506. Source = XmGetImmediateSourceValue(P, 0);
  507. XmSetDestinationValue(P, (PVOID)(&P->Gpr[EAX].Exx));
  508. XmSetImmediateSourceValue(P, Source);
  509. return TRUE;
  510. }
  511. ULONG
  512. XmAccumRegister (
  513. IN PRXM_CONTEXT P
  514. )
  515. /*++
  516. Routine Description:
  517. This function decodes x86 operand specifiers for the following opcodes:
  518. xxxxxx
  519. Arguments:
  520. P - Supplies a pointer to an emulator context structure.
  521. Return Value:
  522. A completion status of TRUE is returned as the function value.
  523. --*/
  524. {
  525. ULONG Number;
  526. //
  527. // Accumulator destination and a general register source encoded in
  528. // the low 3-bits of the opcode value.
  529. //
  530. Number = P->CurrentOpcode & 0x7;
  531. if (P->OpsizePrefixActive != FALSE) {
  532. P->DataType = LONG_DATA;
  533. } else {
  534. P->DataType = WORD_DATA;
  535. }
  536. XmSetSourceValue(P, (PVOID)(&P->Gpr[Number].Exx));
  537. XmSetDestinationValue(P, (PVOID)(&P->Gpr[EAX].Exx));
  538. return TRUE;
  539. }
  540. ULONG
  541. XmMoveGeneral (
  542. IN PRXM_CONTEXT P
  543. )
  544. /*++
  545. Routine Description:
  546. This function decodes x86 operand specifiers for the following opcodes:
  547. xxxxxx
  548. Arguments:
  549. P - Supplies a pointer to an emulator context structure.
  550. Return Value:
  551. A completion status of TRUE is returned as the function value.
  552. --*/
  553. {
  554. PVOID Operand;
  555. ULONG Number;
  556. //
  557. // Move opcodes with general operand specifier and a direction bit.
  558. //
  559. XmSetDataType(P);
  560. Operand = XmEvaluateAddressSpecifier(P, &Number);
  561. if ((P->CurrentOpcode & DIRECTION_BIT) == 0) {
  562. P->DstLong = (ULONG UNALIGNED *)Operand;
  563. XmSetSourceValue(P, XmGetRegisterAddress(P, Number));
  564. } else {
  565. P->DstLong = (ULONG UNALIGNED *)XmGetRegisterAddress(P, Number);
  566. XmSetSourceValue(P, Operand);
  567. }
  568. return TRUE;
  569. }
  570. ULONG
  571. XmMoveImmediate (
  572. IN PRXM_CONTEXT P
  573. )
  574. /*++
  575. Routine Description:
  576. This function decodes x86 operand specifiers for the following opcodes:
  577. xxxxxx
  578. Arguments:
  579. P - Supplies a pointer to an emulator context structure.
  580. Return Value:
  581. A completion status of TRUE is returned as the function value.
  582. --*/
  583. {
  584. PVOID Operand;
  585. ULONG Number;
  586. ULONG Source;
  587. //
  588. // Move opcodes with general operand specifier and an immediate
  589. // operand.
  590. //
  591. XmSetDataType(P);
  592. Operand = XmEvaluateAddressSpecifier(P, &Number);
  593. P->DstLong = (ULONG UNALIGNED *)Operand;
  594. Source = XmGetImmediateSourceValue(P, 0);
  595. XmSetImmediateSourceValue(P, Source);
  596. return TRUE;
  597. }
  598. ULONG
  599. XmMoveRegImmediate (
  600. IN PRXM_CONTEXT P
  601. )
  602. /*++
  603. Routine Description:
  604. This function decodes x86 operand specifiers for the following opcodes:
  605. xxxxxx
  606. Arguments:
  607. P - Supplies a pointer to an emulator context structure.
  608. Return Value:
  609. A completion status of TRUE is returned as the function value.
  610. --*/
  611. {
  612. ULONG Number;
  613. //
  614. // Move register immediate opcodes with a general register encoded
  615. // in the low 3-bits of the opcode value and an immediate operand.
  616. //
  617. Number = P->CurrentOpcode & 0x7;
  618. if ((P->CurrentOpcode & 0x8) == 0) {
  619. P->DataType = BYTE_DATA;
  620. } else {
  621. if (P->OpsizePrefixActive != FALSE) {
  622. P->DataType = LONG_DATA;
  623. } else {
  624. P->DataType = WORD_DATA;
  625. }
  626. }
  627. P->DstLong = (ULONG UNALIGNED *)XmGetRegisterAddress(P, Number);
  628. XmSetImmediateSourceValue(P, XmGetImmediateSourceValue(P, 0));
  629. return TRUE;
  630. }
  631. ULONG
  632. XmSegmentOffset (
  633. IN PRXM_CONTEXT P
  634. )
  635. /*++
  636. Routine Description:
  637. This function decodes x86 operand specifiers for the following opcodes:
  638. xxxxxx
  639. Arguments:
  640. P - Supplies a pointer to an emulator context structure.
  641. Return Value:
  642. A completion status of TRUE is returned as the function value.
  643. --*/
  644. {
  645. PVOID Operand;
  646. ULONG Offset;
  647. //
  648. // Move opcodes with an implied accumlator operand and an immediate
  649. // segment offset and a direction bit.
  650. //
  651. XmSetDataType(P);
  652. if (P->OpaddrPrefixActive != FALSE) {
  653. Offset = XmGetLongImmediate(P);
  654. } else {
  655. Offset = XmGetWordImmediate(P);
  656. }
  657. Operand = XmGetOffsetAddress(P, Offset);
  658. if ((P->CurrentOpcode & DIRECTION_BIT) == 0) {
  659. P->DstLong = (ULONG UNALIGNED *)(&P->Gpr[EAX].Exx);
  660. XmSetSourceValue(P, Operand);
  661. } else {
  662. P->DstLong = (ULONG UNALIGNED *)Operand;
  663. XmSetSourceValue(P, &P->Gpr[EAX].Exx);
  664. }
  665. return TRUE;
  666. }
  667. ULONG
  668. XmMoveSegment (
  669. IN PRXM_CONTEXT P
  670. )
  671. /*++
  672. Routine Description:
  673. This function decodes x86 operand specifiers for the following opcodes:
  674. xxxxxx
  675. Arguments:
  676. P - Supplies a pointer to an emulator context structure.
  677. Return Value:
  678. A completion status of TRUE is returned as the function value.
  679. --*/
  680. {
  681. PVOID Operand;
  682. ULONG Number;
  683. //
  684. // Move segment opcodes with general operand specifier and a direction
  685. // bit.
  686. //
  687. P->DataType = WORD_DATA;
  688. Operand = XmEvaluateAddressSpecifier(P, &Number);
  689. if ((P->CurrentOpcode & DIRECTION_BIT) == 0) {
  690. P->DstLong = (ULONG UNALIGNED *)Operand;
  691. XmSetSourceValue(P, (PVOID)(&P->SegmentRegister[Number]));
  692. } else {
  693. P->DstLong = (ULONG UNALIGNED *)(&P->SegmentRegister[Number]);
  694. XmSetSourceValue(P, Operand);
  695. }
  696. return TRUE;
  697. }
  698. ULONG
  699. XmMoveXxGeneral (
  700. IN PRXM_CONTEXT P
  701. )
  702. /*++
  703. Routine Description:
  704. This function decodes x86 operand specifiers for the following opcodes:
  705. xxxxxx
  706. Arguments:
  707. P - Supplies a pointer to an emulator context structure.
  708. Return Value:
  709. A completion status of TRUE is returned as the function value.
  710. --*/
  711. {
  712. PVOID Operand;
  713. ULONG Number;
  714. //
  715. // Move zero or sign extended opcodes with general operand specifier.
  716. //
  717. if ((P->CurrentOpcode & WIDTH_BIT) == 0) {
  718. P->DataType = BYTE_DATA;
  719. } else {
  720. P->DataType = WORD_DATA;
  721. }
  722. Operand = XmEvaluateAddressSpecifier(P, &Number);
  723. XmSetSourceValue(P, Operand);
  724. if (P->DataType == BYTE_DATA) {
  725. if ((P->CurrentOpcode & 0x8) == 0) {
  726. P->SrcValue.Long = (ULONG)P->SrcValue.Byte;
  727. } else {
  728. P->SrcValue.Long = (ULONG)((LONG)((SCHAR)P->SrcValue.Byte));
  729. }
  730. } else {
  731. if ((P->CurrentOpcode & 0x8) == 0) {
  732. P->SrcValue.Long = (ULONG)P->SrcValue.Word;
  733. } else {
  734. P->SrcValue.Long = (ULONG)((LONG)((SHORT)P->SrcValue.Word));
  735. }
  736. }
  737. if (P->OpsizePrefixActive != FALSE) {
  738. P->DataType = LONG_DATA;
  739. } else {
  740. P->DataType = WORD_DATA;
  741. P->SrcValue.Long &= 0xffff;
  742. }
  743. P->DstLong = (UNALIGNED ULONG *)(&P->Gpr[Number].Exx);
  744. return TRUE;
  745. }
  746. ULONG
  747. XmFlagsRegister (
  748. IN PRXM_CONTEXT P
  749. )
  750. /*++
  751. Routine Description:
  752. This function decodes x86 operand specifiers for the following opcodes:
  753. xxxxxx
  754. Arguments:
  755. P - Supplies a pointer to an emulator context structure.
  756. Return Value:
  757. A completion status of TRUE is returned as the function value.
  758. --*/
  759. {
  760. //
  761. // Flags register source or destination with a stack source or
  762. // destination.
  763. //
  764. if (P->OpsizePrefixActive != FALSE) {
  765. P->DataType = LONG_DATA;
  766. } else {
  767. P->DataType = WORD_DATA;
  768. }
  769. if (P->FunctionIndex == X86_PUSH_OP) {
  770. XmSetSourceValue(P, (PVOID)(&P->AllFlags));
  771. } else {
  772. XmSetDestinationValue(P, (PVOID)(&P->AllFlags));
  773. }
  774. return TRUE;
  775. }
  776. ULONG
  777. XmPushImmediate (
  778. IN PRXM_CONTEXT P
  779. )
  780. /*++
  781. Routine Description:
  782. This function decodes x86 operand specifiers for the following opcodes:
  783. xxxxxx
  784. Arguments:
  785. P - Supplies a pointer to an emulator context structure.
  786. Return Value:
  787. A completion status of TRUE is returned as the function value.
  788. --*/
  789. {
  790. ULONG Source;
  791. //
  792. // Push opcode with an immediate operand.
  793. //
  794. if (P->OpsizePrefixActive != FALSE) {
  795. P->DataType = LONG_DATA;
  796. } else {
  797. P->DataType = WORD_DATA;
  798. }
  799. Source = XmGetImmediateSourceValue(P, P->CurrentOpcode & SIGN_BIT);
  800. XmSetImmediateSourceValue(P, Source);
  801. return TRUE;
  802. }
  803. ULONG
  804. XmPopGeneral (
  805. IN PRXM_CONTEXT P
  806. )
  807. /*++
  808. Routine Description:
  809. This function decodes x86 operand specifiers for the following opcodes:
  810. xxxxxx
  811. Arguments:
  812. P - Supplies a pointer to an emulator context structure.
  813. Return Value:
  814. A completion status of TRUE is returned as the function value.
  815. --*/
  816. {
  817. PVOID Operand;
  818. ULONG Number;
  819. //
  820. // Pop opcode with a general specifier.
  821. //
  822. if (P->OpsizePrefixActive != FALSE) {
  823. P->DataType = LONG_DATA;
  824. } else {
  825. P->DataType = WORD_DATA;
  826. }
  827. Operand = XmEvaluateAddressSpecifier(P, &Number);
  828. XmSetDestinationValue(P, Operand);
  829. return TRUE;
  830. }
  831. ULONG
  832. XmImulImmediate (
  833. IN PRXM_CONTEXT P
  834. )
  835. /*++
  836. Routine Description:
  837. This function decodes x86 operand specifiers for the following opcodes:
  838. xxxxxx
  839. Arguments:
  840. P - Supplies a pointer to an emulator context structure.
  841. Return Value:
  842. A completion status of TRUE is returned as the function value.
  843. --*/
  844. {
  845. ULONG Number;
  846. PVOID Operand;
  847. ULONG Source;
  848. //
  849. // Multiply signed opcode with a general specifier and an immediate
  850. // operand.
  851. //
  852. if (P->OpsizePrefixActive != FALSE) {
  853. P->DataType = LONG_DATA;
  854. } else {
  855. P->DataType = WORD_DATA;
  856. }
  857. Operand = XmEvaluateAddressSpecifier(P, &Number);
  858. Source = XmGetImmediateSourceValue(P, P->CurrentOpcode & SIGN_BIT);
  859. XmSetImmediateSourceValue(P, Source);
  860. XmSetDestinationValue(P, Operand);
  861. P->DstLong = (UNALIGNED ULONG *)(&P->Gpr[Number].Exx);
  862. return TRUE;
  863. }
  864. ULONG
  865. XmStringOperands (
  866. IN PRXM_CONTEXT P
  867. )
  868. /*++
  869. Routine Description:
  870. This function decodes x86 operand specifiers for the following opcodes:
  871. xxxxxx
  872. Arguments:
  873. P - Supplies a pointer to an emulator context structure.
  874. Return Value:
  875. A completion status of TRUE is returned as the function value.
  876. --*/
  877. {
  878. //
  879. // String opcode with implicit operands of eSI and eDI.
  880. //
  881. XmSetDataType(P);
  882. return TRUE;
  883. }
  884. ULONG
  885. XmEffectiveOffset (
  886. IN PRXM_CONTEXT P
  887. )
  888. /*++
  889. Routine Description:
  890. This function decodes x86 operand specifiers for the following opcodes:
  891. xxxxxx
  892. Arguments:
  893. P - Supplies a pointer to an emulator context structure.
  894. Return Value:
  895. A completion status of TRUE is returned as the function value.
  896. --*/
  897. {
  898. PVOID Operand;
  899. ULONG Number;
  900. //
  901. // Effective offset opcodes with general operand specifier.
  902. //
  903. if (P->OpsizePrefixActive != FALSE) {
  904. P->DataType = LONG_DATA;
  905. } else {
  906. P->DataType = WORD_DATA;
  907. }
  908. P->ComputeOffsetAddress = TRUE;
  909. Operand = XmEvaluateAddressSpecifier(P, &Number);
  910. if (P->RegisterOffsetAddress != FALSE) {
  911. longjmp(&P->JumpBuffer[0], XM_ILLEGAL_REGISTER_SPECIFIER);
  912. }
  913. P->SrcValue.Long = (ULONG)Operand;
  914. XmTraceSource(P, P->SrcValue.Long);
  915. P->DstLong = (ULONG UNALIGNED *)(&P->Gpr[Number].Exx);
  916. return TRUE;
  917. }
  918. ULONG
  919. XmImmediateJump (
  920. IN PRXM_CONTEXT P
  921. )
  922. /*++
  923. Routine Description:
  924. This function decodes x86 operand specifiers for the following opcodes:
  925. xxxxxx
  926. Arguments:
  927. P - Supplies a pointer to an emulator context structure.
  928. Return Value:
  929. A completion status of TRUE is returned as the function value.
  930. --*/
  931. {
  932. //
  933. // Immediate long jump with the destination offset and new CS
  934. // segment value. The destination of the jump is stored in the
  935. // destination value and the new CS segment value is stored in
  936. // destination segment.
  937. //
  938. if (P->OpsizePrefixActive != FALSE) {
  939. P->DstValue.Long = XmGetLongImmediate(P);
  940. } else {
  941. P->DstValue.Long = XmGetWordImmediate(P);
  942. }
  943. P->DstSegment = XmGetWordImmediate(P);
  944. return TRUE;
  945. }
  946. ULONG
  947. XmImmediateEnter (
  948. IN PRXM_CONTEXT P
  949. )
  950. /*++
  951. Routine Description:
  952. This function decodes x86 operand specifiers for the following opcodes:
  953. enter
  954. Arguments:
  955. P - Supplies a pointer to an emulator context structure.
  956. Return Value:
  957. A completion status of TRUE is returned as the function value.
  958. --*/
  959. {
  960. //
  961. // Enter operands with an allocation size and level number.
  962. //
  963. P->SrcValue.Long = XmGetWordImmediate(P);
  964. P->DstValue.Long = XmGetByteImmediate(P) & 0x1f;
  965. if (P->OpsizePrefixActive != FALSE) {
  966. P->DataType = LONG_DATA;
  967. } else {
  968. P->DataType = WORD_DATA;
  969. }
  970. return TRUE;
  971. }
  972. ULONG
  973. XmGeneralBitOffset (
  974. IN PRXM_CONTEXT P
  975. )
  976. /*++
  977. Routine Description:
  978. This function decodes x86 operand specifiers for the following opcodes:
  979. xxxxxx
  980. Arguments:
  981. P - Supplies a pointer to an emulator context structure.
  982. Return Value:
  983. A completion status of TRUE is returned as the function value.
  984. --*/
  985. {
  986. PVOID Operand;
  987. ULONG Offset;
  988. ULONG Number;
  989. //
  990. // Bit test opcodes with a register bit offset and a memory or
  991. // register operand.
  992. //
  993. if (P->OpsizePrefixActive != FALSE) {
  994. P->DataType = LONG_DATA;
  995. } else {
  996. P->DataType = WORD_DATA;
  997. }
  998. Operand = XmEvaluateAddressSpecifier(P, &Number);
  999. XmSetSourceValue(P, (PVOID)(&P->Gpr[Number].Exx));
  1000. if (P->RegisterOffsetAddress == FALSE) {
  1001. if (P->DataType == LONG_DATA) {
  1002. Offset = (P->SrcValue.Long >> 5) << 2;
  1003. } else {
  1004. Offset = (P->SrcValue.Long >> 4) << 1;
  1005. }
  1006. Operand = XmGetOffsetAddress(P, Offset + P->Offset);
  1007. }
  1008. if (P->DataType == LONG_DATA) {
  1009. P->SrcValue.Long &= 0x1f;
  1010. } else {
  1011. P->SrcValue.Long &= 0xf;
  1012. }
  1013. XmSetDestinationValue(P, Operand);
  1014. return TRUE;
  1015. }
  1016. ULONG
  1017. XmShiftDouble (
  1018. IN PRXM_CONTEXT P
  1019. )
  1020. /*++
  1021. Routine Description:
  1022. This function decodes x86 operand specifiers for the following opcodes:
  1023. shld shrd
  1024. Arguments:
  1025. P - Supplies a pointer to an emulator context structure.
  1026. Return Value:
  1027. A completion status of TRUE is returned as the function value.
  1028. --*/
  1029. {
  1030. PVOID Operand;
  1031. ULONG Number;
  1032. ULONG Source;
  1033. //
  1034. // Shift double operators with an immediate byte or cl shift count.
  1035. //
  1036. if (P->OpsizePrefixActive != FALSE) {
  1037. P->DataType = LONG_DATA;
  1038. } else {
  1039. P->DataType = WORD_DATA;
  1040. }
  1041. Operand = XmEvaluateAddressSpecifier(P, &Number);
  1042. if ((P->CurrentOpcode & 0x1) == 0) {
  1043. Source = XmGetByteImmediate(P);
  1044. } else {
  1045. Source = P->Gpr[CX].Xl;
  1046. }
  1047. if (P->DataType == LONG_DATA) {
  1048. P->Shift = (UCHAR)(Source & 0x1f);
  1049. } else {
  1050. P->Shift = (UCHAR)(Source & 0xf);
  1051. }
  1052. XmSetSourceValue(P, (PVOID)(&P->Gpr[Number].Exx));
  1053. XmSetDestinationValue(P, Operand);
  1054. return TRUE;
  1055. }
  1056. ULONG
  1057. XmPortImmediate (
  1058. IN PRXM_CONTEXT P
  1059. )
  1060. /*++
  1061. Routine Description:
  1062. This function decodes x86 operand specifiers for the following opcodes:
  1063. xxxxxx
  1064. Arguments:
  1065. P - Supplies a pointer to an emulator context structure.
  1066. Return Value:
  1067. A completion status of TRUE is returned as the function value.
  1068. --*/
  1069. {
  1070. ULONG Source;
  1071. //
  1072. // In/out opcodes with an immediate port and all other operands implied.
  1073. //
  1074. Source = (ULONG)XmGetByteImmediate(P);
  1075. P->DataType = WORD_DATA;
  1076. XmSetImmediateSourceValue(P, Source);
  1077. XmSetDataType(P);
  1078. return TRUE;
  1079. }
  1080. ULONG
  1081. XmPortDX (
  1082. IN PRXM_CONTEXT P
  1083. )
  1084. /*++
  1085. Routine Description:
  1086. This function decodes x86 operand specifiers for the following opcodes:
  1087. xxxxxx
  1088. Arguments:
  1089. P - Supplies a pointer to an emulator context structure.
  1090. Return Value:
  1091. A completion status of TRUE is returned as the function value.
  1092. --*/
  1093. {
  1094. ULONG Source;
  1095. //
  1096. // In/out opcodes with a port in DX with all other operands implied.
  1097. //
  1098. Source = P->Gpr[DX].Xx;
  1099. P->DataType = WORD_DATA;
  1100. XmSetImmediateSourceValue(P, Source);
  1101. XmSetDataType(P);
  1102. return TRUE;
  1103. }
  1104. ULONG
  1105. XmBitScanGeneral (
  1106. IN PRXM_CONTEXT P
  1107. )
  1108. /*++
  1109. Routine Description:
  1110. This function decodes x86 operand specifiers for the following opcodes:
  1111. xxxxxx
  1112. Arguments:
  1113. P - Supplies a pointer to an emulator context structure.
  1114. Return Value:
  1115. A completion status of TRUE is returned as the function value.
  1116. --*/
  1117. {
  1118. PVOID Operand;
  1119. ULONG Number;
  1120. //
  1121. // Bit scan general opcodes with general operand specifier.
  1122. // bit.
  1123. //
  1124. if (P->OpsizePrefixActive != FALSE) {
  1125. P->DataType = LONG_DATA;
  1126. } else {
  1127. P->DataType = WORD_DATA;
  1128. }
  1129. Operand = XmEvaluateAddressSpecifier(P, &Number);
  1130. P->DstLong = (ULONG UNALIGNED *)(&P->Gpr[Number].Exx);
  1131. XmSetSourceValue(P, Operand);
  1132. return TRUE;
  1133. }
  1134. ULONG
  1135. XmByteImmediate (
  1136. IN PRXM_CONTEXT P
  1137. )
  1138. /*++
  1139. Routine Description:
  1140. This function decodes x86 operand specifiers for the following opcodes:
  1141. int xxxxxx
  1142. Arguments:
  1143. P - Supplies a pointer to an emulator context structure.
  1144. Return Value:
  1145. A completion status of TRUE is returned as the function value.
  1146. --*/
  1147. {
  1148. ULONG Source;
  1149. //
  1150. // int opcode with an immediate operand.
  1151. //
  1152. P->DataType = BYTE_DATA;
  1153. Source = XmGetImmediateSourceValue(P, 0);
  1154. XmSetImmediateSourceValue(P, Source);
  1155. return TRUE;
  1156. }
  1157. ULONG
  1158. XmXlatOpcode (
  1159. IN PRXM_CONTEXT P
  1160. )
  1161. /*++
  1162. Routine Description:
  1163. This function decodes x86 operand specifiers for the following opcodes:
  1164. xlat
  1165. Arguments:
  1166. P - Supplies a pointer to an emulator context structure.
  1167. Return Value:
  1168. A completion status of TRUE is returned as the function value.
  1169. --*/
  1170. {
  1171. PVOID Operand;
  1172. ULONG Offset;
  1173. //
  1174. // xlat opcode with zero extended [AL] + [eBX] as the effective
  1175. // address.
  1176. //
  1177. P->DataType = BYTE_DATA;
  1178. if (P->OpaddrPrefixActive != FALSE) {
  1179. Offset = P->Gpr[EBX].Exx + P->Gpr[AL].Xl;
  1180. } else {
  1181. Offset = P->Gpr[BX].Xx + P->Gpr[AL].Xl;
  1182. }
  1183. Operand = XmGetOffsetAddress(P, Offset);
  1184. XmSetSourceValue(P, Operand);
  1185. P->DstByte = (UCHAR UNALIGNED *)(&P->Gpr[AL].Xl);
  1186. return TRUE;
  1187. }
  1188. ULONG
  1189. XmGeneralRegister (
  1190. IN PRXM_CONTEXT P
  1191. )
  1192. /*++
  1193. Routine Description:
  1194. This function decodes x86 operand specifiers for the following opcodes:
  1195. bswap
  1196. Arguments:
  1197. P - Supplies a pointer to an emulator context structure.
  1198. Return Value:
  1199. A completion status of TRUE is returned as the function value.
  1200. --*/
  1201. {
  1202. PVOID Operand;
  1203. ULONG Number;
  1204. //
  1205. // General register source and destination.
  1206. //
  1207. if (P->OpsizePrefixActive != FALSE) {
  1208. P->DataType = LONG_DATA;
  1209. } else {
  1210. P->DataType = WORD_DATA;
  1211. }
  1212. Operand = XmEvaluateAddressSpecifier(P, &Number);
  1213. if (P->RegisterOffsetAddress == FALSE) {
  1214. longjmp(&P->JumpBuffer[0], XM_ILLEGAL_GENERAL_SPECIFIER);
  1215. }
  1216. XmSetSourceValue(P, (PVOID)(&P->Gpr[Number].Exx));
  1217. P->DstLong = (ULONG UNALIGNED *)(&P->Gpr[Number].Exx);
  1218. return TRUE;
  1219. }
  1220. ULONG
  1221. XmOpcodeEscape (
  1222. IN PRXM_CONTEXT P
  1223. )
  1224. /*++
  1225. Routine Description:
  1226. This function decodes x86 operand specifiers for the following opcodes:
  1227. 2-byte escape
  1228. Arguments:
  1229. P - Supplies a pointer to an emulator context structure.
  1230. Return Value:
  1231. A completion status of xx is returned as the function value.
  1232. --*/
  1233. {
  1234. //
  1235. // Two byte opcode escape.
  1236. //
  1237. P->OpcodeControlTable = &XmOpcodeControlTable2[0];
  1238. #if defined(XM_DEBUG)
  1239. P->OpcodeNameTable = &XmOpcodeNameTable2[0];
  1240. #endif
  1241. return FALSE;
  1242. }
  1243. ULONG
  1244. XmPrefixOpcode (
  1245. IN PRXM_CONTEXT P
  1246. )
  1247. /*++
  1248. Routine Description:
  1249. This function decodes x86 operand specifiers for the following opcodes:
  1250. CS: DS; ES: SS: FS: GS: lock adrsize
  1251. opsize repz repnz
  1252. Arguments:
  1253. P - Supplies a pointer to an emulator context structure.
  1254. Return Value:
  1255. A completion status of FALSE is returned as the function value.
  1256. --*/
  1257. {
  1258. //
  1259. // Case on the function index.
  1260. //
  1261. switch (P->FunctionIndex) {
  1262. //
  1263. // Segment override prefix.
  1264. //
  1265. // Set the segment override prefix flags and the data segment
  1266. // number.
  1267. //
  1268. case X86_ES_OP:
  1269. case X86_CS_OP:
  1270. case X86_SS_OP:
  1271. case X86_DS_OP:
  1272. case X86_FS_OP:
  1273. case X86_GS_OP:
  1274. P->SegmentPrefixActive = TRUE;
  1275. P->DataSegment = P->FunctionIndex;
  1276. XmTraceOverride(P);
  1277. break;
  1278. //
  1279. // Lock prefix.
  1280. //
  1281. // Set the lock prefix flags.
  1282. //
  1283. case X86_LOCK_OP:
  1284. P->LockPrefixActive = TRUE;
  1285. break;
  1286. //
  1287. // Address size prefix.
  1288. //
  1289. // Set the address size prefix flag.
  1290. //
  1291. case X86_ADSZ_OP:
  1292. P->OpaddrPrefixActive = TRUE;
  1293. break;
  1294. //
  1295. // Operand size prefix.
  1296. //
  1297. // Set the operand size prefix flag.
  1298. //
  1299. case X86_OPSZ_OP:
  1300. P->OpsizePrefixActive = TRUE;
  1301. break;
  1302. //
  1303. // Repeat until ECX or ZF equals zero
  1304. //
  1305. // Set up repeat until ECX or ZF equals zero prefix flags.
  1306. //
  1307. case X86_REPZ_OP:
  1308. P->RepeatPrefixActive = TRUE;
  1309. P->RepeatZflag = 1;
  1310. break;
  1311. //
  1312. // Repeat until ECX equals zero or ZF equals one.
  1313. //
  1314. // Set up repeat until ECX equals zero or ZF equals one prefix
  1315. // flags.
  1316. //
  1317. case X86_REPNZ_OP:
  1318. P->RepeatPrefixActive = TRUE;
  1319. P->RepeatZflag = 0;
  1320. break;
  1321. }
  1322. return FALSE;
  1323. }
  1324. ULONG
  1325. XmNoOperands (
  1326. IN PRXM_CONTEXT P
  1327. )
  1328. /*++
  1329. Routine Description:
  1330. This function decodes x86 operand specifiers for the following opcodes:
  1331. xxxxxx
  1332. Arguments:
  1333. P - Supplies a pointer to an emulator context structure.
  1334. Return Value:
  1335. A completion status of TRUE is returned as the function value.
  1336. --*/
  1337. {
  1338. return TRUE;
  1339. }