From a69ca82751b14802475426a7bef25b316493f798 Mon Sep 17 00:00:00 2001 From: notaz Date: Thu, 24 Oct 2024 02:25:47 +0300 Subject: [PATCH] 3ds: use range clearing for small ranges Seems to be wastefull to throw away the entire icache when just a few new insns are compiled. Not that this gives any noticeable perf difference though. --- frontend/3ds/3ds_utils.h | 1 + frontend/3ds/utils.S | 38 +++++++++++++++++++++++++++ libpcsxcore/new_dynarec/new_dynarec.c | 6 ++++- 3 files changed, 44 insertions(+), 1 deletion(-) diff --git a/frontend/3ds/3ds_utils.h b/frontend/3ds/3ds_utils.h index 25bcc42a..2fc44f2a 100644 --- a/frontend/3ds/3ds_utils.h +++ b/frontend/3ds/3ds_utils.h @@ -18,6 +18,7 @@ void wait_for_input(void); void ctr_clear_cache(void); +void ctr_clear_cache_range(void *start, void *end); //void ctr_invalidate_icache(void); // only icache extern __attribute__((weak)) int __ctr_svchax; diff --git a/frontend/3ds/utils.S b/frontend/3ds/utils.S index 61da1554..6f7a6a2f 100644 --- a/frontend/3ds/utils.S +++ b/frontend/3ds/utils.S @@ -4,11 +4,39 @@ .func ctr_clear_cache_kernel ctr_clear_cache_kernel: + @ this less than what B2.7.3 of DDI0100I_ARM_ARM recommends, but so is Linux + mrs r3, cpsr cpsid aif mov r0, #0 mcr p15, 0, r0, c7, c10, 0 @ Clean entire data cache mcr p15, 0, r0, c7, c10, 4 @ Data Sync Barrier mcr p15, 0, r0, c7, c5, 0 @ Invalidate entire instruction cache / Flush BTB + msr cpsr, r3 + bx lr + .endfunc + + .func ctr_clear_cache_range_kernel +ctr_clear_cache_range_kernel: + bic r0, r0, #31 + mov r12, r0 + mov r2, #0 + mrs r3, cpsr + cpsid aif +0: + mcr p15, 0, r0, c7, c10, 1 @ Clean Data Cache Line (using MVA) + add r0, r0, #32 + cmp r0, r1 + blo 0b + mcr p15, 0, r2, c7, c10, 4 @ Data Sync Barrier + mov r0, r12 +0: + mcr p15, 0, r0, c7, c5, 1 @ Invalidate Instruction Cache Line (using MVA) + add r0, r0, #32 + cmp r0, r1 + blo 0b + mcr p15, 0, r2, c7, c5, 6 @ Flush Entire Branch Target Cache + + msr cpsr, r3 bx lr .endfunc @@ -23,6 +51,16 @@ ctr_clear_cache: bx lr .endfunc + .global ctr_clear_cache_range + .func ctr_clear_cache_range +ctr_clear_cache_range: + mov r2, r1 + mov r1, r0 + adr r0, ctr_clear_cache_range_kernel + svc 0x80 @ svcCustomBackdoor + bx lr + .endfunc + #if 0 .func ctr_invalidate_icache_kernel ctr_invalidate_icache_kernel: diff --git a/libpcsxcore/new_dynarec/new_dynarec.c b/libpcsxcore/new_dynarec/new_dynarec.c index 6243db46..37caf473 100644 --- a/libpcsxcore/new_dynarec/new_dynarec.c +++ b/libpcsxcore/new_dynarec/new_dynarec.c @@ -494,7 +494,11 @@ static void end_tcache_write(void *start, void *end) #elif defined(VITA) sceKernelSyncVMDomain(sceBlock, start, len); #elif defined(_3DS) - ctr_flush_invalidate_cache(); + // tuned for old3ds' 16k:16k cache (in it's mostly clean state...) + if ((char *)end - (char *)start <= 2*1024) + ctr_clear_cache_range(start, end); + else + ctr_flush_invalidate_cache(); ndrc_g.thread.cache_dirty = 1; #elif defined(HAVE_LIBNX) if (g_jit.type == JitType_CodeMemory) { -- 2.39.5