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.
This commit is contained in:
joevt 2024-04-09 02:03:48 -07:00 committed by dingusdev
parent ef8522e101
commit 1e57ac408a
1 changed files with 11 additions and 9 deletions

View File

@ -306,17 +306,19 @@ template void dppc_interpreter::power_maskir<RC1>();
template <field_rc rec, field_ov ov>
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);
}