diff --git a/cpu/ppc/ppcemu.h b/cpu/ppc/ppcemu.h index 3545754..3b97f85 100644 --- a/cpu/ppc/ppcemu.h +++ b/cpu/ppc/ppcemu.h @@ -339,6 +339,8 @@ extern void ppc_dcbtst(); extern void ppc_dcbz(); extern void ppc_divw(); extern void ppc_divwu(); +extern void ppc_eciwx(); +extern void ppc_ecowx(); extern void ppc_eieio(); extern void ppc_eqv(); extern void ppc_extsb(); diff --git a/cpu/ppc/ppcexec.cpp b/cpu/ppc/ppcexec.cpp index ba940fa..9b75933 100644 --- a/cpu/ppc/ppcexec.cpp +++ b/cpu/ppc/ppcexec.cpp @@ -606,6 +606,9 @@ void initialize_ppc_opcode_tables() { SubOpcode31Grabber[918] = ppc_sthbrx; SubOpcode31Grabber[983] = ppc_stfiwx; + SubOpcode31Grabber[310] = ppc_eciwx; + SubOpcode31Grabber[438] = ppc_ecowx; + SubOpcode31Grabber[24] = ppc_slw; SubOpcode31Grabber[28] = ppc_and; SubOpcode31Grabber[60] = ppc_andc; diff --git a/cpu/ppc/ppcopcodes.cpp b/cpu/ppc/ppcopcodes.cpp index 01f1d68..39d611f 100644 --- a/cpu/ppc/ppcopcodes.cpp +++ b/cpu/ppc/ppcopcodes.cpp @@ -909,17 +909,17 @@ void dppc_interpreter::ppc_mtspr() { void dppc_interpreter::ppc_mftb() { uint32_t ref_spr = (((ppc_cur_instruction >> 11) & 31) << 5) | ((ppc_cur_instruction >> 16) & 31); - reg_d = (ppc_cur_instruction >> 21) & 31; + reg_d = (ppc_cur_instruction >> 21) & 31; switch (ref_spr) { - case 268: - ppc_state.gpr[reg_d] = timebase_counter & 0xFFFFFFFFUL; - break; - case 269: - ppc_state.gpr[reg_d] = (timebase_counter >> 32) & 0xFFFFFFFFUL; - break; - default: - std::cout << "Invalid TBR access attempted!" << std::endl; - } + case 268: + ppc_state.gpr[reg_d] = timebase_counter & 0xFFFFFFFFUL; + break; + case 269: + ppc_state.gpr[reg_d] = (timebase_counter >> 32) & 0xFFFFFFFFUL; + break; + default: + LOG_F(ERROR, "Invalid TBR access attempted !\n"); + } } void dppc_interpreter::ppc_mtcrf() { @@ -2096,6 +2096,46 @@ void dppc_interpreter::ppc_stswx() { } } +void dppc_interpreter::ppc_eciwx() { + uint32_t ear_enable = 0x80000000; + + // error if EAR[E] != 1 + if (!(ppc_state.spr[282] && ear_enable)) { + ppc_exception_handler(Except_Type::EXC_DSI, 0x0); + } + + ppc_grab_regsdab(); + ppc_effective_address = (reg_a == 0) ? ppc_result_b : (ppc_result_a + ppc_result_b); + + if (ppc_effective_address & 0x3) { + ppc_exception_handler(Except_Type::EXC_ALIGNMENT, 0x0); + } + + ppc_result_d = mmu_read_vmem(ppc_effective_address); + + ppc_store_result_regd(); +} + +void dppc_interpreter::ppc_ecowx() { + uint32_t ear_enable = 0x80000000; + + // error if EAR[E] != 1 + if (!(ppc_state.spr[282] && ear_enable)) { + ppc_exception_handler(Except_Type::EXC_DSI, 0x0); + } + + ppc_grab_regssab(); + ppc_effective_address = (reg_a == 0) ? ppc_result_b : (ppc_result_a + ppc_result_b); + + if (ppc_effective_address & 0x3) { + ppc_exception_handler(Except_Type::EXC_ALIGNMENT, 0x0); + } + + mmu_write_vmem(ppc_effective_address, ppc_result_d); + + ppc_store_result_regd(); +} + // TLB Instructions void dppc_interpreter::ppc_tlbie() { @@ -2111,6 +2151,9 @@ void dppc_interpreter::ppc_tlbia() { num_supervisor_instrs++; #endif /* placeholder */ + if (ppc_state.spr[SPR::PVR] == PPC_VER::MPC601) { + ppc_exception_handler(Except_Type::EXC_PROGRAM, 0x0); + } } void dppc_interpreter::ppc_tlbld() { @@ -2132,4 +2175,7 @@ void dppc_interpreter::ppc_tlbsync() { num_supervisor_instrs++; #endif /* placeholder */ + if (ppc_state.spr[SPR::PVR] == PPC_VER::MPC601) { + ppc_exception_handler(Except_Type::EXC_PROGRAM, 0x0); + } }