Fix reset() issue with dynarec flushing
On a reset bios_swi_entrypoint can end up pointing to code over the watermark, due to block_lookup_address_arm looking up the function instead of translating it. Fix it by making flush and init different functions (albeit similar). Tested by running and resetting games automatically, causing ~10% of games to crash.
This commit is contained in:
parent
84c347edad
commit
34eb7a3bf3
2
cheats.c
2
cheats.c
|
@ -60,7 +60,7 @@ static void update_hook_codebreaker(cheat_type *cheat)
|
||||||
u32 pcaddr = 0x08000000 | (address & 0x1ffffff);
|
u32 pcaddr = 0x08000000 | (address & 0x1ffffff);
|
||||||
#ifdef HAVE_DYNAREC
|
#ifdef HAVE_DYNAREC
|
||||||
if (cheat_master_hook != pcaddr)
|
if (cheat_master_hook != pcaddr)
|
||||||
init_caches(); /* Flush caches to install hook */
|
flush_dynarec_caches(); /* Flush caches to install hook */
|
||||||
#endif
|
#endif
|
||||||
cheat_master_hook = pcaddr;
|
cheat_master_hook = pcaddr;
|
||||||
return; /* Only support for one hook */
|
return; /* Only support for one hook */
|
||||||
|
|
3
cpu.h
3
cpu.h
|
@ -164,7 +164,8 @@ extern u32 rom_branch_hash[ROM_BRANCH_HASH_SIZE];
|
||||||
void flush_translation_cache_rom(void);
|
void flush_translation_cache_rom(void);
|
||||||
void flush_translation_cache_ram(void);
|
void flush_translation_cache_ram(void);
|
||||||
void dump_translation_cache(void);
|
void dump_translation_cache(void);
|
||||||
void init_caches(void);
|
void init_dynarec_caches(void);
|
||||||
|
void flush_dynarec_caches(void);
|
||||||
void init_emitter(bool);
|
void init_emitter(bool);
|
||||||
void init_bios_hooks(void);
|
void init_bios_hooks(void);
|
||||||
|
|
||||||
|
|
|
@ -3343,6 +3343,7 @@ void init_bios_hooks(void)
|
||||||
|
|
||||||
void flush_translation_cache_ram(void)
|
void flush_translation_cache_ram(void)
|
||||||
{
|
{
|
||||||
|
/* Flushes RAM caches avoiding doing too much work (ie. wiping unused memory) */
|
||||||
flush_ram_count++;
|
flush_ram_count++;
|
||||||
/*printf("ram flush %d (pc %x), %x to %x, %x to %x\n",
|
/*printf("ram flush %d (pc %x), %x to %x, %x to %x\n",
|
||||||
flush_ram_count, reg[REG_PC], iwram_code_min, iwram_code_max,
|
flush_ram_count, reg[REG_PC], iwram_code_min, iwram_code_max,
|
||||||
|
@ -3380,15 +3381,32 @@ void flush_translation_cache_ram(void)
|
||||||
|
|
||||||
void flush_translation_cache_rom(void)
|
void flush_translation_cache_rom(void)
|
||||||
{
|
{
|
||||||
|
/* We flush the generated code except for everything below the watermark. */
|
||||||
last_rom_translation_ptr = &rom_translation_cache[rom_cache_watermark];
|
last_rom_translation_ptr = &rom_translation_cache[rom_cache_watermark];
|
||||||
rom_translation_ptr = &rom_translation_cache[rom_cache_watermark];
|
rom_translation_ptr = &rom_translation_cache[rom_cache_watermark];
|
||||||
|
|
||||||
memset(rom_branch_hash, 0, sizeof(rom_branch_hash));
|
memset(rom_branch_hash, 0, sizeof(rom_branch_hash));
|
||||||
}
|
}
|
||||||
|
|
||||||
void init_caches(void)
|
void init_dynarec_caches(void)
|
||||||
{
|
{
|
||||||
/* Ensure we wipe everything including the SMC mirrors */
|
/* Initialize caches so that we can start initalizing the emitter. */
|
||||||
|
rom_translation_ptr = last_rom_translation_ptr = &rom_translation_cache[0];
|
||||||
|
memset(rom_branch_hash, 0, sizeof(rom_branch_hash));
|
||||||
|
|
||||||
|
ram_translation_ptr = last_ram_translation_ptr = &ram_translation_cache[0];
|
||||||
|
memset(iwram, 0, 0x8000);
|
||||||
|
memset(&ewram[0x40000], 0, 0x40000);
|
||||||
|
|
||||||
|
ewram_code_min = 0;
|
||||||
|
ewram_code_max = 0x40000;
|
||||||
|
iwram_code_min = 0;
|
||||||
|
iwram_code_max = 0x8000;
|
||||||
|
}
|
||||||
|
|
||||||
|
void flush_dynarec_caches(void)
|
||||||
|
{
|
||||||
|
/* Flush ROM and RAM caches. */
|
||||||
flush_translation_cache_rom();
|
flush_translation_cache_rom();
|
||||||
ewram_code_min = 0;
|
ewram_code_min = 0;
|
||||||
ewram_code_max = 0x40000;
|
ewram_code_max = 0x40000;
|
||||||
|
|
|
@ -803,8 +803,9 @@ static void check_variables(int started_from_load)
|
||||||
else if (strcmp(var.value, "enabled") == 0)
|
else if (strcmp(var.value, "enabled") == 0)
|
||||||
dynarec_enable = 1;
|
dynarec_enable = 1;
|
||||||
|
|
||||||
|
/* Flush dynarec cache to ensure we do not execute old code */
|
||||||
if (dynarec_enable != prevvalue)
|
if (dynarec_enable != prevvalue)
|
||||||
init_caches();
|
flush_dynarec_caches();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
dynarec_enable = 1;
|
dynarec_enable = 1;
|
||||||
|
|
2
main.c
2
main.c
|
@ -100,8 +100,8 @@ void init_main(void)
|
||||||
video_count = 960;
|
video_count = 960;
|
||||||
|
|
||||||
#ifdef HAVE_DYNAREC
|
#ifdef HAVE_DYNAREC
|
||||||
|
init_dynarec_caches();
|
||||||
init_emitter(gamepak_must_swap());
|
init_emitter(gamepak_must_swap());
|
||||||
init_caches();
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -103,7 +103,7 @@ bool gba_load_state(const void* src)
|
||||||
// Reset most of the frame state and dynarec state
|
// Reset most of the frame state and dynarec state
|
||||||
#ifdef HAVE_DYNAREC
|
#ifdef HAVE_DYNAREC
|
||||||
if (dynarec_enable)
|
if (dynarec_enable)
|
||||||
init_caches();
|
flush_dynarec_caches();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
instruction_count = 0;
|
instruction_count = 0;
|
||||||
|
|
Loading…
Reference in New Issue