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

floatem.c

Go to the documentation of this file.
00001 /*++ 00002 00003 Copyright (c) 1991 Microsoft Corporation 00004 00005 Module Name: 00006 00007 floatem.c 00008 00009 Abstract: 00010 00011 This module implements a software emulation of the IEEE single and 00012 double floating operations. It is required on MIPS processors since 00013 the hardware does not fully support all of the operations required 00014 by the IEEE standard. In particular, infinitives and Nans are not 00015 handled by the hardware, but rather cause an exception. On receipt 00016 of the exception, a software emulation of the floating operation 00017 is performed to determine the real result of the operation and if 00018 an exception will actually be raised. 00019 00020 Since floating exceptions are rather rare events, this routine is 00021 written in C. Should a higher performance implementation be required, 00022 then the algorithms contained herein, can be used to guide a higher 00023 performance assembly language implementation. 00024 00025 N.B. This routine does not emulate floating loads, floating stores, 00026 control to/from floating, or move to/from floating instructions. 00027 These instructions either do not fault or are emulated elsewhere. 00028 00029 Floating point operations are carried out by unpacking the operands, 00030 normalizing denormalized numbers, checking for NaNs, interpreting 00031 infinities, and computing results. 00032 00033 Floating operands are converted to a format that has a value with the 00034 appropriate number of leading zeros, an overflow bit, the mantissa, a 00035 guard bit, a round bit, and a set of sticky bits. 00036 00037 The overflow bit is needed for addition and is also used for multiply. 00038 The mantissa is 24-bits for single operations and 53-bits for double 00039 operations. The guard bit and round bit are used to hold precise values 00040 for normalization and rounding. 00041 00042 If the result of an operation is normalized, then the guard bit becomes 00043 the round bit and the round bit is accumulated with the sticky bits. If 00044 the result of an operation needs to be shifted left one bit for purposes 00045 of nomalization, then the guard bit becomes part of the mantissa and the 00046 round bit is used for rounding. 00047 00048 The round bit plus the sticky bits are used to determine how rounding is 00049 performed. 00050 00051 Author: 00052 00053 David N. Cutler (davec) 16-Jun-1991 00054 00055 Environment: 00056 00057 Kernel mode only. 00058 00059 Revision History: 00060 00061 --*/ 00062 00063 #include "ki.h" 00064 00065 // 00066 // Define signaling NaN mask values. 00067 // 00068 00069 #define DOUBLE_SIGNAL_NAN_MASK (1 << (53 - 32)) 00070 #define SINGLE_SIGNAL_NAN_MASK (1 << 24) 00071 00072 // 00073 // Define quite NaN mask values. 00074 // 00075 00076 #define DOUBLE_QUIET_NAN_MASK (1 << (51 - 32)) 00077 #define SINGLE_QUIET_NAN_MASK (1 << 22) 00078 00079 // 00080 // Define quiet NaN prefix values. 00081 // 00082 00083 #define DOUBLE_QUIET_NAN_PREFIX 0x7ff00000 00084 #define SINGLE_QUIET_NAN_PREFIX 0x7f800000 00085 00086 // 00087 // Define compare function masks. 00088 // 00089 00090 #define COMPARE_UNORDERED_MASK (1 << 0) 00091 #define COMPARE_EQUAL_MASK (1 << 1) 00092 #define COMPARE_LESS_MASK (1 << 2) 00093 #define COMPARE_ORDERED_MASK (1 << 3) 00094 00095 // 00096 // Define context block structure. 00097 // 00098 00099 typedef struct _FP_CONTEXT_BLOCK { 00100 ULONG Fd; 00101 ULONG BranchAddress; 00102 PEXCEPTION_RECORD ExceptionRecord; 00103 PKEXCEPTION_FRAME ExceptionFrame; 00104 PKTRAP_FRAME TrapFrame; 00105 ULONG Round; 00106 } FP_CONTEXT_BLOCK, *PFP_CONTEXT_BLOCK; 00107 00108 // 00109 // Define single and double operand value structures. 00110 // 00111 00112 typedef struct _FP_DOUBLE_OPERAND { 00113 union { 00114 struct { 00115 ULONG MantissaLow; 00116 LONG MantissaHigh; 00117 }; 00118 00119 LONGLONG Mantissa; 00120 }; 00121 00122 LONG Exponent; 00123 LONG Sign; 00124 BOOLEAN Infinity; 00125 BOOLEAN Nan; 00126 } FP_DOUBLE_OPERAND, *PFP_DOUBLE_OPERAND; 00127 00128 typedef struct _FP_SINGLE_OPERAND { 00129 LONG Mantissa; 00130 LONG Exponent; 00131 LONG Sign; 00132 BOOLEAN Infinity; 00133 BOOLEAN Nan; 00134 } FP_SINGLE_OPERAND, *PFP_SINGLE_OPERAND; 00135 00136 // 00137 // Define forward referenced function protypes. 00138 // 00139 00140 BOOLEAN 00141 KiDivideByZeroDouble ( 00142 IN PFP_CONTEXT_BLOCK ContextBlock, 00143 IN PFP_DOUBLE_OPERAND DoubleOperand1, 00144 IN PFP_DOUBLE_OPERAND DoubleOperand2 00145 ); 00146 00147 BOOLEAN 00148 KiDivideByZeroSingle ( 00149 IN PFP_CONTEXT_BLOCK ContextBlock, 00150 IN PFP_SINGLE_OPERAND SingleOperand1, 00151 IN PFP_SINGLE_OPERAND SingleOperand2 00152 ); 00153 00154 BOOLEAN 00155 KiInvalidCompareDouble ( 00156 IN PFP_CONTEXT_BLOCK ContextBlock, 00157 IN BOOLEAN CheckForNan, 00158 IN PFP_DOUBLE_OPERAND DoubleOperand1, 00159 IN PFP_DOUBLE_OPERAND DoubleOperand2 00160 ); 00161 00162 BOOLEAN 00163 KiInvalidCompareSingle ( 00164 IN PFP_CONTEXT_BLOCK ContextBlock, 00165 IN BOOLEAN CheckForNan, 00166 IN PFP_SINGLE_OPERAND SingleOperand1, 00167 IN PFP_SINGLE_OPERAND SingleOperand2 00168 ); 00169 00170 BOOLEAN 00171 KiInvalidOperationDouble ( 00172 IN PFP_CONTEXT_BLOCK ContextBlock, 00173 IN BOOLEAN CheckForNan, 00174 IN PFP_DOUBLE_OPERAND DoubleOperand1, 00175 IN PFP_DOUBLE_OPERAND DoubleOperand2 00176 ); 00177 00178 BOOLEAN 00179 KiInvalidOperationLongword ( 00180 IN PFP_CONTEXT_BLOCK ContextBlock, 00181 IN BOOLEAN Infinity, 00182 IN LONG Sign 00183 ); 00184 00185 BOOLEAN 00186 KiInvalidOperationQuadword ( 00187 IN PFP_CONTEXT_BLOCK ContextBlock, 00188 IN BOOLEAN Infinity, 00189 IN LONG Sign 00190 ); 00191 00192 BOOLEAN 00193 KiInvalidOperationSingle ( 00194 IN PFP_CONTEXT_BLOCK ContextBlock, 00195 IN BOOLEAN CheckForNan, 00196 IN PFP_SINGLE_OPERAND SingleOperand1, 00197 IN PFP_SINGLE_OPERAND SingleOperand2 00198 ); 00199 00200 BOOLEAN 00201 KiNormalizeDouble ( 00202 IN PFP_CONTEXT_BLOCK ContextBlock, 00203 IN PFP_DOUBLE_OPERAND ResultOperand, 00204 IN ULONG StickyBits 00205 ); 00206 00207 BOOLEAN 00208 KiNormalizeLongword ( 00209 IN PFP_CONTEXT_BLOCK ContextBlock, 00210 IN PFP_DOUBLE_OPERAND ResultOperand 00211 ); 00212 00213 BOOLEAN 00214 KiNormalizeQuadword ( 00215 IN PFP_CONTEXT_BLOCK ContextBlock, 00216 IN PFP_DOUBLE_OPERAND ResultOperand 00217 ); 00218 00219 BOOLEAN 00220 KiNormalizeSingle ( 00221 IN PFP_CONTEXT_BLOCK ContextBlock, 00222 IN PFP_SINGLE_OPERAND ResultOperand, 00223 IN ULONG StickyBits 00224 ); 00225 00226 ULONG 00227 KiSquareRootDouble ( 00228 IN PULARGE_INTEGER DoubleValue 00229 ); 00230 00231 ULONG 00232 KiSquareRootSingle ( 00233 IN PULONG SingleValue 00234 ); 00235 00236 VOID 00237 KiUnpackDouble ( 00238 IN ULONG Source, 00239 IN PFP_CONTEXT_BLOCK ContextBlock, 00240 OUT PFP_DOUBLE_OPERAND DoubleOperand 00241 ); 00242 00243 VOID 00244 KiUnpackSingle ( 00245 IN ULONG Source, 00246 IN PFP_CONTEXT_BLOCK ContextBlock, 00247 OUT PFP_SINGLE_OPERAND SingleOperand 00248 ); 00249 00250 BOOLEAN 00251 KiEmulateFloating ( 00252 IN OUT PEXCEPTION_RECORD ExceptionRecord, 00253 IN OUT PKEXCEPTION_FRAME ExceptionFrame, 00254 IN OUT PKTRAP_FRAME TrapFrame 00255 ) 00256 00257 /*++ 00258 00259 Routine Description: 00260 00261 This function is called to emulate a floating operation and convert the 00262 exception status to the proper value. If the exception is an unimplemented 00263 operation, then the operation is emulated. Otherwise, the status code is 00264 just converted to its proper value. 00265 00266 Arguments: 00267 00268 ExceptionRecord - Supplies a pointer to an exception record. 00269 00270 ExceptionFrame - Supplies a pointer to an exception frame. 00271 00272 TrapFrame - Supplies a pointer to a trap frame. 00273 00274 Return Value: 00275 00276 A value of TRUE is returned if the floating exception is successfully 00277 emulated. Otherwise, a value of FALSE is returned. 00278 00279 --*/ 00280 00281 { 00282 00283 ULARGE_INTEGER AhighBhigh; 00284 ULARGE_INTEGER AhighBlow; 00285 ULARGE_INTEGER AlowBhigh; 00286 ULARGE_INTEGER AlowBlow; 00287 ULONG Carry1; 00288 ULONG Carry2; 00289 BOOLEAN CompareEqual; 00290 ULONG CompareFunction; 00291 BOOLEAN CompareLess; 00292 FP_CONTEXT_BLOCK ContextBlock; 00293 LARGE_INTEGER DoubleDividend; 00294 LARGE_INTEGER DoubleDivisor; 00295 ULARGE_INTEGER DoubleValue; 00296 ULONG DoubleMantissaLow; 00297 LONG DoubleMantissaHigh; 00298 FP_DOUBLE_OPERAND DoubleOperand1; 00299 FP_DOUBLE_OPERAND DoubleOperand2; 00300 FP_DOUBLE_OPERAND DoubleOperand3; 00301 LARGE_INTEGER DoubleQuotient; 00302 PVOID ExceptionAddress; 00303 ULONG ExponentDifference; 00304 ULONG ExponentSum; 00305 ULONG Format; 00306 ULONG Fs; 00307 ULONG Ft; 00308 ULONG Function; 00309 ULONG Index; 00310 MIPS_INSTRUCTION Instruction; 00311 ULARGE_INTEGER LargeResult; 00312 LONG Longword; 00313 LONG Negation; 00314 union { 00315 LONGLONG Quadword; 00316 LARGE_INTEGER LargeValue; 00317 }u; 00318 00319 LONG SingleMantissa; 00320 FP_SINGLE_OPERAND SingleOperand1; 00321 FP_SINGLE_OPERAND SingleOperand2; 00322 FP_SINGLE_OPERAND SingleOperand3; 00323 ULONG SingleValue; 00324 ULONG StickyBits; 00325 00326 // 00327 // Save the original exception address in case another exception 00328 // occurs. 00329 // 00330 00331 ExceptionAddress = ExceptionRecord->ExceptionAddress; 00332 00333 // 00334 // Any exception that occurs during the attempted emulation of the 00335 // floating operation causes the emulation to be aborted. The new 00336 // exception code and information is copied to the original exception 00337 // record and a value of FALSE is returned. 00338 // 00339 00340 try { 00341 00342 // 00343 // If the exception PC is equal to the fault instruction address 00344 // plus four, then the floating exception occurred in the delay 00345 // slot of a branch instruction and the continuation address must 00346 // be computed by emulating the branch instruction. Note that it 00347 // is possible for an exception to occur when the branch instruction 00348 // is read from user memory. 00349 // 00350 00351 if ((TrapFrame->Fir + 4) == (ULONG)ExceptionRecord->ExceptionAddress) { 00352 ContextBlock.BranchAddress = KiEmulateBranch(ExceptionFrame, 00353 TrapFrame); 00354 00355 } else { 00356 ContextBlock.BranchAddress = TrapFrame->Fir + 4; 00357 } 00358 00359 // 00360 // Increment the floating emulation count. 00361 // 00362 00363 KeGetCurrentPrcb()->KeFloatingEmulationCount += 1; 00364 00365 // 00366 // Initialize the address of the exception record, exception frame, 00367 // and trap frame in the context block used during the emulation of 00368 // the floating point operation. 00369 // 00370 00371 ContextBlock.ExceptionRecord = ExceptionRecord; 00372 ContextBlock.ExceptionFrame = ExceptionFrame; 00373 ContextBlock.TrapFrame = TrapFrame; 00374 ContextBlock.Round = ((PFSR)&TrapFrame->Fsr)->RM; 00375 00376 // 00377 // Initialize the number of exception information parameters, set 00378 // the branch address, and clear the IEEE exception value. 00379 // 00380 00381 ExceptionRecord->NumberParameters = 6; 00382 ExceptionRecord->ExceptionInformation[0] = 0; 00383 ExceptionRecord->ExceptionInformation[1] = ContextBlock.BranchAddress; 00384 ExceptionRecord->ExceptionInformation[2] = 0; 00385 ExceptionRecord->ExceptionInformation[3] = 0; 00386 ExceptionRecord->ExceptionInformation[4] = 0; 00387 ExceptionRecord->ExceptionInformation[5] = 0; 00388 00389 // 00390 // Clear all exception flags and emulate the floating point operation 00391 // The return value is dependent on the results of the emulation. 00392 // 00393 00394 TrapFrame->Fsr &= ~(0x3f << 12); 00395 Instruction = *((PMIPS_INSTRUCTION)ExceptionRecord->ExceptionAddress); 00396 Function = Instruction.c_format.Function; 00397 ContextBlock.Fd = Instruction.c_format.Fd; 00398 Fs = Instruction.c_format.Fs; 00399 Ft = Instruction.c_format.Ft; 00400 Format = Instruction.c_format.Format; 00401 Negation = 0; 00402 00403 // 00404 // Check for illegal register specification or format code. 00405 // 00406 00407 if (((ContextBlock.Fd & 0x1) != 0) || ((Fs & 0x1) != 0) || ((Ft & 0x1) != 0) || 00408 ((Format != FORMAT_LONGWORD) && (Format != FORMAT_QUADWORD) && (Format > FORMAT_DOUBLE))) { 00409 Function = FLOAT_ILLEGAL; 00410 } 00411 00412 // 00413 // Decode operand values and dispose with NaNs. 00414 // 00415 00416 if ((Function <= FLOAT_DIVIDE) || (Function >= FLOAT_COMPARE)) { 00417 00418 // 00419 // The function has two operand values. 00420 // 00421 00422 if (Format == FORMAT_SINGLE) { 00423 KiUnpackSingle(Fs, &ContextBlock, &SingleOperand1); 00424 KiUnpackSingle(Ft, &ContextBlock, &SingleOperand2); 00425 00426 // 00427 // If either operand is a NaN, then check to determine if a 00428 // compare instruction or other dyadic operation is being 00429 // performed. 00430 // 00431 00432 if ((SingleOperand1.Nan != FALSE) || (SingleOperand2.Nan != FALSE)) { 00433 if (Function < FLOAT_COMPARE) { 00434 00435 // 00436 // Dyadic operation. 00437 // 00438 // Store a quite Nan if the invalid operation trap 00439 // is disabled, or raise an exception if the invalid 00440 // operation trap is enabled and either of the NaNs 00441 // is a signally NaN. 00442 // 00443 00444 return KiInvalidOperationSingle(&ContextBlock, 00445 TRUE, 00446 &SingleOperand1, 00447 &SingleOperand2); 00448 00449 } else { 00450 00451 // 00452 // Compare operation. 00453 // 00454 // Set the condition based on the predicate of 00455 // the floating comparison. 00456 // 00457 // If the compare is a signaling compare, then 00458 // raise an exception if the invalid operation 00459 // trap is enabled. Otherwise, raise an exception 00460 // if one of the operands is a signaling NaN. 00461 // 00462 00463 if ((Function & COMPARE_UNORDERED_MASK) != 0) { 00464 ((PFSR)&TrapFrame->Fsr)->CC = 1; 00465 00466 } else { 00467 ((PFSR)&TrapFrame->Fsr)->CC = 0; 00468 } 00469 00470 if ((Function & COMPARE_ORDERED_MASK) != 0) { 00471 return KiInvalidCompareSingle(&ContextBlock, 00472 FALSE, 00473 &SingleOperand1, 00474 &SingleOperand2); 00475 00476 } else { 00477 return KiInvalidCompareSingle(&ContextBlock, 00478 TRUE, 00479 &SingleOperand1, 00480 &SingleOperand2); 00481 00482 } 00483 } 00484 00485 } else if (Function >= FLOAT_COMPARE) { 00486 CompareFunction = Function; 00487 Function = FLOAT_COMPARE_SINGLE; 00488 } 00489 00490 } else if (Format == FORMAT_DOUBLE) { 00491 KiUnpackDouble(Fs, &ContextBlock, &DoubleOperand1); 00492 KiUnpackDouble(Ft, &ContextBlock, &DoubleOperand2); 00493 00494 // 00495 // If either operand is a NaN, then check to determine if a 00496 // compare instruction or other dyadic operation is being 00497 // performed. 00498 // 00499 00500 if ((DoubleOperand1.Nan != FALSE) || (DoubleOperand2.Nan != FALSE)) { 00501 if (Function < FLOAT_COMPARE) { 00502 00503 // 00504 // Dyadic operation. 00505 // 00506 // Store a quite Nan if the invalid operation trap 00507 // is disabled, or raise an exception if the invalid 00508 // operation trap is enabled and either of the NaNs 00509 // is a signally NaN. 00510 // 00511 00512 return KiInvalidOperationDouble(&ContextBlock, 00513 TRUE, 00514 &DoubleOperand1, 00515 &DoubleOperand2); 00516 00517 } else { 00518 00519 // 00520 // Compare operation. 00521 // 00522 // Set the condition based on the predicate of 00523 // the floating comparison. 00524 // 00525 // If the compare is a signaling compare, then 00526 // raise an exception if the invalid operation 00527 // trap is enabled. Othersie, raise an exception 00528 // if one of the operands is a signaling NaN. 00529 // 00530 00531 if ((Function & COMPARE_UNORDERED_MASK) != 0) { 00532 ((PFSR)&TrapFrame->Fsr)->CC = 1; 00533 00534 } else { 00535 ((PFSR)&TrapFrame->Fsr)->CC = 0; 00536 } 00537 00538 if ((Function & COMPARE_ORDERED_MASK) != 0) { 00539 return KiInvalidCompareDouble(&ContextBlock, 00540 FALSE, 00541 &DoubleOperand1, 00542 &DoubleOperand2); 00543 00544 } else { 00545 return KiInvalidCompareDouble(&ContextBlock, 00546 TRUE, 00547 &DoubleOperand1, 00548 &DoubleOperand2); 00549 00550 } 00551 } 00552 00553 } else if (Function >= FLOAT_COMPARE) { 00554 CompareFunction = Function; 00555 Function = FLOAT_COMPARE_DOUBLE; 00556 } 00557 00558 } else { 00559 Function = FLOAT_ILLEGAL; 00560 } 00561 00562 } else { 00563 00564 // 00565 // The function has one operand value. 00566 // 00567 00568 if (Format == FORMAT_SINGLE) { 00569 KiUnpackSingle(Fs, &ContextBlock, &SingleOperand1); 00570 00571 // 00572 // If the operand is a NaN and the function is not a convert 00573 // operation, then store a quiet NaN if the invalid operation 00574 // trap is disabled, or raise an exception if the invalid 00575 // operation trap is enabled and the operand is a signaling 00576 // NaN. 00577 // 00578 00579 if ((SingleOperand1.Nan != FALSE) && 00580 (Function < FLOAT_ROUND_QUADWORD) || 00581 (Function > FLOAT_CONVERT_QUADWORD) || 00582 ((Function > FLOAT_FLOOR_LONGWORD) && 00583 (Function < FLOAT_CONVERT_SINGLE))) { 00584 return KiInvalidOperationSingle(&ContextBlock, 00585 TRUE, 00586 &SingleOperand1, 00587 &SingleOperand1); 00588 00589 } 00590 00591 } else if (Format == FORMAT_DOUBLE) { 00592 KiUnpackDouble(Fs, &ContextBlock, &DoubleOperand1); 00593 00594 // 00595 // If the operand is a NaN and the function is not a convert 00596 // operation, then store a quiet NaN if the invalid operation 00597 // trap is disabled, or raise an exception if the invalid 00598 // operation trap is enabled and the operand is a signaling 00599 // NaN. 00600 // 00601 00602 if ((DoubleOperand1.Nan != FALSE) && 00603 (Function < FLOAT_ROUND_QUADWORD) || 00604 (Function > FLOAT_CONVERT_QUADWORD) || 00605 ((Function > FLOAT_FLOOR_LONGWORD) && 00606 (Function < FLOAT_CONVERT_SINGLE))) { 00607 return KiInvalidOperationDouble(&ContextBlock, 00608 TRUE, 00609 &DoubleOperand1, 00610 &DoubleOperand1); 00611 } 00612 00613 } else if ((Format == FORMAT_LONGWORD) && 00614 (Function >= FLOAT_CONVERT_SINGLE)) { 00615 Longword = KiGetRegisterValue(Fs + 32, 00616 ContextBlock.ExceptionFrame, 00617 ContextBlock.TrapFrame); 00618 00619 } else if ((Format == FORMAT_QUADWORD) && 00620 (Function >= FLOAT_CONVERT_SINGLE)) { 00621 u.LargeValue.LowPart = KiGetRegisterValue(Fs + 32, 00622 ContextBlock.ExceptionFrame, 00623 ContextBlock.TrapFrame); 00624 00625 u.LargeValue.HighPart = KiGetRegisterValue(Fs + 33, 00626 ContextBlock.ExceptionFrame, 00627 ContextBlock.TrapFrame); 00628 00629 } else { 00630 Function = FLOAT_ILLEGAL; 00631 } 00632 } 00633 00634 // 00635 // Case to the proper function routine to emulate the operation. 00636 // 00637 00638 switch (Function) { 00639 00640 // 00641 // Floating subtract operation. 00642 // 00643 // Floating subtract is accomplished by complementing the sign 00644 // of the second operand and then performing an add operation. 00645 // 00646 00647 case FLOAT_SUBTRACT: 00648 Negation = 0x1; 00649 00650 // 00651 // Floating add operation. 00652 // 00653 // Floating add is accomplished using signed magnitude addition. 00654 // 00655 // The exponent difference is calculated and the smaller number 00656 // is right shifted by the specified amount, but no more than 00657 // the width of the operand values (i.e., 26 for single and 55 00658 // for double). The shifted out value is saved for rounding. 00659 // 00660 // If the signs of the two operands are the same, then they 00661 // are added together after having performed the alignment 00662 // shift. 00663 // 00664 // If the signs of the two operands are different, then the 00665 // sign of the result is the sign of the larger operand and 00666 // the smaller operand is subtracted from the larger operand. 00667 // In order to avoid making a double level test (i.e., one on 00668 // the exponents, and one on the mantissas if the exponents 00669 // are equal), it is posible that the result of the subtract 00670 // could be negative (if the exponents are equal). If this 00671 // occurs, then the result sign and mantissa are complemented 00672 // to obtain the correct result. 00673 // 00674 00675 case FLOAT_ADD: 00676 if (Format == FORMAT_SINGLE) { 00677 00678 // 00679 // Complement the sign of the second operand if the operation 00680 // is subtraction. 00681 // 00682 00683 SingleOperand2.Sign ^= Negation; 00684 00685 // 00686 // Reorder then operands according to their exponent value. 00687 // 00688 00689 if (SingleOperand2.Exponent > SingleOperand1.Exponent) { 00690 SingleOperand3 = SingleOperand2; 00691 SingleOperand2 = SingleOperand1; 00692 SingleOperand1 = SingleOperand3; 00693 } 00694 00695 // 00696 // Compute the exponent difference and shift the smaller 00697 // mantissa right by the difference value or 26 which ever 00698 // is smaller. The bits shifted out are termed the sticky 00699 // bits and are used later in the rounding operation. 00700 // 00701 00702 ExponentDifference = 00703 SingleOperand1.Exponent - SingleOperand2.Exponent; 00704 00705 if (ExponentDifference > 26) { 00706 ExponentDifference = 26; 00707 } 00708 00709 StickyBits = 00710 SingleOperand2.Mantissa & ((1 << ExponentDifference) - 1); 00711 SingleMantissa = SingleOperand2.Mantissa >> ExponentDifference; 00712 00713 // 00714 // If the operands both have the same sign, then perform the 00715 // operation by adding the values together. Otherwise, perform 00716 // the operation by subtracting the second operand from the 00717 // first operand. 00718 // 00719 00720 if ((SingleOperand1.Sign ^ SingleOperand2.Sign) == 0) { 00721 SingleOperand1.Mantissa += SingleMantissa; 00722 00723 } else { 00724 if ((SingleOperand1.Infinity != FALSE) && 00725 (SingleOperand2.Infinity != FALSE)) { 00726 return KiInvalidOperationSingle(&ContextBlock, 00727 FALSE, 00728 &SingleOperand1, 00729 &SingleOperand2); 00730 00731 } else if (SingleOperand1.Infinity == FALSE) { 00732 if (StickyBits != 0) { 00733 SingleOperand1.Mantissa -= 1; 00734 } 00735 00736 SingleOperand1.Mantissa -= SingleMantissa; 00737 if (SingleOperand1.Mantissa < 0) { 00738 SingleOperand1.Mantissa = -SingleOperand1.Mantissa; 00739 SingleOperand1.Sign ^= 0x1; 00740 } 00741 } 00742 } 00743 00744 // 00745 // Normalize and store the result value. 00746 // 00747 00748 return KiNormalizeSingle(&ContextBlock, 00749 &SingleOperand1, 00750 StickyBits); 00751 00752 } else if (Format == FORMAT_DOUBLE) { 00753 00754 // 00755 // Complement the sign of the second operand if the operation 00756 // is subtraction. 00757 // 00758 00759 DoubleOperand2.Sign ^= Negation; 00760 00761 // 00762 // Reorder then operands according to their exponent value. 00763 // 00764 00765 if (DoubleOperand2.Exponent > DoubleOperand1.Exponent) { 00766 DoubleOperand3 = DoubleOperand2; 00767 DoubleOperand2 = DoubleOperand1; 00768 DoubleOperand1 = DoubleOperand3; 00769 } 00770 00771 // 00772 // Compute the exponent difference and shift the smaller 00773 // mantissa right by the difference value or 55 which ever 00774 // is smaller. The bits shifted out are termed the sticky 00775 // bits and are used later in the rounding operation. 00776 // 00777 00778 ExponentDifference = 00779 DoubleOperand1.Exponent - DoubleOperand2.Exponent; 00780 00781 if (ExponentDifference > 55) { 00782 ExponentDifference = 55; 00783 } 00784 00785 if (ExponentDifference >= 32) { 00786 ExponentDifference -= 32; 00787 StickyBits = (DoubleOperand2.MantissaLow) | 00788 (DoubleOperand2.MantissaHigh & ((1 << ExponentDifference) - 1)); 00789 00790 DoubleMantissaLow = 00791 DoubleOperand2.MantissaHigh >> ExponentDifference; 00792 00793 DoubleMantissaHigh = 0; 00794 00795 } else if (ExponentDifference > 0) { 00796 StickyBits = 00797 DoubleOperand2.MantissaLow & ((1 << ExponentDifference) - 1); 00798 00799 DoubleMantissaLow = 00800 (DoubleOperand2.MantissaLow >> ExponentDifference) | 00801 (DoubleOperand2.MantissaHigh << (32 - ExponentDifference)); 00802 00803 DoubleMantissaHigh = 00804 DoubleOperand2.MantissaHigh >> ExponentDifference; 00805 00806 } else { 00807 StickyBits = 0; 00808 DoubleMantissaLow = DoubleOperand2.MantissaLow; 00809 DoubleMantissaHigh = DoubleOperand2.MantissaHigh; 00810 } 00811 00812 // 00813 // If the operands both have the same sign, then perform the 00814 // operation by adding the values together. Otherwise, perform 00815 // the operation by subtracting the second operand from the 00816 // first operand. 00817 // 00818 00819 if ((DoubleOperand1.Sign ^ DoubleOperand2.Sign) == 0) { 00820 DoubleOperand1.MantissaLow += DoubleMantissaLow; 00821 DoubleOperand1.MantissaHigh += DoubleMantissaHigh; 00822 if (DoubleOperand1.MantissaLow < DoubleMantissaLow) { 00823 DoubleOperand1.MantissaHigh += 1; 00824 } 00825 00826 } else { 00827 if ((DoubleOperand1.Infinity != FALSE) && 00828 (DoubleOperand2.Infinity != FALSE)) { 00829 return KiInvalidOperationDouble(&ContextBlock, 00830 FALSE, 00831 &DoubleOperand1, 00832 &DoubleOperand2); 00833 00834 } else if (DoubleOperand1.Infinity == FALSE) { 00835 if (StickyBits != 0) { 00836 if (DoubleOperand1.MantissaLow < 1) { 00837 DoubleOperand1.MantissaHigh -= 1; 00838 } 00839 00840 DoubleOperand1.MantissaLow -= 1; 00841 } 00842 00843 if (DoubleOperand1.MantissaLow < DoubleMantissaLow) { 00844 DoubleOperand1.MantissaHigh -= 1; 00845 } 00846 00847 DoubleOperand1.MantissaLow -= DoubleMantissaLow; 00848 DoubleOperand1.MantissaHigh -= DoubleMantissaHigh; 00849 if (DoubleOperand1.MantissaHigh < 0) { 00850 DoubleOperand1.MantissaLow = ~DoubleOperand1.MantissaLow + 1; 00851 DoubleOperand1.MantissaHigh = -DoubleOperand1.MantissaHigh; 00852 if (DoubleOperand1.MantissaLow != 0) { 00853 DoubleOperand1.MantissaHigh -= 1; 00854 } 00855 00856 DoubleOperand1.Sign ^= 0x1; 00857 } 00858 } 00859 } 00860 00861 // 00862 // Normalize and store the result value. 00863 // 00864 00865 return KiNormalizeDouble(&ContextBlock, 00866 &DoubleOperand1, 00867 StickyBits); 00868 00869 } else { 00870 break; 00871 } 00872 00873 // 00874 // Floating multiply operation. 00875 // 00876 // Floating multiply is accomplished using unsigned multiplies 00877 // of the mantissa values, and adding the parital results together 00878 // to form the total product. 00879 // 00880 // The two mantissa values are preshifted such that the final 00881 // result is properly aligned. 00882 // 00883 00884 case FLOAT_MULTIPLY: 00885 if (Format == FORMAT_SINGLE) { 00886 00887 // 00888 // Reorder the operands according to their exponent value. 00889 // 00890 00891 if (SingleOperand2.Exponent > SingleOperand1.Exponent) { 00892 SingleOperand3 = SingleOperand2; 00893 SingleOperand2 = SingleOperand1; 00894 SingleOperand1 = SingleOperand3; 00895 } 00896 00897 // 00898 // If the first operand is infinite and the second operand is 00899 // zero, then an invalid operation is specified. 00900 // 00901 00902 if ((SingleOperand1.Infinity != FALSE) && 00903 (SingleOperand2.Infinity == FALSE) && 00904 (SingleOperand2.Mantissa == 0)) { 00905 return KiInvalidOperationSingle(&ContextBlock, 00906 FALSE, 00907 &SingleOperand1, 00908 &SingleOperand2); 00909 00910 } 00911 00912 // 00913 // Preshift the operand mantissas so the result will be a 00914 // properly aligned 64-bit value and then unsigned multiply 00915 // the two mantissa values. The single result is the high part 00916 // of the 64-bit product and the sticky bits are the low part 00917 // of the 64-bit product. 00918 // 00919 00920 LargeResult.QuadPart = UInt32x32To64(SingleOperand1.Mantissa << (32 - 26), 00921 SingleOperand2.Mantissa << 1); 00922 00923 SingleOperand1.Mantissa = LargeResult.HighPart; 00924 StickyBits = LargeResult.LowPart; 00925 00926 // 00927 // Compute the sign and exponent of the result. 00928 // 00929 00930 SingleOperand1.Sign ^= SingleOperand2.Sign; 00931 SingleOperand1.Exponent += 00932 SingleOperand2.Exponent - SINGLE_EXPONENT_BIAS; 00933 00934 // 00935 // Normalize and store the result value. 00936 // 00937 00938 return KiNormalizeSingle(&ContextBlock, 00939 &SingleOperand1, 00940 StickyBits); 00941 00942 } else if (Format == FORMAT_DOUBLE) { 00943 00944 // 00945 // Reorder the operands according to their exponent value. 00946 // 00947 00948 if (DoubleOperand2.Exponent > DoubleOperand1.Exponent) { 00949 DoubleOperand3 = DoubleOperand2; 00950 DoubleOperand2 = DoubleOperand1; 00951 DoubleOperand1 = DoubleOperand3; 00952 } 00953 00954 // 00955 // If the first operand is infinite and the second operand is 00956 // zero, then an invalid operation is specified. 00957 // 00958 00959 if ((DoubleOperand1.Infinity != FALSE) && 00960 (DoubleOperand2.Infinity == FALSE) && 00961 (DoubleOperand2.MantissaHigh == 0)) { 00962 return KiInvalidOperationDouble(&ContextBlock, 00963 FALSE, 00964 &DoubleOperand1, 00965 &DoubleOperand2); 00966 00967 } 00968 00969 // 00970 // Preshift the operand mantissas so the result will be a 00971 // properly aligned 128-bit value and then unsigned multiply 00972 // the two mantissa values. The double result is the high part 00973 // of the 128-bit product and the sticky bits are the low part 00974 // of the 128-bit product. 00975 // 00976 00977 DoubleOperand1.MantissaHigh = 00978 (DoubleOperand1.MantissaHigh << 1) | 00979 (DoubleOperand1.MantissaLow >> 31); 00980 00981 DoubleOperand1.MantissaLow <<= 1; 00982 DoubleOperand2.MantissaHigh = 00983 (DoubleOperand2.MantissaHigh << (64 - 55)) | 00984 (DoubleOperand2.MantissaLow >> (32 - (64 -55))); 00985 00986 DoubleOperand2.MantissaLow <<= (64 - 55); 00987 00988 // 00989 // The 128-bit product is formed by mutiplying and adding 00990 // all the cross product values. 00991 // 00992 // Consider the operands (A and B) as being composed of two 00993 // parts Ahigh, Alow, Bhigh, and Blow. The cross product sum 00994 // is then: 00995 // 00996 // Ahigh * Bhigh * 2^64 + 00997 // Ahigh * Blow * 2^32 + 00998 // Alow * Bhigh * 2^32 + 00999 // Alow * Blow 01000 // 01001 01002 AhighBhigh.QuadPart = UInt32x32To64(DoubleOperand1.MantissaHigh, 01003 DoubleOperand2.MantissaHigh); 01004 01005 AhighBlow.QuadPart = UInt32x32To64(DoubleOperand1.MantissaHigh, 01006 DoubleOperand2.MantissaLow); 01007 01008 AlowBhigh.QuadPart = UInt32x32To64(DoubleOperand1.MantissaLow, 01009 DoubleOperand2.MantissaHigh); 01010 01011 AlowBlow.QuadPart = UInt32x32To64(DoubleOperand1.MantissaLow, 01012 DoubleOperand2.MantissaLow); 01013 01014 AlowBlow.HighPart += AhighBlow.LowPart; 01015 if (AlowBlow.HighPart < AhighBlow.LowPart) { 01016 Carry1 = 1; 01017 01018 } else { 01019 Carry1 = 0; 01020 } 01021 01022 AlowBlow.HighPart += AlowBhigh.LowPart; 01023 if (AlowBlow.HighPart < AlowBhigh.LowPart) { 01024 Carry1 += 1; 01025 } 01026 01027 DoubleOperand1.MantissaLow = AhighBlow.HighPart + Carry1; 01028 if (DoubleOperand1.MantissaLow < Carry1) { 01029 Carry2 = 1; 01030 01031 } else { 01032 Carry2 = 0; 01033 } 01034 01035 DoubleOperand1.MantissaLow += AlowBhigh.HighPart; 01036 if (DoubleOperand1.MantissaLow < AlowBhigh.HighPart) { 01037 Carry2 += 1; 01038 } 01039 01040 DoubleOperand1.MantissaLow += AhighBhigh.LowPart; 01041 if (DoubleOperand1.MantissaLow < AhighBhigh.LowPart) { 01042 Carry2 += 1; 01043 } 01044 01045 DoubleOperand1.MantissaHigh = AhighBhigh.HighPart + Carry2; 01046 StickyBits = AlowBlow.HighPart | AlowBlow.LowPart; 01047 01048 // 01049 // Compute the sign and exponent of the result. 01050 // 01051 01052 DoubleOperand1.Sign ^= DoubleOperand2.Sign; 01053 DoubleOperand1.Exponent += 01054 DoubleOperand2.Exponent - DOUBLE_EXPONENT_BIAS; 01055 01056 // 01057 // Normalize and store the result value. 01058 // 01059 01060 return KiNormalizeDouble(&ContextBlock, 01061 &DoubleOperand1, 01062 StickyBits); 01063 01064 } else { 01065 break; 01066 } 01067 01068 // 01069 // Floating divide operation. 01070 // 01071 // Floating division is accomplished by repeated subtract using 01072 // a single one-bit-at-a-time algorithm. The number of division 01073 // steps performed is equal to the mantissa size plus one guard 01074 // bit. 01075 // 01076 // The sticky bits are the remainder after the specified number 01077 // of division steps. 01078 // 01079 01080 case FLOAT_DIVIDE: 01081 if (Format == FORMAT_SINGLE) { 01082 01083 // 01084 // If the first operand is infinite and the second operand 01085 // is infinite, or both operands are zero, then an invalid 01086 // operation is specified. 01087 // 01088 01089 if (((SingleOperand1.Infinity != FALSE) && 01090 (SingleOperand2.Infinity != FALSE)) || 01091 ((SingleOperand1.Infinity == FALSE) && 01092 (SingleOperand1.Mantissa == 0) && 01093 (SingleOperand2.Infinity == FALSE) && 01094 (SingleOperand2.Mantissa == 0))) { 01095 return KiInvalidOperationSingle(&ContextBlock, 01096 FALSE, 01097 &SingleOperand1, 01098 &SingleOperand2); 01099 01100 } 01101 01102 // 01103 // If the second operand is zero, then a divide by zero 01104 // operation is specified. 01105 // 01106 01107 if ((SingleOperand2.Infinity == FALSE) && 01108 (SingleOperand2.Mantissa == 0)) { 01109 return KiDivideByZeroSingle(&ContextBlock, 01110 &SingleOperand1, 01111 &SingleOperand2); 01112 } 01113 01114 // 01115 // If the first operand is infinite, then the result is 01116 // infinite. Otherwise, if the second operand is infinite, 01117 // then the result is zero (note that both operands cannot 01118 // be infinite). 01119 // 01120 01121 if (SingleOperand1.Infinity != FALSE) { 01122 SingleOperand1.Sign ^= SingleOperand2.Sign; 01123 return KiNormalizeSingle(&ContextBlock, 01124 &SingleOperand1, 01125 0); 01126 01127 } else if (SingleOperand2.Infinity != FALSE) { 01128 SingleOperand1.Sign ^= SingleOperand2.Sign; 01129 SingleOperand1.Exponent = 0; 01130 SingleOperand1.Mantissa = 0; 01131 return KiNormalizeSingle(&ContextBlock, 01132 &SingleOperand1, 01133 0); 01134 01135 } 01136 01137 // 01138 // Perform divide operation by repeating a single bit 01139 // divide step 26 iterations. 01140 // 01141 01142 SingleOperand3.Mantissa = 0; 01143 for (Index = 0; Index < 26; Index += 1) { 01144 SingleOperand3.Mantissa <<=1; 01145 if (SingleOperand1.Mantissa >= SingleOperand2.Mantissa) { 01146 SingleOperand1.Mantissa -= SingleOperand2.Mantissa; 01147 SingleOperand3.Mantissa |= 1; 01148 } 01149 01150 SingleOperand1.Mantissa <<= 1; 01151 } 01152 01153 // 01154 // Compute the sign and exponent of the result. 01155 // 01156 01157 SingleOperand3.Sign = SingleOperand1.Sign ^ SingleOperand2.Sign; 01158 SingleOperand3.Exponent = SingleOperand1.Exponent - 01159 SingleOperand2.Exponent + SINGLE_EXPONENT_BIAS; 01160 01161 // 01162 // Normalize and store the result value. 01163 // 01164 01165 SingleOperand3.Infinity = FALSE; 01166 SingleOperand3.Nan = FALSE; 01167 return KiNormalizeSingle(&ContextBlock, 01168 &SingleOperand3, 01169 SingleOperand1.Mantissa); 01170 01171 } else if (Format == FORMAT_DOUBLE) { 01172 01173 // 01174 // If the first operand is infinite and the second operand 01175 // is infinite, or both operands are zero, then an invalid 01176 // operation is specified. 01177 // 01178 01179 if (((DoubleOperand1.Infinity != FALSE) && 01180 (DoubleOperand2.Infinity != FALSE)) || 01181 ((DoubleOperand1.Infinity == FALSE) && 01182 (DoubleOperand1.MantissaHigh == 0) && 01183 (DoubleOperand2.Infinity == FALSE) && 01184 (DoubleOperand2.MantissaHigh == 0))) { 01185 return KiInvalidOperationDouble(&ContextBlock, 01186 FALSE, 01187 &DoubleOperand1, 01188 &DoubleOperand2); 01189 01190 } 01191 01192 // 01193 // If the second operand is zero, then a divide by zero 01194 // operation is specified. 01195 // 01196 01197 if ((DoubleOperand2.Infinity == FALSE) && 01198 (DoubleOperand2.MantissaHigh == 0)) { 01199 return KiDivideByZeroDouble(&ContextBlock, 01200 &DoubleOperand1, 01201 &DoubleOperand2); 01202 } 01203 01204 // 01205 // If the first operand is infinite, then the result is 01206 // infinite. Otherwise, if the second operand is infinite, 01207 // then the result is zero (note that both operands cannot 01208 // be infinite). 01209 // 01210 01211 if (DoubleOperand1.Infinity != FALSE) { 01212 DoubleOperand1.Sign ^= DoubleOperand2.Sign; 01213 return KiNormalizeDouble(&ContextBlock, 01214 &DoubleOperand1, 01215 0); 01216 01217 } else if (DoubleOperand2.Infinity != FALSE) { 01218 DoubleOperand1.Sign ^= DoubleOperand2.Sign; 01219 DoubleOperand1.Exponent = 0; 01220 DoubleOperand1.MantissaHigh = 0; 01221 DoubleOperand1.MantissaLow = 0; 01222 return KiNormalizeDouble(&ContextBlock, 01223 &DoubleOperand1, 01224 0); 01225 01226 } 01227 01228 // 01229 // Perform divide operation by repeating a single bit 01230 // divide step 55 iterations. 01231 // 01232 01233 DoubleDividend.LowPart = DoubleOperand1.MantissaLow; 01234 DoubleDividend.HighPart = DoubleOperand1.MantissaHigh; 01235 DoubleDivisor.LowPart = DoubleOperand2.MantissaLow; 01236 DoubleDivisor.HighPart = DoubleOperand2.MantissaHigh; 01237 DoubleQuotient.LowPart = 0; 01238 DoubleQuotient.HighPart = 0; 01239 for (Index = 0; Index < 55; Index += 1) { 01240 DoubleQuotient.HighPart = 01241 (DoubleQuotient.HighPart << 1) | 01242 DoubleQuotient.LowPart >> 31; 01243 01244 DoubleQuotient.LowPart <<= 1; 01245 if (DoubleDividend.QuadPart >= DoubleDivisor.QuadPart) { 01246 DoubleDividend.QuadPart -= DoubleDivisor.QuadPart; 01247 DoubleQuotient.LowPart |= 1; 01248 } 01249 01250 DoubleDividend.HighPart = 01251 (DoubleDividend.HighPart << 1) | 01252 DoubleDividend.LowPart >> 31; 01253 01254 DoubleDividend.LowPart <<= 1; 01255 } 01256 01257 DoubleOperand3.MantissaLow = DoubleQuotient.LowPart; 01258 DoubleOperand3.MantissaHigh = DoubleQuotient.HighPart; 01259 01260 // 01261 // Compute the sign and exponent of the result. 01262 // 01263 01264 DoubleOperand3.Sign = DoubleOperand1.Sign ^ DoubleOperand2.Sign; 01265 DoubleOperand3.Exponent = DoubleOperand1.Exponent - 01266 DoubleOperand2.Exponent + DOUBLE_EXPONENT_BIAS; 01267 01268 // 01269 // Normalize and store the result value. 01270 // 01271 01272 DoubleOperand3.Infinity = FALSE; 01273 DoubleOperand3.Nan = FALSE; 01274 return KiNormalizeDouble(&ContextBlock, 01275 &DoubleOperand3, 01276 DoubleDividend.LowPart | DoubleDividend.HighPart); 01277 01278 } else { 01279 break; 01280 } 01281 01282 // 01283 // Floating square root. 01284 // 01285 01286 case FLOAT_SQUARE_ROOT: 01287 if (Format == FORMAT_SINGLE) { 01288 01289 // 01290 // If the operand is plus infinity, then the result is 01291 // plus infinity, or if the operand is plus or minus 01292 // zero, then the result is plus or minus zero. 01293 // 01294 01295 if (((SingleOperand1.Sign == 0) && 01296 (SingleOperand1.Infinity != FALSE)) || 01297 (SingleOperand1.Mantissa == 0)) { 01298 return KiNormalizeSingle(&ContextBlock, 01299 &SingleOperand1, 01300 0); 01301 } 01302 01303 // 01304 // If the operand is negative, then the operation is 01305 // invalid. 01306 // 01307 01308 if (SingleOperand1.Sign != 0) { 01309 return KiInvalidOperationSingle(&ContextBlock, 01310 FALSE, 01311 &SingleOperand1, 01312 &SingleOperand1); 01313 } 01314 01315 // 01316 // The only case remaining that could cause an exception 01317 // is a denomalized source value. The square root of a 01318 // denormalized value is computed by: 01319 // 01320 // 1. Converting the value to a normalized value with 01321 // an exponent equal to the denormalization shift count 01322 // plus the bias of the exponent plus one. 01323 // 01324 // 2. Computing the square root of the value and unpacking 01325 // the result. 01326 // 01327 // 3. Converting the shift count back to a normalization 01328 // shift count. 01329 // 01330 // 4. Rounding and packing the resultant value. 01331 // 01332 // N.B. The square root of all denormalized number is a 01333 // normalized number. 01334 // 01335 01336 SingleOperand1.Exponent = (SINGLE_EXPONENT_BIAS + 1 + 01337 SingleOperand1.Exponent) << 23; 01338 01339 SingleValue = (SingleOperand1.Mantissa & ~(1 << 25)) >> 2; 01340 SingleValue |= SingleOperand1.Exponent; 01341 StickyBits = KiSquareRootSingle(&SingleValue); 01342 SingleOperand1.Exponent = (SingleValue >> 23) - 01343 ((SINGLE_EXPONENT_BIAS + 1) / 2); 01344 01345 SingleOperand1.Mantissa = ((SingleValue & 01346 0x7fffff) | 0x800000) << 2; 01347 01348 return KiNormalizeSingle(&ContextBlock, 01349 &SingleOperand1, 01350 StickyBits); 01351 01352 } else if (Format == FORMAT_DOUBLE) { 01353 01354 // 01355 // If the operand is plus infinity, then the result is 01356 // plus infinity, or if the operand is plus or minus 01357 // zero, then the result is plus or minus zero. 01358 // 01359 01360 if (((DoubleOperand1.Sign == 0) && 01361 (DoubleOperand1.Infinity != FALSE)) || 01362 (DoubleOperand1.MantissaHigh == 0)) { 01363 return KiNormalizeDouble(&ContextBlock, 01364 &DoubleOperand1, 01365 0); 01366 } 01367 01368 // 01369 // If the operand is negative, then the operation is 01370 // invalid. 01371 // 01372 01373 if (DoubleOperand1.Sign != 0) { 01374 return KiInvalidOperationDouble(&ContextBlock, 01375 FALSE, 01376 &DoubleOperand1, 01377 &DoubleOperand1); 01378 } 01379 01380 // 01381 // The only case remaining that could cause an exception 01382 // is a denomalized source value. The square root of a 01383 // denormalized value is computed by: 01384 // 01385 // 1. Converting the value to a normalized value with 01386 // an exponent equal to the denormalization shift count 01387 // plus the bias of the exponent plus one. 01388 // 01389 // 2. Computing the square root of the value and unpacking 01390 // the result. 01391 // 01392 // 3. Converting the shift count back to a normalization 01393 // shift count. 01394 // 01395 // 4. Rounding and packing the resultant value. 01396 // 01397 // N.B. The square root of all denormalized numbers is a 01398 // normalized number. 01399 // 01400 01401 DoubleOperand1.Exponent = (DOUBLE_EXPONENT_BIAS + 1 + 01402 DoubleOperand1.Exponent) << 20; 01403 01404 DoubleValue.HighPart = (DoubleOperand1.MantissaHigh & ~(1 << 22)) >> 2; 01405 DoubleValue.LowPart = (DoubleOperand1.MantissaHigh << 30) | 01406 (DoubleOperand1.MantissaLow >> 2); 01407 01408 DoubleValue.HighPart |= DoubleOperand1.Exponent; 01409 StickyBits = KiSquareRootDouble(&DoubleValue); 01410 DoubleOperand1.Exponent = (DoubleValue.HighPart >> 20) - 01411 ((DOUBLE_EXPONENT_BIAS + 1) / 2); 01412 01413 DoubleOperand1.MantissaLow = DoubleValue.LowPart << 2; 01414 DoubleOperand1.MantissaHigh = ((DoubleValue.HighPart & 01415 0xfffff) | 0x100000) << 2; 01416 01417 DoubleOperand1.MantissaHigh |= (DoubleValue.LowPart >> 30); 01418 return KiNormalizeDouble(&ContextBlock, 01419 &DoubleOperand1, 01420 StickyBits); 01421 01422 } else { 01423 break; 01424 } 01425 01426 // 01427 // Floating absolute operation. 01428 // 01429 // Floating absolute is accomplished by clearing the sign 01430 // of the floating value. 01431 // 01432 01433 case FLOAT_ABSOLUTE: 01434 if (Format == FORMAT_SINGLE) { 01435 01436 // 01437 // Clear the sign, normalize the result, and store in the 01438 // destination register. 01439 // 01440 01441 SingleOperand1.Sign = 0; 01442 return KiNormalizeSingle(&ContextBlock, 01443 &SingleOperand1, 01444 0); 01445 01446 } else if (Format == FORMAT_DOUBLE) { 01447 01448 // 01449 // Clear the sign, normalize the result, and store in the 01450 // destination register. 01451 // 01452 01453 DoubleOperand1.Sign = 0; 01454 return KiNormalizeDouble(&ContextBlock, 01455 &DoubleOperand1, 01456 0); 01457 01458 } else { 01459 break; 01460 } 01461 01462 // 01463 // Floating move operation. 01464 // 01465 // Floating move is accomplished by moving the source operand 01466 // to the destination register. 01467 // 01468 01469 case FLOAT_MOVE: 01470 if (Format == FORMAT_SINGLE) { 01471 01472 // 01473 // Normalize the result and store in the destination 01474 // register. 01475 // 01476 01477 return KiNormalizeSingle(&ContextBlock, 01478 &SingleOperand1, 01479 0); 01480 01481 } else if (Format == FORMAT_DOUBLE) { 01482 01483 // 01484 // Normalize the result and store in the destination 01485 // register. 01486 // 01487 01488 return KiNormalizeDouble(&ContextBlock, 01489 &DoubleOperand1, 01490 0); 01491 01492 } else { 01493 break; 01494 } 01495 01496 // 01497 // Floating negate operation. 01498 // 01499 // Floating absolute is accomplished by complementing the sign 01500 // of the floating value. 01501 // 01502 01503 case FLOAT_NEGATE: 01504 if (Format == FORMAT_SINGLE) { 01505 01506 // 01507 // Complement the sign, normalize the result, and store in the 01508 // destination register. 01509 // 01510 01511 SingleOperand1.Sign ^= 0x1; 01512 return KiNormalizeSingle(&ContextBlock, 01513 &SingleOperand1, 01514 0); 01515 01516 } else if (Format == FORMAT_DOUBLE) { 01517 01518 // 01519 // Complement the sign, normalize the result, and store in the 01520 // destination register. 01521 // 01522 01523 DoubleOperand1.Sign ^= 0x1; 01524 return KiNormalizeDouble(&ContextBlock, 01525 &DoubleOperand1, 01526 0); 01527 01528 } else { 01529 break; 01530 } 01531 01532 // 01533 // Floating compare single. 01534 // 01535 // This operation is performed after having separated out NaNs, 01536 // and therefore the only comparison predicates left are equal 01537 // and less. 01538 // 01539 // Floating compare single is accomplished by comparing signs, 01540 // then exponents, and finally the mantissa if necessary. 01541 // 01542 // N.B. The sign of zero is ignorned. 01543 // 01544 01545 case FLOAT_COMPARE_SINGLE: 01546 01547 // 01548 // If either operand is zero, then set the sign of the operand 01549 // positive. 01550 // 01551 01552 if ((SingleOperand1.Infinity == FALSE) && 01553 (SingleOperand1.Mantissa == 0)) { 01554 SingleOperand1.Sign = 0; 01555 SingleOperand1.Exponent = - 23; 01556 } 01557 01558 if ((SingleOperand2.Infinity == FALSE) && 01559 (SingleOperand2.Mantissa == 0)) { 01560 SingleOperand2.Sign = 0; 01561 SingleOperand2.Exponent = - 23; 01562 } 01563 01564 // 01565 // Compare signs first. 01566 // 01567 01568 if (SingleOperand1.Sign < SingleOperand2.Sign) { 01569 01570 // 01571 // The first operand is greater than the second operand. 01572 // 01573 01574 CompareEqual = FALSE; 01575 CompareLess = FALSE; 01576 01577 } else if (SingleOperand1.Sign > SingleOperand2.Sign) { 01578 01579 // 01580 // The first operand is less than the second operand. 01581 // 01582 01583 CompareEqual = FALSE; 01584 CompareLess = TRUE; 01585 01586 } else { 01587 01588 // 01589 // The operand signs are equal. 01590 // 01591 // If the sign of the operand is negative, then the sense of 01592 // the comparison is reversed. 01593 // 01594 01595 if (SingleOperand1.Sign == 0) { 01596 01597 // 01598 // Compare positive operand with positive operand. 01599 // 01600 01601 if (SingleOperand1.Exponent > SingleOperand2.Exponent) { 01602 CompareEqual = FALSE; 01603 CompareLess = FALSE; 01604 01605 } else if (SingleOperand1.Exponent < SingleOperand2.Exponent) { 01606 CompareEqual = FALSE; 01607 CompareLess = TRUE; 01608 01609 } else { 01610 if (SingleOperand1.Mantissa > SingleOperand2.Mantissa) { 01611 CompareEqual = FALSE; 01612 CompareLess = FALSE; 01613 01614 } else if (SingleOperand1.Mantissa < SingleOperand2.Mantissa) { 01615 CompareEqual = FALSE; 01616 CompareLess = TRUE; 01617 01618 } else { 01619 CompareEqual = TRUE; 01620 CompareLess = FALSE; 01621 } 01622 } 01623 01624 } else { 01625 01626 // 01627 // Compare negative operand with negative operand. 01628 // 01629 01630 if (SingleOperand2.Exponent > SingleOperand1.Exponent) { 01631 CompareEqual = FALSE; 01632 CompareLess = FALSE; 01633 01634 } else if (SingleOperand2.Exponent < SingleOperand1.Exponent) { 01635 CompareEqual = FALSE; 01636 CompareLess = TRUE; 01637 01638 } else { 01639 if (SingleOperand2.Mantissa > SingleOperand1.Mantissa) { 01640 CompareEqual = FALSE; 01641 CompareLess = FALSE; 01642 01643 } else if (SingleOperand2.Mantissa < SingleOperand1.Mantissa) { 01644 CompareEqual = FALSE; 01645 CompareLess = TRUE; 01646 01647 } else { 01648 CompareEqual = TRUE; 01649 CompareLess = FALSE; 01650 } 01651 } 01652 } 01653 } 01654 01655 // 01656 // Form the condition code using the comparison information 01657 // and the compare function predicate bits. 01658 // 01659 01660 if (((CompareLess != FALSE) && 01661 ((CompareFunction & COMPARE_LESS_MASK) != 0)) || 01662 ((CompareEqual != FALSE) && 01663 ((CompareFunction & COMPARE_EQUAL_MASK) != 0))) { 01664 ((PFSR)&TrapFrame->Fsr)->CC = 1; 01665 01666 } else { 01667 ((PFSR)&TrapFrame->Fsr)->CC = 0; 01668 } 01669 01670 TrapFrame->Fir = ContextBlock.BranchAddress; 01671 return TRUE; 01672 01673 // 01674 // Floating compare double. 01675 // 01676 // This operation is performed after having separated out NaNs, 01677 // and therefore the only comparison predicates left are equal 01678 // and less. 01679 // 01680 // Floating compare double is accomplished by comparing signs, 01681 // then exponents, and finally the mantissa if necessary. 01682 // 01683 // N.B. The sign of zero is ignorned. 01684 // 01685 01686 case FLOAT_COMPARE_DOUBLE: 01687 01688 // 01689 // If either operand is zero, then set the sign of the operand 01690 // positive. 01691 // 01692 01693 if ((DoubleOperand1.Infinity == FALSE) && 01694 (DoubleOperand1.MantissaHigh == 0)) { 01695 DoubleOperand1.Sign = 0; 01696 DoubleOperand1.Exponent = - 52; 01697 } 01698 01699 if ((DoubleOperand2.Infinity == FALSE) && 01700 (DoubleOperand2.MantissaHigh == 0)) { 01701 DoubleOperand2.Sign = 0; 01702 DoubleOperand2.Exponent = - 52; 01703 } 01704 01705 // 01706 // Compare signs first. 01707 // 01708 01709 if (DoubleOperand1.Sign < DoubleOperand2.Sign) { 01710 01711 // 01712 // The first operand is greater than the second operand. 01713 // 01714 01715 CompareEqual = FALSE; 01716 CompareLess = FALSE; 01717 01718 } else if (DoubleOperand1.Sign > DoubleOperand2.Sign) { 01719 01720 // 01721 // The first operand is less than the second operand. 01722 // 01723 01724 CompareEqual = FALSE; 01725 CompareLess = TRUE; 01726 01727 } else { 01728 01729 // 01730 // The operand signs are equal. 01731 // 01732 // If the sign of the operand is negative, then the sense of 01733 // the comparison is reversed. 01734 // 01735 01736 if (DoubleOperand1.Sign == 0) { 01737 01738 // 01739 // Compare positive operand with positive operand. 01740 // 01741 01742 if (DoubleOperand1.Exponent > DoubleOperand2.Exponent) { 01743 CompareEqual = FALSE; 01744 CompareLess = FALSE; 01745 01746 } else if (DoubleOperand1.Exponent < DoubleOperand2.Exponent) { 01747 CompareEqual = FALSE; 01748 CompareLess = TRUE; 01749 01750 } else { 01751 if (DoubleOperand1.MantissaHigh > 01752 DoubleOperand2.MantissaHigh) { 01753 CompareEqual = FALSE; 01754 CompareLess = FALSE; 01755 01756 } else if (DoubleOperand1.MantissaHigh < 01757 DoubleOperand2.MantissaHigh) { 01758 CompareEqual = FALSE; 01759 CompareLess = TRUE; 01760 01761 } else { 01762 if (DoubleOperand1.MantissaLow > 01763 DoubleOperand2.MantissaLow) { 01764 CompareEqual = FALSE; 01765 CompareLess = FALSE; 01766 01767 } else if (DoubleOperand1.MantissaLow < 01768 DoubleOperand2.MantissaLow) { 01769 CompareEqual = FALSE; 01770 CompareLess = TRUE; 01771 01772 } else { 01773 CompareEqual = TRUE; 01774 CompareLess = FALSE; 01775 } 01776 } 01777 } 01778 01779 } else { 01780 01781 // 01782 // Compare negative operand with negative operand. 01783 // 01784 01785 if (DoubleOperand2.Exponent > DoubleOperand1.Exponent) { 01786 CompareEqual = FALSE; 01787 CompareLess = FALSE; 01788 01789 } else if (DoubleOperand2.Exponent < DoubleOperand1.Exponent) { 01790 CompareEqual = FALSE; 01791 CompareLess = TRUE; 01792 01793 } else { 01794 if (DoubleOperand2.MantissaHigh > 01795 DoubleOperand1.MantissaHigh) { 01796 CompareEqual = FALSE; 01797 CompareLess = FALSE; 01798 01799 } else if (DoubleOperand2.MantissaHigh < 01800 DoubleOperand1.MantissaHigh) { 01801 CompareEqual = FALSE; 01802 CompareLess = TRUE; 01803 01804 } else { 01805 if (DoubleOperand2.MantissaLow > 01806 DoubleOperand1.MantissaLow) { 01807 CompareEqual = FALSE; 01808 CompareLess = FALSE; 01809 01810 } else if (DoubleOperand2.MantissaLow < 01811 DoubleOperand1.MantissaLow) { 01812 CompareEqual = FALSE; 01813 CompareLess = TRUE; 01814 01815 } else { 01816 CompareEqual = TRUE; 01817 CompareLess = FALSE; 01818 } 01819 } 01820 } 01821 } 01822 } 01823 01824 // 01825 // Form the condition code using the comparison information 01826 // and the compare function predicate bits. 01827 // 01828 01829 if (((CompareLess != FALSE) && 01830 ((CompareFunction & COMPARE_LESS_MASK) != 0)) || 01831 ((CompareEqual != FALSE) && 01832 ((CompareFunction & COMPARE_EQUAL_MASK) != 0))) { 01833 ((PFSR)&TrapFrame->Fsr)->CC = 1; 01834 01835 } else { 01836 ((PFSR)&TrapFrame->Fsr)->CC = 0; 01837 } 01838 01839 TrapFrame->Fir = ContextBlock.BranchAddress; 01840 return TRUE; 01841 01842 // 01843 // Floating convert to single. 01844 // 01845 // This operation is only legal for conversion from quadword, 01846 // longword, and double formats to single format. This operation 01847 // can not be used to convert from a single format to a single format. 01848 // 01849 // Floating conversion to single is accompished by forming a 01850 // single floating operand and then normalize and storing the 01851 // result value. 01852 // 01853 01854 case FLOAT_CONVERT_SINGLE: 01855 if (Format == FORMAT_SINGLE) { 01856 break; 01857 01858 } else if (Format == FORMAT_DOUBLE) { 01859 01860 // 01861 // If the operand is a NaN, then store a quiet NaN if the 01862 // invalid operation trap is disabled, or raise an exception 01863 // if the invalid operation trap is enabled and the operand 01864 // is a signaling NaN. 01865 // 01866 01867 if (DoubleOperand1.Nan != FALSE) { 01868 SingleOperand1.Mantissa = 01869 (DoubleOperand1.MantissaHigh << (26 - (55 - 32))) | 01870 (DoubleOperand1.MantissaLow >> (32 - (26 - (55 - 32)))); 01871 SingleOperand1.Exponent = SINGLE_MAXIMUM_EXPONENT; 01872 SingleOperand1.Sign = DoubleOperand1.Sign; 01873 SingleOperand1.Infinity = FALSE; 01874 SingleOperand1.Nan = TRUE; 01875 return KiInvalidOperationSingle(&ContextBlock, 01876 TRUE, 01877 &SingleOperand1, 01878 &SingleOperand1); 01879 01880 } 01881 01882 // 01883 // Transform the double operand to single format. 01884 // 01885 01886 SingleOperand1.Mantissa = 01887 (DoubleOperand1.MantissaHigh << (26 - (55 - 32))) | 01888 (DoubleOperand1.MantissaLow >> (32 - (26 - (55 - 32)))); 01889 StickyBits = DoubleOperand1.MantissaLow << (26 - (55 - 32)); 01890 SingleOperand1.Exponent = DoubleOperand1.Exponent + 01891 SINGLE_EXPONENT_BIAS - DOUBLE_EXPONENT_BIAS; 01892 SingleOperand1.Sign = DoubleOperand1.Sign; 01893 SingleOperand1.Infinity = DoubleOperand1.Infinity; 01894 SingleOperand1.Nan = FALSE; 01895 01896 // 01897 // Normalize and store the result value. 01898 // 01899 01900 return KiNormalizeSingle(&ContextBlock, 01901 &SingleOperand1, 01902 StickyBits); 01903 01904 } else if (Format == FORMAT_LONGWORD) { 01905 01906 // 01907 // Compute the sign of the result. 01908 // 01909 01910 if (Longword < 0) { 01911 SingleOperand1.Sign = 0x1; 01912 Longword = -Longword; 01913 01914 } else { 01915 SingleOperand1.Sign = 0; 01916 } 01917 01918 // 01919 // Initialize the infinity and NaN values. 01920 // 01921 01922 SingleOperand1.Infinity = FALSE; 01923 SingleOperand1.Nan = FALSE; 01924 01925 // 01926 // Compute the exponent value and normalize the longword 01927 // value. 01928 // 01929 01930 if (Longword != 0) { 01931 SingleOperand1.Exponent = SINGLE_EXPONENT_BIAS + 31; 01932 while (Longword > 0) { 01933 Longword <<= 1; 01934 SingleOperand1.Exponent -= 1; 01935 } 01936 01937 SingleOperand1.Mantissa = (ULONG)Longword >> (32 - 26); 01938 StickyBits = Longword << 26; 01939 01940 } else { 01941 SingleOperand1.Mantissa = 0; 01942 StickyBits = 0; 01943 SingleOperand1.Exponent = 0; 01944 } 01945 01946 // 01947 // Normalize and store the result value. 01948 // 01949 01950 return KiNormalizeSingle(&ContextBlock, 01951 &SingleOperand1, 01952 StickyBits); 01953 01954 } else if (Format == FORMAT_QUADWORD) { 01955 01956 // 01957 // Compute the sign of the result. 01958 // 01959 01960 if (u.Quadword < 0) { 01961 SingleOperand1.Sign = 0x1; 01962 u.Quadword = -u.Quadword; 01963 01964 } else { 01965 SingleOperand1.Sign = 0; 01966 } 01967 01968 // 01969 // Initialize the infinity and NaN values. 01970 // 01971 01972 SingleOperand1.Infinity = FALSE; 01973 SingleOperand1.Nan = FALSE; 01974 01975 // 01976 // Compute the exponent value and normalize the quadword 01977 // value. 01978 // 01979 01980 if (u.Quadword != 0) { 01981 SingleOperand1.Exponent = SINGLE_EXPONENT_BIAS + 63; 01982 while (u.Quadword > 0) { 01983 u.Quadword <<= 1; 01984 SingleOperand1.Exponent -= 1; 01985 } 01986 01987 SingleOperand1.Mantissa = (LONG)((ULONGLONG)u.Quadword >> (64 - 26)); 01988 StickyBits = (u.Quadword << 26) ? 1 : 0; 01989 01990 } else { 01991 SingleOperand1.Mantissa = 0; 01992 StickyBits = 0; 01993 SingleOperand1.Exponent = 0; 01994 } 01995 01996 // 01997 // Normalize and store the result value. 01998 // 01999 02000 return KiNormalizeSingle(&ContextBlock, 02001 &SingleOperand1, 02002 StickyBits); 02003 02004 } else { 02005 break; 02006 } 02007 02008 // 02009 // Floating convert to double. 02010 // 02011 // This operation is only legal for conversion from quadword, 02012 // longword, and single formats to double format. This operation 02013 // cannot be used to convert from a double format to a double 02014 // format. 02015 // 02016 // Floating conversion to double is accomplished by forming 02017 // double floating operand and then normalizing and storing 02018 // the result value. 02019 // 02020 02021 case FLOAT_CONVERT_DOUBLE: 02022 if (Format == FORMAT_SINGLE) { 02023 02024 // 02025 // If the operand is a NaN, then store a quiet NaN if the 02026 // invalid operation trap is disabled, or raise an exception 02027 // if the invalid operation trap is enabled and the operand 02028 // is a signaling NaN. 02029 // 02030 02031 if (SingleOperand1.Nan != FALSE) { 02032 DoubleOperand1.MantissaHigh = 02033 SingleOperand1.Mantissa >> (26 - (55 - 32)); 02034 DoubleOperand1.MantissaLow = (0xffffffff >> (26 - 2 - (55 - 32))) | 02035 SingleOperand1.Mantissa << (32 - (26 - (55 - 32))); 02036 DoubleOperand1.Exponent = DOUBLE_MAXIMUM_EXPONENT; 02037 DoubleOperand1.Sign = SingleOperand1.Sign; 02038 DoubleOperand1.Infinity = FALSE; 02039 DoubleOperand1.Nan = TRUE; 02040 return KiInvalidOperationDouble(&ContextBlock, 02041 TRUE, 02042 &DoubleOperand1, 02043 &DoubleOperand1); 02044 02045 } 02046 02047 // 02048 // Transform the single operand to double format. 02049 // 02050 02051 DoubleOperand1.MantissaHigh = 02052 SingleOperand1.Mantissa >> (26 - (55 - 32)); 02053 DoubleOperand1.MantissaLow = 02054 SingleOperand1.Mantissa << (32 - (26 - (55 - 32))); 02055 DoubleOperand1.Exponent = SingleOperand1.Exponent + 02056 DOUBLE_EXPONENT_BIAS - SINGLE_EXPONENT_BIAS; 02057 DoubleOperand1.Sign = SingleOperand1.Sign; 02058 DoubleOperand1.Infinity = SingleOperand1.Infinity; 02059 DoubleOperand1.Nan = FALSE; 02060 02061 // 02062 // Normalize and store the result value. 02063 // 02064 02065 return KiNormalizeDouble(&ContextBlock, 02066 &DoubleOperand1, 02067 0); 02068 02069 } else if (Format == FORMAT_DOUBLE) { 02070 break; 02071 02072 } else if (Format == FORMAT_LONGWORD) { 02073 02074 // 02075 // Compute the sign of the result. 02076 // 02077 02078 if (Longword < 0) { 02079 DoubleOperand1.Sign = 0x1; 02080 Longword = -Longword; 02081 02082 } else { 02083 DoubleOperand1.Sign = 0; 02084 } 02085 02086 // 02087 // Initialize the infinity and NaN values. 02088 // 02089 02090 DoubleOperand1.Infinity = FALSE; 02091 DoubleOperand1.Nan = FALSE; 02092 02093 // 02094 // Compute the exponent value and normalize the longword 02095 // value. 02096 // 02097 02098 if (Longword != 0) { 02099 SingleOperand1.Exponent = DOUBLE_EXPONENT_BIAS + 31; 02100 while (Longword > 0) { 02101 Longword <<= 1; 02102 DoubleOperand1.Exponent -= 1; 02103 } 02104 02105 DoubleOperand1.Mantissa = (ULONGLONG)Longword >> (64 - 55); 02106 02107 } else { 02108 DoubleOperand1.Mantissa = 0; 02109 DoubleOperand1.Exponent = 0; 02110 } 02111 02112 // 02113 // Normalize and store the result value. 02114 // 02115 02116 return KiNormalizeDouble(&ContextBlock, 02117 &DoubleOperand1, 02118 0); 02119 02120 } else if (Format == FORMAT_QUADWORD) { 02121 02122 // 02123 // Compute the sign of the result. 02124 // 02125 02126 if (u.Quadword < 0) { 02127 DoubleOperand1.Sign = 0x1; 02128 u.Quadword = -u.Quadword; 02129 02130 } else { 02131 DoubleOperand1.Sign = 0; 02132 } 02133 02134 // 02135 // Initialize the infinity and NaN values. 02136 // 02137 02138 DoubleOperand1.Infinity = FALSE; 02139 DoubleOperand1.Nan = FALSE; 02140 02141 // 02142 // Compute the exponent value and normalize the quadword 02143 // value. 02144 // 02145 02146 if (u.Quadword != 0) { 02147 DoubleOperand1.Exponent = DOUBLE_EXPONENT_BIAS + 63; 02148 while (u.Quadword > 0) { 02149 u.Quadword <<= 1; 02150 DoubleOperand1.Exponent -= 1; 02151 } 02152 02153 DoubleOperand1.Mantissa = (ULONGLONG)u.Quadword >> (64 - 55); 02154 StickyBits = (u.Quadword << 55) ? 1 : 0; 02155 02156 } else { 02157 DoubleOperand1.Mantissa = 0; 02158 StickyBits = 0; 02159 DoubleOperand1.Exponent = 0; 02160 } 02161 02162 // 02163 // Normalize and store the result value. 02164 // 02165 02166 return KiNormalizeDouble(&ContextBlock, 02167 &DoubleOperand1, 02168 StickyBits); 02169 02170 } else { 02171 break; 02172 } 02173 02174 // 02175 // Floating convert to quadword. 02176 // 02177 // This operation is only legal for conversion from double 02178 // and single formats to quadword format. This operation 02179 // cannot be used to convert from a quadword format to a 02180 // longword or quadword format. 02181 // 02182 // Floating conversion to quadword is accomplished by forming 02183 // a quadword value from a single or double floating value. 02184 // 02185 // There is one general conversion operation and four directed 02186 // rounding operations. 02187 // 02188 02189 case FLOAT_ROUND_QUADWORD: 02190 ContextBlock.Round = ROUND_TO_NEAREST; 02191 goto ConvertQuadword; 02192 02193 case FLOAT_TRUNC_QUADWORD: 02194 ContextBlock.Round = ROUND_TO_ZERO; 02195 goto ConvertQuadword; 02196 02197 case FLOAT_CEIL_QUADWORD: 02198 ContextBlock.Round = ROUND_TO_PLUS_INFINITY; 02199 goto ConvertQuadword; 02200 02201 case FLOAT_FLOOR_QUADWORD: 02202 ContextBlock.Round = ROUND_TO_MINUS_INFINITY; 02203 goto ConvertQuadword; 02204 02205 case FLOAT_CONVERT_QUADWORD: 02206 ConvertQuadword: 02207 if (Format == FORMAT_SINGLE) { 02208 02209 // 02210 // If the operand is infinite or is a NaN, then store a 02211 // quiet NaN or an appropriate infinity if the invalid 02212 // operation trap is disabled, or raise an exception if 02213 // the invalid trap is enabled. 02214 // 02215 02216 if ((SingleOperand1.Infinity != FALSE) || 02217 (SingleOperand1.Nan != FALSE)) { 02218 return KiInvalidOperationQuadword(&ContextBlock, 02219 SingleOperand1.Infinity, 02220 SingleOperand1.Sign); 02221 } 02222 02223 // 02224 // Transform the single operand to double format. 02225 // 02226 02227 DoubleOperand1.Mantissa = (LONGLONG)SingleOperand1.Mantissa << (55 - 26); 02228 DoubleOperand1.Exponent = SingleOperand1.Exponent + 02229 DOUBLE_EXPONENT_BIAS - SINGLE_EXPONENT_BIAS; 02230 02231 DoubleOperand1.Sign = SingleOperand1.Sign; 02232 DoubleOperand1.Infinity = FALSE; 02233 DoubleOperand1.Nan = FALSE; 02234 02235 // 02236 // Convert double to quadword and store the result value. 02237 // 02238 02239 return KiNormalizeQuadword(&ContextBlock, &DoubleOperand1); 02240 02241 } else if (Format == FORMAT_DOUBLE) { 02242 02243 // 02244 // If the operand is infinite or is a NaN, then store a 02245 // quiet NaN or an appropriate infinity if the invalid 02246 // operation trap is disabled, or raise an exception if 02247 // the invalid trap is enabled. 02248 // 02249 02250 if ((DoubleOperand1.Infinity != FALSE) || 02251 (DoubleOperand1.Nan != FALSE)) { 02252 return KiInvalidOperationQuadword(&ContextBlock, 02253 DoubleOperand1.Infinity, 02254 DoubleOperand1.Sign); 02255 } 02256 02257 // 02258 // Convert double to quadword and store the result value. 02259 // 02260 02261 return KiNormalizeQuadword(&ContextBlock, &DoubleOperand1); 02262 02263 } else { 02264 break; 02265 } 02266 02267 // 02268 // Floating convert to longword. 02269 // 02270 // This operation is only legal for conversion from double 02271 // and single formats to longword format. This operation 02272 // cannot be used to convert from a longword format to a 02273 // longword format. 02274 // 02275 // Floating conversion to longword is accomplished by forming 02276 // a longword value from a single or double floating value. 02277 // 02278 // There is one general conversion operation and four directed 02279 // rounding operations. 02280 // 02281 02282 case FLOAT_ROUND_LONGWORD: 02283 ContextBlock.Round = ROUND_TO_NEAREST; 02284 goto ConvertLongword; 02285 02286 case FLOAT_TRUNC_LONGWORD: 02287 ContextBlock.Round = ROUND_TO_ZERO; 02288 goto ConvertLongword; 02289 02290 case FLOAT_CEIL_LONGWORD: 02291 ContextBlock.Round = ROUND_TO_PLUS_INFINITY; 02292 goto ConvertLongword; 02293 02294 case FLOAT_FLOOR_LONGWORD: 02295 ContextBlock.Round = ROUND_TO_MINUS_INFINITY; 02296 goto ConvertLongword; 02297 02298 case FLOAT_CONVERT_LONGWORD: 02299 ConvertLongword: 02300 if (Format == FORMAT_SINGLE) { 02301 02302 // 02303 // If the operand is infinite or is a NaN, then store a 02304 // quiet NaN or an appropriate infinity if the invalid 02305 // operation trap is disabled, or raise an exception if 02306 // the invalid trap is enabled. 02307 // 02308 02309 if ((SingleOperand1.Infinity != FALSE) || 02310 (SingleOperand1.Nan != FALSE)) { 02311 return KiInvalidOperationLongword(&ContextBlock, 02312 SingleOperand1.Infinity, 02313 SingleOperand1.Sign); 02314 } 02315 02316 // 02317 // Transform the single operand to double format. 02318 // 02319 02320 DoubleOperand1.MantissaHigh = 02321 SingleOperand1.Mantissa >> (26 - (55 - 32)); 02322 DoubleOperand1.MantissaLow = 02323 SingleOperand1.Mantissa << (32 - (26 - (55 - 32))); 02324 DoubleOperand1.Exponent = SingleOperand1.Exponent + 02325 DOUBLE_EXPONENT_BIAS - SINGLE_EXPONENT_BIAS; 02326 DoubleOperand1.Sign = SingleOperand1.Sign; 02327 DoubleOperand1.Infinity = FALSE; 02328 DoubleOperand1.Nan = FALSE; 02329 02330 // 02331 // Convert double to longword and store the result value. 02332 // 02333 02334 return KiNormalizeLongword(&ContextBlock, &DoubleOperand1); 02335 02336 } else if (Format == FORMAT_DOUBLE) { 02337 02338 // 02339 // If the operand is infinite or is a NaN, then store a 02340 // quiet NaN or an appropriate infinity if the invalid 02341 // operation trap is disabled, or raise an exception if 02342 // the invalid trap is enabled. 02343 // 02344 02345 if ((DoubleOperand1.Infinity != FALSE) || 02346 (DoubleOperand1.Nan != FALSE)) { 02347 return KiInvalidOperationLongword(&ContextBlock, 02348 DoubleOperand1.Infinity, 02349 DoubleOperand1.Sign); 02350 } 02351 02352 // 02353 // Convert double to longword and store the result value. 02354 // 02355 02356 return KiNormalizeLongword(&ContextBlock, &DoubleOperand1); 02357 02358 } else { 02359 break; 02360 } 02361 02362 // 02363 // An illegal function, format value, or field value. 02364 // 02365 02366 default : 02367 break; 02368 } 02369 02370 // 02371 // An illegal function, format value, or field value was encoutnered. 02372 // Generate and illegal instruction exception. 02373 // 02374 02375 ExceptionRecord->ExceptionCode = STATUS_ILLEGAL_INSTRUCTION; 02376 return FALSE; 02377 02378 // 02379 // If an exception occurs, then copy the new exception information to the 02380 // original exception record and handle the exception. 02381 // 02382 02383 } except (KiCopyInformation(ExceptionRecord, 02384 (GetExceptionInformation())->ExceptionRecord)) { 02385 02386 // 02387 // Preserve the original exception address and branch destination. 02388 // 02389 02390 ExceptionRecord->ExceptionAddress = ExceptionAddress; 02391 return FALSE; 02392 } 02393 } 02394 02395 BOOLEAN 02396 KiDivideByZeroDouble ( 02397 IN PFP_CONTEXT_BLOCK ContextBlock, 02398 IN PFP_DOUBLE_OPERAND DoubleOperand1, 02399 IN PFP_DOUBLE_OPERAND DoubleOperand2 02400 ) 02401 02402 /*++ 02403 02404 Routine Description: 02405 02406 This function is called to either raise an exception or store a 02407 quiet NaN or properly signed infinity for a divide by zero double 02408 floating operation. 02409 02410 Arguments: 02411 02412 ContextBlock - Supplies a pointer to the emulation context block. 02413 02414 DoubleOperand1 - Supplies a pointer to the first operand value. 02415 02416 DoubleOperand2 - Supplies a pointer ot the second operand value. 02417 02418 Return Value: 02419 02420 If the divide by zero trap is enabled and the dividend is not infinite, 02421 then a value of FALSE is returned. Otherwise, a quite NaN or a properly 02422 signed infinity is stored as the destination result and a value of TRUE 02423 is returned. 02424 02425 --*/ 02426 02427 { 02428 02429 PEXCEPTION_RECORD ExceptionRecord; 02430 PFP_IEEE_VALUE IeeeValue; 02431 ULONG ResultSign; 02432 ULONG ResultValueHigh; 02433 ULONG ResultValueLow; 02434 PKTRAP_FRAME TrapFrame; 02435 02436 // 02437 // The result value is a properly signed infinity. 02438 // 02439 02440 ResultSign = DoubleOperand1->Sign ^ DoubleOperand2->Sign; 02441 ResultValueHigh = DOUBLE_INFINITY_VALUE_HIGH | (ResultSign << 31); 02442 ResultValueLow = DOUBLE_INFINITY_VALUE_LOW; 02443 02444 // 02445 // If the first operand is not infinite and the divide by zero trap is 02446 // enabled, then store the proper exception code and exception flags 02447 // and return a value of FALSE. Otherwise, store the appropriatly signed 02448 // infinity and return a value of TRUE. 02449 // 02450 02451 ExceptionRecord = ContextBlock->ExceptionRecord; 02452 TrapFrame = ContextBlock->TrapFrame; 02453 if (DoubleOperand1->Infinity == FALSE) { 02454 ((PFSR)&TrapFrame->Fsr)->SZ = 1; 02455 if (((PFSR)&TrapFrame->Fsr)->EZ != 0) { 02456 ExceptionRecord->ExceptionCode = STATUS_FLOAT_DIVIDE_BY_ZERO; 02457 ((PFSR)&TrapFrame->Fsr)->XZ = 1; 02458 IeeeValue = (PFP_IEEE_VALUE)&ExceptionRecord->ExceptionInformation[2]; 02459 IeeeValue->Value.Fp64Value.W[0] = ResultValueLow; 02460 IeeeValue->Value.Fp64Value.W[1] = ResultValueHigh; 02461 return FALSE; 02462 } 02463 } 02464 02465 KiSetRegisterValue(ContextBlock->Fd + 32, 02466 ResultValueLow, 02467 ContextBlock->ExceptionFrame, 02468 ContextBlock->TrapFrame); 02469 02470 KiSetRegisterValue(ContextBlock->Fd + 32 + 1, 02471 ResultValueHigh, 02472 ContextBlock->ExceptionFrame, 02473 ContextBlock->TrapFrame); 02474 02475 TrapFrame->Fir = ContextBlock->BranchAddress; 02476 return TRUE; 02477 } 02478 02479 BOOLEAN 02480 KiDivideByZeroSingle ( 02481 IN PFP_CONTEXT_BLOCK ContextBlock, 02482 IN PFP_SINGLE_OPERAND SingleOperand1, 02483 IN PFP_SINGLE_OPERAND SingleOperand2 02484 ) 02485 02486 /*++ 02487 02488 Routine Description: 02489 02490 This function is called to either raise an exception or store a 02491 quiet NaN or properly signed infinity for a divide by zero single 02492 floating operation. 02493 02494 Arguments: 02495 02496 ContextBlock - Supplies a pointer to the emulation context block. 02497 02498 SingleOperand1 - Supplies a pointer to the first operand value. 02499 02500 SingleOperand2 - Supplies a pointer ot the second operand value. 02501 02502 Return Value: 02503 02504 If the divide by zero trap is enabled and the dividend is not infinite, 02505 then a value of FALSE is returned. Otherwise, a quite NaN is or properly 02506 signed infinity is stored as the destination result and a value of TRUE 02507 is returned. 02508 02509 --*/ 02510 02511 { 02512 02513 PEXCEPTION_RECORD ExceptionRecord; 02514 PFP_IEEE_VALUE IeeeValue; 02515 ULONG ResultSign; 02516 ULONG ResultValue; 02517 PKTRAP_FRAME TrapFrame; 02518 02519 // 02520 // The result value is a properly signed infinity. 02521 // 02522 02523 ResultSign = SingleOperand1->Sign ^ SingleOperand2->Sign; 02524 ResultValue = SINGLE_INFINITY_VALUE | (ResultSign << 31); 02525 02526 // 02527 // If the first operand is not infinite and the divide by zero trap is 02528 // enabled, then store the proper exception code and exception flags 02529 // and return a value of FALSE. Otherwise, store the appropriatly signed 02530 // infinity and return a value of TRUE. 02531 // 02532 // 02533 02534 ExceptionRecord = ContextBlock->ExceptionRecord; 02535 TrapFrame = ContextBlock->TrapFrame; 02536 if (SingleOperand1->Infinity == FALSE) { 02537 ((PFSR)&TrapFrame->Fsr)->SZ = 1; 02538 if (((PFSR)&TrapFrame->Fsr)->EZ != 0) { 02539 ExceptionRecord->ExceptionCode = STATUS_FLOAT_DIVIDE_BY_ZERO; 02540 ((PFSR)&TrapFrame->Fsr)->XZ = 1; 02541 IeeeValue = (PFP_IEEE_VALUE)&ExceptionRecord->ExceptionInformation[2]; 02542 IeeeValue->Value.Fp32Value.W[0] = ResultValue; 02543 return FALSE; 02544 } 02545 } 02546 02547 KiSetRegisterValue(ContextBlock->Fd + 32, 02548 ResultValue, 02549 ContextBlock->ExceptionFrame, 02550 ContextBlock->TrapFrame); 02551 02552 TrapFrame->Fir = ContextBlock->BranchAddress; 02553 return TRUE; 02554 } 02555 02556 BOOLEAN 02557 KiInvalidCompareDouble ( 02558 IN PFP_CONTEXT_BLOCK ContextBlock, 02559 IN BOOLEAN CheckForNan, 02560 IN PFP_DOUBLE_OPERAND DoubleOperand1, 02561 IN PFP_DOUBLE_OPERAND DoubleOperand2 02562 ) 02563 02564 /*++ 02565 02566 Routine Description: 02567 02568 This function is called to determine whether an invalid operation 02569 exception should be raised for a double compare operation. 02570 02571 Arguments: 02572 02573 ContextBlock - Supplies a pointer to the emulation context block. 02574 02575 CheckForNan - Supplies a boolean value that detetermines whether the 02576 operand values should be checked for a signaling NaN. 02577 02578 DoubleOperand1 - Supplies a pointer to the first operand value. 02579 02580 DoubleOperand2 - Supplies a pointer ot the second operand value. 02581 02582 Return Value: 02583 02584 If the invalid operation trap is enabled and either the operation is 02585 invalid or one of the operands in a signaling NaN, then a value of 02586 FALSE is returned. Otherwise, no operation is performed and a value 02587 of TRUE is returned. 02588 02589 --*/ 02590 02591 { 02592 02593 PEXCEPTION_RECORD ExceptionRecord; 02594 PFP_IEEE_VALUE IeeeValue; 02595 PKTRAP_FRAME TrapFrame; 02596 02597 // 02598 // If an invalid operation is specified or one of the operands is a 02599 // signaling NaN and the invalid operation trap is enabled, then 02600 // store the proper exception code and exception flags and return 02601 // a value of FALSE. Otherwise, perform no operation and return a 02602 // value of TRUE. 02603 // 02604 02605 ExceptionRecord = ContextBlock->ExceptionRecord; 02606 TrapFrame = ContextBlock->TrapFrame; 02607 if ((CheckForNan == FALSE) || 02608 ((DoubleOperand1->Nan != FALSE) && 02609 ((DoubleOperand1->MantissaHigh & DOUBLE_SIGNAL_NAN_MASK) != 0)) || 02610 ((DoubleOperand2->Nan != FALSE) && 02611 ((DoubleOperand2->MantissaHigh & DOUBLE_SIGNAL_NAN_MASK) != 0))) { 02612 ((PFSR)&TrapFrame->Fsr)->SV = 1; 02613 if (((PFSR)&TrapFrame->Fsr)->EV != 0) { 02614 ExceptionRecord->ExceptionCode = STATUS_FLOAT_INVALID_OPERATION; 02615 ((PFSR)&TrapFrame->Fsr)->XV = 1; 02616 IeeeValue = (PFP_IEEE_VALUE)&ExceptionRecord->ExceptionInformation[2]; 02617 IeeeValue->Value.CompareValue = FpCompareUnordered; 02618 return FALSE; 02619 } 02620 } 02621 02622 TrapFrame->Fir = ContextBlock->BranchAddress; 02623 return TRUE; 02624 } 02625 02626 BOOLEAN 02627 KiInvalidCompareSingle ( 02628 IN PFP_CONTEXT_BLOCK ContextBlock, 02629 IN BOOLEAN CheckForNan, 02630 IN PFP_SINGLE_OPERAND SingleOperand1, 02631 IN PFP_SINGLE_OPERAND SingleOperand2 02632 ) 02633 02634 /*++ 02635 02636 Routine Description: 02637 02638 This function is called to determine whether an invalid operation 02639 exception should be raised for a single compare operation. 02640 02641 Arguments: 02642 02643 ContextBlock - Supplies a pointer to the emulation context block. 02644 02645 CheckForNan - Supplies a boolean value that detetermines whether the 02646 operand values should be checked for a signaling NaN. 02647 02648 SingleOperand1 - Supplies a pointer to the first operand value. 02649 02650 SingleOperand2 - Supplies a pointer ot the second operand value. 02651 02652 Return Value: 02653 02654 If the invalid operation trap is enabled and either the operation is 02655 invalid or one of the operands in a signaling NaN, then a value of 02656 FALSE is returned. Otherwise, no operation is performed and a value 02657 of TRUE is returned. 02658 02659 --*/ 02660 02661 { 02662 02663 PEXCEPTION_RECORD ExceptionRecord; 02664 PFP_IEEE_VALUE IeeeValue; 02665 PKTRAP_FRAME TrapFrame; 02666 02667 // 02668 // If an invalid operation is specified or one of the operands is a 02669 // signaling NaN and the invalid operation trap is enabled, then 02670 // store the proper exception code and exception flags and return 02671 // a value of FALSE. Otherwise, perform no operation and return a 02672 // value of TRUE. 02673 // 02674 02675 ExceptionRecord = ContextBlock->ExceptionRecord; 02676 TrapFrame = ContextBlock->TrapFrame; 02677 if ((CheckForNan == FALSE) || 02678 ((SingleOperand1->Nan != FALSE) && 02679 ((SingleOperand1->Mantissa & SINGLE_SIGNAL_NAN_MASK) != 0)) || 02680 ((SingleOperand2->Nan != FALSE) && 02681 ((SingleOperand2->Mantissa & SINGLE_SIGNAL_NAN_MASK) != 0))) { 02682 ((PFSR)&TrapFrame->Fsr)->SV = 1; 02683 if (((PFSR)&TrapFrame->Fsr)->EV != 0) { 02684 ExceptionRecord->ExceptionCode = STATUS_FLOAT_INVALID_OPERATION; 02685 ((PFSR)&TrapFrame->Fsr)->XV = 1; 02686 IeeeValue = (PFP_IEEE_VALUE)&ExceptionRecord->ExceptionInformation[2]; 02687 IeeeValue->Value.CompareValue = FpCompareUnordered; 02688 return FALSE; 02689 } 02690 } 02691 02692 TrapFrame->Fir = ContextBlock->BranchAddress; 02693 return TRUE; 02694 } 02695 02696 BOOLEAN 02697 KiInvalidOperationDouble ( 02698 IN PFP_CONTEXT_BLOCK ContextBlock, 02699 IN BOOLEAN CheckForNan, 02700 IN PFP_DOUBLE_OPERAND DoubleOperand1, 02701 IN PFP_DOUBLE_OPERAND DoubleOperand2 02702 ) 02703 02704 /*++ 02705 02706 Routine Description: 02707 02708 This function is called to either raise and exception or store a 02709 quiet NaN for an invalid double floating operation. 02710 02711 Arguments: 02712 02713 ContextBlock - Supplies a pointer to the emulation context block. 02714 02715 CheckForNan - Supplies a boolean value that detetermines whether the 02716 operand values should be checked for a signaling NaN. 02717 02718 DoubleOperand1 - Supplies a pointer to the first operand value. 02719 02720 DoubleOperand2 - Supplies a pointer ot the second operand value. 02721 02722 Return Value: 02723 02724 If the invalid operation trap is enabled and either the operation is 02725 invalid or one of the operands in a signaling NaN, then a value of 02726 FALSE is returned. Otherwise, a quite NaN is stored as the destination 02727 result and a value of TRUE is returned. 02728 02729 --*/ 02730 02731 { 02732 02733 PEXCEPTION_RECORD ExceptionRecord; 02734 PFP_IEEE_VALUE IeeeValue; 02735 ULONG MantissaHigh; 02736 ULONG ResultValueHigh; 02737 ULONG ResultValueLow; 02738 PKTRAP_FRAME TrapFrame; 02739 02740 // 02741 // If the first operand is a NaN, then compute a quite NaN from its 02742 // value. Otherwise, if the second operand is a NaN, then compute a 02743 // quiet NaN from its value. Otherwise, the result value is a quite 02744 // NaN. 02745 02746 if (DoubleOperand1->Nan != FALSE) { 02747 MantissaHigh = DoubleOperand1->MantissaHigh & ~DOUBLE_SIGNAL_NAN_MASK; 02748 if ((DoubleOperand1->MantissaLow | MantissaHigh) != 0) { 02749 ResultValueLow = DoubleOperand1->MantissaLow >> 2; 02750 ResultValueLow |= DoubleOperand1->MantissaHigh << 30; 02751 ResultValueHigh = DoubleOperand1->MantissaHigh >> 2; 02752 ResultValueHigh |= DOUBLE_QUIET_NAN_PREFIX; 02753 ResultValueHigh &= ~DOUBLE_QUIET_NAN_MASK; 02754 02755 } else { 02756 ResultValueLow = DOUBLE_NAN_LOW; 02757 ResultValueHigh = DOUBLE_QUIET_NAN; 02758 } 02759 02760 } else if (DoubleOperand2->Nan != FALSE) { 02761 MantissaHigh = DoubleOperand2->MantissaHigh & ~DOUBLE_SIGNAL_NAN_MASK; 02762 if ((DoubleOperand2->MantissaLow | MantissaHigh) != 0) { 02763 ResultValueLow = DoubleOperand2->MantissaLow >> 2; 02764 ResultValueLow |= DoubleOperand2->MantissaHigh << 30; 02765 ResultValueHigh = DoubleOperand2->MantissaHigh >> 2; 02766 ResultValueHigh |= DOUBLE_QUIET_NAN_PREFIX; 02767 ResultValueHigh &= ~DOUBLE_QUIET_NAN_MASK; 02768 02769 } else { 02770 ResultValueLow = DOUBLE_NAN_LOW; 02771 ResultValueHigh = DOUBLE_QUIET_NAN; 02772 } 02773 02774 } else { 02775 ResultValueLow = DOUBLE_NAN_LOW; 02776 ResultValueHigh = DOUBLE_QUIET_NAN; 02777 } 02778 02779 // 02780 // If an invalid operation is specified or one of the operands is a 02781 // signaling NaN and the invalid operation trap is enabled, then 02782 // store the proper exception code and exception flags and return 02783 // a value of FALSE. Otherwise, store a quiet NaN as the destination 02784 // result and return a value of TRUE. 02785 // 02786 02787 ExceptionRecord = ContextBlock->ExceptionRecord; 02788 TrapFrame = ContextBlock->TrapFrame; 02789 if ((CheckForNan == FALSE) || 02790 ((DoubleOperand1->Nan != FALSE) && 02791 ((DoubleOperand1->MantissaHigh & DOUBLE_SIGNAL_NAN_MASK) != 0)) || 02792 ((DoubleOperand2->Nan != FALSE) && 02793 ((DoubleOperand2->MantissaHigh & DOUBLE_SIGNAL_NAN_MASK) != 0))) { 02794 ((PFSR)&TrapFrame->Fsr)->SV = 1; 02795 if (((PFSR)&TrapFrame->Fsr)->EV != 0) { 02796 ExceptionRecord->ExceptionCode = STATUS_FLOAT_INVALID_OPERATION; 02797 ((PFSR)&TrapFrame->Fsr)->XV = 1; 02798 IeeeValue = (PFP_IEEE_VALUE)&ExceptionRecord->ExceptionInformation[2]; 02799 IeeeValue->Value.Fp64Value.W[0] = ResultValueLow; 02800 IeeeValue->Value.Fp64Value.W[1] = ResultValueHigh; 02801 return FALSE; 02802 } 02803 } 02804 02805 KiSetRegisterValue(ContextBlock->Fd + 32, 02806 ResultValueLow, 02807 ContextBlock->ExceptionFrame, 02808 ContextBlock->TrapFrame); 02809 02810 KiSetRegisterValue(ContextBlock->Fd + 32 + 1, 02811 ResultValueHigh, 02812 ContextBlock->ExceptionFrame, 02813 ContextBlock->TrapFrame); 02814 02815 TrapFrame->Fir = ContextBlock->BranchAddress; 02816 return TRUE; 02817 } 02818 02819 BOOLEAN 02820 KiInvalidOperationLongword ( 02821 IN PFP_CONTEXT_BLOCK ContextBlock, 02822 IN BOOLEAN Infinity, 02823 IN LONG Sign 02824 ) 02825 02826 /*++ 02827 02828 Routine Description: 02829 02830 This function is called to either raise and exception or store a 02831 quiet NaN for an invalid conversion to longword. 02832 02833 Arguments: 02834 02835 ContextBlock - Supplies a pointer to the emulation context block. 02836 02837 Infinity - Suuplies a boolean variable that specifies whether the 02838 invalid operand is infinite. 02839 02840 Sign - Supplies the infinity sign if the invalid operand is infinite. 02841 02842 Return Value: 02843 02844 If the invalid operation trap is enabled, then a value of FALSE is 02845 returned. Otherwise, an appropriate longword value is stored as the 02846 destination result and a value of TRUE is returned. 02847 02848 --*/ 02849 02850 { 02851 02852 PEXCEPTION_RECORD ExceptionRecord; 02853 PFP_IEEE_VALUE IeeeValue; 02854 ULONG ResultValue; 02855 PKTRAP_FRAME TrapFrame; 02856 02857 // 02858 // If the value is infinite, then the result is a properly signed value 02859 // whose magnitude is the largest that will fit in 32-bits. Otherwise, 02860 // the result is an integer NaN. 02861 // 02862 02863 if (Infinity != FALSE) { 02864 if (Sign == 0) { 02865 ResultValue = 0x7fffffff; 02866 02867 } else { 02868 ResultValue = 0x80000000; 02869 } 02870 02871 } else { 02872 ResultValue = SINGLE_INTEGER_NAN; 02873 } 02874 02875 // 02876 // If the invalid operation trap is enabled then store the proper 02877 // exception code and exception flags and return a value of FALSE. 02878 // Otherwise, store a quiet NaN as the destination result and return 02879 // a value of TRUE. 02880 // 02881 02882 ExceptionRecord = ContextBlock->ExceptionRecord; 02883 TrapFrame = ContextBlock->TrapFrame; 02884 ((PFSR)&TrapFrame->Fsr)->SV = 1; 02885 if (((PFSR)&TrapFrame->Fsr)->EV != 0) { 02886 ExceptionRecord->ExceptionCode = STATUS_FLOAT_INVALID_OPERATION; 02887 ((PFSR)&TrapFrame->Fsr)->XV = 1; 02888 IeeeValue = (PFP_IEEE_VALUE)&ExceptionRecord->ExceptionInformation[2]; 02889 IeeeValue->Value.U32Value = ResultValue; 02890 return FALSE; 02891 02892 } else { 02893 02894 KiSetRegisterValue(ContextBlock->Fd + 32, 02895 ResultValue, 02896 ContextBlock->ExceptionFrame, 02897 ContextBlock->TrapFrame); 02898 02899 TrapFrame->Fir = ContextBlock->BranchAddress; 02900 return TRUE; 02901 } 02902 } 02903 02904 BOOLEAN 02905 KiInvalidOperationQuadword ( 02906 IN PFP_CONTEXT_BLOCK ContextBlock, 02907 IN BOOLEAN Infinity, 02908 IN LONG Sign 02909 ) 02910 02911 /*++ 02912 02913 Routine Description: 02914 02915 This function is called to either raise and exception or store a 02916 quiet NaN for an invalid conversion to quadword. 02917 02918 Arguments: 02919 02920 ContextBlock - Supplies a pointer to the emulation context block. 02921 02922 Infinity - Suuplies a boolean variable that specifies whether the 02923 invalid operand is infinite. 02924 02925 Sign - Supplies the infinity sign if the invalid operand is infinite. 02926 02927 Return Value: 02928 02929 If the invalid operation trap is enabled, then a value of FALSE is 02930 returned. Otherwise, an appropriate longword value is stored as the 02931 destination result and a value of TRUE is returned. 02932 02933 --*/ 02934 02935 { 02936 02937 PEXCEPTION_RECORD ExceptionRecord; 02938 PFP_IEEE_VALUE IeeeValue; 02939 union { 02940 ULONGLONG ResultValue; 02941 ULARGE_INTEGER LargeValue; 02942 }u; 02943 02944 PKTRAP_FRAME TrapFrame; 02945 02946 // 02947 // If the value is infinite, then the result is a properly signed value 02948 // whose magnitude is the largest that will fit in 64-bits. Otherwise, 02949 // the result is an integer NaN. 02950 // 02951 02952 if (Infinity != FALSE) { 02953 if (Sign == 0) { 02954 u.ResultValue = 0x7fffffffffffffff; 02955 02956 } else { 02957 u.ResultValue = 0x8000000000000000; 02958 } 02959 02960 } else { 02961 u.ResultValue = DOUBLE_INTEGER_NAN; 02962 } 02963 02964 // 02965 // If the invalid operation trap is enabled then store the proper 02966 // exception code and exception flags and return a value of FALSE. 02967 // Otherwise, store a quiet NaN as the destination result and return 02968 // a value of TRUE. 02969 // 02970 02971 ExceptionRecord = ContextBlock->ExceptionRecord; 02972 TrapFrame = ContextBlock->TrapFrame; 02973 ((PFSR)&TrapFrame->Fsr)->SV = 1; 02974 if (((PFSR)&TrapFrame->Fsr)->EV != 0) { 02975 ExceptionRecord->ExceptionCode = STATUS_FLOAT_INVALID_OPERATION; 02976 ((PFSR)&TrapFrame->Fsr)->XV = 1; 02977 IeeeValue = (PFP_IEEE_VALUE)&ExceptionRecord->ExceptionInformation[2]; 02978 IeeeValue->Value.U64Value.QuadPart = u.ResultValue; 02979 return FALSE; 02980 02981 } else { 02982 02983 KiSetRegisterValue(ContextBlock->Fd + 32, 02984 u.LargeValue.LowPart, 02985 ContextBlock->ExceptionFrame, 02986 ContextBlock->TrapFrame); 02987 02988 KiSetRegisterValue(ContextBlock->Fd + 33, 02989 u.LargeValue.HighPart, 02990 ContextBlock->ExceptionFrame, 02991 ContextBlock->TrapFrame); 02992 02993 TrapFrame->Fir = ContextBlock->BranchAddress; 02994 return TRUE; 02995 } 02996 } 02997 02998 BOOLEAN 02999 KiInvalidOperationSingle ( 03000 IN PFP_CONTEXT_BLOCK ContextBlock, 03001 IN BOOLEAN CheckForNan, 03002 IN PFP_SINGLE_OPERAND SingleOperand1, 03003 IN PFP_SINGLE_OPERAND SingleOperand2 03004 ) 03005 03006 /*++ 03007 03008 Routine Description: 03009 03010 This function is called to either raise and exception or store a 03011 quiet NaN for an invalid single floating operation. 03012 03013 Arguments: 03014 03015 ContextBlock - Supplies a pointer to the emulation context block. 03016 03017 CheckForNan - Supplies a boolean value that detetermines whether the 03018 operand values should be checked for a signaling NaN. 03019 03020 SingleOperand1 - Supplies a pointer to the first operand value. 03021 03022 SingleOperand2 - Supplies a pointer ot the second operand value. 03023 03024 Return Value: 03025 03026 If the invalid operation trap is enabled and either the operation is 03027 invalid or one of the operands in a signaling NaN, then a value of 03028 FALSE is returned. Otherwise, a quite NaN is stored as the destination 03029 result and a value of TRUE is returned. 03030 03031 --*/ 03032 03033 { 03034 03035 PEXCEPTION_RECORD ExceptionRecord; 03036 PFP_IEEE_VALUE IeeeValue; 03037 ULONG ResultValue; 03038 PKTRAP_FRAME TrapFrame; 03039 03040 // 03041 // If the first operand is a NaN, then compute a quite NaN from its 03042 // value. Otherwise, if the second operand is a NaN, then compute a 03043 // quiet NaN from its value. Otherwise, the result value is a quite 03044 // NaN. 03045 03046 if (SingleOperand1->Nan != FALSE) { 03047 if ((SingleOperand1->Mantissa & ~SINGLE_SIGNAL_NAN_MASK) != 0) { 03048 ResultValue = SingleOperand1->Mantissa >> 2; 03049 ResultValue |= SINGLE_QUIET_NAN_PREFIX; 03050 ResultValue &= ~SINGLE_QUIET_NAN_MASK; 03051 03052 } else { 03053 ResultValue = SINGLE_QUIET_NAN; 03054 } 03055 03056 } else if (SingleOperand2->Nan != FALSE) { 03057 if ((SingleOperand2->Mantissa & ~SINGLE_SIGNAL_NAN_MASK) != 0) { 03058 ResultValue = SingleOperand2->Mantissa >> 2; 03059 ResultValue |= SINGLE_QUIET_NAN_PREFIX; 03060 ResultValue &= ~SINGLE_QUIET_NAN_MASK; 03061 03062 } else { 03063 ResultValue = SINGLE_QUIET_NAN; 03064 } 03065 03066 } else { 03067 ResultValue = SINGLE_QUIET_NAN; 03068 } 03069 03070 // 03071 // If an invalid operation is specified or one of the operands is a 03072 // signaling NaN and the invalid operation trap is enabled, then 03073 // store the proper exception code and exception flags and return 03074 // a value of FALSE. Otherwise, store a quiet NaN as the destination 03075 // result and return a value of TRUE. 03076 // 03077 03078 ExceptionRecord = ContextBlock->ExceptionRecord; 03079 TrapFrame = ContextBlock->TrapFrame; 03080 if ((CheckForNan == FALSE) || 03081 ((SingleOperand1->Nan != FALSE) && 03082 ((SingleOperand1->Mantissa & SINGLE_SIGNAL_NAN_MASK) != 0)) || 03083 ((SingleOperand2->Nan != FALSE) && 03084 ((SingleOperand2->Mantissa & SINGLE_SIGNAL_NAN_MASK) != 0))) { 03085 ((PFSR)&TrapFrame->Fsr)->SV = 1; 03086 if (((PFSR)&TrapFrame->Fsr)->EV != 0) { 03087 ExceptionRecord->ExceptionCode = STATUS_FLOAT_INVALID_OPERATION; 03088 ((PFSR)&TrapFrame->Fsr)->XV = 1; 03089 IeeeValue = (PFP_IEEE_VALUE)&ExceptionRecord->ExceptionInformation[2]; 03090 IeeeValue->Value.Fp32Value.W[0] = ResultValue; 03091 return FALSE; 03092 } 03093 } 03094 03095 KiSetRegisterValue(ContextBlock->Fd + 32, 03096 ResultValue, 03097 ContextBlock->ExceptionFrame, 03098 ContextBlock->TrapFrame); 03099 03100 TrapFrame->Fir = ContextBlock->BranchAddress; 03101 return TRUE; 03102 } 03103 03104 BOOLEAN 03105 KiNormalizeDouble ( 03106 IN PFP_CONTEXT_BLOCK ContextBlock, 03107 IN PFP_DOUBLE_OPERAND ResultOperand, 03108 IN ULONG StickyBits 03109 ) 03110 03111 /*++ 03112 03113 Routine Description: 03114 03115 This function is called to normalize a double floating result. 03116 03117 N.B. The result value is specified with a guard bit on the right, 03118 the hidden bit (if appropriate), and a possible overflow bit. 03119 The result format is: 03120 03121 <63:56> - zero 03122 <55> - overflow bit 03123 <54> - hidden bit 03124 <53:2> - mantissa 03125 <1> - guard bit 03126 <0> - round bit 03127 03128 The sticky bits specify bits that were lost during the computable. 03129 03130 Arguments: 03131 03132 ContextBlock - Supplies a pointer to the emulation context block. 03133 03134 ResultOperand - Supplies a pointer to the result operand value. 03135 03136 StickyBits - Supplies the value of the sticky bits. 03137 03138 Return Value: 03139 03140 If there is not an exception, or the exception is handled, then a proper 03141 result is stored in the destination result, the continuation address is 03142 set, and a value of TRUE is returned. Otherwise, no value is stored and 03143 a value of FALSE is returned. 03144 03145 --*/ 03146 03147 { 03148 03149 ULONG DenormalizeShift; 03150 PEXCEPTION_RECORD ExceptionRecord; 03151 ULONG ExceptionResultHigh; 03152 ULONG ExceptionResultLow; 03153 PFP_IEEE_VALUE IeeeValue; 03154 BOOLEAN Inexact; 03155 BOOLEAN Overflow; 03156 ULONG ResultValueHigh; 03157 ULONG ResultValueLow; 03158 ULONG RoundBit; 03159 PKTRAP_FRAME TrapFrame; 03160 BOOLEAN Underflow; 03161 03162 // 03163 // If the result is infinite, then store a properly signed infinity 03164 // in the destination register and return a value of TRUE. Otherwise, 03165 // round and normalize the result and check for overflow and underflow. 03166 // 03167 03168 ExceptionRecord = ContextBlock->ExceptionRecord; 03169 TrapFrame = ContextBlock->TrapFrame; 03170 if (ResultOperand->Infinity != FALSE) { 03171 KiSetRegisterValue(ContextBlock->Fd + 32, 03172 DOUBLE_INFINITY_VALUE_LOW, 03173 ContextBlock->ExceptionFrame, 03174 ContextBlock->TrapFrame); 03175 03176 KiSetRegisterValue(ContextBlock->Fd + 32 + 1, 03177 DOUBLE_INFINITY_VALUE_HIGH | (ResultOperand->Sign << 31), 03178 ContextBlock->ExceptionFrame, 03179 ContextBlock->TrapFrame); 03180 03181 TrapFrame->Fir = ContextBlock->BranchAddress; 03182 return TRUE; 03183 } 03184 03185 // 03186 // If the overflow bit is set, then right shift the mantissa one bit, 03187 // accumlate the lost bit with the sticky bits, and adjust the exponent 03188 // value. 03189 // 03190 03191 if ((ResultOperand->MantissaHigh & (1 << (55 - 32))) != 0) { 03192 StickyBits |= (ResultOperand->MantissaLow & 0x1); 03193 ResultOperand->MantissaLow = 03194 (ResultOperand->MantissaLow >> 1) | 03195 (ResultOperand->MantissaHigh << 31); 03196 03197 ResultOperand->MantissaHigh >>= 1; 03198 ResultOperand->Exponent += 1; 03199 } 03200 03201 // 03202 // If the mantissa is not zero, then normalize the mantissa by left 03203 // shifting one bit at a time until there is a one bit in bit 54. 03204 // 03205 03206 if ((ResultOperand->MantissaLow != 0) || (ResultOperand->MantissaHigh != 0)) { 03207 while ((ResultOperand->MantissaHigh & (1 << (54 - 32))) == 0) { 03208 ResultOperand->MantissaHigh = 03209 (ResultOperand->MantissaHigh << 1) | 03210 (ResultOperand->MantissaLow >> 31); 03211 03212 ResultOperand->MantissaLow <<= 1; 03213 ResultOperand->Exponent -= 1; 03214 } 03215 } 03216 03217 // 03218 // Right shift the mantissa one bit and accumlate the lost bit with the 03219 // sticky bits. 03220 // 03221 03222 StickyBits |= (ResultOperand->MantissaLow & 0x1); 03223 ResultOperand->MantissaLow = 03224 (ResultOperand->MantissaLow >> 1) | 03225 (ResultOperand->MantissaHigh << 31); 03226 03227 ResultOperand->MantissaHigh >>= 1; 03228 03229 // 03230 // Round the result value using the mantissa and the sticky bits, 03231 // 03232 03233 RoundBit = ResultOperand->MantissaLow & 0x1; 03234 switch (ContextBlock->Round) { 03235 03236 // 03237 // Round to nearest representable number. 03238 // 03239 03240 case ROUND_TO_NEAREST: 03241 if (RoundBit != 0) { 03242 if ((StickyBits != 0) || ((ResultOperand->MantissaLow & 0x2) != 0)) { 03243 ResultOperand->MantissaLow += 2; 03244 if (ResultOperand->MantissaLow < 2) { 03245 ResultOperand->MantissaHigh += 1; 03246 } 03247 } 03248 } 03249 03250 break; 03251 03252 // 03253 // Round toward zero. 03254 // 03255 03256 case ROUND_TO_ZERO: 03257 break; 03258 03259 // 03260 // Round toward plus infinity. 03261 // 03262 03263 case ROUND_TO_PLUS_INFINITY: 03264 if ((ResultOperand->Sign == 0) && 03265 ((StickyBits != 0) || (RoundBit != 0))) { 03266 ResultOperand->MantissaLow += 2; 03267 if (ResultOperand->MantissaLow < 2) { 03268 ResultOperand->MantissaHigh += 1; 03269 } 03270 } 03271 03272 break; 03273 03274 // 03275 // Round toward minus infinity. 03276 // 03277 03278 case ROUND_TO_MINUS_INFINITY: 03279 if ((ResultOperand->Sign != 0) && 03280 ((StickyBits != 0) || (RoundBit != 0))) { 03281 ResultOperand->MantissaLow += 2; 03282 if (ResultOperand->MantissaLow < 2) { 03283 ResultOperand->MantissaHigh += 1; 03284 } 03285 } 03286 03287 break; 03288 } 03289 03290 // 03291 // If rounding resulted in a carry into bit 54, then right shift the 03292 // mantissa one bit and adjust the exponent. 03293 // 03294 03295 if ((ResultOperand->MantissaHigh & (1 << (54 - 32))) != 0) { 03296 ResultOperand->MantissaLow = 03297 (ResultOperand->MantissaLow >> 1) | 03298 (ResultOperand->MantissaHigh << 31); 03299 03300 ResultOperand->MantissaHigh >>= 1; 03301 ResultOperand->Exponent += 1; 03302 } 03303 03304 // 03305 // Right shift the mantissa one bit to normalize the final result. 03306 // 03307 03308 StickyBits |= ResultOperand->MantissaLow & 0x1; 03309 ResultOperand->MantissaLow = 03310 (ResultOperand->MantissaLow >> 1) | 03311 (ResultOperand->MantissaHigh << 31); 03312 03313 ResultOperand->MantissaHigh >>= 1; 03314 03315 // 03316 // If the exponent value is greater than or equal to the maximum 03317 // exponent value, then overflow has occurred. This results in both 03318 // the inexact and overflow sticky bits being set in FSR. 03319 // 03320 // If the exponent value is less than or equal to the minimum exponent 03321 // value, the mantissa is nonzero, and the result is inexact or the 03322 // denormalized result causes loss of accuracy, then underflow has 03323 // occurred. If denormals are being flushed to zero, then a result of 03324 // zero is returned. Otherwise, both the inexact and underflow sticky 03325 // bits are set in FSR. 03326 // 03327 // Otherwise, a normal result can be delivered, but it may be inexact. 03328 // If the result is inexact, then the inexact sticky bit is set in FSR. 03329 // 03330 03331 if (ResultOperand->Exponent >= DOUBLE_MAXIMUM_EXPONENT) { 03332 Inexact = TRUE; 03333 Overflow = TRUE; 03334 Underflow = FALSE; 03335 03336 // 03337 // The overflow value is dependent on the rounding mode. 03338 // 03339 03340 switch (ContextBlock->Round) { 03341 03342 // 03343 // Round to nearest representable number. 03344 // 03345 // The result value is infinity with the sign of the result. 03346 // 03347 03348 case ROUND_TO_NEAREST: 03349 ResultValueLow = DOUBLE_INFINITY_VALUE_LOW; 03350 ResultValueHigh = 03351 DOUBLE_INFINITY_VALUE_HIGH | (ResultOperand->Sign << 31); 03352 03353 break; 03354 03355 // 03356 // Round toward zero. 03357 // 03358 // The result is the maximum number with the sign of the result. 03359 // 03360 03361 case ROUND_TO_ZERO: 03362 ResultValueLow = DOUBLE_MAXIMUM_VALUE_LOW; 03363 ResultValueHigh = 03364 DOUBLE_MAXIMUM_VALUE_HIGH | (ResultOperand->Sign << 31); 03365 break; 03366 03367 // 03368 // Round toward plus infinity. 03369 // 03370 // If the sign of the result is positive, then the result is 03371 // plus infinity. Otherwise, the result is the maximum negative 03372 // number. 03373 // 03374 03375 case ROUND_TO_PLUS_INFINITY: 03376 if (ResultOperand->Sign == 0) { 03377 ResultValueLow = DOUBLE_INFINITY_VALUE_LOW; 03378 ResultValueHigh = DOUBLE_INFINITY_VALUE_HIGH; 03379 03380 } else { 03381 ResultValueLow = DOUBLE_MAXIMUM_VALUE_LOW; 03382 ResultValueHigh = (ULONG)(DOUBLE_MAXIMUM_VALUE_HIGH | (1 << 31)); 03383 } 03384 03385 break; 03386 03387 // 03388 // Round toward minus infinity. 03389 // 03390 // If the sign of the result is negative, then the result is 03391 // negative infinity. Otherwise, the result is the maximum 03392 // positive number. 03393 // 03394 03395 03396 case ROUND_TO_MINUS_INFINITY: 03397 if (ResultOperand->Sign != 0) { 03398 ResultValueLow = DOUBLE_INFINITY_VALUE_LOW; 03399 ResultValueHigh = (ULONG)(DOUBLE_INFINITY_VALUE_HIGH | (1 << 31)); 03400 03401 } else { 03402 ResultValueLow = DOUBLE_MAXIMUM_VALUE_LOW; 03403 ResultValueHigh = DOUBLE_MAXIMUM_VALUE_HIGH; 03404 } 03405 03406 break; 03407 } 03408 03409 // 03410 // Compute the overflow exception result value by subtracting 1536 03411 // from the exponent. 03412 // 03413 03414 ExceptionResultLow = ResultOperand->MantissaLow; 03415 ExceptionResultHigh = ResultOperand->MantissaHigh & ((1 << (52 - 32)) - 1); 03416 ExceptionResultHigh |= ((ResultOperand->Exponent - 1536) << (52 - 32)); 03417 ExceptionResultHigh |= (ResultOperand->Sign << 31); 03418 03419 } else { 03420 if ((ResultOperand->Exponent <= DOUBLE_MINIMUM_EXPONENT) && 03421 (ResultOperand->MantissaHigh != 0)) { 03422 if (((PFSR)&TrapFrame->Fsr)->FS == 0) { 03423 DenormalizeShift = 1 - ResultOperand->Exponent; 03424 if (DenormalizeShift >= 53) { 03425 DenormalizeShift = 53; 03426 } 03427 03428 if (DenormalizeShift >= 32) { 03429 DenormalizeShift -= 32; 03430 StickyBits |= ResultOperand->MantissaLow | 03431 (ResultOperand->MantissaHigh & ((1 << DenormalizeShift) - 1)); 03432 03433 ResultValueLow = ResultOperand->MantissaHigh >> DenormalizeShift; 03434 ResultValueHigh = 0; 03435 03436 } else if (DenormalizeShift > 0) { 03437 StickyBits |= 03438 ResultOperand->MantissaLow & ((1 << DenormalizeShift) - 1); 03439 03440 ResultValueLow = 03441 (ResultOperand->MantissaLow >> DenormalizeShift) | 03442 (ResultOperand->MantissaHigh << (32 - DenormalizeShift)); 03443 03444 ResultValueHigh = 03445 (ResultOperand->MantissaHigh >> DenormalizeShift); 03446 03447 } else { 03448 ResultValueLow = ResultOperand->MantissaLow; 03449 ResultValueHigh = ResultOperand->MantissaHigh; 03450 } 03451 03452 ResultValueHigh |= (ResultOperand->Sign << 31); 03453 if (StickyBits != 0) { 03454 Inexact = TRUE; 03455 Overflow = FALSE; 03456 Underflow = TRUE; 03457 03458 // 03459 // Compute the underflow exception result value by adding 03460 // 1536 to the exponent. 03461 // 03462 03463 ExceptionResultLow = ResultOperand->MantissaLow; 03464 ExceptionResultHigh = ResultOperand->MantissaHigh & ((1 << (52 - 32)) - 1); 03465 ExceptionResultHigh |= ((ResultOperand->Exponent + 1536) << (52 - 32)); 03466 ExceptionResultHigh |= (ResultOperand->Sign << 31); 03467 03468 } else { 03469 Inexact = FALSE; 03470 Overflow = FALSE; 03471 Underflow = FALSE; 03472 } 03473 03474 } else { 03475 ResultValueLow = 0; 03476 ResultValueHigh = 0; 03477 Inexact = FALSE; 03478 Overflow = FALSE; 03479 Underflow = FALSE; 03480 } 03481 03482 } else { 03483 if (ResultOperand->MantissaHigh == 0) { 03484 ResultOperand->Exponent = 0; 03485 } 03486 03487 ResultValueLow = ResultOperand->MantissaLow; 03488 ResultValueHigh = ResultOperand->MantissaHigh & ((1 << (52 - 32)) - 1); 03489 ResultValueHigh |= (ResultOperand->Exponent << (52 - 32)); 03490 ResultValueHigh |= (ResultOperand->Sign << 31); 03491 Inexact = StickyBits ? TRUE : FALSE; 03492 Overflow = FALSE; 03493 Underflow = FALSE; 03494 } 03495 } 03496 03497 // 03498 // Check to determine if an exception should be delivered or the result 03499 // should be written to the destination register. 03500 // 03501 03502 if (Overflow != FALSE) { 03503 ((PFSR)&TrapFrame->Fsr)->SI = 1; 03504 ((PFSR)&TrapFrame->Fsr)->SO = 1; 03505 if ((((PFSR)&TrapFrame->Fsr)->EO != 0) || 03506 (((PFSR)&TrapFrame->Fsr)->EI != 0)) { 03507 if (((PFSR)&TrapFrame->Fsr)->EO != 0) { 03508 ExceptionRecord->ExceptionCode = STATUS_FLOAT_OVERFLOW; 03509 03510 } else { 03511 ExceptionRecord->ExceptionCode = STATUS_FLOAT_INEXACT_RESULT; 03512 } 03513 03514 IeeeValue = (PFP_IEEE_VALUE)&ExceptionRecord->ExceptionInformation[2]; 03515 IeeeValue->Value.Fp64Value.W[0] = ExceptionResultLow; 03516 IeeeValue->Value.Fp64Value.W[1] = ExceptionResultHigh; 03517 ((PFSR)&TrapFrame->Fsr)->XI = 1; 03518 ((PFSR)&TrapFrame->Fsr)->XO = 1; 03519 return FALSE; 03520 } 03521 03522 } else if (Underflow != FALSE) { 03523 ((PFSR)&TrapFrame->Fsr)->SI = 1; 03524 ((PFSR)&TrapFrame->Fsr)->SU = 1; 03525 if ((((PFSR)&TrapFrame->Fsr)->EU != 0) || 03526 (((PFSR)&TrapFrame->Fsr)->EI != 0)) { 03527 if (((PFSR)&TrapFrame->Fsr)->EU != 0) { 03528 ExceptionRecord->ExceptionCode = STATUS_FLOAT_UNDERFLOW; 03529 03530 } else { 03531 ExceptionRecord->ExceptionCode = STATUS_FLOAT_INEXACT_RESULT; 03532 } 03533 03534 IeeeValue = (PFP_IEEE_VALUE)&ExceptionRecord->ExceptionInformation[2]; 03535 IeeeValue->Value.Fp64Value.W[0] = ExceptionResultLow; 03536 IeeeValue->Value.Fp64Value.W[1] = ExceptionResultHigh; 03537 ((PFSR)&TrapFrame->Fsr)->XI = 1; 03538 ((PFSR)&TrapFrame->Fsr)->XU = 1; 03539 return FALSE; 03540 } 03541 03542 } else if (Inexact != FALSE) { 03543 ((PFSR)&TrapFrame->Fsr)->SI = 1; 03544 if (((PFSR)&TrapFrame->Fsr)->EI != 0) { 03545 ExceptionRecord->ExceptionCode = STATUS_FLOAT_INEXACT_RESULT; 03546 ((PFSR)&TrapFrame->Fsr)->XI = 1; 03547 IeeeValue = (PFP_IEEE_VALUE)&ExceptionRecord->ExceptionInformation[2]; 03548 IeeeValue->Value.Fp64Value.W[0] = ResultValueLow; 03549 IeeeValue->Value.Fp64Value.W[1] = ResultValueHigh; 03550 return FALSE; 03551 } 03552 } 03553 03554 // 03555 // Set the destination register value, update the return address, 03556 // and return a value of TRUE. 03557 // 03558 03559 KiSetRegisterValue(ContextBlock->Fd + 32, 03560 ResultValueLow, 03561 ContextBlock->ExceptionFrame, 03562 ContextBlock->TrapFrame); 03563 03564 KiSetRegisterValue(ContextBlock->Fd + 32 + 1, 03565 ResultValueHigh, 03566 ContextBlock->ExceptionFrame, 03567 ContextBlock->TrapFrame); 03568 03569 TrapFrame->Fir = ContextBlock->BranchAddress; 03570 return TRUE; 03571 } 03572 03573 BOOLEAN 03574 KiNormalizeLongword ( 03575 IN PFP_CONTEXT_BLOCK ContextBlock, 03576 IN PFP_DOUBLE_OPERAND ResultOperand 03577 ) 03578 03579 /*++ 03580 03581 Routine Description: 03582 03583 This function is called to convert a result value to a longword result. 03584 03585 N.B. The result value is specified with a guard bit on the right, 03586 the hidden bit (if appropriate), and an overlfow bit of zero. 03587 The result format is: 03588 03589 <63:55> - zero 03590 <54 - hidden bit 03591 <53:2> - mantissa 03592 <1> - guard bit 03593 <0> - round bit 03594 03595 There are no sticky bits. 03596 03597 Arguments: 03598 03599 ContextBlock - Supplies a pointer to the emulation context block. 03600 03601 ResultOperand - Supplies a pointer to the result operand value. 03602 03603 Return Value: 03604 03605 If there is not an exception, or the exception is handled, then a proper 03606 result is stored in the destination result, the continuation address is 03607 set, and a value of TRUE is returned. Otherwise, no value is stored and 03608 a value of FALSE is returned. 03609 03610 --*/ 03611 03612 { 03613 03614 PEXCEPTION_RECORD ExceptionRecord; 03615 LONG ExponentShift; 03616 PFP_IEEE_VALUE IeeeValue; 03617 BOOLEAN Inexact; 03618 BOOLEAN Overflow; 03619 ULONG ResultValue; 03620 ULONG RoundBit; 03621 ULONG StickyBits; 03622 PKTRAP_FRAME TrapFrame; 03623 03624 // 03625 // Subtract out the exponent bias and divide the cases into right 03626 // and left shifts. 03627 // 03628 03629 ExceptionRecord = ContextBlock->ExceptionRecord; 03630 TrapFrame = ContextBlock->TrapFrame; 03631 ExponentShift = ResultOperand->Exponent - DOUBLE_EXPONENT_BIAS; 03632 if (ExponentShift < 23) { 03633 03634 // 03635 // The integer value is less than 2**23 and a right shift must 03636 // be performed. 03637 // 03638 03639 ExponentShift = 22 - ExponentShift; 03640 if (ExponentShift > 24) { 03641 ExponentShift = 24; 03642 } 03643 03644 StickyBits = 03645 (ResultOperand->MantissaLow >> 2) | 03646 (ResultOperand->MantissaHigh << (32 - ExponentShift)); 03647 03648 ResultValue = ResultOperand->MantissaHigh >> ExponentShift; 03649 Overflow = FALSE; 03650 03651 } else { 03652 03653 // 03654 // The integer value is two or greater and a left shift must be 03655 // performed. 03656 // 03657 03658 ExponentShift -= 22; 03659 if (ExponentShift <= (31 - 22)) { 03660 StickyBits = ResultOperand->MantissaLow << ExponentShift; 03661 ResultValue = 03662 (ResultOperand->MantissaHigh << ExponentShift) | 03663 (ResultOperand->MantissaLow >> (32 - ExponentShift)); 03664 03665 Overflow = FALSE; 03666 03667 } else { 03668 Overflow = TRUE; 03669 } 03670 } 03671 03672 // 03673 // Round the result value using the mantissa and the sticky bits, 03674 // 03675 03676 RoundBit = StickyBits >> 31; 03677 StickyBits <<= 1; 03678 switch (ContextBlock->Round) { 03679 03680 // 03681 // Round to nearest representable number. 03682 // 03683 03684 case ROUND_TO_NEAREST: 03685 if (RoundBit != 0) { 03686 if ((StickyBits != 0) || ((ResultValue & 0x1) != 0)) { 03687 ResultValue += 1; 03688 if (ResultValue == 0) { 03689 Overflow = TRUE; 03690 } 03691 } 03692 } 03693 03694 break; 03695 03696 // 03697 // Round toward zero. 03698 // 03699 03700 case ROUND_TO_ZERO: 03701 break; 03702 03703 // 03704 // Round toward plus infinity. 03705 // 03706 03707 case ROUND_TO_PLUS_INFINITY: 03708 if ((ResultOperand->Sign == 0) && (StickyBits != 0)) { 03709 ResultValue += 1; 03710 if (ResultValue == 0) { 03711 Overflow = TRUE; 03712 } 03713 } 03714 03715 break; 03716 03717 // 03718 // Round toward minus infinity. 03719 // 03720 03721 case ROUND_TO_MINUS_INFINITY: 03722 if ((ResultOperand->Sign != 0) && (StickyBits != 0)) { 03723 ResultValue += 1; 03724 if (ResultValue == 0) { 03725 Overflow = TRUE; 03726 } 03727 } 03728 03729 break; 03730 } 03731 03732 // 03733 // If the result value is positive and the result is negative, then 03734 // overflow has occurred. Otherwise, negate the result value and 03735 // check if the result is negative. If the result is positive, then 03736 // overflow has occurred. 03737 // 03738 03739 if (ResultOperand->Sign == 0) { 03740 if ((ResultValue >> 31) != 0) { 03741 Overflow = TRUE; 03742 } 03743 03744 } else { 03745 ResultValue = ~ResultValue + 1; 03746 if ((ResultValue >> 31) == 0) { 03747 Overflow = TRUE; 03748 } 03749 } 03750 03751 // 03752 // Check to determine if an exception should be delivered or the result 03753 // should be written to the destination register. 03754 // 03755 03756 if (Overflow != FALSE) { 03757 return KiInvalidOperationLongword(ContextBlock, 03758 FALSE, 03759 0); 03760 03761 } else if ((StickyBits | RoundBit) != 0) { 03762 ((PFSR)&TrapFrame->Fsr)->SI = 1; 03763 if (((PFSR)&TrapFrame->Fsr)->EI != 0) { 03764 ExceptionRecord->ExceptionCode = STATUS_FLOAT_INEXACT_RESULT; 03765 ((PFSR)&TrapFrame->Fsr)->XI = 1; 03766 IeeeValue = (PFP_IEEE_VALUE)&ExceptionRecord->ExceptionInformation[2]; 03767 IeeeValue->Value.U32Value = ResultValue; 03768 return FALSE; 03769 } 03770 03771 } 03772 03773 // 03774 // Set the destination register value, update the return address, 03775 // and return a value of TRUE. 03776 // 03777 03778 KiSetRegisterValue(ContextBlock->Fd + 32, 03779 ResultValue, 03780 ContextBlock->ExceptionFrame, 03781 ContextBlock->TrapFrame); 03782 03783 TrapFrame->Fir = ContextBlock->BranchAddress; 03784 return TRUE; 03785 } 03786 03787 BOOLEAN 03788 KiNormalizeQuadword ( 03789 IN PFP_CONTEXT_BLOCK ContextBlock, 03790 IN PFP_DOUBLE_OPERAND ResultOperand 03791 ) 03792 03793 /*++ 03794 03795 Routine Description: 03796 03797 This function is called to convert a result value to a quadword result. 03798 03799 N.B. The result value is specified with a guard bit on the right, 03800 the hidden bit (if appropriate), and an overlfow bit of zero. 03801 The result format is: 03802 03803 <63:55> - zero 03804 <54 - hidden bit 03805 <53:2> - mantissa 03806 <1> - guard bit 03807 <0> - round bit 03808 03809 There are no sticky bits. 03810 03811 Arguments: 03812 03813 ContextBlock - Supplies a pointer to the emulation context block. 03814 03815 ResultOperand - Supplies a pointer to the result operand value. 03816 03817 Return Value: 03818 03819 If there is not an exception, or the exception is handled, then a proper 03820 result is stored in the destination result, the continuation address is 03821 set, and a value of TRUE is returned. Otherwise, no value is stored and 03822 a value of FALSE is returned. 03823 03824 --*/ 03825 03826 { 03827 03828 PEXCEPTION_RECORD ExceptionRecord; 03829 LONG ExponentShift; 03830 PFP_IEEE_VALUE IeeeValue; 03831 BOOLEAN Inexact; 03832 BOOLEAN Overflow; 03833 union { 03834 ULONGLONG ResultValue; 03835 ULARGE_INTEGER LargeValue; 03836 }u; 03837 03838 ULONG RoundBit; 03839 ULONG StickyBits; 03840 PKTRAP_FRAME TrapFrame; 03841 03842 // 03843 // Subtract out the exponent bias and divide the cases into right 03844 // and left shifts. 03845 // 03846 03847 ExceptionRecord = ContextBlock->ExceptionRecord; 03848 TrapFrame = ContextBlock->TrapFrame; 03849 ExponentShift = ResultOperand->Exponent - DOUBLE_EXPONENT_BIAS; 03850 if (ExponentShift < 54) { 03851 03852 // 03853 // The integer value is less than 2**52 and a right shift must 03854 // be performed. 03855 // 03856 03857 ExponentShift = 54 - ExponentShift; 03858 if (ExponentShift > 54) { 03859 ExponentShift = 54; 03860 } 03861 03862 StickyBits = (ULONG)(ResultOperand->Mantissa << (32 - ExponentShift)); 03863 u.ResultValue = ResultOperand->Mantissa >> ExponentShift; 03864 Overflow = FALSE; 03865 03866 } else { 03867 03868 // 03869 // The integer value is two or greater and a left shift must be 03870 // performed. 03871 // 03872 03873 ExponentShift -= 54; 03874 if (ExponentShift <= (63 - 54)) { 03875 StickyBits = 0; 03876 u.ResultValue = ResultOperand->Mantissa << ExponentShift; 03877 Overflow = FALSE; 03878 03879 } else { 03880 Overflow = TRUE; 03881 } 03882 } 03883 03884 // 03885 // Round the result value using the mantissa and the sticky bits, 03886 // 03887 03888 RoundBit = StickyBits >> 31; 03889 StickyBits <<= 1; 03890 switch (ContextBlock->Round) { 03891 03892 // 03893 // Round to nearest representable number. 03894 // 03895 03896 case ROUND_TO_NEAREST: 03897 if (RoundBit != 0) { 03898 if ((StickyBits != 0) || ((u.ResultValue & 0x1) != 0)) { 03899 u.ResultValue += 1; 03900 if (u.ResultValue == 0) { 03901 Overflow = TRUE; 03902 } 03903 } 03904 } 03905 03906 break; 03907 03908 // 03909 // Round toward zero. 03910 // 03911 03912 case ROUND_TO_ZERO: 03913 break; 03914 03915 // 03916 // Round toward plus infinity. 03917 // 03918 03919 case ROUND_TO_PLUS_INFINITY: 03920 if ((ResultOperand->Sign == 0) && (StickyBits != 0)) { 03921 u.ResultValue += 1; 03922 if (u.ResultValue == 0) { 03923 Overflow = TRUE; 03924 } 03925 } 03926 03927 break; 03928 03929 // 03930 // Round toward minus infinity. 03931 // 03932 03933 case ROUND_TO_MINUS_INFINITY: 03934 if ((ResultOperand->Sign != 0) && (StickyBits != 0)) { 03935 u.ResultValue += 1; 03936 if (u.ResultValue == 0) { 03937 Overflow = TRUE; 03938 } 03939 } 03940 03941 break; 03942 } 03943 03944 // 03945 // If the result value is positive and the result is negative, then 03946 // overflow has occurred. Otherwise, negate the result value and 03947 // check if the result is negative. If the result is positive, then 03948 // overflow has occurred. 03949 // 03950 03951 if (ResultOperand->Sign == 0) { 03952 if ((u.ResultValue >> 63) != 0) { 03953 Overflow = TRUE; 03954 } 03955 03956 } else { 03957 u.ResultValue = ~u.ResultValue + 1; 03958 if ((u.ResultValue >> 63) == 0) { 03959 Overflow = TRUE; 03960 } 03961 } 03962 03963 // 03964 // Check to determine if an exception should be delivered or the result 03965 // should be written to the destination register. 03966 // 03967 03968 if (Overflow != FALSE) { 03969 return KiInvalidOperationQuadword(ContextBlock, 03970 FALSE, 03971 0); 03972 03973 } else if ((StickyBits | RoundBit) != 0) { 03974 ((PFSR)&TrapFrame->Fsr)->SI = 1; 03975 if (((PFSR)&TrapFrame->Fsr)->EI != 0) { 03976 ExceptionRecord->ExceptionCode = STATUS_FLOAT_INEXACT_RESULT; 03977 ((PFSR)&TrapFrame->Fsr)->XI = 1; 03978 IeeeValue = (PFP_IEEE_VALUE)&ExceptionRecord->ExceptionInformation[2]; 03979 IeeeValue->Value.U64Value.QuadPart = u.ResultValue; 03980 return FALSE; 03981 } 03982 03983 } 03984 03985 // 03986 // Set the destination register value, update the return address, 03987 // and return a value of TRUE. 03988 // 03989 03990 KiSetRegisterValue(ContextBlock->Fd + 32, 03991 u.LargeValue.LowPart, 03992 ContextBlock->ExceptionFrame, 03993 ContextBlock->TrapFrame); 03994 03995 KiSetRegisterValue(ContextBlock->Fd + 33, 03996 u.LargeValue.HighPart, 03997 ContextBlock->ExceptionFrame, 03998 ContextBlock->TrapFrame); 03999 04000 TrapFrame->Fir = ContextBlock->BranchAddress; 04001 return TRUE; 04002 } 04003 04004 BOOLEAN 04005 KiNormalizeSingle ( 04006 IN PFP_CONTEXT_BLOCK ContextBlock, 04007 IN PFP_SINGLE_OPERAND ResultOperand, 04008 IN ULONG StickyBits 04009 ) 04010 04011 /*++ 04012 04013 Routine Description: 04014 04015 This function is called to normalize a single floating result. 04016 04017 N.B. The result value is specified with a guard bit on the right, 04018 the hidden bit (if appropriate), and a possible overflow bit. 04019 The result format is: 04020 04021 <31:27> - zero 04022 <26> - overflow bit 04023 <25> - hidden bit 04024 <24:2> - mantissa 04025 <1> - guard bit 04026 <0> - round bit 04027 04028 The sticky bits specify bits that were lost during the computable. 04029 04030 Arguments: 04031 04032 ContextBlock - Supplies a pointer to the emulation context block. 04033 04034 ResultOperand - Supplies a pointer to the result operand value. 04035 04036 StickyBits - Supplies the value of the sticky bits. 04037 04038 Return Value: 04039 04040 If there is not an exception, or the exception is handled, then a proper 04041 result is stored in the destination result, the continuation address is 04042 set, and a value of TRUE is returned. Otherwise, no value is stored and 04043 a value of FALSE is returned. 04044 04045 --*/ 04046 04047 { 04048 04049 ULONG DenormalizeShift; 04050 PEXCEPTION_RECORD ExceptionRecord; 04051 ULONG ExceptionResult; 04052 PFP_IEEE_VALUE IeeeValue; 04053 BOOLEAN Inexact; 04054 BOOLEAN Overflow; 04055 ULONG ResultValue; 04056 ULONG RoundBit; 04057 PKTRAP_FRAME TrapFrame; 04058 BOOLEAN Underflow; 04059 04060 // 04061 // If the result is infinite, then store a properly signed infinity 04062 // in the destination register and return a value of TRUE. Otherwise, 04063 // round and normalize the result and check for overflow and underflow. 04064 // 04065 04066 ExceptionRecord = ContextBlock->ExceptionRecord; 04067 TrapFrame = ContextBlock->TrapFrame; 04068 if (ResultOperand->Infinity != FALSE) { 04069 KiSetRegisterValue(ContextBlock->Fd + 32, 04070 SINGLE_INFINITY_VALUE | (ResultOperand->Sign << 31), 04071 ContextBlock->ExceptionFrame, 04072 ContextBlock->TrapFrame); 04073 04074 TrapFrame->Fir = ContextBlock->BranchAddress; 04075 return TRUE; 04076 } 04077 04078 // 04079 // If the overflow bit is set, then right shift the mantissa one bit, 04080 // accumlate the lost bit with the sticky bits, and adjust the exponent 04081 // value. 04082 // 04083 04084 if ((ResultOperand->Mantissa & (1 << 26)) != 0) { 04085 StickyBits |= (ResultOperand->Mantissa & 0x1); 04086 ResultOperand->Mantissa >>= 1; 04087 ResultOperand->Exponent += 1; 04088 } 04089 04090 // 04091 // If the mantissa is not zero, then normalize the mantissa by left 04092 // shifting one bit at a time until there is a one bit in bit 25. 04093 // 04094 04095 if (ResultOperand->Mantissa != 0) { 04096 while ((ResultOperand->Mantissa & (1 << 25)) == 0) { 04097 ResultOperand->Mantissa <<= 1; 04098 ResultOperand->Exponent -= 1; 04099 } 04100 } 04101 04102 // 04103 // Right shift the mantissa one bit and accumlate the lost bit with the 04104 // sticky bits. 04105 // 04106 04107 StickyBits |= (ResultOperand->Mantissa & 0x1); 04108 ResultOperand->Mantissa >>= 1; 04109 04110 // 04111 // Round the result value using the mantissa, the round bit, and the 04112 // sticky bits, 04113 // 04114 04115 RoundBit = ResultOperand->Mantissa & 0x1; 04116 switch (ContextBlock->Round) { 04117 04118 // 04119 // Round to nearest representable number. 04120 // 04121 04122 case ROUND_TO_NEAREST: 04123 if (RoundBit != 0) { 04124 if ((StickyBits != 0) || ((ResultOperand->Mantissa & 0x2) != 0)) { 04125 ResultOperand->Mantissa += 2; 04126 } 04127 } 04128 04129 break; 04130 04131 // 04132 // Round toward zero. 04133 // 04134 04135 case ROUND_TO_ZERO: 04136 break; 04137 04138 // 04139 // Round toward plus infinity. 04140 // 04141 04142 case ROUND_TO_PLUS_INFINITY: 04143 if ((ResultOperand->Sign == 0) && 04144 ((StickyBits != 0) || (RoundBit != 0))) { 04145 ResultOperand->Mantissa += 2; 04146 } 04147 04148 break; 04149 04150 // 04151 // Round toward minus infinity. 04152 // 04153 04154 case ROUND_TO_MINUS_INFINITY: 04155 if ((ResultOperand->Sign != 0) && 04156 ((StickyBits != 0) || (RoundBit != 0))) { 04157 ResultOperand->Mantissa += 2; 04158 } 04159 04160 break; 04161 } 04162 04163 // 04164 // If rounding resulted in a carry into bit 25, then right shift the 04165 // mantissa one bit and adjust the exponent. 04166 // 04167 04168 if ((ResultOperand->Mantissa & (1 << 25)) != 0) { 04169 ResultOperand->Mantissa >>= 1; 04170 ResultOperand->Exponent += 1; 04171 } 04172 04173 // 04174 // Right shift the mantissa one bit to normalize the final result. 04175 // 04176 04177 StickyBits |= RoundBit; 04178 ResultOperand->Mantissa >>= 1; 04179 04180 // 04181 // If the exponent value is greater than or equal to the maximum 04182 // exponent value, then overflow has occurred. This results in both 04183 // the inexact and overflow stickt bits being set in FSR. 04184 // 04185 // If the exponent value is less than or equal to the minimum exponent 04186 // value, the mantissa is nonzero, and the result is inexact or the 04187 // denormalized result causes loss of accuracy, then underflow has 04188 // occurred. If denormals are being flushed to zero, then a result of 04189 // zero is returned. Otherwise, both the inexact and underflow sticky 04190 // bits are set in FSR. 04191 // 04192 // Otherwise, a normal result can be delivered, but it may be inexact. 04193 // If the result is inexact, then the inexact sticky bit is set in FSR. 04194 // 04195 04196 if (ResultOperand->Exponent >= SINGLE_MAXIMUM_EXPONENT) { 04197 Inexact = TRUE; 04198 Overflow = TRUE; 04199 Underflow = FALSE; 04200 04201 // 04202 // The overflow value is dependent on the rounding mode. 04203 // 04204 04205 switch (ContextBlock->Round) { 04206 04207 // 04208 // Round to nearest representable number. 04209 // 04210 // The result value is infinity with the sign of the result. 04211 // 04212 04213 case ROUND_TO_NEAREST: 04214 ResultValue = SINGLE_INFINITY_VALUE | (ResultOperand->Sign << 31); 04215 break; 04216 04217 // 04218 // Round toward zero. 04219 // 04220 // The result is the maximum number with the sign of the result. 04221 // 04222 04223 case ROUND_TO_ZERO: 04224 ResultValue = SINGLE_MAXIMUM_VALUE | (ResultOperand->Sign << 31); 04225 break; 04226 04227 // 04228 // Round toward plus infinity. 04229 // 04230 // If the sign of the result is positive, then the result is 04231 // plus infinity. Otherwise, the result is the maximum negative 04232 // number. 04233 // 04234 04235 case ROUND_TO_PLUS_INFINITY: 04236 if (ResultOperand->Sign == 0) { 04237 ResultValue = SINGLE_INFINITY_VALUE; 04238 04239 } else { 04240 ResultValue = (ULONG)(SINGLE_MAXIMUM_VALUE | (1 << 31)); 04241 } 04242 04243 break; 04244 04245 // 04246 // Round toward minus infinity. 04247 // 04248 // If the sign of the result is negative, then the result is 04249 // negative infinity. Otherwise, the result is the maximum 04250 // positive number. 04251 // 04252 04253 04254 case ROUND_TO_MINUS_INFINITY: 04255 if (ResultOperand->Sign != 0) { 04256 ResultValue = (ULONG)(SINGLE_INFINITY_VALUE | (1 << 31)); 04257 04258 } else { 04259 ResultValue = SINGLE_MAXIMUM_VALUE; 04260 } 04261 04262 break; 04263 } 04264 04265 // 04266 // Compute the overflow exception result value by subtracting 192 04267 // from the exponent. 04268 // 04269 04270 ExceptionResult = ResultOperand->Mantissa & ((1 << 23) - 1); 04271 ExceptionResult |= ((ResultOperand->Exponent - 192) << 23); 04272 ExceptionResult |= (ResultOperand->Sign << 31); 04273 04274 } else { 04275 if ((ResultOperand->Exponent <= SINGLE_MINIMUM_EXPONENT) && 04276 (ResultOperand->Mantissa != 0)) { 04277 if (((PFSR)&TrapFrame->Fsr)->FS == 0) { 04278 DenormalizeShift = 1 - ResultOperand->Exponent; 04279 if (DenormalizeShift >= 24) { 04280 DenormalizeShift = 24; 04281 } 04282 04283 ResultValue = ResultOperand->Mantissa >> DenormalizeShift; 04284 ResultValue |= (ResultOperand->Sign << 31); 04285 if ((StickyBits != 0) || 04286 ((ResultOperand->Mantissa & ((1 << DenormalizeShift) - 1)) != 0)) { 04287 Inexact = TRUE; 04288 Overflow = FALSE; 04289 Underflow = TRUE; 04290 04291 // 04292 // Compute the underflow exception result value by adding 04293 // 192 to the exponent. 04294 // 04295 04296 ExceptionResult = ResultOperand->Mantissa & ((1 << 23) - 1); 04297 ExceptionResult |= ((ResultOperand->Exponent + 192) << 23); 04298 ExceptionResult |= (ResultOperand->Sign << 31); 04299 04300 } else { 04301 Inexact = FALSE; 04302 Overflow = FALSE; 04303 Underflow = FALSE; 04304 } 04305 04306 } else { 04307 ResultValue = 0; 04308 Inexact = FALSE; 04309 Overflow = FALSE; 04310 Underflow = FALSE; 04311 } 04312 04313 } else { 04314 if (ResultOperand->Mantissa == 0) { 04315 ResultOperand->Exponent = 0; 04316 } 04317 04318 ResultValue = ResultOperand->Mantissa & ((1 << 23) - 1); 04319 ResultValue |= (ResultOperand->Exponent << 23); 04320 ResultValue |= (ResultOperand->Sign << 31); 04321 Inexact = StickyBits ? TRUE : FALSE; 04322 Overflow = FALSE; 04323 Underflow = FALSE; 04324 } 04325 } 04326 04327 // 04328 // Check to determine if an exception should be delivered or the result 04329 // should be written to the destination register. 04330 // 04331 04332 if (Overflow != FALSE) { 04333 ((PFSR)&TrapFrame->Fsr)->SI = 1; 04334 ((PFSR)&TrapFrame->Fsr)->SO = 1; 04335 if ((((PFSR)&TrapFrame->Fsr)->EO != 0) || 04336 (((PFSR)&TrapFrame->Fsr)->EI != 0)) { 04337 if (((PFSR)&TrapFrame->Fsr)->EO != 0) { 04338 ExceptionRecord->ExceptionCode = STATUS_FLOAT_OVERFLOW; 04339 04340 } else { 04341 ExceptionRecord->ExceptionCode = STATUS_FLOAT_INEXACT_RESULT; 04342 } 04343 04344 IeeeValue = (PFP_IEEE_VALUE)&ExceptionRecord->ExceptionInformation[2]; 04345 IeeeValue->Value.Fp32Value.W[0] = ExceptionResult; 04346 ((PFSR)&TrapFrame->Fsr)->XI = 1; 04347 ((PFSR)&TrapFrame->Fsr)->XO = 1; 04348 return FALSE; 04349 } 04350 04351 } else if (Underflow != FALSE) { 04352 ((PFSR)&TrapFrame->Fsr)->SI = 1; 04353 ((PFSR)&TrapFrame->Fsr)->SU = 1; 04354 if ((((PFSR)&TrapFrame->Fsr)->EU != 0) || 04355 (((PFSR)&TrapFrame->Fsr)->EI != 0)) { 04356 if (((PFSR)&TrapFrame->Fsr)->EU != 0) { 04357 ExceptionRecord->ExceptionCode = STATUS_FLOAT_UNDERFLOW; 04358 04359 } else { 04360 ExceptionRecord->ExceptionCode = STATUS_FLOAT_INEXACT_RESULT; 04361 } 04362 04363 IeeeValue = (PFP_IEEE_VALUE)&ExceptionRecord->ExceptionInformation[2]; 04364 IeeeValue->Value.Fp32Value.W[0] = ExceptionResult; 04365 ((PFSR)&TrapFrame->Fsr)->XI = 1; 04366 ((PFSR)&TrapFrame->Fsr)->XU = 1; 04367 return FALSE; 04368 } 04369 04370 } else if (Inexact != FALSE) { 04371 ((PFSR)&TrapFrame->Fsr)->SI = 1; 04372 if (((PFSR)&TrapFrame->Fsr)->EI != 0) { 04373 ExceptionRecord->ExceptionCode = STATUS_FLOAT_INEXACT_RESULT; 04374 ((PFSR)&TrapFrame->Fsr)->XI = 1; 04375 IeeeValue = (PFP_IEEE_VALUE)&ExceptionRecord->ExceptionInformation[2]; 04376 IeeeValue->Value.Fp32Value.W[0] = ResultValue; 04377 return FALSE; 04378 } 04379 04380 } 04381 04382 // 04383 // Set the destination register value, update the return address, 04384 // and return a value of TRUE. 04385 // 04386 04387 KiSetRegisterValue(ContextBlock->Fd + 32, 04388 ResultValue, 04389 ContextBlock->ExceptionFrame, 04390 ContextBlock->TrapFrame); 04391 04392 TrapFrame->Fir = ContextBlock->BranchAddress; 04393 return TRUE; 04394 } 04395 04396 VOID 04397 KiUnpackDouble ( 04398 IN ULONG Source, 04399 IN PFP_CONTEXT_BLOCK ContextBlock, 04400 OUT PFP_DOUBLE_OPERAND DoubleOperand 04401 ) 04402 04403 /*++ 04404 04405 Routine Description: 04406 04407 This function is called to unpack a double floating value from the 04408 specified source register. 04409 04410 N.B. The unpacked mantissa value is returned with a guard bit and a 04411 round bit on the right and the hidden bit inserted if appropriate. 04412 The format of the returned value is: 04413 04414 <63:55> - zero 04415 <54> - hidden bit 04416 <53:2> - mantissa 04417 <1> - guard bit 04418 <0> - round bit 04419 04420 Arguments: 04421 04422 Source - Supplies the number of the register that contains the operand. 04423 04424 ContextBlock - Supplies a pointer to the emulation context block. 04425 04426 DoubleOperand - Supplies a pointer to a structure that is to receive the 04427 operand value. 04428 04429 Return Value: 04430 04431 None. 04432 04433 --*/ 04434 04435 { 04436 04437 ULONG Value1; 04438 ULONG Value2; 04439 04440 // 04441 // Get the source register value and unpack the sign, exponent, and 04442 // mantissa value. 04443 // 04444 04445 Value1 = KiGetRegisterValue(Source + 32, 04446 ContextBlock->ExceptionFrame, 04447 ContextBlock->TrapFrame); 04448 04449 Value2 = KiGetRegisterValue(Source + 32 + 1, 04450 ContextBlock->ExceptionFrame, 04451 ContextBlock->TrapFrame); 04452 04453 DoubleOperand->Sign = Value2 >> 31; 04454 DoubleOperand->Exponent = (Value2 >> (52 - 32)) & 0x7ff; 04455 DoubleOperand->MantissaHigh = Value2 & 0xfffff; 04456 DoubleOperand->MantissaLow = Value1; 04457 04458 // 04459 // If the exponent is the largest possible value, then the number is 04460 // either a Nan or an infinity. 04461 // 04462 04463 if (DoubleOperand->Exponent == DOUBLE_MAXIMUM_EXPONENT) { 04464 if ((DoubleOperand->MantissaLow | DoubleOperand->MantissaHigh) != 0) { 04465 DoubleOperand->Infinity = FALSE; 04466 DoubleOperand->Nan = TRUE; 04467 04468 } else { 04469 DoubleOperand->Infinity = TRUE; 04470 DoubleOperand->Nan = FALSE; 04471 } 04472 04473 } else { 04474 DoubleOperand->Infinity = FALSE; 04475 DoubleOperand->Nan = FALSE; 04476 if (DoubleOperand->Exponent == DOUBLE_MINIMUM_EXPONENT) { 04477 if ((DoubleOperand->MantissaHigh | DoubleOperand->MantissaLow) != 0) { 04478 DoubleOperand->Exponent += 1; 04479 while ((DoubleOperand->MantissaHigh & (1 << 20)) == 0) { 04480 DoubleOperand->MantissaHigh = 04481 (DoubleOperand->MantissaHigh << 1) | 04482 (DoubleOperand->MantissaLow >> 31); 04483 DoubleOperand->MantissaLow <<= 1; 04484 DoubleOperand->Exponent -= 1; 04485 } 04486 } 04487 04488 } else { 04489 DoubleOperand->MantissaHigh |= (1 << 20); 04490 } 04491 } 04492 04493 // 04494 // Left shift the mantissa 2-bits to provide for a guard bit and a round 04495 // bit. 04496 // 04497 04498 DoubleOperand->MantissaHigh = 04499 (DoubleOperand->MantissaHigh << 2) | (DoubleOperand->MantissaLow >> 30); 04500 DoubleOperand->MantissaLow <<= 2; 04501 return; 04502 } 04503 04504 VOID 04505 KiUnpackSingle ( 04506 IN ULONG Source, 04507 IN PFP_CONTEXT_BLOCK ContextBlock, 04508 OUT PFP_SINGLE_OPERAND SingleOperand 04509 ) 04510 04511 /*++ 04512 04513 Routine Description: 04514 04515 This function is called to unpack a single floating value from the 04516 specified source register. 04517 04518 N.B. The unpacked mantissa value is returned with a guard bit and a 04519 round bit on the right and the hidden bit inserted if appropriate. 04520 The format of the returned value is: 04521 04522 <31:26> - zero 04523 <25> - hidden bit 04524 <24:2> - mantissa 04525 <1> - guard bit 04526 <0> - round bit 04527 04528 Arguments: 04529 04530 Source - Supplies the number of the register that contains the operand. 04531 04532 ContextBlock - Supplies a pointer to the emulation context block. 04533 04534 SingleOperand - Supplies a pointer to a structure that is to receive the 04535 operand value. 04536 04537 Return Value: 04538 04539 None. 04540 04541 --*/ 04542 04543 { 04544 04545 ULONG Value; 04546 04547 // 04548 // Get the source register value and unpack the sign, exponent, and 04549 // mantissa value. 04550 // 04551 04552 Value = KiGetRegisterValue(Source + 32, 04553 ContextBlock->ExceptionFrame, 04554 ContextBlock->TrapFrame); 04555 04556 SingleOperand->Sign = Value >> 31; 04557 SingleOperand->Exponent = (Value >> 23) & 0xff; 04558 SingleOperand->Mantissa = Value & 0x7fffff; 04559 04560 // 04561 // If the exponent is the largest possible value, then the number is 04562 // either a Nan or an infinity. 04563 // 04564 04565 if (SingleOperand->Exponent == SINGLE_MAXIMUM_EXPONENT) { 04566 if (SingleOperand->Mantissa != 0) { 04567 SingleOperand->Infinity = FALSE; 04568 SingleOperand->Nan = TRUE; 04569 04570 } else { 04571 SingleOperand->Infinity = TRUE; 04572 SingleOperand->Nan = FALSE; 04573 } 04574 04575 } else { 04576 SingleOperand->Infinity = FALSE; 04577 SingleOperand->Nan = FALSE; 04578 if (SingleOperand->Exponent == SINGLE_MINIMUM_EXPONENT) { 04579 if (SingleOperand->Mantissa != 0) { 04580 SingleOperand->Exponent += 1; 04581 while ((SingleOperand->Mantissa & (1 << 23)) == 0) { 04582 SingleOperand->Mantissa <<= 1; 04583 SingleOperand->Exponent -= 1; 04584 } 04585 } 04586 04587 } else { 04588 SingleOperand->Mantissa |= (1 << 23); 04589 } 04590 } 04591 04592 // 04593 // Left shift the mantissa 2-bits to provide for a guard bit and a round 04594 // bit. 04595 // 04596 04597 SingleOperand->Mantissa <<= 2; 04598 return; 04599 }

Generated on Sat May 15 19:40:01 2004 for test by doxygen 1.3.7