📄 float.c
字号:
#ifdef MIPS_HAS_FPU/*++Copyright (c) 1991-2000 Microsoft Corporation. All rights reserved.Module Name: floatem.cAbstract: This module implements a software emulation of the IEEE single and double floating operations. It is required on MIPS processors since the hardware does not fully support all of the operations required by the IEEE standard. In particular, infinitives and Nans are not handled by the hardware, but rather cause an exception. On receipt of the exception, a software emulation of the floating operation is performed to determine the real result of the operation and if an exception will actually be raised. Since floating exceptions are rather rare events, this routine is written in C. Should a higher performance implementation be required, then the algorithms contained herein, can be used to guide a higher performance assembly language implementation. N.B. This routine does not emulate floating loads, floating stores, control to/from floating, or move to/from floating instructions. These instructions either do not fault or are emulated elsewhere. Floating point operations are carried out by unpacking the operands, normalizing denormalized numbers, checking for NaNs, interpreting infinities, and computing results. Floating operands are converted to a format that has a value with the appropriate number of leading zeros, an overflow bit, the mantissa, a guard bit, a round bit, and a set of sticky bits. The overflow bit is needed for addition and is also used for multiply. The mantissa is 24-bits for single operations and 53-bits for double operations. The guard bit and round bit are used to hold precise values for normalization and rounding. If the result of an operation is normalized, then the guard bit becomes the round bit and the round bit is accumulated with the sticky bits. If the result of an operation needs to be shifted left one bit for purposes of nomalization, then the guard bit becomes part of the mantissa and the round bit is used for rounding. The round bit plus the sticky bits are used to determine how rounding is performed.Environment: Kernel mode only.--*/#include "kernel.h"#include "ntxcapi.h"//// Define signaling NaN mask values.//#define DOUBLE_SIGNAL_NAN_MASK (1 << (53 - 32))#define SINGLE_SIGNAL_NAN_MASK (1 << 24)//// Define quite NaN mask values.//#define DOUBLE_QUIET_NAN_MASK (1 << (51 - 32))#define SINGLE_QUIET_NAN_MASK (1 << 22)//// Define quiet NaN prefix values.//#define DOUBLE_QUIET_NAN_PREFIX 0x7ff00000#define SINGLE_QUIET_NAN_PREFIX 0x7f800000//// Define compare function masks.//#define COMPARE_UNORDERED_MASK (1 << 0)#define COMPARE_EQUAL_MASK (1 << 1)#define COMPARE_LESS_MASK (1 << 2)#define COMPARE_ORDERED_MASK (1 << 3)//// Define context block structure.//typedef struct _FP_CONTEXT_BLOCK { ULONG Fd; ULONG BranchAddress; PEXCEPTION_RECORD ExceptionRecord; PCONTEXT pctx; ULONG Round;} FP_CONTEXT_BLOCK, *PFP_CONTEXT_BLOCK;//// Define single and double operand value structures.//typedef struct _FP_DOUBLE_OPERAND { union { struct { ULONG MantissaLow; LONG MantissaHigh; }; LONGLONG Mantissa; }; LONG Exponent; LONG Sign; BOOLEAN Infinity; BOOLEAN Nan;} FP_DOUBLE_OPERAND, *PFP_DOUBLE_OPERAND;typedef struct _FP_SINGLE_OPERAND { LONG Mantissa; LONG Exponent; LONG Sign; BOOLEAN Infinity; BOOLEAN Nan;} FP_SINGLE_OPERAND, *PFP_SINGLE_OPERAND;//// Define forward referenced function protypes.//BOOLEANKiDivideByZeroDouble ( IN PFP_CONTEXT_BLOCK ContextBlock, IN PFP_DOUBLE_OPERAND DoubleOperand1, IN PFP_DOUBLE_OPERAND DoubleOperand2 );BOOLEANKiDivideByZeroSingle ( IN PFP_CONTEXT_BLOCK ContextBlock, IN PFP_SINGLE_OPERAND SingleOperand1, IN PFP_SINGLE_OPERAND SingleOperand2 );BOOLEANKiInvalidCompareDouble ( IN PFP_CONTEXT_BLOCK ContextBlock, IN BOOLEAN CheckForNan, IN PFP_DOUBLE_OPERAND DoubleOperand1, IN PFP_DOUBLE_OPERAND DoubleOperand2 );BOOLEANKiInvalidCompareSingle ( IN PFP_CONTEXT_BLOCK ContextBlock, IN BOOLEAN CheckForNan, IN PFP_SINGLE_OPERAND SingleOperand1, IN PFP_SINGLE_OPERAND SingleOperand2 );BOOLEANKiInvalidOperationDouble ( IN PFP_CONTEXT_BLOCK ContextBlock, IN BOOLEAN CheckForNan, IN PFP_DOUBLE_OPERAND DoubleOperand1, IN PFP_DOUBLE_OPERAND DoubleOperand2 );BOOLEANKiInvalidOperationLongword ( IN PFP_CONTEXT_BLOCK ContextBlock, IN BOOLEAN Infinity, IN LONG Sign );BOOLEANKiInvalidOperationQuadword ( IN PFP_CONTEXT_BLOCK ContextBlock, IN BOOLEAN Infinity, IN LONG Sign );BOOLEANKiInvalidOperationSingle ( IN PFP_CONTEXT_BLOCK ContextBlock, IN BOOLEAN CheckForNan, IN PFP_SINGLE_OPERAND SingleOperand1, IN PFP_SINGLE_OPERAND SingleOperand2 );BOOLEANKiNormalizeDouble ( IN PFP_CONTEXT_BLOCK ContextBlock, IN PFP_DOUBLE_OPERAND ResultOperand, IN ULONG StickyBits );BOOLEANKiNormalizeLongword ( IN PFP_CONTEXT_BLOCK ContextBlock, IN PFP_DOUBLE_OPERAND ResultOperand );BOOLEANKiNormalizeQuadword ( IN PFP_CONTEXT_BLOCK ContextBlock, IN PFP_DOUBLE_OPERAND ResultOperand );BOOLEANKiNormalizeSingle ( IN PFP_CONTEXT_BLOCK ContextBlock, IN PFP_SINGLE_OPERAND ResultOperand, IN ULONG StickyBits );ULONGKiSquareRootDouble ( IN PULARGE_INTEGER DoubleValue );ULONGKiSquareRootSingle ( IN PULONG SingleValue );VOIDKiUnpackDouble ( IN ULONG Source, IN PFP_CONTEXT_BLOCK ContextBlock, OUT PFP_DOUBLE_OPERAND DoubleOperand );VOIDKiUnpackSingle ( IN ULONG Source, IN PFP_CONTEXT_BLOCK ContextBlock, OUT PFP_SINGLE_OPERAND SingleOperand );ULONGKiEmulateBranch ( IN PCONTEXT pctx ); VOIDKiSetRegisterValue ( IN ULONG Register, IN ULONG Value, IN PCONTEXT pctx );ULONGKiGetRegisterValue ( IN ULONG Register, IN PCONTEXT pctx );BOOL HandleHWFloatException(EXCEPTION_RECORD *ExceptionRecord, PCONTEXT pctx, CAUSE cause) {//BOOLEAN//KiEmulateFloating (// IN OUT PEXCEPTION_RECORD ExceptionRecord,// IN OUT PKEXCEPTION_FRAME ExceptionFrame,// IN OUT PKTRAP_FRAME TrapFrame// )/*++Routine Description: This function is called to emulate a floating operation and convert the exception status to the proper value. If the exception is an unimplemented operation, then the operation is emulated. Otherwise, the status code is just converted to its proper value.Arguments: ExceptionRecord - Supplies a pointer to an exception record. ExceptionFrame - Supplies a pointer to an exception frame. TrapFrame - Supplies a pointer to a trap frame.Return Value: A value of TRUE is returned if the floating exception is successfully emulated. Otherwise, a value of FALSE is returned.--*/ ULARGE_INTEGER AhighBhigh; ULARGE_INTEGER AhighBlow; ULARGE_INTEGER AlowBhigh; ULARGE_INTEGER AlowBlow; ULONG Carry1; ULONG Carry2; BOOLEAN CompareEqual; ULONG CompareFunction; BOOLEAN CompareLess; FP_CONTEXT_BLOCK ContextBlock; LARGE_INTEGER DoubleDividend; LARGE_INTEGER DoubleDivisor; ULARGE_INTEGER DoubleValue; ULONG DoubleMantissaLow; LONG DoubleMantissaHigh; FP_DOUBLE_OPERAND DoubleOperand1; FP_DOUBLE_OPERAND DoubleOperand2; FP_DOUBLE_OPERAND DoubleOperand3; LARGE_INTEGER DoubleQuotient; PVOID ExceptionAddress; ULONG ExponentDifference; ULONG Format; ULONG Fs; ULONG Ft; ULONG Function; ULONG Index; MIPS_INSTRUCTION Instruction; ULARGE_INTEGER LargeResult; LONG Longword; LONG Negation; union { LONGLONG Quadword; LARGE_INTEGER LargeValue; }u; LONG SingleMantissa; FP_SINGLE_OPERAND SingleOperand1; FP_SINGLE_OPERAND SingleOperand2; FP_SINGLE_OPERAND SingleOperand3; ULONG SingleValue; ULONG StickyBits; // // Save the original exception address in case another exception // occurs. // ExceptionAddress = ExceptionRecord->ExceptionAddress; // // Any exception that occurs during the attempted emulation of the // floating operation causes the emulation to be aborted. The new // exception code and information is copied to the original exception // record and a value of FALSE is returned. // try { // // If the exception PC is equal to the fault instruction address // plus four, then the floating exception occurred in the delay // slot of a branch instruction and the continuation address must // be computed by emulating the branch instruction. Note that it // is possible for an exception to occur when the branch instruction // is read from user memory. //
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -