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

alignem.c File Reference

#include "ki.h"

Go to the source code of this file.

Functions

BOOLEAN KiEmulateReference (IN OUT PEXCEPTION_RECORD ExceptionRecord, IN OUT PKEXCEPTION_FRAME ExceptionFrame, IN OUT PKTRAP_FRAME TrapFrame)


Function Documentation

BOOLEAN KiEmulateReference IN OUT PEXCEPTION_RECORD  ExceptionRecord,
IN OUT PKEXCEPTION_FRAME  ExceptionFrame,
IN OUT PKTRAP_FRAME  TrapFrame
 

Definition at line 29 of file mips/alignem.c.

References FALSE, KeLowerIrql(), KeProfileInterruptWithSource(), KeRaiseIrql(), KiCopyInformation(), KiEmulateBranch(), KiGetRegisterValue(), KiGetRegisterValue64(), KiProfileAlignmentFixup, KiProfileAlignmentFixupCount, KiProfileAlignmentFixupInterval, KiSetRegisterValue(), KiSetRegisterValue64(), LD_OP, PROFILE_LEVEL, SHORT, TRUE, and USHORT.

00037 : 00038 00039 This function is called to emulate an unaligned data reference to an 00040 address in the user part of the address space. 00041 00042 Arguments: 00043 00044 ExceptionRecord - Supplies a pointer to an exception record. 00045 00046 ExceptionFrame - Supplies a pointer to an exception frame. 00047 00048 TrapFrame - Supplies a pointer to a trap frame. 00049 00050 Return Value: 00051 00052 A value of TRUE is returned if the data reference is successfully 00053 emulated. Otherwise, a value of FALSE is returned. 00054 00055 --*/ 00056 00057 { 00058 00059 ULONG BranchAddress; 00060 PUCHAR DataAddress; 00061 00062 union { 00063 ULONGLONG Longlong; 00064 ULONG Long; 00065 USHORT Short; 00066 } DataReference; 00067 00068 PUCHAR DataValue; 00069 PVOID ExceptionAddress; 00070 MIPS_INSTRUCTION FaultInstruction; 00071 ULONG Rt; 00072 KIRQL OldIrql; 00073 00074 // 00075 // If alignment profiling is active, then call the proper profile 00076 // routine. 00077 // 00078 00079 if (KiProfileAlignmentFixup) { 00080 KiProfileAlignmentFixupCount += 1; 00081 if (KiProfileAlignmentFixupCount >= KiProfileAlignmentFixupInterval) { 00082 KeRaiseIrql(PROFILE_LEVEL, &OldIrql); 00083 KiProfileAlignmentFixupCount = 0; 00084 KeProfileInterruptWithSource(TrapFrame, ProfileAlignmentFixup); 00085 KeLowerIrql(OldIrql); 00086 } 00087 } 00088 00089 // 00090 // Save the original exception address in case another exception 00091 // occurs. 00092 // 00093 00094 ExceptionAddress = ExceptionRecord->ExceptionAddress; 00095 00096 // 00097 // Any exception that occurs during the attempted emulation of the 00098 // unaligned reference causes the emulation to be aborted. The new 00099 // exception code and information is copied to the original exception 00100 // record and a value of FALSE is returned. 00101 // 00102 00103 try { 00104 00105 // 00106 // If the exception PC is equal to the fault instruction address 00107 // plus four, then the misalignment exception occurred in the delay 00108 // slot of a branch instruction and the continuation address must 00109 // be computed by emulating the branch instruction. Note that it 00110 // is possible for an exception to occur when the branch instruction 00111 // is read from user memory. 00112 // 00113 00114 if ((TrapFrame->Fir + 4) == (ULONG)ExceptionRecord->ExceptionAddress) { 00115 BranchAddress = KiEmulateBranch(ExceptionFrame, TrapFrame); 00116 00117 } else { 00118 BranchAddress = TrapFrame->Fir + 4; 00119 } 00120 00121 // 00122 // Compute the effective address of the reference and check to make 00123 // sure it is within the user part of the address space. Alignment 00124 // exceptions take precedence over memory management exceptions and 00125 // the address could be a system address. 00126 // 00127 00128 FaultInstruction.Long = *((PULONG)ExceptionRecord->ExceptionAddress); 00129 DataAddress = (PUCHAR)KiGetRegisterValue64(FaultInstruction.i_format.Rs, 00130 ExceptionFrame, 00131 TrapFrame); 00132 00133 DataAddress = (PUCHAR)((LONG)DataAddress + 00134 (LONG)FaultInstruction.i_format.Simmediate); 00135 00136 // 00137 // The emulated data reference must be in user space and must be less 00138 // than 16 types from the end of user space. 00139 // 00140 00141 if ((ULONG)DataAddress < 0x7ffffff0) { 00142 00143 // 00144 // Dispatch on the opcode value. 00145 // 00146 00147 DataValue = (PUCHAR)&DataReference; 00148 Rt = FaultInstruction.i_format.Rt; 00149 switch (FaultInstruction.i_format.Opcode) { 00150 00151 // 00152 // Load halfword integer. 00153 // 00154 00155 case LH_OP: 00156 DataValue[0] = DataAddress[0]; 00157 DataValue[1] = DataAddress[1]; 00158 KiSetRegisterValue64(Rt, 00159 (SHORT)DataReference.Short, 00160 ExceptionFrame, 00161 TrapFrame); 00162 00163 break; 00164 00165 // 00166 // Load halfword unsigned integer. 00167 // 00168 00169 case LHU_OP: 00170 DataValue[0] = DataAddress[0]; 00171 DataValue[1] = DataAddress[1]; 00172 KiSetRegisterValue64(Rt, 00173 DataReference.Short, 00174 ExceptionFrame, 00175 TrapFrame); 00176 00177 break; 00178 00179 // 00180 // Load word floating. 00181 // 00182 00183 case LWC1_OP: 00184 DataValue[0] = DataAddress[0]; 00185 DataValue[1] = DataAddress[1]; 00186 DataValue[2] = DataAddress[2]; 00187 DataValue[3] = DataAddress[3]; 00188 KiSetRegisterValue(Rt + 32, 00189 DataReference.Long, 00190 ExceptionFrame, 00191 TrapFrame); 00192 00193 break; 00194 00195 // 00196 // Load word integer. 00197 // 00198 00199 case LW_OP: 00200 DataValue[0] = DataAddress[0]; 00201 DataValue[1] = DataAddress[1]; 00202 DataValue[2] = DataAddress[2]; 00203 DataValue[3] = DataAddress[3]; 00204 KiSetRegisterValue64(Rt, 00205 (LONG)DataReference.Long, 00206 ExceptionFrame, 00207 TrapFrame); 00208 00209 break; 00210 00211 // 00212 // Load double integer. 00213 // 00214 00215 case LD_OP: 00216 DataValue[0] = DataAddress[0]; 00217 DataValue[1] = DataAddress[1]; 00218 DataValue[2] = DataAddress[2]; 00219 DataValue[3] = DataAddress[3]; 00220 DataValue[4] = DataAddress[4]; 00221 DataValue[5] = DataAddress[5]; 00222 DataValue[6] = DataAddress[6]; 00223 DataValue[7] = DataAddress[7]; 00224 KiSetRegisterValue64(Rt, 00225 DataReference.Longlong, 00226 ExceptionFrame, 00227 TrapFrame); 00228 00229 break; 00230 00231 // 00232 // Load double floating. 00233 // 00234 00235 case LDC1_OP: 00236 Rt = (Rt & 0x1e) + 32; 00237 DataValue[0] = DataAddress[0]; 00238 DataValue[1] = DataAddress[1]; 00239 DataValue[2] = DataAddress[2]; 00240 DataValue[3] = DataAddress[3]; 00241 KiSetRegisterValue(Rt, 00242 DataReference.Long, 00243 ExceptionFrame, 00244 TrapFrame); 00245 00246 DataValue[0] = DataAddress[4]; 00247 DataValue[1] = DataAddress[5]; 00248 DataValue[2] = DataAddress[6]; 00249 DataValue[3] = DataAddress[7]; 00250 KiSetRegisterValue(Rt + 1, 00251 DataReference.Long, 00252 ExceptionFrame, 00253 TrapFrame); 00254 00255 break; 00256 00257 // 00258 // Store halfword integer. 00259 // 00260 00261 case SH_OP: 00262 DataReference.Longlong = KiGetRegisterValue64(Rt, 00263 ExceptionFrame, 00264 TrapFrame); 00265 00266 DataAddress[0] = DataValue[0]; 00267 DataAddress[1] = DataValue[1]; 00268 break; 00269 00270 // 00271 // Store word floating. 00272 // 00273 00274 case SWC1_OP: 00275 DataReference.Long = KiGetRegisterValue(Rt + 32, 00276 ExceptionFrame, 00277 TrapFrame); 00278 00279 DataAddress[0] = DataValue[0]; 00280 DataAddress[1] = DataValue[1]; 00281 DataAddress[2] = DataValue[2]; 00282 DataAddress[3] = DataValue[3]; 00283 break; 00284 00285 // 00286 // Store word integer. 00287 // 00288 00289 case SW_OP: 00290 DataReference.Longlong = KiGetRegisterValue64(Rt, 00291 ExceptionFrame, 00292 TrapFrame); 00293 00294 DataAddress[0] = DataValue[0]; 00295 DataAddress[1] = DataValue[1]; 00296 DataAddress[2] = DataValue[2]; 00297 DataAddress[3] = DataValue[3]; 00298 break; 00299 00300 // 00301 // Store double integer. 00302 // 00303 00304 case SD_OP: 00305 DataReference.Longlong = KiGetRegisterValue64(Rt, 00306 ExceptionFrame, 00307 TrapFrame); 00308 00309 DataAddress[0] = DataValue[0]; 00310 DataAddress[1] = DataValue[1]; 00311 DataAddress[2] = DataValue[2]; 00312 DataAddress[3] = DataValue[3]; 00313 DataAddress[4] = DataValue[4]; 00314 DataAddress[5] = DataValue[5]; 00315 DataAddress[6] = DataValue[6]; 00316 DataAddress[7] = DataValue[7]; 00317 break; 00318 00319 // 00320 // Store double floating. 00321 // 00322 00323 case SDC1_OP: 00324 Rt = (Rt & 0x1e) + 32; 00325 DataReference.Long = KiGetRegisterValue(Rt, 00326 ExceptionFrame, 00327 TrapFrame); 00328 00329 DataAddress[0] = DataValue[0]; 00330 DataAddress[1] = DataValue[1]; 00331 DataAddress[2] = DataValue[2]; 00332 DataAddress[3] = DataValue[3]; 00333 DataReference.Long = KiGetRegisterValue(Rt + 1, 00334 ExceptionFrame, 00335 TrapFrame); 00336 00337 DataAddress[4] = DataValue[0]; 00338 DataAddress[5] = DataValue[1]; 00339 DataAddress[6] = DataValue[2]; 00340 DataAddress[7] = DataValue[3]; 00341 break; 00342 00343 // 00344 // All other instructions are not emulated. 00345 // 00346 00347 default: 00348 return FALSE; 00349 } 00350 00351 TrapFrame->Fir = BranchAddress; 00352 return TRUE; 00353 } 00354 00355 // 00356 // If an exception occurs, then copy the new exception information to the 00357 // original exception record and handle the exception. 00358 // 00359 00360 } except (KiCopyInformation(ExceptionRecord, 00361 (GetExceptionInformation())->ExceptionRecord)) { 00362 00363 // 00364 // Preserve the original exception address. 00365 // 00366 00367 ExceptionRecord->ExceptionAddress = ExceptionAddress; 00368 } 00369 00370 // 00371 // Return a value of FALSE. 00372 // 00373 00374 return FALSE; 00375 } }


Generated on Sat May 15 19:42:50 2004 for test by doxygen 1.3.7