From 1e57ac408a4e22ab142021ecd513bbd92c456f2e Mon Sep 17 00:00:00 2001 From: joevt Date: Tue, 9 Apr 2024 02:03:48 -0700 Subject: [PATCH] poweropcodes: Fix mul. Operands are supposed to be twos complement numbers. Calculate overflow first before calculating condition codes because the overflow condition is copied from XER. Fix OV calculation. Previously, it was using power_setsoov which I think is only for add and subtract operations. Fix CR calcalation. It's supposed to depend on the low order 32 bits that are placed into MQ. --- cpu/ppc/poweropcodes.cpp | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/cpu/ppc/poweropcodes.cpp b/cpu/ppc/poweropcodes.cpp index df43d48..5583727 100644 --- a/cpu/ppc/poweropcodes.cpp +++ b/cpu/ppc/poweropcodes.cpp @@ -306,17 +306,19 @@ template void dppc_interpreter::power_maskir(); template void dppc_interpreter::power_mul() { ppc_grab_regsdab(ppc_cur_instruction); - uint64_t product; - - product = ((uint64_t)ppc_result_a) * ((uint64_t)ppc_result_b); - uint32_t ppc_result_d = ((uint32_t)(product >> 32)); - ppc_state.spr[SPR::MQ] = ((uint32_t)(product)); + int64_t product = int64_t(int32_t(ppc_result_a)) * int32_t(ppc_result_b); + uint32_t ppc_result_d = uint32_t(uint64_t(product) >> 32); + ppc_state.spr[SPR::MQ] = uint32_t(product); + if (ov) { + if (uint64_t(product >> 31) + 1 & ~1) { + ppc_state.spr[SPR::XER] |= XER::SO | XER::OV; + } else { + ppc_state.spr[SPR::XER] &= ~XER::OV; + } + } if (rec) - ppc_changecrf0(ppc_result_d); - if (ov) - power_setsoov(ppc_result_a, ppc_result_b, ppc_result_d); - + ppc_changecrf0(uint32_t(product)); ppc_store_iresult_reg(reg_d, ppc_result_d); }