Merge pull request #93 from davidgfnet/master

More cleanups (mostly whitespace and unused stuff)
This commit is contained in:
Autechre 2021-02-15 22:30:27 +01:00 committed by GitHub
commit 300d0c0028
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 431 additions and 465 deletions

View file

@ -3273,435 +3273,435 @@ block_exit_type block_exits[MAX_EXITS];
#define thumb_fix_pc() \ #define thumb_fix_pc() \
pc &= ~0x01 \ pc &= ~0x01 \
s32 translate_block_arm(u32 pc, translation_region_type s32 translate_block_arm(u32 pc, translation_region_type
translation_region, u32 smc_enable) translation_region, u32 smc_enable)
{ {
u32 opcode = 0; u32 opcode = 0;
u32 last_opcode; u32 last_opcode;
u32 condition; u32 condition;
u32 last_condition; u32 last_condition;
u32 pc_region = (pc >> 15); u32 pc_region = (pc >> 15);
u32 new_pc_region; u32 new_pc_region;
u8 *pc_address_block = memory_map_read[pc_region]; u8 *pc_address_block = memory_map_read[pc_region];
u32 block_start_pc = pc; u32 block_start_pc = pc;
u32 block_end_pc = pc; u32 block_end_pc = pc;
u32 block_exit_position = 0; u32 block_exit_position = 0;
s32 block_data_position = 0; s32 block_data_position = 0;
u32 external_block_exit_position = 0; u32 external_block_exit_position = 0;
u32 branch_target; u32 branch_target;
u32 cycle_count = 0; u32 cycle_count = 0;
u8 *translation_target; u8 *translation_target;
u8 *backpatch_address = NULL; u8 *backpatch_address = NULL;
u8 *translation_ptr = NULL; u8 *translation_ptr = NULL;
u8 *translation_cache_limit = NULL; u8 *translation_cache_limit = NULL;
s32 i; s32 i;
u32 flag_status; u32 flag_status;
block_exit_type external_block_exits[MAX_EXITS]; block_exit_type external_block_exits[MAX_EXITS];
generate_block_extra_vars_arm(); generate_block_extra_vars_arm();
arm_fix_pc(); arm_fix_pc();
if(!pc_address_block) if(!pc_address_block)
pc_address_block = load_gamepak_page(pc_region & 0x3FF); pc_address_block = load_gamepak_page(pc_region & 0x3FF);
switch(translation_region) switch(translation_region)
{ {
case TRANSLATION_REGION_RAM: case TRANSLATION_REGION_RAM:
if(pc >= 0x3000000) if(pc >= 0x3000000)
{ {
if((pc < iwram_code_min) || (iwram_code_min == 0xFFFFFFFF)) if((pc < iwram_code_min) || (iwram_code_min == 0xFFFFFFFF))
iwram_code_min = pc; iwram_code_min = pc;
} }
else else
if(pc >= 0x2000000) if(pc >= 0x2000000)
{ {
if((pc < ewram_code_min) || (ewram_code_min == 0xFFFFFFFF)) if((pc < ewram_code_min) || (ewram_code_min == 0xFFFFFFFF))
ewram_code_min = pc; ewram_code_min = pc;
} }
translation_ptr = ram_translation_ptr; translation_ptr = ram_translation_ptr;
translation_cache_limit = translation_cache_limit =
ram_translation_cache + RAM_TRANSLATION_CACHE_SIZE - ram_translation_cache + RAM_TRANSLATION_CACHE_SIZE -
TRANSLATION_CACHE_LIMIT_THRESHOLD; TRANSLATION_CACHE_LIMIT_THRESHOLD;
break; break;
case TRANSLATION_REGION_ROM: case TRANSLATION_REGION_ROM:
translation_ptr = rom_translation_ptr; translation_ptr = rom_translation_ptr;
translation_cache_limit = translation_cache_limit =
rom_translation_cache + ROM_TRANSLATION_CACHE_SIZE - rom_translation_cache + ROM_TRANSLATION_CACHE_SIZE -
TRANSLATION_CACHE_LIMIT_THRESHOLD; TRANSLATION_CACHE_LIMIT_THRESHOLD;
break; break;
case TRANSLATION_REGION_BIOS: case TRANSLATION_REGION_BIOS:
translation_ptr = bios_translation_ptr; translation_ptr = bios_translation_ptr;
translation_cache_limit = bios_translation_cache + translation_cache_limit = bios_translation_cache +
BIOS_TRANSLATION_CACHE_SIZE; BIOS_TRANSLATION_CACHE_SIZE;
break; break;
} }
generate_block_prologue(); generate_block_prologue();
/* This is a function because it's used a lot more than it might seem (all /* This is a function because it's used a lot more than it might seem (all
of the data processing functions can access it), and its expansion was of the data processing functions can access it), and its expansion was
massacreing the compiler. */ massacreing the compiler. */
if(smc_enable) if(smc_enable)
{ {
scan_block(arm, yes); scan_block(arm, yes);
} }
else else
{ {
scan_block(arm, no); scan_block(arm, no);
} }
for(i = 0; i < block_exit_position; i++) for(i = 0; i < block_exit_position; i++)
{ {
branch_target = block_exits[i].branch_target; branch_target = block_exits[i].branch_target;
if((branch_target > block_start_pc) && if((branch_target > block_start_pc) &&
(branch_target < block_end_pc)) (branch_target < block_end_pc))
{ {
block_data[(branch_target - block_start_pc) / block_data[(branch_target - block_start_pc) /
arm_instruction_width].update_cycles = 1; arm_instruction_width].update_cycles = 1;
} }
} }
arm_dead_flag_eliminate(); arm_dead_flag_eliminate();
block_exit_position = 0; block_exit_position = 0;
block_data_position = 0; block_data_position = 0;
last_condition = 0x0E; last_condition = 0x0E;
while(pc != block_end_pc) while(pc != block_end_pc)
{ {
block_data[block_data_position].block_offset = translation_ptr; block_data[block_data_position].block_offset = translation_ptr;
arm_base_cycles(); arm_base_cycles();
translate_arm_instruction(); translate_arm_instruction();
block_data_position++; block_data_position++;
/* If it went too far the cache needs to be flushed and the process /* If it went too far the cache needs to be flushed and the process
restarted. Because we might already be nested several stages in restarted. Because we might already be nested several stages in
a simple recursive call here won't work, it has to pedal out to a simple recursive call here won't work, it has to pedal out to
the beginning. */ the beginning. */
if(translation_ptr > translation_cache_limit) if(translation_ptr > translation_cache_limit)
{ {
translation_flush_count++; translation_flush_count++;
switch(translation_region) switch(translation_region)
{ {
case TRANSLATION_REGION_RAM: case TRANSLATION_REGION_RAM:
flush_translation_cache_ram(); flush_translation_cache_ram();
break; break;
case TRANSLATION_REGION_ROM: case TRANSLATION_REGION_ROM:
flush_translation_cache_rom(); flush_translation_cache_rom();
break; break;
case TRANSLATION_REGION_BIOS: case TRANSLATION_REGION_BIOS:
flush_translation_cache_bios(); flush_translation_cache_bios();
break; break;
} }
return -1; return -1;
} }
/* If the next instruction is a block entry point update the /* If the next instruction is a block entry point update the
cycle counter and update */ cycle counter and update */
if(block_data[block_data_position].update_cycles == 1) if(block_data[block_data_position].update_cycles == 1)
{ {
generate_cycle_update(); generate_cycle_update();
} }
} }
for(i = 0; i < translation_gate_targets; i++) for(i = 0; i < translation_gate_targets; i++)
{ {
if(pc == translation_gate_target_pc[i]) if(pc == translation_gate_target_pc[i])
{ {
generate_translation_gate(arm); generate_translation_gate(arm);
break; break;
} }
} }
for(i = 0; i < block_exit_position; i++) for(i = 0; i < block_exit_position; i++)
{ {
branch_target = block_exits[i].branch_target; branch_target = block_exits[i].branch_target;
if((branch_target >= block_start_pc) && (branch_target < block_end_pc)) if((branch_target >= block_start_pc) && (branch_target < block_end_pc))
{ {
/* Internal branch, patch to recorded address */ /* Internal branch, patch to recorded address */
translation_target = translation_target =
block_data[(branch_target - block_start_pc) / block_data[(branch_target - block_start_pc) /
arm_instruction_width].block_offset; arm_instruction_width].block_offset;
generate_branch_patch_unconditional(block_exits[i].branch_source, generate_branch_patch_unconditional(block_exits[i].branch_source,
translation_target); translation_target);
} }
else else
{ {
/* External branch, save for later */ /* External branch, save for later */
external_block_exits[external_block_exit_position].branch_target = external_block_exits[external_block_exit_position].branch_target =
branch_target; branch_target;
external_block_exits[external_block_exit_position].branch_source = external_block_exits[external_block_exit_position].branch_source =
block_exits[i].branch_source; block_exits[i].branch_source;
external_block_exit_position++; external_block_exit_position++;
} }
} }
switch(translation_region) switch(translation_region)
{ {
case TRANSLATION_REGION_RAM: case TRANSLATION_REGION_RAM:
if(pc >= 0x3000000) if(pc >= 0x3000000)
{ {
if((pc > iwram_code_max) || (iwram_code_max == 0xFFFFFFFF)) if((pc > iwram_code_max) || (iwram_code_max == 0xFFFFFFFF))
iwram_code_max = pc; iwram_code_max = pc;
} }
else else
if(pc >= 0x2000000) if(pc >= 0x2000000)
{ {
if((pc > ewram_code_max) || (ewram_code_max == 0xFFFFFFFF)) if((pc > ewram_code_max) || (ewram_code_max == 0xFFFFFFFF))
ewram_code_max = pc; ewram_code_max = pc;
} }
ram_translation_ptr = translation_ptr; ram_translation_ptr = translation_ptr;
break; break;
case TRANSLATION_REGION_ROM: case TRANSLATION_REGION_ROM:
rom_translation_ptr = translation_ptr; rom_translation_ptr = translation_ptr;
break; break;
case TRANSLATION_REGION_BIOS: case TRANSLATION_REGION_BIOS:
bios_translation_ptr = translation_ptr; bios_translation_ptr = translation_ptr;
break; break;
} }
for(i = 0; i < external_block_exit_position; i++) for(i = 0; i < external_block_exit_position; i++)
{ {
branch_target = external_block_exits[i].branch_target; branch_target = external_block_exits[i].branch_target;
arm_link_block(); arm_link_block();
if(!translation_target){ if(!translation_target){
return -1; return -1;
} }
generate_branch_patch_unconditional( generate_branch_patch_unconditional(
external_block_exits[i].branch_source, translation_target); external_block_exits[i].branch_source, translation_target);
} }
return 0; return 0;
} }
s32 translate_block_thumb(u32 pc, translation_region_type s32 translate_block_thumb(u32 pc, translation_region_type
translation_region, u32 smc_enable) translation_region, u32 smc_enable)
{ {
u32 opcode = 0; u32 opcode = 0;
u32 last_opcode; u32 last_opcode;
u32 condition; u32 condition;
u32 last_condition; u32 last_condition;
u32 pc_region = (pc >> 15); u32 pc_region = (pc >> 15);
u32 new_pc_region; u32 new_pc_region;
u8 *pc_address_block = memory_map_read[pc_region]; u8 *pc_address_block = memory_map_read[pc_region];
u32 block_start_pc = pc; u32 block_start_pc = pc;
u32 block_end_pc = pc; u32 block_end_pc = pc;
u32 block_exit_position = 0; u32 block_exit_position = 0;
s32 block_data_position = 0; s32 block_data_position = 0;
u32 external_block_exit_position = 0; u32 external_block_exit_position = 0;
u32 branch_target; u32 branch_target;
u32 cycle_count = 0; u32 cycle_count = 0;
u8 *translation_target; u8 *translation_target;
u8 *backpatch_address = NULL; u8 *backpatch_address = NULL;
u8 *translation_ptr = NULL; u8 *translation_ptr = NULL;
u8 *translation_cache_limit = NULL; u8 *translation_cache_limit = NULL;
s32 i; s32 i;
u32 flag_status; u32 flag_status;
block_exit_type external_block_exits[MAX_EXITS]; block_exit_type external_block_exits[MAX_EXITS];
generate_block_extra_vars_thumb(); generate_block_extra_vars_thumb();
thumb_fix_pc(); thumb_fix_pc();
if(!pc_address_block) if(!pc_address_block)
pc_address_block = load_gamepak_page(pc_region & 0x3FF); pc_address_block = load_gamepak_page(pc_region & 0x3FF);
switch(translation_region) switch(translation_region)
{ {
case TRANSLATION_REGION_RAM: case TRANSLATION_REGION_RAM:
if(pc >= 0x3000000) if(pc >= 0x3000000)
{ {
if((pc < iwram_code_min) || (iwram_code_min == 0xFFFFFFFF)) if((pc < iwram_code_min) || (iwram_code_min == 0xFFFFFFFF))
iwram_code_min = pc; iwram_code_min = pc;
} }
else else
if(pc >= 0x2000000) if(pc >= 0x2000000)
{ {
if((pc < ewram_code_min) || (ewram_code_min == 0xFFFFFFFF)) if((pc < ewram_code_min) || (ewram_code_min == 0xFFFFFFFF))
ewram_code_min = pc; ewram_code_min = pc;
} }
translation_ptr = ram_translation_ptr; translation_ptr = ram_translation_ptr;
translation_cache_limit = translation_cache_limit =
ram_translation_cache + RAM_TRANSLATION_CACHE_SIZE - ram_translation_cache + RAM_TRANSLATION_CACHE_SIZE -
TRANSLATION_CACHE_LIMIT_THRESHOLD; TRANSLATION_CACHE_LIMIT_THRESHOLD;
break; break;
case TRANSLATION_REGION_ROM: case TRANSLATION_REGION_ROM:
translation_ptr = rom_translation_ptr; translation_ptr = rom_translation_ptr;
translation_cache_limit = translation_cache_limit =
rom_translation_cache + ROM_TRANSLATION_CACHE_SIZE - rom_translation_cache + ROM_TRANSLATION_CACHE_SIZE -
TRANSLATION_CACHE_LIMIT_THRESHOLD; TRANSLATION_CACHE_LIMIT_THRESHOLD;
break; break;
case TRANSLATION_REGION_BIOS: case TRANSLATION_REGION_BIOS:
translation_ptr = bios_translation_ptr; translation_ptr = bios_translation_ptr;
translation_cache_limit = bios_translation_cache + translation_cache_limit = bios_translation_cache +
BIOS_TRANSLATION_CACHE_SIZE; BIOS_TRANSLATION_CACHE_SIZE;
break; break;
} }
generate_block_prologue(); generate_block_prologue();
/* This is a function because it's used a lot more than it might seem (all /* This is a function because it's used a lot more than it might seem (all
of the data processing functions can access it), and its expansion was of the data processing functions can access it), and its expansion was
massacreing the compiler. */ massacreing the compiler. */
if(smc_enable) if(smc_enable)
{ {
scan_block(thumb, yes); scan_block(thumb, yes);
} }
else else
{ {
scan_block(thumb, no); scan_block(thumb, no);
} }
for(i = 0; i < block_exit_position; i++) for(i = 0; i < block_exit_position; i++)
{ {
branch_target = block_exits[i].branch_target; branch_target = block_exits[i].branch_target;
if((branch_target > block_start_pc) && if((branch_target > block_start_pc) &&
(branch_target < block_end_pc)) (branch_target < block_end_pc))
{ {
block_data[(branch_target - block_start_pc) / block_data[(branch_target - block_start_pc) /
thumb_instruction_width].update_cycles = 1; thumb_instruction_width].update_cycles = 1;
} }
} }
thumb_dead_flag_eliminate(); thumb_dead_flag_eliminate();
block_exit_position = 0; block_exit_position = 0;
block_data_position = 0; block_data_position = 0;
last_condition = 0x0E; last_condition = 0x0E;
while(pc != block_end_pc) while(pc != block_end_pc)
{ {
block_data[block_data_position].block_offset = translation_ptr; block_data[block_data_position].block_offset = translation_ptr;
thumb_base_cycles(); thumb_base_cycles();
translate_thumb_instruction(); translate_thumb_instruction();
block_data_position++; block_data_position++;
/* If it went too far the cache needs to be flushed and the process /* If it went too far the cache needs to be flushed and the process
restarted. Because we might already be nested several stages in restarted. Because we might already be nested several stages in
a simple recursive call here won't work, it has to pedal out to a simple recursive call here won't work, it has to pedal out to
the beginning. */ the beginning. */
if(translation_ptr > translation_cache_limit) if(translation_ptr > translation_cache_limit)
{ {
translation_flush_count++; translation_flush_count++;
switch(translation_region) switch(translation_region)
{ {
case TRANSLATION_REGION_RAM: case TRANSLATION_REGION_RAM:
flush_translation_cache_ram(); flush_translation_cache_ram();
break; break;
case TRANSLATION_REGION_ROM: case TRANSLATION_REGION_ROM:
flush_translation_cache_rom(); flush_translation_cache_rom();
break; break;
case TRANSLATION_REGION_BIOS: case TRANSLATION_REGION_BIOS:
flush_translation_cache_bios(); flush_translation_cache_bios();
break; break;
} }
return -1; return -1;
} }
/* If the next instruction is a block entry point update the /* If the next instruction is a block entry point update the
cycle counter and update */ cycle counter and update */
if(block_data[block_data_position].update_cycles == 1) if(block_data[block_data_position].update_cycles == 1)
{ {
generate_cycle_update(); generate_cycle_update();
} }
} }
for(i = 0; i < translation_gate_targets; i++) for(i = 0; i < translation_gate_targets; i++)
{ {
if(pc == translation_gate_target_pc[i]) if(pc == translation_gate_target_pc[i])
{ {
generate_translation_gate(thumb); generate_translation_gate(thumb);
break; break;
} }
} }
for(i = 0; i < block_exit_position; i++) for(i = 0; i < block_exit_position; i++)
{ {
branch_target = block_exits[i].branch_target; branch_target = block_exits[i].branch_target;
if((branch_target >= block_start_pc) && (branch_target < block_end_pc)) if((branch_target >= block_start_pc) && (branch_target < block_end_pc))
{ {
/* Internal branch, patch to recorded address */ /* Internal branch, patch to recorded address */
translation_target = translation_target =
block_data[(branch_target - block_start_pc) / block_data[(branch_target - block_start_pc) /
thumb_instruction_width].block_offset; thumb_instruction_width].block_offset;
generate_branch_patch_unconditional(block_exits[i].branch_source, generate_branch_patch_unconditional(block_exits[i].branch_source,
translation_target); translation_target);
} }
else else
{ {
/* External branch, save for later */ /* External branch, save for later */
external_block_exits[external_block_exit_position].branch_target = external_block_exits[external_block_exit_position].branch_target =
branch_target; branch_target;
external_block_exits[external_block_exit_position].branch_source = external_block_exits[external_block_exit_position].branch_source =
block_exits[i].branch_source; block_exits[i].branch_source;
external_block_exit_position++; external_block_exit_position++;
} }
} }
switch(translation_region) switch(translation_region)
{ {
case TRANSLATION_REGION_RAM: case TRANSLATION_REGION_RAM:
if(pc >= 0x3000000) if(pc >= 0x3000000)
{ {
if((pc > iwram_code_max) || (iwram_code_max == 0xFFFFFFFF)) if((pc > iwram_code_max) || (iwram_code_max == 0xFFFFFFFF))
iwram_code_max = pc; iwram_code_max = pc;
} }
else else
if(pc >= 0x2000000) if(pc >= 0x2000000)
{ {
if((pc > ewram_code_max) || (ewram_code_max == 0xFFFFFFFF)) if((pc > ewram_code_max) || (ewram_code_max == 0xFFFFFFFF))
ewram_code_max = pc; ewram_code_max = pc;
} }
ram_translation_ptr = translation_ptr; ram_translation_ptr = translation_ptr;
break; break;
case TRANSLATION_REGION_ROM: case TRANSLATION_REGION_ROM:
rom_translation_ptr = translation_ptr; rom_translation_ptr = translation_ptr;
break; break;
case TRANSLATION_REGION_BIOS: case TRANSLATION_REGION_BIOS:
bios_translation_ptr = translation_ptr; bios_translation_ptr = translation_ptr;
break; break;
} }
for(i = 0; i < external_block_exit_position; i++) for(i = 0; i < external_block_exit_position; i++)
{ {
branch_target = external_block_exits[i].branch_target; branch_target = external_block_exits[i].branch_target;
thumb_link_block(); thumb_link_block();
if(!translation_target){ if(!translation_target){
return -1; return -1;
} }
generate_branch_patch_unconditional( generate_branch_patch_unconditional(
external_block_exits[i].branch_source, translation_target); external_block_exits[i].branch_source, translation_target);
} }
return 0; return 0;
} }

