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) 1993   IBM Corporation and Microsoft Corporation
    00004
    00005 Module Name:
    00006
    00007     alignem.c
    00008
    00009 Abstract:
    00010
    00011     This module implements the code necessary to emulate unaligned data
    00012     references.
    00013
    00014 Author:
    00015
    00016     Rick Simpson  4-Aug-1993
    00017
    00018     Based on MIPS version by David N. Cutler (davec) 17-Jun-1991
    00019
    00020 Environment:
    00021
    00022     Kernel mode only.
    00023
    00024 Revision History:
    00025
    00026 --*/
    00027
    00028 #include "ki.h"
    00029
    00030 VOID
    00031 KiSetFloatRegisterValue (
    00032     IN ULONG,
    00033     IN DOUBLE,
    00034     OUT PKEXCEPTION_FRAME,
    00035     OUT PKTRAP_FRAME
    00036     );
    00037
    00038 DOUBLE
    00039 KiGetFloatRegisterValue (
    00040     IN ULONG,
    00041     IN PKEXCEPTION_FRAME,
    00042     IN PKTRAP_FRAME
    00043     );
    00044
    00045 /*++
    00046     When PowerPC takes an Alignment Interrupt, the hardware loads the following:
    00047         SRR 0 <- Address of instruction causing the interrupt
    00048         SRR 1 <- MSR
    00049         DAR   <- Effective address of the misaligned reference as computed
    00050                    by the instruction that caused the interrupt
    00051         DSISR <- Several fields relevant to the failing instruction:
    00052                    Bits 12..13 <- Extended op-code (XO) if instr is DS-form
    00053                    Bits 15..21 <- Index into the table below, identifying
    00054                                     (for the most part) the failing instr
    00055                    Bits 22..26 <- RT/RS/FRT/FRS field (reg no.) of instr
    00056                    Bits 27..31 <- RA (reg no.) field for update-form instrs
    00057
    00058     For the most part, it is not necessary to retrieve the actual instruction
    00059     in order to emulate the effects of an unaligned load or store.  Enough
    00060     information is in the DSISR to distinguish most cases.  Special processing
    00061     is required for certain instructions -- the DSISR does not have enough
    00062     information for them.
    00063
    00064     It is unnecessary to compute the failing effective address by emulating
    00065     the instruction's addressing arithmetic, because the value required is
    00066     contained in the DAR.
    00067
    00068     The table here is indexed by bits 15..21 of the DSISR.
    00069
    00070     The "escape" flag indicates that some sort of special handling is needed,
    00071     for one of the following reasons:
    00072          1) More than one instruction maps to the same DSISR value
    00073               (ld/ldu/lwa, std/stdu)
    00074          2) The instruction is load-and-reserve or store-conditional,
    00075               and misalignment should not be "fixed up"
    00076          3) The instruction is a byte-reversed load or store
    00077          4) The instruction is "ecowx" or "eciwx"
    00078          5) The instruction is "dcbz"
    00079          6) The instruction is "stfiwx"
    00080
    00081     NOTE:  Even though lwz and lwarx share the same DSISR value (0), the
    00082     table entry for position 0 is used only for lwz.  This is so that the
    00083     most likely case (load word from unaligned address) can take the
    00084     mainline path.  The less likely case (load word and reserve from
    00085     unaligned address) is ignored and treated as if it were simply load
    00086     word.  Unaligned addresses are not supported for lwarx/stwcx. in the
    00087     PowerPC architecture.  The implementation here (allowing lwarx to
    00088     proceed as if it were lwx, without establishing a reservation) is
    00089     allowable according to the architecture; a matching store conditional
    00090     (stwcx.) to the same unaligned address will fail (return FALSE from
    00091     this routine), so the incorrect reservation address will be caught
    00092     then.
    00093 --*/
    00094
    00095 typedef struct _ALFAULT {
    00096     ULONG Valid    : 1;  // Valid DSISR value (1) vs. Should not occur (0)
    00097     ULONG Load     : 1;  // Load (1) vs. Store (0)
    00098     ULONG Length   : 2;  // Length:  2 bytes (1), 4 bytes (2), 8 bytes (3)
    00099     ULONG Signed   : 1;  // Sign-extended (1) vs. Zero-extended (0)
    00100     ULONG Fixed    : 1;  // Fixed point (1) vs. Floating point (0)
    00101     ULONG Update   : 1;  // Update-form (1) vs. Non-Update-form (0)
    00102     ULONG Escape   : 1;  // Needs special processing (1) vs. Regular (0)
    00103 } ALFAULT, *PALFAULT;
    00104
    00105 // Table indices for instructions needing special handling
    00106
    00107 #define LDARX_INDEX_VALUE     1
    00108 #define LD_INDEX_VALUE       13
    00109 #define STD_INDEX_VALUE      15
    00110 #define STWCX_INDEX_VALUE    66
    00111 #define STDCX_INDEX_VALUE    67
    00112 #define LWBRX_INDEX_VALUE    72
    00113 #define STWBRX_INDEX_VALUE   74
    00114 #define LHBRX_INDEX_VALUE    76
    00115 #define STHBRX_INDEX_VALUE   78
    00116 #define ECIWX_INDEX_VALUE    84
    00117 #define ECOWX_INDEX_VALUE    86
    00118 #define DCBZ_INDEX_VALUE     95
    00119 #define STFIWX_INDEX_VALUE  111
    00120
    00121 static ALFAULT AlFault[128] = {
    00122
    00123 //   Valid  Load  Length  Signed  Fixed  Update  Escape
    00124     {  1,     1,     2,      0,     1,      0,      0  },  //   0   lwz, lwarx
    00125     {  1,     1,     3,      0,     1,      0,      1  },  //   1   ldarx
    00126     {  1,     0,     2,      0,     1,      0,      0  },  //   2   stw
    00127     {  0,     0,     0,      0,     0,      0,      0  },  //   3
    00128     {  1,     1,     1,      0,     1,      0,      0  },  //   4   lhz
    00129     {  1,     1,     1,      1,     1,      0,      0  },  //   5   lha
    00130     {  1,     0,     1,      0,     1,      0,      0  },  //   6   sth
    00131     {  0,     0,     0,      0,     0,      0,      0  },  //   7
    00132     {  1,     1,     2,      0,     0,      0,      0  },  //   8   lfs
    00133     {  1,     1,     3,      0,     0,      0,      0  },  //   9   lfd
    00134     {  1,     0,     2,      0,     0,      0,      0  },  //  10   stfs
    00135     {  1,     0,     3,      0,     0,      0,      0  },  //  11   stfd
    00136     {  0,     0,     0,      0,     0,      0,      0  },  //  12
    00137     {  1,     1,     0,      0,     0,      0,      1  },  //  13   ld, ldu, lwa
    00138     {  0,     0,     0,      0,     0,      0,      0  },  //  14
    00139     {  1,     0,     0,      0,     0,      0,      1  },  //  15   std, stdu
    00140     {  1,     1,     2,      0,     1,      1,      0  },  //  16   lwzu
    00141     {  0,     0,     0,      0,     0,      0,      0  },  //  17
    00142     {  1,     0,     2,      0,     1,      1,      0  },  //  18   stwu
    00143     {  0,     0,     0,      0,     0,      0,      0  },  //  19
    00144     {  1,     1,     1,      0,     1,      1,      0  },  //  20   lhzu
    00145     {  1,     1,     1,      1,     1,      1,      0  },  //  21   lhau
    00146     {  1,     0,     1,      0,     1,      1,      0  },  //  22   sthu
    00147     {  0,     0,     0,      0,     0,      0,      0  },  //  23
    00148     {  1,     1,     2,      0,     0,      1,      0  },  //  24   lfsu
    00149     {  1,     1,     3,      0,     0,      1,      0  },  //  25   lfdu
    00150     {  1,     0,     2,      0,     0,      1,      0  },  //  26   stfsu
    00151     {  1,     0,     3,      0,     0,      1,      0  },  //  27   stfdu
    00152     {  0,     0,     0,      0,     0,      0,      0  },  //  28
    00153     {  0,     0,     0,      0,     0,      0,      0  },  //  29
    00154     {  0,     0,     0,      0,     0,      0,      0  },  //  30
    00155     {  0,     0,     0,      0,     0,      0,      0  },  //  31
    00156     {  1,     1,     3,      0,     1,      0,      0  },  //  32   ldx
    00157     {  0,     0,     0,      0,     0,      0,      0  },  //  33
    00158     {  1,     0,     3,      0,     1,      0,      0  },  //  34   stdx
    00159     {  0,     0,     0,      0,     0,      0,      0  },  //  35
    00160     {  0,     0,     0,      0,     0,      0,      0  },  //  36
    00161     {  1,     1,     2,      1,     1,      0,      0  },  //  37   lwax
    00162     {  0,     0,     0,      0,     0,      0,      0  },  //  38
    00163     {  0,     0,     0,      0,     0,      0,      0  },  //  39
    00164     {  0,     0,     0,      0,     0,      0,      0  },  //  40
    00165     {  0,     0,     0,      0,     0,      0,      0  },  //  41
    00166     {  0,     0,     0,      0,     0,      0,      0  },  //  42
    00167     {  0,     0,     0,      0,     0,      0,      0  },  //  43
    00168     {  0,     0,     0,      0,     0,      0,      0  },  //  44
    00169     {  0,     0,     0,      0,     0,      0,      0  },  //  45
    00170     {  0,     0,     0,      0,     0,      0,      0  },  //  46
    00171     {  0,     0,     0,      0,     0,      0,      0  },  //  47
    00172     {  1,     1,     3,      0,     1,      1,      0  },  //  48   ldux
    00173     {  0,     0,     0,      0,     0,      0,      0  },  //  49
    00174     {  1,     0,     3,      0,     1,      1,      0  },  //  50   stdux
    00175     {  0,     0,     0,      0,     0,      0,      0  },  //  51
    00176     {  0,     0,     0,      0,     0,      0,      0  },  //  52
    00177     {  1,     1,     2,      1,     1,      1,      0  },  //  53   lwaux
    00178     {  0,     0,     0,      0,     0,      0,      0  },  //  54
    00179     {  0,     0,     0,      0,     0,      0,      0  },  //  55
    00180     {  0,     0,     0,      0,     0,      0,      0  },  //  56
    00181     {  0,     0,     0,      0,     0,      0,      0  },  //  57
    00182     {  0,     0,     0,      0,     0,      0,      0  },  //  58
    00183     {  0,     0,     0,      0,     0,      0,      0  },  //  59
    00184     {  0,     0,     0,      0,     0,      0,      0  },  //  60
    00185     {  0,     0,     0,      0,     0,      0,      0  },  //  61
    00186     {  0,     0,     0,      0,     0,      0,      0  },  //  62
    00187     {  0,     0,     0,      0,     0,      0,      0  },  //  63
    00188     {  0,     0,     0,      0,     0,      0,      0  },  //  64
    00189     {  0,     0,     0,      0,     0,      0,      0  },  //  65
    00190     {  1,     0,     2,      0,     1,      0,      1  },  //  66   stwcx.
    00191     {  1,     0,     3,      0,     1,      0,      1  },  //  67   stdcx.
    00192     {  0,     0,     0,      0,     0,      0,      0  },  //  68
    00193     {  0,     0,     0,      0,     0,      0,      0  },  //  69
    00194     {  0,     0,     0,      0,     0,      0,      0  },  //  70
    00195     {  0,     0,     0,      0,     0,      0,      0  },  //  71
    00196     {  1,     1,     2,      0,     1,      0,      1  },  //  72   lwbrx
    00197     {  0,     0,     0,      0,     0,      0,      0  },  //  73
    00198     {  1,     0,     2,      0,     1,      0,      1  },  //  74   stwbrx
    00199     {  0,     0,     0,      0,     0,      0,      0  },  //  75
    00200     {  1,     1,     1,      0,     1,      0,      1  },  //  76   lhbrx
    00201     {  0,     0,     0,      0,     0,      0,      0  },  //  77
    00202     {  1,     0,     1,      0,     1,      0,      1  },  //  78   sthbrx
    00203     {  0,     0,     0,      0,     0,      0,      0  },  //  79
    00204     {  0,     0,     0,      0,     0,      0,      0  },  //  80
    00205     {  0,     0,     0,      0,     0,      0,      0  },  //  81
    00206     {  0,     0,     0,      0,     0,      0,      0  },  //  82
    00207     {  0,     0,     0,      0,     0,      0,      0  },  //  83
    00208     {  1,     1,     2,      0,     1,      0,      1  },  //  84   eciwx
    00209     {  0,     0,     0,      0,     0,      0,      0  },  //  85
    00210     {  1,     0,     2,      0,     1,      0,      1  },  //  86   ecowx
    00211     {  0,     0,     0,      0,     0,      0,      0  },  //  87
    00212     {  0,     0,     0,      0,     0,      0,      0  },  //  88
    00213     {  0,     0,     0,      0,     0,      0,      0  },  //  89
    00214     {  0,     0,     0,      0,     0,      0,      0  },  //  90
    00215     {  0,     0,     0,      0,     0,      0,      0  },  //  91
    00216     {  0,     0,     0,      0,     0,      0,      0  },  //  92
    00217     {  0,     0,     0,      0,     0,      0,      0  },  //  93
    00218     {  0,     0,     0,      0,     0,      0,      0  },  //  94
    00219     {  1,     0,     0,      0,     0,      0,      1  },  //  95   dcbz
    00220     {  1,     1,     2,      0,     1,      0,      0  },  //  96   lwzx
    00221     {  0,     0,     0,      0,     0,      0,      0  },  //  97
    00222     {  1,     0,     2,      0,     1,      0,      0  },  //  98   stwzx
    00223     {  0,     0,     0,      0,     0,      0,      0  },  //  99
    00224     {  1,     1,     1,      0,     1,      0,      0  },  // 100   lhzx
    00225     {  1,     1,     1,      1,     1,      0,      0  },  // 101   lhax
    00226     {  1,     0,     1,      0,     1,      0,      0  },  // 102   sthx
    00227     {  0,     0,     0,      0,     0,      0,      0  },  // 103
    00228     {  1,     1,     2,      0,     0,      0,      0  },  // 104   lfsx
    00229     {  1,     1,     3,      0,     0,      0,      0  },  // 105   lfdx
    00230     {  1,     0,     2,      0,     0,      0,      0  },  // 106   stfsx
    00231     {  1,     0,     3,      0,     0,      0,      0  },  // 107   stfdx
    00232     {  0,     0,     0,      0,     0,      0,      0  },  // 108
    00233     {  0,     0,     0,      0,     0,      0,      0  },  // 109
    00234     {  0,     0,     0,      0,     0,      0,      0  },  // 110
    00235     {  1,     0,     2,      0,     1,      0,      1  },  // 111   stfiwx
    00236     {  1,     1,     2,      0,     1,      1,      0  },  // 112   lwzux
    00237     {  0,     0,     0,      0,     0,      0,      0  },  // 113
    00238     {  1,     0,     2,      0,     1,      1,      0  },  // 114   stwux
    00239     {  0,     0,     0,      0,     0,      0,      0  },  // 115
    00240     {  1,     1,     1,      0,     1,      1,      0  },  // 116   lhzux
    00241     {  1,     1,     1,      1,     1,      1,      0  },  // 117   lhaux
    00242     {  1,     0,     1,      0,     1,      1,      0  },  // 118   sthux
    00243     {  0,     0,     0,      0,     0,      0,      0  },  // 119
    00244     {  1,     1,     2,      0,     0,      1,      0  },  // 120   lfsux
    00245     {  1,     1,     3,      0,     0,      1,      0  },  // 121   lfdux
    00246     {  1,     0,     2,      0,     0,      1,      0  },  // 122   stfsux
    00247     {  1,     0,     3,      0,     0,      1,      0  },  // 123   stfdux
    00248     {  0,     0,     0,      0,     0,      0,      0  },  // 124
    00249     {  0,     0,     0,      0,     0,      0,      0  },  // 125
    00250     {  0,     0,     0,      0,     0,      0,      0  },  // 126
    00251     {  0,     0,     0,      0,     0,      0,      0  }   // 127
    00252 };
    00253
    00254 BOOLEAN
    00255 KiEmulateReference (
    00256     IN OUT PEXCEPTION_RECORD ExceptionRecord,
    00257     IN OUT PKEXCEPTION_FRAME ExceptionFrame,
    00258     IN OUT PKTRAP_FRAME TrapFrame
    00259     )
    00260
    00261 /*++
    00262
    00263 Routine Description:
    00264
    00265     This function is called to emulate an unaligned data reference to an
    00266     address in the user part of the address space.
    00267
    00268 Arguments:
    00269
    00270     ExceptionRecord - Supplies a pointer to an exception record.
    00271
    00272     ExceptionFrame - Supplies a pointer to an exception frame.
    00273
    00274     TrapFrame - Supplies a pointer to a trap frame.
    00275
    00276 Return Value:
    00277
    00278     A value of TRUE is returned if the data reference is successfully
    00279     emulated. Otherwise, a value of FALSE is returned.
    00280
    00281 --*/
    00282
    00283 {
    00284
    00285     ULONG BranchAddress;
    00286     PUCHAR DataAddress;
    00287
    00288     union {
    00289         DOUBLE Double;
    00290         float  Float;
    00291         ULONG  Long;
    00292         SHORT  Short;
    00293     } DataReference;
    00294     PUCHAR DataValue = (PUCHAR) &DataReference;
    00295
    00296     PVOID ExceptionAddress;
    00297     DSISR DsisrValue;
    00298     ULONG TableIndex;
    00299     ULONG DataRegNum;
    00300     ALFAULT Info;
    00301     KIRQL OldIrql;
    00302
    00303     //
    00304     // Call out to profile interrupt if alignment profiling is active
    00305     //
    00306     if (KiProfileAlignmentFixup) {
    00307
    00308         if (++KiProfileAlignmentFixupCount >= KiProfileAlignmentFixupInterval) {
    00309
    00310             KeRaiseIrql(PROFILE_LEVEL, &OldIrql);
    00311             KiProfileAlignmentFixupCount = 0;
    00312             KeProfileInterruptWithSource(TrapFrame, ProfileAlignmentFixup);
    00313             KeLowerIrql(OldIrql);
    00314
    00315         }
    00316     }
    00317
    00318     //
    00319     // Save the original exception address in case another exception
    00320     // occurs.
    00321     //
    00322
    00323     ExceptionAddress = ExceptionRecord->ExceptionAddress;
    00324
    00325     //
    00326     // Any exception that occurs during the attempted emulation of the
    00327     // unaligned reference causes the emulation to be aborted. The new
    00328     // exception code and information is copied to the original exception
    00329     // record and a value of FALSE is returned.
    00330     //
    00331
    00332     try {
    00333
    00334         //
    00335         // PowerPC has no branch-delay-slot complexities like MIPS
    00336         //
    00337
    00338         BranchAddress = TrapFrame->Iar + 4;
    00339
    00340         //
    00341         // The effective address of the reference from the DAR was saved
    00342         // in the exception record. Check to make sure it is within the
    00343         // user part of the address space. Alignment exceptions take
    00344         // precedence over memory management exceptions (this is true
    00345         // for PowerPC as well as MIPS) and the address could be a
    00346         // system address.
    00347         //
    00348
    00349         DataAddress = (PUCHAR) (ExceptionRecord->ExceptionInformation[1]);
    00350
    00351         if ((ULONG)DataAddress < MM_USER_PROBE_ADDRESS) {
    00352
    00353             //
    00354             // Get information about the failing instruction from saved DSISR.
    00355             //
    00356
    00357             DsisrValue = *(DSISR*) &(ExceptionRecord->ExceptionInformation[2]);
    00358             TableIndex = DsisrValue.Index;
    00359             DataRegNum = DsisrValue.DataReg;
    00360             Info = AlFault[TableIndex];
    00361
    00362             //
    00363             // If table entry is marked invalid, we have some sort of logic error.
    00364             //
    00365
    00366             if (!Info.Valid)
    00367                 return FALSE;
    00368
    00369             //
    00370             // If table entry does not indicate special processing needed,
    00371             //   emulate the execution of the instruction
    00372             //
    00373
    00374             if (!Info.Escape) {
    00375
    00376                     //
    00377                     // Integer or float load or store
    00378                     //
    00379
    00380                 if (Info.Fixed) {
    00381
    00382                         //
    00383                         // Integer register
    00384                         //
    00385
    00386                     if (Info.Load) {
    00387
    00388                             //
    00389                             // Integer load
    00390                             //
    00391
    00392                         switch (Info.Length) {
    00393
    00394                                 //
    00395                                 // Halfword integer load
    00396                                 //
    00397
    00398                           case 1:
    00399                             DataValue[0] = DataAddress[0];
    00400                             DataValue[1] = DataAddress[1];
    00401                             KiSetRegisterValue
    00402                                 (DataRegNum,
    00403                                  Info.Signed ?   // sign extension ...
    00404                                      (ULONG) ((LONG) DataReference.Short) :
    00405                                      (ULONG) ((USHORT) DataReference.Short),
    00406                                  ExceptionFrame,
    00407                                  TrapFrame);
    00408                             break;
    00409
    00410                                 //
    00411                                 // Fullword integer load
    00412                                 //
    00413
    00414                           case 2:
    00415                             DataValue[0] = DataAddress[0];
    00416                             DataValue[1] = DataAddress[1];
    00417                             DataValue[2] = DataAddress[2];
    00418                             DataValue[3] = DataAddress[3];
    00419                             KiSetRegisterValue
    00420                                 (DataRegNum,
    00421                                  DataReference.Long,
    00422                                  ExceptionFrame,
    00423                                  TrapFrame);
    00424                             break;
    00425
    00426                                 //
    00427                                 // Doubleword integer load
    00428                                 //
    00429
    00430                           case 3:
    00431                             return FALSE; // Have no 8-byte integer regs yet
    00432
    00433                         }
    00434                     } else {
    00435
    00436                             //
    00437                             // Integer store
    00438                             //
    00439
    00440                         switch (Info.Length) {
    00441
    00442                                 //
    00443                                 // Halfword integer store
    00444                                 //
    00445
    00446                           case 1:
    00447                             DataReference.Short = (SHORT)
    00448                                 KiGetRegisterValue
    00449                                     (DataRegNum,
    00450                                      ExceptionFrame,
    00451                                      TrapFrame);
    00452                             DataAddress[0] = DataValue[0];
    00453                             DataAddress[1] = DataValue[1];
    00454                             break;
    00455
    00456                                 //
    00457                                 // Fullword integer store
    00458                                 //
    00459
    00460                           case 2:       // Word
    00461                             DataReference.Long =
    00462                                 KiGetRegisterValue
    00463                                     (DataRegNum,
    00464                                      ExceptionFrame,
    00465                                      TrapFrame);
    00466                             DataAddress[0] = DataValue[0];
    00467                             DataAddress[1] = DataValue[1];
    00468                             DataAddress[2] = DataValue[2];
    00469                             DataAddress[3] = DataValue[3];
    00470                             break;
    00471
    00472                                 //
    00473                                 // Doubleword integer store
    00474                                 //
    00475
    00476                           case 3:
    00477
    00478                             return FALSE; // Have no 8-byte integer regs yet
    00479                         }
    00480                     }
    00481                 } else {                // Floating point
    00482
    00483                         //
    00484                         // Floating-point register
    00485                         //
    00486
    00487                     if (Info.Load) {    // Floating point load
    00488
    00489                             //
    00490                             // Floating-point load
    00491                             //
    00492
    00493                         if (Info.Length == 2) {
    00494
    00495                                 //
    00496                                 // Floating-point single precision load
    00497                                 //
    00498                             DataValue[0] = DataAddress[0];
    00499                             DataValue[1] = DataAddress[1];
    00500                             DataValue[2] = DataAddress[2];
    00501                             DataValue[3] = DataAddress[3];
    00502                             KiSetFloatRegisterValue
    00503                                 (DataRegNum,
    00504                                  (DOUBLE) DataReference.Float,
    00505                                  ExceptionFrame,
    00506                                  TrapFrame);
    00507
    00508                         } else {
    00509
    00510                                 //
    00511                                 // Floating-point double precision load
    00512                                 //
    00513                             DataValue[0] = DataAddress[0];
    00514                             DataValue[1] = DataAddress[1];
    00515                             DataValue[2] = DataAddress[2];
    00516                             DataValue[3] = DataAddress[3];
    00517                             DataValue[4] = DataAddress[4];
    00518                             DataValue[5] = DataAddress[5];
    00519                             DataValue[6] = DataAddress[6];
    00520                             DataValue[7] = DataAddress[7];
    00521                             KiSetFloatRegisterValue
    00522                                 (DataRegNum,
    00523                                  DataReference.Double,
    00524                                  ExceptionFrame,
    00525                                  TrapFrame);
    00526                         }
    00527                     } else {
    00528
    00529                             //
    00530                             // Floating-point store
    00531                             //
    00532
    00533                         if (Info.Length == 2) {
    00534
    00535                                 //
    00536                                 // Floating-point single precision store
    00537                                 //
    00538
    00539                             DataReference.Float = (float)
    00540                                 KiGetFloatRegisterValue
    00541                                     (DataRegNum,
    00542                                      ExceptionFrame,
    00543                                      TrapFrame);
    00544                             DataAddress[0] = DataValue[0];
    00545                             DataAddress[1] = DataValue[1];
    00546                             DataAddress[2] = DataValue[2];
    00547                             DataAddress[3] = DataValue[3];
    00548
    00549                         } else {
    00550
    00551                                 //
    00552                                 // Floating-point double precision store
    00553                                 //
    00554                             DataReference.Double =
    00555                                 KiGetFloatRegisterValue
    00556                                     (DataRegNum,
    00557                                      ExceptionFrame,
    00558                                      TrapFrame);
    00559                             DataAddress[0] = DataValue[0];
    00560                             DataAddress[1] = DataValue[1];
    00561                             DataAddress[2] = DataValue[2];
    00562                             DataAddress[3] = DataValue[3];
    00563                             DataAddress[4] = DataValue[4];
    00564                             DataAddress[5] = DataValue[5];
    00565                             DataAddress[6] = DataValue[6];
    00566                             DataAddress[7] = DataValue[7];
    00567                         }
    00568                     }
    00569                 }
    00570
    00571                 //
    00572                 // See if "update" (post-increment) form of addressing
    00573                 //
    00574
    00575                 if (Info.Update)
    00576                     KiSetRegisterValue  // Store effective addr back into base reg
    00577                         (DsisrValue.UpdateReg,
    00578                          (ULONG) DataAddress,
    00579                          ExceptionFrame,
    00580                          TrapFrame);
    00581
    00582             }
    00583
    00584             //
    00585             // Table indicates that special processing is needed, either because
    00586             // the DSISR does not contain enough information to disambiguate the
    00587             // failing instruction, or the instruction is not a load or store,
    00588             // or the instruction has some other unusual requirement.
    00589             //
    00590
    00591             else {                      // Info.Escape == 1
    00592                 switch (TableIndex) {
    00593
    00594                 //
    00595                 // Doubleword integers not yet supported
    00596                 //
    00597
    00598                   case LD_INDEX_VALUE:
    00599                   case STD_INDEX_VALUE:
    00600                     return FALSE;
    00601
    00602                 //
    00603                 // Load-and-reserve, store-conditional not supported
    00604                 //   for misaligned addresses
    00605                 //
    00606
    00607                   case LDARX_INDEX_VALUE:
    00608                   case STWCX_INDEX_VALUE:
    00609                   case STDCX_INDEX_VALUE:
    00610                     return FALSE;
    00611
    00612                 //
    00613                 // Integer byte-reversed fullword load
    00614                 //
    00615
    00616                   case LWBRX_INDEX_VALUE:
    00617                     DataValue[0] = DataAddress[3];
    00618                     DataValue[1] = DataAddress[2];
    00619                     DataValue[2] = DataAddress[1];
    00620                     DataValue[3] = DataAddress[0];
    00621                     KiSetRegisterValue
    00622                         (DataRegNum,
    00623                          DataReference.Long,
    00624                          ExceptionFrame,
    00625                          TrapFrame);
    00626                     break;
    00627
    00628                 //
    00629                 // Integer byte-reversed fullword store
    00630                 //
    00631
    00632                   case STWBRX_INDEX_VALUE:
    00633                     DataReference.Long =
    00634                         KiGetRegisterValue
    00635                             (DataRegNum,
    00636                              ExceptionFrame,
    00637                              TrapFrame);
    00638                     DataAddress[0] = DataValue[3];
    00639                     DataAddress[1] = DataValue[2];
    00640                     DataAddress[2] = DataValue[1];
    00641                     DataAddress[3] = DataValue[0];
    00642                     break;
    00643
    00644                 //
    00645                 // Integer byte-reversed halfword load
    00646                 //
    00647
    00648                   case LHBRX_INDEX_VALUE:
    00649                     DataValue[0] = DataAddress[1];
    00650                     DataValue[1] = DataAddress[0];
    00651                     KiSetRegisterValue
    00652                         (DataRegNum,
    00653                          Info.Signed ?   // sign extension ...
    00654                              (ULONG) ((LONG) DataReference.Short) :
    00655                              (ULONG) ((USHORT) DataReference.Short),
    00656                          ExceptionFrame,
    00657                          TrapFrame);
    00658                     break;
    00659
    00660                 //
    00661                 // Integer byte-reversed halfword store
    00662                 //
    00663
    00664                   case STHBRX_INDEX_VALUE:
    00665                     DataReference.Short = (SHORT)
    00666                         KiGetRegisterValue
    00667                             (DataRegNum,
    00668                              ExceptionFrame,
    00669                              TrapFrame);
    00670                     DataAddress[0] = DataValue[1];
    00671                     DataAddress[1] = DataValue[0];
    00672                     break;
    00673
    00674                 //
    00675                 // Special I/O instructions not supported yet
    00676                 //
    00677
    00678                   case ECIWX_INDEX_VALUE:
    00679                   case ECOWX_INDEX_VALUE:
    00680                     return FALSE;
    00681
    00682                 //
    00683                 // Data Cache Block Zero
    00684                 //
    00685                 //   dcbz causes an alignment fault if cache is disabled
    00686                 //   for the address range covered by the block.
    00687                 //
    00688                 //   A data cache block is 32 bytes long, we emulate this
    00689                 //   instruction by storing 8 zero integers a the address
    00690                 //   specified.
    00691                 //
    00692                 //   Note, dcbz zeros the block "containing" the address
    00693                 //   so we round down first.
    00694                 //
    00695
    00696                   case DCBZ_INDEX_VALUE: {
    00697                     PULONG DcbAddress = (PULONG)((ULONG)DataAddress & ~0x1f);
    00698
    00699                     *DcbAddress++ = 0;
    00700                     *DcbAddress++ = 0;
    00701                     *DcbAddress++ = 0;
    00702                     *DcbAddress++ = 0;
    00703                     *DcbAddress++ = 0;
    00704                     *DcbAddress++ = 0;
    00705                     *DcbAddress++ = 0;
    00706                     *DcbAddress++ = 0;
    00707                     break;
    00708                   }
    00709
    00710                 //
    00711                 // Store Floating as Integer
    00712                 //
    00713
    00714                   case STFIWX_INDEX_VALUE:
    00715                     DataReference.Double =
    00716                         KiGetFloatRegisterValue
    00717                             (DataRegNum,
    00718                              ExceptionFrame,
    00719                              TrapFrame);
    00720                     DataAddress[0] = DataValue[0];
    00721                     DataAddress[1] = DataValue[1];
    00722                     DataAddress[2] = DataValue[2];
    00723                     DataAddress[3] = DataValue[3];
    00724                 }
    00725             }
    00726
    00727             TrapFrame->Iar = BranchAddress;
    00728             return TRUE;
    00729         }
    00730
    00731     //
    00732     // If an exception occurs, then copy the new exception information to the
    00733     // original exception record and handle the exception.
    00734     //
    00735
    00736     } except (KiCopyInformation(ExceptionRecord,
    00737                                (GetExceptionInformation())->ExceptionRecord)) {
    00738
    00739         //
    00740         // Preserve the original exception address.
    00741         //
    00742
    00743         ExceptionRecord->ExceptionAddress = ExceptionAddress;
    00744     }
    00745
    00746     //
    00747     // Return a value of FALSE.
    00748     //
    00749
    00750     return FALSE;
    00751 }
    00752
    00753 BOOLEAN
    00754 KiEmulateDcbz (
    00755     IN OUT PEXCEPTION_RECORD ExceptionRecord,
    00756     IN OUT PKEXCEPTION_FRAME ExceptionFrame,
    00757     IN OUT PKTRAP_FRAME TrapFrame
    00758     )
    00759
    00760 /*++
    00761
    00762 Routine Description:
    00763
    00764     This function is called to emulate a Data Cache Block Zero instruction.
    00765     The PowerPC hardware will raise an alignment exception if a DCBZ is
    00766     attempted on non-cached memory.   We need to emulate this even in kernel
    00767     mode so we can debug h/w problems by disabling the data cache.
    00768
    00769 Arguments:
    00770
    00771     ExceptionRecord - Supplies a pointer to an exception record.
    00772
    00773     ExceptionFrame - Supplies a pointer to an exception frame.
    00774
    00775     TrapFrame - Supplies a pointer to a trap frame.
    00776
    00777 Return Value:
    00778
    00779     A value of TRUE is returned if the data reference is successfully
    00780     emulated. Otherwise, a value of FALSE is returned.
    00781
    00782 --*/
    00783
    00784 {
    00785
    00786     PUCHAR DataAddress;
    00787     PVOID ExceptionAddress;
    00788     DSISR DsisrValue;
    00789     ULONG TableIndex;
    00790     ULONG DataRegNum;
    00791     ALFAULT Info;
    00792
    00793     //
    00794     // Save the original exception address in case another exception
    00795     // occurs.
    00796     //
    00797
    00798     ExceptionAddress = ExceptionRecord->ExceptionAddress;
    00799
    00800     //
    00801     // Any exception that occurs during the attempted emulation of the
    00802     // unaligned reference causes the emulation to be aborted. The new
    00803     // exception code and information is copied to the original exception
    00804     // record and a value of FALSE is returned.
    00805     //
    00806
    00807     try {
    00808
    00809         //
    00810         // The effective address of the reference from the DAR was saved
    00811         // in the exception record. Check to make sure it is within the
    00812         // user part of the address space. Alignment exceptions take
    00813         // precedence over memory management exceptions (this is true
    00814         // for PowerPC as well as MIPS) and the address could be a
    00815         // system address.
    00816         //
    00817
    00818         DataAddress = (PUCHAR) (ExceptionRecord->ExceptionInformation[1]);
    00819
    00820         //
    00821         // Get information about the failing instruction from saved DSISR.
    00822         //
    00823
    00824         DsisrValue = *(DSISR*) &(ExceptionRecord->ExceptionInformation[2]);
    00825         TableIndex = DsisrValue.Index;
    00826         DataRegNum = DsisrValue.DataReg;
    00827         Info = AlFault[TableIndex];
    00828
    00829         //
    00830         // If table entry is valid and does not indicate special processing
    00831         // needed, and is a DCBZ instruction, emulate the execution of the
    00832         // instruction
    00833         //
    00834
    00835         if (Info.Valid && Info.Escape && (TableIndex == DCBZ_INDEX_VALUE)) {
    00836
    00837             //
    00838             // Data Cache Block Zero
    00839             //
    00840             //   A data cache block is 32 bytes long, we emulate this
    00841             //   instruction by storing 8 zero integers a the address
    00842             //   specified.
    00843             //
    00844             //   Note, dcbz zeros the block "containing" the address
    00845             //   so we round down first.
    00846             //
    00847
    00848             PULONG DcbAddress = (PULONG)((ULONG)DataAddress & ~0x1f);
    00849
    00850             *DcbAddress++ = 0;
    00851             *DcbAddress++ = 0;
    00852             *DcbAddress++ = 0;
    00853             *DcbAddress++ = 0;
    00854             *DcbAddress++ = 0;
    00855             *DcbAddress++ = 0;
    00856             *DcbAddress++ = 0;
    00857             *DcbAddress++ = 0;
    00858
    00859             //
    00860             // Bump instruction address to next instruction.
    00861             //
    00862
    00863             TrapFrame->Iar += 4;
    00864
    00865             return TRUE;
    00866         }
    00867
    00868     //
    00869     // If an exception occurs, then copy the new exception information to the
    00870     // original exception record and handle the exception.
    00871     //
    00872
    00873     } except (KiCopyInformation(ExceptionRecord,
    00874                                (GetExceptionInformation())->ExceptionRecord)) {
    00875
    00876         //
    00877         // Preserve the original exception address.
    00878         //
    00879
    00880         ExceptionRecord->ExceptionAddress = ExceptionAddress;
    00881     }
    00882
    00883     //
    00884     // Return a value of FALSE.
    00885     //
    00886
    00887     return FALSE;
    00888 }