diff --git a/cpu/ppc/ppcexceptions.cpp b/cpu/ppc/ppcexceptions.cpp index 0639421..11a8587 100644 --- a/cpu/ppc/ppcexceptions.cpp +++ b/cpu/ppc/ppcexceptions.cpp @@ -43,7 +43,7 @@ void ppc_exception_handler(Except_Type exception_type, uint32_t srr1_bits) { break; case Except_Type::EXC_MACHINE_CHECK: - if (!(ppc_state.msr & 0x1000)) { + if (!(ppc_state.msr & MSR::ME)) { /* TODO: handle internal checkstop */ } ppc_state.spr[SPR::SRR0] = ppc_state.pc & 0xFFFFFFFC; @@ -117,7 +117,7 @@ void ppc_exception_handler(Except_Type exception_type, uint32_t srr1_bits) { /* copy MSR[ILE] to MSR[LE] */ ppc_state.msr = (ppc_state.msr & 0xFFFFFFFE) | ((ppc_state.msr >> 16) & 1); - if (ppc_state.msr & 0x40) { + if (ppc_state.msr & MSR::IP) { ppc_next_instruction_address |= 0xFFF00000; } diff --git a/cpu/ppc/ppcfpopcodes.cpp b/cpu/ppc/ppcfpopcodes.cpp index 4014759..bf6a82e 100644 --- a/cpu/ppc/ppcfpopcodes.cpp +++ b/cpu/ppc/ppcfpopcodes.cpp @@ -170,10 +170,9 @@ void update_fex() { } template -void ppc_confirm_inf_nan(int chosen_reg_1, int chosen_reg_2, int chosen_reg_3, bool rc_flag = false) { +void ppc_confirm_inf_nan(int chosen_reg_1, int chosen_reg_2, bool rc_flag = false) { T input_a = T(ppc_state.fpr[chosen_reg_1].dbl64_r); T input_b = T(ppc_state.fpr[chosen_reg_2].dbl64_r); - T input_c = T(ppc_state.fpr[chosen_reg_3].dbl64_r); ppc_state.fpscr &= 0x7fbfffff; @@ -208,29 +207,10 @@ void ppc_confirm_inf_nan(int chosen_reg_1, int chosen_reg_2, int chosen_reg_3, b update_fex(); break; case FPOP::MUL: - if (std::isnan(input_a) && std::isnan(input_c)) { + if (std::isnan(input_a) && std::isnan(input_b)) { ppc_state.fpscr |= (FPSCR::FX); } - update_fex(); - break; - case FPOP::FMSUB: - case FPOP::FNMSUB: - if (std::isnan(input_a) || std::isnan(input_b) || std::isnan(input_c)) { - ppc_state.fpscr |= (FPSCR::FX | FPSCR::VXSNAN); - if (((input_a == FP_ZERO) && (input_c == FP_INFINITE)) || - ((input_c == FP_ZERO) && (input_a == FP_INFINITE))) { - ppc_state.fpscr |= FPSCR::VXIMZ; - } - } - - update_fex(); - break; - case FPOP::FMADD: - case FPOP::FNMADD: - if (std::isnan(input_a) || std::isnan(input_b) || std::isnan(input_c)) { - ppc_state.fpscr |= (FPSCR::VXSNAN | FPSCR::FPCC_FUNAN); - } update_fex(); break; } @@ -240,7 +220,10 @@ static void fpresult_update(double set_result, bool confirm_arc) { if (ppc_state.fpscr & 0x3) ppc_state.cr |= 0x2; - if (set_result > 0.0) { + if (std::isnan(set_result)) { + ppc_state.fpscr |= FPCC_FUNAN; + } + else if (set_result > 0.0) { ppc_state.fpscr |= FPCC_POS; } else if (set_result < 0.0) { ppc_state.fpscr |= FPCC_NEG; @@ -280,12 +263,9 @@ void ppc_changecrf1(double set_result) { void dppc_interpreter::ppc_fadd() { ppc_grab_regsfpdab(); - if ((val_reg_a == DBL_MAX) || (val_reg_b == DBL_MAX)) { - ppc_state.fpscr |= FX | OX | XX; - } - else if(std::isnan(val_reg_a) || std::isnan(val_reg_b)) { + if (std::isnan(val_reg_a) || std::isnan(val_reg_b)) { ppc_state.fpscr |= FPCC_FUNAN; - ppc_confirm_inf_nan(reg_a, reg_b, 0, rc_flag); + ppc_confirm_inf_nan(reg_a, reg_b, rc_flag); } ppc_dblresult64_d = double(val_reg_a + val_reg_b); @@ -299,11 +279,9 @@ void dppc_interpreter::ppc_fadd() { void dppc_interpreter::ppc_fsub() { ppc_grab_regsfpdab(); - if ((val_reg_a == DBL_MAX) || (val_reg_b == DBL_MAX)) { - ppc_state.fpscr |= FX | OX | XX; - } else if (std::isnan(val_reg_a) || std::isnan(val_reg_b)) { + if (std::isnan(val_reg_a) || std::isnan(val_reg_b)) { ppc_state.fpscr |= FPCC_FUNAN; - ppc_confirm_inf_nan(reg_a, reg_b, 0, rc_flag); + ppc_confirm_inf_nan(reg_a, reg_b, rc_flag); } ppc_dblresult64_d = double(val_reg_a - val_reg_b); @@ -317,10 +295,8 @@ void dppc_interpreter::ppc_fsub() { void dppc_interpreter::ppc_fdiv() { ppc_grab_regsfpdab(); - if (val_reg_b == 0.0) { - ppc_state.fpscr |= FX | OX | XX; - } else if (std::isnan(val_reg_a) || std::isnan(val_reg_b)) { - ppc_confirm_inf_nan(reg_a, reg_b, 0, rc_flag); + if (std::isnan(val_reg_a) || std::isnan(val_reg_b)) { + ppc_confirm_inf_nan(reg_a, reg_b, rc_flag); } ppc_dblresult64_d = val_reg_a / val_reg_b; @@ -334,12 +310,8 @@ void dppc_interpreter::ppc_fdiv() { void dppc_interpreter::ppc_fmul() { ppc_grab_regsfpdac(); - if (((val_reg_a == FP_ZERO) && (val_reg_c == FP_INFINITE)) || - ((val_reg_c == FP_ZERO) && (val_reg_a == FP_INFINITE))) { - ppc_state.fpscr |= (FPSCR::FX | FPSCR::VXSNAN | FPSCR::VXIMZ); - } - else if (std::isnan(val_reg_a) || std::isnan(val_reg_c)) { - ppc_confirm_inf_nan(reg_a, reg_b, 0, rc_flag); + if (std::isnan(val_reg_a) || std::isnan(val_reg_c)) { + ppc_confirm_inf_nan(reg_a, reg_c, rc_flag); } ppc_dblresult64_d = val_reg_a * val_reg_c; @@ -353,8 +325,11 @@ void dppc_interpreter::ppc_fmul() { void dppc_interpreter::ppc_fmadd() { ppc_grab_regsfpdabc(); - if (std::isnan(val_reg_a) || std::isnan(val_reg_b) || std::isnan(val_reg_c)) { - ppc_confirm_inf_nan(reg_a, reg_b, reg_c); + if (std::isnan(val_reg_a) || std::isnan(val_reg_c)) { + ppc_confirm_inf_nan(reg_a, reg_c, rc_flag); + } + if (std::isnan(val_reg_b)) { + ppc_confirm_inf_nan(reg_a, reg_b, rc_flag); } ppc_dblresult64_d = std::fma(val_reg_a, val_reg_c, val_reg_b); @@ -368,9 +343,11 @@ void dppc_interpreter::ppc_fmadd() { void dppc_interpreter::ppc_fmsub() { ppc_grab_regsfpdabc(); - - if (std::isnan(val_reg_a) || std::isnan(val_reg_b) || std::isnan(val_reg_c)) { - ppc_confirm_inf_nan(reg_a, reg_b, reg_c); + if (std::isnan(val_reg_a) || std::isnan(val_reg_c)) { + ppc_confirm_inf_nan(reg_a, reg_c, rc_flag); + } + if (std::isnan(val_reg_b)) { + ppc_confirm_inf_nan(reg_a, reg_b, rc_flag); } ppc_dblresult64_d = (val_reg_a * val_reg_c); @@ -385,8 +362,11 @@ void dppc_interpreter::ppc_fmsub() { void dppc_interpreter::ppc_fnmadd() { ppc_grab_regsfpdabc(); - if (std::isnan(val_reg_a) || std::isnan(val_reg_b) || std::isnan(val_reg_c)) { - ppc_confirm_inf_nan(reg_a, reg_b, reg_c); + if (std::isnan(val_reg_a) || std::isnan(val_reg_c)) { + ppc_confirm_inf_nan(reg_a, reg_c, rc_flag); + } + if (std::isnan(val_reg_b)) { + ppc_confirm_inf_nan(reg_a, reg_b, rc_flag); } ppc_dblresult64_d = std::fma(val_reg_a, val_reg_c, val_reg_b); @@ -418,14 +398,14 @@ void dppc_interpreter::ppc_fnmsub() { void dppc_interpreter::ppc_fadds() { ppc_grab_regsfpdab(); + if (std::isnan(val_reg_a) || std::isnan(val_reg_b)) { + ppc_confirm_inf_nan(reg_a, reg_b, rc_flag); + } + float ppc_fltresult32_d = (float)(val_reg_a) + (float)val_reg_b; ppc_dblresult64_d = (double)ppc_fltresult32_d; ppc_store_sfpresult_flt(reg_d); - if (std::isnan(ppc_dblresult64_d)) { - ppc_confirm_inf_nan(reg_a, reg_b, 0, rc_flag); - } - fpresult_update(ppc_dblresult64_d, rc_flag); if (rc_flag) @@ -435,14 +415,13 @@ void dppc_interpreter::ppc_fadds() { void dppc_interpreter::ppc_fsubs() { ppc_grab_regsfpdab(); + if (std::isnan(val_reg_a) || std::isnan(val_reg_b)) { + ppc_confirm_inf_nan(reg_a, reg_b, rc_flag); + } + ppc_dblresult64_d = (float)(val_reg_a - val_reg_b); ppc_store_sfpresult_flt(reg_d); - - if (!std::isnan(ppc_dblresult64_d)) { - fpresult_update(ppc_dblresult64_d, rc_flag); - } else { - ppc_confirm_inf_nan(reg_a, reg_b, 0, rc_flag); - } + fpresult_update(ppc_dblresult64_d, rc_flag); if (rc_flag) ppc_changecrf1(ppc_dblresult64_d); @@ -451,15 +430,13 @@ void dppc_interpreter::ppc_fsubs() { void dppc_interpreter::ppc_fdivs() { ppc_grab_regsfpdab(); + if (std::isnan(val_reg_a) || std::isnan(val_reg_b)) { + ppc_confirm_inf_nan(reg_a, reg_b, rc_flag); + } + ppc_dblresult64_d = (float)(val_reg_a / val_reg_b); ppc_store_sfpresult_flt(reg_d); - - if (!std::isnan(ppc_dblresult64_d)) { - ppc_store_sfpresult_flt(reg_d); - fpresult_update(ppc_dblresult64_d, rc_flag); - } else { - ppc_confirm_inf_nan(reg_a, reg_b, 0, rc_flag); - } + fpresult_update(ppc_dblresult64_d, rc_flag); if (rc_flag) ppc_changecrf1(ppc_dblresult64_d); @@ -468,31 +445,32 @@ void dppc_interpreter::ppc_fdivs() { void dppc_interpreter::ppc_fmuls() { ppc_grab_regsfpdac(); - ppc_dblresult64_d = (float)(val_reg_a * val_reg_c); - - if (!std::isnan(ppc_dblresult64_d)) { - ppc_store_sfpresult_flt(reg_d); - fpresult_update(ppc_dblresult64_d, rc_flag); - } else { - ppc_confirm_inf_nan(reg_a, 0, reg_c, rc_flag); + if (std::isnan(val_reg_a) || std::isnan(val_reg_c)) { + ppc_confirm_inf_nan(reg_a, reg_c, rc_flag); } + ppc_dblresult64_d = (float)(val_reg_a * val_reg_c); + ppc_store_sfpresult_flt(reg_d); + fpresult_update(ppc_dblresult64_d, rc_flag); + if (rc_flag) ppc_changecrf1(ppc_dblresult64_d); } void dppc_interpreter::ppc_fmadds() { ppc_grab_regsfpdabc(); + + if (std::isnan(val_reg_a) || std::isnan(val_reg_c)) { + ppc_confirm_inf_nan(reg_a, reg_c, rc_flag); + } + if (std::isnan(val_reg_b)) { + ppc_confirm_inf_nan(reg_a, reg_b, rc_flag); + } ppc_dblresult64_d = static_cast( std::fma((float)val_reg_a, (float)val_reg_c, (float)val_reg_b)); - - if (!std::isnan(ppc_dblresult64_d)) { - ppc_store_sfpresult_flt(reg_d); - fpresult_update(ppc_dblresult64_d, rc_flag); - } else { - ppc_confirm_inf_nan(reg_a, reg_b, reg_c, rc_flag); - } + ppc_store_sfpresult_flt(reg_d); + fpresult_update(ppc_dblresult64_d, rc_flag); if (rc_flag) ppc_changecrf1(ppc_dblresult64_d); @@ -501,16 +479,18 @@ void dppc_interpreter::ppc_fmadds() { void dppc_interpreter::ppc_fmsubs() { ppc_grab_regsfpdabc(); + if (std::isnan(val_reg_a) || std::isnan(val_reg_c)) { + ppc_confirm_inf_nan(reg_a, reg_c, rc_flag); + } + if (std::isnan(val_reg_b)) { + ppc_confirm_inf_nan(reg_a, reg_b, rc_flag); + } + float intermediate = float(val_reg_a * val_reg_c); intermediate -= (float)val_reg_b; ppc_dblresult64_d = static_cast(intermediate); - - if (!std::isnan(ppc_dblresult64_d)) { - ppc_store_sfpresult_flt(reg_d); - fpresult_update(ppc_dblresult64_d, rc_flag); - } else { - ppc_confirm_inf_nan(reg_a, reg_b, reg_c, rc_flag); - } + ppc_store_sfpresult_flt(reg_d); + fpresult_update(ppc_dblresult64_d, rc_flag); if (rc_flag) ppc_changecrf1(ppc_dblresult64_d); @@ -519,17 +499,19 @@ void dppc_interpreter::ppc_fmsubs() { void dppc_interpreter::ppc_fnmadds() { ppc_grab_regsfpdabc(); + if (std::isnan(val_reg_a) || std::isnan(val_reg_c)) { + ppc_confirm_inf_nan(reg_a, reg_c, rc_flag); + } + if (std::isnan(val_reg_b)) { + ppc_confirm_inf_nan(reg_a, reg_b, rc_flag); + } + float intermediate = (float)val_reg_a * (float)val_reg_c; intermediate += (float)val_reg_b; intermediate = -intermediate; - ppc_dblresult64_d = static_cast(intermediate); - - if (!std::isnan(ppc_dblresult64_d)) { - ppc_store_sfpresult_flt(reg_d); - fpresult_update(ppc_dblresult64_d, rc_flag); - } else { - ppc_confirm_inf_nan(reg_a, reg_b, reg_c, rc_flag); - } + ppc_dblresult64_d = static_cast(intermediate); + ppc_store_sfpresult_flt(reg_d); + fpresult_update(ppc_dblresult64_d, rc_flag); if (rc_flag) ppc_changecrf1(ppc_dblresult64_d); @@ -538,18 +520,20 @@ void dppc_interpreter::ppc_fnmadds() { void dppc_interpreter::ppc_fnmsubs() { ppc_grab_regsfpdabc(); + + if (std::isnan(val_reg_a) || std::isnan(val_reg_c)) { + ppc_confirm_inf_nan(reg_a, reg_c, rc_flag); + } + if (std::isnan(val_reg_b)) { + ppc_confirm_inf_nan(reg_a, reg_b, rc_flag); + } + float intermediate = (float)val_reg_a * (float)val_reg_c; intermediate -= (float)val_reg_b; intermediate = -intermediate; ppc_dblresult64_d = static_cast(intermediate); - - - if (!std::isnan(ppc_dblresult64_d)) { - ppc_store_sfpresult_flt(reg_d); - fpresult_update(ppc_dblresult64_d, rc_flag); - } else { - ppc_confirm_inf_nan(reg_a, reg_b, reg_c, rc_flag); - } + ppc_store_sfpresult_flt(reg_d); + fpresult_update(ppc_dblresult64_d, rc_flag); if (rc_flag) ppc_changecrf1(ppc_dblresult64_d); @@ -601,10 +585,11 @@ void dppc_interpreter::ppc_fsel() { } void dppc_interpreter::ppc_fsqrt() { - ppc_grab_regsfpdb(); - ppc_dblresult64_d = std::sqrt(GET_FPR(reg_b)); + ppc_grab_regsfpdb(); + double testd2 = (double)(GET_FPR(reg_b)); + ppc_dblresult64_d = std::sqrt(testd2); ppc_store_dfpresult_flt(reg_d); - ppc_confirm_inf_nan(0, reg_b, 0, rc_flag); + ppc_confirm_inf_nan(0, reg_b, rc_flag); if (rc_flag) ppc_changecrf1(ppc_dblresult64_d); @@ -612,9 +597,10 @@ void dppc_interpreter::ppc_fsqrt() { void dppc_interpreter::ppc_fsqrts() { ppc_grab_regsfpdb(); - ppc_dblresult64_d = (float)std::sqrt(GET_FPR(reg_b)); + double testd2 = (double)(GET_FPR(reg_b)); + ppc_dblresult64_d = (float)std::sqrt(testd2); ppc_store_sfpresult_flt(reg_d); - ppc_confirm_inf_nan(0, reg_b, 0, rc_flag); + ppc_confirm_inf_nan(0, reg_b, rc_flag); if (rc_flag) ppc_changecrf1(ppc_dblresult64_d); @@ -624,6 +610,7 @@ void dppc_interpreter::ppc_frsqrte() { ppc_grab_regsfpdb(); double testd2 = (double)(GET_FPR(reg_b)); ppc_dblresult64_d = 1.0 / sqrt(testd2); + ppc_confirm_inf_nan(0, reg_b, rc_flag); ppc_store_dfpresult_flt(reg_d); @@ -655,8 +642,8 @@ void dppc_interpreter::ppc_fres() { ppc_state.fpscr |= FPSCR::VXSNAN; } else if (std::isinf(start_num)){ - ppc_state.fpscr |= FPSCR::VXSNAN; ppc_state.fpscr &= 0xFFF9FFFF; + ppc_state.fpscr |= FPSCR::VXSNAN; } if (rc_flag)