ref: 35e060d44959b30447b51c5a3ef2100124b61725
parent: 40fb4a3ae2f05f500cc3e1c0b5fc7031ce02b4ab
author: allkern <lisandroaalarcon@gmail.com>
date: Sun Jul 2 19:31:18 EDT 2023
Improve IRQ handling
--- a/psx/cpu.c
+++ b/psx/cpu.c
@@ -65,6 +65,25 @@
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 @@
return;
}
+ if (psx_cpu_check_irq(cpu))
+ return;
+
psx_cpu_fetch(cpu);
cpu->delay_slot = cpu->branch;
@@ -333,32 +355,20 @@
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;
+ cpu->total_cycles += cpu->last_cycles;
- cpu->last_cycles = 2 + psx_bus_get_access_cycles(cpu->bus);
-
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 @@
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 @@
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) {--- a/psx/cpu.h
+++ b/psx/cpu.h
@@ -161,7 +161,7 @@
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
--- a/psx/dev/gpu.c
+++ b/psx/dev/gpu.c
@@ -759,7 +759,7 @@
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 @@
// 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);
}
--- a/psx/dev/pad.c
+++ b/psx/dev/pad.c
@@ -42,7 +42,7 @@
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;
--- a/psx/dev/timer.c
+++ b/psx/dev/timer.c
@@ -38,16 +38,16 @@
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);--- a/psx/psx.c
+++ b/psx/psx.c
@@ -28,7 +28,7 @@
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) {--
⑨