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

floatem.c File Reference

#include "ki.h"
#include "alphaops.h"

Go to the source code of this file.

Classes

struct  _FP_CONTEXT_BLOCK
struct  _FP_DOUBLE_OPERAND
struct  _FP_SINGLE_OPERAND
struct  _DOUBLE_FORMAT
struct  _SINGLE_FORMAT

Defines

#define DBGPRINT   0 && DbgPrint
#define DBGPRINT2   0 && DbgPrint
#define LOW_PART(Quad)   ((ULONG)(Quad))
#define HIGH_PART(Quad)   ((ULONG)(Quad >> 32))
#define MAKE_QUAD(Low, High)   (((ULONGLONG)(High)) << 32 | ((ULONGLONG)(Low)))
#define CVTST_FUNC_PROPER   0x00E
#define DOUBLE_NAN_BIT_HIGH   (1 << (53 - 32))
#define SINGLE_NAN_BIT   (1 << 24)
#define DoubleSignalNan(DoubleOperand)
#define DoubleQuietNan(DoubleOperand)
#define SingleSignalNan(SingleOperand)
#define SingleQuietNan(SingleOperand)

Typedefs

typedef _FP_CONTEXT_BLOCK FP_CONTEXT_BLOCK
typedef _FP_CONTEXT_BLOCKPFP_CONTEXT_BLOCK
typedef _FP_DOUBLE_OPERAND FP_DOUBLE_OPERAND
typedef _FP_DOUBLE_OPERANDPFP_DOUBLE_OPERAND
typedef _FP_SINGLE_OPERAND FP_SINGLE_OPERAND
typedef _FP_SINGLE_OPERANDPFP_SINGLE_OPERAND
typedef _DOUBLE_FORMAT DOUBLE_FORMAT
typedef _DOUBLE_FORMATPDOUBLE_FORMAT
typedef _SINGLE_FORMAT SINGLE_FORMAT
typedef _SINGLE_FORMATPSINGLE_FORMAT

Functions

ULONGLONG KiConvertSingleOperandToRegister (IN ULONG SingleValue)
ULONG KiConvertRegisterToSingleOperand (IN ULONGLONG DoubleValue)
BOOLEAN KiConvertQuadwordToLongword (IN PFP_CONTEXT_BLOCK ContextBlock, IN LONGLONG Quadword)
BOOLEAN KiDivideByZeroDouble (IN PFP_CONTEXT_BLOCK ContextBlock, IN PFP_DOUBLE_OPERAND DoubleOperand1, IN PFP_DOUBLE_OPERAND DoubleOperand2)
BOOLEAN KiDivideByZeroSingle (IN PFP_CONTEXT_BLOCK ContextBlock, IN PFP_SINGLE_OPERAND SingleOperand1, IN PFP_SINGLE_OPERAND SingleOperand2)
PFP_IEEE_VALUE KiInitializeIeeeValue (IN PEXCEPTION_RECORD ExceptionRecord)
BOOLEAN KiInvalidCompareDouble (IN PFP_CONTEXT_BLOCK ContextBlock, IN BOOLEAN CheckForSignalNan, IN PFP_DOUBLE_OPERAND DoubleOperand1, IN PFP_DOUBLE_OPERAND DoubleOperand2)
BOOLEAN KiInvalidOperationDouble (IN PFP_CONTEXT_BLOCK ContextBlock, IN BOOLEAN CheckForSignalNan, IN PFP_DOUBLE_OPERAND DoubleOperand1, IN PFP_DOUBLE_OPERAND DoubleOperand2)
BOOLEAN KiInvalidOperationQuadword (IN PFP_CONTEXT_BLOCK ContextBlock, IN ULONGLONG ResultValue)
BOOLEAN KiInvalidOperationSingle (IN PFP_CONTEXT_BLOCK ContextBlock, IN BOOLEAN CheckForSignalNan, IN PFP_SINGLE_OPERAND SingleOperand1, IN PFP_SINGLE_OPERAND SingleOperand2)
BOOLEAN KiNormalizeDouble (IN PFP_CONTEXT_BLOCK ContextBlock, IN PFP_DOUBLE_OPERAND ResultOperand, IN ULONGLONG StickyBits)
BOOLEAN KiNormalizeQuadword (IN PFP_CONTEXT_BLOCK ContextBlock, IN PFP_DOUBLE_OPERAND ResultOperand)
BOOLEAN KiNormalizeSingle (IN PFP_CONTEXT_BLOCK ContextBlock, IN PFP_SINGLE_OPERAND ResultOperand, IN ULONG StickyBits)
VOID KiUnpackDouble (IN ULONG Source, IN PFP_CONTEXT_BLOCK ContextBlock, OUT PFP_DOUBLE_OPERAND DoubleOperand)
VOID KiUnpackSingle (IN ULONG Source, IN PFP_CONTEXT_BLOCK ContextBlock, OUT PFP_SINGLE_OPERAND SingleOperand)
BOOLEAN KiEmulateFloating (IN OUT PEXCEPTION_RECORD ExceptionRecord, IN OUT PKEXCEPTION_FRAME ExceptionFrame, IN OUT PKTRAP_FRAME TrapFrame, IN OUT PSW_FPCR SoftwareFpcr)


Define Documentation

#define CVTST_FUNC_PROPER   0x00E
 

Definition at line 109 of file alpha/floatem.c.

Referenced by KiEmulateFloating().

#define DBGPRINT   0 && DbgPrint
 

Definition at line 95 of file alpha/floatem.c.

#define DBGPRINT2   0 && DbgPrint
 

Definition at line 96 of file alpha/floatem.c.

Referenced by KiEmulateFloating().

#define DOUBLE_NAN_BIT_HIGH   (1 << (53 - 32))
 

Definition at line 118 of file alpha/floatem.c.

#define DoubleQuietNan DoubleOperand   ) 
 

Value:

(((DoubleOperand)->Nan != FALSE) && \ (((DoubleOperand)->MantissaHigh & DOUBLE_NAN_BIT_HIGH) != 0))

Definition at line 125 of file alpha/floatem.c.

#define DoubleSignalNan DoubleOperand   ) 
 

Value:

(((DoubleOperand)->Nan != FALSE) && \ (((DoubleOperand)->MantissaHigh & DOUBLE_NAN_BIT_HIGH) == 0))

Definition at line 121 of file alpha/floatem.c.

Referenced by KiInvalidCompareDouble(), and KiInvalidOperationDouble().

#define HIGH_PART Quad   )     ((ULONG)(Quad >> 32))
 

Definition at line 101 of file alpha/floatem.c.

Referenced by KiConvertQuadwordToLongword(), KiInvalidOperationQuadword(), KiNormalizeDouble(), and KiNormalizeQuadword().

#define LOW_PART Quad   )     ((ULONG)(Quad))
 

Definition at line 100 of file alpha/floatem.c.

Referenced by KiConvertQuadwordToLongword(), KiInvalidOperationQuadword(), KiNormalizeDouble(), and KiNormalizeQuadword().

#define MAKE_QUAD Low,
High   )     (((ULONGLONG)(High)) << 32 | ((ULONGLONG)(Low)))
 

Definition at line 102 of file alpha/floatem.c.

Referenced by KiDivideByZeroDouble(), KiInvalidOperationDouble(), KiNormalizeDouble(), and KiNormalizeQuadword().

#define SINGLE_NAN_BIT   (1 << 24)
 

Definition at line 119 of file alpha/floatem.c.

#define SingleQuietNan SingleOperand   ) 
 

Value:

(((SingleOperand)->Nan != FALSE) && \ (((SingleOperand)->Mantissa & SINGLE_NAN_BIT) != 0))

Definition at line 133 of file alpha/floatem.c.

#define SingleSignalNan SingleOperand   ) 
 

Value:

(((SingleOperand)->Nan != FALSE) && \ (((SingleOperand)->Mantissa & SINGLE_NAN_BIT) == 0))

Definition at line 129 of file alpha/floatem.c.

Referenced by KiInvalidOperationSingle().


Typedef Documentation

typedef struct _DOUBLE_FORMAT DOUBLE_FORMAT
 

typedef struct _FP_CONTEXT_BLOCK FP_CONTEXT_BLOCK
 

typedef struct _FP_DOUBLE_OPERAND FP_DOUBLE_OPERAND
 

typedef struct _FP_SINGLE_OPERAND FP_SINGLE_OPERAND
 

typedef struct _DOUBLE_FORMAT * PDOUBLE_FORMAT
 

Referenced by KiConvertRegisterToSingleOperand(), and KiConvertSingleOperandToRegister().

typedef struct _FP_CONTEXT_BLOCK * PFP_CONTEXT_BLOCK
 

typedef struct _FP_DOUBLE_OPERAND * PFP_DOUBLE_OPERAND
 

typedef struct _FP_SINGLE_OPERAND * PFP_SINGLE_OPERAND
 

typedef struct _SINGLE_FORMAT * PSINGLE_FORMAT
 

Referenced by KiConvertRegisterToSingleOperand(), and KiConvertSingleOperandToRegister().

typedef struct _SINGLE_FORMAT SINGLE_FORMAT
 


Function Documentation

BOOLEAN KiConvertQuadwordToLongword IN PFP_CONTEXT_BLOCK  ContextBlock,
IN LONGLONG  Quadword
 

Definition at line 2111 of file alpha/floatem.c.

References FALSE, HIGH_PART, KiInitializeIeeeValue(), KiSetRegisterValue(), LOW_PART, and TRUE.

Referenced by KiEmulateFloating().

02118 : 02119 02120 This function is called to convert a quadword operand to a longword 02121 result. 02122 02123 Arguments: 02124 02125 ContextBlock - Supplies a pointer to the emulation context block. 02126 02127 Operand - Supplies the quadword operand value. 02128 02129 Return Value: 02130 02131 If the quadword value would overflow the longword result and the invalid 02132 trap is enabled then a value of FALSE is returned. Otherwise, the quadword 02133 is truncated to a longword and a value of TRUE is returned. 02134 02135 --*/ 02136 02137 { 02138 PEXCEPTION_RECORD ExceptionRecord; 02139 PFPCR Fpcr; 02140 PFP_IEEE_VALUE IeeeValue; 02141 ULONGLONG ResultValue; 02142 PSW_FPCR SoftwareFpcr; 02143 02144 // 02145 // Truncate the quadword to a longword and convert the longword integer 02146 // to floating register longword integer format. 02147 // 02148 02149 ResultValue = ((Quadword & (ULONGLONG)0xc0000000) << 32) | 02150 ((Quadword & (ULONGLONG)0x3fffffff) << 29); 02151 02152 // 02153 // Check to determine if an exception should be delivered or the result 02154 // should be written to the destination register. 02155 // 02156 02157 if ((Quadword < (LONG)0x80000000) || (Quadword > (LONG)0x7fffffff)) { 02158 Fpcr = (PFPCR)&ContextBlock->TrapFrame->Fpcr; 02159 Fpcr->InvalidOperation = 1; 02160 Fpcr->SummaryBit = 1; 02161 if (ContextBlock->IeeeMode == FALSE) { 02162 ExceptionRecord = ContextBlock->ExceptionRecord; 02163 ExceptionRecord->ExceptionCode = STATUS_FLOAT_INVALID_OPERATION; 02164 return FALSE; 02165 } 02166 SoftwareFpcr = ContextBlock->SoftwareFpcr; 02167 SoftwareFpcr->StatusInvalid = 1; 02168 if (SoftwareFpcr->EnableInvalid != 0) { 02169 ExceptionRecord = ContextBlock->ExceptionRecord; 02170 ExceptionRecord->ExceptionCode = STATUS_FLOAT_INVALID_OPERATION; 02171 IeeeValue = KiInitializeIeeeValue(ExceptionRecord); 02172 IeeeValue->Value.U64Value.LowPart = LOW_PART(ResultValue); 02173 IeeeValue->Value.U64Value.HighPart = HIGH_PART(ResultValue); 02174 return FALSE; 02175 } 02176 02177 Fpcr->DisableInvalid = 1; 02178 } 02179 02180 // 02181 // Set the destination register value and return a value of TRUE. 02182 // 02183 02184 KiSetRegisterValue(ContextBlock->Fc + 32, 02185 ResultValue, 02186 ContextBlock->ExceptionFrame, 02187 ContextBlock->TrapFrame); 02188 return TRUE; 02189 }

ULONG KiConvertRegisterToSingleOperand IN ULONGLONG  DoubleValue  ) 
 

Definition at line 2064 of file alpha/floatem.c.

References _SINGLE_FORMAT::Exponent, _DOUBLE_FORMAT::Exponent, _DOUBLE_FORMAT::Mantissa, _SINGLE_FORMAT::Mantissa, PDOUBLE_FORMAT, PSINGLE_FORMAT, _DOUBLE_FORMAT::Sign, and _SINGLE_FORMAT::Sign.

Referenced by KiUnpackSingle().

02070 : 02071 02072 This function converts the 64-bit, double format floating point value 02073 used within the floating point registers to a 32-bit, single format 02074 floating point value. 02075 02076 Arguments: 02077 02078 DoubleValue - Supplies the 64-bit double operand value as an integer. 02079 02080 Return Value: 02081 02082 The 32-bit register format operand value is returned as the function 02083 value. 02084 02085 --*/ 02086 02087 { 02088 PDOUBLE_FORMAT DoubleFormat; 02089 ULONG Result; 02090 PSINGLE_FORMAT SingleFormat; 02091 02092 SingleFormat = (PSINGLE_FORMAT)&Result; 02093 DoubleFormat = (PDOUBLE_FORMAT)&DoubleValue; 02094 02095 SingleFormat->Sign = (ULONG)DoubleFormat->Sign; 02096 SingleFormat->Mantissa = (ULONG)(DoubleFormat->Mantissa >> (52 - 23)); 02097 if (DoubleFormat->Exponent == DOUBLE_MAXIMUM_EXPONENT) { 02098 SingleFormat->Exponent = SINGLE_MAXIMUM_EXPONENT; 02099 02100 } else if (DoubleFormat->Exponent == DOUBLE_MINIMUM_EXPONENT) { 02101 SingleFormat->Exponent = SINGLE_MINIMUM_EXPONENT; 02102 02103 } else { 02104 SingleFormat->Exponent = (ULONG)(DoubleFormat->Exponent - DOUBLE_EXPONENT_BIAS + 02105 SINGLE_EXPONENT_BIAS); 02106 } 02107 return Result; 02108 }

ULONGLONG KiConvertSingleOperandToRegister IN ULONG  SingleValue  ) 
 

Definition at line 2016 of file alpha/floatem.c.

References _DOUBLE_FORMAT::Exponent, _SINGLE_FORMAT::Exponent, _SINGLE_FORMAT::Mantissa, _DOUBLE_FORMAT::Mantissa, PDOUBLE_FORMAT, PSINGLE_FORMAT, _SINGLE_FORMAT::Sign, and _DOUBLE_FORMAT::Sign.

Referenced by KiDivideByZeroSingle(), KiInvalidOperationSingle(), and KiNormalizeSingle().

02022 : 02023 02024 This function converts a 32-bit single format floating point value to 02025 the 64-bit, double format used within floating point registers. Alpha 02026 floating point registers are 64-bits wide and single format values are 02027 transformed to 64-bits when stored or loaded from memory. 02028 02029 Arguments: 02030 02031 SingleValue - Supplies the 32-bit single operand value as an integer. 02032 02033 Return Value: 02034 02035 The 64-bit register format operand value is returned as the function 02036 value. 02037 02038 --*/ 02039 02040 { 02041 PDOUBLE_FORMAT DoubleFormat; 02042 ULONGLONG Result; 02043 PSINGLE_FORMAT SingleFormat; 02044 02045 SingleFormat = (PSINGLE_FORMAT)&SingleValue; 02046 DoubleFormat = (PDOUBLE_FORMAT)&Result; 02047 02048 DoubleFormat->Sign = SingleFormat->Sign; 02049 DoubleFormat->Mantissa = ((ULONGLONG)SingleFormat->Mantissa) << (52 - 23); 02050 if (SingleFormat->Exponent == SINGLE_MAXIMUM_EXPONENT) { 02051 DoubleFormat->Exponent = DOUBLE_MAXIMUM_EXPONENT; 02052 02053 } else if (SingleFormat->Exponent == SINGLE_MINIMUM_EXPONENT) { 02054 DoubleFormat->Exponent = DOUBLE_MINIMUM_EXPONENT; 02055 02056 } else { 02057 DoubleFormat->Exponent = SingleFormat->Exponent - SINGLE_EXPONENT_BIAS + 02058 DOUBLE_EXPONENT_BIAS; 02059 } 02060 return Result; 02061 }

BOOLEAN KiDivideByZeroDouble IN PFP_CONTEXT_BLOCK  ContextBlock,
IN PFP_DOUBLE_OPERAND  DoubleOperand1,
IN PFP_DOUBLE_OPERAND  DoubleOperand2
 

Definition at line 2192 of file alpha/floatem.c.

References FALSE, KiInitializeIeeeValue(), KiSetRegisterValue(), MAKE_QUAD, and TRUE.

