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

📄 vfp.c

📁 ARM9基于WINDOWSCE的BSP源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
        default:
            break;
        }
        if (fAdd1) {
            FPStatus.iterations = (FPStatus.iterations + 1) & 7;
        }
#endif  // REV0_QUOTE_FEATURE
    }

    FPStatus.Rn = VFPir_DecodeRegister(FPStatus.FPINST, FPStatus.precision, RN_LSB);
    FPStatus.Rm = VFPir_DecodeRegister(FPStatus.FPINST, FPStatus.precision, RM_LSB);
    FPStatus.Rd = VFPir_DecodeRegister(FPStatus.FPINST, FPStatus.precision, RD_LSB);

    // save the interrupt enable bits. Need to restore them after calling the handler
    fpctrl = FPStatus.FPSCR & FPSCR_IE_MASK;

    // clear emulator status first
    _clearfp ();

    // get the software exception enable bits and mask all of them
    // so we don't get exception running emulator's code
    dwIeee = FpscrToIeee (fpctrl);

    __try {
        if (FPStatus.precision == DOUBLE_PRECISION) {
            ret_val = VFPir_DoubleHandler(&FPStatus, pctx);
        } else {
            ret_val = VFPir_SingleHandler(&FPStatus, pctx);
        }
    } __except (EXCEPTION_EXECUTE_HANDLER) {
        ret_val = FALSE;    // unable to handle the exception
    }

    emstat = _statusfp ();   // get the new emulator status status
    
    // updaet emulator fp control to match hardware
    _controlfp (dwIeee, _MCW_EM);

    if (ret_val) {
        DWORD code = CheckException (FPStatus.FPSCR, emstat);
        // exception handled, report exception if we need to
        if (code) {
            pEr->ExceptionCode = code;
            ret_val = FALSE;
        } else {
            // clear control registers
            pctx->FpExtra[FPINST_REG] = 0;
            VFP10RestoreCtrlRegs (pctx->FpExtra, 1);    // update registers

            // restore exception control bits and update thread context
            pctx->Fpscr = (FPStatus.FPSCR & ~FPSCR_IE_MASK) | fpctrl;
        }
    }

    return ret_val;
}

