⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 float.c

📁 WinCE5.0部分核心源码
💻 C
📖 第 1 页 / 共 5 页
字号:
    BOOLEAN fCop1XInstruction;
    FP_SINGLE_OPERAND SingleOperand4;
    FP_DOUBLE_OPERAND DoubleOperand4;
#endif
    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.
        //
        if (cause.BD)
            ContextBlock.BranchAddress = KiEmulateBranch(pctx);
        else
            ContextBlock.BranchAddress = pctx->Fir + 4;

        //
        // Initialize the address of the exception record, exception frame,
        // and trap frame in the context block used during the emulation of
        // the floating point operation.
        //

        ContextBlock.ExceptionRecord = ExceptionRecord;
        ContextBlock.pctx = pctx;
        ContextBlock.Round = ((PFSR)&pctx->Fsr)->RM;

        //
        // Initialize the number of exception information parameters, set
        // the branch address, and clear the IEEE exception value.
        //

        ExceptionRecord->NumberParameters = 6;
        ExceptionRecord->ExceptionInformation[0] = 0;
        ExceptionRecord->ExceptionInformation[1] = ContextBlock.BranchAddress;
        ExceptionRecord->ExceptionInformation[2] = 0;
        ExceptionRecord->ExceptionInformation[3] = 0;
        ExceptionRecord->ExceptionInformation[4] = 0;
        ExceptionRecord->ExceptionInformation[5] = 0;

        //
        // Clear all exception flags and emulate the floating point operation
        // The return value is dependent on the results of the emulation.
        //

        pctx->Fsr &= ~(0x3f << 12);
        Instruction = *((PMIPS_INSTRUCTION)ExceptionAddress + (cause.BD ? 1 : 0));
#ifdef _MIPS64
        if (Instruction.c_format.Opcode == COP1X_OP) {
            fCop1XInstruction = TRUE;
            Function = Instruction.cx_format.Function;
            ContextBlock.Fd = Instruction.cx_format.Fd;
            Fs = Instruction.cx_format.Fs;
            Ft = Instruction.cx_format.Ft;
            Fr = Instruction.cx_format.Fr;
            Format = Instruction.cx_format.Format;
        } else {
            fCop1XInstruction = FALSE;
            Function = Instruction.c_format.Function;
            ContextBlock.Fd = Instruction.c_format.Fd;
            Fs = Instruction.c_format.Fs;
            Ft = Instruction.c_format.Ft;
            Format = Instruction.c_format.Format;
        }
#else
        Function = Instruction.c_format.Function;
        ContextBlock.Fd = Instruction.c_format.Fd;
        Fs = Instruction.c_format.Fs;
        Ft = Instruction.c_format.Ft;
        Format = Instruction.c_format.Format;
#endif
        Negation = 0;

        //
        // Check for illegal register specification or format code.
        // NOTE: only MIPS64 use odd-number floating registers (fr1, fr3, fr5, ...)
        //

        if (
#ifndef _MIPS64
            ((ContextBlock.Fd & 0x1) != 0) || ((Fs & 0x1) != 0) || ((Ft & 0x1) != 0) ||
#endif
            ((Format != FORMAT_LONGWORD) && (Format != FORMAT_QUADWORD) && (Format > FORMAT_DOUBLE))) {
            Function = FLOAT_ILLEGAL;
        }

        //
        // Decode operand values and dispose with NaNs.
        //
#ifdef _MIPS64
        if (fCop1XInstruction) {
            if (Function >= FLOAT_MADD && Function <= FLOAT_NMSUB) {

                //
                // The function has three operand values
                //

                if (Format == FORMAT_SINGLE) {
                    KiUnpackSingle(Fs, &ContextBlock, &SingleOperand1);
                    KiUnpackSingle(Ft, &ContextBlock, &SingleOperand2);
                    KiUnpackSingle(Fr, &ContextBlock, &SingleOperand4);

                    //
                    // If one of operand is a NaN, then it is a Dyadic operation
                    //
                    if (SingleOperand1.Nan != FALSE || SingleOperand2.Nan != FALSE || SingleOperand4.Nan != FALSE) {
                        //
                        // Dyadic operation.
                        //
                        // Store a quite Nan if the invalid operation trap
                        // is disabled, or raise an exception if the invalid
                        // operation trap is enabled and either of the NaNs
                        // is a signally NaN.
                        //
                        return KiInvalidOperationSingle(&ContextBlock,
                                                        TRUE,
                                                        &SingleOperand1,
                                                        (SingleOperand2.Nan != FALSE) ? &SingleOperand2 : &SingleOperand4);
                    }

                } else if (Format == FORMAT_DOUBLE) {
                    KiUnpackDouble(Fs, &ContextBlock, &DoubleOperand1);
                    KiUnpackDouble(Ft, &ContextBlock, &DoubleOperand2);
                    KiUnpackDouble(Fr, &ContextBlock, &DoubleOperand4);

                    //
                    // If one of operand is a NaN, then it is a Dyadic operation
                    //
                    if (DoubleOperand1.Nan != FALSE || DoubleOperand2.Nan != FALSE || DoubleOperand4.Nan != FALSE) {
                        //
                        // Dyadic operation.
                        //
                        // Store a quite Nan if the invalid operation trap
                        // is disabled, or raise an exception if the invalid
                        // operation trap is enabled and either of the NaNs
                        // is a signally NaN.
                        //

                        return KiInvalidOperationDouble(&ContextBlock,
                                                        TRUE,
                                                        &DoubleOperand1,
                                                        (DoubleOperand2.Nan != FALSE) ? &DoubleOperand2 : &DoubleOperand4);
                    }
                } else {
                    //
                    // invalid format
                    //
                    Function = FLOAT_ILLEGAL;
                }
            } else {
                //
                // invalid instruction
                //
                Function = FLOAT_ILLEGAL;
            }
        } else 