02200 : 02201 02202 This function is called to either raise an exception or store a 02203 quiet NaN or properly signed infinity for a divide by zero double 02204 floating operation. 02205 02206 Arguments: 02207 02208 ContextBlock - Supplies a pointer to the emulation context block. 02209 02210 DoubleOperand1 - Supplies a pointer to the first operand value. 02211 02212 DoubleOperand2 - Supplies a pointer ot the second operand value. 02213 02214 Return Value: 02215 02216 If the divide by zero trap is enabled and the dividend is not infinite, 02217 then a value of FALSE is returned. Otherwise, a quiet NaN or a properly 02218 signed infinity is stored as the destination result and a value of TRUE 02219 is returned. 02220 02221 --*/ 02222 02223 { 02224 02225 PEXCEPTION_RECORD ExceptionRecord; 02226 PFPCR Fpcr; 02227 PFP_IEEE_VALUE IeeeValue; 02228 ULONG ResultSign; 02229 ULONG ResultValueHigh; 02230 ULONG ResultValueLow; 02231 PSW_FPCR SoftwareFpcr; 02232 02233 // 02234 // The result value is a properly signed infinity. 02235 // 02236 02237 ResultSign = DoubleOperand1->Sign ^ DoubleOperand2->Sign; 02238 ResultValueHigh = DOUBLE_INFINITY_VALUE_HIGH | (ResultSign << 31); 02239 ResultValueLow = DOUBLE_INFINITY_VALUE_LOW; 02240 02241 // 02242 // If the first operand is not infinite and the divide by zero trap is 02243 // enabled, then store the proper exception code and exception flags 02244 // and return a value of FALSE. Otherwise, store the appropriately signed 02245 // infinity and return a value of TRUE. 02246 // 02247 02248 if (DoubleOperand1->Infinity == FALSE) { 02249 02250 Fpcr = (PFPCR)&ContextBlock->TrapFrame->Fpcr; 02251 Fpcr->DivisionByZero = 1; 02252 Fpcr->SummaryBit = 1; 02253 if (ContextBlock->IeeeMode == FALSE) { 02254 ExceptionRecord = ContextBlock->ExceptionRecord; 02255 ExceptionRecord->ExceptionCode = STATUS_FLOAT_DIVIDE_BY_ZERO; 02256 return FALSE; 02257 } 02258 SoftwareFpcr = ContextBlock->SoftwareFpcr; 02259 SoftwareFpcr->StatusDivisionByZero = 1; 02260 if (SoftwareFpcr->EnableDivisionByZero != 0) { 02261 ExceptionRecord = ContextBlock->ExceptionRecord; 02262 ExceptionRecord->ExceptionCode = STATUS_FLOAT_DIVIDE_BY_ZERO; 02263 IeeeValue = KiInitializeIeeeValue(ExceptionRecord); 02264 IeeeValue->Value.Fp64Value.W[0] = ResultValueLow; 02265 IeeeValue->Value.Fp64Value.W[1] = ResultValueHigh; 02266 return FALSE; 02267 } 02268 02269 Fpcr->DisableDivisionByZero = 1; 02270 } 02271 02272 KiSetRegisterValue(ContextBlock->Fc + 32, 02273 MAKE_QUAD(ResultValueLow, ResultValueHigh), 02274 ContextBlock->ExceptionFrame, 02275 ContextBlock->TrapFrame); 02276 02277 return TRUE; 02278 }

BOOLEAN KiDivideByZeroSingle IN PFP_CONTEXT_BLOCK  ContextBlock,
IN PFP_SINGLE_OPERAND  SingleOperand1,
IN PFP_SINGLE_OPERAND  SingleOperand2
 

Definition at line 2281 of file alpha/floatem.c.

References FALSE, KiConvertSingleOperandToRegister(), KiInitializeIeeeValue(), KiSetRegisterValue(), and TRUE.

02289 : 02290 02291 This function is called to either raise an exception or store a 02292 quiet NaN or properly signed infinity for a divide by zero single 02293 floating operation. 02294 02295 Arguments: 02296 02297 ContextBlock - Supplies a pointer to the emulation context block. 02298 02299 SingleOperand1 - Supplies a pointer to the first operand value. 02300 02301 SingleOperand2 - Supplies a pointer ot the second operand value. 02302 02303 Return Value: 02304 02305 If the divide by zero trap is enabled and the dividend is not infinite, 02306 then a value of FALSE is returned. Otherwise, a quiet NaN or a properly 02307 signed infinity is stored as the destination result and a value of TRUE 02308 is returned. 02309 02310 --*/ 02311 02312 { 02313 02314 PEXCEPTION_RECORD ExceptionRecord; 02315 PFPCR Fpcr; 02316 PFP_IEEE_VALUE IeeeValue; 02317 ULONG ResultSign; 02318 ULONG ResultValue; 02319 PSW_FPCR SoftwareFpcr; 02320 02321 // 02322 // The result value is a properly signed infinity. 02323 // 02324 02325 ResultSign = SingleOperand1->Sign ^ SingleOperand2->Sign; 02326 ResultValue = SINGLE_INFINITY_VALUE | (ResultSign << 31); 02327 02328 // 02329 // If the first operand is not infinite and the divide by zero trap is 02330 // enabled, then store the proper exception code and exception flags 02331 // and return a value of FALSE. Otherwise, store the appropriately signed 02332 // infinity and return a value of TRUE. 02333 // 02334 02335 if (SingleOperand1->Infinity == FALSE) { 02336 02337 Fpcr = (PFPCR)&ContextBlock->TrapFrame->Fpcr; 02338 Fpcr->DivisionByZero = 1; 02339 Fpcr->SummaryBit = 1; 02340 if (ContextBlock->IeeeMode == FALSE) { 02341 ExceptionRecord = ContextBlock->ExceptionRecord; 02342 ExceptionRecord->ExceptionCode = STATUS_FLOAT_DIVIDE_BY_ZERO; 02343 return FALSE; 02344 } 02345 SoftwareFpcr = ContextBlock->SoftwareFpcr; 02346 SoftwareFpcr->StatusDivisionByZero = 1; 02347 if (SoftwareFpcr->EnableDivisionByZero != 0) { 02348 ExceptionRecord = ContextBlock->ExceptionRecord; 02349 ExceptionRecord->ExceptionCode = STATUS_FLOAT_DIVIDE_BY_ZERO; 02350 IeeeValue = KiInitializeIeeeValue(ExceptionRecord); 02351 IeeeValue->Value.Fp32Value.W[0] = ResultValue; 02352 return FALSE; 02353 } 02354 02355 Fpcr->DisableDivisionByZero = 1; 02356 } 02357 02358 KiSetRegisterValue(ContextBlock->Fc + 32, 02359 KiConvertSingleOperandToRegister(ResultValue), 02360 ContextBlock->ExceptionFrame, 02361 ContextBlock->TrapFrame); 02362 02363 return TRUE; 02364 }

BOOLEAN KiEmulateFloating IN OUT PEXCEPTION_RECORD  ExceptionRecord,
IN OUT PKEXCEPTION_FRAME  ExceptionFrame,
IN OUT PKTRAP_FRAME  TrapFrame,
IN OUT PSW_FPCR  SoftwareFpcr
 

Definition at line 296 of file alpha/floatem.c.

References CVTST_FUNC_PROPER, DBGPRINT, DBGPRINT2, _FP_CONTEXT_BLOCK::ExceptionFrame, _FP_CONTEXT_BLOCK::ExceptionRecord, _FP_DOUBLE_OPERAND::Exponent, _FP_SINGLE_OPERAND::Exponent, FALSE, _FP_CONTEXT_BLOCK::Fc, _FP_CONTEXT_BLOCK::IeeeMode, Index, _FP_SINGLE_OPERAND::Infinity, _FP_DOUBLE_OPERAND::Infinity, KeGetCurrentPrcb, KiConvertQuadwordToLongword(), KiCopyInformation(), KiDivideByZeroDouble(), KiDivideByZeroSingle(), KiGetRegisterValue(), KiInvalidCompareDouble(), KiInvalidOperationDouble(), KiInvalidOperationQuadword(), KiInvalidOperationSingle(), KiNormalizeDouble(), KiNormalizeQuadword(), KiNormalizeSingle(), KiSetRegisterValue(), KiUnpackDouble(), KiUnpackSingle(), _FP_SINGLE_OPERAND::Mantissa, _FP_DOUBLE_OPERAND::MantissaHigh, _FP_DOUBLE_OPERAND::MantissaLow, _FP_DOUBLE_OPERAND::Nan, _FP_SINGLE_OPERAND::Nan, _FP_DOUBLE_OPERAND::Normal, _FP_SINGLE_OPERAND::Normal, _FP_CONTEXT_BLOCK::Round, _FP_DOUBLE_OPERAND::Sign, _FP_SINGLE_OPERAND::Sign, _FP_CONTEXT_BLOCK::SoftwareFpcr, _FP_CONTEXT_BLOCK::TrapFrame, TRUE, and _FP_CONTEXT_BLOCK::UnderflowEnable.

00305 : 00306 00307 This function is called to emulate a floating operation and convert the 00308 exception status to the proper value. If the exception is an unimplemented 00309 operation, then the operation is emulated. Otherwise, the status code is 00310 just converted to its proper value. 00311 00312 Arguments: 00313 00314 ExceptionRecord - Supplies a pointer to an exception record. 00315 00316 ExceptionFrame - Supplies a pointer to an exception frame. 00317 00318 TrapFrame - Supplies a pointer to a trap frame. 00319 00320 SoftwareFpcr - Supplies a pointer to a variable that contains a copy of 00321 the software FPCR. 00322 00323 Return Value: 00324 00325 A value of TRUE is returned if the floating exception is successfully 00326 emulated. Otherwise, a value of FALSE is returned. 00327 00328 --*/ 00329 00330 { 00331 00332 ULARGE_INTEGER AhighBhigh; 00333 ULARGE_INTEGER AhighBlow; 00334 ULARGE_INTEGER AlowBhigh; 00335 ULARGE_INTEGER AlowBlow; 00336 ULONG Carry1; 00337 ULONG Carry2; 00338 BOOLEAN CompareEqual; 00339 BOOLEAN CompareLess; 00340 BOOLEAN CompareResult; 00341 FP_CONTEXT_BLOCK ContextBlock; 00342 LARGE_INTEGER DoubleDividend; 00343 LARGE_INTEGER DoubleDivisor; 00344 ULONG DoubleMantissaLow; 00345 LONG DoubleMantissaHigh; 00346 FP_DOUBLE_OPERAND DoubleOperand1; 00347 FP_DOUBLE_OPERAND DoubleOperand2; 00348 FP_DOUBLE_OPERAND DoubleOperand3; 00349 LARGE_INTEGER DoubleQuotient; 00350 PVOID ExceptionAddress; 00351 ULONG ExponentDifference; 00352 ULONG Fa; 00353 ULONG Fb; 00354 ULONG Function; 00355 ULONG Index; 00356 ALPHA_INSTRUCTION Instruction; 00357 ULARGE_INTEGER LargeResult; 00358 LONG Negation; 00359 LONGLONG Quadword; 00360 LONG SingleMantissa; 00361 FP_SINGLE_OPERAND SingleOperand1; 00362 FP_SINGLE_OPERAND SingleOperand2; 00363 FP_SINGLE_OPERAND SingleOperand3; 00364 ULONG StickyBits; 00365 BOOLEAN ValidOperation; 00366 00367 // 00368 // Save the original exception address in case another exception 00369 // occurs. 00370 // 00371 00372 ExceptionAddress = ExceptionRecord->ExceptionAddress; 00373 00374 // 00375 // Any exception that occurs during the attempted emulation of the 00376 // floating operation causes the emulation to be aborted. The new 00377 // exception code and information is copied to the original exception 00378 // record and a value of FALSE is returned. 00379 // 00380 00381 try { 00382 00383 // 00384 // Fetch the faulting or trapping instruction. Check the opcode and 00385 // function code (including the trap enable bits) for IEEE floating 00386 // point operations that are expected to be emulated. 00387 // 00388 // N.B. Only a subset of the 2048 possible combinations of 11 bits 00389 // in the function field are valid. A total of 88 functions 00390 // are affected by missing plus and minus infinity rounding 00391 // mode support in the EV4 chip. 00392 // 00393 00394 Instruction = *((PALPHA_INSTRUCTION)ExceptionRecord->ExceptionAddress); 00395 DBGPRINT("KiEmulateFloating: Instruction = %.8lx, Fpcr = %.16Lx\n", 00396 Instruction.Long, TrapFrame->Fpcr); 00397 Function = Instruction.FpOp.Function; 00398 00399 ValidOperation = FALSE; 00400 if (Instruction.FpOp.Opcode == IEEEFP_OP) { 00401 00402 // 00403 // Adjust the function code if the instruction is CVTST. 00404 // 00405 00406 if (Function == CVTST_FUNC) { 00407 Function = CVTST_FUNC_PROPER; 00408 00409 } else if (Function == CVTST_S_FUNC) { 00410 Function = CVTST_FUNC_PROPER | FP_TRAP_ENABLE_S; 00411 } 00412 00413 switch (Function & FP_FUNCTION_MASK) { 00414 case ADDS_FUNC : 00415 case SUBS_FUNC : 00416 case MULS_FUNC : 00417 case DIVS_FUNC : 00418 case ADDT_FUNC : 00419 case SUBT_FUNC : 00420 case MULT_FUNC : 00421 case DIVT_FUNC : 00422 case CVTTQ_FUNC : 00423 case CVTTS_FUNC : 00424 00425 switch (Function & FP_TRAP_ENABLE_MASK) { 00426 case FP_TRAP_ENABLE_NONE : 00427 case FP_TRAP_ENABLE_U : 00428 case FP_TRAP_ENABLE_SU : 00429 case FP_TRAP_ENABLE_SUI : 00430 00431 ValidOperation = TRUE; 00432 break; 00433 } 00434 break; 00435 00436 case CVTQS_FUNC : 00437 case CVTQT_FUNC : 00438 00439 switch (Function & FP_TRAP_ENABLE_MASK) { 00440 case FP_TRAP_ENABLE_NONE : 00441 case FP_TRAP_ENABLE_SUI : 00442 00443 ValidOperation = TRUE; 00444 break; 00445 } 00446 break; 00447 00448 case CVTST_FUNC_PROPER : 00449 00450 switch (Function & FP_TRAP_ENABLE_MASK) { 00451 case FP_TRAP_ENABLE_NONE : 00452 case FP_TRAP_ENABLE_S : 00453 00454 ValidOperation = TRUE; 00455 break; 00456 } 00457 break; 00458 00459 case CMPTEQ_FUNC : 00460 case CMPTLE_FUNC : 00461 case CMPTLT_FUNC : 00462 case CMPTUN_FUNC : 00463 00464 ValidOperation = TRUE; 00465 break; 00466 } 00467 00468 } else if (Instruction.FpOp.Opcode == FPOP_OP) { 00469 switch (Function) { 00470 case CVTLQ_FUNC : 00471 case CVTQL_FUNC : 00472 case CVTQLV_FUNC : 00473 case CVTQLSV_FUNC : 00474 00475 ValidOperation = TRUE; 00476 break; 00477 } 00478 } 00479 00480 if (ValidOperation == FALSE) { 00481 00482 // 00483 // An illegal instruction, function code, format value, or trap 00484 // enable value was encountered. Generate an illegal instruction 00485 // exception. 00486 // 00487 00488 ExceptionRecord->ExceptionCode = STATUS_ILLEGAL_INSTRUCTION; 00489 DBGPRINT("KiEmulateFloating: Invalid Function or Format\n"); 00490 return FALSE; 00491 } 00492 00493 // 00494 // Increment the floating emulation count. 00495 // 00496 00497 KeGetCurrentPrcb()->KeFloatingEmulationCount += 1; 00498 00499 // 00500 // Initialize the address of the exception record, exception frame, 00501 // and trap frame in the context block used during the emulation of 00502 // the floating point operation. 00503 // 00504 // N.B. The SoftwareFpcr and IEEE exception records are only used 00505 // with IEEE mode instructions. 00506 // 00507 00508 ContextBlock.ExceptionRecord = ExceptionRecord; 00509 ContextBlock.ExceptionFrame = ExceptionFrame; 00510 ContextBlock.TrapFrame = TrapFrame; 00511 ContextBlock.SoftwareFpcr = SoftwareFpcr; 00512 00513 // 00514 // Check if the /S bit is set in the instruction. This bit is always 00515 // set in the case of a trigger instruction of an asynchronous trap 00516 // (assuming valid trap shadow) but not necessarily always set in the 00517 // case of an unimplemented floating instruction fault. 00518 // 00519 00520 if ((Function & FP_TRAP_ENABLE_S) != 0) { 00521 ContextBlock.IeeeMode = TRUE; 00522 00523 } else { 00524 ContextBlock.IeeeMode = FALSE; 00525 } 00526 00527 if ((Function & FP_TRAP_ENABLE_U) != 0) { 00528 ContextBlock.UnderflowEnable = TRUE; 00529 00530 } else { 00531 ContextBlock.UnderflowEnable = FALSE; 00532 } 00533 00534 // 00535 // Set the current rounding mode from the rounding mode specified in 00536 // the instruction, or if dynamic rounding is specified, from the 00537 // rounding mode specified in the FPCR. 00538 // Set the emulation flag and emulate the floating point operation. 00539 // The return value is dependent on the results of the emulation. 00540 // 00541 00542 ContextBlock.Fc = Instruction.FpOp.Fc; 00543 Fa = Instruction.FpOp.Fa; 00544 Fb = Instruction.FpOp.Fb; 00545 00546 if ((Function & FP_ROUND_MASK) == FP_ROUND_D) { 00547 ContextBlock.Round = ((PFPCR)&TrapFrame->Fpcr)->DynamicRoundingMode; 00548 00549 } else { 00550 ContextBlock.Round = (Function & FP_ROUND_MASK) >> FP_ROUND_SHIFT; 00551 } 00552 00553 SoftwareFpcr->EmulationOccurred = 1; 00554 00555 // 00556 // Unpack operands and dispense with NaNs. 00557 // 00558 00559 switch (Function & FP_FUNCTION_MASK) { 00560 case ADDS_FUNC : 00561 case SUBS_FUNC : 00562 case MULS_FUNC : 00563 case DIVS_FUNC : 00564 00565 // 00566 // The function has two single operand values. 00567 // 00568 00569 KiUnpackSingle(Fa, &ContextBlock, &SingleOperand1); 00570 KiUnpackSingle(Fb, &ContextBlock, &SingleOperand2); 00571 00572 // 00573 // Non-IEEE mode operate instructions trap on NaN, infinity, or 00574 // denormal operands. 00575 // 00576 00577 if ((ContextBlock.IeeeMode == FALSE) && 00578 ((SingleOperand1.Normal == FALSE) || 00579 (SingleOperand2.Normal == FALSE))) { 00580 ExceptionRecord->ExceptionCode = STATUS_FLOAT_INVALID_OPERATION; 00581 return FALSE; 00582 } 00583 00584 if ((SingleOperand1.Nan != FALSE) || (SingleOperand2.Nan != FALSE)) { 00585 00586 // 00587 // Store a quiet NaN if the invalid operation trap 00588 // is disabled, or raise an exception if the invalid 00589 // operation trap is enabled and either of the NaNs 00590 // is a signaling NaN. 00591 // 00592 00593 return KiInvalidOperationSingle(&ContextBlock, 00594 TRUE, 00595 &SingleOperand1, 00596 &SingleOperand2); 00597 } 00598 break; 00599 00600 case ADDT_FUNC : 00601 case SUBT_FUNC : 00602 case MULT_FUNC : 00603 case DIVT_FUNC : 00604 00605 // 00606 // The function has two double operand values. 00607 // 00608 00609 KiUnpackDouble(Fa, &ContextBlock, &DoubleOperand1); 00610 KiUnpackDouble(Fb, &ContextBlock, &DoubleOperand2); 00611 00612 // 00613 // Non-IEEE mode operate instructions trap on NaN, infinity, or 00614 // denormal operands. 00615 // 00616 00617 if ((ContextBlock.IeeeMode == FALSE) && 00618 ((DoubleOperand1.Normal == FALSE) || 00619 (DoubleOperand2.Normal == FALSE))) { 00620 ExceptionRecord->ExceptionCode = STATUS_FLOAT_INVALID_OPERATION; 00621 return FALSE; 00622 } 00623 if ((DoubleOperand1.Nan != FALSE) || (DoubleOperand2.Nan != FALSE)) { 00624 00625 // 00626 // Store a quiet NaN if the invalid operation trap 00627 // is disabled, or raise an exception if the invalid 00628 // operation trap is enabled and either of the NaNs 00629 // is a signaling NaN. 00630 // 00631 00632 return KiInvalidOperationDouble(&ContextBlock, 00633 TRUE, 00634 &DoubleOperand1, 00635 &DoubleOperand2); 00636 } 00637 break; 00638 00639 case CMPTEQ_FUNC : 00640 case CMPTLE_FUNC : 00641 case CMPTLT_FUNC : 00642 case CMPTUN_FUNC : 00643 00644 // 00645 // The function has two double operand values. 00646 // 00647 00648 KiUnpackDouble(Fa, &ContextBlock, &DoubleOperand1); 00649 KiUnpackDouble(Fb, &ContextBlock, &DoubleOperand2); 00650 00651 // 00652 // Non-IEEE mode compare instructions trap on NaN or denormal 00653 // operands. 00654 // 00655 00656 if ((ContextBlock.IeeeMode == FALSE) && 00657 (((DoubleOperand1.Normal == FALSE) && 00658 (DoubleOperand1.Infinity == FALSE)) || 00659 ((DoubleOperand2.Normal == FALSE) && 00660 (DoubleOperand2.Infinity == FALSE)))) { 00661 ExceptionRecord->ExceptionCode = STATUS_FLOAT_INVALID_OPERATION; 00662 return FALSE; 00663 } 00664 00665 // 00666 // Compare operation. 00667 // 00668 // If either operand is a NaN, then check the type of compare 00669 // operation to determine the result value and if an exception 00670 // should be raised. Otherwise, if the operation is a compare 00671 // unordered operation, store a false result. 00672 // 00673 00674 if ((DoubleOperand1.Nan != FALSE) || (DoubleOperand2.Nan != FALSE)) { 00675 00676 // 00677 // If the compare is an unordered compare, then store a true 00678 // result (a NaN compares unordered with everything, including 00679 // itself). Raise an exception if the invalid operation trap 00680 // is enabled and either of the NaNs is a signaling NaN. 00681 // 00682 // Otherwise, if the operation is compare equal, then store a 00683 // false result. Raise an exception if the invalid operation 00684 // trap is enabled and either of the NaNs is a signaling NaN. 00685 // 00686 // Otherwise store a false result and raise an exception if 00687 // the invalid operation trap is enabled. 00688 // 00689 00690 if ((Function & FP_FUNCTION_MASK) == CMPTUN_FUNC) { 00691 KiSetRegisterValue(ContextBlock.Fc + 32, 00692 FP_COMPARE_TRUE, 00693 ExceptionFrame, 00694 TrapFrame); 00695 00696 return KiInvalidCompareDouble(&ContextBlock, 00697 TRUE, 00698 &DoubleOperand1, 00699 &DoubleOperand2); 00700 00701 } else if ((Function & FP_FUNCTION_MASK) == CMPTEQ_FUNC) { 00702 KiSetRegisterValue(ContextBlock.Fc + 32, 00703 FP_COMPARE_FALSE, 00704 ExceptionFrame, 00705 TrapFrame); 00706 00707 return KiInvalidCompareDouble(&ContextBlock, 00708 TRUE, 00709 &DoubleOperand1, 00710 &DoubleOperand2); 00711 00712 } else { 00713 KiSetRegisterValue(ContextBlock.Fc + 32, 00714 FP_COMPARE_FALSE, 00715 ExceptionFrame, 00716 TrapFrame); 00717 00718 return KiInvalidCompareDouble(&ContextBlock, 00719 FALSE, 00720 &DoubleOperand1, 00721 &DoubleOperand2); 00722 } 00723 00724 } else { 00725 if ((Function & FP_FUNCTION_MASK) == CMPTUN_FUNC) { 00726 KiSetRegisterValue(ContextBlock.Fc + 32, 00727 FP_COMPARE_FALSE, 00728 ExceptionFrame, 00729 TrapFrame); 00730 00731 return TRUE; 00732 } 00733 } 00734 break; 00735 00736 case CVTST_FUNC_PROPER : 00737 00738 // 00739 // The function has one single operand value which is found in 00740 // the second operand. 00741 // 00742 00743 KiUnpackSingle(Fb, &ContextBlock, &SingleOperand1); 00744 00745 // 00746 // Non-IEEE mode convert instructions trap on NaN, infinity, or 00747 // denormal operands. 00748 // 00749 00750 if ((ContextBlock.IeeeMode == FALSE) && 00751 (SingleOperand1.Normal == FALSE)) { 00752 ExceptionRecord->ExceptionCode = STATUS_FLOAT_INVALID_OPERATION; 00753 return FALSE; 00754 } 00755 break; 00756 00757 case CVTTQ_FUNC : 00758 case CVTTS_FUNC : 00759 00760 // 00761 // The function has one double operand value which is found in 00762 // the second operand. 00763 // 00764 00765 KiUnpackDouble(Fb, &ContextBlock, &DoubleOperand1); 00766 00767 // 00768 // Non-IEEE mode convert instructions trap on NaN, infinity, or 00769 // denormal operands. 00770 // 00771 00772 if ((ContextBlock.IeeeMode == FALSE) && 00773 (DoubleOperand1.Normal == FALSE)) { 00774 ExceptionRecord->ExceptionCode = STATUS_FLOAT_INVALID_OPERATION; 00775 return FALSE; 00776 } 00777 break; 00778 00779 case CVTLQ_FUNC : 00780 case CVTQL_FUNC : 00781 case CVTQS_FUNC : 00782 case CVTQT_FUNC : 00783 00784 // 00785 // The function has one quadword operand value which is found in 00786 // the second operand. 00787 // 00788 00789 Quadword = KiGetRegisterValue(Fb + 32, 00790 ContextBlock.ExceptionFrame, 00791 ContextBlock.TrapFrame); 00792 break; 00793 } 00794 00795 // 00796 // Case to the proper function routine to emulate the operation. 00797 // 00798 00799 Negation = 0; 00800 switch (Function & FP_FUNCTION_MASK) { 00801 00802 // 00803 // Floating subtract operation. 00804 // 00805 // Floating subtract is accomplished by complementing the sign 00806 // of the second operand and then performing an add operation. 00807 // 00808 00809 case SUBS_FUNC : 00810 DBGPRINT2("subs\n"); 00811 Negation = 0x1; 00812 00813 // 00814 // Floating add operation. 00815 // 00816 // Floating add is accomplished using signed magnitude addition. 00817 // 00818 // The exponent difference is calculated and the smaller number 00819 // is right shifted by the specified amount, but no more than 00820 // the width of the operand values (i.e., 26 for single and 55 00821 // for double). The shifted out value is saved for rounding. 00822 // 00823 // If the signs of the two operands are the same, then they 00824 // are added together after having performed the alignment 00825 // shift. 00826 // 00827 // If the signs of the two operands are different, then the 00828 // sign of the result is the sign of the larger operand and 00829 // the smaller operand is subtracted from the larger operand. 00830 // In order to avoid making a double level test (i.e., one on 00831 // the exponents, and one on the mantissas if the exponents 00832 // are equal), it is possible that the result of the subtract 00833 // could be negative (if the exponents are equal). If this 00834 // occurs, then the result sign and mantissa are complemented 00835 // to obtain the correct result. 00836 // 00837 00838 case ADDS_FUNC : 00839 DBGPRINT2("adds\n"); 00840 00841 // 00842 // Complement the sign of the second operand if the operation 00843 // is subtraction. 00844 // 00845 00846 SingleOperand2.Sign ^= Negation; 00847 00848 // 00849 // Reorder the operands according to their exponent value 00850 // so that Operand1 exponent will be >= Operand2 exponent. 00851 // 00852 00853 if (SingleOperand2.Exponent > SingleOperand1.Exponent) { 00854 SingleOperand3 = SingleOperand2; 00855 SingleOperand2 = SingleOperand1; 00856 SingleOperand1 = SingleOperand3; 00857 } 00858 00859 // 00860 // Compute the exponent difference and shift the smaller 00861 // mantissa right by the difference value or 26 which ever 00862 // is smaller. The bits shifted out are termed the sticky 00863 // bits and are used later in the rounding operation. 00864 // 00865 00866 ExponentDifference = 00867 SingleOperand1.Exponent - SingleOperand2.Exponent; 00868 00869 if (ExponentDifference > 26) { 00870 ExponentDifference = 26; 00871 } 00872 00873 StickyBits = 00874 SingleOperand2.Mantissa & ((1 << ExponentDifference) - 1); 00875 SingleMantissa = SingleOperand2.Mantissa >> ExponentDifference; 00876 00877 // 00878 // If the operands both have the same sign, then perform the 00879 // operation by adding the values together. Otherwise, if the 00880 // operands are not infinity, perform the operation by 00881 // subtracting the second operand from the first operand. 00882 // 00883 00884 if ((SingleOperand1.Sign ^ SingleOperand2.Sign) == 0) { 00885 SingleOperand1.Mantissa += SingleMantissa; 00886 00887 } else { 00888 if ((SingleOperand1.Infinity != FALSE) && 00889 (SingleOperand2.Infinity != FALSE)) { 00890 return KiInvalidOperationSingle(&ContextBlock, 00891 FALSE, 00892 &SingleOperand1, 00893 &SingleOperand2); 00894 00895 } else if (SingleOperand1.Infinity == FALSE) { 00896 if (StickyBits != 0) { 00897 SingleOperand1.Mantissa -= 1; 00898 } 00899 00900 SingleOperand1.Mantissa -= SingleMantissa; 00901 if (SingleOperand1.Mantissa < 0) { 00902 SingleOperand1.Mantissa = -SingleOperand1.Mantissa; 00903 SingleOperand1.Sign ^= 0x1; 00904 } 00905 00906 // 00907 // If the result is exactly zero and the signs of the 00908 // operands differ, then the result is plus zero except 00909 // when the rounding mode is minus infinity. 00910 // 00911 00912 if ((SingleOperand1.Mantissa == 0) && (StickyBits == 0)) { 00913 if (ContextBlock.Round == ROUND_TO_MINUS_INFINITY) { 00914 SingleOperand1.Sign = 0x1; 00915 00916 } else { 00917 SingleOperand1.Sign = 0x0; 00918 } 00919 } 00920 } 00921 } 00922 00923 // 00924 // Normalize and store the result value. 00925 // 00926 00927 return KiNormalizeSingle(&ContextBlock, 00928 &SingleOperand1, 00929 StickyBits); 00930 00931 case SUBT_FUNC : 00932 DBGPRINT2("subt\n"); 00933 Negation = 0x1; 00934 00935 case ADDT_FUNC : 00936 DBGPRINT2("addt\n"); 00937 00938 // 00939 // Complement the sign of the second operand if the operation 00940 // is subtraction. 00941 // 00942 00943 DoubleOperand2.Sign ^= Negation; 00944 00945 // 00946 // Reorder the operands according to their exponent value 00947 // so that Operand1 exponent will be >= Operand2 exponent. 00948 // 00949 00950 if (DoubleOperand2.Exponent > DoubleOperand1.Exponent) { 00951 DoubleOperand3 = DoubleOperand2; 00952 DoubleOperand2 = DoubleOperand1; 00953 DoubleOperand1 = DoubleOperand3; 00954 } 00955 00956 // 00957 // Compute the exponent difference and shift the smaller 00958 // mantissa right by the difference value or 55 which ever 00959 // is smaller. The bits shifted out are termed the sticky 00960 // bits and are used later in the rounding operation. 00961 // 00962 00963 ExponentDifference = 00964 DoubleOperand1.Exponent - DoubleOperand2.Exponent; 00965 00966 if (ExponentDifference > 55) { 00967 ExponentDifference = 55; 00968 } 00969 00970 if (ExponentDifference >= 32) { 00971 ExponentDifference -= 32; 00972 StickyBits = (DoubleOperand2.MantissaLow) | 00973 (DoubleOperand2.MantissaHigh & ((1 << ExponentDifference) - 1)); 00974 00975 DoubleMantissaLow = 00976 DoubleOperand2.MantissaHigh >> ExponentDifference; 00977 00978 DoubleMantissaHigh = 0; 00979 00980 } else if (ExponentDifference > 0) { 00981 StickyBits = 00982 DoubleOperand2.MantissaLow & ((1 << ExponentDifference) - 1); 00983 00984 DoubleMantissaLow = 00985 (DoubleOperand2.MantissaLow >> ExponentDifference) | 00986 (DoubleOperand2.MantissaHigh << (32 - ExponentDifference)); 00987 00988 DoubleMantissaHigh = 00989 DoubleOperand2.MantissaHigh >> ExponentDifference; 00990 00991 } else { 00992 StickyBits = 0; 00993 DoubleMantissaLow = DoubleOperand2.MantissaLow; 00994 DoubleMantissaHigh = DoubleOperand2.MantissaHigh; 00995 } 00996 00997 // 00998 // If the operands both have the same sign, then perform the 00999 // operation by adding the values together. Otherwise, if the 01000 // operands are not infinity, perform the operation by 01001 // subtracting the second operand from the first operand. 01002 // 01003 01004 if ((DoubleOperand1.Sign ^ DoubleOperand2.Sign) == 0) { 01005 DoubleOperand1.MantissaLow += DoubleMantissaLow; 01006 DoubleOperand1.MantissaHigh += DoubleMantissaHigh; 01007 if (DoubleOperand1.MantissaLow < DoubleMantissaLow) { 01008 DoubleOperand1.MantissaHigh += 1; 01009 } 01010 01011 } else { 01012 if ((DoubleOperand1.Infinity != FALSE) && 01013 (DoubleOperand2.Infinity != FALSE)) { 01014 return KiInvalidOperationDouble(&ContextBlock, 01015 FALSE, 01016 &DoubleOperand1, 01017 &DoubleOperand2); 01018 01019 } else if (DoubleOperand1.Infinity == FALSE) { 01020 if (StickyBits != 0) { 01021 if (DoubleOperand1.MantissaLow < 1) { 01022 DoubleOperand1.MantissaHigh -= 1; 01023 } 01024 01025 DoubleOperand1.MantissaLow -= 1; 01026 } 01027 01028 if (DoubleOperand1.MantissaLow < DoubleMantissaLow) { 01029 DoubleOperand1.MantissaHigh -= 1; 01030 } 01031 01032 DoubleOperand1.MantissaLow -= DoubleMantissaLow; 01033 DoubleOperand1.MantissaHigh -= DoubleMantissaHigh; 01034 if (DoubleOperand1.MantissaHigh < 0) { 01035 DoubleOperand1.MantissaLow = -(LONG)DoubleOperand1.MantissaLow; 01036 DoubleOperand1.MantissaHigh = -DoubleOperand1.MantissaHigh; 01037 if (DoubleOperand1.MantissaLow != 0) { 01038 DoubleOperand1.MantissaHigh -= 1; 01039 } 01040 DoubleOperand1.Sign ^= 0x1; 01041 } 01042 01043 // 01044 // If the result is exactly zero and the signs of the 01045 // operands differ, then the result is plus zero except 01046 // when the rounding mode is minus infinity. 01047 // 01048 01049 if ((DoubleOperand1.MantissaHigh == 0) && 01050 (DoubleOperand1.MantissaLow == 0) && 01051 (StickyBits == 0)) { 01052 if (ContextBlock.Round == ROUND_TO_MINUS_INFINITY) { 01053 DoubleOperand1.Sign = 0x1; 01054 01055 } else { 01056 DoubleOperand1.Sign = 0x0; 01057 } 01058 } 01059 } 01060 } 01061 01062 // 01063 // Normalize and store the result value. 01064 // 01065 01066 return KiNormalizeDouble(&ContextBlock, 01067 &DoubleOperand1, 01068 StickyBits); 01069 01070 // 01071 // Floating multiply operation. 01072 // 01073 // Floating multiply is accomplished using unsigned multiplies 01074 // of the mantissa values, and adding the partial results together 01075 // to form the total product. 01076 // 01077 // The two mantissa values are preshifted such that the final 01078 // result is properly aligned. 01079 // 01080 01081 case MULS_FUNC : 01082 DBGPRINT2("muls\n"); 01083 01084 // 01085 // Reorder the operands according to their exponent value 01086 // so that Operand1 exponent will be >= Operand2 exponent. 01087 // 01088 01089 if (SingleOperand2.Exponent > SingleOperand1.Exponent) { 01090 SingleOperand3 = SingleOperand2; 01091 SingleOperand2 = SingleOperand1; 01092 SingleOperand1 = SingleOperand3; 01093 } 01094 01095 // 01096 // If the first operand is infinite and the second operand is 01097 // zero, then an invalid operation is specified. 01098 // 01099 01100 if ((SingleOperand1.Infinity != FALSE) && 01101 (SingleOperand2.Infinity == FALSE) && 01102 (SingleOperand2.Mantissa == 0)) { 01103 return KiInvalidOperationSingle(&ContextBlock, 01104 FALSE, 01105 &SingleOperand1, 01106 &SingleOperand2); 01107 } 01108 01109 // 01110 // Preshift the operand mantissas so the result will be a 01111 // properly aligned 64-bit value and then unsigned multiply 01112 // the two mantissa values. The single result is the high part 01113 // of the 64-bit product and the sticky bits are the low part 01114 // of the 64-bit product. 01115 // 01116 // The size of the product will be (1+23+2)+(1+23+2) = 52 bits 01117 // of which the high (1+1+23+2) = 27 bits are result and the 01118 // remaining 25 bits are sticky. By preshifting the operands 01119 // left 7 bits, the number of sticky bits is 32. This alignment 01120 // is convenient. 01121 // 01122 // The 7 bit preshift amount must be applied in part to both 01123 // operands because 26 of 32 bits of the mantissa are used and 01124 // so neither operand can be safely shifted left by more than 6 01125 // bits. Thus one operand is shifted the maximum of 6 bits and 01126 // the other the remaining 1 bit. 01127 // 01128 01129 LargeResult.QuadPart = ((ULONGLONG)((ULONG)(SingleOperand1.Mantissa << (32 - 26)))) * 01130 ((ULONGLONG)((ULONG)(SingleOperand2.Mantissa << 1))); 01131 01132 SingleOperand1.Mantissa = LargeResult.HighPart; 01133 StickyBits = LargeResult.LowPart; 01134 01135 // 01136 // Compute the sign and exponent of the result. 01137 // 01138 01139 SingleOperand1.Sign ^= SingleOperand2.Sign; 01140 SingleOperand1.Exponent += 01141 SingleOperand2.Exponent - SINGLE_EXPONENT_BIAS; 01142 01143 // 01144 // Normalize and store the result value. 01145 // 01146 01147 return KiNormalizeSingle(&ContextBlock, 01148 &SingleOperand1, 01149 StickyBits); 01150 01151 case MULT_FUNC : 01152 DBGPRINT2("mult\n"); 01153 01154 // 01155 // Reorder the operands according to their exponent value 01156 // so that Operand1 exponent will be >= Operand2 exponent. 01157 // 01158 01159 if (DoubleOperand2.Exponent > DoubleOperand1.Exponent) { 01160 DoubleOperand3 = DoubleOperand2; 01161 DoubleOperand2 = DoubleOperand1; 01162 DoubleOperand1 = DoubleOperand3; 01163 } 01164 01165 // 01166 // If the first operand is infinite and the second operand is 01167 // zero, then an invalid operation is specified. 01168 // 01169 01170 if ((DoubleOperand1.Infinity != FALSE) && 01171 (DoubleOperand2.Infinity == FALSE) && 01172 (DoubleOperand2.MantissaHigh == 0)) { 01173 return KiInvalidOperationDouble(&ContextBlock, 01174 FALSE, 01175 &DoubleOperand1, 01176 &DoubleOperand2); 01177 } 01178 01179 // 01180 // Preshift the operand mantissas so the result will be a 01181 // properly aligned 128-bit value and then unsigned multiply 01182 // the two mantissa values. The double result is the high part 01183 // of the 128-bit product and the sticky bits are the low part 01184 // of the 128-bit product. 01185 // 01186 // The size of the product will be (1+52+2)+(1+52+2) = 110 bits 01187 // of which the high (1+1+52+2) = 56 bits are result and the 01188 // remaining 54 bits are sticky. By preshifting the operands 01189 // left 10 bits, the number of sticky bits is 64. This alignment 01190 // is convenient. 01191 // 01192 // The 10 bit preshift amount must be applied in part to both 01193 // operands because 55 of 64 bits of the mantissa are used and 01194 // so neither operand can be safely shifted left by more than 9 01195 // bits. Thus one operand is shifted the maximum of 9 bits and 01196 // the other the remaining 1 bit. 01197 // 01198 01199 DoubleOperand1.MantissaHigh = 01200 (DoubleOperand1.MantissaHigh << 1) | 01201 (DoubleOperand1.MantissaLow >> 31); 01202 01203 DoubleOperand1.MantissaLow <<= 1; 01204 DoubleOperand2.MantissaHigh = 01205 (DoubleOperand2.MantissaHigh << (64 - 55)) | 01206 (DoubleOperand2.MantissaLow >> (32 - (64 - 55))); 01207 01208 DoubleOperand2.MantissaLow <<= (64 - 55); 01209 01210 // 01211 // The 128-bit product is formed by multiplying and adding 01212 // all the cross product values. 01213 // 01214 // Consider the operands (A and B) as being composed of two 01215 // parts Ahigh, Alow, Bhigh, and Blow. The cross product sum 01216 // is then: 01217 // 01218 // Ahigh * Bhigh * 2^64 + 01219 // Ahigh * Blow * 2^32 + 01220 // Alow * Bhigh * 2^32 + 01221 // Alow * Blow 01222 // 01223 01224 AhighBhigh.QuadPart = (ULONGLONG)(ULONG)DoubleOperand1.MantissaHigh * 01225 (ULONGLONG)(ULONG)DoubleOperand2.MantissaHigh; 01226 01227 AhighBlow.QuadPart = (ULONGLONG)(ULONG)DoubleOperand1.MantissaHigh * 01228 (ULONGLONG)DoubleOperand2.MantissaLow; 01229 01230 AlowBhigh.QuadPart = (ULONGLONG)DoubleOperand1.MantissaLow * 01231 (ULONGLONG)(ULONG)DoubleOperand2.MantissaHigh; 01232 01233 AlowBlow.QuadPart = (ULONGLONG)DoubleOperand1.MantissaLow * 01234 (ULONGLONG)DoubleOperand2.MantissaLow; 01235 01236 AlowBlow.HighPart += AhighBlow.LowPart; 01237 if (AlowBlow.HighPart < AhighBlow.LowPart) { 01238 Carry1 = 1; 01239 01240 } else { 01241 Carry1 = 0; 01242 } 01243 01244 AlowBlow.HighPart += AlowBhigh.LowPart; 01245 if (AlowBlow.HighPart < AlowBhigh.LowPart) { 01246 Carry1 += 1; 01247 } 01248 01249 DoubleOperand1.MantissaLow = AhighBlow.HighPart + Carry1; 01250 if (DoubleOperand1.MantissaLow < Carry1) { 01251 Carry2 = 1; 01252 01253 } else { 01254 Carry2 = 0; 01255 } 01256 01257 DoubleOperand1.MantissaLow += AlowBhigh.HighPart; 01258 if (DoubleOperand1.MantissaLow < AlowBhigh.HighPart) { 01259 Carry2 += 1; 01260 } 01261 01262 DoubleOperand1.MantissaLow += AhighBhigh.LowPart; 01263 if (DoubleOperand1.MantissaLow < AhighBhigh.LowPart) { 01264 Carry2 += 1; 01265 } 01266 01267 DoubleOperand1.MantissaHigh = AhighBhigh.HighPart + Carry2; 01268 StickyBits = AlowBlow.HighPart | AlowBlow.LowPart; 01269 01270 // 01271 // Compute the sign and exponent of the result. 01272 // 01273 01274 DoubleOperand1.Sign ^= DoubleOperand2.Sign; 01275 DoubleOperand1.Exponent += 01276 DoubleOperand2.Exponent - DOUBLE_EXPONENT_BIAS; 01277 01278 // 01279 // Normalize and store the result value. 01280 // 01281 01282 return KiNormalizeDouble(&ContextBlock, 01283 &DoubleOperand1, 01284 StickyBits); 01285 01286 // 01287 // Floating divide operation. 01288 // 01289 // Floating division is accomplished by repeated subtract using 01290 // a single one-bit-at-a-time algorithm. The number of division 01291 // steps performed is equal to the mantissa size plus one guard 01292 // bit. 01293 // 01294 // The sticky bits are the remainder after the specified number 01295 // of division steps. 01296 // 01297 01298 case DIVS_FUNC : 01299 DBGPRINT2("divs\n"); 01300 01301 // 01302 // If the first operand is infinite and the second operand 01303 // is infinite, or both operands are zero, then an invalid 01304 // operation is specified. 01305 // 01306 01307 if (((SingleOperand1.Infinity != FALSE) && 01308 (SingleOperand2.Infinity != FALSE)) || 01309 ((SingleOperand1.Infinity == FALSE) && 01310 (SingleOperand1.Mantissa == 0) && 01311 (SingleOperand2.Infinity == FALSE) && 01312 (SingleOperand2.Mantissa == 0))) { 01313 return KiInvalidOperationSingle(&ContextBlock, 01314 FALSE, 01315 &SingleOperand1, 01316 &SingleOperand2); 01317 } 01318 01319 // 01320 // If the second operand is zero, then a divide by zero 01321 // operation is specified. 01322 // 01323 01324 if ((SingleOperand2.Infinity == FALSE) && 01325 (SingleOperand2.Mantissa == 0)) { 01326 return KiDivideByZeroSingle(&ContextBlock, 01327 &SingleOperand1, 01328 &SingleOperand2); 01329 } 01330 01331 // 01332 // If the first operand is infinite, then the result is 01333 // infinite. Otherwise, if the second operand is infinite, 01334 // then the result is zero (note that both operands cannot 01335 // be infinite). 01336 // 01337 01338 if (SingleOperand1.Infinity != FALSE) { 01339 SingleOperand1.Sign ^= SingleOperand2.Sign; 01340 return KiNormalizeSingle(&ContextBlock, 01341 &SingleOperand1, 01342 0); 01343 01344 } else if (SingleOperand2.Infinity != FALSE) { 01345 SingleOperand1.Sign ^= SingleOperand2.Sign; 01346 SingleOperand1.Exponent = 0; 01347 SingleOperand1.Mantissa = 0; 01348 return KiNormalizeSingle(&ContextBlock, 01349 &SingleOperand1, 01350 0); 01351 } 01352 01353 // 01354 // Perform divide operation by repeating a single bit 01355 // divide step 26 iterations. 01356 // 01357 01358 SingleOperand3.Mantissa = 0; 01359 for (Index = 0; Index < 26; Index += 1) { 01360 SingleOperand3.Mantissa <<= 1; 01361 if (SingleOperand1.Mantissa >= SingleOperand2.Mantissa) { 01362 SingleOperand1.Mantissa -= SingleOperand2.Mantissa; 01363 SingleOperand3.Mantissa |= 1; 01364 } 01365 01366 SingleOperand1.Mantissa <<= 1; 01367 } 01368 01369 // 01370 // Compute the sign and exponent of the result. 01371 // 01372 01373 SingleOperand3.Sign = SingleOperand1.Sign ^ SingleOperand2.Sign; 01374 SingleOperand3.Exponent = SingleOperand1.Exponent - 01375 SingleOperand2.Exponent + SINGLE_EXPONENT_BIAS; 01376 01377 // 01378 // Normalize and store the result value. 01379 // 01380 01381 SingleOperand3.Infinity = FALSE; 01382 SingleOperand3.Nan = FALSE; 01383 return KiNormalizeSingle(&ContextBlock, 01384 &SingleOperand3, 01385 SingleOperand1.Mantissa); 01386 01387 case DIVT_FUNC : 01388 DBGPRINT2("divt\n"); 01389 01390 // 01391 // If the first operand is infinite and the second operand 01392 // is infinite, or both operands are zero, then an invalid 01393 // operation is specified. 01394 // 01395 01396 if (((DoubleOperand1.Infinity != FALSE) && 01397 (DoubleOperand2.Infinity != FALSE)) || 01398 ((DoubleOperand1.Infinity == FALSE) && 01399 (DoubleOperand1.MantissaHigh == 0) && 01400 (DoubleOperand2.Infinity == FALSE) && 01401 (DoubleOperand2.MantissaHigh == 0))) { 01402 return KiInvalidOperationDouble(&ContextBlock, 01403 FALSE, 01404 &DoubleOperand1, 01405 &DoubleOperand2); 01406 } 01407 01408 // 01409 // If the second operand is zero, then a divide by zero 01410 // operation is specified. 01411 // 01412 01413 if ((DoubleOperand2.Infinity == FALSE) && 01414 (DoubleOperand2.MantissaHigh == 0)) { 01415 return KiDivideByZeroDouble(&ContextBlock, 01416 &DoubleOperand1, 01417 &DoubleOperand2); 01418 } 01419 01420 // 01421 // If the first operand is infinite, then the result is 01422 // infinite. Otherwise, if the second operand is infinite, 01423 // then the result is zero (note that both operands cannot 01424 // be infinite). 01425 // 01426 01427 if (DoubleOperand1.Infinity != FALSE) { 01428 DoubleOperand1.Sign ^= DoubleOperand2.Sign; 01429 return KiNormalizeDouble(&ContextBlock, 01430 &DoubleOperand1, 01431 0); 01432 01433 } else if (DoubleOperand2.Infinity != FALSE) { 01434 DoubleOperand1.Sign ^= DoubleOperand2.Sign; 01435 DoubleOperand1.Exponent = 0; 01436 DoubleOperand1.MantissaHigh = 0; 01437 DoubleOperand1.MantissaLow = 0; 01438 return KiNormalizeDouble(&ContextBlock, 01439 &DoubleOperand1, 01440 0); 01441 } 01442 01443 // 01444 // Perform divide operation by repeating a single bit 01445 // divide step 55 iterations. 01446 // 01447 01448 DoubleDividend.LowPart = DoubleOperand1.MantissaLow; 01449 DoubleDividend.HighPart = DoubleOperand1.MantissaHigh; 01450 DoubleDivisor.LowPart = DoubleOperand2.MantissaLow; 01451 DoubleDivisor.HighPart = DoubleOperand2.MantissaHigh; 01452 DoubleQuotient.LowPart = 0; 01453 DoubleQuotient.HighPart = 0; 01454 for (Index = 0; Index < 55; Index += 1) { 01455 DoubleQuotient.HighPart = 01456 (DoubleQuotient.HighPart << 1) | 01457 DoubleQuotient.LowPart >> 31; 01458 01459 DoubleQuotient.LowPart <<= 1; 01460 if (DoubleDividend.QuadPart >= DoubleDivisor.QuadPart) { 01461 DoubleDividend.QuadPart = DoubleDividend.QuadPart - DoubleDivisor.QuadPart; 01462 DoubleQuotient.LowPart |= 1; 01463 } 01464 01465 DoubleDividend.HighPart = 01466 (DoubleDividend.HighPart << 1) | 01467 DoubleDividend.LowPart >> 31; 01468 01469 DoubleDividend.LowPart <<= 1; 01470 } 01471 01472 DoubleOperand3.MantissaLow = DoubleQuotient.LowPart; 01473 DoubleOperand3.MantissaHigh = DoubleQuotient.HighPart; 01474 01475 // 01476 // Compute the sign and exponent of the result. 01477 // 01478 01479 DoubleOperand3.Sign = DoubleOperand1.Sign ^ DoubleOperand2.Sign; 01480 DoubleOperand3.Exponent = DoubleOperand1.Exponent - 01481 DoubleOperand2.Exponent + DOUBLE_EXPONENT_BIAS; 01482 01483 // 01484 // Normalize and store the result value. 01485 // 01486 01487 DoubleOperand3.Infinity = FALSE; 01488 DoubleOperand3.Nan = FALSE; 01489 return KiNormalizeDouble(&ContextBlock, 01490 &DoubleOperand3, 01491 DoubleDividend.LowPart | DoubleDividend.HighPart); 01492 01493 // 01494 // Floating compare double. 01495 // 01496 // This operation is performed after having separated out NaNs, 01497 // and therefore the only comparison predicates left are equal 01498 // and less. 01499 // 01500 // Floating compare double is accomplished by comparing signs, 01501 // then exponents, and finally the mantissa if necessary. 01502 // 01503 // N.B. The sign of zero is ignored. 01504 // 01505 01506 case CMPTEQ_FUNC : 01507 case CMPTLE_FUNC : 01508 case CMPTLT_FUNC : 01509 01510 // 01511 // If either operand is zero, then set the sign of the operand 01512 // positive and the exponent to a value less than the minimum 01513 // denormal number. 01514 // 01515 01516 if ((DoubleOperand1.Infinity == FALSE) && 01517 (DoubleOperand1.MantissaHigh == 0)) { 01518 DoubleOperand1.Sign = 0; 01519 DoubleOperand1.Exponent = -52; 01520 } 01521 01522 if ((DoubleOperand2.Infinity == FALSE) && 01523 (DoubleOperand2.MantissaHigh == 0)) { 01524 DoubleOperand2.Sign = 0; 01525 DoubleOperand2.Exponent = -52; 01526 } 01527 01528 // 01529 // Compare signs first. 01530 // 01531 01532 if (DoubleOperand1.Sign < DoubleOperand2.Sign) { 01533 01534 // 01535 // The first operand is greater than the second operand. 01536 // 01537 01538 CompareEqual = FALSE; 01539 CompareLess = FALSE; 01540 01541 } else if (DoubleOperand1.Sign > DoubleOperand2.Sign) { 01542 01543 // 01544 // The first operand is less than the second operand. 01545 // 01546 01547 CompareEqual = FALSE; 01548 CompareLess = TRUE; 01549 01550 } else { 01551 01552 // 01553 // The operand signs are equal. 01554 // 01555 // If the sign of the operand is negative, then the sense of 01556 // the comparison is reversed. 01557 // 01558 01559 if (DoubleOperand1.Sign == 0) { 01560 01561 // 01562 // Compare positive operand with positive operand. 01563 // 01564 01565 if (DoubleOperand1.Exponent > DoubleOperand2.Exponent) { 01566 CompareEqual = FALSE; 01567 CompareLess = FALSE; 01568 01569 } else if (DoubleOperand1.Exponent < DoubleOperand2.Exponent) { 01570 CompareEqual = FALSE; 01571 CompareLess = TRUE; 01572 01573 } else { 01574 if (DoubleOperand1.MantissaHigh > 01575 DoubleOperand2.MantissaHigh) { 01576 CompareEqual = FALSE; 01577 CompareLess = FALSE; 01578 01579 } else if (DoubleOperand1.MantissaHigh < 01580 DoubleOperand2.MantissaHigh) { 01581 CompareEqual = FALSE; 01582 CompareLess = TRUE; 01583 01584 } else { 01585 if (DoubleOperand1.MantissaLow > 01586 DoubleOperand2.MantissaLow) { 01587 CompareEqual = FALSE; 01588 CompareLess = FALSE; 01589 01590 } else if (DoubleOperand1.MantissaLow < 01591 DoubleOperand2.MantissaLow) { 01592 CompareEqual = FALSE; 01593 CompareLess = TRUE; 01594 01595 } else { 01596 CompareEqual = TRUE; 01597 CompareLess = FALSE; 01598 } 01599 } 01600 } 01601 01602 } else { 01603 01604 // 01605 // Compare negative operand with negative operand. 01606 // 01607 01608 if (DoubleOperand2.Exponent > DoubleOperand1.Exponent) { 01609 CompareEqual = FALSE; 01610 CompareLess = FALSE; 01611 01612 } else if (DoubleOperand2.Exponent < DoubleOperand1.Exponent) { 01613 CompareEqual = FALSE; 01614 CompareLess = TRUE; 01615 01616 } else { 01617 if (DoubleOperand2.MantissaHigh > 01618 DoubleOperand1.MantissaHigh) { 01619 CompareEqual = FALSE; 01620 CompareLess = FALSE; 01621 01622 } else if (DoubleOperand2.MantissaHigh < 01623 DoubleOperand1.MantissaHigh) { 01624 CompareEqual = FALSE; 01625 CompareLess = TRUE; 01626 01627 } else { 01628 if (DoubleOperand2.MantissaLow > 01629 DoubleOperand1.MantissaLow) { 01630 CompareEqual = FALSE; 01631 CompareLess = FALSE; 01632 01633 } else if (DoubleOperand2.MantissaLow < 01634 DoubleOperand1.MantissaLow) { 01635 CompareEqual = FALSE; 01636 CompareLess = TRUE; 01637 01638 } else { 01639 CompareEqual = TRUE; 01640 CompareLess = FALSE; 01641 } 01642 } 01643 } 01644 } 01645 } 01646 01647 // 01648 // Form the condition code result value using the comparison 01649 // information and the compare function codes. 01650 // 01651 01652 switch (Function & FP_FUNCTION_MASK) { 01653 case CMPTEQ_FUNC : 01654 CompareResult = CompareEqual; 01655 DBGPRINT2("cmpteq\n"); 01656 break; 01657 01658 case CMPTLE_FUNC : 01659 CompareResult = (CompareLess | CompareEqual); 01660 DBGPRINT2("cmptle\n"); 01661 break; 01662 01663 case CMPTLT_FUNC : 01664 CompareResult = CompareLess; 01665 DBGPRINT2("cmptlt\n"); 01666 break; 01667 } 01668 01669 // 01670 // Set the result operand to 2.0 if the comparison is true, 01671 // otherwise store 0.0. 01672 // 01673 01674 if (CompareResult != FALSE) { 01675 KiSetRegisterValue(ContextBlock.Fc + 32, 01676 FP_COMPARE_TRUE, 01677 ExceptionFrame, 01678 TrapFrame); 01679 01680 } else { 01681 KiSetRegisterValue(ContextBlock.Fc + 32, 01682 FP_COMPARE_FALSE, 01683 ExceptionFrame, 01684 TrapFrame); 01685 } 01686 return TRUE; 01687 01688 // 01689 // Floating convert single to double. 01690 // 01691 // Floating conversion to double is accomplished by forming a 01692 // double floating operand and then normalizing and storing 01693 // the result value. 01694 // 01695 01696 case CVTST_FUNC_PROPER : 01697 DBGPRINT2("cvtst\n"); 01698 01699 // 01700 // If the operand is a NaN, then store a quiet NaN if the 01701 // invalid operation trap is disabled, or raise an exception 01702 // if the invalid operation trap is enabled and the operand 01703 // is a signaling NaN. 01704 // 01705 01706 if (SingleOperand1.Nan != FALSE) { 01707 DoubleOperand1.MantissaHigh = 01708 SingleOperand1.Mantissa >> (26 - (55 - 32)); 01709 DoubleOperand1.MantissaLow = 01710 SingleOperand1.Mantissa << (32 - (26 - (55 - 32))); 01711 DoubleOperand1.Exponent = DOUBLE_MAXIMUM_EXPONENT; 01712 DoubleOperand1.Sign = SingleOperand1.Sign; 01713 DoubleOperand1.Infinity = FALSE; 01714 DoubleOperand1.Nan = TRUE; 01715 return KiInvalidOperationDouble(&ContextBlock, 01716 TRUE, 01717 &DoubleOperand1, 01718 &DoubleOperand1); 01719 } 01720 01721 // 01722 // Transform the single operand to double format. 01723 // 01724 01725 DoubleOperand1.MantissaHigh = 01726 SingleOperand1.Mantissa >> (26 - (55 - 32)); 01727 DoubleOperand1.MantissaLow = 01728 SingleOperand1.Mantissa << (32 - (26 - (55 - 32))); 01729 DoubleOperand1.Exponent = SingleOperand1.Exponent + 01730 DOUBLE_EXPONENT_BIAS - SINGLE_EXPONENT_BIAS; 01731 DoubleOperand1.Sign = SingleOperand1.Sign; 01732 DoubleOperand1.Infinity = SingleOperand1.Infinity; 01733 DoubleOperand1.Nan = FALSE; 01734 01735 // 01736 // Normalize and store the result value. 01737 // 01738 01739 return KiNormalizeDouble(&ContextBlock, 01740 &DoubleOperand1, 01741 0); 01742 01743 // 01744 // Floating convert double to single. 01745 // 01746 // Floating conversion to single is accomplished by forming a 01747 // single floating operand and then normalizing and storing the 01748 // result value. 01749 // 01750 01751 case CVTTS_FUNC : 01752 DBGPRINT2("cvtts\n"); 01753 01754 // 01755 // If the operand is a NaN, then store a quiet NaN if the 01756 // invalid operation trap is disabled, or raise an exception 01757 // if the invalid operation trap is enabled and the operand 01758 // is a signaling NaN. 01759 // 01760 01761 if (DoubleOperand1.Nan != FALSE) { 01762 SingleOperand1.Mantissa = 01763 (DoubleOperand1.MantissaHigh << (26 - (55 - 32))) | 01764 (DoubleOperand1.MantissaLow >> (32 - (26 - (55 - 32)))); 01765 SingleOperand1.Exponent = SINGLE_MAXIMUM_EXPONENT; 01766 SingleOperand1.Sign = DoubleOperand1.Sign; 01767 SingleOperand1.Infinity = FALSE; 01768 SingleOperand1.Nan = TRUE; 01769 return KiInvalidOperationSingle(&ContextBlock, 01770 TRUE, 01771 &SingleOperand1, 01772 &SingleOperand1); 01773 } 01774 01775 // 01776 // Transform the double operand to single format. 01777 // 01778 01779 SingleOperand1.Mantissa = 01780 (DoubleOperand1.MantissaHigh << (26 - (55 - 32))) | 01781 (DoubleOperand1.MantissaLow >> (32 - (26 - (55 - 32)))); 01782 StickyBits = DoubleOperand1.MantissaLow << (26 - (55 - 32)); 01783 SingleOperand1.Exponent = DoubleOperand1.Exponent + 01784 SINGLE_EXPONENT_BIAS - DOUBLE_EXPONENT_BIAS; 01785 SingleOperand1.Sign = DoubleOperand1.Sign; 01786 SingleOperand1.Infinity = DoubleOperand1.Infinity; 01787 SingleOperand1.Nan = FALSE; 01788 01789 // 01790 // Normalize and store the result value. 01791 // 01792 01793 return KiNormalizeSingle(&ContextBlock, 01794 &SingleOperand1, 01795 StickyBits); 01796 01797 // 01798 // Floating convert longword to quadword. 01799 // 01800 // Floating conversion from longword to quadword is accomplished by 01801 // a repositioning of 32 bits of the operand, with sign extension. 01802 // 01803 01804 case CVTLQ_FUNC : 01805 DBGPRINT2("cvtlq\n"); 01806 01807 // 01808 // Pack floating register longword format into upper 32-bits 01809 // by keeping bits 63..62 and 58..29, eliminating unused bits 01810 // 61..59. Then right justify and sign extend the 32 bits into 01811 // 64 bits. 01812 // 01813 01814 Quadword = ((Quadword >> 62) << 62) | ((ULONGLONG)(Quadword << 5) >> 2); 01815 KiSetRegisterValue(ContextBlock.Fc + 32, 01816 Quadword >> 32, 01817 ExceptionFrame, 01818 TrapFrame); 01819 01820 return TRUE; 01821 01822 // 01823 // Floating convert quadword to longword. 01824 // 01825 // Floating conversion from quadword to longword is accomplished by 01826 // truncating the high order 32 bits of the quadword after checking 01827 // for overflow. 01828 // 01829 01830 case CVTQL_FUNC : 01831 DBGPRINT2("cvtql\n"); 01832 01833 return KiConvertQuadwordToLongword(&ContextBlock, Quadword); 01834 01835 // 01836 // Floating convert quadword to single. 01837 // 01838 // Floating conversion to single is accomplished by forming a 01839 // single floating operand and then normalizing and storing the 01840 // result value. 01841 // 01842 01843 case CVTQS_FUNC : 01844 DBGPRINT2("cvtqs\n"); 01845 01846 // 01847 // Compute the sign of the result. 01848 // 01849 01850 if (Quadword < 0) { 01851 SingleOperand1.Sign = 0x1; 01852 Quadword = -Quadword; 01853 01854 } else { 01855 SingleOperand1.Sign = 0; 01856 } 01857 01858 // 01859 // Initialize the infinity and NaN values. 01860 // 01861 01862 SingleOperand1.Infinity = FALSE; 01863 SingleOperand1.Nan = FALSE; 01864 01865 // 01866 // Compute the exponent value and normalize the quadword 01867 // value. 01868 // 01869 01870 if (Quadword != 0) { 01871 SingleOperand1.Exponent = SINGLE_EXPONENT_BIAS + 63; 01872 while (Quadword > 0) { 01873 Quadword <<= 1; 01874 SingleOperand1.Exponent -= 1; 01875 } 01876 01877 SingleOperand1.Mantissa = (LONG)((ULONGLONG)Quadword >> (64 - 26)); 01878 if (Quadword & (((ULONGLONG)1 << (64 - 26)) - 1)) { 01879 StickyBits = 1; 01880 01881 } else { 01882 StickyBits = 0; 01883 } 01884 01885 } else { 01886 SingleOperand1.Exponent = 0; 01887 SingleOperand1.Mantissa = 0; 01888 StickyBits = 0; 01889 } 01890 01891 // 01892 // Normalize and store the result value. 01893 // 01894 01895 return KiNormalizeSingle(&ContextBlock, 01896 &SingleOperand1, 01897 StickyBits); 01898 01899 // 01900 // Floating convert quadword to double. 01901 // 01902 // Floating conversion to double is accomplished by forming a 01903 // double floating operand and then normalizing and storing the 01904 // result value. 01905 // 01906 01907 case CVTQT_FUNC : 01908 DBGPRINT2("cvtqt\n"); 01909 01910 // 01911 // Compute the sign of the result. 01912 // 01913 01914 if (Quadword < 0) { 01915 DoubleOperand1.Sign = 0x1; 01916 Quadword = -Quadword; 01917 01918 } else { 01919 DoubleOperand1.Sign = 0; 01920 } 01921 01922 // 01923 // Initialize the infinity and NaN values. 01924 // 01925 01926 DoubleOperand1.Infinity = FALSE; 01927 DoubleOperand1.Nan = FALSE; 01928 01929 // 01930 // Compute the exponent value and normalize the quadword 01931 // value. 01932 // 01933 01934 if (Quadword != 0) { 01935 DoubleOperand1.Exponent = DOUBLE_EXPONENT_BIAS + 63; 01936 while (Quadword > 0) { 01937 Quadword <<= 1; 01938 DoubleOperand1.Exponent -= 1; 01939 } 01940 01941 DoubleOperand1.MantissaHigh = (LONG)((ULONGLONG)Quadword >> ((64 - 55) + 32)); 01942 DoubleOperand1.MantissaLow = (LONG)((ULONGLONG)Quadword >> (64 - 55)); 01943 if (Quadword & (((ULONGLONG)1 << (64 - 55)) - 1)) { 01944 StickyBits = 1; 01945 01946 } else { 01947 StickyBits = 0; 01948 } 01949 01950 } else { 01951 DoubleOperand1.MantissaHigh = 0; 01952 DoubleOperand1.MantissaLow = 0; 01953 DoubleOperand1.Exponent = 0; 01954 StickyBits = 0; 01955 } 01956 01957 // 01958 // Normalize and store the result value. 01959 // 01960 01961 return KiNormalizeDouble(&ContextBlock, 01962 &DoubleOperand1, 01963 StickyBits); 01964 01965 // 01966 // Floating convert double to quadword. 01967 // 01968 // Floating conversion to quadword is accomplished by forming 01969 // a quadword value from a double floating value. 01970 // 01971 01972 case CVTTQ_FUNC : 01973 DBGPRINT2("cvttq\n"); 01974 01975 // 01976 // If the operand is infinite or is a NaN, then store a 01977 // quiet NaN or an appropriate infinity if the invalid 01978 // operation trap is disabled, or raise an exception if 01979 // the invalid trap is enabled. 01980 // 01981 01982 if ((DoubleOperand1.Infinity != FALSE) || 01983 (DoubleOperand1.Nan != FALSE)) { 01984 return KiInvalidOperationQuadword(&ContextBlock, 0); 01985 } 01986 01987 // 01988 // Convert double to quadword and store the result value. 01989 // 01990 01991 return KiNormalizeQuadword(&ContextBlock, &DoubleOperand1); 01992 } 01993 01994 // 01995 // If an exception occurs, then copy the new exception information to the 01996 // original exception record and handle the exception. 01997 // 01998 01999 } except (KiCopyInformation(ExceptionRecord, 02000 (GetExceptionInformation())->ExceptionRecord)) { 02001 02002 // 02003 // Preserve the original exception address. 02004 // 02005 02006 ExceptionRecord->ExceptionAddress = ExceptionAddress; 02007 DBGPRINT("KiEmulateFloating: Exception\n"); 02008 return FALSE; 02009 } 02010 02011 DBGPRINT("KiEmulateFloating: Invalid Instruction\n"); 02012 return FALSE; 02013 }

PFP_IEEE_VALUE KiInitializeIeeeValue IN PEXCEPTION_RECORD  ExceptionRecord  ) 
 

Definition at line 2367 of file alpha/floatem.c.

Referenced by KiConvertQuadwordToLongword(), KiDivideByZeroDouble(), KiDivideByZeroSingle(), KiInvalidCompareDouble(), KiInvalidOperationDouble(), KiInvalidOperationQuadword(), KiInvalidOperationSingle(), KiNormalizeDouble(), KiNormalizeQuadword(), and KiNormalizeSingle().

02373 : 02374 02375 This function is called to initialize an IEEE exception record. 02376 02377 N.B. The original hardware exception record should be overwritten with an 02378 IEEE exception record only when it is known for certain that an IEEE 02379 exception must be generated. 02380 02381 Arguments: 02382 02383 ExceptionRecord - Supplies a pointer to the exception record. 02384 02385 Return Value: 02386 02387 The address of the IEEE value portion of the exception record is returned 02388 as the function value. 02389 02390 --*/ 02391 02392 { 02393 02394 // 02395 // Initialize the number of exception information parameters, zero 02396 // the first parameter to indicate a hardware initiated exception, 02397 // set the continuation address, and clear the IEEE exception value. 02398 // 02399 02400 ExceptionRecord->NumberParameters = 6; 02401 ExceptionRecord->ExceptionInformation[0] = 0; 02402 ExceptionRecord->ExceptionInformation[1] = 02403 ((ULONG_PTR)(ExceptionRecord)->ExceptionAddress) + 4; 02404 ExceptionRecord->ExceptionInformation[2] = 0; 02405 ExceptionRecord->ExceptionInformation[3] = 0; 02406 ExceptionRecord->ExceptionInformation[4] = 0; 02407 ExceptionRecord->ExceptionInformation[5] = 0; 02408 02409 // 02410 // Return address of IEEE exception value. 02411 // 02412 02413 return (PFP_IEEE_VALUE)&ExceptionRecord->ExceptionInformation[2]; 02414 }

BOOLEAN KiInvalidCompareDouble IN PFP_CONTEXT_BLOCK  ContextBlock,
IN BOOLEAN  CheckForSignalNan,
IN PFP_DOUBLE_OPERAND  DoubleOperand1,
IN PFP_DOUBLE_OPERAND  DoubleOperand2
 

Definition at line 2417 of file alpha/floatem.c.

References DoubleSignalNan, FALSE, KiInitializeIeeeValue(), and TRUE.

02426 : 02427 02428 This function is called to determine whether an invalid operation 02429 exception should be raised for a double compare operation. 02430 02431 Arguments: 02432 02433 ContextBlock - Supplies a pointer to the emulation context block. 02434 02435 CheckForSignalNan - Supplies a boolean value that determines whether the 02436 operand values should be checked for a signaling NaN. 02437 02438 DoubleOperand1 - Supplies a pointer to the first operand value. 02439 02440 DoubleOperand2 - Supplies a pointer ot the second operand value. 02441 02442 Return Value: 02443 02444 If the invalid operation trap is enabled and either the operation is 02445 invalid or one of the operands in a signaling NaN, then a value of 02446 FALSE is returned. Otherwise, no operation is performed and a value 02447 of TRUE is returned. 02448 02449 --*/ 02450 02451 { 02452 02453 PEXCEPTION_RECORD ExceptionRecord; 02454 PFPCR Fpcr; 02455 PFP_IEEE_VALUE IeeeValue; 02456 PSW_FPCR SoftwareFpcr; 02457 02458 // 02459 // If an invalid operation is specified or one of the operands is a 02460 // signaling NaN and the invalid operation trap is enabled, then 02461 // store the proper exception code and exception flags and return 02462 // a value of FALSE. Otherwise, perform no operation and return a 02463 // value of TRUE. 02464 // 02465 02466 if ((CheckForSignalNan == FALSE) || 02467 (DoubleSignalNan(DoubleOperand1) != FALSE) || 02468 (DoubleSignalNan(DoubleOperand2) != FALSE)) { 02469 02470 Fpcr = (PFPCR)&ContextBlock->TrapFrame->Fpcr; 02471 Fpcr->InvalidOperation = 1; 02472 Fpcr->SummaryBit = 1; 02473 if (ContextBlock->IeeeMode == FALSE) { 02474 ExceptionRecord = ContextBlock->ExceptionRecord; 02475 ExceptionRecord->ExceptionCode = STATUS_FLOAT_INVALID_OPERATION; 02476 return FALSE; 02477 } 02478 SoftwareFpcr = ContextBlock->SoftwareFpcr; 02479 SoftwareFpcr->StatusInvalid = 1; 02480 if (SoftwareFpcr->EnableInvalid != 0) { 02481 ExceptionRecord = ContextBlock->ExceptionRecord; 02482 ExceptionRecord->ExceptionCode = STATUS_FLOAT_INVALID_OPERATION; 02483 IeeeValue = KiInitializeIeeeValue(ExceptionRecord); 02484 IeeeValue->Value.CompareValue = FpCompareUnordered; 02485 return FALSE; 02486 } 02487 02488 Fpcr->DisableInvalid = 1; 02489 } 02490 02491 return TRUE; 02492 }

BOOLEAN KiInvalidOperationDouble IN PFP_CONTEXT_BLOCK  ContextBlock,
IN BOOLEAN  CheckForSignalNan,
IN PFP_DOUBLE_OPERAND  DoubleOperand1,
IN PFP_DOUBLE_OPERAND  DoubleOperand2
 

Definition at line 2495 of file alpha/floatem.c.

References DBGPRINT, DoubleSignalNan, FALSE, KiInitializeIeeeValue(), KiSetRegisterValue(), MAKE_QUAD, and TRUE.

02504 : 02505 02506 This function is called to either raise an exception or store a 02507 quiet NaN for an invalid double floating operation. 02508 02509 Arguments: 02510 02511 ContextBlock - Supplies a pointer to the emulation context block. 02512 02513 CheckForSignalNan - Supplies a boolean value that determines whether the 02514 operand values should be checked for a signaling NaN. 02515 02516 DoubleOperand1 - Supplies a pointer to the first operand value. 02517 02518 DoubleOperand2 - Supplies a pointer ot the second operand value. 02519 02520 Return Value: 02521 02522 If the invalid operation trap is enabled and either the operation is 02523 invalid or one of the operands in a signaling NaN, then a value of 02524 FALSE is returned. Otherwise, a quiet NaN is stored as the destination 02525 result and a value of TRUE is returned. 02526 02527 --*/ 02528 02529 { 02530 02531 PEXCEPTION_RECORD ExceptionRecord; 02532 PFPCR Fpcr; 02533 PFP_IEEE_VALUE IeeeValue; 02534 ULONG ResultValueHigh; 02535 ULONG ResultValueLow; 02536 PSW_FPCR SoftwareFpcr; 02537 02538 // 02539 // If the second operand is a NaN, then compute a quiet NaN from its 02540 // value. Otherwise, if the first operand is a NaN, then compute a 02541 // quiet NaN from its value. Otherwise, the result value is a quiet 02542 // (real indefinite) NaN. 02543 // 02544 02545 DBGPRINT("Operand1: Inf=%d NaN=%d Sign=%d Exponent=%d Mantissa=%.8x%.8x\n", 02546 DoubleOperand1->Infinity, DoubleOperand1->Nan, 02547 DoubleOperand1->Sign, 02548 DoubleOperand1->Exponent, 02549 DoubleOperand1->MantissaHigh, DoubleOperand1->MantissaLow); 02550 DBGPRINT("Operand2: Inf=%d NaN=%d Sign=%d Exponent=%d Mantissa=%.8x%.8x\n", 02551 DoubleOperand2->Infinity, DoubleOperand2->Nan, 02552 DoubleOperand2->Sign, 02553 DoubleOperand2->Exponent, 02554 DoubleOperand2->MantissaHigh, DoubleOperand2->MantissaLow); 02555 02556 if (DoubleOperand2->Nan != FALSE) { 02557 ResultValueLow = DoubleOperand2->MantissaLow >> 2; 02558 ResultValueLow |= DoubleOperand2->MantissaHigh << 30; 02559 ResultValueHigh = DoubleOperand2->MantissaHigh >> 2; 02560 ResultValueHigh |= DOUBLE_QUIET_NAN_PREFIX_HIGH; 02561 ResultValueHigh |= DoubleOperand2->Sign << 31; 02562 02563 } else if (DoubleOperand1->Nan != FALSE) { 02564 ResultValueLow = DoubleOperand1->MantissaLow >> 2; 02565 ResultValueLow |= DoubleOperand1->MantissaHigh << 30; 02566 ResultValueHigh = DoubleOperand1->MantissaHigh >> 2; 02567 ResultValueHigh |= DOUBLE_QUIET_NAN_PREFIX_HIGH; 02568 ResultValueHigh |= DoubleOperand1->Sign << 31; 02569 02570 } else { 02571 ResultValueLow = DOUBLE_QUIET_NAN_VALUE_LOW; 02572 ResultValueHigh = DOUBLE_QUIET_NAN_VALUE_HIGH; 02573 } 02574 02575 // 02576 // If an invalid operation is specified or one of the operands is a 02577 // signaling NaN and the invalid operation trap is enabled, then 02578 // store the proper exception code and exception flags and return 02579 // a value of FALSE. Otherwise, store a quiet NaN as the destination 02580 // result and return a value of TRUE. 02581 // 02582 02583 if ((CheckForSignalNan == FALSE) || 02584 (DoubleSignalNan(DoubleOperand1) != FALSE) || 02585 (DoubleSignalNan(DoubleOperand2) != FALSE)) { 02586 02587 Fpcr = (PFPCR)&ContextBlock->TrapFrame->Fpcr; 02588 Fpcr->InvalidOperation = 1; 02589 Fpcr->SummaryBit = 1; 02590 if (ContextBlock->IeeeMode == FALSE) { 02591 ExceptionRecord = ContextBlock->ExceptionRecord; 02592 ExceptionRecord->ExceptionCode = STATUS_FLOAT_INVALID_OPERATION; 02593 return FALSE; 02594 } 02595 SoftwareFpcr = ContextBlock->SoftwareFpcr; 02596 SoftwareFpcr->StatusInvalid = 1; 02597 if (SoftwareFpcr->EnableInvalid != 0) { 02598 ExceptionRecord = ContextBlock->ExceptionRecord; 02599 ExceptionRecord->ExceptionCode = STATUS_FLOAT_INVALID_OPERATION; 02600 IeeeValue = KiInitializeIeeeValue(ExceptionRecord); 02601 IeeeValue->Value.Fp64Value.W[0] = ResultValueLow; 02602 IeeeValue->Value.Fp64Value.W[1] = ResultValueHigh; 02603 return FALSE; 02604 } 02605 02606 Fpcr->DisableInvalid = 1; 02607 } 02608 02609 KiSetRegisterValue(ContextBlock->Fc + 32, 02610 MAKE_QUAD(ResultValueLow, ResultValueHigh), 02611 ContextBlock->ExceptionFrame, 02612 ContextBlock->TrapFrame); 02613 02614 return TRUE; 02615 }

BOOLEAN KiInvalidOperationQuadword IN PFP_CONTEXT_BLOCK  ContextBlock,
IN ULONGLONG  ResultValue
 

Definition at line 2618 of file alpha/floatem.c.

References FALSE, HIGH_PART, KiInitializeIeeeValue(), KiSetRegisterValue(), LOW_PART, and TRUE.

02625 : 02626 02627 This function is called to either raise an exception or store a 02628 quiet NaN for an invalid conversion to quadword. 02629 02630 Arguments: 02631 02632 ContextBlock - Supplies a pointer to the emulation context block. 02633 02634 ResultValue - Suplies a quadword result value to be stored. 02635 02636 Return Value: 02637 02638 If the invalid operation trap is enabled, then a value of FALSE is 02639 returned. Otherwise, an appropriate quadword value is stored as the 02640 destination result and a value of TRUE is returned. 02641 02642 --*/ 02643 02644 { 02645 02646 PEXCEPTION_RECORD ExceptionRecord; 02647 PFPCR Fpcr; 02648 PFP_IEEE_VALUE IeeeValue; 02649 PSW_FPCR SoftwareFpcr; 02650 02651 // 02652 // If the invalid operation trap is enabled then store the proper 02653 // exception code and exception flags and return a value of FALSE. 02654 // Otherwise, store a quiet NaN as the destination result and return 02655 // a value of TRUE. 02656 // 02657 02658 Fpcr = (PFPCR)&ContextBlock->TrapFrame->Fpcr; 02659 Fpcr->InvalidOperation = 1; 02660 Fpcr->SummaryBit = 1; 02661 if (ContextBlock->IeeeMode == FALSE) { 02662 ExceptionRecord = ContextBlock->ExceptionRecord; 02663 ExceptionRecord->ExceptionCode = STATUS_FLOAT_INVALID_OPERATION; 02664 return FALSE; 02665 } 02666 SoftwareFpcr = ContextBlock->SoftwareFpcr; 02667 SoftwareFpcr->StatusInvalid = 1; 02668 if (SoftwareFpcr->EnableInvalid != 0) { 02669 ExceptionRecord = ContextBlock->ExceptionRecord; 02670 ExceptionRecord->ExceptionCode = STATUS_FLOAT_INVALID_OPERATION; 02671 IeeeValue = KiInitializeIeeeValue(ExceptionRecord); 02672 IeeeValue->Value.U64Value.LowPart = LOW_PART(ResultValue); 02673 IeeeValue->Value.U64Value.HighPart = HIGH_PART(ResultValue); 02674 return FALSE; 02675 } 02676 02677 Fpcr->DisableInvalid = 1; 02678 02679 KiSetRegisterValue(ContextBlock->Fc + 32, 02680 ResultValue, 02681 ContextBlock->ExceptionFrame, 02682 ContextBlock->TrapFrame); 02683 02684 return TRUE; 02685 }

BOOLEAN KiInvalidOperationSingle IN PFP_CONTEXT_BLOCK  ContextBlock,
IN BOOLEAN  CheckForSignalNan,
IN PFP_SINGLE_OPERAND  SingleOperand1,
IN PFP_SINGLE_OPERAND  SingleOperand2
 

Definition at line 2688 of file alpha/floatem.c.

References FALSE, KiConvertSingleOperandToRegister(), KiInitializeIeeeValue(), KiSetRegisterValue(), SINGLE_QUIET_NAN_PREFIX, SingleSignalNan, and TRUE.

02697 : 02698 02699 This function is called to either raise an exception or store a 02700 quiet NaN for an invalid single floating operation. 02701 02702 Arguments: 02703 02704 ContextBlock - Supplies a pointer to the emulation context block. 02705 02706 CheckForSignalNan - Supplies a boolean value that determines whether the 02707 operand values should be checked for a signaling NaN. 02708 02709 SingleOperand1 - Supplies a pointer to the first operand value. 02710 02711 SingleOperand2 - Supplies a pointer ot the second operand value. 02712 02713 Return Value: 02714 02715 If the invalid operation trap is enabled and either the operation is 02716 invalid or one of the operands in a signaling NaN, then a value of 02717 FALSE is returned. Otherwise, a quiet NaN is stored as the destination 02718 result and a value of TRUE is returned. 02719 02720 --*/ 02721 02722 { 02723 02724 PEXCEPTION_RECORD ExceptionRecord; 02725 PFPCR Fpcr; 02726 PFP_IEEE_VALUE IeeeValue; 02727 ULONG ResultValue; 02728 PSW_FPCR SoftwareFpcr; 02729 02730 // 02731 // If the second operand is a NaN, then compute a quiet NaN from its 02732 // value. Otherwise, if the first operand is a NaN, then compute a 02733 // quiet NaN from its value. Otherwise, the result value is a quiet 02734 // (real indefinite) NaN. 02735 // 02736 02737 if (SingleOperand2->Nan != FALSE) { 02738 ResultValue = SingleOperand2->Mantissa >> 2; 02739 ResultValue |= SINGLE_QUIET_NAN_PREFIX; 02740 ResultValue |= SingleOperand2->Sign << 31; 02741 02742 } else if (SingleOperand1->Nan != FALSE) { 02743 ResultValue = SingleOperand1->Mantissa >> 2; 02744 ResultValue |= SINGLE_QUIET_NAN_PREFIX; 02745 ResultValue |= SingleOperand1->Sign << 31; 02746 02747 } else { 02748 ResultValue = SINGLE_QUIET_NAN_VALUE; 02749 } 02750 02751 // 02752 // If an invalid operation is specified or one of the operands is a 02753 // signaling NaN and the invalid operation trap is enabled, then 02754 // store the proper exception code and exception flags and return 02755 // a value of FALSE. Otherwise, store a quiet NaN as the destination 02756 // result and return a value of TRUE. 02757 // 02758 02759 if ((CheckForSignalNan == FALSE) || 02760 (SingleSignalNan(SingleOperand1) != FALSE) || 02761 (SingleSignalNan(SingleOperand2) != FALSE)) { 02762 02763 Fpcr = (PFPCR)&ContextBlock->TrapFrame->Fpcr; 02764 Fpcr->InvalidOperation = 1; 02765 Fpcr->SummaryBit = 1; 02766 if (ContextBlock->IeeeMode == FALSE) { 02767 ExceptionRecord = ContextBlock->ExceptionRecord; 02768 ExceptionRecord->ExceptionCode = STATUS_FLOAT_INVALID_OPERATION; 02769 return FALSE; 02770 } 02771 SoftwareFpcr = ContextBlock->SoftwareFpcr; 02772 SoftwareFpcr->StatusInvalid = 1; 02773 if (SoftwareFpcr->EnableInvalid != 0) { 02774 ExceptionRecord = ContextBlock->ExceptionRecord; 02775 ExceptionRecord->ExceptionCode = STATUS_FLOAT_INVALID_OPERATION; 02776 IeeeValue = KiInitializeIeeeValue(ExceptionRecord); 02777 IeeeValue->Value.Fp32Value.W[0] = ResultValue; 02778 return FALSE; 02779 } 02780 02781 Fpcr->DisableInvalid = 1; 02782 } 02783 02784 KiSetRegisterValue(ContextBlock->Fc + 32, 02785 KiConvertSingleOperandToRegister(ResultValue), 02786 ContextBlock->ExceptionFrame, 02787 ContextBlock->TrapFrame); 02788 02789 return TRUE; 02790 }

BOOLEAN KiNormalizeDouble IN PFP_CONTEXT_BLOCK  ContextBlock,
IN PFP_DOUBLE_OPERAND  ResultOperand,
IN ULONGLONG  StickyBits
 

Definition at line 2793 of file alpha/floatem.c.

References DBGPRINT, FALSE, HIGH_PART, KiInitializeIeeeValue(), KiSetRegisterValue(), LOW_PART, MAKE_QUAD, and TRUE.

02801 : 02802 02803 This function is called to normalize a double floating result. 02804 02805 N.B. The result value is specified with a guard bit on the right, 02806 the hidden bit (if appropriate), and a possible overflow bit. 02807 The result format is: 02808 02809 <63:56> - zero 02810 <55> - overflow bit 02811 <54> - hidden bit 02812 <53:2> - mantissa 02813 <1> - guard bit 02814 <0> - round bit 02815 02816 The sticky bits specify bits that were lost during the computation. 02817 02818 Arguments: 02819 02820 ContextBlock - Supplies a pointer to the emulation context block. 02821 02822 ResultOperand - Supplies a pointer to the result operand value. 02823 02824 StickyBits - Supplies the value of the sticky bits. 02825 02826 Return Value: 02827 02828 If there is not an exception, or the exception is handled, then a proper 02829 result is stored in the destination result, the continuation address is 02830 set, and a value of TRUE is returned. Otherwise, a proper value is stored and 02831 a value of FALSE is returned. 02832 02833 --*/ 02834 02835 { 02836 02837 ULONGLONG DenormalizeShift; 02838 PEXCEPTION_RECORD ExceptionRecord; 02839 ULONGLONG ExceptionResult; 02840 PFPCR Fpcr; 02841 PFP_IEEE_VALUE IeeeValue; 02842 BOOLEAN Inexact; 02843 ULONGLONG Mantissa; 02844 BOOLEAN Overflow; 02845 ULONGLONG ResultValue; 02846 ULONG RoundBit; 02847 PSW_FPCR SoftwareFpcr; 02848 BOOLEAN Underflow; 02849 ULONGLONG ResultStickyBits; 02850 ULONGLONG ResultMantissa; 02851 ULONG ResultRoundBit; 02852 LONG ResultExponent; 02853 BOOLEAN ReturnValue = TRUE; 02854 02855 // 02856 // If the result is infinite, then store a properly signed infinity 02857 // in the destination register and return a value of TRUE. Otherwise, 02858 // round and normalize the result and check for overflow and underflow. 02859 // 02860 02861 DBGPRINT("KiNormalizeDouble: Inf=%d NaN=%d Sign=%d Exponent=%d Mantissa=%.8x%.8x\n", 02862 ResultOperand->Infinity, ResultOperand->Nan, ResultOperand->Sign, 02863 ResultOperand->Exponent, 02864 ResultOperand->MantissaHigh, ResultOperand->MantissaLow); 02865 DBGPRINT("KiNormalizeDouble: StickyBits=%.16Lx\n", StickyBits); 02866 02867 if (ResultOperand->Infinity != FALSE) { 02868 KiSetRegisterValue(ContextBlock->Fc + 32, 02869 MAKE_QUAD(DOUBLE_INFINITY_VALUE_LOW, 02870 DOUBLE_INFINITY_VALUE_HIGH | 02871 (ResultOperand->Sign << 31)), 02872 ContextBlock->ExceptionFrame, 02873 ContextBlock->TrapFrame); 02874 02875 return TRUE; 02876 } 02877 02878 Mantissa = MAKE_QUAD(ResultOperand->MantissaLow, 02879 ResultOperand->MantissaHigh); 02880 Fpcr = (PFPCR)&ContextBlock->TrapFrame->Fpcr; 02881 SoftwareFpcr = ContextBlock->SoftwareFpcr; 02882 02883 // 02884 // If the overflow bit is set, then right shift the mantissa one bit, 02885 // accumulate the lost bit with the sticky bits, and adjust the exponent 02886 // value. 02887 // 02888 02889 if ((Mantissa & ((ULONGLONG)1 << 55)) != 0) { 02890 StickyBits |= (Mantissa & 0x1); 02891 Mantissa >>= 1; 02892 ResultOperand->Exponent += 1; 02893 } 02894 02895 // 02896 // If the mantissa is nonzero, then normalize the mantissa by left 02897 // shifting one bit at a time until there is a one bit in bit 54. 02898 // 02899 02900 if (Mantissa != 0) { 02901 while ((Mantissa & ((ULONGLONG)1 << 54)) == 0) { 02902 Mantissa <<= 1; 02903 ResultOperand->Exponent -= 1; 02904 } 02905 } 02906 02907 // 02908 // Right shift the mantissa two bits, set the round bit, and accumulate 02909 // the other lost bit with the sticky bits. 02910 // 02911 02912 StickyBits |= (Mantissa & 0x1); 02913 RoundBit = (ULONG)(Mantissa & 0x2); 02914 Mantissa >>= 2; 02915 02916 // 02917 // Convert to denormal format before rounding to allow underflow to 02918 // be detected on rounded result. Save context to calculate IEEE 02919 // exception record, if needed. 02920 // 02921 02922 if (ResultOperand->Exponent <= DOUBLE_MINIMUM_EXPONENT && Mantissa != 0) { 02923 02924 // 02925 // Save everything needed for calculating IEEE exception record value 02926 // 02927 02928 ResultMantissa = Mantissa; 02929 ResultExponent = ResultOperand->Exponent; 02930 ResultStickyBits = StickyBits; 02931 ResultRoundBit = RoundBit; 02932 02933 // 02934 // Right shift the mantissa to set the minimum exponent plus an extra 02935 // bit for the denormal format 02936 // 02937 02938 DenormalizeShift = 1 - ResultOperand->Exponent; 02939 02940 // 02941 // The maximum denormal shift is 52 bits for the mantissa plus 1 bit for the round 02942 // A denormal shift of 54 guarantees 0 mantissa and 0 round bit and preserves all sticky bits 02943 // 02944 02945 if (DenormalizeShift > 54) { 02946 DenormalizeShift = 54; 02947 } 02948 02949 // 02950 // The denormalized result will be rounded after it is 02951 // shifted. Preserve existing Round and Sticky Bits. 02952 // 02953 02954 StickyBits |= RoundBit; 02955 StickyBits |= (Mantissa << 1) << (64 - DenormalizeShift); 02956 RoundBit = (ULONG)(Mantissa >> (DenormalizeShift - 1)) & 1; 02957 Mantissa = Mantissa >> DenormalizeShift; 02958 ResultOperand->Exponent = DOUBLE_MINIMUM_EXPONENT; 02959 } 02960 02961 // 02962 // Round the result value using the mantissa, the round bit, and the sticky bits. 02963 // 02964 02965 switch (ContextBlock->Round) { 02966 02967 // 02968 // Round to nearest representable number. 02969 // 02970 02971 case ROUND_TO_NEAREST: 02972 if (RoundBit != 0) { 02973 if ((StickyBits != 0) || ((Mantissa & 0x1) != 0)) { 02974 Mantissa += 1; 02975 } 02976 } 02977 break; 02978 02979 // 02980 // Round toward zero. 02981 // 02982 02983 case ROUND_TO_ZERO: 02984 break; 02985 02986 // 02987 // Round toward plus infinity. 02988 // 02989 02990 case ROUND_TO_PLUS_INFINITY: 02991 if ((ResultOperand->Sign == 0) && 02992 ((StickyBits != 0) || (RoundBit != 0))) { 02993 Mantissa += 1; 02994 } 02995 break; 02996 02997 // 02998 // Round toward minus infinity. 02999 // 03000 03001 case ROUND_TO_MINUS_INFINITY: 03002 if ((ResultOperand->Sign != 0) && 03003 ((StickyBits != 0) || (RoundBit != 0))) { 03004 Mantissa += 1; 03005 } 03006 break; 03007 } 03008 03009 // 03010 // If rounding resulted in a carry into bit 53, then right shift the 03011 // mantissa one bit and adjust the exponent. 03012 // 03013 03014 if ((Mantissa & ((ULONGLONG)1 << 53)) != 0) { 03015 Mantissa >>= 1; 03016 ResultOperand->Exponent += 1; 03017 } 03018 03019 // 03020 // If rounding resulted in a carry into bit 52 in denormal format, then 03021 // adjust the exponent. 03022 // 03023 03024 if ((ResultOperand->Exponent == DOUBLE_MINIMUM_EXPONENT) && 03025 (Mantissa & ((ULONGLONG)1 << 52)) != 0) { 03026 ResultOperand->Exponent += 1; 03027 } 03028 03029 // 03030 // If the exponent value is greater than or equal to the maximum 03031 // exponent value, then overflow has occurred. This results in both 03032 // the inexact and overflow sticky bits being set in the FPCR. 03033 // 03034 // If the exponent value is less than or equal to the minimum exponent 03035 // value, the mantissa is nonzero, and the denormalized result is inexact, 03036 // then underflow has occurred. This results in both the inexact and 03037 // underflow sticky bits being set in the FPCR. 03038 // 03039 // Or if underflow exceptions are enabled, underflow occurs for all denormal 03040 // numbers. This results in the underflow sticky bit always being set in the 03041 // FPCR and the inexact sticky bit is set when the denormalized result is 03042 // also inexact. 03043 // 03044 // Otherwise, a normal result can be delivered, but it may be inexact. 03045 // If the result is inexact, then the inexact sticky bit is set in the 03046 // FPCR. 03047 // 03048 03049 if (ResultOperand->Exponent >= DOUBLE_MAXIMUM_EXPONENT) { 03050 Inexact = TRUE; 03051 Overflow = TRUE; 03052 Underflow = FALSE; 03053 03054 // 03055 // The overflow value is dependent on the rounding mode. 03056 // 03057 03058 switch (ContextBlock->Round) { 03059 03060 // 03061 // Round to nearest representable number. 03062 // 03063 // The result value is infinity with the sign of the result. 03064 // 03065 03066 case ROUND_TO_NEAREST: 03067 ResultValue = MAKE_QUAD(DOUBLE_INFINITY_VALUE_LOW, 03068 DOUBLE_INFINITY_VALUE_HIGH | 03069 (ResultOperand->Sign << 31)); 03070 break; 03071 03072 // 03073 // Round toward zero. 03074 // 03075 // The result is the maximum number with the sign of the result. 03076 // 03077 03078 case ROUND_TO_ZERO: 03079 ResultValue = MAKE_QUAD(DOUBLE_MAXIMUM_VALUE_LOW, 03080 DOUBLE_MAXIMUM_VALUE_HIGH | 03081 (ResultOperand->Sign << 31)); 03082 break; 03083 03084 // 03085 // Round toward plus infinity. 03086 // 03087 // If the sign of the result is positive, then the result is 03088 // plus infinity. Otherwise, the result is the maximum negative 03089 // number. 03090 // 03091 03092 case ROUND_TO_PLUS_INFINITY: 03093 if (ResultOperand->Sign == 0) { 03094 ResultValue = MAKE_QUAD(DOUBLE_INFINITY_VALUE_LOW, 03095 DOUBLE_INFINITY_VALUE_HIGH); 03096 03097 } else { 03098 ResultValue = MAKE_QUAD(DOUBLE_MAXIMUM_VALUE_LOW, 03099 DOUBLE_MAXIMUM_VALUE_HIGH | 03100 (1 << 31)); 03101 } 03102 break; 03103 03104 // 03105 // Round toward minus infinity. 03106 // 03107 // If the sign of the result is negative, then the result is 03108 // negative infinity. Otherwise, the result is the maximum 03109 // positive number. 03110 // 03111 03112 03113 case ROUND_TO_MINUS_INFINITY: 03114 if (ResultOperand->Sign != 0) { 03115 ResultValue = MAKE_QUAD(DOUBLE_INFINITY_VALUE_LOW, 03116 DOUBLE_INFINITY_VALUE_HIGH | 03117 (1 << 31)); 03118 03119 } else { 03120 ResultValue = MAKE_QUAD(DOUBLE_MAXIMUM_VALUE_LOW, 03121 DOUBLE_MAXIMUM_VALUE_HIGH); 03122 } 03123 break; 03124 } 03125 03126 // 03127 // Compute the overflow exception result value by subtracting 1536 03128 // from the exponent. 03129 // 03130 03131 ExceptionResult = Mantissa & (((ULONGLONG)1 << 52) - 1); 03132 ExceptionResult |= (((ULONGLONG)ResultOperand->Exponent - 1536) << 52); 03133 ExceptionResult |= ((ULONGLONG)ResultOperand->Sign << 63); 03134 03135 } else { 03136 03137 // 03138 // After rounding if the exponent value is equal to 03139 // the minimum exponent value and the result was nonzero, then 03140 // underflow has occurred. 03141 // 03142 03143 if ((ResultOperand->Exponent == DOUBLE_MINIMUM_EXPONENT) && 03144 (Mantissa != 0 || RoundBit != 00 || StickyBits != 0)) { 03145 03146 // 03147 // If the FPCR underflow to zero (denormal enable) control bit 03148 // is set, then flush the denormalized result to zero and do 03149 // not set an underflow status or generate an exception. 03150 // 03151 03152 if ((ContextBlock->IeeeMode == FALSE) || 03153 (SoftwareFpcr->DenormalResultEnable == 0)) { 03154 DBGPRINT("SoftwareFpcr->DenormalResultEnable == 0\n"); 03155 ResultValue = 0; 03156 Inexact = FALSE; 03157 Overflow = FALSE; 03158 Underflow = FALSE; 03159 03160 } else { 03161 03162 ResultValue = Mantissa; 03163 ResultValue |= (ULONGLONG)ResultOperand->Sign << 63; 03164 03165 // 03166 // 03167 // Compute the underflow exception result value by recalculating the 03168 // full precision answer and adding 1536 to the exponent. 03169 // 03170 03171 // 03172 // Round the result value using the mantissa, the round bit, and the sticky bits. 03173 // 03174 03175 switch (ContextBlock->Round) { 03176 03177 // 03178 // Round to nearest representable number. 03179 // 03180 03181 case ROUND_TO_NEAREST: 03182 if (ResultRoundBit != 0) { 03183 if ((ResultStickyBits != 0) || ((ResultMantissa & 0x1) != 0)) { 03184 ResultMantissa += 1; 03185 } 03186 } 03187 break; 03188 03189 // 03190 // Round toward zero. 03191 // 03192 03193 case ROUND_TO_ZERO: 03194 break; 03195 03196 // 03197 // Round toward plus infinity. 03198 // 03199 03200 case ROUND_TO_PLUS_INFINITY: 03201 if ((ResultOperand->Sign == 0) && 03202 ((ResultStickyBits != 0) || (ResultRoundBit != 0))) { 03203 ResultMantissa += 1; 03204 } 03205 break; 03206 03207 // 03208 // Round toward minus infinity. 03209 // 03210 03211 case ROUND_TO_MINUS_INFINITY: 03212 if ((ResultOperand->Sign != 0) && 03213 ((ResultStickyBits != 0) || (ResultRoundBit != 0))) { 03214 ResultMantissa += 1; 03215 } 03216 break; 03217 } 03218 03219 // 03220 // If rounding resulted in a carry into bit 53, then right shift the 03221 // mantissa one bit and adjust the exponent. 03222 // 03223 03224 if ((ResultMantissa & ((ULONGLONG)1 << 53)) != 0) { 03225 ResultMantissa >>= 1; 03226 ResultExponent += 1; 03227 } 03228 03229 // Compute the underflow exception result value by adding 03230 // 1536 to the exponent. 03231 // 03232 03233 ExceptionResult = ResultMantissa & (((ULONGLONG)1 << 52) - 1); 03234 ExceptionResult |= (((ULONGLONG)ResultExponent + 1536) << 52); 03235 ExceptionResult |= ((ULONGLONG)ResultOperand->Sign << 63); 03236 03237 // 03238 // If the denormalized result is inexact, then set underflow. 03239 // Otherwise, for exact denormals do not set the underflow 03240 // sticky bit unless underflow exception is enabled. 03241 // 03242 03243 Overflow = FALSE; 03244 Underflow = TRUE; 03245 if ((StickyBits != 0) || (RoundBit != 0)) { 03246 Inexact = TRUE; 03247 03248 } else { 03249 Inexact = FALSE; 03250 } 03251 } 03252 03253 } else { 03254 03255 // 03256 // If the result is zero, then set the proper sign for zero. 03257 // 03258 03259 if (Mantissa == 0) { 03260 ResultOperand->Exponent = 0; 03261 } 03262 03263 ResultValue = Mantissa & (((ULONGLONG)1 << 52) - 1); 03264 ResultValue |= (ULONGLONG)ResultOperand->Exponent << 52; 03265 ResultValue |= (ULONGLONG)ResultOperand->Sign << 63; 03266 if ((StickyBits != 0) || (RoundBit != 0)) { 03267 Inexact = TRUE; 03268 03269 } else { 03270 Inexact = FALSE; 03271 } 03272 Overflow = FALSE; 03273 Underflow = FALSE; 03274 } 03275 } 03276 03277 // 03278 // Check to determine if an exception should be delivered. 03279 // 03280 03281 ExceptionRecord = ContextBlock->ExceptionRecord; 03282 03283 if (Overflow != FALSE) { 03284 Fpcr->Overflow = 1; 03285 Fpcr->InexactResult = 1; 03286 Fpcr->SummaryBit = 1; 03287 if (ContextBlock->IeeeMode == FALSE) { 03288 ExceptionRecord->ExceptionCode = STATUS_FLOAT_OVERFLOW; 03289 return FALSE; 03290 } 03291 IeeeValue = KiInitializeIeeeValue(ExceptionRecord); 03292 SoftwareFpcr->StatusOverflow = 1; 03293 SoftwareFpcr->StatusInexact = 1; 03294 if (SoftwareFpcr->EnableOverflow != 0) { 03295 ExceptionRecord->ExceptionCode = STATUS_FLOAT_OVERFLOW; 03296 IeeeValue->Value.Fp64Value.W[0] = LOW_PART(ExceptionResult); 03297 IeeeValue->Value.Fp64Value.W[1] = HIGH_PART(ExceptionResult); 03298 ReturnValue = FALSE; 03299 } else if (SoftwareFpcr->EnableInexact != 0) { 03300 ExceptionRecord->ExceptionCode = STATUS_FLOAT_INEXACT_RESULT; 03301 IeeeValue->Value.Fp64Value.W[0] = LOW_PART(ExceptionResult); 03302 IeeeValue->Value.Fp64Value.W[1] = HIGH_PART(ExceptionResult); 03303 ReturnValue = FALSE; 03304 } else { 03305 Fpcr->DisableOverflow = 1; 03306 Fpcr->DisableInexact = 1; 03307 } 03308 03309 } else if (Underflow != FALSE) { 03310 03311 // 03312 // Non-IEEE instruction always forces underflow to zero 03313 // 03314 03315 if (ContextBlock->IeeeMode == FALSE) { 03316 Fpcr->Underflow = 1; 03317 Fpcr->SummaryBit = 1; 03318 Fpcr->InexactResult = 1; 03319 if (ContextBlock->UnderflowEnable != FALSE) { 03320 ExceptionRecord->ExceptionCode = STATUS_FLOAT_UNDERFLOW; 03321 return FALSE; 03322 } 03323 03324 // 03325 // IEEE instructions don't report underflow unless the results are 03326 // inexact or underflow exceptions are enabled 03327 // 03328 03329 } else { 03330 IeeeValue = KiInitializeIeeeValue(ExceptionRecord); 03331 if (Inexact != FALSE) { 03332 Fpcr->Underflow = 1; 03333 Fpcr->SummaryBit = 1; 03334 Fpcr->InexactResult = 1; 03335 SoftwareFpcr->StatusUnderflow = 1; 03336 SoftwareFpcr->StatusInexact = 1; 03337 } 03338 if (SoftwareFpcr->EnableUnderflow != 0) { 03339 Fpcr->Underflow = 1; 03340 Fpcr->SummaryBit = 1; 03341 SoftwareFpcr->StatusUnderflow = 1; 03342 ExceptionRecord->ExceptionCode = STATUS_FLOAT_UNDERFLOW; 03343 IeeeValue->Value.Fp64Value.W[0] = LOW_PART(ExceptionResult); 03344 IeeeValue->Value.Fp64Value.W[1] = HIGH_PART(ExceptionResult); 03345 ReturnValue = FALSE; 03346 } else if (Inexact != FALSE && SoftwareFpcr->EnableInexact != 0) { 03347 ExceptionRecord->ExceptionCode = STATUS_FLOAT_INEXACT_RESULT; 03348 IeeeValue->Value.Fp64Value.W[0] = LOW_PART(ExceptionResult); 03349 IeeeValue->Value.Fp64Value.W[1] = HIGH_PART(ExceptionResult); 03350 ReturnValue = FALSE; 03351 } else if (Inexact != FALSE) { 03352 Fpcr->DisableUnderflow = 1; 03353 Fpcr->DisableInexact = 1; 03354 } 03355 } 03356 03357 } else if (Inexact != FALSE) { 03358 Fpcr->InexactResult = 1; 03359 Fpcr->SummaryBit = 1; 03360 if (ContextBlock->IeeeMode != FALSE) { 03361 IeeeValue = KiInitializeIeeeValue(ExceptionRecord); 03362 SoftwareFpcr->StatusInexact = 1; 03363 if (SoftwareFpcr->EnableInexact != 0) { 03364 ExceptionRecord->ExceptionCode = STATUS_FLOAT_INEXACT_RESULT; 03365 IeeeValue->Value.Fp64Value.W[0] = LOW_PART(ResultValue); 03366 IeeeValue->Value.Fp64Value.W[1] = HIGH_PART(ResultValue); 03367 ReturnValue = FALSE; 03368 } else { 03369 Fpcr->DisableInexact = 1; 03370 } 03371 } 03372 } 03373 03374 // 03375 // Always write the destination register. If an exception is delivered, and 03376 // then dismissed, the correct value must be in the register. 03377 // 03378 03379 KiSetRegisterValue(ContextBlock->Fc + 32, 03380 ResultValue, 03381 ContextBlock->ExceptionFrame, 03382 ContextBlock->TrapFrame); 03383 03384 // 03385 // Return a value of TRUE.unless an exception should be generated 03386 // 03387 03388 return ReturnValue; 03389 }

BOOLEAN KiNormalizeQuadword IN PFP_CONTEXT_BLOCK  ContextBlock,
IN PFP_DOUBLE_OPERAND  ResultOperand
 

Definition at line 3392 of file alpha/floatem.c.

References DBGPRINT, FALSE, HIGH_PART, KiInitializeIeeeValue(), KiInvalidOperationQuadword(), KiSetRegisterValue(), LOW_PART, MAKE_QUAD, and TRUE.

03399 : 03400 03401 This function is called to convert a result value to a quadword result. 03402 03403 N.B. The result value is specified with a guard bit on the right, 03404 the hidden bit (if appropriate), and an overflow bit of zero. 03405 As called above, the guard bit and the round bit are also zero. 03406 The result format is: 03407 03408 <63:55> - zero 03409 <54 - hidden bit 03410 <53:2> - mantissa 03411 <1> - guard bit 03412 <0> - round bit 03413 03414 There are no sticky bits. 03415 03416 Arguments: 03417 03418 ContextBlock - Supplies a pointer to the emulation context block. 03419 03420 ResultOperand - Supplies a pointer to the result operand value. 03421 03422 Return Value: 03423 03424 If there is not an exception, or the exception is handled, then a proper 03425 result is stored in the destination result, the continuation address is 03426 set, and a value of TRUE is returned. Otherwise, no value is stored and 03427 a value of FALSE is returned. 03428 03429 --*/ 03430 03431 { 03432 03433 PEXCEPTION_RECORD ExceptionRecord; 03434 LONGLONG ExponentShift; 03435 PFPCR Fpcr; 03436 PFP_IEEE_VALUE IeeeValue; 03437 ULONGLONG Mantissa; 03438 BOOLEAN Overflow; 03439 ULONGLONG ResultValue; 03440 ULONG RoundBit; 03441 ULONGLONG StickyBits; 03442 PSW_FPCR SoftwareFpcr; 03443 03444 // 03445 // Subtract out the exponent bias and divide the cases into right 03446 // and left shifts. 03447 // 03448 03449 ExponentShift = ResultOperand->Exponent - DOUBLE_EXPONENT_BIAS; 03450 DBGPRINT("KiNormalizeQuadword: Inf=%d NaN=%d Sign=%d Exponent=%d Mantissa=%.8x%.8x\n", 03451 ResultOperand->Infinity, ResultOperand->Nan, ResultOperand->Sign, 03452 ResultOperand->Exponent, 03453 ResultOperand->MantissaHigh, ResultOperand->MantissaLow); 03454 DBGPRINT(".. ExponentShift = %d\n", ExponentShift); 03455 Mantissa = MAKE_QUAD(ResultOperand->MantissaLow, 03456 ResultOperand->MantissaHigh); 03457 03458 if (ExponentShift < 54) { 03459 03460 // 03461 // The integer result value is less than 2**54 and so a right shift 03462 // must be performed. 03463 // 03464 03465 ExponentShift = 54 - ExponentShift; 03466 if (ExponentShift < 64) { 03467 StickyBits = Mantissa << (64 - ExponentShift); 03468 ResultValue = Mantissa >> ExponentShift; 03469 03470 } else { 03471 StickyBits = Mantissa; 03472 ResultValue = 0; 03473 } 03474 Overflow = FALSE; 03475 03476 } else if (ExponentShift > 54) { 03477 ExponentShift -= 54; 03478 03479 // 03480 // The integer result value is 2**54 or greater and so a left shift 03481 // must be performed. If the unsigned integer result value is 2**64 03482 // or greater, then overflow has occurred and store the low order 64 03483 // bits of the true result. 03484 // 03485 03486 if (ExponentShift < (64 - 54)) { 03487 StickyBits = Mantissa >> (64 - ExponentShift); 03488 ResultValue = Mantissa << ExponentShift; 03489 Overflow = FALSE; 03490 03491 } else { 03492 StickyBits = 0; 03493 if (ExponentShift < 64) { 03494 ResultValue = Mantissa << ExponentShift; 03495 03496 } else { 03497 ResultValue = 0; 03498 } 03499 Overflow = TRUE; 03500 } 03501 03502 } else { 03503 StickyBits = 0; 03504 ResultValue = Mantissa; 03505 Overflow = FALSE; 03506 } 03507 DBGPRINT(".. ResultValue = %.16Lx, StickyBits = %.16Lx\n", 03508 ResultValue, StickyBits); 03509 03510 // 03511 // Round the result value using the mantissa, the round bit, and the 03512 // sticky bits. 03513 // 03514 03515 RoundBit = (ULONG)(StickyBits >> 63); 03516 StickyBits <<= 1; 03517 DBGPRINT(".. ResultValue = %.16Lx, StickyBits = %.16Lx, RoundBit = %lx\n", 03518 ResultValue, StickyBits, RoundBit); 03519 switch (ContextBlock->Round) { 03520 03521 // 03522 // Round to nearest representable number. 03523 // 03524 03525 case ROUND_TO_NEAREST: 03526 if (RoundBit != 0) { 03527 if ((StickyBits != 0) || ((ResultValue & 0x1) != 0)) { 03528 ResultValue += 1; 03529 if (ResultValue == 0) { 03530 Overflow = TRUE; 03531 } 03532 } 03533 } 03534 break; 03535 03536 // 03537 // Round toward zero. 03538 // 03539 03540 case ROUND_TO_ZERO: 03541 break; 03542 03543 // 03544 // Round toward plus infinity. 03545 // 03546 03547 case ROUND_TO_PLUS_INFINITY: 03548 if ((ResultOperand->Sign == 0) && 03549 ((StickyBits != 0) || (RoundBit != 0))) { 03550 ResultValue += 1; 03551 if (ResultValue == 0) { 03552 Overflow = TRUE; 03553 } 03554 } 03555 break; 03556 03557 // 03558 // Round toward minus infinity. 03559 // 03560 03561 case ROUND_TO_MINUS_INFINITY: 03562 if ((ResultOperand->Sign != 0) && 03563 ((StickyBits != 0) || (RoundBit != 0))) { 03564 ResultValue += 1; 03565 if (ResultValue == 0) { 03566 Overflow = TRUE; 03567 } 03568 } 03569 break; 03570 } 03571 03572 // 03573 // If the result value is positive and the result is negative, then 03574 // overflow has occurred. Otherwise, negate the result value and 03575 // check if the result is negative. If the result is positive, then 03576 // overflow has occurred. 03577 // 03578 03579 if (ResultOperand->Sign == 0) { 03580 if ((LONGLONG)ResultValue < 0) { 03581 Overflow = TRUE; 03582 } 03583 03584 } else { 03585 ResultValue = -(LONGLONG)ResultValue; 03586 if ((LONGLONG)ResultValue > 0) { 03587 Overflow = TRUE; 03588 } 03589 } 03590 DBGPRINT(".. ResultValue = %.16Lx, StickyBits = %.16Lx\n", 03591 ResultValue, StickyBits); 03592 03593 // 03594 // Check to determine if an exception should be delivered or the result 03595 // should be written to the destination register. 03596 // 03597 03598 if (Overflow != FALSE) { 03599 return KiInvalidOperationQuadword(ContextBlock, ResultValue); 03600 03601 } else if ((StickyBits | RoundBit) != 0) { 03602 Fpcr = (PFPCR)&ContextBlock->TrapFrame->Fpcr; 03603 Fpcr->InexactResult = 1; 03604 Fpcr->SummaryBit = 1; 03605 if (ContextBlock->IeeeMode != FALSE) { 03606 SoftwareFpcr = ContextBlock->SoftwareFpcr; 03607 SoftwareFpcr->StatusInexact = 1; 03608 if (SoftwareFpcr->EnableInexact != 0) { 03609 ExceptionRecord = ContextBlock->ExceptionRecord; 03610 ExceptionRecord->ExceptionCode = STATUS_FLOAT_INEXACT_RESULT; 03611 IeeeValue = KiInitializeIeeeValue(ExceptionRecord); 03612 IeeeValue->Value.U64Value.LowPart = LOW_PART(ResultValue); 03613 IeeeValue->Value.U64Value.HighPart = HIGH_PART(ResultValue); 03614 return FALSE; 03615 } 03616 03617 Fpcr->DisableInexact = 1; 03618 } 03619 } 03620 03621 // 03622 // Set the destination register value and return a value of TRUE. 03623 // 03624 03625 KiSetRegisterValue(ContextBlock->Fc + 32, 03626 ResultValue, 03627 ContextBlock->ExceptionFrame, 03628 ContextBlock->TrapFrame); 03629 03630 return TRUE; 03631 }

BOOLEAN KiNormalizeSingle IN PFP_CONTEXT_BLOCK  ContextBlock,
IN PFP_SINGLE_OPERAND  ResultOperand,
IN ULONG  StickyBits
 

Definition at line 3634 of file alpha/floatem.c.

References DBGPRINT, FALSE, KiConvertSingleOperandToRegister(), KiInitializeIeeeValue(), KiSetRegisterValue(), and TRUE.

03642 : 03643 03644 This function is called to normalize a single floating result. 03645 03646 N.B. The result value is specified with a guard bit on the right, 03647 the hidden bit (if appropriate), and a possible overflow bit. 03648 The result format is: 03649 03650 <31:27> - zero 03651 <26> - overflow bit 03652 <25> - hidden bit 03653 <24:2> - mantissa 03654 <1> - guard bit 03655 <0> - round bit 03656 03657 The sticky bits specify bits that were lost during the computation. 03658 03659 Arguments: 03660 03661 ContextBlock - Supplies a pointer to the emulation context block. 03662 03663 ResultOperand - Supplies a pointer to the result operand value. 03664 03665 StickyBits - Supplies the value of the sticky bits. 03666 03667 Return Value: 03668 03669 If there is not an exception, or the exception is handled, then a proper 03670 result is stored in the destination result, the continuation address is 03671 set, and a value of TRUE is returned. Otherwise, a proper value is stored and 03672 a value of FALSE is returned. 03673 03674 --*/ 03675 03676 { 03677 03678 ULONG DenormalizeShift; 03679 PEXCEPTION_RECORD ExceptionRecord; 03680 ULONG ExceptionResult; 03681 PFPCR Fpcr; 03682 PFP_IEEE_VALUE IeeeValue; 03683 BOOLEAN Inexact; 03684 ULONG Mantissa; 03685 BOOLEAN Overflow; 03686 ULONG ResultValue; 03687 ULONG RoundBit; 03688 PSW_FPCR SoftwareFpcr; 03689 BOOLEAN Underflow; 03690 ULONG ResultStickyBits; 03691 ULONG ResultMantissa; 03692 ULONG ResultRoundBit; 03693 LONG ResultExponent; 03694 BOOLEAN ReturnValue = TRUE; 03695 03696 // 03697 // If the result is infinite, then store a properly signed infinity 03698 // in the destination register and return a value of TRUE. Otherwise, 03699 // round and normalize the result and check for overflow and underflow. 03700 // 03701 03702 DBGPRINT("KiNormalizeSingle: Inf=%d NaN=%d Sign=%d Exponent=%d Mantissa=%.8x\n", 03703 ResultOperand->Infinity, ResultOperand->Nan, ResultOperand->Sign, 03704 ResultOperand->Exponent, ResultOperand->Mantissa); 03705 DBGPRINT("KiNormalizeSingle: StickyBits=%.8lx\n", StickyBits); 03706 03707 if (ResultOperand->Infinity != FALSE) { 03708 ResultValue = SINGLE_INFINITY_VALUE | (ResultOperand->Sign << 31); 03709 KiSetRegisterValue(ContextBlock->Fc + 32, 03710 KiConvertSingleOperandToRegister(ResultValue), 03711 ContextBlock->ExceptionFrame, 03712 ContextBlock->TrapFrame); 03713 03714 return TRUE; 03715 } 03716 03717 Mantissa = ResultOperand->Mantissa; 03718 Fpcr = (PFPCR)&ContextBlock->TrapFrame->Fpcr; 03719 SoftwareFpcr = ContextBlock->SoftwareFpcr; 03720 03721 // 03722 // If the overflow bit is set, then right shift the mantissa one bit, 03723 // accumulate the lost bit with the sticky bits, and adjust the exponent 03724 // value. 03725 // 03726 03727 if ((Mantissa & (1 << 26)) != 0) { 03728 StickyBits |= (Mantissa & 0x1); 03729 Mantissa >>= 1; 03730 ResultOperand->Exponent += 1; 03731 } 03732 03733 // 03734 // If the mantissa is nonzero, then normalize the mantissa by left 03735 // shifting one bit at a time until there is a one bit in bit 25. 03736 // 03737 03738 if (Mantissa != 0) { 03739 while ((Mantissa & (1 << 25)) == 0) { 03740 Mantissa <<= 1; 03741 ResultOperand->Exponent -= 1; 03742 } 03743 } 03744 03745 // 03746 // Right shift the mantissa two bits, set the round bit, and accumulate 03747 // the other lost bit with the sticky bits. 03748 // 03749 03750 StickyBits |= (Mantissa & 0x1); 03751 RoundBit = (Mantissa & 0x2); 03752 Mantissa >>= 2; 03753 03754 // 03755 // Convert to denormal format before rounding to allow underflow to 03756 // be detected on rounded result. Save context to calculate IEEE 03757 // exception record, if needed. 03758 // 03759 03760 if (ResultOperand->Exponent <= SINGLE_MINIMUM_EXPONENT && Mantissa != 0) { 03761 03762 // 03763 // Save everything needed for calculating IEEE exception record value 03764 // 03765 03766 ResultMantissa = Mantissa; 03767 ResultExponent = ResultOperand->Exponent; 03768 ResultStickyBits = StickyBits; 03769 ResultRoundBit = RoundBit; 03770 03771 // 03772 // Right shift the mantissa to set the minimum exponent plus an extra 03773 // bit for the denormal format 03774 // 03775 03776 DenormalizeShift = 1 - ResultOperand->Exponent; 03777 03778 // 03779 // The maximum denormal shift is 23 bits for the mantissa plus 1 bit for the round 03780 // A denormal shift of 25 guarantees 0 mantissa and 0 round bit and preserves all sticky bits 03781 // 03782 03783 if (DenormalizeShift > 25) { 03784 DenormalizeShift = 25; 03785 } 03786 03787 // 03788 // The denormalized result will be rounded after it is 03789 // shifted. Preserve existing Round and Sticky Bits. 03790 // 03791 03792 StickyBits |= RoundBit; 03793 StickyBits |= (Mantissa << 1) << (32 - DenormalizeShift); 03794 RoundBit = (Mantissa >> (DenormalizeShift - 1)) & 1; 03795 Mantissa = Mantissa >> DenormalizeShift; 03796 ResultOperand->Exponent = SINGLE_MINIMUM_EXPONENT; 03797 } 03798 03799 // 03800 // Round the result value using the mantissa, the round bit, and the sticky bits. 03801 // 03802 03803 switch (ContextBlock->Round) { 03804 03805 // 03806 // Round to nearest representable number. 03807 // 03808 03809 case ROUND_TO_NEAREST: 03810 if (RoundBit != 0) { 03811 if ((StickyBits != 0) || ((Mantissa & 0x1) != 0)) { 03812 Mantissa += 1; 03813 } 03814 } 03815 break; 03816 03817 // 03818 // Round toward zero. 03819 // 03820 03821 case ROUND_TO_ZERO: 03822 break; 03823 03824 // 03825 // Round toward plus infinity. 03826 // 03827 03828 case ROUND_TO_PLUS_INFINITY: 03829 if ((ResultOperand->Sign == 0) && 03830 ((StickyBits != 0) || (RoundBit != 0))) { 03831 Mantissa += 1; 03832 } 03833 break; 03834 03835 // 03836 // Round toward minus infinity. 03837 // 03838 03839 case ROUND_TO_MINUS_INFINITY: 03840 if ((ResultOperand->Sign != 0) && 03841 ((StickyBits != 0) || (RoundBit != 0))) { 03842 Mantissa += 1; 03843 } 03844 break; 03845 } 03846 03847 // 03848 // If rounding resulted in a carry into bit 24, then right shift the 03849 // mantissa one bit and adjust the exponent. 03850 // 03851 03852 if ((Mantissa & (1 << 24)) != 0) { 03853 Mantissa >>= 1; 03854 ResultOperand->Exponent += 1; 03855 } 03856 03857 // 03858 // If rounding resulted in a carry into bit 23 in denormal format, then 03859 // adjust the exponent. 03860 // 03861 03862 if ((ResultOperand->Exponent == SINGLE_MINIMUM_EXPONENT) && 03863 (Mantissa & (1 << 23)) != 0) { 03864 ResultOperand->Exponent += 1; 03865 } 03866 03867 // 03868 // If the exponent value is greater than or equal to the maximum 03869 // exponent value, then overflow has occurred. This results in both 03870 // the inexact and overflow sticky bits being set in the FPCR. 03871 // 03872 // If the exponent value is less than or equal to the minimum exponent 03873 // value, the mantissa is nonzero, and the denormalized result is inexact, 03874 // then underflow has occurred. This results in both the inexact and 03875 // underflow sticky bits being set in the FPCR. 03876 // 03877 // Or if underflow exceptions are enabled, underflow occurs for all denormal 03878 // numbers. This results in the underflow sticky bit always being set in the 03879 // FPCR and the inexact sticky bit is set when the denormalized result is 03880 // also inexact. 03881 // 03882 // Otherwise, a normal result can be delivered, but it may be inexact. 03883 // If the result is inexact, then the inexact sticky bit is set in the 03884 // FPCR. 03885 // 03886 03887 if (ResultOperand->Exponent >= SINGLE_MAXIMUM_EXPONENT) { 03888 Inexact = TRUE; 03889 Overflow = TRUE; 03890 Underflow = FALSE; 03891 03892 // 03893 // The overflow value is dependent on the rounding mode. 03894 // 03895 03896 switch (ContextBlock->Round) { 03897 03898 // 03899 // Round to nearest representable number. 03900 // 03901 // The result value is infinity with the sign of the result. 03902 // 03903 03904 case ROUND_TO_NEAREST: 03905 ResultValue = SINGLE_INFINITY_VALUE | (ResultOperand->Sign << 31); 03906 break; 03907 03908 // 03909 // Round toward zero. 03910 // 03911 // The result is the maximum number with the sign of the result. 03912 // 03913 03914 case ROUND_TO_ZERO: 03915 ResultValue = SINGLE_MAXIMUM_VALUE | (ResultOperand->Sign << 31); 03916 break; 03917 03918 // 03919 // Round toward plus infinity. 03920 // 03921 // If the sign of the result is positive, then the result is 03922 // plus infinity. Otherwise, the result is the maximum negative 03923 // number. 03924 // 03925 03926 case ROUND_TO_PLUS_INFINITY: 03927 if (ResultOperand->Sign == 0) { 03928 ResultValue = SINGLE_INFINITY_VALUE; 03929 03930 } else { 03931 ResultValue = (ULONG)(SINGLE_MAXIMUM_VALUE | (1 << 31)); 03932 } 03933 break; 03934 03935 // 03936 // Round toward minus infinity. 03937 // 03938 // If the sign of the result is negative, then the result is 03939 // negative infinity. Otherwise, the result is the maximum 03940 // positive number. 03941 // 03942 03943 case ROUND_TO_MINUS_INFINITY: 03944 if (ResultOperand->Sign != 0) { 03945 ResultValue = (ULONG)(SINGLE_INFINITY_VALUE | (1 << 31)); 03946 03947 } else { 03948 ResultValue = SINGLE_MAXIMUM_VALUE; 03949 } 03950 break; 03951 } 03952 03953 // 03954 // Compute the overflow exception result value by subtracting 192 03955 // from the exponent. 03956 // 03957 03958 ExceptionResult = Mantissa & ((1 << 23) - 1); 03959 ExceptionResult |= ((ResultOperand->Exponent - 192) << 23); 03960 ExceptionResult |= (ResultOperand->Sign << 31); 03961 03962 } else { 03963 03964 // 03965 // After rounding if the exponent value is equal to 03966 // the minimum exponent value and the result was nonzero, then 03967 // underflow has occurred. 03968 // 03969 03970 if ((ResultOperand->Exponent == SINGLE_MINIMUM_EXPONENT) && 03971 (Mantissa != 0 || RoundBit != 00 || StickyBits != 0)) { 03972 03973 // 03974 // If the FPCR underflow to zero (denormal enable) control bit 03975 // is set, then flush the denormalized result to zero and do 03976 // not set an underflow status or generate an exception. 03977 // 03978 03979 if ((ContextBlock->IeeeMode == FALSE) || 03980 (SoftwareFpcr->DenormalResultEnable == 0)) { 03981 DBGPRINT("SoftwareFpcr->DenormalResultEnable == 0\n"); 03982 ResultValue = 0; 03983 Inexact = FALSE; 03984 Overflow = FALSE; 03985 Underflow = FALSE; 03986 03987 } else { 03988 03989 ResultValue = Mantissa; 03990 ResultValue |= ResultOperand->Sign << 31; 03991 03992 // 03993 // 03994 // Compute the underflow exception result value by first recalculating the 03995 // full precision answer. 03996 // 03997 03998 // 03999 // Round the result value using the mantissa, the round bit, and the sticky bits. 04000 // 04001 04002 switch (ContextBlock->Round) { 04003 04004 // 04005 // Round to nearest representable number. 04006 // 04007 04008 case ROUND_TO_NEAREST: 04009 if (ResultRoundBit != 0) { 04010 if ((ResultStickyBits != 0) || ((ResultMantissa & 0x1) != 0)) { 04011 ResultMantissa += 1; 04012 } 04013 } 04014 break; 04015 04016 // 04017 // Round toward zero. 04018 // 04019 04020 case ROUND_TO_ZERO: 04021 break; 04022 04023 // 04024 // Round toward plus infinity. 04025 // 04026 04027 case ROUND_TO_PLUS_INFINITY: 04028 if ((ResultOperand->Sign == 0) && 04029 ((ResultStickyBits != 0) || (ResultRoundBit != 0))) { 04030 ResultMantissa += 1; 04031 } 04032 break; 04033 04034 // 04035 // Round toward minus infinity. 04036 // 04037 04038 case ROUND_TO_MINUS_INFINITY: 04039 if ((ResultOperand->Sign != 0) && 04040 ((ResultStickyBits != 0) || (ResultRoundBit != 0))) { 04041 ResultMantissa += 1; 04042 } 04043 break; 04044 } 04045 04046 // 04047 // If rounding resulted in a carry into bit 24, then right shift the 04048 // mantissa one bit and adjust the exponent. 04049 // 04050 04051 if ((ResultMantissa & (1 << 24)) != 0) { 04052 ResultMantissa >>= 1; 04053 ResultExponent += 1; 04054 } 04055 04056 // 04057 // Compute the underflow exception result value by adding 04058 // 192 to the exponent. 04059 // 04060 04061 ExceptionResult = ResultMantissa & ((1 << 23) - 1); 04062 ExceptionResult |= ((ResultExponent + 192) << 23); 04063 ExceptionResult |= (ResultOperand->Sign << 31); 04064 04065 // 04066 // If the denormalized result is inexact, then set underflow. 04067 // Otherwise, for exact denormals do not set the underflow 04068 // sticky bit unless underflow exception is enabled. 04069 // 04070 04071 Overflow = FALSE; 04072 Underflow = TRUE; 04073 if ((StickyBits != 0) || (RoundBit != 0)) { 04074 Inexact = TRUE; 04075 04076 } else { 04077 Inexact = FALSE; 04078 } 04079 } 04080 04081 } else { 04082 04083 // 04084 // If the result is zero, then set the proper sign for zero. 04085 // 04086 04087 if (Mantissa == 0) { 04088 ResultOperand->Exponent = 0; 04089 } 04090 04091 ResultValue = Mantissa & ((1 << 23) - 1); 04092 ResultValue |= (ResultOperand->Exponent << 23); 04093 ResultValue |= (ResultOperand->Sign << 31); 04094 if ((StickyBits != 0) || (RoundBit != 0)) { 04095 Inexact = TRUE; 04096 04097 } else { 04098 Inexact = FALSE; 04099 } 04100 Overflow = FALSE; 04101 Underflow = FALSE; 04102 } 04103 } 04104 04105 // 04106 // Check to determine if an exception should be delivered. 04107 // 04108 04109 ExceptionRecord = ContextBlock->ExceptionRecord; 04110 04111 if (Overflow != FALSE) { 04112 Fpcr->Overflow = 1; 04113 Fpcr->InexactResult = 1; 04114 Fpcr->SummaryBit = 1; 04115 if (ContextBlock->IeeeMode == FALSE) { 04116 ExceptionRecord->ExceptionCode = STATUS_FLOAT_OVERFLOW; 04117 return FALSE; 04118 } 04119 IeeeValue = KiInitializeIeeeValue(ExceptionRecord); 04120 SoftwareFpcr->StatusOverflow = 1; 04121 SoftwareFpcr->StatusInexact = 1; 04122 if (SoftwareFpcr->EnableOverflow != 0) { 04123 ExceptionRecord->ExceptionCode = STATUS_FLOAT_OVERFLOW; 04124 IeeeValue->Value.Fp32Value.W[0] = ExceptionResult; 04125 ReturnValue = FALSE; 04126 } else if (SoftwareFpcr->EnableInexact != 0) { 04127 ExceptionRecord->ExceptionCode = STATUS_FLOAT_INEXACT_RESULT; 04128 IeeeValue->Value.Fp32Value.W[0] = ExceptionResult; 04129 ReturnValue = FALSE; 04130 } else { 04131 Fpcr->DisableOverflow = 1; 04132 Fpcr->DisableInexact = 1; 04133 } 04134 04135 } else if (Underflow != FALSE) { 04136 04137 // 04138 // Non-IEEE instruction always forces underflow to zero 04139 // 04140 04141 if (ContextBlock->IeeeMode == FALSE) { 04142 Fpcr->Underflow = 1; 04143 Fpcr->SummaryBit = 1; 04144 Fpcr->InexactResult = 1; 04145 if (ContextBlock->UnderflowEnable != FALSE) { 04146 ExceptionRecord->ExceptionCode = STATUS_FLOAT_UNDERFLOW; 04147 return FALSE; 04148 } 04149 04150 // 04151 // IEEE instructions don't report underflow unless the results are 04152 // inexact or underflow exceptions are enabled 04153 // 04154 04155 } else { 04156 IeeeValue = KiInitializeIeeeValue(ExceptionRecord); 04157 if (Inexact != FALSE) { 04158 Fpcr->Underflow = 1; 04159 Fpcr->InexactResult = 1; 04160 Fpcr->SummaryBit = 1; 04161 SoftwareFpcr->StatusUnderflow = 1; 04162 SoftwareFpcr->StatusInexact = 1; 04163 } 04164 if (SoftwareFpcr->EnableUnderflow != 0) { 04165 Fpcr->Underflow = 1; 04166 Fpcr->SummaryBit = 1; 04167 SoftwareFpcr->StatusUnderflow = 1; 04168 ExceptionRecord->ExceptionCode = STATUS_FLOAT_UNDERFLOW; 04169 IeeeValue->Value.Fp32Value.W[0] = ExceptionResult; 04170 ReturnValue = FALSE; 04171 } else if (Inexact != FALSE && SoftwareFpcr->EnableInexact != 0) { 04172 ExceptionRecord->ExceptionCode = STATUS_FLOAT_INEXACT_RESULT; 04173 IeeeValue->Value.Fp32Value.W[0] = ExceptionResult; 04174 ReturnValue = FALSE; 04175 } else if (Inexact != FALSE) { 04176 Fpcr->DisableUnderflow = 1; 04177 Fpcr->DisableInexact = 1; 04178 } 04179 } 04180 04181 } else if (Inexact != FALSE) { 04182 Fpcr->InexactResult = 1; 04183 Fpcr->SummaryBit = 1; 04184 if (ContextBlock->IeeeMode != FALSE) { 04185 IeeeValue = KiInitializeIeeeValue(ExceptionRecord); 04186 SoftwareFpcr->StatusInexact = 1; 04187 if (SoftwareFpcr->EnableInexact != 0) { 04188 ExceptionRecord->ExceptionCode = STATUS_FLOAT_INEXACT_RESULT; 04189 IeeeValue->Value.Fp32Value.W[0] = ResultValue; 04190 ReturnValue = FALSE; 04191 } else { 04192 Fpcr->DisableInexact = 1; 04193 } 04194 } 04195 } 04196 04197 // 04198 // Always write the destination register. If an exception is delivered, and 04199 // then dismissed, the correct value must be in the register. 04200 // 04201 04202 KiSetRegisterValue(ContextBlock->Fc + 32, 04203 KiConvertSingleOperandToRegister(ResultValue), 04204 ContextBlock->ExceptionFrame, 04205 ContextBlock->TrapFrame); 04206 04207 // 04208 // Return a value of TRUE.unless an exception should be generated 04209 // 04210 04211 return ReturnValue; 04212 }

VOID KiUnpackDouble IN ULONG  Source,
IN PFP_CONTEXT_BLOCK  ContextBlock,
OUT PFP_DOUBLE_OPERAND  DoubleOperand
 

Definition at line 4215 of file alpha/floatem.c.

References DBGPRINT, FALSE, KiGetRegisterValue(), and TRUE.

04223 : 04224 04225 This function is called to unpack a double floating value from the 04226 specified source register. 04227 04228 N.B. The unpacked mantissa value is returned with a guard bit and a 04229 round bit on the right and the hidden bit inserted if appropriate. 04230 The format of the returned value is: 04231 04232 <63:55> - zero 04233 <54> - hidden bit 04234 <53:2> - mantissa 04235 <1> - guard bit 04236 <0> - round bit 04237 04238 Arguments: 04239 04240 Source - Supplies the number of the register that contains the operand. 04241 04242 ContextBlock - Supplies a pointer to the emulation context block. 04243 04244 DoubleOperand - Supplies a pointer to a structure that is to receive the 04245 operand value. 04246 04247 Return Value: 04248 04249 None. 04250 04251 --*/ 04252 04253 { 04254 04255 ULONGLONG Value; 04256 ULONG Value1; 04257 ULONG Value2; 04258 04259 // 04260 // Get the source register value and unpack the sign, exponent, and 04261 // mantissa value. 04262 // 04263 04264 Value = KiGetRegisterValue(Source + 32, 04265 ContextBlock->ExceptionFrame, 04266 ContextBlock->TrapFrame); 04267 Value1 = (ULONG)Value; 04268 Value2 = (ULONG)(Value >> 32); 04269 04270 DoubleOperand->Sign = Value2 >> 31; 04271 DoubleOperand->Exponent = (Value2 >> (52 - 32)) & 0x7ff; 04272 DoubleOperand->MantissaHigh = Value2 & 0xfffff; 04273 DoubleOperand->MantissaLow = Value1; 04274 04275 // 04276 // If the exponent is the largest possible value, then the number is 04277 // either a NaN or an infinity. Otherwise if the exponent is the smallest 04278 // possible value and the mantissa is nonzero, then the number is 04279 // denormalized. Otherwise the number is finite and normal. 04280 // 04281 04282 if (DoubleOperand->Exponent == DOUBLE_MAXIMUM_EXPONENT) { 04283 DoubleOperand->Normal = FALSE; 04284 if ((DoubleOperand->MantissaLow | DoubleOperand->MantissaHigh) != 0) { 04285 DoubleOperand->Infinity = FALSE; 04286 DoubleOperand->Nan = TRUE; 04287 04288 } else { 04289 DoubleOperand->Infinity = TRUE; 04290 DoubleOperand->Nan = FALSE; 04291 } 04292 04293 } else { 04294 DoubleOperand->Infinity = FALSE; 04295 DoubleOperand->Nan = FALSE; 04296 DoubleOperand->Normal = TRUE; 04297 if (DoubleOperand->Exponent == DOUBLE_MINIMUM_EXPONENT) { 04298 if ((DoubleOperand->MantissaHigh | DoubleOperand->MantissaLow) != 0) { 04299 if (ContextBlock->SoftwareFpcr->DenormalOperandsEnable == 0) { 04300 DBGPRINT("SoftwareFpcr->DenormalOperandsEnable == 0\n"); 04301 DoubleOperand->MantissaHigh = 0; 04302 DoubleOperand->MantissaLow = 0; 04303 DoubleOperand->Exponent = 0; 04304 } else { 04305 DoubleOperand->Normal = FALSE; 04306 DoubleOperand->Exponent += 1; 04307 while ((DoubleOperand->MantissaHigh & (1 << 20)) == 0) { 04308 DoubleOperand->MantissaHigh = 04309 (DoubleOperand->MantissaHigh << 1) | 04310 (DoubleOperand->MantissaLow >> 31); 04311 DoubleOperand->MantissaLow <<= 1; 04312 DoubleOperand->Exponent -= 1; 04313 } 04314 } 04315 } 04316 04317 } else { 04318 DoubleOperand->MantissaHigh |= (1 << 20); 04319 } 04320 } 04321 04322 // 04323 // Left shift the mantissa 2-bits to provide for a guard bit and a round 04324 // bit. 04325 // 04326 04327 DoubleOperand->MantissaHigh = 04328 (DoubleOperand->MantissaHigh << 2) | (DoubleOperand->MantissaLow >> 30); 04329 DoubleOperand->MantissaLow <<= 2; 04330 DBGPRINT("KiUnpackDouble: Inf=%d NaN=%d Sign=%d Exponent=%d Mantissa=%.8x%.8x\n", 04331 DoubleOperand->Infinity, DoubleOperand->Nan, DoubleOperand->Sign, 04332 DoubleOperand->Exponent, 04333 DoubleOperand->MantissaHigh, DoubleOperand->MantissaLow); 04334 04335 return; 04336 }

VOID KiUnpackSingle IN ULONG  Source,
IN PFP_CONTEXT_BLOCK  ContextBlock,
OUT PFP_SINGLE_OPERAND  SingleOperand
 

Definition at line 4339 of file alpha/floatem.c.

References DBGPRINT, FALSE, KiConvertRegisterToSingleOperand(), KiGetRegisterValue(), and TRUE.

04347 : 04348 04349 This function is called to unpack a single floating value from the 04350 specified source register. 04351 04352 N.B. The unpacked mantissa value is returned with a guard bit and a 04353 round bit on the right and the hidden bit inserted if appropriate. 04354 The format of the returned value is: 04355 04356 <31:26> - zero 04357 <25> - hidden bit 04358 <24:2> - mantissa 04359 <1> - guard bit 04360 <0> - round bit 04361 04362 Arguments: 04363 04364 Source - Supplies the number of the register that contains the operand. 04365 04366 ContextBlock - Supplies a pointer to the emulation context block. 04367 04368 SingleOperand - Supplies a pointer to a structure that is to receive the 04369 operand value. 04370 04371 Return Value: 04372 04373 None. 04374 04375 --*/ 04376 04377 { 04378 04379 ULONG Value; 04380 04381 // 04382 // Get the source register value and unpack the sign, exponent, and 04383 // mantissa value. 04384 // 04385 04386 Value = KiConvertRegisterToSingleOperand( 04387 KiGetRegisterValue(Source + 32, 04388 ContextBlock->ExceptionFrame, 04389 ContextBlock->TrapFrame)); 04390 04391 SingleOperand->Sign = Value >> 31; 04392 SingleOperand->Exponent = (Value >> 23) & 0xff; 04393 SingleOperand->Mantissa = Value & 0x7fffff; 04394 04395 // 04396 // If the exponent is the largest possible value, then the number is 04397 // either a NaN or an infinity. Otherwise if the exponent is the smallest 04398 // possible value and the mantissa is nonzero, then the number is 04399 // denormalized. Otherwise the number is finite and normal. 04400 // 04401 04402 if (SingleOperand->Exponent == SINGLE_MAXIMUM_EXPONENT) { 04403 SingleOperand->Normal = FALSE; 04404 if (SingleOperand->Mantissa != 0) { 04405 SingleOperand->Infinity = FALSE; 04406 SingleOperand->Nan = TRUE; 04407 04408 } else { 04409 SingleOperand->Infinity = TRUE; 04410 SingleOperand->Nan = FALSE; 04411 } 04412 04413 } else { 04414 SingleOperand->Infinity = FALSE; 04415 SingleOperand->Nan = FALSE; 04416 SingleOperand->Normal = TRUE; 04417 if (SingleOperand->Exponent == SINGLE_MINIMUM_EXPONENT) { 04418 if (SingleOperand->Mantissa != 0) { 04419 if (ContextBlock->SoftwareFpcr->DenormalOperandsEnable == 0) { 04420 DBGPRINT("SoftwareFpcr->DenormalOperandsEnable == 0\n"); 04421 SingleOperand->Mantissa = 0; 04422 SingleOperand->Exponent = 0; 04423 } else { 04424 SingleOperand->Normal = FALSE; 04425 SingleOperand->Exponent += 1; 04426 while ((SingleOperand->Mantissa & (1 << 23)) == 0) { 04427 SingleOperand->Mantissa <<= 1; 04428 SingleOperand->Exponent -= 1; 04429 } 04430 } 04431 } 04432 04433 } else { 04434 SingleOperand->Mantissa |= (1 << 23); 04435 } 04436 } 04437 04438 // 04439 // Left shift the mantissa 2-bits to provide for a guard bit and a round 04440 // bit. 04441 // 04442 04443 SingleOperand->Mantissa <<= 2; 04444 DBGPRINT("KiUnpackSingle: Inf=%d NaN=%d Sign=%d Exponent=%d Mantissa=%.8x\n", 04445 SingleOperand->Infinity, SingleOperand->Nan, SingleOperand->Sign, 04446 SingleOperand->Exponent, SingleOperand->Mantissa); 04447 return; 04448 } }


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