Floating point overhaul, part 2

Further formatting fixes. Removed obsoleted separation definitions. Fixed rounding to nearest.
This commit is contained in:
dingusdev 2021-10-09 19:42:25 -07:00
parent e344b089b3
commit 2d65ed47fc
2 changed files with 45 additions and 65 deletions

View File

@ -202,6 +202,7 @@ enum class BB_end_kind {
enum class CR_select { enum class CR_select {
CR0_field = (0xF << 28), CR0_field = (0xF << 28),
CR1_field = (0xF << 24),
}; };
enum class CRx_bit { enum class CRx_bit {
@ -479,15 +480,10 @@ extern void ppc_mtspr();
extern void ppc_mtfsb0(); extern void ppc_mtfsb0();
extern void ppc_mtfsb1(); extern void ppc_mtfsb1();
extern void ppc_mcrfs(); extern void ppc_mcrfs();
extern void ppc_mtfsb0dot();
extern void ppc_mtfsb1dot();
extern void ppc_fmr(); extern void ppc_fmr();
extern void ppc_mffs(); extern void ppc_mffs();
extern void ppc_mffsdot();
extern void ppc_mtfsf(); extern void ppc_mtfsf();
extern void ppc_mtfsfdot();
extern void ppc_mtfsfi(); extern void ppc_mtfsfi();
extern void ppc_mtfsfidot();
extern void ppc_addi(); extern void ppc_addi();
extern void ppc_addic(); extern void ppc_addic();

View File

@ -162,9 +162,9 @@ void ppc_divbyzero(uint64_t input_a, uint64_t input_b, bool is_single) {
int64_t round_to_nearest(double f) { int64_t round_to_nearest(double f) {
if (f >= 0.0) { if (f >= 0.0) {
return static_cast<int32_t>(static_cast<int64_t> (f + 0.5)); return static_cast<int32_t>(static_cast<int64_t> (ceil(f)));
} else { } else {
return static_cast<int32_t>(static_cast<int64_t> (-f + 0.5)); return static_cast<int32_t>(static_cast<int64_t> (floor(f)));
} }
} }
@ -290,8 +290,8 @@ void fpresult_update(double set_result, bool confirm_arc) {
} }
void ppc_changecrf1() { void ppc_changecrf1() {
ppc_state.cr &= 0xF0FFFFFF; ppc_state.cr &= ~((uint32_t)CR_select::CR1_field);
ppc_state.cr |= (ppc_state.fpscr & 0xF0000000) >> 4; ppc_state.cr |= (ppc_state.fpscr & (uint32_t)CR_select::CR0_field) >> 4;
} }
// Floating Point Arithmetic // Floating Point Arithmetic
@ -558,7 +558,7 @@ void dppc_interpreter::ppc_fneg() {
void dppc_interpreter::ppc_fsel() { void dppc_interpreter::ppc_fsel() {
ppc_grab_regsfpdabc(); ppc_grab_regsfpdabc();
ppc_dblresult64_d = (val_reg_a >= 0.0) ? val_reg_c : val_reg_b; ppc_dblresult64_d = (val_reg_a >= -0.0) ? val_reg_c : val_reg_b;
ppc_store_dfpresult_flt(reg_d); ppc_store_dfpresult_flt(reg_d);
@ -613,11 +613,23 @@ void dppc_interpreter::ppc_frsp() {
void dppc_interpreter::ppc_fres() { void dppc_interpreter::ppc_fres() {
ppc_grab_regsfpdb(); ppc_grab_regsfpdb();
float testf2 = (float)GET_FPR(reg_b); double start_num = GET_FPR(reg_b);
float testf2 = (float)start_num;
testf2 = 1 / testf2; testf2 = 1 / testf2;
ppc_dblresult64_d = (double)testf2; ppc_dblresult64_d = (double)testf2;
ppc_store_dfpresult_flt(reg_d); ppc_store_dfpresult_flt(reg_d);
if (start_num == 0.0) {
ppc_state.fpscr |= (uint32_t)FPSCR_bit::FPSCR_ZX;
}
else if (std::isnan(start_num)) {
ppc_state.fpscr |= (uint32_t)FPSCR_bit::FPSCR_VXSNAN;
}
else if (std::isinf(start_num)){
ppc_state.fpscr |= (uint32_t)FPSCR_bit::FPSCR_VXSNAN;
ppc_state.fpscr &= 0xFFF9FFFF;
}
if (rc_flag) if (rc_flag)
ppc_changecrf1(); ppc_changecrf1();
} }
@ -628,15 +640,15 @@ void dppc_interpreter::ppc_fctiw() {
if (std::isnan(val_reg_b)) { if (std::isnan(val_reg_b)) {
ppc_state.fpr[reg_d].int64_r = 0x80000000; ppc_state.fpr[reg_d].int64_r = 0x80000000;
ppc_state.fpscr |= 0x1000100; ppc_state.fpscr |= (uint32_t)FPSCR_bit::FPSCR_VXSNAN | (uint32_t)FPSCR_bit::FPSCR_VXCVI;
} }
else if (val_reg_b > static_cast<double>(0x7fffffff)) { else if (val_reg_b > static_cast<double>(0x7fffffff)) {
ppc_state.fpr[reg_d].int64_r = 0x7fffffff; ppc_state.fpr[reg_d].int64_r = 0x7fffffff;
ppc_state.fpscr |= 0x100; ppc_state.fpscr |= (uint32_t)FPSCR_bit::FPSCR_VXCVI;
} }
else if (val_reg_b < -static_cast<double>(0x80000000)) { else if (val_reg_b < -static_cast<double>(0x80000000)) {
ppc_state.fpr[reg_d].int64_r = 0x80000000; ppc_state.fpr[reg_d].int64_r = 0x80000000;
ppc_state.fpscr |= 0x100; ppc_state.fpscr |= (uint32_t)FPSCR_bit::FPSCR_VXCVI;
} }
else { else {
switch (ppc_state.fpscr & 0x3) { switch (ppc_state.fpscr & 0x3) {
@ -668,15 +680,15 @@ void dppc_interpreter::ppc_fctiwz() {
if (std::isnan(val_reg_b)) { if (std::isnan(val_reg_b)) {
ppc_state.fpr[reg_d].int64_r = 0x80000000; ppc_state.fpr[reg_d].int64_r = 0x80000000;
ppc_state.fpscr |= 0x1000100; ppc_state.fpscr |= (uint32_t)FPSCR_bit::FPSCR_VXSNAN | (uint32_t)FPSCR_bit::FPSCR_VXCVI;
} }
else if (val_reg_b > static_cast<double>(0x7fffffff)) { else if (val_reg_b > static_cast<double>(0x7fffffff)) {
ppc_state.fpr[reg_d].int64_r = 0x7fffffff; ppc_state.fpr[reg_d].int64_r = 0x7fffffff;
ppc_state.fpscr |= 0x100; ppc_state.fpscr |= (uint32_t)FPSCR_bit::FPSCR_VXCVI;
} }
else if (val_reg_b < -static_cast<double>(0x80000000)) { else if (val_reg_b < -static_cast<double>(0x80000000)) {
ppc_state.fpr[reg_d].int64_r = 0x80000000; ppc_state.fpr[reg_d].int64_r = 0x80000000;
ppc_state.fpscr |= 0x100; ppc_state.fpscr |= (uint32_t)FPSCR_bit::FPSCR_VXCVI;
} }
else { else {
ppc_result64_d = round_to_zero(val_reg_b); ppc_result64_d = round_to_zero(val_reg_b);
@ -873,22 +885,23 @@ void dppc_interpreter::ppc_fmr() {
ppc_state.fpr[reg_d].dbl64_r = ppc_state.fpr[reg_b].dbl64_r; ppc_state.fpr[reg_d].dbl64_r = ppc_state.fpr[reg_b].dbl64_r;
} }
void dppc_interpreter::ppc_mffs() { void dppc_interpreter::ppc_mffs() {
ppc_grab_regsda(); ppc_grab_regsda();
uint64_t fpstore1 = ppc_state.fpr[reg_d].int64_r & 0xFFFFFFFF00000000; uint64_t fpstore1 = 0;
uint64_t fpstore2 = ppc_state.fpscr & 0x00000000FFFFFFFF;
fpstore1 |= fpstore2;
fp_save_uint64(fpstore1);
}
void dppc_interpreter::ppc_mffsdot() { if (ppc_state.spr[SPR::PVR] == PPC_VER::MPC601) {
ppc_grab_regsda(); fpstore1 = ppc_state.fpr[reg_d].int64_r & ((uint64_t)0xFFF80000 << 32);
uint64_t fpstore1 = ppc_state.fpr[reg_d].int64_r & 0xFFFFFFFF00000000; }
uint64_t fpstore2 = ppc_state.fpscr & 0x00000000FFFFFFFF; else {
fpstore1 = ppc_state.fpr[reg_d].int64_r & ((uint64_t)0xFFFFFFFF << 32);
}
uint64_t fpstore2 = ppc_state.fpscr & (uint64_t)0xFFFFFFFF;
fpstore1 |= fpstore2; fpstore1 |= fpstore2;
fp_save_uint64(fpstore1); fp_save_uint64(fpstore1);
ppc_fp_changecrf1();
if (rc_flag)
ppc_fp_changecrf1();
} }
void dppc_interpreter::ppc_mtfsf() { void dppc_interpreter::ppc_mtfsf() {
@ -904,22 +917,9 @@ void dppc_interpreter::ppc_mtfsf() {
crm += (((fm_mask >> 7) & 1) == 1) ? 0x0000000F : 0x00000000; crm += (((fm_mask >> 7) & 1) == 1) ? 0x0000000F : 0x00000000;
uint32_t quickfprval = (uint32_t)ppc_state.fpr[reg_b].int64_r; uint32_t quickfprval = (uint32_t)ppc_state.fpr[reg_b].int64_r;
ppc_state.fpscr = (quickfprval & crm) | (quickfprval & ~(crm)); ppc_state.fpscr = (quickfprval & crm) | (quickfprval & ~(crm));
}
void dppc_interpreter::ppc_mtfsfdot() { if (rc_flag)
reg_b = (ppc_cur_instruction >> 11) & 31; ppc_fp_changecrf1();
uint32_t fm_mask = (ppc_cur_instruction >> 17) & 255;
crm += ((fm_mask & 1) == 1) ? 0xF0000000 : 0x00000000;
crm += (((fm_mask >> 1) & 1) == 1) ? 0x0F000000 : 0x00000000;
crm += (((fm_mask >> 2) & 1) == 1) ? 0x00F00000 : 0x00000000;
crm += (((fm_mask >> 3) & 1) == 1) ? 0x000F0000 : 0x00000000;
crm += (((fm_mask >> 4) & 1) == 1) ? 0x0000F000 : 0x00000000;
crm += (((fm_mask >> 5) & 1) == 1) ? 0x00000F00 : 0x00000000;
crm += (((fm_mask >> 6) & 1) == 1) ? 0x000000F0 : 0x00000000;
crm += (((fm_mask >> 7) & 1) == 1) ? 0x0000000F : 0x00000000;
uint32_t quickfprval = (uint32_t)ppc_state.fpr[reg_b].int64_r;
ppc_state.fpscr = (quickfprval & crm) | (quickfprval & ~(crm));
ppc_fp_changecrf1();
} }
void dppc_interpreter::ppc_mtfsfi() { void dppc_interpreter::ppc_mtfsfi() {
@ -928,15 +928,9 @@ void dppc_interpreter::ppc_mtfsfi() {
crf_d = crf_d << 2; crf_d = crf_d << 2;
ppc_state.fpscr = (ppc_state.cr & ~(0xF0000000UL >> crf_d)) | ppc_state.fpscr = (ppc_state.cr & ~(0xF0000000UL >> crf_d)) |
((ppc_state.spr[SPR::XER] & 0xF0000000UL) >> crf_d); ((ppc_state.spr[SPR::XER] & 0xF0000000UL) >> crf_d);
}
void dppc_interpreter::ppc_mtfsfidot() { if (rc_flag)
ppc_result_b = (ppc_cur_instruction >> 11) & 15; ppc_fp_changecrf1();
crf_d = (ppc_cur_instruction >> 23) & 7;
crf_d = crf_d << 2;
ppc_state.fpscr = (ppc_state.cr & ~(0xF0000000UL >> crf_d)) |
((ppc_state.spr[SPR::XER] & 0xF0000000UL) >> crf_d);
ppc_fp_changecrf1();
} }
void dppc_interpreter::ppc_mtfsb0() { void dppc_interpreter::ppc_mtfsb0() {
@ -944,14 +938,9 @@ void dppc_interpreter::ppc_mtfsb0() {
if ((crf_d == 0) || (crf_d > 2)) { if ((crf_d == 0) || (crf_d > 2)) {
ppc_state.fpscr &= ~(0x80000000UL >> crf_d); ppc_state.fpscr &= ~(0x80000000UL >> crf_d);
} }
}
void dppc_interpreter::ppc_mtfsb0dot() { if (rc_flag)
crf_d = (ppc_cur_instruction >> 21) & 0x1F; ppc_fp_changecrf1();
if ((crf_d == 0) || (crf_d > 2)) {
ppc_state.fpscr &= ~(0x80000000UL >> crf_d);
}
ppc_fp_changecrf1();
} }
void dppc_interpreter::ppc_mtfsb1() { void dppc_interpreter::ppc_mtfsb1() {
@ -959,14 +948,9 @@ void dppc_interpreter::ppc_mtfsb1() {
if ((crf_d == 0) || (crf_d > 2)) { if ((crf_d == 0) || (crf_d > 2)) {
ppc_state.fpscr |= (0x80000000UL >> crf_d); ppc_state.fpscr |= (0x80000000UL >> crf_d);
} }
}
void dppc_interpreter::ppc_mtfsb1dot() { if (rc_flag)
crf_d = (ppc_cur_instruction >> 21) & 0x1F; ppc_fp_changecrf1();
if ((crf_d == 0) || (crf_d > 2)) {
ppc_state.fpscr |= (0x80000000UL >> crf_d);
}
ppc_fp_changecrf1();
} }
void dppc_interpreter::ppc_mcrfs() { void dppc_interpreter::ppc_mcrfs() {