| 694 | */ |
| 695 | |
| 696 | void FPU::FPREM(bool truncate) { |
| 697 | // don't want to convert STV(1) to cache just for inspection |
| 698 | if (isRegCached[STV(1)]) { |
| 699 | double valtop = getF64(this->top); |
| 700 | double valdiv = getF64(STV(1)); |
| 701 | |
| 702 | if (isnan(valtop) || isnan(valdiv) || isinf(valtop)) { |
| 703 | regCache[top].l = DOUBLE_QUIET_NAN_BITS; |
| 704 | isRegCached[top] = true; |
| 705 | return; |
| 706 | } |
| 707 | if (isinf(valdiv)) { |
| 708 | return; |
| 709 | } |
| 710 | |
| 711 | S64 ressaved = (S64)((valtop / valdiv)); |
| 712 | // Some backups |
| 713 | // Real64 res=valtop - ressaved*valdiv; |
| 714 | // res= fmod(valtop,valdiv); |
| 715 | this->regCache[this->top].d = valtop - ressaved * valdiv; |
| 716 | FPU_SET_C0(this, (int)(ressaved & 4)); |
| 717 | FPU_SET_C3(this, (int)(ressaved & 2)); |
| 718 | FPU_SET_C1(this, (int)(ressaved & 1)); |
| 719 | FPU_SET_C2(this, 0); |
| 720 | return; |
| 721 | } |
| 722 | extFloat80_t& top = getReg(this->top); |
| 723 | extFloat80_t& bottom = getReg(STV(1)); |
| 724 | |
| 725 | // conditions based on spec and what hardware returned in unit tests |
| 726 | if (F80_isnan(bottom) || F80_isnan(top)) { |
| 727 | regs[this->top] = fx80_nan; |
| 728 | return; |
| 729 | } |
| 730 | if (F80_isinf(top)) { |
| 731 | regs[this->top] = fx80_nan; |
| 732 | return; |
| 733 | } |
| 734 | if (F80_isinf(bottom)) { |
| 735 | return; |
| 736 | } |
| 737 | // D := exponent(ST(0)) � exponent(ST(1)); |
| 738 | S32 d = (top.signExp & 0x7FFF) - (bottom.signExp & 0x7FFF); |
| 739 | if (d < 64) { |
| 740 | // Q := Integer(TruncateTowardZero(ST(0) / ST(1))); |
| 741 | extFloat80_t divResult = extF80_div(top, bottom); |
| 742 | S64 q = extF80_to_i64(divResult, truncate ? softfloat_round_minMag : softfloat_round_near_even, false); |
| 743 | // ST(0) := ST(0) � (ST(1) * Q); |
| 744 | regs[this->top] = extF80_sub(top, extF80_mul(bottom, i64_to_extF80(q))); |
| 745 | // C2 := 0; |
| 746 | FPU_SET_C2(this, 0); |
| 747 | // C0, C3, C1 : = LeastSignificantBits(Q); (*Q2, Q1, Q0*) |
| 748 | FPU_SET_C1(this, (q & 1) ? 1 : 0); |
| 749 | FPU_SET_C3(this, (q & 2) ? 1 : 0); |
| 750 | FPU_SET_C0(this, (q & 4) ? 1 : 0); |
| 751 | } else { |
| 752 | // C2 := 1; |
| 753 | FPU_SET_C2(this, 0); |
no test coverage detected