From c71d856a083a0266416a03b6463c618583282a72 Mon Sep 17 00:00:00 2001 From: joevt Date: Tue, 9 Apr 2024 01:54:28 -0700 Subject: [PATCH] poweropcodes: Fix lscbx. - Fix CR calculation. It depends on whether a match occurred and only the EQ flag is affected. - Remove bytes_copied. We can subtract bytes_remaining from bytes_to_load to calculate that. - Initialize ppc_result_d to zero so that bitmask is not needed to add new bytes to it. This is ok since the manual says that bytes that are not loaded are undefined. --- cpu/ppc/poweropcodes.cpp | 35 +++++++++++++++++++---------------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/cpu/ppc/poweropcodes.cpp b/cpu/ppc/poweropcodes.cpp index 9edaf99..b6cd798 100644 --- a/cpu/ppc/poweropcodes.cpp +++ b/cpu/ppc/poweropcodes.cpp @@ -212,47 +212,50 @@ void dppc_interpreter::power_lscbx() { ppc_grab_regsdab(ppc_cur_instruction); ppc_effective_address = ppc_result_b + (reg_a ? ppc_result_a : 0); - uint8_t return_value = 0; uint32_t bytes_to_load = (ppc_state.spr[SPR::XER] & 0x7F); - uint32_t bytes_copied = 0; + uint32_t bytes_remaining = bytes_to_load; uint8_t matching_byte = (uint8_t)(ppc_state.spr[SPR::XER] >> 8); - uint32_t ppc_result_d = 0; + uint32_t ppc_result_d = 0; + bool is_match = false; // for storing each byte - uint32_t bitmask = 0xFF000000; uint8_t shift_amount = 24; - while (bytes_to_load > 0) { - return_value = mmu_read_vmem(ppc_effective_address); + while (bytes_remaining > 0) { + uint8_t return_value = mmu_read_vmem(ppc_effective_address); - ppc_result_d = (ppc_result_d & ~bitmask) | (return_value << shift_amount); + ppc_result_d |= return_value << shift_amount; if (!shift_amount) { if (reg_d != reg_a && reg_d != reg_b) ppc_store_iresult_reg(reg_d, ppc_result_d); reg_d = (reg_d + 1) & 0x1F; - bitmask = 0xFF000000; + ppc_result_d = 0; shift_amount = 24; } else { - bitmask >>= 8; shift_amount -= 8; } ppc_effective_address++; - bytes_copied++; - bytes_to_load--; + bytes_remaining--; - if (return_value == matching_byte) + if (return_value == matching_byte) { + is_match = true; break; + } } - // store partiallly loaded register if any + // store partially loaded register if any if (shift_amount != 24 && reg_d != reg_a && reg_d != reg_b) ppc_store_iresult_reg(reg_d, ppc_result_d); - ppc_state.spr[SPR::XER] = (ppc_state.spr[SPR::XER] & ~0x7F) | bytes_copied; + ppc_state.spr[SPR::XER] = (ppc_state.spr[SPR::XER] & ~0x7F) | (bytes_to_load - bytes_remaining); - if (rec) - ppc_changecrf0(ppc_result_d); + if (rec) { + ppc_state.cr = + (ppc_state.cr & 0x0FFFFFFFUL) | + (is_match ? CRx_bit::CR_EQ : 0) | + ((ppc_state.spr[SPR::XER] & XER::SO) >> 3); + } } template void dppc_interpreter::power_lscbx();