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.

1239 lines
24 KiB

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