#endif
        if ((Function <= FLOAT_DIVIDE) || (Function >= FLOAT_COMPARE)) {

            //
            // The function has two operand values.
            //

            if (Format == FORMAT_SINGLE) {
                KiUnpackSingle(Fs, &ContextBlock, &SingleOperand1);
                KiUnpackSingle(Ft, &ContextBlock, &SingleOperand2);

                //
                // If either operand is a NaN, then check to determine if a
                // compare instruction or other dyadic operation is being
                // performed.
                //

                if ((SingleOperand1.Nan != FALSE) || (SingleOperand2.Nan != FALSE)) {
                    if (Function < FLOAT_COMPARE) {

                        //
                        // Dyadic operation.
                        //
                        // Store a quite Nan if the invalid operation trap
                        // is disabled, or raise an exception if the invalid
                        // operation trap is enabled and either of the NaNs
                        // is a signally NaN.
                        //

                        return KiInvalidOperationSingle(&ContextBlock,
                                                        TRUE,
                                                        &SingleOperand1,
                                                        &SingleOperand2);

                    } else {

                        //
                        // Compare operation.
                        //
                        // Set the condition based on the predicate of
                        // the floating comparison.
                        //
                        // If the compare is a signaling compare, then
                        // raise an exception if the invalid operation
                        // trap is enabled. Otherwise, raise an exception
                        // if one of the operands is a signaling NaN.
                        //

                        if ((Function & COMPARE_UNORDERED_MASK) != 0) {
                            ((PFSR)&pctx->Fsr)->CC = 1;

                        } else {
                            ((PFSR)&pctx->Fsr)->CC = 0;
                        }

                        if ((Function & COMPARE_ORDERED_MASK) != 0) {
                            return KiInvalidCompareSingle(&ContextBlock,
                                                          FALSE,
                                                          &SingleOperand1,
                                                          &SingleOperand2);

                        } else {
                            return KiInvalidCompareSingle(&ContextBlock,
                                                          TRUE,
                                                          &SingleOperand1,
                                                          &SingleOperand2);

                        }
                    }

                } else if (Function >= FLOAT_COMPARE) {
                    CompareFunction = Function;
                    Function = FLOAT_COMPARE_SINGLE;
                }

            } else if (Format == FORMAT_DOUBLE) {
                KiUnpackDouble(Fs, &ContextBlock, &DoubleOperand1);
                KiUnpackDouble(Ft, &ContextBlock, &DoubleOperand2);

                //
                // If either operand is a NaN, then check to determine if a
                // compare instruction or other dyadic operation is being
                // performed.
                //

                if ((DoubleOperand1.Nan != FALSE) || (DoubleOperand2.Nan != FALSE)) {
                    if (Function < FLOAT_COMPARE) {

                        //
                        // Dyadic operation.
                        //
                        // Store a quite Nan if the invalid operation trap
                        // is disabled, or raise an exception if the invalid
                        // operation trap is enabled and either of the NaNs
                        // is a signally NaN.
                        //

                        return KiInvalidOperationDouble(&ContextBlock,
                                                        TRUE,
                                                        &DoubleOperand1,
                                                        &DoubleOperand2);

                    } else {

                        //
                        // Compare operation.
                        //
                        // Set the condition based on the predicate of
                        // the floating comparison.
                        //
                        // If the compare is a signaling compare, then
                        // raise an exception if the invalid operation
                        // trap is enabled. Othersie, raise an exception
                        // if one of the operands is a signaling NaN.
                        //

                        if ((Function & COMPARE_UNORDERED_MASK) != 0) {
                            ((PFSR)&pctx->Fsr)->CC = 1;

                        } else {
                            ((PFSR)&pctx->Fsr)->CC = 0;
                        }

                        if ((Function & COMPARE_ORDERED_MASK) != 0) {
                            return KiInvalidCompareDouble(&ContextBlock,
                                                          FALSE,
                                                          &DoubleOperand1,
                                                          &DoubleOperand2);

                        } else {
                            return KiInvalidCompareDouble(&ContextBlock,
                                                          TRUE,
                                                          &DoubleOperand1,
                                                          &DoubleOperand2);

                        }
                    }

                } else if (Function >= FLOAT_COMPARE) {
                    CompareFunction = Function;
                    Function = FLOAT_COMPARE_DOUBLE;
                }

            } else {
                Function = FLOAT_ILLEGAL;
            }

        } else {

            //
            // The function has one operand value.
            //

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -