static void schedule_timeslice(void)
{
u32 i, c = psxRegs.cycle;
+ u32 irqs = psxRegs.interrupt;
s32 min, dif;
- min = psxNextsCounter + psxNextCounter - c;
- for (i = 0; i < ARRAY_SIZE(event_cycles); i++) {
+ min = PSXCLK;
+ for (i = 0; irqs != 0; i++, irqs >>= 1) {
+ if (!(irqs & 1))
+ continue;
dif = event_cycles[i] - c;
//evprintf(" ev %d\n", dif);
if (0 < dif && dif < min)
min = dif;
}
next_interupt = c + min;
-
-#if 0
- static u32 cnt, last_cycle;
- static u64 sum;
- if (last_cycle) {
- cnt++;
- sum += psxRegs.cycle - last_cycle;
- if ((cnt & 0xff) == 0)
- printf("%u\n", (u32)(sum / cnt));
- }
- last_cycle = psxRegs.cycle;
-#endif
}
typedef void (irq_func)();
[PSXINT_CDRDMA] = cdrDmaInterrupt,
[PSXINT_CDRLID] = cdrLidSeekInterrupt,
[PSXINT_CDRPLAY] = cdrPlayInterrupt,
+ [PSXINT_SPU_UPDATE] = spuUpdate,
+ [PSXINT_RCNT] = psxRcntUpdate,
};
/* local dupe of psxBranchTest, using event_cycles */
u32 cycle = psxRegs.cycle;
u32 irq, irq_bits;
- if ((psxRegs.cycle - psxNextsCounter) >= psxNextCounter)
- psxRcntUpdate();
-
// irq_funcs() may queue more irqs
psxRegs.interrupt = 0;
evprintf("MTC0 %d #%x @%08x %u\n", reg, val, psxRegs.pc, psxRegs.cycle);
MTC0(reg, val);
gen_interupt();
+ if (Cause & Status & 0x0300) // possible sw irq
+ pending_exception = 1;
}
void pcsx_mtc0_ds(u32 reg, u32 val)
MTC0(reg, val);
}
-void new_dyna_save(void)
+void new_dyna_before_save(void)
{
+ psxRegs.interrupt &= ~(1 << PSXINT_RCNT); // old savestate compat
+
// psxRegs.intCycle is always maintained, no need to convert
}
-void new_dyna_restore(void)
+void new_dyna_after_save(void)
+{
+ psxRegs.interrupt |= 1 << PSXINT_RCNT;
+}
+
+static void new_dyna_restore(void)
{
int i;
for (i = 0; i < PSXINT_COUNT; i++)
event_cycles[i] = psxRegs.intCycle[i].sCycle + psxRegs.intCycle[i].cycle;
+ event_cycles[PSXINT_RCNT] = psxNextsCounter + psxNextCounter;
+ psxRegs.interrupt |= 1 << PSXINT_RCNT;
+ psxRegs.interrupt &= (1 << PSXINT_COUNT) - 1;
+
new_dyna_pcsx_mem_load_state();
}
+void new_dyna_freeze(void *f, int mode)
+{
+ const char header_save[8] = "ariblks";
+ uint32_t addrs[1024 * 4];
+ int32_t size = 0;
+ int bytes;
+ char header[8];
+
+ if (mode != 0) { // save
+ size = new_dynarec_save_blocks(addrs, sizeof(addrs));
+ if (size == 0)
+ return;
+
+ SaveFuncs.write(f, header_save, sizeof(header_save));
+ SaveFuncs.write(f, &size, sizeof(size));
+ SaveFuncs.write(f, addrs, size);
+ }
+ else {
+ new_dyna_restore();
+
+ bytes = SaveFuncs.read(f, header, sizeof(header));
+ if (bytes != sizeof(header) || strcmp(header, header_save)) {
+ if (bytes > 0)
+ SaveFuncs.seek(f, -bytes, SEEK_CUR);
+ return;
+ }
+ SaveFuncs.read(f, &size, sizeof(size));
+ if (size <= 0)
+ return;
+ if (size > sizeof(addrs)) {
+ bytes = size - sizeof(addrs);
+ SaveFuncs.seek(f, bytes, SEEK_CUR);
+ size = sizeof(addrs);
+ }
+ bytes = SaveFuncs.read(f, addrs, size);
+ if (bytes != size)
+ return;
+
+ new_dynarec_load_blocks(addrs, size);
+ }
+
+ //printf("drc: %d block info entries %s\n", size/8, mode ? "saved" : "loaded");
+}
+
+#ifndef DRC_DISABLE
+
/* GTE stuff */
void *gte_handlers[64];
[GTE_OP] = GCBITS3(0,2,4) | GDBITS3(9,10,11),
[GTE_DPCS] = GCBITS3(21,22,23) | GDBITS4(6,8,21,22),
[GTE_INTPL] = GCBITS3(21,22,23) | GDBITS7(6,8,9,10,11,21,22),
- [GTE_MVMVA] = 0x00ffffff00000000ll | GDBITS6(0,1,2,3,4,5), // XXX: maybe decode further?
- [GTE_NCDS] = 0x00ffff0000000000ll | GDBITS5(0,1,6,21,22),
- [GTE_CDP] = 0x00fff00000000000ll | GDBITS7(6,8,9,10,11,21,22),
+ [GTE_MVMVA] = 0x00ffffff00000000ll | GDBITS9(0,1,2,3,4,5,9,10,11), // XXX: maybe decode further?
+ [GTE_NCDS] = 0x00ffff0000000000ll | GDBITS6(0,1,6,8,21,22),
+ [GTE_CDP] = 0x00ffe00000000000ll | GDBITS7(6,8,9,10,11,21,22),
[GTE_NCDT] = 0x00ffff0000000000ll | GDBITS8(0,1,2,3,4,5,6,8),
- [GTE_NCCS] = 0x00ffff0000000000ll | GDBITS6(0,1,6,8,21,22),
+ [GTE_NCCS] = 0x001fff0000000000ll | GDBITS5(0,1,6,21,22),
[GTE_CC] = 0x001fe00000000000ll | GDBITS6(6,9,10,11,21,22),
- [GTE_NCS] = 0x001fff0000000000ll | GDBITS4(0,1,21,22),
+ [GTE_NCS] = 0x001fff0000000000ll | GDBITS5(0,1,6,21,22),
[GTE_NCT] = 0x001fff0000000000ll | GDBITS7(0,1,2,3,4,5,6),
[GTE_SQR] = GDBITS3(9,10,11),
[GTE_DCPL] = GCBITS3(21,22,23) | GDBITS7(6,8,9,10,11,21,22),
static int ari64_init()
{
+ static u32 scratch_buf[8*8*2] __attribute__((aligned(64)));
extern void (*psxCP2[64])();
extern void psxNULL();
+ extern unsigned char *out;
size_t i;
new_dynarec_init();
if (psxCP2[i] != psxNULL)
gte_handlers[i] = psxCP2[i];
-#if !defined(DRC_DBG) && !defined(PCNT)
-#ifdef __arm__
+#if defined(__arm__) && !defined(DRC_DBG)
gte_handlers[0x06] = gteNCLIP_arm;
+#ifdef HAVE_ARMV5
gte_handlers_nf[0x01] = gteRTPS_nf_arm;
gte_handlers_nf[0x30] = gteRTPT_nf_arm;
#endif
#endif
psxH_ptr = psxH;
zeromem_ptr = zero_mem;
+ scratch_buf_ptr = scratch_buf;
+
+ SysPrintf("Mapped (RAM/scrp/ROM/LUTs/TC):\n");
+ SysPrintf("%08x/%08x/%08x/%08x/%08x\n",
+ psxM, psxH, psxR, mem_rtab, out);
return 0;
}
{
u32 start, end, main_ram;
- size *= 4; /* PCSX uses DMA units */
+ size *= 4; /* PCSX uses DMA units (words) */
evprintf("ari64_clear %08x %04x\n", addr, size);
invalidate_block(start);
}
+#ifdef ICACHE_EMULATION
+static void ari64_notify(int note, void *data) {
+ /*
+ Should be fixed when ARM dynarec has proper icache emulation.
+ switch (note)
+ {
+ case R3000ACPU_NOTIFY_CACHE_UNISOLATED:
+ break;
+ case R3000ACPU_NOTIFY_CACHE_ISOLATED:
+ Sent from psxDma3().
+ case R3000ACPU_NOTIFY_DMA3_EXE_LOAD:
+ default:
+ break;
+ }
+ */
+}
+#endif
+
static void ari64_shutdown()
{
new_dynarec_cleanup();
+ new_dyna_pcsx_mem_shutdown();
}
-extern void intExecute();
-extern void intExecuteT();
-extern void intExecuteBlock();
-extern void intExecuteBlockT();
-#ifndef DRC_DBG
-#define intExecuteT intExecute
-#define intExecuteBlockT intExecuteBlock
-#endif
-
R3000Acpu psxRec = {
ari64_init,
ari64_reset,
-#if defined(__arm__)
ari64_execute,
ari64_execute_until,
-#else
- intExecuteT,
- intExecuteBlockT,
-#endif
ari64_clear,
+#ifdef ICACHE_EMULATION
+ ari64_notify,
+#endif
ari64_shutdown
};
-// TODO: rm
-#ifndef DRC_DBG
-void do_insn_trace() {}
-void do_insn_cmp() {}
-#endif
+#else // if DRC_DISABLE
-#if defined(__x86_64__) || defined(__i386__)
unsigned int address;
int pending_exception, stop;
unsigned int next_interupt;
int new_dynarec_did_compile;
int cycle_multiplier;
+int new_dynarec_hacks;
void *psxH_ptr;
void *zeromem_ptr;
u8 zero_mem[0x1000];
+unsigned char *out;
+void *mem_rtab;
+void *scratch_buf_ptr;
void new_dynarec_init() {}
void new_dyna_start() {}
void new_dynarec_cleanup() {}
void new_dyna_pcsx_mem_init(void) {}
void new_dyna_pcsx_mem_reset(void) {}
void new_dyna_pcsx_mem_load_state(void) {}
+void new_dyna_pcsx_mem_shutdown(void) {}
+int new_dynarec_save_blocks(void *save, int size) { return 0; }
+void new_dynarec_load_blocks(const void *save, int size) {}
#endif
#ifdef DRC_DBG
return *(u32 *)(psxM + (a & 0x1ffffc));
}
+#if 0
void do_insn_trace(void)
{
static psxRegisters oldregs;
static u32 old_io_addr = (u32)-1;
static u32 old_io_data = 0xbad0c0de;
+ static u32 event_cycles_o[PSXINT_COUNT];
u32 *allregs_p = (void *)&psxRegs;
u32 *allregs_o = (void *)&oldregs;
u32 io_data;
int i;
u8 byte;
-//last_io_addr = 0x5e2c8;
+ //last_io_addr = 0x5e2c8;
if (f == NULL)
f = fopen("tracelog", "wb");
+ // log reg changes
oldregs.code = psxRegs.code; // don't care
for (i = 0; i < offsetof(psxRegisters, intCycle) / 4; i++) {
if (allregs_p[i] != allregs_o[i]) {
allregs_o[i] = allregs_p[i];
}
}
+ // log event changes
+ for (i = 0; i < PSXINT_COUNT; i++) {
+ if (event_cycles[i] != event_cycles_o[i]) {
+ byte = 0xfc;
+ fwrite(&byte, 1, 1, f);
+ fwrite(&i, 1, 1, f);
+ fwrite(&event_cycles[i], 1, 4, f);
+ event_cycles_o[i] = event_cycles[i];
+ }
+ }
+ // log last io
if (old_io_addr != last_io_addr) {
byte = 0xfd;
fwrite(&byte, 1, 1, f);
}
#endif
}
+#endif
static const char *regnames[offsetof(psxRegisters, intCycle) / 4] = {
"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
u32 *allregs_p = (void *)&psxRegs;
u32 *allregs_e = (void *)&rregs;
static u32 ppc, failcount;
- int i, ret, bad = 0;
+ int i, ret, bad = 0, which_event = -1;
+ u32 ev_cycles = 0;
u8 code;
if (f == NULL)
break;
if (code == 0xff)
break;
- if (code == 0xfd) {
- if ((ret = fread(&mem_addr, 1, 4, f)) <= 0)
- break;
+ switch (code) {
+ case 0xfc:
+ which_event = 0;
+ fread(&which_event, 1, 1, f);
+ fread(&ev_cycles, 1, 4, f);
continue;
- }
- if (code == 0xfe) {
- if ((ret = fread(&mem_val, 1, 4, f)) <= 0)
- break;
+ case 0xfd:
+ fread(&mem_addr, 1, 4, f);
+ continue;
+ case 0xfe:
+ fread(&mem_val, 1, 4, f);
continue;
}
- if ((ret = fread(&allregs_e[code], 1, 4, f)) <= 0)
- break;
+ fread(&allregs_e[code], 1, 4, f);
}
if (ret <= 0) {
psxRegs.cycle = rregs.cycle;
psxRegs.CP0.r[9] = rregs.CP0.r[9]; // Count
-//if (psxRegs.cycle == 166172) breakme();
+ //if (psxRegs.cycle == 166172) breakme();
if (memcmp(&psxRegs, &rregs, offsetof(psxRegisters, intCycle)) == 0 &&
mem_val == memcheck_read(mem_addr)
goto end;
}
+ if (which_event >= 0 && event_cycles[which_event] != ev_cycles) {
+ printf("bad ev_cycles #%d: %08x %08x\n", which_event, event_cycles[which_event], ev_cycles);
+ goto end;
+ }
+
if (psxRegs.pc == rregs.pc && bad < 6 && failcount < 32) {
static int last_mcycle;
if (last_mcycle != psxRegs.cycle >> 20) {