test: alignem.c Source File

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