Improve IRQ handling

This commit is contained in:
allkern
2023-07-02 23:31:18 -03:00
parent 40fb4a3ae2
commit 35e060d449
6 changed files with 52 additions and 37 deletions
+38 -23
View File
@@ -65,6 +65,25 @@ psx_cpu_instruction_t g_psx_cpu_bxx_table[] = {
psx_cpu_i_bltz , psx_cpu_i_bgez , psx_cpu_i_bltz , psx_cpu_i_bgez
};
uint32_t g_psx_cpu_cop0_write_mask_table[] = {
0x00000000, // cop0r0-r2 - N/A
0x00000000, // cop0r0-r2 - N/A
0x00000000, // cop0r0-r2 - N/A
0xffffffff, // cop0r3 - BPC - Breakpoint on execute (R/W)
0x00000000, // cop0r4 - N/A
0xffffffff, // cop0r5 - BDA - Breakpoint on data access (R/W)
0x00000000, // cop0r6 - JUMPDEST - Randomly memorized jump address (R)
0xffc0f03f, // cop0r7 - DCIC - Breakpoint control (R/W)
0x00000000, // cop0r8 - BadVaddr - Bad Virtual Address (R)
0xffffffff, // cop0r9 - BDAM - Data Access breakpoint mask (R/W)
0x00000000, // cop0r10 - N/A
0xffffffff, // cop0r11 - BPCM - Execute breakpoint mask (R/W)
0xffffffff, // cop0r12 - SR - System status register (R/W)
0x00000300, // cop0r13 - CAUSE - (R) Describes the most recently recognised exception
0x00000000, // cop0r14 - EPC - Return Address from Trap (R)
0x00000000 // cop0r15 - PRID - Processor ID (R)
};
#define OP ((cpu->buf[1] >> 26) & 0x3f)
#define S ((cpu->buf[1] >> 21) & 0x1f)
#define T ((cpu->buf[1] >> 16) & 0x1f)
@@ -326,6 +345,9 @@ void psx_cpu_cycle(psx_cpu_t* cpu) {
return;
}
if (psx_cpu_check_irq(cpu))
return;
psx_cpu_fetch(cpu);
cpu->delay_slot = cpu->branch;
@@ -333,32 +355,20 @@ void psx_cpu_cycle(psx_cpu_t* cpu) {
g_psx_cpu_primary_table[OP](cpu);
if ((cpu->cop0_r[COP0_SR] & SR_IEC) && (cpu->cop0_r[COP0_CAUSE] & cpu->cop0_r[COP0_SR] & SR_IM2)) {
psx_cpu_exception(cpu, CAUSE_INT);
}
cpu->last_cycles = 2 + psx_bus_get_access_cycles(cpu->bus);
cpu->last_cycles = 2;
cpu->total_cycles += cpu->last_cycles;
cpu->r[0] = 0;
}
void psx_cpu_check_irq(psx_cpu_t* cpu) {
if ((cpu->cop0_r[COP0_SR] & SR_IEC) && (cpu->cop0_r[COP0_CAUSE] & cpu->cop0_r[COP0_SR] & SR_IM2)) {
// log_fatal("(before) IRQ pc=%08x, epc=%08x, cause=%08x, sr=%08x, tc=%u (%08x), istat=%08x, imask=%08x, [0]=%08x, [1]=%08x",
// cpu->pc,
// cpu->cop0_r[COP0_EPC],
// cpu->cop0_r[COP0_CAUSE],
// cpu->cop0_r[COP0_SR],
// cpu->total_cycles,
// cpu->total_cycles,
// psx_bus_read32(cpu->bus, 0x1F801070),
// psx_bus_read32(cpu->bus, 0x1F801074),
// cpu->buf[0],
// cpu->buf[1]
// );
int psx_cpu_check_irq(psx_cpu_t* cpu) {
if ((cpu->cop0_r[COP0_SR] & SR_IEC) && (cpu->cop0_r[COP0_SR] & cpu->cop0_r[COP0_CAUSE] & 0x00000700)) {
psx_cpu_exception(cpu, CAUSE_INT);
return 1;
}
return 0;
}
void psx_cpu_exception(psx_cpu_t* cpu, uint32_t cause) {
@@ -366,13 +376,18 @@ void psx_cpu_exception(psx_cpu_t* cpu, uint32_t cause) {
cpu->cop0_r[COP0_CAUSE] &= 0xffffff80;
cpu->cop0_r[COP0_CAUSE] |= cause;
if (cause == CAUSE_INT) {
cpu->cop0_r[COP0_EPC] = cpu->pc - 4;
} else {
cpu->cop0_r[COP0_EPC] = cpu->pc - 8;
}
// If we're in a delay slot, set delay slot bit
// on CAUSE
if (cpu->delay_slot) {
cpu->cop0_r[COP0_EPC] = cpu->pc - 12;
cpu->cop0_r[COP0_EPC] -= 4;
cpu->cop0_r[COP0_CAUSE] |= 0x80000000;
} else {
cpu->cop0_r[COP0_EPC] = cpu->pc - 8;
cpu->cop0_r[COP0_CAUSE] &= 0x7fffffff;
}
@@ -1266,7 +1281,7 @@ void psx_cpu_i_mtc0(psx_cpu_t* cpu) {
DO_PENDING_LOAD;
cpu->cop0_r[D] = t;
cpu->cop0_r[D] = t & g_psx_cpu_cop0_write_mask_table[D];
}
void psx_cpu_i_ctc0(psx_cpu_t* cpu) {
+1 -1
View File
@@ -161,7 +161,7 @@ void psx_cpu_save_state(psx_cpu_t*, FILE*);
void psx_cpu_fetch(psx_cpu_t*);
void psx_cpu_set_a_kcall_hook(psx_cpu_t*, psx_cpu_kcall_hook_t);
void psx_cpu_set_b_kcall_hook(psx_cpu_t*, psx_cpu_kcall_hook_t);
void psx_cpu_check_irq(psx_cpu_t*);
int psx_cpu_check_irq(psx_cpu_t*);
/*
00h INT Interrupt
+2 -2
View File
@@ -759,7 +759,7 @@ void gpu_scanline_event(psx_gpu_t* gpu) {
if (gpu->line == GPU_SCANS_PER_VDRAW_NTSC) {
// Disable Vblank for now
// log_fatal("Vblank");
// psx_ic_irq(gpu->ic, IC_VBLANK);
psx_ic_irq(gpu->ic, IC_VBLANK);
} else if (gpu->line == GPU_SCANS_PER_FRAME_NTSC) {
gpu->line = 0;
}
@@ -780,7 +780,7 @@ void psx_gpu_update(psx_gpu_t* gpu, int cyc) {
// Tick Hblank timer
if (gpu->cycles >= (float)GPU_CYCLES_PER_SCANL_NTSC) {
gpu->cycles = 0;
gpu->cycles -= (float)GPU_CYCLES_PER_SCANL_NTSC;
gpu_scanline_event(gpu);
}
+1 -1
View File
@@ -42,7 +42,7 @@ uint32_t psx_pad_read32(psx_pad_t* pad, uint32_t offset) {
uint16_t psx_pad_read16(psx_pad_t* pad, uint32_t offset) {
switch (offset) {
// case 0: return 0x00;
// case 4: return 0x03;
case 4: return 0x05;
// case 8: return pad->mode;
case 10: return pad->ctrl;
// case 14: return pad->baud;
+9 -9
View File
@@ -38,16 +38,16 @@ uint16_t psx_timer_read16(psx_timer_t* timer, uint32_t offset) {
return 0x000016b0;
}
// int t = (offset >> 4) & 0x3;
// int r = offset & 0xf;
int t = (offset >> 4) & 0x3;
int r = offset & 0xf;
// if (r == 0) {
// switch (t) {
// case 0: return timer->t0_stub++;
// case 1: return timer->t1_stub++;
// case 2: return timer->t2_stub++;
// }
// }
if (r == 0) {
switch (t) {
case 0: return timer->t0_stub++;
case 1: return timer->t1_stub++;
case 2: return timer->t2_stub++;
}
}
log_fatal("Unhandled 16-bit TIMER read at offset %08x", offset);
+1 -1
View File
@@ -28,7 +28,7 @@ void psx_update(psx_t* psx) {
psx_cpu_cycle(psx->cpu);
psx_cdrom_update(psx->cdrom);
psx_gpu_update(psx->gpu, psx->cpu->last_cycles);
psx_cpu_check_irq(psx->cpu);
//psx_cpu_check_irq(psx->cpu);
}
void psx_run_frame(psx_t* psx) {