From 65722e0455a2a42eece5e67ce2e92bfac03e1368 Mon Sep 17 00:00:00 2001 From: notaz Date: Wed, 4 Oct 2023 23:51:55 +0300 Subject: [PATCH] drc: avoid excessive recursion in hle mode --- libpcsxcore/new_dynarec/linkage_arm.S | 1 - libpcsxcore/new_dynarec/new_dynarec.c | 25 +++++++++++++++---------- libpcsxcore/psxbios.c | 14 ++++++++++---- libpcsxcore/r3000a.h | 3 ++- 4 files changed, 27 insertions(+), 16 deletions(-) diff --git a/libpcsxcore/new_dynarec/linkage_arm.S b/libpcsxcore/new_dynarec/linkage_arm.S index d2d6d874..5d931809 100644 --- a/libpcsxcore/new_dynarec/linkage_arm.S +++ b/libpcsxcore/new_dynarec/linkage_arm.S @@ -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} diff --git a/libpcsxcore/new_dynarec/new_dynarec.c b/libpcsxcore/new_dynarec/new_dynarec.c index 73840137..74f32ee3 100644 --- a/libpcsxcore/new_dynarec/new_dynarec.c +++ b/libpcsxcore/new_dynarec/new_dynarec.c @@ -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); diff --git a/libpcsxcore/psxbios.c b/libpcsxcore/psxbios.c index 73f277a0..432b0e2c 100644 --- a/libpcsxcore/psxbios.c +++ b/libpcsxcore/psxbios.c @@ -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++) { diff --git a/libpcsxcore/r3000a.h b/libpcsxcore/r3000a.h index a8f39abb..157d31b9 100644 --- a/libpcsxcore/r3000a.h +++ b/libpcsxcore/r3000a.h @@ -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; -- 2.39.5