From 462f0e97843fad1e05b72e4512c99bef3347303d Mon Sep 17 00:00:00 2001 From: David Guillen Fandos Date: Fri, 12 Mar 2021 01:46:09 +0100 Subject: [PATCH] Improve cache flush magic Make it better and more generic. Add support for MIPS32 and fix the messy PSP code. --- cpu_threaded.c | 98 +++++++++++++++++++------------------------------ psp/mips_emit.h | 6 --- psp/mips_stub.S | 32 ++++------------ 3 files changed, 45 insertions(+), 91 deletions(-) diff --git a/cpu_threaded.c b/cpu_threaded.c index f0d38be..5bd9aed 100644 --- a/cpu_threaded.c +++ b/cpu_threaded.c @@ -252,65 +252,48 @@ extern u8 bit_count[256]; /* Cache invalidation */ #if defined(PSP) -#define translate_invalidate_dcache() sceKernelDcacheWritebackAll() -#define invalidate_icache_region(addr, size) (void)0 - + void platform_cache_sync(void *baseaddr, void *endptr) { + sceKernelDcacheWritebackRange(baseaddr, ((char*)endptr) - ((char*)baseaddr)); + sceKernelIcacheInvalidateRange(baseaddr, ((char*)endptr) - ((char*)baseaddr)); + } #elif defined(VITA) -#define translate_invalidate_dcache_one(which) \ - if (which##_translation_ptr > last_##which##_translation_ptr) \ - { \ - sceKernelSyncVMDomain(sceBlock,last_##which##_translation_ptr, \ - which##_translation_ptr - last_##which##_translation_ptr); \ - last_##which##_translation_ptr = which##_translation_ptr; \ + void platform_cache_sync(void *baseaddr, void *endptr) { + sceKernelSyncVMDomain(baseaddr, ((char*)endptr) - ((char*)baseaddr) + 64); } - -#define translate_invalidate_dcache() \ -{ \ - translate_invalidate_dcache_one(rom) \ - translate_invalidate_dcache_one(ram) \ - translate_invalidate_dcache_one(bios) \ -} - -#define invalidate_icache_region(addr, size) (void)0 - #elif defined(_3DS) -#include "3ds/3ds_utils.h" - -#define translate_invalidate_dcache() ctr_flush_invalidate_cache() -#define invalidate_icache_region(addr, size) (void)0 - -#elif defined(ARM_ARCH) -static void sys_cacheflush(void *addr, unsigned long size) -{ - void *start = (void*)addr; - void *end = (void*)(char *)addr + size; - __clear_cache(start, end); -} - -#define translate_invalidate_dcache_one(which) \ - if (which##_translation_ptr > last_##which##_translation_ptr) \ - { \ - sys_cacheflush(last_##which##_translation_ptr, \ - which##_translation_ptr - last_##which##_translation_ptr); \ - sys_cacheflush(last_##which##_translation_ptr, 32);\ - last_##which##_translation_ptr = which##_translation_ptr; \ + #include "3ds/3ds_utils.h" + void platform_cache_sync(void *baseaddr, void *endptr) { + ctr_flush_invalidate_cache(); + } +#elif defined(ARM_ARCH) + void platform_cache_sync(void *baseaddr, void *endptr) { + __clear_cache(baseaddr, endptr); + } +#elif defined(MIPS_ARCH) + void platform_cache_sync(void *baseaddr, void *endptr) { + icache_region_sync(baseaddr, ((char*)endptr) - ((char*)baseaddr)); } - -#define translate_invalidate_dcache() \ -{ \ - translate_invalidate_dcache_one(rom) \ - translate_invalidate_dcache_one(ram) \ - translate_invalidate_dcache_one(bios) \ -} -#define invalidate_icache_region(addr, size) (void)0 - #else - -#define translate_invalidate_dcache() (void)0 -#define invalidate_icache_region(addr, size) (void)0 - + /* x86 CPUs have icache consistency checks */ + void platform_cache_sync(void *baseaddr, void *endptr) {} #endif +void translate_icache_sync() { + // Cache emitted code can only grow + if (last_rom_translation_ptr < rom_translation_ptr) { + platform_cache_sync(last_rom_translation_ptr, rom_translation_ptr); + last_rom_translation_ptr = rom_translation_ptr; + } + if (last_ram_translation_ptr < ram_translation_ptr) { + platform_cache_sync(last_ram_translation_ptr, ram_translation_ptr); + last_ram_translation_ptr = ram_translation_ptr; + } + if (last_bios_translation_ptr < bios_translation_ptr) { + platform_cache_sync(last_bios_translation_ptr, bios_translation_ptr); + last_bios_translation_ptr = bios_translation_ptr; + } +} + /* End of Cache invalidation */ @@ -2833,7 +2816,7 @@ u32 bios_block_tag_top = 0x0101; } \ \ if(translation_recursion_level == 0) \ - translate_invalidate_dcache(); \ + translate_icache_sync(); \ } \ else \ { \ @@ -2924,7 +2907,7 @@ u8 function_cc *block_lookup_address_##type(u32 pc) \ } \ \ if(translation_recursion_level == 0) \ - translate_invalidate_dcache(); \ + translate_icache_sync(); \ } \ if(translation_recursion_level == 0) \ bios_region_read_protect(); \ @@ -2949,7 +2932,7 @@ u8 function_cc *block_lookup_address_##type(u32 pc) \ block_address = (u8 *)(-1); \ break; \ } \ - \ + \ return block_address; \ } \ @@ -3719,7 +3702,6 @@ void flush_translation_cache_ram(void) flush_ram_count, reg[REG_PC], iwram_code_min, iwram_code_max, ewram_code_min, ewram_code_max); */ - invalidate_icache_region(ram_translation_cache, (ram_translation_ptr - ram_translation_cache) + 0x100); last_ram_translation_ptr = ram_translation_cache; ram_translation_ptr = ram_translation_cache; ram_block_tag_top = 0x0101; @@ -3769,8 +3751,6 @@ void flush_translation_cache_ram(void) void flush_translation_cache_rom(void) { - invalidate_icache_region(rom_translation_cache, rom_translation_ptr - rom_translation_cache + 0x100); - last_rom_translation_ptr = rom_translation_cache; rom_translation_ptr = rom_translation_cache; @@ -3779,8 +3759,6 @@ void flush_translation_cache_rom(void) void flush_translation_cache_bios(void) { - invalidate_icache_region(bios_translation_cache, bios_translation_ptr - bios_translation_cache + 0x100); - bios_block_tag_top = 0x0101; last_bios_translation_ptr = bios_translation_cache; diff --git a/psp/mips_emit.h b/psp/mips_emit.h index f01fbe7..7c69091 100644 --- a/psp/mips_emit.h +++ b/psp/mips_emit.h @@ -631,12 +631,6 @@ u32 arm_to_mips_reg[] = #define generate_block_prologue() \ update_trampoline = translation_ptr; \ - __asm__ \ - ( \ - "cache 8, 0(%0)\n" \ - "cache 8, 0(%0)" : : "r"(translation_ptr) \ - ); \ - \ mips_emit_j(mips_absolute_offset(mips_update_gba)); \ mips_emit_nop(); \ generate_load_imm(reg_pc, stored_pc) \ diff --git a/psp/mips_stub.S b/psp/mips_stub.S index c89a5b1..7f0f303 100644 --- a/psp/mips_stub.S +++ b/psp/mips_stub.S @@ -16,6 +16,7 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +.set mips32r2 .align 4 .global mips_update_gba @@ -43,8 +44,7 @@ .global execute_asr_flags_reg .global execute_ror_flags_reg .global execute_arm_translate -.global invalidate_icache_region -.global invalidate_all_cache +.global icache_region_sync .global reg_check .global memory_map_read @@ -2808,42 +2808,24 @@ execute_arm_translate: jr $2 # jump to return nop -# sceKernelInvalidateIcacheRange gives me problems, trying this instead -# Invalidates an n byte region starting at the start address +# This is only to be used with MIPS32 # $4: start location # $5: length -invalidate_icache_region: +icache_region_sync: ins $4, $0, 0, 6 # align to 64 bytes addiu $2, $5, 63 # align up to 64 bytes srl $2, $2, 6 # divide by 64 - beq $2, $0, done # exit early on 0 - nop -iir_loop: - cache 0x08, ($4) # hit invalidate icache line +1: + synci ($4) # sync caches addiu $2, $2, -1 # next loop iteration - bne $2, $0, iir_loop # loop + bne $2, $0, 1b # loop addiu $4, $4, 64 # go to next cache line (delay slot) -done: jr $ra # return nop -# Writes back dcache and invalidates icache. - -invalidate_all_cache: - addu $4, $0, $0 # $4 = 0 - addiu $5, $0, 0x4000 # $5 = 0x4000 - -iac_loop: - cache 0x14, 0($4) # index invalidate/writeback dcache index - addiu $4, $4, 0x40 # goto next cache line - bne $4, $5, iac_loop # next iteration - cache 0x04, -0x40($4) # index invalidate icache index.. maybe? - - jr $ra # return - nop memory_map_read: .space 0x8000