mirror of
https://github.com/ARMSX2/ARMSX1.git
synced 2026-08-24 16:53:35 -07:00
Improve IRQ handling
This commit is contained in:
@@ -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) {
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user