summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortwinaphex2014-12-10 01:25:37 +0100
committertwinaphex2014-12-10 01:25:37 +0100
commit1a8b77c1850db3fb4545c55adb07dbf1e7584dbf (patch)
treea464791b9845e9cfb3aa18d99a028e6e1d7bbbc2
parentfe19474dca84b5d00570e3fb5a04c8a359615f70 (diff)
downloadpicogpsp-1a8b77c1850db3fb4545c55adb07dbf1e7584dbf.tar.gz
picogpsp-1a8b77c1850db3fb4545c55adb07dbf1e7584dbf.tar.bz2
picogpsp-1a8b77c1850db3fb4545c55adb07dbf1e7584dbf.zip
Demacro-ize block_builder_arm/block_builder_thumb
-rw-r--r--cpu_threaded.c654
1 files changed, 434 insertions, 220 deletions
diff --git a/cpu_threaded.c b/cpu_threaded.c
index 0c4e924..30abec3 100644
--- a/cpu_threaded.c
+++ b/cpu_threaded.c
@@ -3182,227 +3182,441 @@ block_exit_type block_exits[MAX_EXITS];
#define thumb_fix_pc() \
pc &= ~0x01 \
-#define translate_block_builder(type) \
-s32 translate_block_##type(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_##type(); \
- type##_fix_pc(); \
- \
- if(pc_address_block == NULL) \
- 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(type, yes); \
- } \
- else \
- { \
- scan_block(type, 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) / \
- type##_instruction_width].update_cycles = 1; \
- } \
- } \
- \
- type##_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; \
- type##_base_cycles(); \
- /*generate_step_debug();*/ \
- \
- translate_##type##_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(type); \
- 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) / \
- type##_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; \
- type##_link_block(); \
- if(translation_target == NULL) \
- return -1; \
- generate_branch_patch_unconditional( \
- external_block_exits[i].branch_source, translation_target); \
- } \
- \
- return 0; \
-} \
+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 == NULL)
+ 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();
+ /*generate_step_debug();*/
+
+ 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 == NULL)
+ return -1;
+ generate_branch_patch_unconditional(
+ external_block_exits[i].branch_source, translation_target);
+ }
+
+ return 0;
+}
-translate_block_builder(arm);
-translate_block_builder(thumb);
+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 == NULL)
+ 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();
+ /*generate_step_debug();*/
+
+ 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 == NULL)
+ return -1;
+ generate_branch_patch_unconditional(
+ external_block_exits[i].branch_source, translation_target);
+ }
+
+ return 0;
+}
void flush_translation_cache_ram()
{