diff --git a/cpu/ppc/ppcopcodes.cpp b/cpu/ppc/ppcopcodes.cpp index faf8864..adcd8df 100644 --- a/cpu/ppc/ppcopcodes.cpp +++ b/cpu/ppc/ppcopcodes.cpp @@ -385,23 +385,19 @@ void dppc_interpreter::ppc_subfme() { void dppc_interpreter::ppc_subfze() { ppc_grab_regsda(); - ppc_result_d = ~ppc_result_a + !!(ppc_state.spr[SPR::XER] & 0x20000000); + uint32_t grab_ca = !!(ppc_state.spr[SPR::XER] & XER::CA); + ppc_result_d = ~ppc_result_a + grab_ca; - if (ppc_result_d == ppc_result_a) { - // this only occurs when CA is 1 and ppc_result_a is 0x00000000 or 0x80000000 - if (ppc_result_d == 0) { - ppc_state.spr[SPR::XER] |= 0x20000000UL; // set CA - if (oe_flag) - ppc_state.spr[SPR::XER] &= ~0x40000000UL; // clear OV - } else { - ppc_state.spr[SPR::XER] &= ~0x20000000UL; // clear CA - if (oe_flag) - ppc_state.spr[SPR::XER] |= 0xC0000000UL; // set SO,OV - } - } else { - ppc_state.spr[SPR::XER] &= ~0x20000000UL; // clear CA - if (oe_flag) - ppc_state.spr[SPR::XER] &= ~0x40000000UL; // clear OV + if (!ppc_result_d && grab_ca) // special case: ppc_result_d = 0 and CA=1 + ppc_state.spr[SPR::XER] |= XER::CA; + else + ppc_state.spr[SPR::XER] &= ~XER::CA; + + if (oe_flag) { + if (ppc_result_d && ppc_result_d == ppc_result_a) + ppc_state.spr[SPR::XER] |= XER::SO | XER::OV; + else + ppc_state.spr[SPR::XER] &= ~XER::OV; } if (rc_flag)