Emit BIOS SWI entrypoint to ROM arena
This fixes a race condition that happens whenever the ROM cache is flushed but the RAM one is not, causing any SWI calls (implemented as direct branches) to jump to random instructions. The fix could be to flush both caches at the same time (~expensive on low mem platforms), use indirect jumps (a bit expensive) or emit the SWI handler below the watermark to ensure it is never flushed. This is cheap and effective, requires minimal changes.
This commit is contained in:
parent
b431a8a4b6
commit
33f1e25099
6 changed files with 30 additions and 7 deletions
|
@ -1937,6 +1937,9 @@ extern u32 ldst_lookup_tables[9][16];
|
|||
|
||||
void init_emitter(void) {
|
||||
memcpy(ldst_lookup_tables, ldst_handler_functions, sizeof(ldst_lookup_tables));
|
||||
|
||||
rom_cache_watermark = 0;
|
||||
init_bios_hooks();
|
||||
}
|
||||
|
||||
u32 execute_arm_translate_internal(u32 cycles, void *regptr);
|
||||
|
|
1
cpu.h
1
cpu.h
|
@ -163,6 +163,7 @@ void flush_translation_cache_ram(void);
|
|||
void dump_translation_cache(void);
|
||||
void init_caches(void);
|
||||
void init_emitter(void);
|
||||
void init_bios_hooks(void);
|
||||
|
||||
extern u32 reg_mode[7][7];
|
||||
extern u32 spsr[6];
|
||||
|
|
|
@ -60,6 +60,7 @@ u32 ewram_code_min = ~0U;
|
|||
u32 ewram_code_max = 0U;
|
||||
u32 rom_cache_watermark = 0;
|
||||
|
||||
u8 *bios_swi_entrypoint = NULL;
|
||||
u32 *rom_branch_hash[ROM_BRANCH_HASH_SIZE];
|
||||
|
||||
typedef struct
|
||||
|
@ -2779,7 +2780,10 @@ block_lookup_address_builder(dual);
|
|||
} \
|
||||
|
||||
#define arm_link_block() \
|
||||
translation_target = block_lookup_address_arm(branch_target) \
|
||||
if(branch_target == 0x00000008) \
|
||||
translation_target = bios_swi_entrypoint; \
|
||||
else \
|
||||
translation_target = block_lookup_address_arm(branch_target); \
|
||||
|
||||
#define arm_instruction_width 4
|
||||
|
||||
|
@ -2851,10 +2855,11 @@ block_lookup_address_builder(dual);
|
|||
#define thumb_set_condition(_condition) \
|
||||
|
||||
#define thumb_link_block() \
|
||||
if(branch_target != 0x00000008) \
|
||||
translation_target = block_lookup_address_thumb(branch_target); \
|
||||
/* Speed hack to make SWI calls direct jumps */ \
|
||||
if(branch_target == 0x00000008) \
|
||||
translation_target = bios_swi_entrypoint; \
|
||||
else \
|
||||
translation_target = block_lookup_address_arm(branch_target) \
|
||||
translation_target = block_lookup_address_thumb(branch_target); \
|
||||
|
||||
#define thumb_instruction_width 2
|
||||
|
||||
|
@ -2959,8 +2964,8 @@ block_exit_type block_exits[MAX_EXITS];
|
|||
no_direct_branch:; \
|
||||
} \
|
||||
\
|
||||
/* SWI branches to the BIOS, this will likely change when \
|
||||
some HLE BIOS is implemented. */ \
|
||||
/* SWI branches to the BIOS, unless it's an HLE call, then it is \
|
||||
not parsed as an exit_point but rather an "instruction" of sorts. */ \
|
||||
if(type##_opcode_swi) \
|
||||
{ \
|
||||
block_exits[block_exit_position].branch_target = 0x00000008; \
|
||||
|
@ -3404,6 +3409,15 @@ s32 translate_block_thumb(u32 pc, translation_region_type
|
|||
return 0;
|
||||
}
|
||||
|
||||
void init_bios_hooks(void)
|
||||
{
|
||||
// Pre-generate this entry point so that we can safely invoke fast
|
||||
// SWI calls from ROM and RAM regardless of cache flushes.
|
||||
rom_translation_ptr = &rom_translation_cache[rom_cache_watermark];
|
||||
bios_swi_entrypoint = block_lookup_address_arm(0x8);
|
||||
rom_cache_watermark = (u32)(rom_translation_ptr - rom_translation_cache);
|
||||
}
|
||||
|
||||
void flush_translation_cache_ram(void)
|
||||
{
|
||||
flush_ram_count++;
|
||||
|
|
2
main.c
2
main.c
|
@ -252,8 +252,8 @@ u32 update_gba(void)
|
|||
|
||||
void reset_gba(void)
|
||||
{
|
||||
init_main();
|
||||
init_memory();
|
||||
init_main();
|
||||
init_cpu();
|
||||
reset_sound();
|
||||
}
|
||||
|
|
|
@ -3292,6 +3292,8 @@ void init_emitter() {
|
|||
|
||||
// Ensure rom flushes do not wipe this area
|
||||
rom_cache_watermark = (u32)(translation_ptr - rom_translation_cache);
|
||||
|
||||
init_bios_hooks();
|
||||
}
|
||||
|
||||
u32 execute_arm_translate_internal(u32 cycles, void *regptr);
|
||||
|
|
|
@ -2274,6 +2274,9 @@ extern u32 x86_table_info[3][16];
|
|||
|
||||
void init_emitter(void) {
|
||||
memcpy(x86_table_info, x86_table_data, sizeof(x86_table_data));
|
||||
|
||||
rom_cache_watermark = 0;
|
||||
init_bios_hooks();
|
||||
}
|
||||
|
||||
u32 function_cc execute_arm_translate_internal(u32 cycles, void *regptr);
|
||||
|
|
Loading…
Add table
Reference in a new issue