void pl_frame_limit(void)
{
/* called once per frame, make psxCpu->Execute() above return */
- stop++;
+ psxRegs.stop++;
}
void pl_timing_prepare(int is_pal)
if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE_UPDATE, &updated) && updated)
update_variables(true);
- stop = 0;
- psxCpu->Execute();
+ psxRegs.stop = 0;
+ psxCpu->Execute(&psxRegs);
if (pl_rearmed_cbs.fskip_dirty == 1) {
if (frameskip_counter < frameskip_interval)
void emu_core_ask_exit(void)
{
- stop++;
+ psxRegs.stop++;
g_emu_want_quit = 1;
}
while (!g_emu_want_quit)
{
- stop = 0;
+ psxRegs.stop = 0;
emu_action = SACTION_NONE;
- psxCpu->Execute();
+ psxCpu->Execute(&psxRegs);
if (emu_action != SACTION_NONE)
do_emu_action();
}
#define SACTION_GUN_MASK (0x0f << SACTION_GUN_TRIGGER)
-static inline void emu_set_action(enum sched_action action_)
-{
- extern enum sched_action emu_action, emu_action_old;
- extern int stop;
-
- if (action_ == SACTION_NONE)
- emu_action_old = 0;
- else if (action_ != emu_action_old)
- stop++;
- emu_action = action_;
-}
-
#endif /* __FRONTEND_MAIN_H__ */
}
}
+static void emu_set_action(enum sched_action action_)
+{
+ extern enum sched_action emu_action, emu_action_old;
+
+ if (action_ == SACTION_NONE)
+ emu_action_old = 0;
+ else if (action_ != emu_action_old)
+ psxRegs.stop++;
+ emu_action = action_;
+}
+
static void update_input(void)
{
int actions[IN_BINDTYPE_COUNT] = { 0, };
{
sleep(sleep_time);
- if (stop) {
+ if (psxRegs.stop) {
seen_dead = 0;
sleep_time = 5;
continue;
static struct lightrec_state *lightrec_state;
static bool use_lightrec_interpreter;
-static bool use_pcsx_interpreter;
static bool block_stepping;
+//static bool use_pcsx_interpreter;
+#define use_pcsx_interpreter 0
extern u32 lightrec_hacks;
static void lightrec_tansition_from_pcsx(struct lightrec_state *state)
{
- s32 cycles_left = next_interupt - psxRegs.cycle;
+ s32 cycles_left = psxRegs.next_interupt - psxRegs.cycle;
if (block_stepping || cycles_left <= 0 || has_interrupt())
lightrec_set_exit_flags(state, LIGHTREC_EXIT_CHECK_INTERRUPT);
regs = lightrec_get_registers(lightrec_state);
gen_interupt((psxCP0Regs *)regs->cp0);
- if (!block_only && stop)
+ if (!block_only && psxRegs.stop)
return;
- cycles_pcsx = next_interupt - psxRegs.cycle;
+ cycles_pcsx = psxRegs.next_interupt - psxRegs.cycle;
assert((s32)cycles_pcsx > 0);
// step during early boot so that 0x80030000 fastboot hack works
cycles_pcsx = 0;
if (use_pcsx_interpreter) {
- intExecuteBlock(0);
+ psxInt.ExecuteBlock(&psxRegs, 0);
} else {
u32 cycles_lightrec = cycles_pcsx * 1024;
if (unlikely(use_lightrec_interpreter)) {
}
}
-static void lightrec_plugin_execute(void)
+static void lightrec_plugin_execute(psxRegisters *regs)
{
- while (!stop)
+ while (!regs->stop)
lightrec_plugin_execute_internal(false);
}
-static void lightrec_plugin_execute_block(enum blockExecCaller caller)
+static void lightrec_plugin_execute_block(psxRegisters *regs,
+ enum blockExecCaller caller)
{
lightrec_plugin_execute_internal(true);
}
}
cycles_per_op_old = cycles_per_op;
lightrec_set_cycles_per_opcode(lightrec_state, cycles_per_op);
+
+ intApplyConfig();
}
static void lightrec_plugin_shutdown(void)
SaveFuncs.read(f, psxH, 0x00010000);
SaveFuncs.read(f, &psxRegs, offsetof(psxRegisters, gteBusyCycle));
psxRegs.gteBusyCycle = psxRegs.cycle;
+ psxRegs.branching = 0;
psxRegs.biosBranchCheck = ~0;
+ psxRegs.cpuInRecursion = 0;
psxRegs.gpuIdleAfter = psxRegs.cycle - 1;
HW_GPU_STATUS &= SWAP32(~PSXGPU_nBUSY);
if (misc->magic == MISC_MAGIC) {
//#define evprintf printf
#define evprintf(...)
-#if !defined(DRC_DISABLE) && !defined(LIGHTREC)
-// reduce global loads/literal pools (maybe)
-#include "linkage_offsets.h"
-#define dynarec_local_var4(x) dynarec_local[(x) / sizeof(dynarec_local[0])]
-#define stop dynarec_local_var4(LO_stop)
-#define psxRegs (*(psxRegisters *)((char *)dynarec_local + LO_psxRegs))
-#define next_interupt dynarec_local_var4(LO_next_interupt)
-#endif
-
static void ari64_thread_sync(void);
-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(&psxRegs.CP0);
-}
-
-void pcsx_mtc0_ds(u32 reg, u32 val)
-{
- evprintf("MTC0 %d #%x @%08x %u\n", reg, val, psxRegs.pc, psxRegs.cycle);
- MTC0(&psxRegs, reg, val);
-}
-
void ndrc_freeze(void *f, int mode)
{
const char header_save[8] = "ariblks";
}
#if !defined(DRC_DISABLE) && !defined(LIGHTREC)
+#include "linkage_offsets.h"
static void ari64_thread_init(void);
static int ari64_thread_check_range(unsigned int start, unsigned int end);
+void pcsx_mtc0(psxRegisters *regs, u32 reg, u32 val)
+{
+ evprintf("MTC0 %d #%x @%08x %u\n", reg, val, regs->pc, regs->cycle);
+ MTC0(regs, reg, val);
+ gen_interupt(®s->CP0);
+}
+
+void pcsx_mtc0_ds(psxRegisters *regs, u32 reg, u32 val)
+{
+ evprintf("MTC0 %d #%x @%08x %u\n", reg, val, regs->pc, regs->cycle);
+ MTC0(regs, reg, val);
+}
+
/* GTE stuff */
void *gte_handlers[64];
// execute until predefined leave points
// (HLE softcall exit and BIOS fastboot end)
-static void ari64_execute_until()
+static void ari64_execute_until(psxRegisters *regs)
{
- evprintf("ari64_execute %08x, %u->%u (%d)\n", psxRegs.pc,
- psxRegs.cycle, next_interupt, next_interupt - psxRegs.cycle);
+ void *drc_local = (char *)regs - LO_psxRegs;
+
+ assert(drc_local == dynarec_local);
+ evprintf("ari64_execute %08x, %u->%u (%d)\n", regs->pc,
+ regs->cycle, regs->next_interupt, regs->next_interupt - regs->cycle);
- new_dyna_start(dynarec_local);
+ new_dyna_start(drc_local);
- evprintf("ari64_execute end %08x, %u->%u (%d)\n", psxRegs.pc,
- psxRegs.cycle, next_interupt, next_interupt - psxRegs.cycle);
+ evprintf("ari64_execute end %08x, %u->%u (%d)\n", regs->pc,
+ regs->cycle, regs->next_interupt, regs->next_interupt - regs->cycle);
}
-static void ari64_execute()
+static void ari64_execute(struct psxRegisters *regs)
{
- while (!stop) {
- schedule_timeslice();
- ari64_execute_until();
- evprintf("drc left @%08x\n", psxRegs.pc);
+ while (!regs->stop) {
+ schedule_timeslice(regs);
+ ari64_execute_until(regs);
+ evprintf("drc left @%08x\n", regs->pc);
}
}
-static void ari64_execute_block(enum blockExecCaller caller)
+static void ari64_execute_block(struct psxRegisters *regs, enum blockExecCaller caller)
{
if (caller == EXEC_CALLER_BOOT)
- stop++;
+ regs->stop++;
- next_interupt = psxRegs.cycle + 1;
- ari64_execute_until();
+ regs->next_interupt = regs->cycle + 1;
+ ari64_execute_until(regs);
if (caller == EXEC_CALLER_BOOT)
- stop--;
+ regs->stop--;
}
static void ari64_clear(u32 addr, u32 size)
#endif
}
-static noinline void ari64_execute_threaded_slow(enum blockExecCaller block_caller)
+static noinline void ari64_execute_threaded_slow(struct psxRegisters *regs,
+ enum blockExecCaller block_caller)
{
if (!ndrc_g.thread.busy) {
- memcpy(ndrc_smrv_regs, psxRegs.GPR.r, sizeof(ndrc_smrv_regs));
+ memcpy(ndrc_smrv_regs, regs->GPR.r, sizeof(ndrc_smrv_regs));
slock_lock(ndrc_g.thread.lock);
- ndrc_g.thread.addr = psxRegs.pc;
+ ndrc_g.thread.addr = regs->pc;
ndrc_g.thread.busy = 1;
slock_unlock(ndrc_g.thread.lock);
scond_signal(ndrc_g.thread.cond);
psxInt.Notify(R3000ACPU_NOTIFY_AFTER_LOAD, NULL);
do
{
- psxInt.ExecuteBlock(block_caller);
+ psxInt.ExecuteBlock(regs, block_caller);
}
- while (!stop && ndrc_g.thread.busy && block_caller == EXEC_CALLER_OTHER);
+ while (!regs->stop && ndrc_g.thread.busy && block_caller == EXEC_CALLER_OTHER);
psxInt.Notify(R3000ACPU_NOTIFY_BEFORE_SAVE, NULL);
//ari64_notify(R3000ACPU_NOTIFY_AFTER_LOAD, NULL);
ari64_on_ext_change(0, 1);
}
-static void ari64_execute_threaded_once(enum blockExecCaller block_caller)
+static void ari64_execute_threaded_once(struct psxRegisters *regs,
+ enum blockExecCaller block_caller)
{
- psxRegisters *regs = (void *)((char *)dynarec_local + LO_psxRegs);
+ void *drc_local = (char *)regs - LO_psxRegs;
void *target;
if (likely(!ndrc_g.thread.busy)) {
target = ndrc_get_addr_ht_param(regs->pc, ndrc_cm_no_compile);
if (target) {
clear_local_cache();
- new_dyna_start_at(dynarec_local, target);
+ new_dyna_start_at(drc_local, target);
return;
}
}
- ari64_execute_threaded_slow(block_caller);
+ ari64_execute_threaded_slow(regs, block_caller);
}
-static void ari64_execute_threaded()
+static void ari64_execute_threaded(struct psxRegisters *regs)
{
- schedule_timeslice();
- while (!stop)
+ schedule_timeslice(regs);
+ while (!regs->stop)
{
- ari64_execute_threaded_once(EXEC_CALLER_OTHER);
+ ari64_execute_threaded_once(regs, EXEC_CALLER_OTHER);
- if ((s32)(psxRegs.cycle - next_interupt) >= 0)
- schedule_timeslice();
+ if ((s32)(regs->cycle - regs->next_interupt) >= 0)
+ schedule_timeslice(regs);
}
}
-static void ari64_execute_threaded_block(enum blockExecCaller caller)
+static void ari64_execute_threaded_block(struct psxRegisters *regs,
+ enum blockExecCaller caller)
{
if (caller == EXEC_CALLER_BOOT)
- stop++;
+ regs->stop++;
- next_interupt = psxRegs.cycle + 1;
- ari64_execute_threaded_once(caller);
+ regs->next_interupt = regs->cycle + 1;
+ ari64_execute_threaded_once(regs, caller);
if (caller == EXEC_CALLER_BOOT)
- stop--;
+ regs->stop--;
}
static void ari64_thread_sync(void)
#else // if DRC_DISABLE
struct ndrc_globals ndrc_g; // dummy
-unsigned int address;
-int stop;
-u32 next_interupt;
void *psxH_ptr;
void *zeromem_ptr;
u32 zero_mem[0x1000/4];
for (i = 0; i < 8; i++)
printf("r%d=%08x r%2d=%08x r%2d=%08x r%2d=%08x\n", i, allregs_p[i],
i+8, allregs_p[i+8], i+16, allregs_p[i+16], i+24, allregs_p[i+24]);
- printf("PC: %08x/%08x, cycle %u, next %u\n", psxRegs.pc, ppc, psxRegs.cycle, next_interupt);
+ printf("PC: %08x/%08x, cycle %u, next %u\n", psxRegs.pc, ppc,
+ psxRegs.cycle, psxRegs.next_interupt);
//dump_mem("/tmp/psxram.dump", psxM, 0x200000);
//dump_mem("/mnt/ntz/dev/pnd/tmp/psxregs.dump", psxH, 0x10000);
exit(1);
extern u32 next_interupt;
/* called by drc */
-void pcsx_mtc0(u32 reg, u32 val);
-void pcsx_mtc0_ds(u32 reg, u32 val);
+struct psxRegisters;
+void pcsx_mtc0(struct psxRegisters *regs, u32 reg, u32 val);
+void pcsx_mtc0_ds(struct psxRegisters *regs, u32 reg, u32 val);
/* misc */
extern void SysPrintf(const char *fmt, ...);
#define DRC_VAR(name, size_) \
DRC_VAR_(name, ESYM(name), size_)
-DRC_VAR(next_interupt, 4)
+@DRC_VAR(next_interupt, 4)
DRC_VAR(cycle_count, 4)
DRC_VAR(last_count, 4)
-@DRC_VAR(unused1, 4)
-DRC_VAR(stop, 4)
-DRC_VAR(branch_target, 4)
+@DRC_VAR(stop, 4)
DRC_VAR(address, 4)
DRC_VAR(hack_addr, 4)
DRC_VAR(psxRegs, LO_psxRegs_end - LO_psxRegs)
/* psxRegs */
-@DRC_VAR(reg, 128)
@DRC_VAR(lo, 4)
@DRC_VAR(hi, 4)
-DRC_VAR(reg_cop0, 128)
DRC_VAR(reg_cop2d, 128)
DRC_VAR(reg_cop2c, 128)
-DRC_VAR(pcaddr, 4)
@DRC_VAR(code, 4)
@DRC_VAR(cycle, 4)
@DRC_VAR(interrupt, 4)
#define DRC_VAR(name, size_) \
DRC_VAR_(name, ESYM(name), size_)
-DRC_VAR(next_interupt, 4)
+#DRC_VAR(next_interupt, 4)
DRC_VAR(cycle_count, 4)
DRC_VAR(last_count, 4)
-@DRC_VAR(unused1, 4)
-DRC_VAR(stop, 4)
-DRC_VAR(branch_target, 4)
+#DRC_VAR(stop, 4)
DRC_VAR(address, 4)
DRC_VAR(hack_addr, 4)
DRC_VAR(psxRegs, LO_psxRegs_end - LO_psxRegs)
/* psxRegs */
-#DRC_VAR(reg, 128)
#DRC_VAR(lo, 4)
#DRC_VAR(hi, 4)
-DRC_VAR(reg_cop0, 128)
DRC_VAR(reg_cop2d, 128)
DRC_VAR(reg_cop2c, 128)
-DRC_VAR(pcaddr, 4)
#DRC_VAR(code, 4)
#DRC_VAR(cycle, 4)
#DRC_VAR(interrupt, 4)
#define PTRSZ __SIZEOF_POINTER__
-#define LO_next_interupt 64
-#define LO_cycle_count (LO_next_interupt + 4)
+#define LO_unused0 64
+#define LO_unused1 (LO_unused0 + 4)
+#define LO_unused2 (LO_unused1 + 4)
+#define LO_unused3 (LO_unused2 + 4)
+#define LO_cycle_count (LO_unused3 + 4)
#define LO_last_count (LO_cycle_count + 4)
-#define LO_unused1 (LO_last_count + 4)
-#define LO_stop (LO_unused1 + 4)
-#define LO_branch_target (LO_stop + 4)
-#define LO_address (LO_branch_target + 4)
+#define LO_address (LO_last_count + 4)
#define LO_hack_addr (LO_address + 4)
#define LO_psxRegs (LO_hack_addr + 4)
-#define LO_reg (LO_psxRegs)
-#define LO_lo (LO_reg + 128)
+#define LO_lo (LO_psxRegs + 128)
#define LO_hi (LO_lo + 4)
#define LO_reg_cop0 (LO_hi + 4)
#define LO_reg_cop2d (LO_reg_cop0 + 128)
#define LO_cycle (LO_code + 4)
#define LO_interrupt (LO_cycle + 4)
#define LO_intCycle (LO_interrupt + 4)
-#define LO_gteBusyCycle (LO_intCycle + 256)
+#define LO_next_interupt (LO_intCycle + 4*2*31)
+#define LO_unused4 (LO_next_interupt + 4)
+#define LO_gteBusyCycle (LO_unused4 + 4)
#define LO_muldivBusyCycle (LO_gteBusyCycle + 4)
#define LO_psxRegs_subCycle (LO_muldivBusyCycle + 4)
#define LO_psxRegs_biuReg (LO_psxRegs_subCycle + 4*2)
-#define LO_psxRegs_reserved (LO_psxRegs_biuReg + 4)
-#define LO_psxRegs_end (LO_psxRegs_reserved + 4*7)
+#define LO_stop (LO_psxRegs_biuReg + 4)
+#define LO_psxRegs_end (LO_stop + 4*7)
#define LO_rcnts (LO_psxRegs_end)
#define LO_rcnts_end (LO_rcnts + 7*4*4)
#define LO_inv_code_start (LO_rcnts_end)
// from linkage_*
extern int cycle_count; // ... until end of the timeslice, counts -N -> 0 (CCREG)
extern int last_count; // last absolute target, often = next_interupt
-extern int pcaddr;
-extern int branch_target;
-/* same as psxRegs.CP0.n.* */
-extern int reg_cop0[];
extern int reg_cop2d[], reg_cop2c[];
extern uintptr_t ram_offset;
load_all_consts(regs[i].regmap_entry,regs[i].wasdirty,i);
wb_dirtys(regs[i].regmap_entry,regs[i].wasdirty);
emit_movimm(start+i*4+4,0);
- emit_writeword(0,&pcaddr);
+ emit_writeword(0,&psxRegs.pc);
emit_addimm(HOST_CCREG,2,HOST_CCREG);
emit_far_call(ndrc_get_addr_ht);
emit_jmpreg(0);
signed char t=get_reg_w(i_regs->regmap, dops[i].rt1);
u_int copr=(source[i]>>11)&0x1f;
if(t>=0&&dops[i].rt1!=0) {
- emit_readword(®_cop0[copr],t);
+ emit_readword(&psxRegs.CP0.r[copr],t);
}
}
else if(dops[i].opcode2==4) // MTC0
emit_writeword(HOST_CCREG,&last_count);
emit_movimm(0,HOST_CCREG);
emit_storereg(CCREG,HOST_CCREG);
- emit_loadreg(dops[i].rs1,1);
- emit_movimm(copr,0);
+ emit_loadreg(dops[i].rs1, 2);
+ emit_movimm(copr, 1);
+ emit_addimm_ptr(FP, (u_char *)&psxRegs - (u_char *)&dynarec_local, 0);
emit_far_call(pcsx_mtc0_ds);
emit_loadreg(dops[i].rs1,s);
return;
}
emit_movimm(start+i*4+4,HOST_TEMPREG);
- emit_writeword(HOST_TEMPREG,&pcaddr);
+ emit_writeword(HOST_TEMPREG,&psxRegs.pc);
}
- if( s != 1)
- emit_mov(s, 1);
- emit_movimm(copr, 0);
+ if (s != 2)
+ emit_mov(s, 2);
+ emit_movimm(copr, 1);
+ emit_addimm_ptr(FP, (u_char *)&psxRegs - (u_char *)&dynarec_local, 0);
emit_far_call(pcsx_mtc0);
if (copr == 12 || copr == 13) {
emit_readword(&psxRegs.cycle,HOST_CCREG);
emit_sub(HOST_CCREG,HOST_TEMPREG,HOST_CCREG);
//emit_writeword(HOST_TEMPREG,&last_count);
assert(!is_delayslot);
- emit_readword(&pcaddr, 0);
+ emit_readword(&psxRegs.pc, 0);
emit_movimm(start+i*4+4, HOST_TEMPREG);
emit_cmp(HOST_TEMPREG, 0);
void *jaddr = out;
emit_storereg(dops[i].rt1, 0);
}
emit_movimm(start+i*4,0);
- emit_writeword(0,&pcaddr);
+ emit_writeword(0,&psxRegs.pc);
int cc = get_reg(regs[i].regmap_entry, CCREG);
if (cc < 0)
emit_loadreg(CCREG, cc = 0);
}
else {SysPrintf("Unknown branch type in do_ccstub\n");abort();}
}
- emit_writeword(r_pc, &pcaddr);
+ emit_writeword(r_pc, &psxRegs.pc);
// Update cycle count
assert(branch_regs[i].regmap[HOST_CCREG]==CCREG||branch_regs[i].regmap[HOST_CCREG]==-1);
if(stubs[n].a) emit_addimm(HOST_CCREG,(int)stubs[n].a,HOST_CCREG);
load_needed_regs(branch_regs[i].regmap,regs[(cinfo[i].ba-start)>>2].regmap_entry);
else if(dops[i].itype==RJUMP) {
if(get_reg(branch_regs[i].regmap,RTEMP)>=0)
- emit_readword(&pcaddr,get_reg(branch_regs[i].regmap,RTEMP));
+ emit_readword(&psxRegs.pc,get_reg(branch_regs[i].regmap,RTEMP));
else
emit_loadreg(dops[i].rs1,get_reg(branch_regs[i].regmap,dops[i].rs1));
}
void *beginning = start_block();
emit_movimm(start,0);
- emit_writeword(0,&pcaddr);
+ emit_writeword(0,&psxRegs.pc);
emit_far_jump(new_dyna_leave);
literal_pool(0);
end_block(beginning);
// for BiosBootBypass() to work
// io address var abused as a "already been here" flag
emit_readword(&address, 1);
- emit_writeword(0, &pcaddr);
+ emit_writeword(0, &psxRegs.pc);
emit_writeword(0, &address);
emit_cmp(0, 1);
}
else {
emit_readword(&psxRegs.cpuInRecursion, 1);
- emit_writeword(0, &pcaddr);
+ emit_writeword(0, &psxRegs.pc);
emit_test(1, 1);
}
#ifdef __aarch64__
#define MAXBLOCK 2048 // in mips instructions
-extern int stop;
-
#define NDHACK_NO_SMC_CHECK (1<<0)
#define NDHACK_GTE_UNNEEDED (1<<1)
#define NDHACK_GTE_NO_FLAGS (1<<2)
psxCpu->Notify(R3000ACPU_NOTIFY_AFTER_LOAD, PTR_1);
while (pc0 != 0x80001000 && ++lim < 0x100000)
- psxCpu->ExecuteBlock(EXEC_CALLER_HLE);
+ psxCpu->ExecuteBlock(&psxRegs, EXEC_CALLER_HLE);
psxCpu->Notify(R3000ACPU_NOTIFY_BEFORE_SAVE, PTR_1);
psxRegs.cpuInRecursion--;
psxCpu->Notify(R3000ACPU_NOTIFY_AFTER_LOAD, PTR_1);
while (!returned_from_exception() && pc0 != 0x80001000 && ++lim < 0x100000)
- psxCpu->ExecuteBlock(EXEC_CALLER_HLE);
+ psxCpu->ExecuteBlock(&psxRegs, EXEC_CALLER_HLE);
psxCpu->Notify(R3000ACPU_NOTIFY_BEFORE_SAVE, PTR_1);
psxRegs.cpuInRecursion--;
// retrigger this hlecall after the next emulation event
pc0 -= 4;
- if ((s32)(next_interupt - psxRegs.cycle) > 0)
- psxRegs.cycle = next_interupt;
+ if ((s32)(psxRegs.next_interupt - psxRegs.cycle) > 0)
+ psxRegs.cycle = psxRegs.next_interupt;
psxBranchTest();
}
if (cycles_passed < 10 || cycles_passed > 50 || v0 != v0_expect)
return;
- waste_cycles = schedule_timeslice() - psxRegs.cycle;
+ waste_cycles = schedule_timeslice(&psxRegs) - psxRegs.cycle;
loops = waste_cycles / cycles_passed;
if (loops > v0)
loops = v0;
+#include <stddef.h>
#include <stdio.h>
#include "r3000a.h"
#include "cdrom.h"
u32 event_cycles[PSXINT_COUNT];
-u32 schedule_timeslice(void)
+static psxRegisters *cp0TOpsxRegs(psxCP0Regs *cp0)
{
- u32 i, c = psxRegs.cycle;
- u32 irqs = psxRegs.interrupt;
+#ifndef LIGHTREC
+ return (void *)((char *)cp0 - offsetof(psxRegisters, CP0));
+#else
+ // lightrec has it's own cp0
+ return &psxRegs;
+#endif
+}
+
+u32 schedule_timeslice(psxRegisters *regs)
+{
+ u32 i, c = regs->cycle;
+ u32 irqs = regs->interrupt;
s32 min, dif;
min = PSXCLK;
if (0 < dif && dif < min)
min = dif;
}
- next_interupt = c + min;
- return next_interupt;
+ regs->next_interupt = c + min;
+ return regs->next_interupt;
}
static void irqNoOp() {
/* local dupe of psxBranchTest, using event_cycles */
void irq_test(psxCP0Regs *cp0)
{
- u32 cycle = psxRegs.cycle;
+ psxRegisters *regs = cp0TOpsxRegs(cp0);
+ u32 cycle = regs->cycle;
u32 irq, irq_bits;
- for (irq = 0, irq_bits = psxRegs.interrupt; irq_bits != 0; irq++, irq_bits >>= 1) {
+ for (irq = 0, irq_bits = regs->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);
+ // note: irq_funcs() also modify regs->interrupt
+ regs->interrupt &= ~(1u << irq);
irq_funcs[irq]();
}
}
void gen_interupt(psxCP0Regs *cp0)
{
- evprintf(" +ge %08x, %u->%u (%d)\n", psxRegs.pc, psxRegs.cycle,
- next_interupt, next_interupt - psxRegs.cycle);
+ psxRegisters *regs = cp0TOpsxRegs(cp0);
- irq_test(cp0);
+ evprintf(" +ge %08x, %u->%u (%d)\n", regs->pc, regs->cycle,
+ regs->next_interupt, regs->next_interupt - regs->cycle);
- schedule_timeslice();
+ irq_test(cp0);
+ schedule_timeslice(regs);
- evprintf(" -ge %08x, %u->%u (%d)\n", psxRegs.pc, psxRegs.cycle,
- next_interupt, next_interupt - psxRegs.cycle);
+ evprintf(" -ge %08x, %u->%u (%d)\n", regs->pc, regs->cycle,
+ regs->next_interupt, regs->next_interupt - regs->cycle);
}
void events_restore(void)
};
extern u32 event_cycles[PSXINT_COUNT];
-extern u32 next_interupt;
-extern int stop;
#define set_event_raw_abs(e, abs) { \
u32 abs_ = abs; \
- s32 di_ = next_interupt - abs_; \
+ s32 di_ = psxRegs.next_interupt - abs_; \
event_cycles[e] = abs_; \
if (di_ > 0) { \
- /*printf("%u: next_interupt %u -> %u\n", psxRegs.cycle, next_interupt, abs_);*/ \
- next_interupt = abs_; \
+ /*printf("%u: next_interupt %u -> %u\n", psxRegs.cycle, psxRegs.next_interupt, abs_);*/ \
+ psxRegs.next_interupt = abs_; \
} \
}
} while (0)
union psxCP0Regs_;
-u32 schedule_timeslice(void);
+struct psxRegisters;
+
+u32 schedule_timeslice(struct psxRegisters *regs);
void irq_test(union psxCP0Regs_ *cp0);
void gen_interupt(union psxCP0Regs_ *cp0);
void events_restore(void);
#define DO_EXCEPTION_RESERVEDI
#define HANDLE_LOAD_DELAY
-static int branchSeen = 0;
-
#ifdef __i386__
#define INT_ATTR __attribute__((regparm(2)))
#else
cp0->n.Cause |= (regs->branching << 30) | (R3000E_Bp << 2);
cp0->n.SR = (cp0->n.SR & ~0x3f) | ((cp0->n.SR & 0x0f) << 2);
cp0->n.EPC = regs->branching ? pc - 4 : pc;
- psxRegs.pc = 0x80000040;
+ regs->pc = 0x80000040;
}
static int execBreakCheck(psxRegisters *regs, u32 pc)
static void doBranch(psxRegisters *regs, u32 tar, enum R3000Abdt taken) {
u32 code, pc, pc_final;
- branchSeen = regs->branching = taken;
+ regs->branchSeen = regs->branching = taken;
pc_final = taken == R3000A_BRANCH_TAKEN ? tar : regs->pc + 4;
// fetch the delay slot
}
dloadFlush(regs_);
psxHLEt[hleCode]();
- branchSeen = 1;
+ regs_->branchSeen = 1;
}
static void (INT_ATTR *psxBSC[64])(psxRegisters *regs_, u32 code) = {
psxBSC[regs->code >> 26](regs, regs->code);
}
-static void intExecute() {
- psxRegisters *regs_ = &psxRegs;
+static void intExecute(psxRegisters *regs) {
u8 **memRLUT = psxMemRLUT;
- extern int stop;
- while (!stop)
- execI_(memRLUT, regs_);
+ while (!regs->stop)
+ execI_(memRLUT, regs);
}
-static void intExecuteBp() {
- psxRegisters *regs_ = &psxRegs;
+static void intExecuteBp(psxRegisters *regs) {
u8 **memRLUT = psxMemRLUT;
- extern int stop;
- while (!stop)
- execIbp(memRLUT, regs_);
+ while (!regs->stop)
+ execIbp(memRLUT, regs);
}
-void intExecuteBlock(enum blockExecCaller caller) {
- psxRegisters *regs_ = &psxRegs;
+static void intExecuteBlock(psxRegisters *regs, enum blockExecCaller caller) {
u8 **memRLUT = psxMemRLUT;
- branchSeen = 0;
- while (!branchSeen)
- execI_(memRLUT, regs_);
+ regs->branchSeen = 0;
+ while (!regs->branchSeen)
+ execI_(memRLUT, regs);
}
-static void intExecuteBlockBp(enum blockExecCaller caller) {
- psxRegisters *regs_ = &psxRegs;
+static void intExecuteBlockBp(psxRegisters *regs, enum blockExecCaller caller) {
u8 **memRLUT = psxMemRLUT;
- branchSeen = 0;
- while (!branchSeen)
- execIbp(memRLUT, regs_);
+ regs->branchSeen = 0;
+ while (!regs->branchSeen)
+ execIbp(memRLUT, regs);
}
static void intClear(u32 Addr, u32 Size) {
#ifndef __PSXINTERPRETER_H__
#define __PSXINTERPRETER_H__
+struct psxRegisters;
+
// get an opcode without triggering exceptions or affecting cache
u32 intFakeFetch(u32 pc);
// called by "new_dynarec"
-void execI(psxRegisters *regs);
+void execI(struct psxRegisters *regs);
void intApplyConfig();
-void MTC0(psxRegisters *regs_, int reg, u32 val);
+void MTC0(struct psxRegisters *regs, int reg, u32 val);
void gteNULL(struct psxCP2Regs *regs);
extern void (*psxCP2[64])(struct psxCP2Regs *regs);
-// called by lightrec
-void intExecuteBlock(enum blockExecCaller caller);
-
#endif // __PSXINTERPRETER_H__
void psxExecuteBios() {
int i;
for (i = 0; i < 5000000; i++) {
- psxCpu->ExecuteBlock(EXEC_CALLER_BOOT);
+ psxCpu->ExecuteBlock(&psxRegs, EXEC_CALLER_BOOT);
if ((psxRegs.pc & 0xff800000) == 0x80000000)
break;
}
EXEC_CALLER_OTHER,
};
+struct psxRegisters;
+
typedef struct {
int (*Init)();
void (*Reset)();
- void (*Execute)();
- void (*ExecuteBlock)(enum blockExecCaller caller); /* executes up to a jump */
+ void (*Execute)(struct psxRegisters *regs);
+ /* executes up to a jump */
+ void (*ExecuteBlock)(struct psxRegisters *regs, enum blockExecCaller caller);
void (*Clear)(u32 Addr, u32 Size);
void (*Notify)(enum R3000Anote note, void *data);
void (*ApplyConfig)();
psxCP2Ctrl CP2C; /* Cop2 control registers */
} psxCP2Regs;
-typedef struct {
+typedef struct psxRegisters {
// note: some cores like lightrec don't keep their data here,
// so use R3000ACPU_NOTIFY_BEFORE_SAVE to sync
psxGPRRegs GPR; /* General Purpose Registers */
u32 code; /* The instruction */
u32 cycle;
u32 interrupt;
- struct { u32 sCycle, cycle; } intCycle[32];
+ struct { u32 sCycle, cycle; } intCycle[31];
+ u32 next_interupt; /* cycle */
+ u32 unused;
u32 gteBusyCycle;
u32 muldivBusyCycle;
u32 subCycle; /* interpreter cycle counting */
u32 subCycleStep;
u32 biuReg;
+ u8 stop;
+ u8 branchSeen; /* interp. */
u8 branching; /* interp. R3000A_BRANCH_TAKEN / not, 0 if not branch */
u8 dloadSel; /* interp. delay load state */
u8 dloadReg[2];
+ u8 unused2[2];
u32 dloadVal[2];
u32 biosBranchCheck;
u32 cpuInRecursion;
u32 gpuIdleAfter;
- u32 reserved[1];
// warning: changing anything in psxRegisters requires update of all
- // asm in libpcsxcore/new_dynarec/
+ // asm in libpcsxcore/new_dynarec/ and may break savestates
} psxRegisters;
extern psxRegisters psxRegs;