📄 mipsfp.c
字号:
{
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 + -