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.

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