hle: assorted fixes
authornotaz <notasas@gmail.com>
Thu, 23 Jan 2025 23:51:59 +0000 (01:51 +0200)
committernotaz <notasas@gmail.com>
Fri, 24 Jan 2025 23:34:41 +0000 (01:34 +0200)
like switching bios<->hle, w^x dynarec

libpcsxcore/new_dynarec/emu_if.c
libpcsxcore/psxbios.c
libpcsxcore/psxbios.h
libpcsxcore/psxmem.c
libpcsxcore/r3000a.c
libpcsxcore/r3000a.h

index 618cafd..69e2bc9 100644 (file)
@@ -13,6 +13,7 @@
 #include "../psxinterpreter.h"
 #include "../psxcounters.h"
 #include "../psxevents.h"
+#include "../psxbios.h"
 #include "../r3000a.h"
 #include "../gte_arm.h"
 #include "../gte_neon.h"
@@ -352,11 +353,27 @@ static noinline void ari64_execute_threaded_slow(struct psxRegisters *regs,
 
        //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);
@@ -402,7 +419,12 @@ static void ari64_execute_threaded_block(struct psxRegisters *regs,
                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--;
index 0e80875..d008cc9 100644 (file)
@@ -404,9 +404,22 @@ static void mips_return_void_c(u32 cycle)
 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;
@@ -419,14 +432,15 @@ static inline void softCall(u32 pc) {
        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;
 }
@@ -444,14 +458,15 @@ static inline void softCallInException(u32 pc) {
        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;
 }
index c8c07ff..1f26693 100644 (file)
@@ -42,6 +42,7 @@ void psxBiosCnfLoaded(u32 tcb_cnt, u32 evcb_cnt, u32 sp);
 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)();
index e08bd89..1330199 100644 (file)
@@ -270,7 +270,6 @@ void psxMemReset() {
 
                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;
@@ -280,6 +279,8 @@ void psxMemReset() {
                        fclose(f);
                }
        }
+       if (Config.HLE)
+               memset(psxR, 0, 0x80000);
 }
 
 void psxMemShutdown() {
index c282422..cfd1ab0 100644 (file)
@@ -62,6 +62,8 @@ int psxInit() {
 
 void psxReset() {
        boolean introBypassed = FALSE;
+       boolean oldhle = Config.HLE;
+
        psxMemReset();
 
        memset(&psxRegs, 0, sizeof(psxRegs));
@@ -75,6 +77,11 @@ void psxReset() {
                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();
 
@@ -174,11 +181,15 @@ void psxJumpTest() {
        }
 }
 
+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)
index 2889885..df7882c 100644 (file)
@@ -234,6 +234,7 @@ void psxShutdown();
 void psxException(u32 code, enum R3000Abdt bdt, psxCP0Regs *cp0);
 void psxBranchTest();
 void psxExecuteBios();
+int  psxExecuteBiosEnded(void);
 void psxJumpTest();
 
 void irq10Interrupt();