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.

1241 lines
25 KiB

  1. /*++
  2. Copyright (c) 1994 Microsoft Corporation
  3. Module Name:
  4. regmode.c
  5. Abstract:
  6. This module implements the code necessary to decode the address
  7. mode specifier byte.
  8. N.B. This routine could be probably be more tightly encoded with a
  9. loss of clarity.
  10. Author:
  11. David N. Cutler (davec) 10-Sep-1994
  12. Environment:
  13. Kernel mode only.
  14. Revision History:
  15. --*/
  16. #include "nthal.h"
  17. #include "emulate.h"
  18. //
  19. // Define forward referenced function prototypes.
  20. //
  21. ULONG
  22. XmEvaluateIndexSpecifier (
  23. IN PRXM_CONTEXT P,
  24. IN ULONG Mode
  25. );
  26. PVOID
  27. XmEvaluateAddressSpecifier (
  28. IN PRXM_CONTEXT P,
  29. OUT PLONG Number
  30. )
  31. /*++
  32. Routine Description:
  33. This function decodes x86 operand specifiers.
  34. Arguments:
  35. P - Supplies a pointer to an emulator context structure.
  36. Number - Supplies a pointer to a variable that receives the register
  37. number selected by the reg field of the operand specifier.
  38. Operand - Supplies a pointer to a variable that receives the address
  39. of the operand specified by the mod-r/m field of the operand
  40. specifier.
  41. Return Value:
  42. None.
  43. --*/
  44. {
  45. ULONG DispatchIndex;
  46. ULONG Mode;
  47. ULONG Modifier;
  48. ULONG Offset;
  49. ULONG Register;
  50. UCHAR SpecifierByte;
  51. PVOID Address;
  52. //
  53. // Get the next byte from the instruction stream and isolate
  54. // the fields. The format of an operand specifier byte is:
  55. //
  56. // <7:6> - Mode
  57. // <5:3> - Operand Register
  58. // <2:0> - Modifier
  59. //
  60. SpecifierByte = XmGetCodeByte(P);
  61. XmTraceSpecifier(SpecifierByte);
  62. Mode = (SpecifierByte >> 6) & 0x3;
  63. Modifier = SpecifierByte & 0x7;
  64. Register = (SpecifierByte >> 3) & 0x7;
  65. DispatchIndex = (Mode << 3) | (Modifier);
  66. P->RegisterOffsetAddress = FALSE;
  67. //
  68. // Set the segment base address and select between 16- and 32-bit
  69. // addressing.
  70. //
  71. *Number = Register;
  72. if (P->OpaddrPrefixActive != FALSE) {
  73. //
  74. // 32-bit addressing.
  75. //
  76. // Case on dispatch index.
  77. //
  78. switch (DispatchIndex) {
  79. //
  80. // 00-000 DS:[EAX]
  81. //
  82. case 0:
  83. Offset = P->Gpr[EAX].Exx;
  84. break;
  85. //
  86. // 00-001 DS:[ECX]
  87. //
  88. case 1:
  89. Offset = P->Gpr[ECX].Exx;
  90. break;
  91. //
  92. // 00-010 DS:[EDX]
  93. //
  94. case 2:
  95. Offset = P->Gpr[EDX].Exx;
  96. break;
  97. //
  98. // 00-011 DS:[EBX]
  99. //
  100. case 3:
  101. Offset = P->Gpr[EBX].Exx;
  102. break;
  103. //
  104. // 00-100 - scale index byte
  105. //
  106. case 4:
  107. Offset = XmEvaluateIndexSpecifier(P, Mode);
  108. break;
  109. //
  110. // 00-101 DS:d32
  111. //
  112. case 5:
  113. Offset = XmGetLongImmediate(P);
  114. break;
  115. //
  116. // 00-110 DS:[ESI]
  117. //
  118. case 6:
  119. Offset = P->Gpr[ESI].Exx;
  120. break;
  121. //
  122. // 00-111 DS:[EDI]
  123. //
  124. case 7:
  125. Offset = P->Gpr[EDI].Exx;
  126. break;
  127. //
  128. // 01-000 DS:[EAX + d8]
  129. //
  130. case 8:
  131. Offset = P->Gpr[EAX].Exx + XmGetSignedByteImmediateToLong(P);
  132. break;
  133. //
  134. // 01-001 DS:[ECX + d8]
  135. //
  136. case 9:
  137. Offset = P->Gpr[ECX].Exx + XmGetSignedByteImmediateToLong(P);
  138. break;
  139. //
  140. // 01-010 DS:[EDX + d8]
  141. //
  142. case 10:
  143. Offset = P->Gpr[EDX].Exx + XmGetSignedByteImmediateToLong(P);
  144. break;
  145. //
  146. // 01-011 DS:[EBX + d8]
  147. //
  148. case 11:
  149. Offset = P->Gpr[EBX].Exx + XmGetSignedByteImmediateToLong(P);
  150. break;
  151. //
  152. // 01-100 - scale index byte
  153. //
  154. case 12:
  155. Offset = XmEvaluateIndexSpecifier(P, Mode);
  156. break;
  157. //
  158. // 01-101 DS:[EBP + d8]
  159. //
  160. case 13:
  161. Offset = P->Gpr[EBP].Exx + XmGetSignedByteImmediateToLong(P);
  162. if (P->SegmentPrefixActive == FALSE) {
  163. P->DataSegment = SS;
  164. }
  165. break;
  166. //
  167. // 01-110 DS:[ESI + d8]
  168. //
  169. case 14:
  170. Offset = P->Gpr[ESI].Exx + XmGetSignedByteImmediateToLong(P);
  171. break;
  172. //
  173. // 01-111 DS:[EDI + d8]
  174. //
  175. case 15:
  176. Offset = P->Gpr[EDI].Exx + XmGetSignedByteImmediateToLong(P);
  177. break;
  178. //
  179. // 10-000 DS:[EAX + d32]
  180. //
  181. case 16:
  182. Offset = P->Gpr[EAX].Exx + XmGetLongImmediate(P);
  183. break;
  184. //
  185. // 10-001 DS:[ECX + d32]
  186. //
  187. case 17:
  188. Offset = P->Gpr[ECX].Exx + XmGetLongImmediate(P);
  189. break;
  190. //
  191. // 10-010 DS:[EDX + d32]
  192. //
  193. case 18:
  194. Offset = P->Gpr[EDX].Exx + XmGetLongImmediate(P);
  195. break;
  196. //
  197. // 10-011 DS:[EBX + d32]
  198. //
  199. case 19:
  200. Offset = P->Gpr[EBX].Exx + XmGetLongImmediate(P);
  201. break;
  202. //
  203. // 10-100 - scale index byte
  204. //
  205. case 20:
  206. Offset = XmEvaluateIndexSpecifier(P, Mode);
  207. break;
  208. //
  209. // 10-101 DS:[EBP + d32]
  210. //
  211. case 21:
  212. Offset = P->Gpr[EBP].Exx + XmGetLongImmediate(P);
  213. if (P->SegmentPrefixActive == FALSE) {
  214. P->DataSegment = SS;
  215. }
  216. break;
  217. //
  218. // 10-110 DS:[ESI + d32]
  219. //
  220. case 22:
  221. Offset = P->Gpr[ESI].Exx + XmGetLongImmediate(P);
  222. break;
  223. //
  224. // 10-111 DS:[EDI + d32]
  225. //
  226. case 23:
  227. Offset = P->Gpr[EDI].Exx + XmGetLongImmediate(P);
  228. break;
  229. //
  230. // 11-xxx - Register mode.
  231. //
  232. case 24:
  233. case 25:
  234. case 26:
  235. case 27:
  236. case 28:
  237. case 29:
  238. case 30:
  239. case 31:
  240. P->RegisterOffsetAddress = TRUE;
  241. return XmGetRegisterAddress(P, Modifier);
  242. }
  243. } else {
  244. //
  245. // 16-bit addressing.
  246. //
  247. // Case on dispatch index.
  248. //
  249. switch (DispatchIndex) {
  250. //
  251. // 00-000 DS:[BX + SI]
  252. //
  253. case 0:
  254. Offset = (USHORT)(P->Gpr[BX].Xx + P->Gpr[SI].Xx);
  255. break;
  256. //
  257. // 00-001 DS:[BX + DI]
  258. //
  259. case 1:
  260. Offset = (USHORT)(P->Gpr[BX].Xx + P->Gpr[DI].Xx);
  261. break;
  262. //
  263. // 00-010 SS:[BP + SI]
  264. //
  265. case 2:
  266. Offset = (USHORT)(P->Gpr[BP].Xx + P->Gpr[SI].Xx);
  267. if (P->SegmentPrefixActive == FALSE) {
  268. P->DataSegment = SS;
  269. }
  270. break;
  271. //
  272. // 00-011 SS:[BP + DI]
  273. //
  274. case 3:
  275. Offset = (USHORT)(P->Gpr[BP].Xx + P->Gpr[DI].Xx);
  276. if (P->SegmentPrefixActive == FALSE) {
  277. P->DataSegment = SS;
  278. }
  279. break;
  280. //
  281. // 00-100 DS:[SI]
  282. //
  283. case 4:
  284. Offset = (USHORT)(P->Gpr[SI].Xx);
  285. break;
  286. //
  287. // 00-101 DS:[DI]
  288. //
  289. case 5:
  290. Offset = (USHORT)(P->Gpr[DI].Xx);
  291. break;
  292. //
  293. // 00-110 DS:d16
  294. //
  295. case 6:
  296. Offset = XmGetWordImmediate(P);
  297. break;
  298. //
  299. // 00-111 DS:[BX]
  300. //
  301. case 7:
  302. Offset = (USHORT)(P->Gpr[BX].Xx);
  303. break;
  304. //
  305. // 01-000 DS:[BX + SI + d8]
  306. //
  307. case 8:
  308. Offset = (USHORT)(P->Gpr[BX].Xx + P->Gpr[SI].Xx + XmGetSignedByteImmediateToWord(P));
  309. break;
  310. //
  311. // 01-001 DS:[BX + DI + d8]
  312. //
  313. case 9:
  314. Offset = (USHORT)(P->Gpr[BX].Xx + P->Gpr[DI].Xx + XmGetSignedByteImmediateToWord(P));
  315. break;
  316. //
  317. // 01-010 SS:[BP + SI + d8]
  318. //
  319. case 10:
  320. Offset = (USHORT)(P->Gpr[BP].Xx + P->Gpr[SI].Xx + XmGetSignedByteImmediateToWord(P));
  321. if (P->SegmentPrefixActive == FALSE) {
  322. P->DataSegment = SS;
  323. }
  324. break;
  325. //
  326. // 01-011 SS:[BP + DI + d8]
  327. //
  328. case 11:
  329. Offset = (USHORT)(P->Gpr[BP].Xx + P->Gpr[DI].Xx + XmGetSignedByteImmediateToWord(P));
  330. if (P->SegmentPrefixActive == FALSE) {
  331. P->DataSegment = SS;
  332. }
  333. break;
  334. //
  335. // 01-100 DS:[SI + d8]
  336. //
  337. case 12:
  338. Offset = (USHORT)(P->Gpr[SI].Xx + XmGetSignedByteImmediateToWord(P));
  339. break;
  340. //
  341. // 01-101 DS:[DI + d8]
  342. //
  343. case 13:
  344. Offset = (USHORT)(P->Gpr[DI].Xx + XmGetSignedByteImmediateToWord(P));
  345. break;
  346. //
  347. // 01-110 DS:[BP + d8]
  348. //
  349. case 14:
  350. Offset = (USHORT)(P->Gpr[BP].Xx + XmGetSignedByteImmediateToWord(P));
  351. if (P->SegmentPrefixActive == FALSE) {
  352. P->DataSegment = SS;
  353. }
  354. break;
  355. //
  356. // 01-111 DS:[BX + d8]
  357. //
  358. case 15:
  359. Offset = (USHORT)(P->Gpr[BX].Xx + XmGetSignedByteImmediateToWord(P));
  360. break;
  361. //
  362. // 10-000 DS:[BX + SI + d16]
  363. //
  364. case 16:
  365. Offset = (USHORT)(P->Gpr[BX].Xx + P->Gpr[SI].Xx + XmGetWordImmediate(P));
  366. break;
  367. //
  368. // 10-001 DS:[BX + DI + d16]
  369. //
  370. case 17:
  371. Offset = (USHORT)(P->Gpr[BX].Xx + P->Gpr[DI].Xx + XmGetWordImmediate(P));
  372. break;
  373. //
  374. // 10-010 SS:[BP + SI + d16]
  375. //
  376. case 18:
  377. Offset = (USHORT)(P->Gpr[BP].Xx + P->Gpr[SI].Xx + XmGetWordImmediate(P));
  378. if (P->SegmentPrefixActive == FALSE) {
  379. P->DataSegment = SS;
  380. }
  381. break;
  382. //
  383. // 10-011 SS:[BP + DI + d16]
  384. //
  385. case 19:
  386. Offset = (USHORT)(P->Gpr[BP].Xx + P->Gpr[DI].Xx + XmGetWordImmediate(P));
  387. if (P->SegmentPrefixActive == FALSE) {
  388. P->DataSegment = SS;
  389. }
  390. break;
  391. //
  392. // 10-100 DS:[SI + d16]
  393. //
  394. case 20:
  395. Offset = (USHORT)(P->Gpr[SI].Xx + XmGetWordImmediate(P));
  396. break;
  397. //
  398. // 10-101 DS:[DI + d16]
  399. //
  400. case 21:
  401. Offset = (USHORT)(P->Gpr[DI].Xx + XmGetWordImmediate(P));
  402. break;
  403. //
  404. // 10-110 DS:[BP + d16]
  405. //
  406. case 22:
  407. Offset = (USHORT)(P->Gpr[BP].Xx + XmGetWordImmediate(P));
  408. if (P->SegmentPrefixActive == FALSE) {
  409. P->DataSegment = SS;
  410. }
  411. break;
  412. //
  413. // 10-111 DS:[BX + d16]
  414. //
  415. case 23:
  416. Offset = (USHORT)(P->Gpr[BX].Xx + XmGetWordImmediate(P));
  417. break;
  418. //
  419. // 11-xxx - Register mode.
  420. //
  421. case 24:
  422. case 25:
  423. case 26:
  424. case 27:
  425. case 28:
  426. case 29:
  427. case 30:
  428. case 31:
  429. P->RegisterOffsetAddress = TRUE;
  430. return XmGetRegisterAddress(P, Modifier);
  431. }
  432. }
  433. //
  434. // If an effective offset is being calculated, then return the offset
  435. // value. Otherwise, If the offset displacement value plus the datum
  436. // size is not within the segment limits, then raise an exception.
  437. // Otherwise, compute the operand address.
  438. //
  439. if (P->ComputeOffsetAddress != FALSE) {
  440. if (P->DataType == WORD_DATA) {
  441. Offset &= 0xffff;
  442. }
  443. P->Offset = Offset;
  444. Address = UlongToPtr(Offset);
  445. } else {
  446. if ((Offset > P->SegmentLimit[P->DataSegment]) ||
  447. ((Offset + P->DataType) > P->SegmentLimit[P->DataSegment])) {
  448. longjmp(&P->JumpBuffer[0], XM_SEGMENT_LIMIT_VIOLATION);
  449. } else {
  450. P->Offset = Offset;
  451. Address = (PVOID)(ULONG_PTR)(P->TranslateAddress)(P->SegmentRegister[P->DataSegment],
  452. (USHORT)Offset);
  453. }
  454. }
  455. return Address;
  456. }
  457. ULONG
  458. XmEvaluateIndexSpecifier (
  459. IN PRXM_CONTEXT P,
  460. IN ULONG Mode
  461. )
  462. /*++
  463. Routine Description:
  464. This function evaluates a index specifier byte.
  465. Arguments:
  466. P - Supplies a pointer to an emulator context structure.
  467. Mode - Supplies the mode of the address specifier.
  468. Return Value:
  469. The offset value computes from the index specifier.
  470. --*/
  471. {
  472. ULONG DispatchIndex;
  473. ULONG Modifier;
  474. ULONG Offset;
  475. ULONG Register;
  476. ULONG Scale;
  477. UCHAR SpecifierByte;
  478. //
  479. // Get the next byte from the instruction stream and isolate the
  480. // specifier fields. The format of an scale/index byte is:
  481. //
  482. // <7:6> - Scale
  483. // <5:3> - Index register
  484. // <2:0> - Modifier
  485. //
  486. SpecifierByte = XmGetCodeByte(P);
  487. XmTraceInstruction(BYTE_DATA, (ULONG)SpecifierByte);
  488. Scale = (SpecifierByte >> 6) & 0x3;
  489. Modifier = SpecifierByte & 0x7;
  490. Register = (SpecifierByte >> 3) & 0x7;
  491. DispatchIndex = (Mode << 3) | (Modifier);
  492. //
  493. // Case of dispatch index.
  494. //
  495. switch (DispatchIndex) {
  496. //
  497. // 00-000 DS:[EAX + scaled index]
  498. //
  499. case 0:
  500. Offset = P->Gpr[EAX].Exx;
  501. break;
  502. //
  503. // 00-001 DS:[ECX + scaled index]
  504. //
  505. case 1:
  506. Offset = P->Gpr[ECX].Exx;
  507. break;
  508. //
  509. // 00-010 DS:[EDX + scaled index]
  510. //
  511. case 2:
  512. Offset = P->Gpr[EDX].Exx;
  513. break;
  514. //
  515. // 00-011 DS:[EBX + scaled index]
  516. //
  517. case 3:
  518. Offset = P->Gpr[EBX].Exx;
  519. break;
  520. //
  521. // 00-100 SS:[ESP + scaled index]
  522. //
  523. case 4:
  524. Offset = P->Gpr[ESP].Exx;
  525. if (P->SegmentPrefixActive == FALSE) {
  526. P->DataSegment = SS;
  527. }
  528. break;
  529. //
  530. // 00-101 DS:[d32 + scaled index]
  531. //
  532. case 5:
  533. Offset = XmGetLongImmediate(P);
  534. break;
  535. //
  536. // 00-110 DS:[ESI + scaled index]
  537. //
  538. case 6:
  539. Offset = P->Gpr[ESI].Exx;
  540. break;
  541. //
  542. // 00-111 DS:[EDI + scaled index]
  543. //
  544. case 7:
  545. Offset = P->Gpr[EDI].Exx;
  546. break;
  547. //
  548. // 01-000 DS:[EAX + scaled index + d8]
  549. //
  550. case 8:
  551. Offset = P->Gpr[EAX].Exx + XmGetSignedByteImmediateToLong(P);
  552. break;
  553. //
  554. // 01-001 DS:[ECX + scaled index + d8]
  555. //
  556. case 9:
  557. Offset = P->Gpr[ECX].Exx + XmGetSignedByteImmediateToLong(P);
  558. break;
  559. //
  560. // 01-010 DS:[EDX + scaled index + d8]
  561. //
  562. case 10:
  563. Offset = P->Gpr[EDX].Exx + XmGetSignedByteImmediateToLong(P);
  564. break;
  565. //
  566. // 01-011 DS:[EBX + scaled index + d8]
  567. //
  568. case 11:
  569. Offset = P->Gpr[EBX].Exx + XmGetSignedByteImmediateToLong(P);
  570. break;
  571. //
  572. // 01-100 SS:[ESP + scaled index + d8]
  573. //
  574. case 12:
  575. Offset = P->Gpr[ESP].Exx + XmGetSignedByteImmediateToLong(P);
  576. if (P->SegmentPrefixActive == FALSE) {
  577. P->DataSegment = SS;
  578. }
  579. break;
  580. //
  581. // 01-101 DS:[EBP + scaled index + d8]
  582. //
  583. case 13:
  584. Offset = P->Gpr[EBP].Exx + XmGetSignedByteImmediateToLong(P);
  585. if (P->SegmentPrefixActive == FALSE) {
  586. P->DataSegment = SS;
  587. }
  588. break;
  589. //
  590. // 01-110 DS:[ESI + scaled index + d8]
  591. //
  592. case 14:
  593. Offset = P->Gpr[ESI].Exx + XmGetSignedByteImmediateToLong(P);
  594. break;
  595. //
  596. // 01-111 DS:[EDI + scaled index + d8]
  597. //
  598. case 15:
  599. Offset = P->Gpr[EDI].Exx + XmGetSignedByteImmediateToLong(P);
  600. break;
  601. //
  602. // 10-000 DS:[EAX + scaled index + d32]
  603. //
  604. case 16:
  605. Offset = P->Gpr[EAX].Exx + XmGetLongImmediate(P);
  606. break;
  607. //
  608. // 10-001 DS:[ECX + scaled index + d32]
  609. //
  610. case 17:
  611. Offset = P->Gpr[ECX].Exx + XmGetLongImmediate(P);
  612. break;
  613. //
  614. // 10-010 DS:[EDX + scaled index + d32]
  615. //
  616. case 18:
  617. Offset = P->Gpr[EDX].Exx + XmGetLongImmediate(P);
  618. break;
  619. //
  620. // 10-011 DS:[EBX + scaled index + d32]
  621. //
  622. case 19:
  623. Offset = P->Gpr[EBX].Exx + XmGetLongImmediate(P);
  624. break;
  625. //
  626. // 10-100 SS:[ESP + scaled index + d32]
  627. //
  628. case 20:
  629. Offset = P->Gpr[ESP].Exx + XmGetLongImmediate(P);
  630. if (P->SegmentPrefixActive == FALSE) {
  631. P->DataSegment = SS;
  632. }
  633. break;
  634. //
  635. // 10-101 DS:[EBP + scaled index + d32]
  636. //
  637. case 21:
  638. Offset = P->Gpr[EBP].Exx + XmGetLongImmediate(P);
  639. if (P->SegmentPrefixActive == FALSE) {
  640. P->DataSegment = SS;
  641. }
  642. break;
  643. //
  644. // 10-110 DS:[ESI + scaled index + d32]
  645. //
  646. case 22:
  647. Offset = P->Gpr[ESI].Exx + XmGetLongImmediate(P);
  648. break;
  649. //
  650. // 10-111 DS:[EDI + scaled index + d32]
  651. //
  652. case 23:
  653. Offset = P->Gpr[EDI].Exx + XmGetLongImmediate(P);
  654. break;
  655. //
  656. // Illegal mode specifier.
  657. //
  658. default:
  659. longjmp(&P->JumpBuffer[0], XM_ILLEGAL_INDEX_SPECIFIER);
  660. }
  661. //
  662. // Compute the total offset value.
  663. //
  664. return Offset + (P->Gpr[Register].Exx << Scale);
  665. }
  666. PVOID
  667. XmGetOffsetAddress (
  668. IN PRXM_CONTEXT P,
  669. IN ULONG Offset
  670. )
  671. /*++
  672. Routine Description:
  673. This function evaluates a data segment address given a specified
  674. offset.
  675. Arguments:
  676. P - Supplies a pointer to an emulator context structure.
  677. Offset - Supplies the offset value.
  678. Return Value:
  679. A pointer to the operand value.
  680. --*/
  681. {
  682. //
  683. // If the offset displacement value plus the datum size is not within
  684. // the segment limits, then raise an exception. Otherwise, compute the
  685. // operand address.
  686. //
  687. if ((Offset > P->SegmentLimit[P->DataSegment]) ||
  688. ((Offset + P->DataType) > P->SegmentLimit[P->DataSegment])) {
  689. longjmp(&P->JumpBuffer[0], XM_SEGMENT_LIMIT_VIOLATION);
  690. }
  691. return (P->TranslateAddress)(P->SegmentRegister[P->DataSegment], (USHORT)Offset);
  692. }
  693. PVOID
  694. XmGetRegisterAddress (
  695. IN PRXM_CONTEXT P,
  696. IN ULONG Number
  697. )
  698. /*++
  699. Routine Description:
  700. This function computes the address of a register value.
  701. Arguments:
  702. P - Supplies a pointer to an emulator context structure.
  703. Number - Supplies the register number.
  704. Return Value:
  705. A pointer to the register value.
  706. --*/
  707. {
  708. PVOID Value;
  709. //
  710. // If the operand width is a byte, then the register is a
  711. // byte register. Otherwise, the register is a word register.
  712. //
  713. if (P->DataType == BYTE_DATA) {
  714. if (Number < 4) {
  715. Value = (PVOID)&P->Gpr[Number].Xl;
  716. } else {
  717. Value = (PVOID)&P->Gpr[Number - 4].Xh;
  718. }
  719. } else if (P->DataType == WORD_DATA) {
  720. Value = (PVOID)&P->Gpr[Number].Xx;
  721. } else {
  722. Value = (PVOID)&P->Gpr[Number].Exx;
  723. }
  724. return Value;
  725. }
  726. PVOID
  727. XmGetStringAddress (
  728. IN PRXM_CONTEXT P,
  729. IN ULONG Segment,
  730. IN ULONG Register
  731. )
  732. /*++
  733. Routine Description:
  734. This function evaluates a string address.
  735. Arguments:
  736. P - Supplies a pointer to an emulator context structure.
  737. Segment - Supplies the segment number of the string operand.
  738. Register - Supplies the register number of the string operand.
  739. Return Value:
  740. A pointer to the string value.
  741. --*/
  742. {
  743. ULONG Increment;
  744. ULONG Offset;
  745. //
  746. // Get the offset of the specified address and increment the specified
  747. // register.
  748. //
  749. Increment = P->DataType + 1;
  750. if (P->Eflags.EFLAG_DF != 0) {
  751. Increment = ~Increment + 1;
  752. }
  753. if (P->OpaddrPrefixActive != FALSE) {
  754. Offset = P->Gpr[Register].Exx;
  755. P->Gpr[Register].Exx += Increment;
  756. } else {
  757. Offset = P->Gpr[Register].Xx;
  758. P->Gpr[Register].Xx += (USHORT)Increment;
  759. }
  760. //
  761. // If the offset displacement value plus the datum size is not within
  762. // the segment limits, then raise an exception. Otherwise, compute the
  763. // operand address.
  764. //
  765. if ((Offset > P->SegmentLimit[Segment]) ||
  766. ((Offset + P->DataType) > P->SegmentLimit[Segment])) {
  767. longjmp(&P->JumpBuffer[0], XM_SEGMENT_LIMIT_VIOLATION);
  768. }
  769. return (P->TranslateAddress)(P->SegmentRegister[Segment], (USHORT)Offset);
  770. }
  771. VOID
  772. XmSetDestinationValue (
  773. IN PRXM_CONTEXT P,
  774. IN PVOID Destination
  775. )
  776. /*++
  777. Routine Description:
  778. This function stores the destination operand value in the emulator
  779. context.
  780. Arguments:
  781. P - Supplies a pointer to an emulator context structure.
  782. Destination - Supplies a pointer to the destination operand value.
  783. Return Value:
  784. None.
  785. --*/
  786. {
  787. //
  788. // Set address and value of destination.
  789. //
  790. P->DstLong = (ULONG UNALIGNED *)Destination;
  791. if (P->DataType == BYTE_DATA) {
  792. P->DstValue.Long = *(UCHAR *)Destination;
  793. } else if (P->DataType == WORD_DATA) {
  794. if (((ULONG_PTR)Destination & 0x1) == 0) {
  795. P->DstValue.Long = *(USHORT *)Destination;
  796. } else {
  797. P->DstValue.Long = *(USHORT UNALIGNED *)Destination;
  798. }
  799. } else {
  800. if (((ULONG_PTR)Destination & 0x3) == 0) {
  801. P->DstValue.Long = *(ULONG *)Destination;
  802. } else {
  803. P->DstValue.Long = *(ULONG UNALIGNED *)Destination;
  804. }
  805. }
  806. XmTraceDestination(P, P->DstValue.Long);
  807. return;
  808. }
  809. VOID
  810. XmSetSourceValue (
  811. IN PRXM_CONTEXT P,
  812. IN PVOID Source
  813. )
  814. /*++
  815. Routine Description:
  816. This function stores the source operand value in the emulator
  817. context.
  818. Arguments:
  819. P - Supplies a pointer to an emulator context structure.
  820. Source - Supplies a pointer to the source operand value.
  821. Return Value:
  822. None.
  823. --*/
  824. {
  825. //
  826. // Set address and value of source.
  827. //
  828. P->SrcLong = (ULONG UNALIGNED *)Source;
  829. if (P->DataType == BYTE_DATA) {
  830. P->SrcValue.Long = *(UCHAR UNALIGNED *)Source;
  831. } else if (P->DataType == WORD_DATA) {
  832. P->SrcValue.Long = *(USHORT UNALIGNED *)Source;
  833. } else {
  834. P->SrcValue.Long = *(ULONG UNALIGNED *)Source;
  835. }
  836. XmTraceSource(P, P->SrcValue.Long);
  837. return;
  838. }
  839. ULONG
  840. XmGetImmediateSourceValue (
  841. IN PRXM_CONTEXT P,
  842. IN ULONG ByteFlag
  843. )
  844. /*++
  845. Routine Description:
  846. This function gets an immediate source from the instruction stream.
  847. Arguments:
  848. P - Supplies a pointer to an emulator context structure.
  849. ByteFlag - Supplies a flag value that determines whether the
  850. immediate value is a sign extended byte.
  851. Return Value:
  852. None.
  853. --*/
  854. {
  855. ULONG Value;
  856. //
  857. // Get source value.
  858. //
  859. if (P->DataType == BYTE_DATA) {
  860. Value = XmGetByteImmediate(P);
  861. } else if (P->DataType == WORD_DATA) {
  862. if (ByteFlag == 0) {
  863. Value = XmGetWordImmediate(P);
  864. } else {
  865. Value = XmGetSignedByteImmediateToWord(P);
  866. }
  867. } else {
  868. if (ByteFlag == 0) {
  869. Value = XmGetLongImmediate(P);
  870. } else {
  871. Value = XmGetSignedByteImmediateToLong(P);
  872. }
  873. }
  874. return Value;
  875. }
  876. VOID
  877. XmSetImmediateSourceValue (
  878. IN PRXM_CONTEXT P,
  879. IN ULONG Source
  880. )
  881. /*++
  882. Routine Description:
  883. This function stores the immediate source operand value in the
  884. emulator context.
  885. Arguments:
  886. P - Supplies a pointer to an emulator context structure.
  887. Source - Supplies the source value.
  888. Return Value:
  889. None.
  890. --*/
  891. {
  892. //
  893. // Set source value.
  894. //
  895. P->SrcValue.Long = Source;
  896. XmTraceSource(P, Source);
  897. return;
  898. }