drc: avoid excessive recursion in hle mode
authornotaz <notasas@gmail.com>
Wed, 4 Oct 2023 20:51:55 +0000 (23:51 +0300)
committernotaz <notasas@gmail.com>
Wed, 4 Oct 2023 21:30:41 +0000 (00:30 +0300)
libpcsxcore/new_dynarec/linkage_arm.S
libpcsxcore/new_dynarec/new_dynarec.c
libpcsxcore/psxbios.c
libpcsxcore/r3000a.h

index d2d6d87..5d93180 100644 (file)
@@ -318,7 +318,6 @@ FUNCTION(jump_to_new_pc):
        .align  2
 FUNCTION(new_dyna_leave):
        ldr     r0, [fp, #LO_last_count]
-       add     r12, fp, #28
        add     r10, r0, r10
        str     r10, [fp, #LO_cycle]
        ldmfd   sp!, {r4, r5, r6, r7, r8, r9, sl, fp, ip, pc}
index 7384013..74f32ee 100644 (file)
@@ -9086,17 +9086,22 @@ static int new_recompile_block(u_int addr)
   void *instr_addr0_override = NULL;
   int ds = 0;
 
-  if (start == 0x80030000) {
-    // nasty hack for the fastbios thing
-    // override block entry to this code
+  if ((Config.HLE && start == 0x80000080) || start == 0x80030000) {
     instr_addr0_override = out;
-    emit_movimm(start,0);
-    // abuse io address var as a flag that we
-    // have already returned here once
-    emit_readword(&address,1);
-    emit_writeword(0,&pcaddr);
-    emit_writeword(0,&address);
-    emit_cmp(0,1);
+    emit_movimm(start, 0);
+    if (start == 0x80030000) {
+      // 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, &address);
+      emit_cmp(0, 1);
+    }
+    else {
+      emit_readword(&psxRegs.cpuInRecursion, 1);
+      emit_writeword(0, &pcaddr);
+      emit_test(1, 1);
+    }
     #ifdef __aarch64__
     emit_jeq(out + 4*2);
     emit_far_jump(new_dyna_leave);
index 73f277a..432b0e2 100644 (file)
@@ -398,14 +398,17 @@ static inline void softCall(u32 pc) {
        ra = 0x80001000;
        psxRegs.CP0.n.SR &= ~0x404; // disable interrupts
 
+       assert(psxRegs.cpuInRecursion <= 1);
+       psxRegs.cpuInRecursion++;
        psxCpu->Notify(R3000ACPU_NOTIFY_AFTER_LOAD, PTR_1);
 
-       while (pc0 != 0x80001000 && ++lim < 1000000)
+       while (pc0 != 0x80001000 && ++lim < 0x100000)
                psxCpu->ExecuteBlock(EXEC_CALLER_HLE);
 
        psxCpu->Notify(R3000ACPU_NOTIFY_BEFORE_SAVE, PTR_1);
+       psxRegs.cpuInRecursion--;
 
-       if (lim == 1000000)
+       if (lim == 0x100000)
                PSXBIOS_LOG("softCall @%x hit lim\n", pc);
        ra = sra;
        psxRegs.CP0.n.SR |= ssr & 0x404;
@@ -421,14 +424,16 @@ static inline void softCallInException(u32 pc) {
                return;
        ra = 0x80001000;
 
+       psxRegs.cpuInRecursion++;
        psxCpu->Notify(R3000ACPU_NOTIFY_AFTER_LOAD, PTR_1);
 
-       while (!returned_from_exception() && pc0 != 0x80001000 && ++lim < 1000000)
+       while (!returned_from_exception() && pc0 != 0x80001000 && ++lim < 0x100000)
                psxCpu->ExecuteBlock(EXEC_CALLER_HLE);
 
        psxCpu->Notify(R3000ACPU_NOTIFY_BEFORE_SAVE, PTR_1);
+       psxRegs.cpuInRecursion--;
 
-       if (lim == 1000000)
+       if (lim == 0x100000)
                PSXBIOS_LOG("softCallInException @%x hit lim\n", pc);
        if (pc0 == 0x80001000)
                ra = sra;
@@ -4035,6 +4040,7 @@ void psxBiosException() {
        sp = fp = loadRam32(A_EXC_SP);
        gp = A_EXC_GP;
        use_cycles(46);
+       assert(!psxRegs.cpuInRecursion);
 
        // do the chains (always 4)
        for (c = lim = 0; c < 4; c++) {
index a8f39ab..157d31b 100644 (file)
@@ -222,7 +222,8 @@ typedef struct {
        u8  dloadReg[2];
        u32 dloadVal[2];
        u32 biosBranchCheck;
-       u32 reserved[3];
+       u32 cpuInRecursion;
+       u32 reserved[2];
        // warning: changing anything in psxRegisters requires update of all
        // asm in libpcsxcore/new_dynarec/
 } psxRegisters;