Demacro-ize block_builder_arm/block_builder_thumb

This commit is contained in:
twinaphex 2014-12-10 01:25:37 +01:00
parent fe19474dca
commit 1a8b77c185
1 changed files with 434 additions and 220 deletions

View File

@ -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();
translate_block_builder(arm);
translate_block_builder(thumb);
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;
}
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()
{