diff options
-rw-r--r-- | cpu_threaded.c | 848 | ||||
-rw-r--r-- | gba_memory.c | 15 | ||||
-rw-r--r-- | gba_memory.h | 8 | ||||
-rw-r--r-- | psp/mips_stub.S | 25 |
4 files changed, 431 insertions, 465 deletions
diff --git a/cpu_threaded.c b/cpu_threaded.c index ef7d83b..083c027 100644 --- a/cpu_threaded.c +++ b/cpu_threaded.c @@ -3273,435 +3273,435 @@ block_exit_type block_exits[MAX_EXITS]; #define thumb_fix_pc() \ pc &= ~0x01 \ -s32 translate_block_arm(u32 pc, translation_region_type - translation_region, u32 smc_enable) -{ - u32 opcode = 0; - u32 last_opcode; - u32 condition; - u32 last_condition; - u32 pc_region = (pc >> 15); - u32 new_pc_region; - u8 *pc_address_block = memory_map_read[pc_region]; - u32 block_start_pc = pc; - u32 block_end_pc = pc; - u32 block_exit_position = 0; - s32 block_data_position = 0; - u32 external_block_exit_position = 0; - u32 branch_target; - u32 cycle_count = 0; - u8 *translation_target; - u8 *backpatch_address = NULL; - u8 *translation_ptr = NULL; - u8 *translation_cache_limit = NULL; - s32 i; - u32 flag_status; - block_exit_type external_block_exits[MAX_EXITS]; - generate_block_extra_vars_arm(); - arm_fix_pc(); - - if(!pc_address_block) - pc_address_block = load_gamepak_page(pc_region & 0x3FF); - - switch(translation_region) - { - case TRANSLATION_REGION_RAM: - if(pc >= 0x3000000) - { - if((pc < iwram_code_min) || (iwram_code_min == 0xFFFFFFFF)) - iwram_code_min = pc; - } - else - - if(pc >= 0x2000000) - { - if((pc < ewram_code_min) || (ewram_code_min == 0xFFFFFFFF)) - ewram_code_min = pc; - } - - translation_ptr = ram_translation_ptr; - translation_cache_limit = - ram_translation_cache + RAM_TRANSLATION_CACHE_SIZE - - TRANSLATION_CACHE_LIMIT_THRESHOLD; - break; - - case TRANSLATION_REGION_ROM: - translation_ptr = rom_translation_ptr; - translation_cache_limit = - rom_translation_cache + ROM_TRANSLATION_CACHE_SIZE - - TRANSLATION_CACHE_LIMIT_THRESHOLD; - break; - - case TRANSLATION_REGION_BIOS: - translation_ptr = bios_translation_ptr; - translation_cache_limit = bios_translation_cache + - BIOS_TRANSLATION_CACHE_SIZE; - break; - } - - generate_block_prologue(); - - /* 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 - massacreing the compiler. */ - - if(smc_enable) - { - scan_block(arm, yes); - } - else - { - scan_block(arm, no); - } - - for(i = 0; i < block_exit_position; i++) - { - branch_target = block_exits[i].branch_target; - - if((branch_target > block_start_pc) && - (branch_target < block_end_pc)) - { - block_data[(branch_target - block_start_pc) / - arm_instruction_width].update_cycles = 1; - } - } - - arm_dead_flag_eliminate(); - - block_exit_position = 0; - block_data_position = 0; - - last_condition = 0x0E; - - while(pc != block_end_pc) - { - block_data[block_data_position].block_offset = translation_ptr; +s32 translate_block_arm(u32 pc, translation_region_type + translation_region, u32 smc_enable) +{ + u32 opcode = 0; + u32 last_opcode; + u32 condition; + u32 last_condition; + u32 pc_region = (pc >> 15); + u32 new_pc_region; + u8 *pc_address_block = memory_map_read[pc_region]; + u32 block_start_pc = pc; + u32 block_end_pc = pc; + u32 block_exit_position = 0; + s32 block_data_position = 0; + u32 external_block_exit_position = 0; + u32 branch_target; + u32 cycle_count = 0; + u8 *translation_target; + u8 *backpatch_address = NULL; + u8 *translation_ptr = NULL; + u8 *translation_cache_limit = NULL; + s32 i; + u32 flag_status; + block_exit_type external_block_exits[MAX_EXITS]; + generate_block_extra_vars_arm(); + arm_fix_pc(); + + if(!pc_address_block) + pc_address_block = load_gamepak_page(pc_region & 0x3FF); + + switch(translation_region) + { + case TRANSLATION_REGION_RAM: + if(pc >= 0x3000000) + { + if((pc < iwram_code_min) || (iwram_code_min == 0xFFFFFFFF)) + iwram_code_min = pc; + } + else + + if(pc >= 0x2000000) + { + if((pc < ewram_code_min) || (ewram_code_min == 0xFFFFFFFF)) + ewram_code_min = pc; + } + + translation_ptr = ram_translation_ptr; + translation_cache_limit = + ram_translation_cache + RAM_TRANSLATION_CACHE_SIZE - + TRANSLATION_CACHE_LIMIT_THRESHOLD; + break; + + case TRANSLATION_REGION_ROM: + translation_ptr = rom_translation_ptr; + translation_cache_limit = + rom_translation_cache + ROM_TRANSLATION_CACHE_SIZE - + TRANSLATION_CACHE_LIMIT_THRESHOLD; + break; + + case TRANSLATION_REGION_BIOS: + translation_ptr = bios_translation_ptr; + translation_cache_limit = bios_translation_cache + + BIOS_TRANSLATION_CACHE_SIZE; + break; + } + + generate_block_prologue(); + + /* 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 + massacreing the compiler. */ + + if(smc_enable) + { + scan_block(arm, yes); + } + else + { + scan_block(arm, no); + } + + for(i = 0; i < block_exit_position; i++) + { + branch_target = block_exits[i].branch_target; + + if((branch_target > block_start_pc) && + (branch_target < block_end_pc)) + { + block_data[(branch_target - block_start_pc) / + arm_instruction_width].update_cycles = 1; + } + } + + arm_dead_flag_eliminate(); + + block_exit_position = 0; + block_data_position = 0; + + last_condition = 0x0E; + + while(pc != block_end_pc) + { + block_data[block_data_position].block_offset = translation_ptr; arm_base_cycles(); - - translate_arm_instruction(); - block_data_position++; - - /* If it went too far the cache needs to be flushed and the process - restarted. Because we might already be nested several stages in - a simple recursive call here won't work, it has to pedal out to - the beginning. */ - - if(translation_ptr > translation_cache_limit) - { - translation_flush_count++; - - switch(translation_region) - { - case TRANSLATION_REGION_RAM: - flush_translation_cache_ram(); - break; - - case TRANSLATION_REGION_ROM: - flush_translation_cache_rom(); - break; - - case TRANSLATION_REGION_BIOS: - flush_translation_cache_bios(); - break; - } - return -1; - } - - /* If the next instruction is a block entry point update the - cycle counter and update */ - if(block_data[block_data_position].update_cycles == 1) - { - generate_cycle_update(); - } - } - for(i = 0; i < translation_gate_targets; i++) - { - if(pc == translation_gate_target_pc[i]) - { - generate_translation_gate(arm); - break; - } - } - - for(i = 0; i < block_exit_position; i++) - { - branch_target = block_exits[i].branch_target; - - if((branch_target >= block_start_pc) && (branch_target < block_end_pc)) - { - /* Internal branch, patch to recorded address */ - translation_target = - block_data[(branch_target - block_start_pc) / - arm_instruction_width].block_offset; - - generate_branch_patch_unconditional(block_exits[i].branch_source, - translation_target); - } - else - { - /* External branch, save for later */ - external_block_exits[external_block_exit_position].branch_target = - branch_target; - external_block_exits[external_block_exit_position].branch_source = - block_exits[i].branch_source; - external_block_exit_position++; - } - } - - switch(translation_region) - { - case TRANSLATION_REGION_RAM: - if(pc >= 0x3000000) - { - if((pc > iwram_code_max) || (iwram_code_max == 0xFFFFFFFF)) - iwram_code_max = pc; - } - else - - if(pc >= 0x2000000) - { - if((pc > ewram_code_max) || (ewram_code_max == 0xFFFFFFFF)) - ewram_code_max = pc; - } - - ram_translation_ptr = translation_ptr; - break; - - case TRANSLATION_REGION_ROM: - rom_translation_ptr = translation_ptr; - break; - - case TRANSLATION_REGION_BIOS: - bios_translation_ptr = translation_ptr; - break; - } - - for(i = 0; i < external_block_exit_position; i++) - { - branch_target = external_block_exits[i].branch_target; - arm_link_block(); - if(!translation_target){ + + translate_arm_instruction(); + block_data_position++; + + /* If it went too far the cache needs to be flushed and the process + restarted. Because we might already be nested several stages in + a simple recursive call here won't work, it has to pedal out to + the beginning. */ + + if(translation_ptr > translation_cache_limit) + { + translation_flush_count++; + + switch(translation_region) + { + case TRANSLATION_REGION_RAM: + flush_translation_cache_ram(); + break; + + case TRANSLATION_REGION_ROM: + flush_translation_cache_rom(); + break; + + case TRANSLATION_REGION_BIOS: + flush_translation_cache_bios(); + break; + } + return -1; + } + + /* If the next instruction is a block entry point update the + cycle counter and update */ + if(block_data[block_data_position].update_cycles == 1) + { + generate_cycle_update(); + } + } + for(i = 0; i < translation_gate_targets; i++) + { + if(pc == translation_gate_target_pc[i]) + { + generate_translation_gate(arm); + break; + } + } + + for(i = 0; i < block_exit_position; i++) + { + branch_target = block_exits[i].branch_target; + + if((branch_target >= block_start_pc) && (branch_target < block_end_pc)) + { + /* Internal branch, patch to recorded address */ + translation_target = + block_data[(branch_target - block_start_pc) / + arm_instruction_width].block_offset; + + generate_branch_patch_unconditional(block_exits[i].branch_source, + translation_target); + } + else + { + /* External branch, save for later */ + external_block_exits[external_block_exit_position].branch_target = + branch_target; + external_block_exits[external_block_exit_position].branch_source = + block_exits[i].branch_source; + external_block_exit_position++; + } + } + + switch(translation_region) + { + case TRANSLATION_REGION_RAM: + if(pc >= 0x3000000) + { + if((pc > iwram_code_max) || (iwram_code_max == 0xFFFFFFFF)) + iwram_code_max = pc; + } + else + + if(pc >= 0x2000000) + { + if((pc > ewram_code_max) || (ewram_code_max == 0xFFFFFFFF)) + ewram_code_max = pc; + } + + ram_translation_ptr = translation_ptr; + break; + + case TRANSLATION_REGION_ROM: + rom_translation_ptr = translation_ptr; + break; + + case TRANSLATION_REGION_BIOS: + bios_translation_ptr = translation_ptr; + break; + } + + for(i = 0; i < external_block_exit_position; i++) + { + branch_target = external_block_exits[i].branch_target; + arm_link_block(); + if(!translation_target){ return -1; - } - generate_branch_patch_unconditional( - external_block_exits[i].branch_source, translation_target); - } - return 0; + } + generate_branch_patch_unconditional( + external_block_exits[i].branch_source, translation_target); + } + return 0; } -s32 translate_block_thumb(u32 pc, translation_region_type - translation_region, u32 smc_enable) -{ - u32 opcode = 0; - u32 last_opcode; - u32 condition; - u32 last_condition; - u32 pc_region = (pc >> 15); - u32 new_pc_region; - u8 *pc_address_block = memory_map_read[pc_region]; - u32 block_start_pc = pc; - u32 block_end_pc = pc; - u32 block_exit_position = 0; - s32 block_data_position = 0; - u32 external_block_exit_position = 0; - u32 branch_target; - u32 cycle_count = 0; - u8 *translation_target; - u8 *backpatch_address = NULL; - u8 *translation_ptr = NULL; - u8 *translation_cache_limit = NULL; - s32 i; - u32 flag_status; - block_exit_type external_block_exits[MAX_EXITS]; - generate_block_extra_vars_thumb(); - thumb_fix_pc(); - - if(!pc_address_block) - pc_address_block = load_gamepak_page(pc_region & 0x3FF); - - switch(translation_region) - { - case TRANSLATION_REGION_RAM: - if(pc >= 0x3000000) - { - if((pc < iwram_code_min) || (iwram_code_min == 0xFFFFFFFF)) - iwram_code_min = pc; - } - else - - if(pc >= 0x2000000) - { - if((pc < ewram_code_min) || (ewram_code_min == 0xFFFFFFFF)) - ewram_code_min = pc; - } - - translation_ptr = ram_translation_ptr; - translation_cache_limit = - ram_translation_cache + RAM_TRANSLATION_CACHE_SIZE - - TRANSLATION_CACHE_LIMIT_THRESHOLD; - break; - - case TRANSLATION_REGION_ROM: - translation_ptr = rom_translation_ptr; - translation_cache_limit = - rom_translation_cache + ROM_TRANSLATION_CACHE_SIZE - - TRANSLATION_CACHE_LIMIT_THRESHOLD; - break; - - case TRANSLATION_REGION_BIOS: - translation_ptr = bios_translation_ptr; - translation_cache_limit = bios_translation_cache + - BIOS_TRANSLATION_CACHE_SIZE; - break; - } - - generate_block_prologue(); - - /* 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 - massacreing the compiler. */ - - if(smc_enable) - { - scan_block(thumb, yes); - } - else - { - scan_block(thumb, no); - } - - for(i = 0; i < block_exit_position; i++) - { - branch_target = block_exits[i].branch_target; - - if((branch_target > block_start_pc) && - (branch_target < block_end_pc)) - { - block_data[(branch_target - block_start_pc) / - thumb_instruction_width].update_cycles = 1; - } - } - - thumb_dead_flag_eliminate(); - - block_exit_position = 0; - block_data_position = 0; - - last_condition = 0x0E; - - while(pc != block_end_pc) - { - block_data[block_data_position].block_offset = translation_ptr; +s32 translate_block_thumb(u32 pc, translation_region_type + translation_region, u32 smc_enable) +{ + u32 opcode = 0; + u32 last_opcode; + u32 condition; + u32 last_condition; + u32 pc_region = (pc >> 15); + u32 new_pc_region; + u8 *pc_address_block = memory_map_read[pc_region]; + u32 block_start_pc = pc; + u32 block_end_pc = pc; + u32 block_exit_position = 0; + s32 block_data_position = 0; + u32 external_block_exit_position = 0; + u32 branch_target; + u32 cycle_count = 0; + u8 *translation_target; + u8 *backpatch_address = NULL; + u8 *translation_ptr = NULL; + u8 *translation_cache_limit = NULL; + s32 i; + u32 flag_status; + block_exit_type external_block_exits[MAX_EXITS]; + generate_block_extra_vars_thumb(); + thumb_fix_pc(); + + if(!pc_address_block) + pc_address_block = load_gamepak_page(pc_region & 0x3FF); + + switch(translation_region) + { + case TRANSLATION_REGION_RAM: + if(pc >= 0x3000000) + { + if((pc < iwram_code_min) || (iwram_code_min == 0xFFFFFFFF)) + iwram_code_min = pc; + } + else + + if(pc >= 0x2000000) + { + if((pc < ewram_code_min) || (ewram_code_min == 0xFFFFFFFF)) + ewram_code_min = pc; + } + + translation_ptr = ram_translation_ptr; + translation_cache_limit = + ram_translation_cache + RAM_TRANSLATION_CACHE_SIZE - + TRANSLATION_CACHE_LIMIT_THRESHOLD; + break; + + case TRANSLATION_REGION_ROM: + translation_ptr = rom_translation_ptr; + translation_cache_limit = + rom_translation_cache + ROM_TRANSLATION_CACHE_SIZE - + TRANSLATION_CACHE_LIMIT_THRESHOLD; + break; + + case TRANSLATION_REGION_BIOS: + translation_ptr = bios_translation_ptr; + translation_cache_limit = bios_translation_cache + + BIOS_TRANSLATION_CACHE_SIZE; + break; + } + + generate_block_prologue(); + + /* 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 + massacreing the compiler. */ + + if(smc_enable) + { + scan_block(thumb, yes); + } + else + { + scan_block(thumb, no); + } + + for(i = 0; i < block_exit_position; i++) + { + branch_target = block_exits[i].branch_target; + + if((branch_target > block_start_pc) && + (branch_target < block_end_pc)) + { + block_data[(branch_target - block_start_pc) / + thumb_instruction_width].update_cycles = 1; + } + } + + thumb_dead_flag_eliminate(); + + block_exit_position = 0; + block_data_position = 0; + + last_condition = 0x0E; + + while(pc != block_end_pc) + { + block_data[block_data_position].block_offset = translation_ptr; thumb_base_cycles(); - - translate_thumb_instruction(); - block_data_position++; - - /* If it went too far the cache needs to be flushed and the process - restarted. Because we might already be nested several stages in - a simple recursive call here won't work, it has to pedal out to - the beginning. */ - - if(translation_ptr > translation_cache_limit) - { - translation_flush_count++; - - switch(translation_region) - { - case TRANSLATION_REGION_RAM: - flush_translation_cache_ram(); - break; - - case TRANSLATION_REGION_ROM: - flush_translation_cache_rom(); - break; - - case TRANSLATION_REGION_BIOS: - flush_translation_cache_bios(); - break; - } - return -1; - } - - /* If the next instruction is a block entry point update the - cycle counter and update */ - if(block_data[block_data_position].update_cycles == 1) - { - generate_cycle_update(); - } - } - for(i = 0; i < translation_gate_targets; i++) - { - if(pc == translation_gate_target_pc[i]) - { - generate_translation_gate(thumb); - break; - } - } - - for(i = 0; i < block_exit_position; i++) - { - branch_target = block_exits[i].branch_target; - - if((branch_target >= block_start_pc) && (branch_target < block_end_pc)) - { - /* Internal branch, patch to recorded address */ - translation_target = - block_data[(branch_target - block_start_pc) / - thumb_instruction_width].block_offset; - - generate_branch_patch_unconditional(block_exits[i].branch_source, - translation_target); - } - else - { - /* External branch, save for later */ - external_block_exits[external_block_exit_position].branch_target = - branch_target; - external_block_exits[external_block_exit_position].branch_source = - block_exits[i].branch_source; - external_block_exit_position++; - } - } - - switch(translation_region) - { - case TRANSLATION_REGION_RAM: - if(pc >= 0x3000000) - { - if((pc > iwram_code_max) || (iwram_code_max == 0xFFFFFFFF)) - iwram_code_max = pc; - } - else - - if(pc >= 0x2000000) - { - if((pc > ewram_code_max) || (ewram_code_max == 0xFFFFFFFF)) - ewram_code_max = pc; - } - - ram_translation_ptr = translation_ptr; - break; - - case TRANSLATION_REGION_ROM: - rom_translation_ptr = translation_ptr; - break; - - case TRANSLATION_REGION_BIOS: - bios_translation_ptr = translation_ptr; - break; - } - - for(i = 0; i < external_block_exit_position; i++) - { - branch_target = external_block_exits[i].branch_target; - thumb_link_block(); - if(!translation_target){ - return -1; - } - generate_branch_patch_unconditional( - external_block_exits[i].branch_source, translation_target); - } + + translate_thumb_instruction(); + block_data_position++; + + /* If it went too far the cache needs to be flushed and the process + restarted. Because we might already be nested several stages in + a simple recursive call here won't work, it has to pedal out to + the beginning. */ + + if(translation_ptr > translation_cache_limit) + { + translation_flush_count++; + + switch(translation_region) + { + case TRANSLATION_REGION_RAM: + flush_translation_cache_ram(); + break; + + case TRANSLATION_REGION_ROM: + flush_translation_cache_rom(); + break; + + case TRANSLATION_REGION_BIOS: + flush_translation_cache_bios(); + break; + } + return -1; + } + + /* If the next instruction is a block entry point update the + cycle counter and update */ + if(block_data[block_data_position].update_cycles == 1) + { + generate_cycle_update(); + } + } + for(i = 0; i < translation_gate_targets; i++) + { + if(pc == translation_gate_target_pc[i]) + { + generate_translation_gate(thumb); + break; + } + } + + for(i = 0; i < block_exit_position; i++) + { + branch_target = block_exits[i].branch_target; + + if((branch_target >= block_start_pc) && (branch_target < block_end_pc)) + { + /* Internal branch, patch to recorded address */ + translation_target = + block_data[(branch_target - block_start_pc) / + thumb_instruction_width].block_offset; + + generate_branch_patch_unconditional(block_exits[i].branch_source, + translation_target); + } + else + { + /* External branch, save for later */ + external_block_exits[external_block_exit_position].branch_target = + branch_target; + external_block_exits[external_block_exit_position].branch_source = + block_exits[i].branch_source; + external_block_exit_position++; + } + } + + switch(translation_region) + { + case TRANSLATION_REGION_RAM: + if(pc >= 0x3000000) + { + if((pc > iwram_code_max) || (iwram_code_max == 0xFFFFFFFF)) + iwram_code_max = pc; + } + else + + if(pc >= 0x2000000) + { + if((pc > ewram_code_max) || (ewram_code_max == 0xFFFFFFFF)) + ewram_code_max = pc; + } + + ram_translation_ptr = translation_ptr; + break; + + case TRANSLATION_REGION_ROM: + rom_translation_ptr = translation_ptr; + break; + + case TRANSLATION_REGION_BIOS: + bios_translation_ptr = translation_ptr; + break; + } + + for(i = 0; i < external_block_exit_position; i++) + { + branch_target = external_block_exits[i].branch_target; + thumb_link_block(); + if(!translation_target){ + return -1; + } + generate_branch_patch_unconditional( + external_block_exits[i].branch_source, translation_target); + } return 0; } diff --git a/gba_memory.c b/gba_memory.c index 02b3e8b..2cb760a 100644 --- a/gba_memory.c +++ b/gba_memory.c @@ -311,9 +311,9 @@ u16 palette_ram_converted[512]; u16 io_registers[1024 * 16]; u8 ewram[1024 * 256 * 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; // 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); \ } \ -#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 u32 page_time = 0; @@ -3331,6 +3321,7 @@ void init_memory(void) // 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 // 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 // there's 32kb of blank stuff sitting beneath it. diff --git a/gba_memory.h b/gba_memory.h index f1243b5..3a79d6e 100644 --- a/gba_memory.h +++ b/gba_memory.h @@ -196,16 +196,16 @@ extern u32 gbc_sound_update; extern u32 gbc_sound_wave_update; extern dma_transfer_type dma[4]; +extern u32 bios_read_protect; extern u16 palette_ram[512]; extern u16 oam_ram[512]; extern u16 palette_ram_converted[512]; 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 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 u32 *reg; diff --git a/psp/mips_stub.S b/psp/mips_stub.S index d3324c1..7ca985c 100644 --- a/psp/mips_stub.S +++ b/psp/mips_stub.S @@ -2807,31 +2807,6 @@ ext_store_u32a_jtable: .long ext_store_ignore # 0x0D EEPROM (nothing will write this) .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: save_registers jal flush_translation_cache_ram # flush translation cache |