From a5a5410515dddb6ff3f43953f73f8bc34d78094e Mon Sep 17 00:00:00 2001 From: dingusdev <52434309+dingusdev@users.noreply.github.com> Date: Sun, 7 Apr 2024 08:58:38 -0700 Subject: [PATCH] Continued fixing floating-point ops --- cpu/ppc/ppcfpopcodes.cpp | 75 +++++++++++++++++++++++++++++++++++++--- 1 file changed, 71 insertions(+), 4 deletions(-) diff --git a/cpu/ppc/ppcfpopcodes.cpp b/cpu/ppc/ppcfpopcodes.cpp index 42e50b1..e8993e0 100644 --- a/cpu/ppc/ppcfpopcodes.cpp +++ b/cpu/ppc/ppcfpopcodes.cpp @@ -93,6 +93,16 @@ inline static bool check_snan(int check_reg) { ((check_int & (0x1ULL << 51)) == 0ULL)); } +inline static void snan_single_check(int reg_a) { + if (check_snan(reg_a)) + ppc_state.fpscr |= FX | VX | VXSNAN; +} + +inline static void snan_double_check(int reg_a, int reg_b) { + if (check_snan(reg_a) || check_snan(reg_b)) + ppc_state.fpscr |= FX | VX | VXSNAN; +} + inline static bool check_qnan(int check_reg) { uint64_t check_int = ppc_state.fpr[check_reg].int64_r; return (((check_int & (0x7FFULL << 52)) == (0x7FFULL << 52)) && @@ -122,6 +132,8 @@ template void dppc_interpreter::ppc_fadd() { ppc_grab_regsfpdab(ppc_cur_instruction); + snan_double_check(reg_a, reg_b); + double ppc_dblresult64_d = val_reg_a + val_reg_b; ppc_store_dfpresult_flt(reg_d, ppc_dblresult64_d); fpresult_update(ppc_dblresult64_d); @@ -137,6 +149,8 @@ template void dppc_interpreter::ppc_fsub() { ppc_grab_regsfpdab(ppc_cur_instruction); + snan_double_check(reg_a, reg_b); + double ppc_dblresult64_d = val_reg_a - val_reg_b; ppc_store_dfpresult_flt(reg_d, ppc_dblresult64_d); fpresult_update(ppc_dblresult64_d); @@ -152,6 +166,8 @@ template void dppc_interpreter::ppc_fdiv() { ppc_grab_regsfpdab(ppc_cur_instruction); + snan_double_check(reg_a, reg_b); + double ppc_dblresult64_d = val_reg_a / val_reg_b; ppc_store_dfpresult_flt(reg_d, ppc_dblresult64_d); fpresult_update(ppc_dblresult64_d); @@ -167,6 +183,8 @@ template void dppc_interpreter::ppc_fmul() { ppc_grab_regsfpdac(ppc_cur_instruction); + snan_double_check(reg_a, reg_c); + double ppc_dblresult64_d = val_reg_a * val_reg_c; ppc_store_dfpresult_flt(reg_d, ppc_dblresult64_d); fpresult_update(ppc_dblresult64_d); @@ -182,6 +200,9 @@ template void dppc_interpreter::ppc_fmadd() { ppc_grab_regsfpdabc(ppc_cur_instruction); + snan_double_check(reg_a, reg_c); + snan_single_check(reg_b); + double ppc_dblresult64_d = std::fma(val_reg_a, val_reg_c, val_reg_b); ppc_store_dfpresult_flt(reg_d, ppc_dblresult64_d); fpresult_update(ppc_dblresult64_d); @@ -197,6 +218,9 @@ template void dppc_interpreter::ppc_fmsub() { ppc_grab_regsfpdabc(ppc_cur_instruction); + snan_double_check(reg_a, reg_c); + snan_single_check(reg_b); + double ppc_dblresult64_d = std::fma(val_reg_a, val_reg_c, -val_reg_b); ppc_store_dfpresult_flt(reg_d, ppc_dblresult64_d); fpresult_update(ppc_dblresult64_d); @@ -212,6 +236,9 @@ template void dppc_interpreter::ppc_fnmadd() { ppc_grab_regsfpdabc(ppc_cur_instruction); + snan_double_check(reg_a, reg_c); + snan_single_check(reg_b); + double ppc_dblresult64_d = -std::fma(val_reg_a, val_reg_c, val_reg_b); ppc_store_dfpresult_flt(reg_d, ppc_dblresult64_d); fpresult_update(ppc_dblresult64_d); @@ -227,6 +254,9 @@ template void dppc_interpreter::ppc_fnmsub() { ppc_grab_regsfpdabc(ppc_cur_instruction); + snan_double_check(reg_a, reg_c); + snan_single_check(reg_b); + double ppc_dblresult64_d = -std::fma(val_reg_a, val_reg_c, -val_reg_b); ppc_store_dfpresult_flt(reg_d, ppc_dblresult64_d); fpresult_update(ppc_dblresult64_d); @@ -242,6 +272,8 @@ template void dppc_interpreter::ppc_fadds() { ppc_grab_regsfpdab(ppc_cur_instruction); + snan_double_check(reg_a, reg_b); + double ppc_dblresult64_d = (float)(val_reg_a + val_reg_b); ppc_store_sfpresult_flt(reg_d, ppc_dblresult64_d); @@ -258,6 +290,8 @@ template void dppc_interpreter::ppc_fsubs() { ppc_grab_regsfpdab(ppc_cur_instruction); + snan_double_check(reg_a, reg_b); + double ppc_dblresult64_d = (float)(val_reg_a - val_reg_b); ppc_store_sfpresult_flt(reg_d, ppc_dblresult64_d); fpresult_update(ppc_dblresult64_d); @@ -273,6 +307,8 @@ template void dppc_interpreter::ppc_fdivs() { ppc_grab_regsfpdab(ppc_cur_instruction); + snan_double_check(reg_a, reg_b); + double ppc_dblresult64_d = (float)(val_reg_a / val_reg_b); ppc_store_sfpresult_flt(reg_d, ppc_dblresult64_d); fpresult_update(ppc_dblresult64_d); @@ -288,6 +324,8 @@ template void dppc_interpreter::ppc_fmuls() { ppc_grab_regsfpdac(ppc_cur_instruction); + snan_double_check(reg_a, reg_c); + double ppc_dblresult64_d = (float)(val_reg_a * val_reg_c); ppc_store_sfpresult_flt(reg_d, ppc_dblresult64_d); fpresult_update(ppc_dblresult64_d); @@ -303,6 +341,9 @@ template void dppc_interpreter::ppc_fmadds() { ppc_grab_regsfpdabc(ppc_cur_instruction); + snan_double_check(reg_a, reg_c); + snan_single_check(reg_b); + double ppc_dblresult64_d = (float)std::fma(val_reg_a, val_reg_c, val_reg_b); ppc_store_sfpresult_flt(reg_d, ppc_dblresult64_d); fpresult_update(ppc_dblresult64_d); @@ -318,6 +359,9 @@ template void dppc_interpreter::ppc_fmsubs() { ppc_grab_regsfpdabc(ppc_cur_instruction); + snan_double_check(reg_a, reg_c); + snan_single_check(reg_b); + double ppc_dblresult64_d = (float)std::fma(val_reg_a, val_reg_c, -val_reg_b); ppc_store_sfpresult_flt(reg_d, ppc_dblresult64_d); fpresult_update(ppc_dblresult64_d); @@ -333,6 +377,9 @@ template void dppc_interpreter::ppc_fnmadds() { ppc_grab_regsfpdabc(ppc_cur_instruction); + snan_double_check(reg_a, reg_c); + snan_single_check(reg_b); + double ppc_dblresult64_d = -(float)std::fma(val_reg_a, val_reg_c, val_reg_b); ppc_store_sfpresult_flt(reg_d, ppc_dblresult64_d); fpresult_update(ppc_dblresult64_d); @@ -348,6 +395,9 @@ template void dppc_interpreter::ppc_fnmsubs() { ppc_grab_regsfpdabc(ppc_cur_instruction); + snan_double_check(reg_a, reg_c); + snan_single_check(reg_b); + double ppc_dblresult64_d = -(float)std::fma(val_reg_a, val_reg_c, -val_reg_b); ppc_store_sfpresult_flt(reg_d, ppc_dblresult64_d); fpresult_update(ppc_dblresult64_d); @@ -363,6 +413,8 @@ template void dppc_interpreter::ppc_fabs() { ppc_grab_regsfpdb(ppc_cur_instruction); + snan_single_check(reg_b); + double ppc_dblresult64_d = abs(GET_FPR(reg_b)); ppc_store_dfpresult_flt(reg_d, ppc_dblresult64_d); @@ -378,6 +430,8 @@ template void dppc_interpreter::ppc_fnabs() { ppc_grab_regsfpdb(ppc_cur_instruction); + snan_single_check(reg_b); + double ppc_dblresult64_d = abs(GET_FPR(reg_b)); ppc_dblresult64_d = -ppc_dblresult64_d; @@ -394,6 +448,8 @@ template void dppc_interpreter::ppc_fneg() { ppc_grab_regsfpdb(ppc_cur_instruction); + snan_single_check(reg_b); + double ppc_dblresult64_d = -(GET_FPR(reg_b)); ppc_store_dfpresult_flt(reg_d, ppc_dblresult64_d); @@ -423,6 +479,9 @@ template void dppc_interpreter::ppc_fsel(); template void dppc_interpreter::ppc_fsqrt() { ppc_grab_regsfpdb(ppc_cur_instruction); + + snan_single_check(reg_b); + double testd2 = (double)(GET_FPR(reg_b)); double ppc_dblresult64_d = std::sqrt(testd2); ppc_store_dfpresult_flt(reg_d, ppc_dblresult64_d); @@ -437,7 +496,10 @@ template void dppc_interpreter::ppc_fsqrt(); template void dppc_interpreter::ppc_fsqrts() { ppc_grab_regsfpdb(ppc_cur_instruction); - double testd2 = (double)(GET_FPR(reg_b)); + + snan_single_check(reg_b); + + double testd2 = (double)(GET_FPR(reg_b)); double ppc_dblresult64_d = (float)std::sqrt(testd2); ppc_store_sfpresult_flt(reg_d, ppc_dblresult64_d); @@ -451,10 +513,10 @@ template void dppc_interpreter::ppc_fsqrts(); template void dppc_interpreter::ppc_frsqrte() { ppc_grab_regsfpdb(ppc_cur_instruction); - double testd2 = (double)(GET_FPR(reg_b)); + snan_single_check(reg_b); + double testd2 = (double)(GET_FPR(reg_b)); double ppc_dblresult64_d = 1.0 / sqrt(testd2); - ppc_store_dfpresult_flt(reg_d, ppc_dblresult64_d); if (rec) @@ -467,6 +529,8 @@ template void dppc_interpreter::ppc_frsqrte(); template void dppc_interpreter::ppc_frsp() { ppc_grab_regsfpdb(ppc_cur_instruction); + snan_single_check(reg_b); + double ppc_dblresult64_d = (float)(GET_FPR(reg_b)); ppc_store_dfpresult_flt(reg_d, ppc_dblresult64_d); @@ -480,6 +544,9 @@ template void dppc_interpreter::ppc_frsp(); template void dppc_interpreter::ppc_fres() { ppc_grab_regsfpdb(ppc_cur_instruction); + + snan_single_check(reg_b); + double start_num = GET_FPR(reg_b); double ppc_dblresult64_d = (float)(1.0 / start_num); ppc_store_dfpresult_flt(reg_d, ppc_dblresult64_d); @@ -510,7 +577,7 @@ static void round_to_int(const uint8_t mode, field_rc rec) { ppc_state.fpscr &= ~(FPSCR::FR | FPSCR::FI); ppc_state.fpscr |= (FPSCR::VXCVI | FPSCR::VX); - if (!(ppc_state.fpr[reg_b].int64_r & 0x0008000000000000)) // issnan + if (check_snan(reg_b)) // issnan ppc_state.fpscr |= FPSCR::VXSNAN; if (ppc_state.fpscr & FPSCR::VE) {