📄 mipsfp.c
字号:
// 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; *srcreg2 = s2.asi64; 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; d.asi64 = *dstreg; s.asi64 = *srcreg1; 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; *srcreg1 = s.asi64; } else { // but preserve sign if (s.number.sign) d.value = -0.0; else d.value = 0.0; *dstreg = d.asi64; 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; d.asi64 = *dstreg; s.asi64 = *srcreg1; // 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; *srcreg1 = s.asi64; handled++; } } else { d.asi64 = s.asi64; d.number.sign = 0; *dstreg = d.asi64; 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; d.asi64 = *dstreg; s.asi64 = *srcreg1; // 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; *srcreg1 = s.asi64; handled++; } } else { d.asi64 = s.asi64; *dstreg = d.asi64; 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; d.asi64 = *dstreg; s.asi64 = *srcreg1; // 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; *srcreg1 = s.asi64; handled++; } } else { d.asi64 = s.asi64; d.number.sign = s.number.sign ? 0 : 1; *dstreg = d.asi64; 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; s.asi64 = *srcreg1; // 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; *srcreg1 = s.asi64; 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; s1.asi64 = *srcreg1; s2.asi64 = *srcreg2; if ( issubnormal( s1 ) ) { // flush to 0 and restart // but preserve sign if (s1.number.sign) s1.value = -0.0; else s1.value = 0.0; *srcreg1 = s1.asi64; 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; *srcreg2 = s2.asi64; 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 + -