mipsfp.c

来自「eCos操作系统源码」· C语言 代码 · 共 836 行 · 第 1/2 页

C
836
字号
        {        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 + =
减小字号Ctrl + -
显示快捷键?