View file

@ -311,9 +311,9 @@ u16 palette_ram_converted[512];
u16 io_registers[1024 * 16]; u16 io_registers[1024 * 16];
u8 ewram[1024 * 256 * 2]; u8 ewram[1024 * 256 * 2];
u8 iwram[1024 * 32 * 2]; u8 iwram[1024 * 32 * 2];
u8 vram[1024 * 96 * 2]; u8 vram[1024 * 96];
u8 bios_rom[1024 * 32]; u8 bios_rom[1024 * 16 * 2];
u32 bios_read_protect; u32 bios_read_protect;
// Up to 128kb, store SRAM, flash ROM, or EEPROM here. // Up to 128kb, store SRAM, flash ROM, or EEPROM here.
@ -3144,16 +3144,6 @@ cpu_alert_type dma_transfer(dma_transfer_type *dma)
memory_map_##type[map_offset + 3] = vram + (0x8000 * 2); \ memory_map_##type[map_offset + 3] = vram + (0x8000 * 2); \
} \ } \
#define map_vram_firstpage(type) \
for(map_offset = 0x6000000 / 0x8000; map_offset < (0x7000000 / 0x8000); \
map_offset += 4) \
{ \
memory_map_##type[map_offset] = vram; \
memory_map_##type[map_offset + 1] = NULL; \
memory_map_##type[map_offset + 2] = NULL; \
memory_map_##type[map_offset + 3] = NULL; \
} \
// Picks a page to evict // Picks a page to evict
u32 page_time = 0; u32 page_time = 0;
@ -3331,6 +3321,7 @@ void init_memory(void)
// This is because VRAM cannot be efficiently made incontiguous, and still allow // This is because VRAM cannot be efficiently made incontiguous, and still allow
// the renderer to work as efficiently. It would, at the very least, require a // the renderer to work as efficiently. It would, at the very least, require a
// lot of hacking of the renderer which I'm not prepared to do. // lot of hacking of the renderer which I'm not prepared to do.
// TODO(davidgfnet): add SMC VRAM detection
// However, it IS possible to directly map the first page no matter what because // However, it IS possible to directly map the first page no matter what because
// there's 32kb of blank stuff sitting beneath it. // there's 32kb of blank stuff sitting beneath it.

