ref: baa9e6a32f5eb94d1c0d2314fa3ad69ad6567945
parent: 59a2d2650eac83276f32ed8dd869eb39759b2911
author: allkern <lisandroaalarcon@gmail.com>
date: Wed Jun 28 12:59:05 EDT 2023
Fix sub overflow detection Implement ADEL and ADES exceptions Fix initial CPU fetch
--- a/frontend/main.c
+++ b/frontend/main.c
@@ -52,7 +52,7 @@
psx_gpu_set_udata(gpu, 0, screen);
if (cfg->exe) {- while (psx->cpu->pc != 0x80030008) {+ while (psx->cpu->pc != 0xBFC06FF0) {psx_update(psx);
}
--- a/psx/cpu.c
+++ b/psx/cpu.c
@@ -50,7 +50,7 @@
cpu->pc += 4;
// Discard fetch cycles
- cpu->last_cycles += psx_bus_get_access_cycles(cpu->bus);
+ psx_bus_get_access_cycles(cpu->bus);
}
void psx_cpu_init(psx_cpu_t* cpu, psx_bus_t* bus) {@@ -122,11 +122,14 @@
};
psx_cpu_instruction_t g_psx_cpu_bxx_table[] = {- psx_cpu_i_bltz , psx_cpu_i_bgez , psx_cpu_i_invalid, psx_cpu_i_invalid,
- psx_cpu_i_invalid, psx_cpu_i_invalid, psx_cpu_i_invalid, psx_cpu_i_invalid,
- psx_cpu_i_invalid, psx_cpu_i_invalid, psx_cpu_i_invalid, psx_cpu_i_invalid,
- psx_cpu_i_invalid, psx_cpu_i_invalid, psx_cpu_i_invalid, psx_cpu_i_invalid,
- psx_cpu_i_bltzal , psx_cpu_i_bgezal , psx_cpu_i_invalid, psx_cpu_i_invalid
+ psx_cpu_i_bltz , psx_cpu_i_bgez , psx_cpu_i_bltz , psx_cpu_i_bgez ,
+ psx_cpu_i_bltz , psx_cpu_i_bgez , psx_cpu_i_bltz , psx_cpu_i_bgez ,
+ psx_cpu_i_bltz , psx_cpu_i_bgez , psx_cpu_i_bltz , psx_cpu_i_bgez ,
+ psx_cpu_i_bltz , psx_cpu_i_bgez , psx_cpu_i_bltz , psx_cpu_i_bgez ,
+ psx_cpu_i_bltzal , psx_cpu_i_bgezal , psx_cpu_i_bltzal , psx_cpu_i_bgezal ,
+ psx_cpu_i_bltzal , psx_cpu_i_bgezal , psx_cpu_i_bltzal , psx_cpu_i_bgezal ,
+ psx_cpu_i_bltzal , psx_cpu_i_bgezal , psx_cpu_i_bltzal , psx_cpu_i_bgezal ,
+ psx_cpu_i_bltzal , psx_cpu_i_bgezal , psx_cpu_i_bltzal , psx_cpu_i_bgezal
};
#define OP ((cpu->buf[1] >> 26) & 0x3f)
@@ -339,7 +342,7 @@
// If we're in a delay slot, set delay slot bit
// on CAUSE
if (cpu->delay_slot) {- cpu->cop0_epc = cpu->pc - 4;
+ cpu->cop0_epc = cpu->pc - 12;
cpu->cop0_cause |= 0x80000000;
} else {cpu->cop0_epc = cpu->pc - 8;
@@ -366,9 +369,9 @@
}
void psx_cpu_i_invalid(psx_cpu_t* cpu) {- log_warn("%08x: Illegal instruction %08x", cpu->pc - 8, cpu->buf[1]);+ log_fatal("%08x: Illegal instruction %08x", cpu->pc - 8, cpu->buf[1]);- //psx_cpu_exception(cpu, CAUSE_RI);
+ psx_cpu_exception(cpu, CAUSE_RI);
}
// Primary
@@ -649,8 +652,14 @@
DO_PENDING_LOAD;
- cpu->load_d = T;
- cpu->load_v = SE16(psx_bus_read16(cpu->bus, s + IMM16S));
+ uint32_t addr = s + IMM16S;
+
+ if (addr & 0x1) {+ psx_cpu_exception(cpu, CAUSE_ADEL);
+ } else {+ cpu->load_d = T;
+ cpu->load_v = SE16(psx_bus_read16(cpu->bus, addr));
+ }
}
void psx_cpu_i_lwl(psx_cpu_t* cpu) {@@ -676,11 +685,16 @@
TRACE_M("lw");uint32_t s = cpu->r[S];
+ uint32_t addr = s + IMM16S;
DO_PENDING_LOAD;
- cpu->load_d = T;
- cpu->load_v = psx_bus_read32(cpu->bus, s + IMM16S);
+ if (addr & 0x3) {+ psx_cpu_exception(cpu, CAUSE_ADEL);
+ } else {+ cpu->load_d = T;
+ cpu->load_v = psx_bus_read32(cpu->bus, addr);
+ }
}
void psx_cpu_i_lbu(psx_cpu_t* cpu) {@@ -698,11 +712,16 @@
TRACE_M("lhu");uint32_t s = cpu->r[S];
+ uint32_t addr = s + IMM16S;
DO_PENDING_LOAD;
- cpu->load_d = T;
- cpu->load_v = psx_bus_read16(cpu->bus, s + IMM16S);
+ if (addr & 0x1) {+ psx_cpu_exception(cpu, CAUSE_ADEL);
+ } else {+ cpu->load_d = T;
+ cpu->load_v = psx_bus_read16(cpu->bus, addr);
+ }
}
void psx_cpu_i_lwr(psx_cpu_t* cpu) {@@ -745,6 +764,7 @@
uint32_t s = cpu->r[S];
uint32_t t = cpu->r[T];
+ uint32_t addr = s + IMM16S;
DO_PENDING_LOAD;
@@ -755,7 +775,11 @@
return;
}
- psx_bus_write16(cpu->bus, s + IMM16S, t);
+ if (addr & 0x1) {+ psx_cpu_exception(cpu, CAUSE_ADES);
+ } else {+ psx_bus_write16(cpu->bus, addr, t);
+ }
}
void psx_cpu_i_swl(psx_cpu_t* cpu) {@@ -784,6 +808,7 @@
uint32_t s = cpu->r[S];
uint32_t t = cpu->r[T];
+ uint32_t addr = s + IMM16S;
DO_PENDING_LOAD;
@@ -794,7 +819,11 @@
return;
}
- psx_bus_write32(cpu->bus, s + IMM16S, t);
+ if (addr & 0x3) {+ psx_cpu_exception(cpu, CAUSE_ADES);
+ } else {+ psx_bus_write32(cpu->bus, addr, t);
+ }
}
void psx_cpu_i_swr(psx_cpu_t* cpu) {@@ -1093,18 +1122,16 @@
int32_t s = (int32_t)cpu->r[S];
int32_t t = (int32_t)cpu->r[T];
+ int32_t r;
DO_PENDING_LOAD;
- int32_t r = s - t;
+ int o = __builtin_ssub_overflow(s, t, &r);
- // To-do: Check SUB overflow check
- uint32_t o = (s ^ t) & (t & r);
-
- if (o & 0x80000000) {+ if (o) {psx_cpu_exception(cpu, CAUSE_OV);
} else {- cpu->r[D] = (uint32_t)r;
+ cpu->r[D] = r;
}
}
@@ -1249,7 +1276,7 @@
DO_PENDING_LOAD;
- uint32_t mode = cpu->cop0_sr & 0xf;
+ uint32_t mode = cpu->cop0_sr & 0x3f;
cpu->cop0_sr &= 0xfffffff0;
cpu->cop0_sr |= mode >> 2;
--- a/psx/cpu.h
+++ b/psx/cpu.h
@@ -186,11 +186,11 @@
#define CAUSE_ADES 0x05
#define CAUSE_IBE 0x06
#define CAUSE_DBE 0x07
-#define CAUSE_SYSCALL 0x08
-#define CAUSE_BP 0x09
-#define CAUSE_RI 0x0a
-#define CAUSE_CPU 0x0b
-#define CAUSE_OV 0x0c
+#define CAUSE_SYSCALL 0x08
+#define CAUSE_BP 0x09
+#define CAUSE_RI 0x0a
+#define CAUSE_CPU 0x0b
+#define CAUSE_OV 0x0c
void psx_cpu_i_invalid(psx_cpu_t*);
--- a/psx/dev/gpu.c
+++ b/psx/dev/gpu.c
@@ -712,7 +712,7 @@
gpu->line++;
if (gpu->line == GPU_SCANS_PER_FRAME_NTSC) {- psx_ic_irq(gpu->ic, IC_VBLANK);
+ // psx_ic_irq(gpu->ic, IC_VBLANK);
gpu->line = 0;
} else {--- a/psx/psx.c
+++ b/psx/psx.c
@@ -106,14 +106,11 @@
psx_scratchpad_init(psx->scratchpad);
psx_gpu_init(psx->gpu, psx->ic);
psx_spu_init(psx->spu);
- psx_cpu_init(psx->cpu, psx->bus);
psx_timer_init(psx->timer);
psx_cdrom_init(psx->cdrom, psx->ic);
psx_pad_init(psx->pad);
-
psx_bios_load(psx->bios, bios_path);
-
- psx_cpu_fetch(psx->cpu);
+ psx_cpu_init(psx->cpu, psx->bus);
}
void psx_hard_reset(psx_t* psx) {--
⑨