Skip to content

Commit

Permalink
Floating-point fix-ups
Browse files Browse the repository at this point in the history
Largely to fix setting flags, but partially to fix the incorrect nan emulation
  • Loading branch information
dingusdev committed Oct 17, 2024
1 parent b3eb1f6 commit 329bcc6
Show file tree
Hide file tree
Showing 4 changed files with 122 additions and 3 deletions.
1 change: 1 addition & 0 deletions CREDITS.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
- maximumspatium
- joevt
- mihaip
- kkaisershot

## NT4/PPC fork

Expand Down
118 changes: 118 additions & 0 deletions cpu/ppc/ppcfpopcodes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,18 @@ static void fpresult_update(double set_result) {
} else {
ppc_state.fpscr |= FPCC_ZERO;
}

if (std::fetestexcept(FE_OVERFLOW)) {
ppc_state.fpscr |= (OX + FX);
}
if (std::fetestexcept(FE_UNDERFLOW)) {
ppc_state.fpscr |= (UX + FX);
}
if (std::fetestexcept(FE_DIVBYZERO)) {
ppc_state.fpscr |= (ZX + FX);
}

std::feclearexcept(FE_ALL_EXCEPT);

if (std::isinf(set_result))
ppc_state.fpscr |= FPCC_FUNAN;
Expand Down Expand Up @@ -160,6 +172,12 @@ void dppc_interpreter::ppc_fadd() {
max_double_check(val_reg_a, val_reg_b);

double ppc_dblresult64_d = val_reg_a + val_reg_b;

double inf = std::numeric_limits<double>::infinity();
if (((val_reg_a == inf) && (val_reg_b == -inf)) ||
((val_reg_a == -inf) && (val_reg_b == inf)))
ppc_state.fpscr |= VXISI;

ppc_store_dfpresult_flt(reg_d, ppc_dblresult64_d);
fpresult_update(ppc_dblresult64_d);
ppc_update_fex();
Expand All @@ -179,8 +197,13 @@ void dppc_interpreter::ppc_fsub() {

double ppc_dblresult64_d = val_reg_a - val_reg_b;

double inf = std::numeric_limits<double>::infinity();
if ((val_reg_a == inf) && (val_reg_b == inf))
ppc_state.fpscr |= VXISI;

ppc_store_dfpresult_flt(reg_d, ppc_dblresult64_d);
fpresult_update(ppc_dblresult64_d);
ppc_update_fex();

if (rec)
ppc_update_cr1();
Expand All @@ -199,6 +222,12 @@ void dppc_interpreter::ppc_fdiv() {
ppc_store_dfpresult_flt(reg_d, ppc_dblresult64_d);
fpresult_update(ppc_dblresult64_d);

if (isinf(val_reg_a) && isinf(val_reg_b))
ppc_state.fpscr |= VXIDI;

if ((val_reg_a == 0.0) && (val_reg_b == 0.0))
ppc_state.fpscr |= VXZDZ;

if (rec)
ppc_update_cr1();
}
Expand All @@ -216,6 +245,9 @@ void dppc_interpreter::ppc_fmul() {
ppc_store_dfpresult_flt(reg_d, ppc_dblresult64_d);
fpresult_update(ppc_dblresult64_d);

if ((isinf(val_reg_a) && (val_reg_c == 0.0)) || (isinf(val_reg_c) && (val_reg_a == 0.0)))
ppc_state.fpscr |= VXIMZ;

if (rec)
ppc_update_cr1();
}
Expand All @@ -234,6 +266,13 @@ void dppc_interpreter::ppc_fmadd() {
ppc_store_dfpresult_flt(reg_d, ppc_dblresult64_d);
fpresult_update(ppc_dblresult64_d);

double inf = std::numeric_limits<double>::infinity();
if (((val_reg_a == inf) && (val_reg_b == -inf)) || ((val_reg_a == -inf) && (val_reg_b == inf)))
ppc_state.fpscr |= VXISI;

if ((isinf(val_reg_a) && (val_reg_c == 0.0)) || (isinf(val_reg_c) && (val_reg_a == 0.0)))
ppc_state.fpscr |= VXIMZ;

if (rec)
ppc_update_cr1();
}
Expand All @@ -252,6 +291,13 @@ void dppc_interpreter::ppc_fmsub() {
ppc_store_dfpresult_flt(reg_d, ppc_dblresult64_d);
fpresult_update(ppc_dblresult64_d);

if ((isinf(val_reg_a) && (val_reg_c == 0.0)) || (isinf(val_reg_c) && (val_reg_a == 0.0)))
ppc_state.fpscr |= VXIMZ;

double inf = std::numeric_limits<double>::infinity();
if ((val_reg_a == inf) && (val_reg_b == inf))
ppc_state.fpscr |= VXISI;

if (rec)
ppc_update_cr1();
}
Expand All @@ -267,9 +313,19 @@ void dppc_interpreter::ppc_fnmadd() {
snan_single_check(reg_b);

double ppc_dblresult64_d = -std::fma(val_reg_a, val_reg_c, val_reg_b);
if (isnan(ppc_dblresult64_d)) {
ppc_dblresult64_d = -ppc_dblresult64_d;
}
ppc_store_dfpresult_flt(reg_d, ppc_dblresult64_d);
fpresult_update(ppc_dblresult64_d);

double inf = std::numeric_limits<double>::infinity();
if (((val_reg_a == inf) && (val_reg_b == -inf)) || ((val_reg_a == -inf) && (val_reg_b == inf)))
ppc_state.fpscr |= VXISI;

if ((isinf(val_reg_a) && (val_reg_c == 0.0)) || (isinf(val_reg_c) && (val_reg_a == 0.0)))
ppc_state.fpscr |= VXIMZ;

if (rec)
ppc_update_cr1();
}
Expand All @@ -288,6 +344,13 @@ void dppc_interpreter::ppc_fnmsub() {
ppc_store_dfpresult_flt(reg_d, ppc_dblresult64_d);
fpresult_update(ppc_dblresult64_d);

if ((isinf(val_reg_a) && (val_reg_c == 0.0)) || (isinf(val_reg_c) && (val_reg_a == 0.0)))
ppc_state.fpscr |= VXIMZ;

double inf = std::numeric_limits<double>::infinity();
if ((val_reg_a == inf) && (val_reg_b == inf))
ppc_state.fpscr |= VXISI;

if (rec)
ppc_update_cr1();
}
Expand All @@ -304,6 +367,10 @@ void dppc_interpreter::ppc_fadds() {
double ppc_dblresult64_d = (float)(val_reg_a + val_reg_b);
ppc_store_sfpresult_flt(reg_d, ppc_dblresult64_d);

double inf = std::numeric_limits<double>::infinity();
if (((val_reg_a == inf) && (val_reg_b == -inf)) || ((val_reg_a == -inf) && (val_reg_b == inf)))
ppc_state.fpscr |= VXISI;

fpresult_update(ppc_dblresult64_d);

if (rec)
Expand All @@ -321,6 +388,10 @@ void dppc_interpreter::ppc_fsubs() {

double ppc_dblresult64_d = (float)(val_reg_a - val_reg_b);

double inf = std::numeric_limits<double>::infinity();
if ((val_reg_a == inf) && (val_reg_b == inf))
ppc_state.fpscr |= VXISI;

ppc_store_sfpresult_flt(reg_d, ppc_dblresult64_d);
fpresult_update(ppc_dblresult64_d);

Expand All @@ -338,6 +409,13 @@ void dppc_interpreter::ppc_fdivs() {
snan_double_check(reg_a, reg_b);

double ppc_dblresult64_d = (float)(val_reg_a / val_reg_b);

if (isinf(val_reg_a) && isinf(val_reg_b))
ppc_state.fpscr |= VXIDI;

if ((val_reg_a == 0.0) && (val_reg_b == 0.0))
ppc_state.fpscr |= VXZDZ;

ppc_store_sfpresult_flt(reg_d, ppc_dblresult64_d);
fpresult_update(ppc_dblresult64_d);

Expand All @@ -355,9 +433,14 @@ void dppc_interpreter::ppc_fmuls() {
snan_double_check(reg_a, reg_c);

double ppc_dblresult64_d = (float)(val_reg_a * val_reg_c);

if ((isinf(val_reg_a) && (val_reg_c == 0.0)) || (isinf(val_reg_c) && (val_reg_a == 0.0)))
ppc_state.fpscr |= VXIMZ;

ppc_store_sfpresult_flt(reg_d, ppc_dblresult64_d);
fpresult_update(ppc_dblresult64_d);


if (rec)
ppc_update_cr1();
}
Expand All @@ -376,6 +459,13 @@ void dppc_interpreter::ppc_fmadds() {
ppc_store_sfpresult_flt(reg_d, ppc_dblresult64_d);
fpresult_update(ppc_dblresult64_d);

double inf = std::numeric_limits<double>::infinity();
if (((val_reg_a == inf) && (val_reg_b == -inf)) || ((val_reg_a == -inf) && (val_reg_b == inf)))
ppc_state.fpscr |= VXISI;

if ((isinf(val_reg_a) && (val_reg_c == 0.0)) || (isinf(val_reg_c) && (val_reg_a == 0.0)))
ppc_state.fpscr |= VXIMZ;

if (rec)
ppc_update_cr1();
}
Expand All @@ -390,9 +480,20 @@ void dppc_interpreter::ppc_fmsubs() {
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);
if (isnan(ppc_dblresult64_d)) {
ppc_dblresult64_d = -ppc_dblresult64_d;
}
ppc_store_sfpresult_flt(reg_d, ppc_dblresult64_d);
fpresult_update(ppc_dblresult64_d);

if ((isinf(val_reg_a) && (val_reg_c == 0.0)) || (isinf(val_reg_c) && (val_reg_a == 0.0)))
ppc_state.fpscr |= VXIMZ;

double inf = std::numeric_limits<double>::infinity();
if ((val_reg_a == inf) && (val_reg_b == inf))
ppc_state.fpscr |= VXISI;

if (rec)
ppc_update_cr1();
Expand All @@ -409,9 +510,19 @@ void dppc_interpreter::ppc_fnmadds() {
snan_single_check(reg_b);

double ppc_dblresult64_d = -(float)std::fma(val_reg_a, val_reg_c, val_reg_b);
if (isnan(ppc_dblresult64_d)) {
ppc_dblresult64_d = -ppc_dblresult64_d;
}
ppc_store_sfpresult_flt(reg_d, ppc_dblresult64_d);
fpresult_update(ppc_dblresult64_d);

double inf = std::numeric_limits<double>::infinity();
if (((val_reg_a == inf) && (val_reg_b == -inf)) || ((val_reg_a == -inf) && (val_reg_b == inf)))
ppc_state.fpscr |= VXISI;

if ((isinf(val_reg_a) && (val_reg_c == 0.0)) || (isinf(val_reg_c) && (val_reg_a == 0.0)))
ppc_state.fpscr |= VXIMZ;

if (rec)
ppc_update_cr1();
}
Expand All @@ -430,6 +541,13 @@ void dppc_interpreter::ppc_fnmsubs() {
ppc_store_sfpresult_flt(reg_d, ppc_dblresult64_d);
fpresult_update(ppc_dblresult64_d);

if ((isinf(val_reg_a) && (val_reg_c == 0.0)) || (isinf(val_reg_c) && (val_reg_a == 0.0)))
ppc_state.fpscr |= VXIMZ;

double inf = std::numeric_limits<double>::infinity();
if ((val_reg_a == inf) && (val_reg_b == inf))
ppc_state.fpscr |= VXISI;

if (rec)
ppc_update_cr1();
}
Expand Down
2 changes: 1 addition & 1 deletion cpu/ppc/ppcopcodes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ void do_ctx_sync() {
}
}

void add_ctx_sync_action(const CtxSyncCallback& cb) {
static void add_ctx_sync_action(const CtxSyncCallback& cb) {
gCtxSyncCallbacks.push_back(cb);
}

Expand Down
4 changes: 2 additions & 2 deletions main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,9 +53,9 @@ static void sigabrt_handler(int signum) {
}

static string appDescription = string(
"\nDingusPPC - Alpha 1 (5/10/2024) "
"\nDingusPPC - Alpha 1.01 (10/31/2024) "
"\nWritten by divingkatae, maximumspatium, "
"\njoevt, mihaip, et. al. "
"\njoevt, mihaip, kkaisershot, et. al. "
"\n(c) 2018-2024 The DingusPPC Dev Team. "
"\nThis is a build intended for testing. "
"\nUse at your own discretion. "
Expand Down

0 comments on commit 329bcc6

Please sign in to comment.