View file

@ -196,16 +196,16 @@ extern u32 gbc_sound_update;
extern u32 gbc_sound_wave_update; extern u32 gbc_sound_wave_update;
extern dma_transfer_type dma[4]; extern dma_transfer_type dma[4];
extern u32 bios_read_protect;
extern u16 palette_ram[512]; extern u16 palette_ram[512];
extern u16 oam_ram[512]; extern u16 oam_ram[512];
extern u16 palette_ram_converted[512]; extern u16 palette_ram_converted[512];
extern u16 io_registers[1024 * 16]; extern u16 io_registers[1024 * 16];
extern u8 vram[1024 * 96];
// Double buffer used for SMC detection
extern u8 bios_rom[1024 * 16 * 2];
extern u8 ewram[1024 * 256 * 2]; extern u8 ewram[1024 * 256 * 2];
extern u8 iwram[1024 * 32 * 2]; extern u8 iwram[1024 * 32 * 2];
extern u8 vram[1024 * 96 * 2];
extern u8 bios_rom[1024 * 32];
extern u32 bios_read_protect;
extern u8 *memory_map_read[8 * 1024]; extern u8 *memory_map_read[8 * 1024];
extern u32 *reg; extern u32 *reg;

View file

@ -2807,31 +2807,6 @@ ext_store_u32a_jtable:
.long ext_store_ignore # 0x0D EEPROM (nothing will write this) .long ext_store_ignore # 0x0D EEPROM (nothing will write this)
.long ext_store_ignore # 0x0E Flash ROM/SRAM .long ext_store_ignore # 0x0E Flash ROM/SRAM
ext_aligned_store32:
srl $1, $4, 24 # $1 = address >> 24
sltu $2, $1, 16 # check if the value is out of range
beq $2, $0, ext_store_ignore
sll $1, $1, 2 # make address word indexed (delay)
lui $2, %hi(ext_store_u32a_jtable)
addu $2, $2, $1
# $2 = ext_store_u32a_jtable[address >> 24]
lw $2, %lo(ext_store_u32a_jtable)($2)
jr $2 # jump to table location
nop
#execute_aligned_store32:
srl $2, $4, 28 # check if the address is out of range
bne $2, $0, ext_aligned_store32 # if it is, perform an extended load
srl $1, $4, 15 # $1 = page number of address
sll $1, $1, 2 # adjust to word index
addu $1, $1, $16 # $1 = memory_map_write[address >> 15]
lw $1, 256($1)
beq $1, $0, ext_aligned_store32 # if it's NULL perform an extended write
andi $2, $4, 0x7FFF # $2 = low 15bits of address (delay slot)
addu $1, $1, $2 # add the memory map offset
jr $ra # return
sw $5, ($1) # write the value
smc_write: smc_write:
save_registers save_registers
jal flush_translation_cache_ram # flush translation cache jal flush_translation_cache_ram # flush translation cache