cpu/ppc: improve support for external interrupts.

Support generating of external interrupt exception
in MTMSR and RFI when MSR[EE] is re-enabled and
external interrupt still pending.
This commit is contained in:
Maxim Poliakovski 2022-08-24 12:51:43 +02:00
parent 141a276c5b
commit b38d00ce2d
3 changed files with 38 additions and 7 deletions

View File

@ -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();

View File

@ -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. */

View File

@ -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