#include "../psxinterpreter.h"
#include "../psxcounters.h"
#include "../psxevents.h"
+#include "../psxbios.h"
#include "../r3000a.h"
#include "../gte_arm.h"
#include "../gte_neon.h"
//ari64_notify(R3000ACPU_NOTIFY_BEFORE_SAVE, NULL);
psxInt.Notify(R3000ACPU_NOTIFY_AFTER_LOAD, NULL);
- do
+ psxCpu = &psxInt;
+ for (;;)
{
psxInt.ExecuteBlock(regs, block_caller);
+
+ if (ndrc_g.thread.busy_addr == ~0u)
+ break;
+ if (block_caller == EXEC_CALLER_HLE) {
+ if (!psxBiosSoftcallEnded())
+ continue;
+ break;
+ }
+ else if (block_caller == EXEC_CALLER_BOOT) {
+ if (!psxExecuteBiosEnded())
+ continue;
+ break;
+ }
+ if (regs->stop)
+ break;
}
- while (!regs->stop && ndrc_g.thread.busy_addr != ~0u && block_caller == EXEC_CALLER_OTHER);
+ psxCpu = &psxRec;
psxInt.Notify(R3000ACPU_NOTIFY_BEFORE_SAVE, NULL);
//ari64_notify(R3000ACPU_NOTIFY_AFTER_LOAD, NULL);
regs->stop++;
regs->next_interupt = regs->cycle + 1;
+
ari64_execute_threaded_once(regs, caller);
+ if (regs->cpuInRecursion) {
+ // must sync since we are returning to compiled code
+ ari64_thread_sync();
+ }
if (caller == EXEC_CALLER_BOOT)
regs->stop--;
static int returned_from_exception(void)
{
// 0x80000080 means it took another exception just after return
- return pc0 == k0 || pc0 == 0x80000080;
+ return pc0 == k0 || pc0 == 0x80000080
+#ifdef LIGHTREC
+ // lightrec doesn't return at 0x80000080, so look
+ // for the next block too
+ || pc0 == A_EXCEPTION
+#endif
+ ;
+}
+
+int psxBiosSoftcallEnded(void)
+{
+ return pc0 == 0x80001000 || returned_from_exception();
}
+// TODO: get rid of this softCall() thing as recursive cpu calls cause
+// complications with dynarecs
static inline void softCall(u32 pc) {
u32 sra = ra;
u32 ssr = psxRegs.CP0.n.SR;
psxRegs.cpuInRecursion++;
psxCpu->Notify(R3000ACPU_NOTIFY_AFTER_LOAD, PTR_1);
- while (pc0 != 0x80001000 && ++lim < 0x100000)
+ while (!psxBiosSoftcallEnded() && ++lim < 0x100000)
psxCpu->ExecuteBlock(&psxRegs, EXEC_CALLER_HLE);
psxCpu->Notify(R3000ACPU_NOTIFY_BEFORE_SAVE, PTR_1);
psxRegs.cpuInRecursion--;
- if (lim == 0x100000)
- PSXBIOS_LOG("softCall @%x hit lim\n", pc);
+ if (pc0 != 0x80001000)
+ log_unhandled("%s @%x did not return (@%x cnt=%d)\n",
+ __func__, pc, pc0, lim);
ra = sra;
psxRegs.CP0.n.SR |= ssr & 0x404;
}
psxRegs.cpuInRecursion++;
psxCpu->Notify(R3000ACPU_NOTIFY_AFTER_LOAD, PTR_1);
- while (!returned_from_exception() && pc0 != 0x80001000 && ++lim < 0x100000)
+ while (!psxBiosSoftcallEnded() && ++lim < 0x100000)
psxCpu->ExecuteBlock(&psxRegs, EXEC_CALLER_HLE);
psxCpu->Notify(R3000ACPU_NOTIFY_BEFORE_SAVE, PTR_1);
psxRegs.cpuInRecursion--;
- if (lim == 0x100000)
- PSXBIOS_LOG("softCallInException @%x hit lim\n", pc);
+ if (pc0 != 0x80001000 && !psxBiosSoftcallEnded())
+ log_unhandled("%s @%x did not return (@%x cnt=%d)\n",
+ __func__, pc, pc0, lim);
if (pc0 == 0x80001000)
ra = sra;
}
void psxBiosSetupBootState(void);
void psxBiosCheckExe(u32 t_addr, u32 t_size, int loading_state);
void psxBiosCheckBranch(void);
+int psxBiosSoftcallEnded(void);
extern void (*biosA0[256])();
extern void (**biosB0)();
if (f == NULL) {
SysMessage(_("Could not open BIOS:\"%s\". Enabling HLE Bios!\n"), bios);
- memset(psxR, 0, 0x80000);
} else {
if (fread(psxR, 1, 0x80000, f) == 0x80000) {
Config.HLE = FALSE;
fclose(f);
}
}
+ if (Config.HLE)
+ memset(psxR, 0, 0x80000);
}
void psxMemShutdown() {
void psxReset() {
boolean introBypassed = FALSE;
+ boolean oldhle = Config.HLE;
+
psxMemReset();
memset(&psxRegs, 0, sizeof(psxRegs));
psxRegs.CP0.n.SR &= ~(1u << 22); // RAM exception vector
}
+ if (Config.HLE != oldhle) {
+ // at least ari64 drc compiles differently so hard reset
+ psxCpu->Shutdown();
+ psxCpu->Init();
+ }
psxCpu->ApplyConfig();
psxCpu->Reset();
}
}
+int psxExecuteBiosEnded(void) {
+ return (psxRegs.pc & 0xff800000) == 0x80000000;
+}
+
void psxExecuteBios() {
int i;
for (i = 0; i < 5000000; i++) {
psxCpu->ExecuteBlock(&psxRegs, EXEC_CALLER_BOOT);
- if ((psxRegs.pc & 0xff800000) == 0x80000000)
+ if (psxExecuteBiosEnded())
break;
}
if (psxRegs.pc != 0x80030000)
void psxException(u32 code, enum R3000Abdt bdt, psxCP0Regs *cp0);
void psxBranchTest();
void psxExecuteBios();
+int psxExecuteBiosEnded(void);
void psxJumpTest();
void irq10Interrupt();