else
CFLAGS += -DDRC_DISABLE
endif
-OBJS += libpcsxcore/new_dynarec/emu_if.o
+OBJS += libpcsxcore/new_dynarec/emu_if.o libpcsxcore/new_dynarec/events.o
libpcsxcore/new_dynarec/new_dynarec.o: libpcsxcore/new_dynarec/pcsxmem_inline.c
ifdef DRC_DBG
libpcsxcore/new_dynarec/emu_if.o: CFLAGS += -D_FILE_OFFSET_BITS=64
GPU_writeData(gpu_data_def[i]);
}
+static void SetBootRegs(u32 pc, u32 gp, u32 sp)
+{
+ //printf("%s %08x %08x %08x\n", __func__, pc, gp, sp);
+ psxCpu->Notify(R3000ACPU_NOTIFY_BEFORE_SAVE, NULL);
+
+ psxRegs.pc = pc;
+ psxRegs.GPR.n.gp = gp;
+ psxRegs.GPR.n.sp = sp ? sp : 0x801fff00;
+
+ psxCpu->Notify(R3000ACPU_NOTIFY_AFTER_LOAD, NULL);
+}
+
int LoadCdrom() {
EXE_HEADER tmpHead;
struct iso_directory_record *dir;
if (!Config.HLE && !Config.SlowBoot) {
// skip BIOS logos
+ psxCpu->Notify(R3000ACPU_NOTIFY_BEFORE_SAVE, NULL);
psxRegs.pc = psxRegs.GPR.n.ra;
return 0;
}
memcpy(&tmpHead, buf + 12, sizeof(EXE_HEADER));
- psxRegs.pc = SWAP32(tmpHead.pc0);
- psxRegs.GPR.n.gp = SWAP32(tmpHead.gp0);
- psxRegs.GPR.n.sp = SWAP32(tmpHead.s_addr);
- if (psxRegs.GPR.n.sp == 0) psxRegs.GPR.n.sp = 0x801fff00;
+ SetBootRegs(SWAP32(tmpHead.pc0), SWAP32(tmpHead.gp0), SWAP32(tmpHead.s_addr));
tmpHead.t_size = SWAP32(tmpHead.t_size);
tmpHead.t_addr = SWAP32(tmpHead.t_addr);
fread_to_ram(mem, section_size, 1, tmpFile);
psxCpu->Clear(section_address, section_size / 4);
}
- psxRegs.pc = SWAP32(tmpHead.pc0);
- psxRegs.GPR.n.gp = SWAP32(tmpHead.gp0);
- psxRegs.GPR.n.sp = SWAP32(tmpHead.s_addr);
- if (psxRegs.GPR.n.sp == 0)
- psxRegs.GPR.n.sp = 0x801fff00;
+ SetBootRegs(SWAP32(tmpHead.pc0), SWAP32(tmpHead.gp0),
+ SWAP32(tmpHead.s_addr));
retval = 0;
break;
case CPE_EXE:
int SaveState(const char *file) {
void *f;
GPUFreeze_t *gpufP;
+ SPUFreezeHdr_t *spufH;
SPUFreeze_t *spufP;
int Size;
unsigned char *pMem;
free(gpufP);
// spu
- spufP = (SPUFreeze_t *) malloc(16);
- SPU_freeze(2, spufP, psxRegs.cycle);
- Size = spufP->Size; SaveFuncs.write(f, &Size, 4);
- free(spufP);
+ spufH = malloc(sizeof(*spufH));
+ SPU_freeze(2, (SPUFreeze_t *)spufH, psxRegs.cycle);
+ Size = spufH->Size; SaveFuncs.write(f, &Size, 4);
+ free(spufH);
spufP = (SPUFreeze_t *) malloc(Size);
SPU_freeze(1, spufP, psxRegs.cycle);
SaveFuncs.write(f, spufP, Size);
#include "emu_if.h"
#include "pcsxmem.h"
+#include "events.h"
#include "../psxhle.h"
#include "../psxinterpreter.h"
#include "../r3000a.h"
-#include "../cdrom.h"
-#include "../psxdma.h"
-#include "../mdec.h"
#include "../gte_arm.h"
#include "../gte_neon.h"
#define FLAGLESS
//#define evprintf printf
#define evprintf(...)
-char invalid_code[0x100000];
-u32 event_cycles[PSXINT_COUNT];
-
-static void schedule_timeslice(void)
-{
- u32 i, c = psxRegs.cycle;
- u32 irqs = psxRegs.interrupt;
- s32 min, dif;
-
- 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;
-}
-
-static void unusedInterrupt()
-{
-}
-
-typedef void (irq_func)();
-
-static irq_func * const irq_funcs[] = {
- [PSXINT_SIO] = sioInterrupt,
- [PSXINT_CDR] = cdrInterrupt,
- [PSXINT_CDREAD] = cdrPlayReadInterrupt,
- [PSXINT_GPUDMA] = gpuInterrupt,
- [PSXINT_MDECOUTDMA] = mdec1Interrupt,
- [PSXINT_SPUDMA] = spuInterrupt,
- [PSXINT_MDECINDMA] = mdec0Interrupt,
- [PSXINT_GPUOTCDMA] = gpuotcInterrupt,
- [PSXINT_CDRDMA] = cdrDmaInterrupt,
- [PSXINT_CDRLID] = cdrLidSeekInterrupt,
- [PSXINT_CDRPLAY_OLD] = unusedInterrupt,
- [PSXINT_SPU_UPDATE] = spuUpdate,
- [PSXINT_RCNT] = psxRcntUpdate,
-};
-
-/* local dupe of psxBranchTest, using event_cycles */
-static void irq_test(void)
-{
- u32 cycle = psxRegs.cycle;
- u32 irq, irq_bits;
-
- for (irq = 0, irq_bits = psxRegs.interrupt; irq_bits != 0; irq++, irq_bits >>= 1) {
- if (!(irq_bits & 1))
- continue;
- if ((s32)(cycle - event_cycles[irq]) >= 0) {
- // note: irq_funcs() also modify psxRegs.interrupt
- psxRegs.interrupt &= ~(1u << irq);
- irq_funcs[irq]();
- }
- }
-
- if ((psxHu32(0x1070) & psxHu32(0x1074)) && (psxRegs.CP0.n.Status & 0x401) == 0x401) {
- psxException(0x400, 0);
- pending_exception = 1;
- }
-}
-
-void gen_interupt()
-{
- evprintf(" +ge %08x, %u->%u (%d)\n", psxRegs.pc, psxRegs.cycle,
- next_interupt, next_interupt - psxRegs.cycle);
-
- irq_test();
- //psxBranchTest();
- //pending_exception = 1;
-
- schedule_timeslice();
-
- evprintf(" -ge %08x, %u->%u (%d)\n", psxRegs.pc, psxRegs.cycle,
- next_interupt, next_interupt - psxRegs.cycle);
-}
-
void pcsx_mtc0(u32 reg, u32 val)
{
evprintf("MTC0 %d #%x @%08x %u\n", reg, val, psxRegs.pc, psxRegs.cycle);
MTC0(&psxRegs, reg, val);
- gen_interupt();
+ gen_interupt(&psxRegs.CP0);
if (psxRegs.CP0.n.Cause & psxRegs.CP0.n.Status & 0x0300) // possible sw irq
pending_exception = 1;
}
#include "new_dynarec.h"
#include "../r3000a.h"
-extern char invalid_code[0x100000];
-
-/* weird stuff */
-#define EAX 0
-#define ECX 1
-
extern int dynarec_local[];
/* same as psxRegs.GPR.n.* */
--- /dev/null
+#include <stdio.h>
+#include "../r3000a.h"
+#include "../cdrom.h"
+#include "../psxdma.h"
+#include "../mdec.h"
+#include "events.h"
+
+extern int pending_exception;
+
+//#define evprintf printf
+#define evprintf(...)
+
+u32 event_cycles[PSXINT_COUNT];
+
+void schedule_timeslice(void)
+{
+ u32 i, c = psxRegs.cycle;
+ u32 irqs = psxRegs.interrupt;
+ s32 min, dif;
+
+ 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;
+}
+
+static void unusedInterrupt()
+{
+}
+
+typedef void (irq_func)();
+
+static irq_func * const irq_funcs[] = {
+ [PSXINT_SIO] = sioInterrupt,
+ [PSXINT_CDR] = cdrInterrupt,
+ [PSXINT_CDREAD] = cdrPlayReadInterrupt,
+ [PSXINT_GPUDMA] = gpuInterrupt,
+ [PSXINT_MDECOUTDMA] = mdec1Interrupt,
+ [PSXINT_SPUDMA] = spuInterrupt,
+ [PSXINT_MDECINDMA] = mdec0Interrupt,
+ [PSXINT_GPUOTCDMA] = gpuotcInterrupt,
+ [PSXINT_CDRDMA] = cdrDmaInterrupt,
+ [PSXINT_CDRLID] = cdrLidSeekInterrupt,
+ [PSXINT_CDRPLAY_OLD] = unusedInterrupt,
+ [PSXINT_SPU_UPDATE] = spuUpdate,
+ [PSXINT_RCNT] = psxRcntUpdate,
+};
+
+/* local dupe of psxBranchTest, using event_cycles */
+static void irq_test(psxCP0Regs *cp0)
+{
+ u32 cycle = psxRegs.cycle;
+ u32 irq, irq_bits;
+
+ for (irq = 0, irq_bits = psxRegs.interrupt; irq_bits != 0; irq++, irq_bits >>= 1) {
+ if (!(irq_bits & 1))
+ continue;
+ if ((s32)(cycle - event_cycles[irq]) >= 0) {
+ // note: irq_funcs() also modify psxRegs.interrupt
+ psxRegs.interrupt &= ~(1u << irq);
+ irq_funcs[irq]();
+ }
+ }
+
+ if ((psxHu32(0x1070) & psxHu32(0x1074)) && (cp0->n.Status & 0x401) == 0x401) {
+ psxException(0x400, 0, cp0);
+ pending_exception = 1;
+ }
+}
+
+void gen_interupt(psxCP0Regs *cp0)
+{
+ evprintf(" +ge %08x, %u->%u (%d)\n", psxRegs.pc, psxRegs.cycle,
+ next_interupt, next_interupt - psxRegs.cycle);
+
+ irq_test(cp0);
+ //pending_exception = 1;
+
+ schedule_timeslice();
+
+ evprintf(" -ge %08x, %u->%u (%d)\n", psxRegs.pc, psxRegs.cycle,
+ next_interupt, next_interupt - psxRegs.cycle);
+}
+
+
--- /dev/null
+union psxCP0Regs_;
+void schedule_timeslice(void);
+void gen_interupt(union psxCP0Regs_ *cp0);
@@ str r10, [fp, #LO_reg_cop0+36] /* Count - not on PSX */
mov r10, lr
+ add r0, fp, #(LO_psxRegs + 34*4) /* CP0 */
bl gen_interupt
mov lr, r10
ldr r10, [fp, #LO_cycle]
ldr r3, [fp, #LO_last_count]
str r2, [fp, #LO_pcaddr]
add r10, r3, r10
- str r10, [fp, #LO_cycle] /* PCSX cycles */
+ str r10, [fp, #LO_cycle] /* PCSX cycles */
+ add r2, fp, #(LO_psxRegs + 34*4) /* CP0 */
bl psxException
/* note: psxException might do recursive recompiler call from it's HLE code,
# str rCC, [rFP, #LO_reg_cop0+36] /* Count */
mov x21, lr
1:
+ add x0, rFP, #(LO_psxRegs + 34*4) /* CP0 */
bl gen_interupt
mov lr, x21
ldr rCC, [rFP, #LO_cycle]
ldr w3, [rFP, #LO_last_count]
str w2, [rFP, #LO_pcaddr]
add rCC, w3, rCC
- str rCC, [rFP, #LO_cycle] /* PCSX cycles */
+ str rCC, [rFP, #LO_cycle] /* PCSX cycles */
+ add x2, rFP, #(LO_psxRegs + 34*4) /* CP0 */
bl psxException
/* note: psxException might do recursive recompiler call from it's HLE code,
} dops[MAXBLOCK];
static u_char *out;
+ static char invalid_code[0x100000];
static struct ht_entry hash_table[65536];
static struct block_info *blocks[PAGE_COUNT];
static struct jump_info *jumps[PAGE_COUNT];
//else {printf("fp exception in delay slot\n");}
wb_dirtys(i_regs->regmap_entry,i_regs->wasdirty);
if(regs[i].regmap_entry[HOST_CCREG]!=CCREG) emit_loadreg(CCREG,HOST_CCREG);
- emit_movimm(start+(i-ds)*4,EAX); // Get PC
+ emit_movimm(start+(i-ds)*4,0); // Get PC
emit_addimm(HOST_CCREG,ccadj[i],HOST_CCREG); // CHECK: is this right? There should probably be an extra cycle...
emit_far_jump(ds?fp_exception_ds:fp_exception);
}
if(stubs[n].c!=-1)
{
// Save PC as return address
- emit_movimm(stubs[n].c,EAX);
- emit_writeword(EAX,&pcaddr);
+ emit_movimm(stubs[n].c,0);
+ emit_writeword(0,&pcaddr);
}
else
{
typedef long (CALLBACK* SPUconfigure)(void);\r
typedef long (CALLBACK* SPUtest)(void);\r
typedef void (CALLBACK* SPUabout)(void);\r
+typedef struct {\r
+ unsigned char PluginName[8];\r
+ uint32_t PluginVersion;\r
+ uint32_t Size;\r
+} SPUFreezeHdr_t;\r
typedef struct {\r
unsigned char PluginName[8];\r
uint32_t PluginVersion;\r
*********************************************************/
OP(psxBREAK) {
regs_->pc -= 4;
- psxException(0x24, branch);
+ psxException(0x24, branch, ®s_->CP0);
}
OP(psxSYSCALL) {
regs_->pc -= 4;
- psxException(0x20, branch);
+ psxException(0x20, branch, ®s_->CP0);
}
static inline void psxTestSWInts(psxRegisters *regs_) {
if (regs_->CP0.n.Cause & regs_->CP0.n.Status & 0x0300 &&
regs_->CP0.n.Status & 0x1) {
regs_->CP0.n.Cause &= ~0x7c;
- psxException(regs_->CP0.n.Cause, branch);
+ psxException(regs_->CP0.n.Cause, branch, ®s_->CP0);
}
}
psxMemShutdown();
}
-void psxException(u32 code, u32 bd) {
+// cp0 is passed separately for lightrec to be less messy
+void psxException(u32 code, u32 bd, psxCP0Regs *cp0) {
psxRegs.code = PSXMu32(psxRegs.pc);
if (!Config.HLE && ((((psxRegs.code) >> 24) & 0xfe) == 0x4a)) {
// BIOS does not allow to return to GTE instructions
// (just skips it, supposedly because it's scheduled already)
// so we execute it here
- psxCP2[psxRegs.code & 0x3f](&psxRegs.CP2);
+ psxCP2Regs *cp2 = (void *)(cp0 + 1);
+ psxCP2[psxRegs.code & 0x3f](cp2);
}
// Set the Cause
- psxRegs.CP0.n.Cause = (psxRegs.CP0.n.Cause & 0x300) | code;
+ cp0->n.Cause = (cp0->n.Cause & 0x300) | code;
// Set the EPC & PC
if (bd) {
#ifdef PSXCPU_LOG
PSXCPU_LOG("bd set!!!\n");
#endif
- psxRegs.CP0.n.Cause |= 0x80000000;
- psxRegs.CP0.n.EPC = (psxRegs.pc - 4);
+ cp0->n.Cause |= 0x80000000;
+ cp0->n.EPC = (psxRegs.pc - 4);
} else
- psxRegs.CP0.n.EPC = (psxRegs.pc);
+ cp0->n.EPC = (psxRegs.pc);
- if (psxRegs.CP0.n.Status & 0x400000)
+ if (cp0->n.Status & 0x400000)
psxRegs.pc = 0xbfc00180;
else
psxRegs.pc = 0x80000080;
// Set the Status
- psxRegs.CP0.n.Status = (psxRegs.CP0.n.Status &~0x3f) |
- ((psxRegs.CP0.n.Status & 0xf) << 2);
+ cp0->n.Status = (cp0->n.Status & ~0x3f) | ((cp0->n.Status & 0x0f) << 2);
if (Config.HLE) psxBiosException();
}
PSXCPU_LOG("Interrupt: %x %x\n", psxHu32(0x1070), psxHu32(0x1074));
#endif
// SysPrintf("Interrupt (%x): %x %x\n", psxRegs.cycle, psxHu32(0x1070), psxHu32(0x1074));
- psxException(0x400, 0);
+ psxException(0x400, 0, &psxRegs.CP0);
}
}
}
PAIR p[34];
} psxGPRRegs;
-typedef union {
+typedef union psxCP0Regs_ {
struct {
u32 Index, Random, EntryLo0, EntryLo1,
Context, PageMask, Wired, Reserved0,
} psxCP2Regs;
typedef struct {
+ // note: some cores like lightrec don't keep their data here,
+ // so use R3000ACPU_NOTIFY_BEFORE_SAVE to sync
psxGPRRegs GPR; /* General Purpose Registers */
psxCP0Regs CP0; /* Coprocessor0 Registers */
union {
};
psxCP2Regs CP2;
};
- u32 pc; /* Program counter */
- u32 code; /* The instruction */
+ u32 pc; /* Program counter */
+ u32 code; /* The instruction */
u32 cycle;
u32 interrupt;
struct { u32 sCycle, cycle; } intCycle[32];
int psxInit();
void psxReset();
void psxShutdown();
-void psxException(u32 code, u32 bd);
+void psxException(u32 code, u32 bd, psxCP0Regs *cp0);
void psxBranchTest();
void psxExecuteBios();
void psxJumpTest();