Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

alignem.c

Go to the documentation of this file.
00001 /*++ 00002 00003 Copyright (c) 1991 Microsoft Corporation 00004 00005 Module Name: 00006 00007 alignem.c 00008 00009 Abstract: 00010 00011 This module implement the code necessary to emulate unaliged data 00012 references. 00013 00014 Author: 00015 00016 David N. Cutler (davec) 17-Jun-1991 00017 00018 Environment: 00019 00020 Kernel mode only. 00021 00022 Revision History: 00023 00024 --*/ 00025 00026 #include "ki.h" 00027 00028 #define OPCODE_MASK 0x1EF00000000 00029 00030 #define LD_OP 0x08000000000 00031 #define LDS_OP 0x08100000000 00032 #define LDA_OP 0x08200000000 00033 #define LDSA_OP 0x08300000000 00034 #define LDBIAS_OP 0x08400000000 00035 #define LDACQ_OP 0x08500000000 00036 #define LDCCLR_OP 0x08800000000 00037 #define LDCNC_OP 0x08900000000 00038 #define LDCCLRACQ_OP 0x08A00000000 00039 #define ST_OP 0x08C00000000 00040 #define STREL_OP 0x08D00000000 00041 00042 #define LD_IMM_OP 0x0A000000000 00043 #define LDS_IMM_OP 0x0A100000000 00044 #define LDA_IMM_OP 0x0A200000000 00045 #define LDSA_IMM_OP 0x0A300000000 00046 #define LDBIAS_IMM_OP 0x0A400000000 00047 #define LDACQ_IMM_OP 0x0A500000000 00048 #define LDCCLR_IMM_OP 0x0A800000000 00049 #define LDCNC_IMM_OP 0x0A900000000 00050 #define LDCCLRACQ_IMM_OP 0x0AA00000000 00051 #define ST_IMM_OP 0x0AC00000000 00052 #define STREL_IMM_OP 0x0AD00000000 00053 00054 #define LDF_OP 0x0C000000000 00055 #define LDFS_OP 0x0C100000000 00056 #define LDFA_OP 0x0C200000000 00057 #define LDFSA_OP 0x0C300000000 00058 #define LDFCCLR_OP 0x0C800000000 00059 #define LDFCNC_OP 0x0C900000000 00060 #define STF_OP 0x0CC00000000 00061 00062 #define LDF_IMM_OP 0x0E000000000 00063 #define LDFS_IMM_OP 0x0E100000000 00064 #define LDFA_IMM_OP 0x0E200000000 00065 #define LDFSA_IMM_OP 0x0E300000000 00066 #define LDFCCLR_IMM_OP 0x0E800000000 00067 #define LDFCNC_IMM_OP 0x0E900000000 00068 #define STF_IMM_OP 0x0EC00000000 00069 00070 typedef struct _INST_FORMAT { 00071 union { 00072 struct { 00073 ULONGLONG qp: 6; 00074 ULONGLONG r1: 7; 00075 ULONGLONG r2: 7; 00076 ULONGLONG r3: 7; 00077 ULONGLONG x: 1; 00078 ULONGLONG hint: 2; 00079 ULONGLONG x6: 6; 00080 ULONGLONG m: 1; 00081 ULONGLONG Op: 4; 00082 ULONGLONG Rsv: 23; 00083 } i_field; 00084 ULONGLONG Ulong64; 00085 } u; 00086 } INST_FORMAT; 00087 00088 VOID 00089 KiEmulateLoad( 00090 IN PVOID UnalignedAddress, 00091 IN ULONG OperandSize, 00092 IN PVOID Data 00093 ); 00094 00095 VOID 00096 KiEmulateStore( 00097 IN PVOID UnalignedAddress, 00098 IN ULONG OperandSize, 00099 IN PVOID Data 00100 ); 00101 00102 VOID 00103 KiEmulateLoadFloat( 00104 IN PVOID UnalignedAddress, 00105 IN ULONG OperandSize, 00106 IN PVOID Data 00107 ); 00108 00109 VOID 00110 KiEmulateStoreFloat( 00111 IN PVOID UnalignedAddress, 00112 IN ULONG OperandSize, 00113 IN PVOID Data 00114 ); 00115 00116 VOID 00117 KiEmulateLoadFloat80( 00118 IN PVOID UnalignedAddress, 00119 OUT PVOID FloatData 00120 ); 00121 00122 VOID 00123 KiEmulateLoadFloatInt( 00124 IN PVOID UnalignedAddress, 00125 OUT PVOID FloatData 00126 ); 00127 00128 VOID 00129 KiEmulateLoadFloat32( 00130 IN PVOID UnalignedAddress, 00131 OUT PVOID FloatData 00132 ); 00133 00134 VOID 00135 KiEmulateLoadFloat64( 00136 IN PVOID UnalignedAddress, 00137 OUT PVOID FloatData 00138 ); 00139 00140 VOID 00141 KiEmulateStoreFloat80( 00142 IN PVOID UnalignedAddress, 00143 OUT PVOID FloatData 00144 ); 00145 00146 VOID 00147 KiEmulateStoreFloatInt( 00148 IN PVOID UnalignedAddress, 00149 OUT PVOID FloatData 00150 ); 00151 00152 VOID 00153 KiEmulateStoreFloat32( 00154 IN PVOID UnalignedAddress, 00155 OUT PVOID FloatData 00156 ); 00157 00158 VOID 00159 KiEmulateStoreFloat64( 00160 IN PVOID UnalignedAddress, 00161 OUT PVOID FloatData 00162 ); 00163 00164 00165 BOOLEAN 00166 KiEmulateReference ( 00167 IN OUT PEXCEPTION_RECORD ExceptionRecord, 00168 IN OUT PKEXCEPTION_FRAME ExceptionFrame, 00169 IN OUT PKTRAP_FRAME TrapFrame 00170 ) 00171 00172 /*++ 00173 00174 Routine Description: 00175 00176 This function is called to emulate an unaligned data reference to an 00177 address in the user part of the address space. 00178 00179 Arguments: 00180 00181 ExceptionRecord - Supplies a pointer to an exception record. 00182 00183 ExceptionFrame - Supplies a pointer to an exception frame. 00184 00185 TrapFrame - Supplies a pointer to a trap frame. 00186 00187 Return Value: 00188 00189 A value of TRUE is returned if the data reference is successfully 00190 emulated. Otherwise, a value of FALSE is returned. 00191 00192 --*/ 00193 00194 { 00195 00196 PVOID EffectiveAddress; 00197 PVOID ExceptionAddress; 00198 KIRQL OldIrql; 00199 00200 KPROCESSOR_MODE PreviousMode; 00201 INST_FORMAT FaultInstruction; 00202 ULONGLONG Opcode; 00203 ULONGLONG Reg2Value; 00204 ULONGLONG Reg3Value; 00205 ULONGLONG BundleLow; 00206 ULONGLONG BundleHigh; 00207 ULONGLONG Syllable; 00208 ULONGLONG Data = 0; 00209 FLOAT128 FloatData = {0, 0}; 00210 ULONG OpSize; 00211 ULONG ImmValue; 00212 ULONG Length; 00213 00214 00215 // 00216 // Must flush the RSE to synchronize the RSE and backing store contents 00217 // 00218 00219 KiFlushRse(); 00220 00221 // 00222 // Call out to profile interrupt if alignment profiling is active 00223 // 00224 00225 if (KiProfileAlignmentFixup) { 00226 00227 if (++KiProfileAlignmentFixupCount >= KiProfileAlignmentFixupInterval) { 00228 00229 KeRaiseIrql(PROFILE_LEVEL, &OldIrql); 00230 KiProfileAlignmentFixupCount = 0; 00231 KeProfileInterruptWithSource(TrapFrame, ProfileAlignmentFixup); 00232 KeLowerIrql(OldIrql); 00233 00234 } 00235 } 00236 00237 // 00238 // Save the original exception address in case another exception 00239 // occurs. 00240 // 00241 00242 EffectiveAddress = (PVOID) ExceptionRecord->ExceptionInformation[1]; 00243 ExceptionAddress = (PVOID) TrapFrame->StIIP; 00244 00245 // 00246 // Capture previous mode from trap frame not current thread. 00247 // 00248 00249 PreviousMode = (KPROCESSOR_MODE) TrapFrame->PreviousMode; 00250 00251 // 00252 // Any exception that occurs during the attempted emulation of the 00253 // unaligned reference causes the emulation to be aborted. The new 00254 // exception code and information is copied to the original exception 00255 // record and a value of FALSE is returned. 00256 // 00257 00258 try { 00259 00260 00261 BundleLow = *((ULONGLONG *)ExceptionAddress); 00262 BundleHigh = *(((ULONGLONG *)ExceptionAddress) + 1); 00263 00264 Syllable = (TrapFrame->StIPSR >> PSR_RI) & 0x3; 00265 00266 switch (Syllable) { 00267 case 0: 00268 FaultInstruction.u.Ulong64 = (BundleLow >> 5); 00269 break; 00270 case 1: 00271 FaultInstruction.u.Ulong64 = (BundleLow >> 46) | (BundleHigh << 18); 00272 break; 00273 case 2: 00274 FaultInstruction.u.Ulong64 = (BundleHigh >> 23); 00275 case 3: 00276 default: 00277 return FALSE; 00278 } 00279 00280 Opcode = FaultInstruction.u.Ulong64 & OPCODE_MASK; 00281 OpSize = (ULONG)FaultInstruction.u.i_field.x6 & 0x3; 00282 00283 switch (Opcode) { 00284 00285 // 00286 // speculative and speculative advanced load 00287 // 00288 00289 case LDS_OP: 00290 case LDSA_OP: 00291 case LDS_IMM_OP: 00292 case LDSA_IMM_OP: 00293 case LDFS_OP: 00294 case LDFSA_OP: 00295 case LDFS_IMM_OP: 00296 00297 // 00298 // return NaT value to the target register 00299 // 00300 00301 TrapFrame->StIPSR |= (1i64 << PSR_ED); 00302 00303 return TRUE; 00304 00305 // 00306 // normal, advance, and check load 00307 // 00308 00309 case LD_OP: 00310 case LDA_OP: 00311 case LDBIAS_OP: 00312 case LDCCLR_OP: 00313 case LDCNC_OP: 00314 case LDACQ_OP: 00315 case LDCCLRACQ_OP: 00316 00317 if (FaultInstruction.u.i_field.x == 1) { 00318 00319 // 00320 // xField must be 0 00321 // 00322 00323 return FALSE; 00324 } 00325 00326 if( PreviousMode != KernelMode ){ 00327 ProbeForRead( EffectiveAddress, 00328 1 << OpSize, 00329 sizeof(UCHAR) ); 00330 } 00331 KiEmulateLoad(EffectiveAddress, OpSize, &Data); 00332 KiSetRegisterValue( (ULONG) FaultInstruction.u.i_field.r1, 00333 Data, 00334 ExceptionFrame, 00335 TrapFrame ); 00336 00337 if (FaultInstruction.u.i_field.m == 1) { 00338 00339 // 00340 // Update the address register (R3) 00341 // 00342 00343 00344 Reg2Value = KiGetRegisterValue( (ULONG) FaultInstruction.u.i_field.r2, 00345 ExceptionFrame, 00346 TrapFrame ); 00347 00348 Reg3Value = KiGetRegisterValue( (ULONG) FaultInstruction.u.i_field.r3, 00349 ExceptionFrame, 00350 TrapFrame ); 00351 00352 // 00353 // register update form 00354 // 00355 00356 Reg3Value = Reg2Value + Reg3Value; 00357 00358 KiSetRegisterValue ((ULONG) FaultInstruction.u.i_field.r3, 00359 Reg3Value, 00360 ExceptionFrame, 00361 TrapFrame); 00362 } 00363 00364 if ((Opcode == LDACQ_OP) || (Opcode == LDCCLRACQ_OP)) { 00365 00366 // 00367 // all future access should occur after unaligned memory accesses 00368 // 00369 00370 __mf(); 00371 } 00372 00373 break; 00374 00375 // 00376 // normal, advance, and check load 00377 // immidiate updated form 00378 // 00379 00380 case LD_IMM_OP: 00381 case LDA_IMM_OP: 00382 case LDBIAS_IMM_OP: 00383 case LDCCLR_IMM_OP: 00384 case LDCNC_IMM_OP: 00385 case LDACQ_IMM_OP: 00386 case LDCCLRACQ_IMM_OP: 00387 00388 if( PreviousMode != KernelMode ){ 00389 ProbeForRead( EffectiveAddress, 00390 1 << OpSize, 00391 sizeof(UCHAR) ); 00392 } 00393 KiEmulateLoad(EffectiveAddress, OpSize, &Data); 00394 KiSetRegisterValue( (ULONG) FaultInstruction.u.i_field.r1, 00395 Data, 00396 ExceptionFrame, 00397 TrapFrame ); 00398 00399 // 00400 // Update the address register R3 00401 // 00402 00403 Reg3Value = KiGetRegisterValue( (ULONG) FaultInstruction.u.i_field.r3, 00404 ExceptionFrame, 00405 TrapFrame ); 00406 00407 // 00408 // immediate update form 00409 // 00410 00411 ImmValue = (ULONG)(FaultInstruction.u.i_field.r2 00412 + (FaultInstruction.u.i_field.x << 7)); 00413 00414 if (FaultInstruction.u.i_field.m == 1) { 00415 00416 ImmValue = 0xFFFFFFFFFFFFFF00 | ImmValue; 00417 00418 } 00419 00420 Reg3Value = Reg3Value + ImmValue; 00421 00422 KiSetRegisterValue( (ULONG) FaultInstruction.u.i_field.r3, 00423 Reg3Value, 00424 ExceptionFrame, 00425 TrapFrame ); 00426 00427 if ((Opcode == LDACQ_IMM_OP) || (Opcode == LDCCLRACQ_IMM_OP)) { 00428 00429 // 00430 // all future access should occur after unaligned memory accesses 00431 // 00432 00433 __mf(); 00434 } 00435 00436 break; 00437 00438 case LDF_OP: 00439 case LDFA_OP: 00440 case LDFCCLR_OP: 00441 case LDFCNC_OP: 00442 00443 if (FaultInstruction.u.i_field.x == 1) { 00444 00445 // 00446 // floating point load pair 00447 // 00448 00449 if (FaultInstruction.u.i_field.m == 1) { 00450 00451 // 00452 // m field must be zero 00453 // 00454 00455 return FALSE; 00456 00457 } 00458 00459 if( PreviousMode != KernelMode ){ 00460 00461 switch (OpSize) { 00462 case 0: return FALSE; 00463 case 1: Length = 8; break; 00464 case 2: Length = 4; break; 00465 case 3: Length = 8; break; 00466 default: 00467 return FALSE; 00468 } 00469 00470 ProbeForRead( EffectiveAddress, 00471 Length << 1, 00472 sizeof(UCHAR) ); 00473 } 00474 00475 // 00476 // emulate the 1st half of the pair 00477 // 00478 00479 KiEmulateLoadFloat(EffectiveAddress, OpSize, &FloatData); 00480 KiSetFloatRegisterValue( (ULONG) FaultInstruction.u.i_field.r1, 00481 FloatData, 00482 ExceptionFrame, 00483 TrapFrame ); 00484 00485 // 00486 // emulate the 2nd half of the pair 00487 // 00488 00489 EffectiveAddress = (PVOID)((ULONG_PTR)EffectiveAddress + Length); 00490 00491 KiEmulateLoadFloat(EffectiveAddress, OpSize, &FloatData); 00492 KiSetFloatRegisterValue( (ULONG) FaultInstruction.u.i_field.r2, 00493 FloatData, 00494 ExceptionFrame, 00495 TrapFrame ); 00496 00497 } else { 00498 00499 // 00500 // floating point single load 00501 // 00502 00503 if( PreviousMode != KernelMode ){ 00504 00505 switch (OpSize) { 00506 case 0: Length = 16; break; 00507 case 1: Length = 8; break; 00508 case 2: Length = 4; break; 00509 case 3: Length = 8; break; 00510 default: 00511 return FALSE; 00512 } 00513 00514 ProbeForRead( EffectiveAddress, 00515 Length, 00516 sizeof(UCHAR) ); 00517 } 00518 00519 KiEmulateLoadFloat(EffectiveAddress, OpSize, &FloatData); 00520 KiSetFloatRegisterValue( (ULONG) FaultInstruction.u.i_field.r1, 00521 FloatData, 00522 ExceptionFrame, 00523 TrapFrame ); 00524 00525 if (FaultInstruction.u.i_field.m == 1) { 00526 00527 // 00528 // update the address register (R3) 00529 // 00530 00531 Reg2Value = KiGetRegisterValue( (ULONG) FaultInstruction.u.i_field.r2, 00532 ExceptionFrame, 00533 TrapFrame ); 00534 00535 Reg3Value = KiGetRegisterValue( (ULONG) FaultInstruction.u.i_field.r3, 00536 ExceptionFrame, 00537 TrapFrame ); 00538 // 00539 // register update form 00540 // 00541 00542 Reg3Value = Reg2Value + Reg3Value; 00543 00544 KiSetRegisterValue ((ULONG) FaultInstruction.u.i_field.r3, 00545 Reg3Value, 00546 ExceptionFrame, 00547 TrapFrame); 00548 } 00549 } 00550 00551 break; 00552 00553 // 00554 // normal, advanced and checked floating point load 00555 // immediate updated form 00556 // 00557 00558 case LDF_IMM_OP: 00559 case LDFA_IMM_OP: 00560 case LDFCCLR_IMM_OP: 00561 case LDFCNC_IMM_OP: 00562 00563 if (FaultInstruction.u.i_field.x == 1) { 00564 00565 // 00566 // floating point load pair 00567 // 00568 00569 if (FaultInstruction.u.i_field.m == 0) { 00570 00571 // 00572 // m field must be one 00573 // 00574 00575 return FALSE; 00576 00577 } 00578 00579 if( PreviousMode != KernelMode ){ 00580 00581 switch (OpSize) { 00582 case 0: return FALSE; 00583 case 1: Length = 8; break; 00584 case 2: Length = 8; break; 00585 case 3: Length = 4; break; 00586 default: 00587 return FALSE; 00588 } 00589 00590 ProbeForRead( EffectiveAddress, 00591 Length << 1, 00592 sizeof(UCHAR) ); 00593 } 00594 00595 // 00596 // emulate the 1st half of the pair 00597 // 00598 00599 KiEmulateLoadFloat(EffectiveAddress, OpSize, &FloatData); 00600 KiSetFloatRegisterValue( (ULONG) FaultInstruction.u.i_field.r1, 00601 FloatData, 00602 ExceptionFrame, 00603 TrapFrame ); 00604 00605 EffectiveAddress = (PVOID)((ULONG_PTR)EffectiveAddress + Length); 00606 00607 // 00608 // emulate the 2nd half of the pair 00609 // 00610 00611 KiEmulateLoadFloat(EffectiveAddress, OpSize, &FloatData); 00612 KiSetFloatRegisterValue( (ULONG) FaultInstruction.u.i_field.r2, 00613 FloatData, 00614 ExceptionFrame, 00615 TrapFrame ); 00616 00617 // 00618 // Update the address register (R3) 00619 // 00620 00621 Reg3Value = KiGetRegisterValue( (ULONG) FaultInstruction.u.i_field.r3, 00622 ExceptionFrame, 00623 TrapFrame ); 00624 00625 // 00626 // immediate update form 00627 // 00628 00629 ImmValue = Length << 1; 00630 00631 Reg3Value = Reg3Value + ImmValue; 00632 00633 KiSetRegisterValue( (ULONG) FaultInstruction.u.i_field.r3, 00634 Reg3Value, 00635 ExceptionFrame, 00636 TrapFrame ); 00637 00638 } else { 00639 00640 // 00641 // floating point single load 00642 // 00643 00644 if( PreviousMode != KernelMode ){ 00645 00646 switch (OpSize) { 00647 case 0: Length = 16; break; 00648 case 1: Length = 8; break; 00649 case 2: Length = 4; break; 00650 case 3: Length = 8; break; 00651 default: 00652 return FALSE; 00653 } 00654 00655 ProbeForRead( EffectiveAddress, 00656 Length, 00657 sizeof(UCHAR) ); 00658 } 00659 KiEmulateLoadFloat(EffectiveAddress, OpSize, &FloatData); 00660 KiSetFloatRegisterValue( (ULONG) FaultInstruction.u.i_field.r1, 00661 FloatData, 00662 ExceptionFrame, 00663 TrapFrame ); 00664 00665 // 00666 // Update the address register (R3) 00667 // 00668 00669 Reg3Value = KiGetRegisterValue( (ULONG) FaultInstruction.u.i_field.r3, 00670 ExceptionFrame, 00671 TrapFrame ); 00672 00673 // 00674 // immediate update form 00675 // 00676 00677 ImmValue = (ULONG)(FaultInstruction.u.i_field.r2 00678 + (FaultInstruction.u.i_field.x << 7)); 00679 00680 if (FaultInstruction.u.i_field.m == 1) { 00681 00682 ImmValue = 0xFFFFFFFFFFFFFF00 | ImmValue; 00683 00684 } 00685 00686 Reg3Value = Reg3Value + ImmValue; 00687 00688 KiSetRegisterValue( (ULONG) FaultInstruction.u.i_field.r3, 00689 Reg3Value, 00690 ExceptionFrame, 00691 TrapFrame ); 00692 } 00693 00694 break; 00695 00696 00697 case STREL_OP: 00698 00699 __mf(); 00700 00701 case ST_OP: 00702 00703 if (FaultInstruction.u.i_field.x == 1) { 00704 00705 // 00706 // xField must be 0 00707 // 00708 00709 return FALSE; 00710 } 00711 00712 if (FaultInstruction.u.i_field.m == 1) { 00713 00714 // 00715 // no register update form defined 00716 // 00717 00718 return FALSE; 00719 } 00720 00721 if( PreviousMode != KernelMode ){ 00722 ProbeForWrite( EffectiveAddress, 00723 1 << OpSize, 00724 sizeof(UCHAR) ); 00725 } 00726 Data = KiGetRegisterValue( (ULONG) FaultInstruction.u.i_field.r2, 00727 ExceptionFrame, 00728 TrapFrame ); 00729 00730 KiEmulateStore( EffectiveAddress, OpSize, &Data); 00731 00732 break; 00733 00734 case STREL_IMM_OP: 00735 00736 __mf(); 00737 00738 case ST_IMM_OP: 00739 00740 if( PreviousMode != KernelMode ){ 00741 ProbeForWrite( EffectiveAddress, 00742 1 << OpSize, 00743 sizeof(UCHAR) ); 00744 } 00745 Data = KiGetRegisterValue( (ULONG) FaultInstruction.u.i_field.r2, 00746 ExceptionFrame, 00747 TrapFrame ); 00748 00749 KiEmulateStore( EffectiveAddress, OpSize, &Data); 00750 00751 // 00752 // update the address register (R3) 00753 // 00754 00755 Reg3Value = KiGetRegisterValue( (ULONG) FaultInstruction.u.i_field.r3, 00756 ExceptionFrame, 00757 TrapFrame ); 00758 00759 // 00760 // immediate update form 00761 // 00762 00763 ImmValue = (ULONG)(FaultInstruction.u.i_field.r1 00764 + (FaultInstruction.u.i_field.x << 7)); 00765 00766 if (FaultInstruction.u.i_field.m == 1) { 00767 00768 ImmValue = 0xFFFFFFFFFFFFFF00 | ImmValue; 00769 00770 } 00771 00772 Reg3Value = Reg3Value + ImmValue; 00773 00774 KiSetRegisterValue( (ULONG) FaultInstruction.u.i_field.r3, 00775 Reg3Value, 00776 ExceptionFrame, 00777 TrapFrame ); 00778 00779 break; 00780 00781 00782 case STF_OP: 00783 00784 if (FaultInstruction.u.i_field.x) { 00785 00786 // 00787 // x field must be 0 00788 // 00789 00790 return FALSE; 00791 } 00792 00793 if (FaultInstruction.u.i_field.m) { 00794 00795 // 00796 // no register update form defined 00797 // 00798 00799 return FALSE; 00800 } 00801 00802 if( PreviousMode != KernelMode ){ 00803 00804 switch (OpSize) { 00805 case 0: Length = 16; break; 00806 case 1: Length = 8; break; 00807 case 2: Length = 4; break; 00808 case 3: Length = 8; break; 00809 default: 00810 return FALSE; 00811 } 00812 00813 ProbeForWrite( EffectiveAddress, 00814 Length, 00815 sizeof(UCHAR) ); 00816 } 00817 FloatData = KiGetFloatRegisterValue( (ULONG) FaultInstruction.u.i_field.r2, 00818 ExceptionFrame, 00819 TrapFrame ); 00820 00821 KiEmulateStoreFloat( EffectiveAddress, OpSize, &FloatData); 00822 00823 break; 00824 00825 case STF_IMM_OP: 00826 00827 if( PreviousMode != KernelMode ){ 00828 00829 switch (OpSize) { 00830 case 0: Length = 16; break; 00831 case 1: Length = 8; break; 00832 case 2: Length = 4; break; 00833 case 3: Length = 8; break; 00834 default: 00835 return FALSE; 00836 } 00837 00838 ProbeForWrite( EffectiveAddress, 00839 Length, 00840 sizeof(UCHAR) ); 00841 } 00842 FloatData = KiGetFloatRegisterValue( (ULONG) FaultInstruction.u.i_field.r2, 00843 ExceptionFrame, 00844 TrapFrame ); 00845 00846 KiEmulateStoreFloat( EffectiveAddress, OpSize, &FloatData); 00847 00848 // 00849 // update the address register (R3) 00850 // 00851 00852 Reg3Value = KiGetRegisterValue( (ULONG) FaultInstruction.u.i_field.r3, 00853 ExceptionFrame, 00854 TrapFrame ); 00855 // 00856 // immediate update form 00857 // 00858 00859 ImmValue = (ULONG)(FaultInstruction.u.i_field.r1 00860 + (FaultInstruction.u.i_field.x << 7)); 00861 00862 if (FaultInstruction.u.i_field.m == 1) { 00863 00864 ImmValue = 0xFFFFFFFFFFFFFF00 | ImmValue; 00865 00866 } 00867 00868 Reg3Value = Reg3Value + ImmValue; 00869 00870 KiSetRegisterValue( (ULONG) FaultInstruction.u.i_field.r3, 00871 Reg3Value, 00872 ExceptionFrame, 00873 TrapFrame ); 00874 00875 break; 00876 00877 default: 00878 00879 return FALSE; 00880 00881 } 00882 00883 // 00884 // advance instruction pointer 00885 // 00886 00887 KiAdvanceInstPointer(TrapFrame); 00888 00889 return TRUE; 00890 00891 // 00892 // If an exception occurs, then copy the new exception information to the 00893 // original exception record and handle the exception. 00894 // 00895 00896 } except (KiCopyInformation(ExceptionRecord, 00897 (GetExceptionInformation())->ExceptionRecord)) { 00898 00899 // 00900 // Preserve the original exception address. 00901 // 00902 00903 ExceptionRecord->ExceptionAddress = ExceptionAddress; 00904 } 00905 00906 // 00907 // Return a value of FALSE. 00908 // 00909 00910 return FALSE; 00911 } 00912 00913 00914 VOID 00915 KiEmulateLoad( 00916 IN PVOID UnalignedAddress, 00917 IN ULONG OperandSize, 00918 IN PVOID Data 00919 ) 00920 00921 /*++ 00922 00923 Routine Description: 00924 00925 This routine returns the integer value stored at the unaligned 00926 address passed in UnalignedAddress. 00927 00928 Arguments: 00929 00930 UnalignedAddress - Supplies a pointer to data value. 00931 00932 OperandSize - Supplies the size of data to be loaded 00933 00934 Data - Supplies a pointer to be filled for data 00935 00936 Return Value: 00937 00938 The value at the address pointed to by UnalignedAddress. 00939 00940 --*/ 00941 00942 { 00943 PUCHAR Source; 00944 PUCHAR Destination; 00945 ULONG i; 00946 00947 Source = (PUCHAR) UnalignedAddress; 00948 Destination = (PUCHAR) Data; 00949 OperandSize = 1 << OperandSize; 00950 00951 for (i = 0; i < OperandSize; i++) { 00952 00953 *Destination++ = *Source++; 00954 00955 } 00956 00957 return; 00958 } 00959 00960 00961 VOID 00962 KiEmulateStore( 00963 IN PVOID UnalignedAddress, 00964 IN ULONG OperandSize, 00965 IN PVOID Data 00966 ) 00967 /*++ 00968 00969 Routine Description: 00970 00971 This routine store the integer value at the unaligned 00972 address passed in UnalignedAddress. 00973 00974 Arguments: 00975 00976 UnalignedAddress - Supplies a pointer to be stored 00977 00978 OperandSize - Supplies the size of data to be storeed 00979 00980 Data - Supplies a pointer to data value 00981 00982 Return Value: 00983 00984 The value at the address pointed to by UnalignedAddress. 00985 00986 --*/ 00987 { 00988 PUCHAR Source; 00989 PUCHAR Destination; 00990 ULONG i; 00991 00992 Source = (PUCHAR) Data; 00993 Destination = (PUCHAR) UnalignedAddress; 00994 OperandSize = 1 << OperandSize; 00995 00996 for (i = 0; i < OperandSize; i++) { 00997 00998 *Destination++ = *Source++; 00999 01000 } 01001 01002 return; 01003 } 01004 01005 01006 VOID 01007 KiEmulateLoadFloat( 01008 IN PVOID UnalignedAddress, 01009 IN ULONG OperandSize, 01010 IN OUT PVOID Data 01011 ) 01012 01013 /*++ 01014 01015 Routine Description: 01016 01017 This routine returns the floating point value stored at the unaligned 01018 address passed in UnalignedAddress. 01019 01020 Arguments: 01021 01022 UnalignedAddress - Supplies a pointer to floating point data value. 01023 01024 OperandSize - Supplies the size of data to be loaded 01025 01026 Data - Supplies a pointer to be filled for data 01027 01028 Return Value: 01029 01030 The value at the address pointed to by UnalignedAddress. 01031 01032 --*/ 01033 01034 { 01035 FLOAT128 FloatData; 01036 01037 RtlMoveMemory(&FloatData, UnalignedAddress, sizeof(FLOAT128)); 01038 01039 switch (OperandSize) { 01040 01041 case 0: 01042 KiEmulateLoadFloat80(&FloatData, Data); 01043 return; 01044 01045 case 1: 01046 KiEmulateLoadFloatInt(&FloatData, Data); 01047 return; 01048 01049 case 2: 01050 KiEmulateLoadFloat32(&FloatData, Data); 01051 return; 01052 01053 case 3: 01054 KiEmulateLoadFloat64(&FloatData, Data); 01055 return; 01056 01057 default: 01058 return; 01059 } 01060 } 01061 01062 VOID 01063 KiEmulateStoreFloat( 01064 IN PVOID UnalignedAddress, 01065 IN ULONG OperandSize, 01066 IN PVOID Data 01067 ) 01068 01069 /*++ 01070 01071 Routine Description: 01072 01073 This routine stores the floating point value stored at the unaligned 01074 address passed in UnalignedAddress. 01075 01076 Arguments: 01077 01078 UnalignedAddress - Supplies a pointer to be stored. 01079 01080 OperandSize - Supplies the size of data to be loaded 01081 01082 Data - Supplies a pointer to floating point data 01083 01084 Return Value: 01085 01086 The value at the address pointed to by UnalignedAddress. 01087 01088 --*/ 01089 01090 { 01091 FLOAT128 FloatData; 01092 ULONG Length; 01093 01094 switch (OperandSize) { 01095 01096 case 0: 01097 KiEmulateStoreFloat80(&FloatData, Data); 01098 Length = 16; 01099 break; 01100 01101 case 1: 01102 KiEmulateStoreFloatInt(&FloatData, Data); 01103 Length = 8; 01104 break; 01105 01106 case 2: 01107 KiEmulateStoreFloat32(&FloatData, Data); 01108 Length = 4; 01109 break; 01110 01111 case 3: 01112 KiEmulateStoreFloat64(&FloatData, Data); 01113 Length = 8; 01114 break; 01115 01116 default: 01117 return; 01118 } 01119 01120 RtlMoveMemory(UnalignedAddress, &FloatData, Length); 01121 } 01122

Generated on Sat May 15 19:39:13 2004 for test by doxygen 1.3.7