Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2036 lines
38 KiB

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