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.
This commit is contained in:
joevt 2024-03-07 02:36:43 -08:00 committed by dingusdev
parent e44676e491
commit 67bd47f11f
3 changed files with 41 additions and 23 deletions

View File

@ -371,7 +371,7 @@ void ppc_release_int();
//void ppc_opcode4();
void ppc_opcode16();
void ppc_opcode18();
void ppc_opcode19();
template <bool for601> 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 <bool l, bool for601> extern void ppc_bcctr();
extern void ppc_bclr();
extern void ppc_bclrl();
extern void ppc_crand();

View File

@ -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<false>,
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<bool for601>
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<false, true>();
else
ppc_bcctr<false, false>();
break;
case 1057:
ppc_bcctrl();
if (for601)
ppc_bcctr<true, true>();
else
ppc_bcctr<true, false>();
break;
default:
ppc_illegalop();
}
}
template void ppc_opcode19<false>();
template void ppc_opcode19<true>();
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<true>;
SubOpcode31Grabber[370] = ppc_illegalop; // tlbia
SubOpcode31Grabber[371] = ppc_illegalop; // mftb
SubOpcode59Grabber[24] = ppc_illegalop; // fres

View File

@ -1228,32 +1228,40 @@ void dppc_interpreter::ppc_bcla() {
ppc_state.spr[SPR::LR] = ppc_state.pc + 4;
}
template<bool l, bool for601>
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<false, false>();
template void dppc_interpreter::ppc_bcctr<false, true>();
template void dppc_interpreter::ppc_bcctr<true, false>();
template void dppc_interpreter::ppc_bcctr<true, true>();
void dppc_interpreter::ppc_bclr() {
uint32_t br_bo = (ppc_cur_instruction >> 21) & 31;