From 67bd47f11f9315d9987361090e7e6cf87c4af93c Mon Sep 17 00:00:00 2001 From: joevt Date: Thu, 7 Mar 2024 02:36:43 -0800 Subject: [PATCH] ppcopcodes: Fixes for bcctr(l)?. Add MPC601 variants. Variants that decrement and test the ctr are invalid bon't don't appear to trigger an exception. The manual says MPC601 can decrement the counter. Other CPUs do not decrement the counter but will branch based on the value. --- cpu/ppc/ppcemu.h | 5 ++--- cpu/ppc/ppcexec.cpp | 17 ++++++++++++++--- cpu/ppc/ppcopcodes.cpp | 42 +++++++++++++++++++++++++----------------- 3 files changed, 41 insertions(+), 23 deletions(-) diff --git a/cpu/ppc/ppcemu.h b/cpu/ppc/ppcemu.h index 6bd070a..05e3323 100644 --- a/cpu/ppc/ppcemu.h +++ b/cpu/ppc/ppcemu.h @@ -371,7 +371,7 @@ void ppc_release_int(); //void ppc_opcode4(); void ppc_opcode16(); void ppc_opcode18(); -void ppc_opcode19(); +template void ppc_opcode19(); void ppc_opcode31(); void ppc_opcode59(); void ppc_opcode63(); @@ -416,8 +416,7 @@ extern void do_ctx_sync(void); // The functions used by the PowerPC processor namespace dppc_interpreter { -extern void ppc_bcctr(); -extern void ppc_bcctrl(); +template extern void ppc_bcctr(); extern void ppc_bclr(); extern void ppc_bclrl(); extern void ppc_crand(); diff --git a/cpu/ppc/ppcexec.cpp b/cpu/ppc/ppcexec.cpp index 00d076a..5998f1c 100644 --- a/cpu/ppc/ppcexec.cpp +++ b/cpu/ppc/ppcexec.cpp @@ -137,7 +137,7 @@ static PPCOpcode OpcodeGrabber[] = { ppc_illegalop, ppc_illegalop, ppc_illegalop, ppc_twi, ppc_illegalop, ppc_illegalop, ppc_illegalop, ppc_mulli, ppc_subfic, power_dozi, ppc_cmpli, ppc_cmpi, ppc_addic, ppc_addicdot, ppc_addi, - ppc_addis, ppc_opcode16, ppc_sc, ppc_opcode18, ppc_opcode19, + ppc_addis, ppc_opcode16, ppc_sc, ppc_opcode18, ppc_opcode19, ppc_rlwimi, ppc_rlwinm, power_rlmi, ppc_rlwnm, ppc_ori, ppc_oris, ppc_xori, ppc_xoris, ppc_andidot, ppc_andisdot, ppc_illegalop, ppc_opcode31, ppc_lwz, ppc_lwzu, ppc_lbz, @@ -203,6 +203,7 @@ void ppc_opcode18() { SubOpcode18Grabber[ppc_cur_instruction & 3](); } +template void ppc_opcode19() { uint16_t subop_grab = ppc_cur_instruction & 0x7FF; @@ -247,16 +248,25 @@ void ppc_opcode19() { ppc_cror(); break; case 1056: - ppc_bcctr(); + if (for601) + ppc_bcctr(); + else + ppc_bcctr(); break; case 1057: - ppc_bcctrl(); + if (for601) + ppc_bcctr(); + else + ppc_bcctr(); break; default: ppc_illegalop(); } } +template void ppc_opcode19(); +template void ppc_opcode19(); + void ppc_opcode31() { uint16_t subop_grab = (ppc_cur_instruction & 0x7FFUL) >> 1UL; rc_flag = ppc_cur_instruction & 0x1; @@ -763,6 +773,7 @@ void ppc_cpu_init(MemCtrlBase* mem_ctrl, uint32_t cpu_version, uint64_t tb_freq) initialize_ppc_opcode_tables(); if (cpu_version == PPC_VER::MPC601) { + OpcodeGrabber[19] = ppc_opcode19; SubOpcode31Grabber[370] = ppc_illegalop; // tlbia SubOpcode31Grabber[371] = ppc_illegalop; // mftb SubOpcode59Grabber[24] = ppc_illegalop; // fres diff --git a/cpu/ppc/ppcopcodes.cpp b/cpu/ppc/ppcopcodes.cpp index 98ad1ce..aaebcd0 100644 --- a/cpu/ppc/ppcopcodes.cpp +++ b/cpu/ppc/ppcopcodes.cpp @@ -1228,32 +1228,40 @@ void dppc_interpreter::ppc_bcla() { ppc_state.spr[SPR::LR] = ppc_state.pc + 4; } +template void dppc_interpreter::ppc_bcctr() { + uint32_t ctr_ok; + uint32_t cnd_ok; uint32_t br_bo = (ppc_cur_instruction >> 21) & 31; uint32_t br_bi = (ppc_cur_instruction >> 16) & 31; - uint32_t cnd_ok = (br_bo & 0x10) | \ - (!(ppc_state.cr & (0x80000000UL >> br_bi)) == !(br_bo & 0x08)); + uint32_t ctr = ppc_state.spr[SPR::CTR]; + uint32_t new_ctr; + if (for601) { + new_ctr = ctr - 1; + if (!(br_bo & 0x04)) { + ppc_state.spr[SPR::CTR] = new_ctr; /* decrement CTR */ + } + } + else { + new_ctr = ctr; + } + ctr_ok = (br_bo & 0x04) | ((new_ctr != 0) == !(br_bo & 0x02)); + cnd_ok = (br_bo & 0x10) | (!(ppc_state.cr & (0x80000000UL >> br_bi)) == !(br_bo & 0x08)); - if (cnd_ok) { - ppc_next_instruction_address = (ppc_state.spr[SPR::CTR] & ~3UL); + if (ctr_ok && cnd_ok) { + ppc_next_instruction_address = (ctr & ~3UL); exec_flags = EXEF_BRANCH; } + + if (l) + ppc_state.spr[SPR::LR] = ppc_state.pc + 4; } -void dppc_interpreter::ppc_bcctrl() { - uint32_t br_bo = (ppc_cur_instruction >> 21) & 31; - uint32_t br_bi = (ppc_cur_instruction >> 16) & 31; - - uint32_t cnd_ok = (br_bo & 0x10) | \ - (!(ppc_state.cr & (0x80000000UL >> br_bi)) == !(br_bo & 0x08)); - - if (cnd_ok) { - ppc_next_instruction_address = (ppc_state.spr[SPR::CTR] & ~3UL); - exec_flags = EXEF_BRANCH; - } - ppc_state.spr[SPR::LR] = ppc_state.pc + 4; -} +template void dppc_interpreter::ppc_bcctr(); +template void dppc_interpreter::ppc_bcctr(); +template void dppc_interpreter::ppc_bcctr(); +template void dppc_interpreter::ppc_bcctr(); void dppc_interpreter::ppc_bclr() { uint32_t br_bo = (ppc_cur_instruction >> 21) & 31;