diff --git a/cpu/ppc/ppcexec.cpp b/cpu/ppc/ppcexec.cpp index 3248165486..2a1371b120 100644 --- a/cpu/ppc/ppcexec.cpp +++ b/cpu/ppc/ppcexec.cpp @@ -275,6 +275,17 @@ PPCOpcode* ppc_opcode_grabber = OpcodeGrabberNoFPU; /** Exception helpers. */ void ppc_illegalop(uint32_t opcode) { + // Zero values are used as sentinels in the TNT ROM and are thus somewhat + // common, don't log them. + if (opcode) { + PPCDisasmContext ctx; + ctx.instr_code = opcode; + ctx.instr_addr = 0; + ctx.simplified = false; + auto op_name = disassemble_single(&ctx); + LOG_F(WARNING, "Illegal opcode exception raised for 0x%08x (decoded as %s). The PC was 0x%08x.", opcode, op_name.c_str(), ppc_state.pc); + } + ppc_exception_handler(Except_Type::EXC_PROGRAM, Exc_Cause::ILLEGAL_OP); } diff --git a/cpu/ppc/ppcfpopcodes.cpp b/cpu/ppc/ppcfpopcodes.cpp index 88263b0faf..d62deb9b5f 100644 --- a/cpu/ppc/ppcfpopcodes.cpp +++ b/cpu/ppc/ppcfpopcodes.cpp @@ -1025,7 +1025,7 @@ void dppc_interpreter::ppc_lfsu(uint32_t opcode) { ppc_store_iresult_reg(reg_a, ea); } else { - ppc_exception_handler(Except_Type::EXC_PROGRAM, Exc_Cause::ILLEGAL_OP); + ppc_illegalop(opcode); } } @@ -1046,7 +1046,7 @@ void dppc_interpreter::ppc_lfsux(uint32_t opcode) { ppc_store_iresult_reg(reg_a, ea); } else { - ppc_exception_handler(Except_Type::EXC_PROGRAM, Exc_Cause::ILLEGAL_OP); + ppc_illegalop(opcode); return; } } @@ -1070,7 +1070,7 @@ void dppc_interpreter::ppc_lfdu(uint32_t opcode) { ppc_store_iresult_reg(reg_a, ea); } else { - ppc_exception_handler(Except_Type::EXC_PROGRAM, Exc_Cause::ILLEGAL_OP); + ppc_illegalop(opcode); } } @@ -1091,7 +1091,7 @@ void dppc_interpreter::ppc_lfdux(uint32_t opcode) { ppc_store_iresult_reg(reg_a, ea); } else { - ppc_exception_handler(Except_Type::EXC_PROGRAM, Exc_Cause::ILLEGAL_OP); + ppc_illegalop(opcode); } } @@ -1114,7 +1114,7 @@ void dppc_interpreter::ppc_stfsu(uint32_t opcode) { ppc_store_iresult_reg(reg_a, ea); } else { - ppc_exception_handler(Except_Type::EXC_PROGRAM, Exc_Cause::ILLEGAL_OP); + ppc_illegalop(opcode); } } @@ -1135,7 +1135,7 @@ void dppc_interpreter::ppc_stfsux(uint32_t opcode) { ppc_store_iresult_reg(reg_a, ea); } else { - ppc_exception_handler(Except_Type::EXC_PROGRAM, Exc_Cause::ILLEGAL_OP); + ppc_illegalop(opcode); } } @@ -1156,7 +1156,7 @@ void dppc_interpreter::ppc_stfdu(uint32_t opcode) { ppc_store_iresult_reg(reg_a, ea); } else { - ppc_exception_handler(Except_Type::EXC_PROGRAM, Exc_Cause::ILLEGAL_OP); + ppc_illegalop(opcode); } } @@ -1175,7 +1175,7 @@ void dppc_interpreter::ppc_stfdux(uint32_t opcode) { ppc_store_iresult_reg(reg_a, ea); } else { - ppc_exception_handler(Except_Type::EXC_PROGRAM, Exc_Cause::ILLEGAL_OP); + ppc_illegalop(opcode); } } diff --git a/cpu/ppc/ppcmmu.cpp b/cpu/ppc/ppcmmu.cpp index 765b51a30b..09c434a752 100644 --- a/cpu/ppc/ppcmmu.cpp +++ b/cpu/ppc/ppcmmu.cpp @@ -1088,7 +1088,7 @@ static void mpc601_bat_update(uint32_t bat_reg) static void mpc601_dbat_update(uint32_t /*bat_reg*/) { - // ppc_exception_handler(Except_Type::EXC_PROGRAM, Exc_Cause::ILLEGAL_OP); + // ppc_illegalop(opcode); } static void ppc_ibat_update(uint32_t bat_reg) diff --git a/cpu/ppc/ppcopcodes.cpp b/cpu/ppc/ppcopcodes.cpp index 9fc410d9a1..3faeaa7713 100644 --- a/cpu/ppc/ppcopcodes.cpp +++ b/cpu/ppc/ppcopcodes.cpp @@ -1002,14 +1002,14 @@ void dppc_interpreter::ppc_mfspr(uint32_t opcode) { switch (ref_spr) { case SPR::MQ: if (!(is_601 || include_601)) { - ppc_exception_handler(Except_Type::EXC_PROGRAM, Exc_Cause::ILLEGAL_OP); + ppc_illegalop(opcode); return; } ppc_state.gpr[reg_d] = ppc_state.spr[ref_spr]; break; case SPR::RTCL_U: if (!is_601) { - ppc_exception_handler(Except_Type::EXC_PROGRAM, Exc_Cause::ILLEGAL_OP); + ppc_illegalop(opcode); return; } calc_rtcl_value(); @@ -1019,7 +1019,7 @@ void dppc_interpreter::ppc_mfspr(uint32_t opcode) { break; case SPR::RTCU_U: if (!is_601) { - ppc_exception_handler(Except_Type::EXC_PROGRAM, Exc_Cause::ILLEGAL_OP); + ppc_illegalop(opcode); return; } calc_rtcl_value(); @@ -1029,7 +1029,7 @@ void dppc_interpreter::ppc_mfspr(uint32_t opcode) { break; case SPR::DEC_U: if (!is_601) { - ppc_exception_handler(Except_Type::EXC_PROGRAM, Exc_Cause::ILLEGAL_OP); + ppc_illegalop(opcode); return; } // fallthrough @@ -1093,13 +1093,13 @@ void dppc_interpreter::ppc_mtspr(uint32_t opcode) { if (is_601 || include_601) ppc_state.spr[ref_spr] = val; else - ppc_exception_handler(Except_Type::EXC_PROGRAM, Exc_Cause::ILLEGAL_OP); + ppc_illegalop(opcode); break; case SPR::RTCL_U: case SPR::RTCU_U: case SPR::DEC_U: if (!is_601) { - ppc_exception_handler(Except_Type::EXC_PROGRAM, Exc_Cause::ILLEGAL_OP); + ppc_illegalop(opcode); } break; case SPR::XER: @@ -1214,7 +1214,7 @@ void dppc_interpreter::ppc_mftb(uint32_t opcode) { ppc_state.spr[TBL_S] = uint32_t(tbr_value); break; default: - ppc_exception_handler(Except_Type::EXC_PROGRAM, Exc_Cause::ILLEGAL_OP); + ppc_illegalop(opcode); } } @@ -1700,14 +1700,16 @@ void dppc_interpreter::ppc_stu(uint32_t opcode) { #endif ppc_grab_regssa(opcode); - if (reg_a != 0) { + // MPC601 permits RA=0 for POWER compatibility and suppresses the update. + if (reg_a != 0 || is_601) { uint32_t ea = int32_t(int16_t(opcode)); - ea += ppc_result_a; + ea += reg_a ? ppc_result_a : 0; mmu_write_vmem(opcode, ea, ppc_result_d); - ppc_state.gpr[reg_a] = ea; + if (reg_a != 0) + ppc_state.gpr[reg_a] = ea; } else { - ppc_exception_handler(Except_Type::EXC_PROGRAM, Exc_Cause::ILLEGAL_OP); + ppc_illegalop(opcode); } } @@ -1723,13 +1725,15 @@ void dppc_interpreter::ppc_stux(uint32_t opcode) { #endif ppc_grab_regssab(opcode); - if (reg_a != 0) { - uint32_t ea = ppc_result_a + ppc_result_b; + // MPC601 permits RA=0 for POWER compatibility and suppresses the update. + if (reg_a != 0 || is_601) { + uint32_t ea = (reg_a ? ppc_result_a : 0) + ppc_result_b; mmu_write_vmem(opcode, ea, ppc_result_d); - ppc_state.gpr[reg_a] = ea; + if (reg_a != 0) + ppc_state.gpr[reg_a] = ea; } else { - ppc_exception_handler(Except_Type::EXC_PROGRAM, Exc_Cause::ILLEGAL_OP); + ppc_illegalop(opcode); } } @@ -1821,7 +1825,7 @@ void dppc_interpreter::ppc_lzu(uint32_t opcode) { ppc_result_a = ea; ppc_store_iresult_reg(reg_a, ppc_result_a); } else { - ppc_exception_handler(Except_Type::EXC_PROGRAM, Exc_Cause::ILLEGAL_OP); + ppc_illegalop(opcode); } } @@ -1857,7 +1861,7 @@ void dppc_interpreter::ppc_lzux(uint32_t opcode) { ppc_result_a = ea; ppc_store_iresult_reg(reg_a, ppc_result_a); } else { - ppc_exception_handler(Except_Type::EXC_PROGRAM, Exc_Cause::ILLEGAL_OP); + ppc_illegalop(opcode); } } @@ -1889,7 +1893,7 @@ void dppc_interpreter::ppc_lhau(uint32_t opcode) { ppc_result_a = ea; ppc_store_iresult_reg(reg_a, ppc_result_a); } else { - ppc_exception_handler(Except_Type::EXC_PROGRAM, Exc_Cause::ILLEGAL_OP); + ppc_illegalop(opcode); } } @@ -1906,7 +1910,7 @@ void dppc_interpreter::ppc_lhaux(uint32_t opcode) { ppc_store_iresult_reg(reg_a, ppc_result_a); } else { - ppc_exception_handler(Except_Type::EXC_PROGRAM, Exc_Cause::ILLEGAL_OP); + ppc_illegalop(opcode); } } @@ -2014,7 +2018,7 @@ void dppc_interpreter::ppc_lswx(uint32_t opcode) { if ((reg_d == 0 && reg_a == 0) || (reg_d == reg_a) || (reg_d == reg_b)) { // UNTESTED! Does invalid form really cause exception? // G4 doesn't do exception - ppc_exception_handler(Except_Type::EXC_PROGRAM, Exc_Cause::ILLEGAL_OP); + ppc_illegalop(opcode); } */