ppcfpopcodes: Fix fctiw/fctiwz.

This commit is contained in:
joevt 2023-12-17 05:06:38 -08:00 committed by Maxim Poliakovski
parent bd419912b5
commit 0100e67ebf
3 changed files with 64 additions and 15 deletions

View File

@ -420,6 +420,7 @@ void update_fpscr(uint32_t new_fpscr);
/* Exception handlers. */
void ppc_exception_handler(Except_Type exception_type, uint32_t srr1_bits);
[[noreturn]] void dbg_exception_handler(Except_Type exception_type, uint32_t srr1_bits);
void ppc_floating_point_exception();
// MEMORY DECLARATIONS
extern MemCtrlBase* mem_ctrl_instance;

View File

@ -194,3 +194,9 @@ void ppc_exception_handler(Except_Type exception_type, uint32_t srr1_bits) {
throw std::invalid_argument(exc_descriptor);
}
void ppc_floating_point_exception() {
LOG_F(ERROR, "Floating point exception at 0x%08x for instruction 0x%08x",
ppc_state.pc, ppc_cur_instruction);
// mmu_exception_handler(Except_Type::EXC_PROGRAM, Exc_Cause::FPU_EXCEPTION);
}

View File

@ -631,16 +631,38 @@ void dppc_interpreter::ppc_fctiw() {
double val_reg_b = GET_FPR(reg_b);
if (std::isnan(val_reg_b)) {
ppc_state.fpr[reg_d].int64_r = 0x80000000;
ppc_state.fpscr |= FPSCR::VXSNAN | FPSCR::VXCVI;
if (ppc_state.fpr[reg_b].int64_r & 0x0008000000000000) {
// isqnan
ppc_state.fpscr = (ppc_state.fpscr & ~(FPSCR::FR | FPSCR::FI)) | FPSCR::VXCVI;
}
else {
// issnan
ppc_state.fpscr = (ppc_state.fpscr & ~(FPSCR::FR | FPSCR::FI)) | FPSCR::VXCVI | FPSCR::VXSNAN;
}
if (ppc_state.fpscr & FPSCR::VE) {
ppc_floating_point_exception();
}
else {
ppc_state.fpr[reg_d].int64_r = 0xfff8000080000000;
}
}
else if (val_reg_b > static_cast<double>(0x7fffffff)) {
ppc_state.fpr[reg_d].int64_r = 0x7fffffff;
ppc_state.fpscr |= FPSCR::VXCVI;
ppc_state.fpscr = (ppc_state.fpscr & ~(FPSCR::FR | FPSCR::FI)) | FPSCR::VXCVI;
if (ppc_state.fpscr & FPSCR::VE) {
ppc_floating_point_exception();
}
else {
ppc_state.fpr[reg_d].int64_r = 0xfff800007fffffff;
}
}
else if (val_reg_b < -static_cast<double>(0x80000000)) {
ppc_state.fpr[reg_d].int64_r = 0x80000000;
ppc_state.fpscr |= FPSCR::VXCVI;
ppc_state.fpscr = (ppc_state.fpscr & ~(FPSCR::FR | FPSCR::FI)) | FPSCR::VXCVI;
if (ppc_state.fpscr & FPSCR::VE) {
ppc_floating_point_exception();
}
else {
ppc_state.fpr[reg_d].int64_r = 0xfff8000080000000;
}
}
else {
switch (ppc_state.fpscr & 0x3) {
@ -659,7 +681,6 @@ void dppc_interpreter::ppc_fctiw() {
}
ppc_store_dfpresult_int(reg_d);
}
if (rc_flag)
@ -671,20 +692,41 @@ void dppc_interpreter::ppc_fctiwz() {
double val_reg_b = GET_FPR(reg_b);
if (std::isnan(val_reg_b)) {
ppc_state.fpr[reg_d].int64_r = 0x80000000;
ppc_state.fpscr |= FPSCR::VXSNAN | FPSCR::VXCVI;
if (ppc_state.fpr[reg_b].int64_r & 0x0008000000000000) {
// isqnan
ppc_state.fpscr = (ppc_state.fpscr & ~(FPSCR::FR | FPSCR::FI)) | FPSCR::VXCVI;
}
else {
// issnan
ppc_state.fpscr = (ppc_state.fpscr & ~(FPSCR::FR | FPSCR::FI)) | FPSCR::VXCVI | FPSCR::VXSNAN;
}
if (ppc_state.fpscr & FPSCR::VE) {
ppc_floating_point_exception();
}
else {
ppc_state.fpr[reg_d].int64_r = 0xfff8000080000000;
}
}
else if (val_reg_b > static_cast<double>(0x7fffffff)) {
ppc_state.fpr[reg_d].int64_r = 0x7fffffff;
ppc_state.fpscr |= FPSCR::VXCVI;
ppc_state.fpscr = (ppc_state.fpscr & ~(FPSCR::FR | FPSCR::FI)) | FPSCR::VXCVI;
if (ppc_state.fpscr & FPSCR::VE) {
ppc_floating_point_exception();
}
else {
ppc_state.fpr[reg_d].int64_r = 0xfff800007fffffff;
}
}
else if (val_reg_b < -static_cast<double>(0x80000000)) {
ppc_state.fpr[reg_d].int64_r = 0x80000000;
ppc_state.fpscr |= FPSCR::VXCVI;
ppc_state.fpscr = (ppc_state.fpscr & ~(FPSCR::FR | FPSCR::FI)) | FPSCR::VXCVI;
if (ppc_state.fpscr & FPSCR::VE) {
ppc_floating_point_exception();
}
else {
ppc_state.fpr[reg_d].int64_r = 0xfff8000080000000;
}
}
else {
ppc_result64_d = round_to_zero(val_reg_b);
uint64_t ppc_result64_d = round_to_zero(val_reg_b);
ppc_store_dfpresult_int(reg_d);
}