diff --git a/cpu/ppc/ppcemu.h b/cpu/ppc/ppcemu.h index 181b81c..9e52a6e 100644 --- a/cpu/ppc/ppcemu.h +++ b/cpu/ppc/ppcemu.h @@ -306,6 +306,7 @@ extern jmp_buf exc_env; extern bool grab_return; extern bool power_on; +extern bool int_pin; extern bool is_601; // For PowerPC 601 Emulation extern bool is_altivec; // For Altivec Emulation @@ -334,7 +335,8 @@ extern void ppc_mmu_init(uint32_t cpu_version); void ppc_illegalop(); void ppc_fpu_off(); -void ppc_ext_int(); +void ppc_assert_int(); +void ppc_release_int(); //void ppc_opcode4(); void ppc_opcode16(); diff --git a/cpu/ppc/ppcexec.cpp b/cpu/ppc/ppcexec.cpp index 570c380..114d196 100644 --- a/cpu/ppc/ppcexec.cpp +++ b/cpu/ppc/ppcexec.cpp @@ -43,8 +43,8 @@ bool power_on = 1; SetPRS ppc_state; -bool rc_flag = 0; // Record flag -bool oe_flag = 0; // Overflow flag +bool rc_flag = 0; // Record flag +bool oe_flag = 0; // Overflow flag bool grab_return; bool grab_breakpoint; @@ -53,7 +53,8 @@ uint32_t ppc_cur_instruction; // Current instruction for the PPC uint32_t ppc_effective_address; uint32_t ppc_next_instruction_address; // Used for branching, setting up the NIA -unsigned exec_flags; +unsigned exec_flags; // execution control flags +bool int_pin = false; // interrupt request pin state: true - asserted /* copy of local variable bb_start_la. Need for correct calculation of CPU cycles after setjmp that clobbers @@ -170,12 +171,20 @@ void ppc_fpu_off() { ppc_exception_handler(Except_Type::EXC_PROGRAM, Exc_Cause::FPU_OFF); } -void ppc_ext_int() { +void ppc_assert_int() { + int_pin = true; if (ppc_state.msr & 0x8000) { + LOG_F(5, "CPU ExtIntHandler called"); ppc_exception_handler(Except_Type::EXC_EXT_INT, 0); + } else { + LOG_F(5, "CPU IRQ ignored!"); } } +void ppc_release_int() { + int_pin = false; +} + /** Opcode decoding functions. */ void ppc_opcode16() { @@ -395,6 +404,9 @@ void ppc_exec_single() mmu_translate_imem(ppc_state.pc); ppc_main_opcode(); + g_icycles++; + process_events(); + if (exec_flags) { if (exec_flags & EXEF_TIMER) { ppc_state.pc += 4; @@ -405,7 +417,6 @@ void ppc_exec_single() } else { ppc_state.pc += 4; } - g_icycles++; } /** Execute PPC code until goal_addr is reached. */ diff --git a/cpu/ppc/ppcopcodes.cpp b/cpu/ppc/ppcopcodes.cpp index 556cc209..6efb1a0 100644 --- a/cpu/ppc/ppcopcodes.cpp +++ b/cpu/ppc/ppcopcodes.cpp @@ -844,7 +844,15 @@ void dppc_interpreter::ppc_mtmsr() { } reg_s = (ppc_cur_instruction >> 21) & 31; ppc_state.msr = ppc_state.gpr[reg_s]; - mmu_change_mode(); + + // generate External Interrupt Exception + // if CPU interrupt line is asserted + if (ppc_state.msr & 0x8000 && int_pin) { + LOG_F(WARNING, "MTMSR: CPU INT pending, generate CPU exception"); + ppc_exception_handler(Except_Type::EXC_EXT_INT, 0); + } else { + mmu_change_mode(); + } } static inline uint64_t calc_rtcl_value() @@ -1359,6 +1367,16 @@ void dppc_interpreter::ppc_rfi() { uint32_t new_srr1_val = (ppc_state.spr[SPR::SRR1] & 0x87C0FF73UL); uint32_t new_msr_val = (ppc_state.msr & ~(0x87C0FF73UL)); ppc_state.msr = (new_msr_val | new_srr1_val) & 0xFFFBFFFFUL; + + // generate External Interrupt Exception + // if CPU interrupt line is still asserted + if (ppc_state.msr & 0x8000 && int_pin) { + uint32_t save_srr0 = ppc_state.spr[SPR::SRR0] & 0xFFFFFFFCUL; + ppc_exception_handler(Except_Type::EXC_EXT_INT, 0); + ppc_state.spr[SPR::SRR0] = save_srr0; + return; + } + ppc_next_instruction_address = ppc_state.spr[SPR::SRR0] & 0xFFFFFFFCUL; do_ctx_sync(); // RFI is context synchronizing