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

📄 mipsfp.c

📁 开放源码实时操作系统源码.
💻 C
📖 第 1 页 / 共 2 页
字号:
        {
        case ADD_INSN:
        case SUB_INSN:
        case MUL_INSN:
        case DIV_INSN:

            if (fp64bit) {
                Cyg_libm_ieee_double_shape_type s1, s2;

                reg2dbl( srcreg1, &s1 );
                reg2dbl( srcreg2, &s2 );

                if ( issubnormal( s1 ) ) {  // flush to 0 and restart
                    // but preserve sign
                    if (s1.number.sign)
                        s1.value = -0.0;
                    else
                        s1.value = 0.0;
                    dbl2reg( &s1, srcreg1 );
                    handled++;
                }

                // We could try flushing both to 0 at the same time, but
                // that's inadvisable if both numbers are very small.
                // Particularly if this is DIV_INSN, when we could therefore
                // get 0/0 even when the program explicitly checked for
                // denominator != 0. That's also why we check s1 first.

                else if (  issubnormal( s2 ) ) {  // flush to 0 and restart
                    // but preserve sign
                    if (s2.number.sign)
                        s2.value = -0.0;
                    else
                        s2.value = 0.0;
                    dbl2reg( &s2, srcreg2 );
                    handled++;
                }

            } else { // 32-bit
                Cyg_libm_ieee_float_shape_type s1, s2;

                reg2flt( srcreg1, &s1 );
                reg2flt( srcreg2, &s2 );

                if ( issubnormal( s1 )) {  // flush to 0 and restart
                    // but preserve sign
                    if (s1.number.sign)
                        s1.value = -0.0;
                    else
                        s1.value = 0.0;
                    flt2reg( &s1, srcreg1 );
                    handled++;
                }
                else if ( issubnormal( s2 ) ) {  // flush to 0 and restart
                    // but preserve sign
                    if (s2.number.sign)
                        s2.value = -0.0;
                    else
                        s2.value = 0.0;
                    flt2reg( &s2, srcreg2 );
                    handled++;
                }
            }
            break;

        case SQRT_INSN:
            if ( fp64bit ) {
                Cyg_libm_ieee_double_shape_type d, s;

                reg2dbl( dstreg, &d );
                reg2dbl( srcreg1, &s );

                if ( issubnormal( s ) ) {  // Sqrt of something tiny is 0
                    // if this is a delay slot, we can't restart properly
                    // so if it is subnormal, clear the source register instead
                    if ( delay_slot ) {
                        // but preserve sign
                        if (s.number.sign)
                            s.value = -0.0;
                        else
                            s.value = 0.0;
                        dbl2reg( &s, srcreg1 );
                    } else {
                        // but preserve sign
                        if (s.number.sign)
                            d.value = -0.0;
                        else
                            d.value = 0.0;
                        dbl2reg( &d, dstreg );
                        regs->pc += 4; // We've dealt with this so move on
                    }
                    handled++;
                }

            } else { // 32-bit
                Cyg_libm_ieee_float_shape_type d, s;

                reg2flt( dstreg, &d );
                reg2flt( srcreg1, &s );

                if ( issubnormal( s ) ) {  // Sqrt of something tiny is 0
                    // if this is a delay slot, we can't restart properly
                    // so if it is subnormal, clear the source register instead
                    if ( delay_slot ) {
                        // but preserve sign
                        if (s.number.sign)
                            s.value = -0.0;
                        else
                            s.value = 0.0;
                        flt2reg( &s, srcreg1 );
                    } else {
                        // but preserve sign
                        if (s.number.sign)
                            d.value = -0.0;
                        else
                            d.value = 0.0;
                        flt2reg( &d, dstreg );
                        regs->pc += 4; // We've dealt with this so move on
                    }
                    handled++;
                }
            }
            break;

        case ABS_INSN:
            // We may as well do this right if we can
            if ( fp64bit ) {
                Cyg_libm_ieee_double_shape_type d, s;

                reg2dbl( dstreg, &d );
                reg2dbl( srcreg1, &s );

                // if this is a delay slot, we can't restart properly
                // so if it is subnormal, clear the source register instead
                if ( delay_slot ) {
                    if ( issubnormal( s ) ) {
                        // The sign is still important for abs in case
                        // there are any further operations on the same
                        // register
                        if (s.number.sign)
                            s.value = -0.0;
                        else
                            s.value = 0.0;
                        dbl2reg( &s, srcreg1 );
                        handled++;
                    }
                } else {
                    d.asi64 = s.asi64;
                    d.number.sign = 0;
                    dbl2reg( &d, dstreg );
                    regs->pc += 4;
                    handled++;
                }
            } else { // 32-bit
                Cyg_libm_ieee_float_shape_type d, s;

                reg2flt( dstreg, &d );
                reg2flt( srcreg1, &s );

                // if this is a delay slot, we can't restart properly
                // so if it is subnormal, clear the source register instead
                if ( delay_slot ) {
                    if ( issubnormal( s ) ) {
                        // The sign is still important for abs in case
                        // there are any further operations on the same
                        // register
                        if (s.number.sign)
                            s.value = -0.0;
                        else
                            s.value = 0.0;
                        flt2reg( &s, srcreg1 );
                        handled++;
                    }
                } else {
                    d.asi32 = s.asi32;
                    d.number.sign = 0;
                    flt2reg( &d, dstreg );
                    regs->pc += 4;
                    handled++;
                }
            }
            break;

        case MOV_INSN:
            // We may as well do this right if we can
            if ( fp64bit ) {
                Cyg_libm_ieee_double_shape_type d, s;

                reg2dbl( dstreg, &d );
                reg2dbl( srcreg1, &s );

                // if this is a delay slot, we can't restart properly
                // so if it is subnormal, clear the source register instead
                if ( delay_slot ) {
                    if ( issubnormal( s ) ) {
                        // but preserve sign
                        if (s.number.sign)
                            s.value = -0.0;
                        else
                            s.value = 0.0;
                        dbl2reg( &s, srcreg1 );
                        handled++;
                    }
                } else {
                    d.asi64 = s.asi64;
                    dbl2reg( &d, dstreg );
                    regs->pc += 4;
                    handled++;
                }
            } else { // 32-bit
                Cyg_libm_ieee_float_shape_type d, s;

                reg2flt( dstreg, &d );
                reg2flt( srcreg1, &s );

                // if this is a delay slot, we can't restart properly
                // so if it is subnormal, clear the source register instead
                if ( delay_slot ) {
                    if ( issubnormal( s ) ) {
                        // The sign is still important for abs in case
                        // there are any further operations on the same
                        // register
                        if (s.number.sign)
                            s.value = -0.0;
                        else
                            s.value = 0.0;
                        flt2reg( &s, srcreg1 );
                        handled++;
                    }
                } else {
                    d.asi32 = s.asi32;
                    flt2reg( &d, dstreg );
                    regs->pc += 4;
                    handled++;
                }
            }
            break;

        case NEG_INSN:
            // We may as well do this right if we can
            if ( fp64bit ) {
                Cyg_libm_ieee_double_shape_type d, s;

                reg2dbl( dstreg, &d );
                reg2dbl( srcreg1, &s );

                // if this is a delay slot, we can't restart properly
                // so if it is subnormal, clear the source register instead
                if ( delay_slot ) {
                    if ( issubnormal( s ) ) {
                        // but preserve sign
                        if (s.number.sign)
                            s.value = -0.0;
                        else
                            s.value = 0.0;
                        dbl2reg( &s, srcreg1 );
                        handled++;
                    }
                } else {
                    d.asi64 = s.asi64;
                    d.number.sign = s.number.sign ? 0 : 1;
                    dbl2reg( &d, dstreg );
                    regs->pc += 4;
                    handled++;
                }
            } else { // 32-bit
                Cyg_libm_ieee_float_shape_type d, s;

                reg2flt( dstreg, &d );
                reg2flt( srcreg1, &s );

                // if this is a delay slot, we can't restart properly
                // so if it is subnormal, clear the source register instead
                if ( delay_slot ) {
                    if ( issubnormal( s ) ) {
                        // but preserve sign
                        if (s.number.sign)
                            s.value = -0.0;
                        else
                            s.value = 0.0;
                        flt2reg( &s, srcreg1 );
                        handled++;
                    }
                } else {
                    d.asi32 = s.asi32;
                    d.number.sign = s.number.sign ? 0 : 1;
                    flt2reg( &d, dstreg );
                    regs->pc += 4;
                    handled++;
                }
            }
            break;

        // We can't do much about floating-point to fixed-point arithmetic
        // without emulating the FPU here ourselves!
        // So simply zero denormalized numbers
        case ROUNDL_INSN:
        case TRUNCL_INSN:
        case CEILL_INSN:
        case FLOORL_INSN:
        case ROUNDW_INSN:
        case TRUNCW_INSN:
        case CEILW_INSN:
        case FLOORW_INSN:
        case CVTS_INSN:
        case CVTD_INSN:
        case CVTW_INSN:
        case CVTL_INSN:
            
            if ( fp64bit ) {
                Cyg_libm_ieee_double_shape_type s;

                reg2dbl( srcreg1, &s );

                // just try and 0 the source register if it is subnormal
                if ( issubnormal( s ) ) {
                    // but preserve sign
                    if (s.number.sign)
                        s.value = -0.0;
                    else
                        s.value = 0.0;
                    dbl2reg( &s, srcreg1 );
                    handled++;
                }
            } else { // 32-bit
                Cyg_libm_ieee_float_shape_type s;

                reg2flt( srcreg1, &s );

                // just try and 0 the source register if it is subnormal
                if ( issubnormal( s ) ) {
                    // but preserve sign
                    if (s.number.sign)
                        s.value = -0.0;
                    else
                        s.value = 0.0;
                    flt2reg( &s, srcreg1 );
                    handled++;
                }
            }
            break;

        default:
            // check for floating-point compare (C.cond.fmt)
            if ( (insn & 0x30) == 0x30 ) {
                if (fp64bit) {
                    Cyg_libm_ieee_double_shape_type s1, s2;
                    
                    reg2dbl( srcreg1, &s1 );
                    reg2dbl( srcreg2, &s2 );
                    
                    if ( issubnormal( s1 ) ) {  // flush to 0 and restart
                        // but preserve sign
                        if (s1.number.sign)
                            s1.value = -0.0;
                        else
                            s1.value = 0.0;
                        dbl2reg( &s1, srcreg1 );
                        handled++;
                    }
                    
                    if (  issubnormal( s2 ) ) {  // flush to 0 and restart
                        // but preserve sign
                        if (s2.number.sign)
                            s2.value = -0.0;
                        else
                            s2.value = 0.0;
                        dbl2reg( &s2, srcreg2 );
                        handled++;
                    }
                    
                } else { // 32-bit
                    Cyg_libm_ieee_float_shape_type s1, s2;
                    
                    reg2flt( srcreg1, &s1 );
                    reg2flt( srcreg2, &s2 );
                    
                    if ( issubnormal( s1 )) {  // flush to 0 and restart
                        // but preserve sign
                        if (s1.number.sign)
                            s1.value = -0.0;
                        else
                            s1.value = 0.0;
                        flt2reg( &s1, srcreg1 );
                        handled++;
                    }
                    if ( issubnormal( s2 ) ) {  // flush to 0 and restart
                        // but preserve sign
                        if (s2.number.sign)
                            s2.value = -0.0;
                        else
                            s2.value = 0.0;
                        flt2reg( &s2, srcreg2 );
                        handled++;
                    }
                } // else 
            } // if
            break;
        } // switch
    } // if (computational_insn && !fixedpoint)
    
    if ( handled != 0) {
        // We must clear the cause and flag bits before restoring FPCR31
        regs->fcr31 &= ~(FCR31_CAUSE_E | FCR31_CAUSE_V | FCR31_CAUSE_Z |
                         FCR31_CAUSE_O | FCR31_CAUSE_U | FCR31_CAUSE_I |
                         FCR31_FLAGS_V | FCR31_FLAGS_Z |
                         FCR31_FLAGS_O | FCR31_FLAGS_U | FCR31_FLAGS_I);

    }

    CYG_REPORT_RETVAL( handled );
    return handled;
} // cyg_hal_mips_process_fpe()

#endif // ifdef CYGHWR_HAL_MIPS_FPU

// EOF mipsfp.c

⌨️ 快捷键说明

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