Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1112 lines
27 KiB

  1. /*++
  2. Copyright (c) 1991 Microsoft Corporation
  3. Module Name:
  4. alignem.c
  5. Abstract:
  6. This module implement the code necessary to emulate unaliged data
  7. references.
  8. Author:
  9. David N. Cutler (davec) 17-Jun-1991
  10. Environment:
  11. Kernel mode only.
  12. Revision History:
  13. --*/
  14. #include "ki.h"
  15. #define OPCODE_MASK 0x1EF00000000
  16. #define LD_OP 0x08000000000
  17. #define LDS_OP 0x08100000000
  18. #define LDA_OP 0x08200000000
  19. #define LDSA_OP 0x08300000000
  20. #define LDBIAS_OP 0x08400000000
  21. #define LDACQ_OP 0x08500000000
  22. #define LDCCLR_OP 0x08800000000
  23. #define LDCNC_OP 0x08900000000
  24. #define LDCCLRACQ_OP 0x08A00000000
  25. #define ST_OP 0x08C00000000
  26. #define STREL_OP 0x08D00000000
  27. #define LD_IMM_OP 0x0A000000000
  28. #define LDS_IMM_OP 0x0A100000000
  29. #define LDA_IMM_OP 0x0A200000000
  30. #define LDSA_IMM_OP 0x0A300000000
  31. #define LDBIAS_IMM_OP 0x0A400000000
  32. #define LDACQ_IMM_OP 0x0A500000000
  33. #define LDCCLR_IMM_OP 0x0A800000000
  34. #define LDCNC_IMM_OP 0x0A900000000
  35. #define LDCCLRACQ_IMM_OP 0x0AA00000000
  36. #define ST_IMM_OP 0x0AC00000000
  37. #define STREL_IMM_OP 0x0AD00000000
  38. #define LDF_OP 0x0C000000000
  39. #define LDFS_OP 0x0C100000000
  40. #define LDFA_OP 0x0C200000000
  41. #define LDFSA_OP 0x0C300000000
  42. #define LDFCCLR_OP 0x0C800000000
  43. #define LDFCNC_OP 0x0C900000000
  44. #define STF_OP 0x0CC00000000
  45. #define LDF_IMM_OP 0x0E000000000
  46. #define LDFS_IMM_OP 0x0E100000000
  47. #define LDFA_IMM_OP 0x0E200000000
  48. #define LDFSA_IMM_OP 0x0E300000000
  49. #define LDFCCLR_IMM_OP 0x0E800000000
  50. #define LDFCNC_IMM_OP 0x0E900000000
  51. #define STF_IMM_OP 0x0EC00000000
  52. typedef struct _INST_FORMAT {
  53. union {
  54. struct {
  55. ULONGLONG qp: 6;
  56. ULONGLONG r1: 7;
  57. ULONGLONG r2: 7;
  58. ULONGLONG r3: 7;
  59. ULONGLONG x: 1;
  60. ULONGLONG hint: 2;
  61. ULONGLONG x6: 6;
  62. ULONGLONG m: 1;
  63. ULONGLONG Op: 4;
  64. ULONGLONG Rsv: 23;
  65. } i_field;
  66. ULONGLONG Ulong64;
  67. } u;
  68. } INST_FORMAT;
  69. VOID
  70. KiEmulateLoad(
  71. IN PVOID UnalignedAddress,
  72. IN ULONG OperandSize,
  73. IN PVOID Data
  74. );
  75. VOID
  76. KiEmulateStore(
  77. IN PVOID UnalignedAddress,
  78. IN ULONG OperandSize,
  79. IN PVOID Data
  80. );
  81. VOID
  82. KiEmulateLoadFloat(
  83. IN PVOID UnalignedAddress,
  84. IN ULONG OperandSize,
  85. IN PVOID Data
  86. );
  87. VOID
  88. KiEmulateStoreFloat(
  89. IN PVOID UnalignedAddress,
  90. IN ULONG OperandSize,
  91. IN PVOID Data
  92. );
  93. VOID
  94. KiEmulateLoadFloat80(
  95. IN PVOID UnalignedAddress,
  96. OUT PVOID FloatData
  97. );
  98. VOID
  99. KiEmulateLoadFloatInt(
  100. IN PVOID UnalignedAddress,
  101. OUT PVOID FloatData
  102. );
  103. VOID
  104. KiEmulateLoadFloat32(
  105. IN PVOID UnalignedAddress,
  106. OUT PVOID FloatData
  107. );
  108. VOID
  109. KiEmulateLoadFloat64(
  110. IN PVOID UnalignedAddress,
  111. OUT PVOID FloatData
  112. );
  113. VOID
  114. KiEmulateStoreFloat80(
  115. IN PVOID UnalignedAddress,
  116. OUT PVOID FloatData
  117. );
  118. VOID
  119. KiEmulateStoreFloatInt(
  120. IN PVOID UnalignedAddress,
  121. OUT PVOID FloatData
  122. );
  123. VOID
  124. KiEmulateStoreFloat32(
  125. IN PVOID UnalignedAddress,
  126. OUT PVOID FloatData
  127. );
  128. VOID
  129. KiEmulateStoreFloat64(
  130. IN PVOID UnalignedAddress,
  131. OUT PVOID FloatData
  132. );
  133. BOOLEAN
  134. KiEmulateReference (
  135. IN OUT PEXCEPTION_RECORD ExceptionRecord,
  136. IN OUT PKEXCEPTION_FRAME ExceptionFrame,
  137. IN OUT PKTRAP_FRAME TrapFrame
  138. )
  139. /*++
  140. Routine Description:
  141. This function is called to emulate an unaligned data reference to an
  142. address in the user part of the address space.
  143. Arguments:
  144. ExceptionRecord - Supplies a pointer to an exception record.
  145. ExceptionFrame - Supplies a pointer to an exception frame.
  146. TrapFrame - Supplies a pointer to a trap frame.
  147. Return Value:
  148. A value of TRUE is returned if the data reference is successfully
  149. emulated. Otherwise, a value of FALSE is returned.
  150. --*/
  151. {
  152. PVOID EffectiveAddress;
  153. PVOID ExceptionAddress;
  154. KIRQL OldIrql;
  155. KPROCESSOR_MODE PreviousMode;
  156. INST_FORMAT FaultInstruction;
  157. ULONGLONG Opcode;
  158. ULONGLONG Reg2Value;
  159. ULONGLONG Reg3Value;
  160. ULONGLONG BundleLow;
  161. ULONGLONG BundleHigh;
  162. ULONGLONG Syllable;
  163. ULONGLONG Data = 0;
  164. ULONGLONG ImmValue;
  165. ULONG OpSize;
  166. ULONG Length;
  167. ULONG Sor;
  168. ULONG Rrbgr;
  169. ULONG Rrbfr;
  170. ULONG Operand1, Operand2, Operand3;
  171. FLOAT128 FloatData = {0, 0};
  172. //
  173. // Must flush the RSE to synchronize the RSE and backing store contents
  174. //
  175. KiFlushRse();
  176. if (TrapFrame->PreviousMode == UserMode) {
  177. KeFlushUserRseState(TrapFrame);
  178. }
  179. //
  180. // Call out to profile interrupt if alignment profiling is active
  181. //
  182. if (KiProfileAlignmentFixup) {
  183. if (++KiProfileAlignmentFixupCount >= KiProfileAlignmentFixupInterval) {
  184. KeRaiseIrql(PROFILE_LEVEL, &OldIrql);
  185. KiProfileAlignmentFixupCount = 0;
  186. KeProfileInterruptWithSource(TrapFrame, ProfileAlignmentFixup);
  187. KeLowerIrql(OldIrql);
  188. }
  189. }
  190. //
  191. // Save the original exception address in case another exception
  192. // occurs.
  193. //
  194. EffectiveAddress = (PVOID) ExceptionRecord->ExceptionInformation[1];
  195. ExceptionAddress = (PVOID) TrapFrame->StIIP;
  196. //
  197. // Capture previous mode from trap frame not current thread.
  198. //
  199. PreviousMode = (KPROCESSOR_MODE) TrapFrame->PreviousMode;
  200. //
  201. // Any exception that occurs during the attempted emulation of the
  202. // unaligned reference causes the emulation to be aborted. The new
  203. // exception code and information is copied to the original exception
  204. // record and a value of FALSE is returned.
  205. //
  206. try {
  207. BundleLow = *((ULONGLONG *)ExceptionAddress);
  208. BundleHigh = *(((ULONGLONG *)ExceptionAddress) + 1);
  209. Syllable = (TrapFrame->StIPSR >> PSR_RI) & 0x3;
  210. switch (Syllable) {
  211. case 0:
  212. FaultInstruction.u.Ulong64 = (BundleLow >> 5);
  213. break;
  214. case 1:
  215. FaultInstruction.u.Ulong64 = (BundleLow >> 46) | (BundleHigh << 18);
  216. break;
  217. case 2:
  218. FaultInstruction.u.Ulong64 = (BundleHigh >> 23);
  219. case 3:
  220. default:
  221. return FALSE;
  222. }
  223. Rrbgr = (ULONG)(TrapFrame->StIFS >> 18) & 0x7f;
  224. Rrbfr = (ULONG)(TrapFrame->StIFS >> 25) & 0x7f;
  225. Sor = (ULONG)((TrapFrame->StIFS >> 14) & 0xf) * 8;
  226. Operand1 = (ULONG)FaultInstruction.u.i_field.r1;
  227. Operand2 = (ULONG)FaultInstruction.u.i_field.r2;
  228. Operand3 = (ULONG)FaultInstruction.u.i_field.r3;
  229. if (Sor > 0) {
  230. if ((Operand1 >= 32) && ((Operand1-32) < Sor))
  231. Operand1 = 32 + (Rrbgr + Operand1 - 32) % Sor;
  232. if ((Operand2 >= 32) && ((Operand2-32) < Sor))
  233. Operand2 = 32 + (Rrbgr + Operand2 - 32) % Sor;
  234. if ((Operand3 >= 32) && ((Operand3-32) < Sor))
  235. Operand3 = 32 + (Rrbgr + Operand3 - 32) % Sor;
  236. }
  237. Opcode = FaultInstruction.u.Ulong64 & OPCODE_MASK;
  238. OpSize = (ULONG)FaultInstruction.u.i_field.x6 & 0x3;
  239. switch (Opcode) {
  240. //
  241. // speculative and speculative advanced load
  242. //
  243. case LDS_OP:
  244. case LDSA_OP:
  245. case LDS_IMM_OP:
  246. case LDSA_IMM_OP:
  247. case LDFS_OP:
  248. case LDFSA_OP:
  249. case LDFS_IMM_OP:
  250. //
  251. // return NaT value to the target register
  252. //
  253. TrapFrame->StIPSR |= (1i64 << PSR_ED);
  254. return TRUE;
  255. //
  256. // normal, advance, and check load
  257. //
  258. case LD_OP:
  259. case LDA_OP:
  260. case LDBIAS_OP:
  261. case LDCCLR_OP:
  262. case LDCNC_OP:
  263. case LDACQ_OP:
  264. case LDCCLRACQ_OP:
  265. if (FaultInstruction.u.i_field.x == 1) {
  266. //
  267. // xField must be 0
  268. //
  269. return FALSE;
  270. }
  271. if( PreviousMode != KernelMode ){
  272. ProbeForRead( EffectiveAddress,
  273. 1 << OpSize,
  274. sizeof(UCHAR) );
  275. }
  276. KiEmulateLoad(EffectiveAddress, OpSize, &Data);
  277. KiSetRegisterValue( Operand1, Data, ExceptionFrame, TrapFrame );
  278. if (FaultInstruction.u.i_field.m == 1) {
  279. //
  280. // Update the address register (R3)
  281. //
  282. Reg2Value = KiGetRegisterValue( Operand2, ExceptionFrame,
  283. TrapFrame );
  284. Reg3Value = KiGetRegisterValue( Operand3, ExceptionFrame,
  285. TrapFrame );
  286. //
  287. // register update form
  288. //
  289. Reg3Value = Reg2Value + Reg3Value;
  290. KiSetRegisterValue ( Operand3, Reg3Value,
  291. ExceptionFrame, TrapFrame);
  292. }
  293. if ((Opcode == LDACQ_OP) || (Opcode == LDCCLRACQ_OP)) {
  294. //
  295. // all future access should occur after unaligned memory access
  296. //
  297. __mf();
  298. }
  299. break;
  300. //
  301. // normal, advance, and check load
  302. // immidiate updated form
  303. //
  304. case LD_IMM_OP:
  305. case LDA_IMM_OP:
  306. case LDBIAS_IMM_OP:
  307. case LDCCLR_IMM_OP:
  308. case LDCNC_IMM_OP:
  309. case LDACQ_IMM_OP:
  310. case LDCCLRACQ_IMM_OP:
  311. if( PreviousMode != KernelMode ){
  312. ProbeForRead( EffectiveAddress,
  313. 1 << OpSize,
  314. sizeof(UCHAR) );
  315. }
  316. KiEmulateLoad(EffectiveAddress, OpSize, &Data);
  317. KiSetRegisterValue( Operand1, Data, ExceptionFrame, TrapFrame );
  318. //
  319. // Update the address register R3
  320. //
  321. Reg3Value = KiGetRegisterValue(Operand3, ExceptionFrame, TrapFrame);
  322. //
  323. // immediate update form
  324. //
  325. ImmValue = (FaultInstruction.u.i_field.r2
  326. + (FaultInstruction.u.i_field.x << 7));
  327. if (FaultInstruction.u.i_field.m == 1) {
  328. ImmValue = 0xFFFFFFFFFFFFFF00i64 | ImmValue;
  329. }
  330. Reg3Value = Reg3Value + ImmValue;
  331. KiSetRegisterValue(Operand3, Reg3Value, ExceptionFrame, TrapFrame);
  332. if ((Opcode == LDACQ_IMM_OP) || (Opcode == LDCCLRACQ_IMM_OP)) {
  333. //
  334. // all future access should occur after unaligned memory access
  335. //
  336. __mf();
  337. }
  338. break;
  339. case LDF_OP:
  340. case LDFA_OP:
  341. case LDFCCLR_OP:
  342. case LDFCNC_OP:
  343. if (Operand1 >= 32) Operand1 = 32 + (Rrbfr + Operand1 - 32) % 96;
  344. if (Operand2 >= 32) Operand2 = 32 + (Rrbfr + Operand2 - 32) % 96;
  345. if (Operand3 >= 32) Operand3 = 32 + (Rrbfr + Operand3 - 32) % 96;
  346. if (FaultInstruction.u.i_field.x == 1) {
  347. //
  348. // floating point load pair
  349. //
  350. if (FaultInstruction.u.i_field.m == 1) {
  351. //
  352. // m field must be zero
  353. //
  354. return FALSE;
  355. }
  356. if( PreviousMode != KernelMode ){
  357. switch (OpSize) {
  358. case 0: return FALSE;
  359. case 1: Length = 8; break;
  360. case 2: Length = 4; break;
  361. case 3: Length = 8; break;
  362. default:
  363. return FALSE;
  364. }
  365. ProbeForRead( EffectiveAddress,
  366. Length << 1,
  367. sizeof(UCHAR) );
  368. }
  369. //
  370. // emulate the 1st half of the pair
  371. //
  372. KiEmulateLoadFloat(EffectiveAddress, OpSize, &FloatData);
  373. KiSetFloatRegisterValue( Operand1, FloatData,
  374. ExceptionFrame, TrapFrame );
  375. //
  376. // emulate the 2nd half of the pair
  377. //
  378. EffectiveAddress = (PVOID)((ULONG_PTR)EffectiveAddress + Length);
  379. KiEmulateLoadFloat(EffectiveAddress, OpSize, &FloatData);
  380. KiSetFloatRegisterValue( Operand2, FloatData,
  381. ExceptionFrame, TrapFrame );
  382. } else {
  383. //
  384. // floating point single load
  385. //
  386. if( PreviousMode != KernelMode ){
  387. switch (OpSize) {
  388. case 0: Length = 16; break;
  389. case 1: Length = 8; break;
  390. case 2: Length = 4; break;
  391. case 3: Length = 8; break;
  392. default:
  393. return FALSE;
  394. }
  395. ProbeForRead( EffectiveAddress,
  396. Length,
  397. sizeof(UCHAR) );
  398. }
  399. KiEmulateLoadFloat(EffectiveAddress, OpSize, &FloatData);
  400. KiSetFloatRegisterValue( Operand1, FloatData,
  401. ExceptionFrame, TrapFrame );
  402. if (FaultInstruction.u.i_field.m == 1) {
  403. //
  404. // update the address register (R3)
  405. //
  406. Reg2Value = KiGetRegisterValue( Operand2,
  407. ExceptionFrame,
  408. TrapFrame );
  409. Reg3Value = KiGetRegisterValue( Operand3,
  410. ExceptionFrame,
  411. TrapFrame );
  412. //
  413. // register update form
  414. //
  415. Reg3Value = Reg2Value + Reg3Value;
  416. KiSetRegisterValue (Operand3, Reg3Value,
  417. ExceptionFrame, TrapFrame);
  418. }
  419. }
  420. break;
  421. //
  422. // normal, advanced and checked floating point load
  423. // immediate updated form
  424. //
  425. case LDF_IMM_OP:
  426. case LDFA_IMM_OP:
  427. case LDFCCLR_IMM_OP:
  428. case LDFCNC_IMM_OP:
  429. if (Operand1 >= 32) Operand1 = 32 + (Rrbfr + Operand1 - 32) % 96;
  430. if (Operand2 >= 32) Operand2 = 32 + (Rrbfr + Operand2 - 32) % 96;
  431. if (Operand3 >= 32) Operand3 = 32 + (Rrbfr + Operand3 - 32) % 96;
  432. if (FaultInstruction.u.i_field.x == 1) {
  433. //
  434. // floating point load pair
  435. //
  436. if (FaultInstruction.u.i_field.m == 0) {
  437. //
  438. // m field must be one
  439. //
  440. return FALSE;
  441. }
  442. if( PreviousMode != KernelMode ){
  443. switch (OpSize) {
  444. case 0: return FALSE;
  445. case 1: Length = 8; break;
  446. case 2: Length = 8; break;
  447. case 3: Length = 4; break;
  448. default:
  449. return FALSE;
  450. }
  451. ProbeForRead( EffectiveAddress,
  452. Length << 1,
  453. sizeof(UCHAR) );
  454. }
  455. //
  456. // emulate the 1st half of the pair
  457. //
  458. KiEmulateLoadFloat(EffectiveAddress, OpSize, &FloatData);
  459. KiSetFloatRegisterValue( Operand1, FloatData,
  460. ExceptionFrame, TrapFrame );
  461. EffectiveAddress = (PVOID)((ULONG_PTR)EffectiveAddress + Length);
  462. //
  463. // emulate the 2nd half of the pair
  464. //
  465. KiEmulateLoadFloat(EffectiveAddress, OpSize, &FloatData);
  466. KiSetFloatRegisterValue( Operand2,
  467. FloatData,
  468. ExceptionFrame,
  469. TrapFrame );
  470. //
  471. // Update the address register (R3)
  472. //
  473. Reg3Value = KiGetRegisterValue( Operand3,
  474. ExceptionFrame,
  475. TrapFrame );
  476. //
  477. // immediate update form
  478. //
  479. ImmValue = Length << 1;
  480. Reg3Value = Reg3Value + ImmValue;
  481. KiSetRegisterValue( Operand3, Reg3Value,
  482. ExceptionFrame, TrapFrame );
  483. } else {
  484. //
  485. // floating point single load
  486. //
  487. if( PreviousMode != KernelMode ){
  488. switch (OpSize) {
  489. case 0: Length = 16; break;
  490. case 1: Length = 8; break;
  491. case 2: Length = 4; break;
  492. case 3: Length = 8; break;
  493. default:
  494. return FALSE;
  495. }
  496. ProbeForRead( EffectiveAddress,
  497. Length,
  498. sizeof(UCHAR) );
  499. }
  500. KiEmulateLoadFloat(EffectiveAddress, OpSize, &FloatData);
  501. KiSetFloatRegisterValue( Operand1, FloatData,
  502. ExceptionFrame, TrapFrame );
  503. //
  504. // Update the address register (R3)
  505. //
  506. Reg3Value = KiGetRegisterValue( Operand3,
  507. ExceptionFrame,
  508. TrapFrame );
  509. //
  510. // immediate update form
  511. //
  512. ImmValue = (FaultInstruction.u.i_field.r2
  513. + (FaultInstruction.u.i_field.x << 7));
  514. if (FaultInstruction.u.i_field.m == 1) {
  515. ImmValue = 0xFFFFFFFFFFFFFF00i64 | ImmValue;
  516. }
  517. Reg3Value = Reg3Value + ImmValue;
  518. KiSetRegisterValue( Operand3, Reg3Value,
  519. ExceptionFrame, TrapFrame );
  520. }
  521. break;
  522. case STREL_OP:
  523. __mf();
  524. case ST_OP:
  525. if (FaultInstruction.u.i_field.x == 1) {
  526. //
  527. // xField must be 0
  528. //
  529. return FALSE;
  530. }
  531. if (FaultInstruction.u.i_field.m == 1) {
  532. //
  533. // no register update form defined
  534. //
  535. return FALSE;
  536. }
  537. if( PreviousMode != KernelMode ){
  538. ProbeForWrite( EffectiveAddress,
  539. 1 << OpSize,
  540. sizeof(UCHAR) );
  541. }
  542. Data = KiGetRegisterValue( Operand2, ExceptionFrame, TrapFrame );
  543. KiEmulateStore( EffectiveAddress, OpSize, &Data);
  544. break;
  545. case STREL_IMM_OP:
  546. __mf();
  547. case ST_IMM_OP:
  548. if( PreviousMode != KernelMode ){
  549. ProbeForWrite( EffectiveAddress,
  550. 1 << OpSize,
  551. sizeof(UCHAR) );
  552. }
  553. Data = KiGetRegisterValue( Operand2, ExceptionFrame, TrapFrame );
  554. KiEmulateStore( EffectiveAddress, OpSize, &Data);
  555. //
  556. // update the address register (R3)
  557. //
  558. Reg3Value = KiGetRegisterValue(Operand3, ExceptionFrame, TrapFrame);
  559. //
  560. // immediate update form
  561. //
  562. ImmValue = (FaultInstruction.u.i_field.r1
  563. + (FaultInstruction.u.i_field.x << 7));
  564. if (FaultInstruction.u.i_field.m == 1) {
  565. ImmValue = 0xFFFFFFFFFFFFFF00i64 | ImmValue;
  566. }
  567. Reg3Value = Reg3Value + ImmValue;
  568. KiSetRegisterValue(Operand3, Reg3Value, ExceptionFrame, TrapFrame);
  569. break;
  570. case STF_OP:
  571. if (FaultInstruction.u.i_field.x) {
  572. //
  573. // x field must be 0
  574. //
  575. return FALSE;
  576. }
  577. if (FaultInstruction.u.i_field.m) {
  578. //
  579. // no register update form defined
  580. //
  581. return FALSE;
  582. }
  583. if( PreviousMode != KernelMode ){
  584. switch (OpSize) {
  585. case 0: Length = 16; break;
  586. case 1: Length = 8; break;
  587. case 2: Length = 4; break;
  588. case 3: Length = 8; break;
  589. default:
  590. return FALSE;
  591. }
  592. ProbeForWrite( EffectiveAddress,
  593. Length,
  594. sizeof(UCHAR) );
  595. }
  596. if (Operand2 >= 32) Operand2 = 32 + (Rrbfr + Operand2 - 32) % 96;
  597. FloatData = KiGetFloatRegisterValue(Operand2,
  598. ExceptionFrame,
  599. TrapFrame);
  600. KiEmulateStoreFloat( EffectiveAddress, OpSize, &FloatData);
  601. break;
  602. case STF_IMM_OP:
  603. if( PreviousMode != KernelMode ){
  604. switch (OpSize) {
  605. case 0: Length = 16; break;
  606. case 1: Length = 8; break;
  607. case 2: Length = 4; break;
  608. case 3: Length = 8; break;
  609. default:
  610. return FALSE;
  611. }
  612. ProbeForWrite( EffectiveAddress,
  613. Length,
  614. sizeof(UCHAR) );
  615. }
  616. if (Operand2 >= 32) Operand2 = 32 + (Rrbfr + Operand2 - 32) % 96;
  617. FloatData = KiGetFloatRegisterValue(Operand2,
  618. ExceptionFrame,
  619. TrapFrame);
  620. KiEmulateStoreFloat( EffectiveAddress, OpSize, &FloatData);
  621. //
  622. // update the address register (R3)
  623. //
  624. if (Operand3 >= 32) Operand3 = 32 + (Rrbfr + Operand3 - 32) % 96;
  625. Reg3Value = KiGetRegisterValue(Operand3, ExceptionFrame, TrapFrame);
  626. //
  627. // immediate update form
  628. //
  629. ImmValue = (FaultInstruction.u.i_field.r1
  630. + (FaultInstruction.u.i_field.x << 7));
  631. if (FaultInstruction.u.i_field.m == 1) {
  632. ImmValue = 0xFFFFFFFFFFFFFF00i64 | ImmValue;
  633. }
  634. Reg3Value = Reg3Value + ImmValue;
  635. KiSetRegisterValue(Operand3, Reg3Value, ExceptionFrame, TrapFrame);
  636. break;
  637. default:
  638. return FALSE;
  639. }
  640. //
  641. // advance instruction pointer
  642. //
  643. KiAdvanceInstPointer(TrapFrame);
  644. return TRUE;
  645. //
  646. // If an exception occurs, then copy the new exception information to the
  647. // original exception record and handle the exception.
  648. //
  649. } except (KiCopyInformation(ExceptionRecord,
  650. (GetExceptionInformation())->ExceptionRecord)) {
  651. //
  652. // Preserve the original exception address.
  653. //
  654. ExceptionRecord->ExceptionAddress = ExceptionAddress;
  655. }
  656. //
  657. // Return a value of FALSE.
  658. //
  659. return FALSE;
  660. }
  661. VOID
  662. KiEmulateLoad(
  663. IN PVOID UnalignedAddress,
  664. IN ULONG OperandSize,
  665. IN PVOID Data
  666. )
  667. /*++
  668. Routine Description:
  669. This routine returns the integer value stored at the unaligned
  670. address passed in UnalignedAddress.
  671. Arguments:
  672. UnalignedAddress - Supplies a pointer to data value.
  673. OperandSize - Supplies the size of data to be loaded
  674. Data - Supplies a pointer to be filled for data
  675. Return Value:
  676. The value at the address pointed to by UnalignedAddress.
  677. --*/
  678. {
  679. PUCHAR Source;
  680. PUCHAR Destination;
  681. ULONG i;
  682. Source = (PUCHAR) UnalignedAddress;
  683. Destination = (PUCHAR) Data;
  684. OperandSize = 1 << OperandSize;
  685. for (i = 0; i < OperandSize; i++) {
  686. *Destination++ = *Source++;
  687. }
  688. return;
  689. }
  690. VOID
  691. KiEmulateStore(
  692. IN PVOID UnalignedAddress,
  693. IN ULONG OperandSize,
  694. IN PVOID Data
  695. )
  696. /*++
  697. Routine Description:
  698. This routine store the integer value at the unaligned
  699. address passed in UnalignedAddress.
  700. Arguments:
  701. UnalignedAddress - Supplies a pointer to be stored
  702. OperandSize - Supplies the size of data to be storeed
  703. Data - Supplies a pointer to data value
  704. Return Value:
  705. The value at the address pointed to by UnalignedAddress.
  706. --*/
  707. {
  708. PUCHAR Source;
  709. PUCHAR Destination;
  710. ULONG i;
  711. Source = (PUCHAR) Data;
  712. Destination = (PUCHAR) UnalignedAddress;
  713. OperandSize = 1 << OperandSize;
  714. for (i = 0; i < OperandSize; i++) {
  715. *Destination++ = *Source++;
  716. }
  717. return;
  718. }
  719. VOID
  720. KiEmulateLoadFloat(
  721. IN PVOID UnalignedAddress,
  722. IN ULONG OperandSize,
  723. IN OUT PVOID Data
  724. )
  725. /*++
  726. Routine Description:
  727. This routine returns the floating point value stored at the unaligned
  728. address passed in UnalignedAddress.
  729. Arguments:
  730. UnalignedAddress - Supplies a pointer to floating point data value.
  731. OperandSize - Supplies the size of data to be loaded
  732. Data - Supplies a pointer to be filled for data
  733. Return Value:
  734. The value at the address pointed to by UnalignedAddress.
  735. --*/
  736. {
  737. FLOAT128 FloatData;
  738. RtlCopyMemory(&FloatData, UnalignedAddress, sizeof(FLOAT128));
  739. switch (OperandSize) {
  740. case 0:
  741. KiEmulateLoadFloat80(&FloatData, Data);
  742. return;
  743. case 1:
  744. KiEmulateLoadFloatInt(&FloatData, Data);
  745. return;
  746. case 2:
  747. KiEmulateLoadFloat32(&FloatData, Data);
  748. return;
  749. case 3:
  750. KiEmulateLoadFloat64(&FloatData, Data);
  751. return;
  752. default:
  753. return;
  754. }
  755. }
  756. VOID
  757. KiEmulateStoreFloat(
  758. IN PVOID UnalignedAddress,
  759. IN ULONG OperandSize,
  760. IN PVOID Data
  761. )
  762. /*++
  763. Routine Description:
  764. This routine stores the floating point value stored at the unaligned
  765. address passed in UnalignedAddress.
  766. Arguments:
  767. UnalignedAddress - Supplies a pointer to be stored.
  768. OperandSize - Supplies the size of data to be loaded
  769. Data - Supplies a pointer to floating point data
  770. Return Value:
  771. The value at the address pointed to by UnalignedAddress.
  772. --*/
  773. {
  774. FLOAT128 FloatData;
  775. ULONG Length;
  776. switch (OperandSize) {
  777. case 0:
  778. KiEmulateStoreFloat80(&FloatData, Data);
  779. Length = 10;
  780. break;
  781. case 1:
  782. KiEmulateStoreFloatInt(&FloatData, Data);
  783. Length = 8;
  784. break;
  785. case 2:
  786. KiEmulateStoreFloat32(&FloatData, Data);
  787. Length = 4;
  788. break;
  789. case 3:
  790. KiEmulateStoreFloat64(&FloatData, Data);
  791. Length = 8;
  792. break;
  793. default:
  794. return;
  795. }
  796. RtlCopyMemory(UnalignedAddress, &FloatData, Length);
  797. }