/*****************************************************************************
*
* int VFPir_SingleHandler (_FPStruct *ptrFPStatus, PCONTEXT pctx)
*
* Handles the single precision floating point exceptions (or possible 
* exceptions). After excution of each operation the number of exceptions is 
* tested to determine if an exception occurred. If an exception did occur and 
* the exception was enabled by the user the floating point status is saved and 
* passed onto the users handler on exit from the VFP exception handling code.
*
*       ptrFPStatus :   Pointer to the floating point status structure.
*
******************************************************************************/
BOOL VFPir_SingleHandler (_FPStruct *ptrFPStatus, PCONTEXT pctx)
{
    SingleIntUnion tmp_dest, tmp_rhs;
    float dest;
    float rhs, lhs;
    double dest_double;
    int i;
    DWORD temp_emctrl;

    for (i = 0; i <= (int)ptrFPStatus->iterations; i++)
    {
        lhs = VFP_GetRegSingle (ptrFPStatus->Rn, pctx);   
        rhs = VFP_GetRegSingle (ptrFPStatus->Rm, pctx);   
        dest = VFP_GetRegSingle (ptrFPStatus->Rd, pctx);

        // dest = Fd    lhs = Fn    rhs = Fm
        switch (ptrFPStatus->opcode)
        {
            case FMAC:      // Fd = Fd + (Fn * Fm)
                rhs = lhs * rhs;
                dest = dest + rhs;
                VFP_SetRegSingle (ptrFPStatus->Rd, dest, pctx);
                break;
            case FNMAC:     // Fd = Fd - (Fn * Fm)
                rhs = lhs * rhs;
                dest = dest - rhs;
                VFP_SetRegSingle (ptrFPStatus->Rd, dest, pctx);
                break;
            case FMSC:      // Fd = -Fd + (Fn * Fm)
                rhs = lhs * rhs;
                lhs = -dest;  
                dest = lhs + rhs;
                VFP_SetRegSingle (ptrFPStatus->Rd, dest, pctx);
                break;
            case FNMSC:     // Fd = -Fd - (Fn * Fm)
                rhs = lhs * rhs;
                lhs = -dest;
                dest = dest - rhs;
                VFP_SetRegSingle (ptrFPStatus->Rd, dest, pctx);
                break;
            case FMUL:      // Fd = Fn * Fm
                dest = lhs * rhs;
                break;
            case FNMUL:     // Fd = -(Fn * Fm)
                rhs = lhs * rhs;
                dest = -rhs;
                VFP_SetRegSingle (ptrFPStatus->Rd, dest, pctx);
                break;
            case FADD:      // Fd = Fn + Fm
                dest = lhs + rhs;
                VFP_SetRegSingle (ptrFPStatus->Rd, dest, pctx);
                break;
            case FSUB:      // Fd = Fn - Fm
                dest = lhs - rhs;
                VFP_SetRegSingle (ptrFPStatus->Rd, dest, pctx);
                break;
            case FDIV:      // Fd = Fn / Fm
                dest = lhs / rhs;
                VFP_SetRegSingle (ptrFPStatus->Rd, dest, pctx);
                break;
            case EXTEND:    // Extended operations
                switch (ptrFPStatus->opcode_ext)
                {
                    case FCPY:      // Fd = Fm
                        VFP_SetRegSingle (ptrFPStatus->Rd, rhs, pctx);
                        break;
                    case FABS:      // Fd = abs(Fm)
                        dest = (float) fabs(rhs);
                        VFP_SetRegSingle (ptrFPStatus->Rd, dest, pctx);
                        break;
                    case FNEG:      // Fd = -(Fm)
                        dest = -rhs;
                        VFP_SetRegSingle (ptrFPStatus->Rd, dest, pctx);
                        break;
                    case FSQRT:     // Fd = sqrt(Fm)
                        dest = (float) sqrt (rhs);
                        VFP_SetRegSingle (ptrFPStatus->Rd, dest, pctx);
                        break;
                    case FCMP:      // Flags := Fd <> Fm
                        ptrFPStatus->FPSCR &= 0x0FFFFFFF; // Clear current flags
                        ptrFPStatus->iterations = 0;
                        tmp_dest.as_float = dest;
                        tmp_rhs.as_float = rhs;
                        
                        if (dest == rhs)
                            ptrFPStatus->FPSCR |= EQUAL_TO;
                        else if (dest < rhs)
                            ptrFPStatus->FPSCR |= LESS_THAN;
                        else if (dest > rhs)
                            ptrFPStatus->FPSCR |= GREATER_THAN;
                        else {
                            // Only signal if there is a S-NAN
                            ptrFPStatus->FPSCR |= UNORDERED;
                            ptrFPStatus->FPSCR &= ~FPSCR_IE_MASK;   // default no exception
                            if (!SIGNAL_NaN_S(tmp_dest.as_unsignedint) && !SIGNAL_NaN_S(tmp_rhs.as_unsignedint)) {
                                // signal invalid
                                ptrFPStatus->FPSCR |= FPSCR_IOE;
                            }
                        }
                        break;
                    case FCMPE:     // Flags := Fd <> Fm with exception reporting
                        ptrFPStatus->FPSCR &= 0x0FFFFFFF; // Clear current flags
                        ptrFPStatus->iterations = 0;
                        tmp_dest.as_float = dest;
                        tmp_rhs.as_float = rhs;
                        if (dest == rhs)
                            ptrFPStatus->FPSCR |= EQUAL_TO;
                        else if (dest < rhs)
                            ptrFPStatus->FPSCR |= LESS_THAN;
                        else if (dest > rhs)
                            ptrFPStatus->FPSCR |= GREATER_THAN;
                        else {
                            // signal as long as there's a NAN.
                            ptrFPStatus->FPSCR &= ~FPSCR_IE_MASK;   // default no exception
                            ptrFPStatus->FPSCR |= UNORDERED;
                            if (SIGNAL_NaN_S(tmp_dest.as_unsignedint)
                                || QUIET_NaN_S(tmp_dest.as_unsignedint)
                                || SIGNAL_NaN_S(tmp_rhs.as_unsignedint)
                                || QUIET_NaN_S(tmp_rhs.as_unsignedint)) {
                                // signal invalid
                                ptrFPStatus->FPSCR |= FPSCR_IOE;
                            }
                        }
                        
                        break;
                    case FCMPZ:     // Flags := Fd <> Zero
                        ptrFPStatus->FPSCR &= 0x0FFFFFFF; // Clear current flags
                        ptrFPStatus->iterations = 0;
                        tmp_dest.as_float = dest;

                        if (dest == (float) 0.0)                        
                            ptrFPStatus->FPSCR |= EQUAL_TO;
                        else if (dest < (float) 0.0)
                            ptrFPStatus->FPSCR |= LESS_THAN;                            
                        else if (dest > (float) 0.0)
                            ptrFPStatus->FPSCR |= GREATER_THAN;
                        else {
                            // Only signal if there is a S-NAN
                            ptrFPStatus->FPSCR &= ~FPSCR_IE_MASK;   // default no exception
                            ptrFPStatus->FPSCR |= UNORDERED;
                            if (!SIGNAL_NaN_S(tmp_dest.as_unsignedint)) {
                                // signal invalid
                                ptrFPStatus->FPSCR |= FPSCR_IOE;
                            }
                        }
                        break;
                    case FCMPEZ:    // Flags := Fd <> Zero with exception reporting
                        ptrFPStatus->FPSCR &= 0x0FFFFFFF; // Clear current flags
                        ptrFPStatus->iterations = 0;
                        tmp_dest.as_float = dest;

                        if (dest == (float) 0.0)                        
                            ptrFPStatus->FPSCR |= EQUAL_TO;
                        else if (dest < (float) 0.0)
                            ptrFPStatus->FPSCR |= LESS_THAN;                            
                        else if (dest > (float) 0.0)
                            ptrFPStatus->FPSCR |= GREATER_THAN;
                        else {
                            ptrFPStatus->FPSCR &= ~FPSCR_IE_MASK;   // default no exception
                            ptrFPStatus->FPSCR |= UNORDERED;
                            if (SIGNAL_NaN_S(tmp_dest.as_unsignedint) || QUIET_NaN_S(tmp_dest.as_unsignedint)) {
                                // signal invalid
                                ptrFPStatus->FPSCR |= FPSCR_IOE;
                            }
                        }
                        break;
                    case FCVTDS:    // Fd(double reg encoding) = Fm(single reg encoding)
                        ptrFPStatus->iterations = 0;
                        dest_double = rhs;
                        VFP_SetRegDouble (VFPir_DecodeRegister(ptrFPStatus->FPINST, DOUBLE_PRECISION, RD_LSB),
                                dest_double, pctx);
                        break;                      
                    case FUITOS:    // Fd = ConvertUnsignedIntToSingle Fm (cp 10)
                        ptrFPStatus->iterations = 0;
                        tmp_rhs.as_float = rhs;
                        dest = (float) tmp_rhs.as_unsignedint;
                        VFP_SetRegSingle (ptrFPStatus->Rd, dest, pctx);
                        break;                                              
                    case FSITOS:    // Fd = ConvertSignedIntToSingle Fm (cp 10)
                        ptrFPStatus->iterations = 0;
                        tmp_rhs.as_float = rhs;
                        dest = (float) tmp_rhs.as_signedint;
                        VFP_SetRegSingle (ptrFPStatus->Rd, dest, pctx);
                        break;                                              
                    case FTOUIS:    // Fd = ConvertToUnsignedInt Fm (cp 10 single Current RMODE)
                        ptrFPStatus->iterations = 0;
                        tmp_rhs.as_unsignedint = (unsigned int) rhs;
                        VFP_SetRegSingle (ptrFPStatus->Rd, tmp_rhs.as_float, pctx);
                        break;
                    case FTOUIZS:   // Fd = ConvertToUnsignedInt Fm <cp 10 single RZ Mode)
                        ptrFPStatus->iterations = 0;
                        // Set the software status to Round Towards Zero
                        temp_emctrl = _controlfp (_RC_DOWN, _MCW_RC);
                        tmp_rhs.as_unsignedint = (unsigned int) rhs;
                        VFP_SetRegSingle (ptrFPStatus->Rd, tmp_rhs.as_float, pctx);
                        // Return the software status
                        _controlfp (temp_emctrl, _MCW_RC);
                        break;                                              
                    case FTOSIS:    // Fd = ConvertToSignedInt Fm (cp 10 single Current RMODE)
                        ptrFPStatus->iterations = 0;
                        tmp_rhs.as_signedint = (int) rhs;
                        VFP_SetRegSingle (ptrFPStatus->Rd, tmp_rhs.as_float, pctx);
                        break;                                          
                    case FTOSIZS:   // Fd = ConvertToSignedInt Fm (cp 10 single RZ mode)
                        ptrFPStatus->iterations = 0;
                        // Set the software status to Round Towards Zero
                        temp_emctrl = _controlfp (_RC_DOWN, _MCW_RC);
                        tmp_rhs.as_signedint = (int) rhs;
                        VFP_SetRegSingle (ptrFPStatus->Rd, tmp_rhs.as_float, pctx);

⌨️ 快捷键说明

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