diff options
author | twinaphex | 2020-10-08 15:47:37 +0200 |
---|---|---|
committer | twinaphex | 2020-10-08 15:47:37 +0200 |
commit | 4181385f39113f8064b27ec9ff08b3a514afbdc3 (patch) | |
tree | b829abf506748ea59614145cb54a0cfa86d71e9b /arm | |
parent | 27419bc0b0d1ec35ff59485b7c803e4025820b82 (diff) | |
download | picogpsp-4181385f39113f8064b27ec9ff08b3a514afbdc3.tar.gz picogpsp-4181385f39113f8064b27ec9ff08b3a514afbdc3.tar.bz2 picogpsp-4181385f39113f8064b27ec9ff08b3a514afbdc3.zip |
Add forward declarations
Diffstat (limited to 'arm')
-rw-r--r-- | arm/arm_emit.h | 216 |
1 files changed, 111 insertions, 105 deletions
diff --git a/arm/arm_emit.h b/arm/arm_emit.h index c40d1ce..9c7057a 100644 --- a/arm/arm_emit.h +++ b/arm/arm_emit.h @@ -22,13 +22,17 @@ #include "arm_codegen.h" +void generate_indirect_branch_arm(void); +u32 prepare_load_reg_pc(u32 scratch_reg, u32 reg_index, u32 pc_offset); +void generate_store_reg(u32 ireg, u32 reg_index); + u32 arm_update_gba_arm(u32 pc); u32 arm_update_gba_thumb(u32 pc); u32 arm_update_gba_idle_arm(u32 pc); u32 arm_update_gba_idle_thumb(u32 pc); -// Although these are defined as a function, don't call them as -// such (jump to it instead) +/* Although these are defined as a function, don't call them as + * such (jump to it instead) */ void arm_indirect_branch_arm(u32 address); void arm_indirect_branch_thumb(u32 address); void arm_indirect_branch_dual_arm(u32 address); @@ -37,7 +41,7 @@ void arm_indirect_branch_dual_thumb(u32 address); void execute_store_cpsr(u32 new_cpsr, u32 store_mask, u32 address); u32 execute_store_cpsr_body(u32 _cpsr, u32 store_mask, u32 address); void execute_store_spsr(u32 new_cpsr, u32 store_mask); -u32 execute_read_spsr(); +u32 execute_read_spsr(void); u32 execute_spsr_restore(u32 address); void execute_swi_arm(u32 pc); @@ -53,8 +57,8 @@ void execute_store_u32_safe(u32 address, u32 source); (((((u32)offset - (u32)source) - 8) >> 2) & 0xFFFFFF) \ -// reg_base_offset is the amount of bytes after reg_base where the registers -// actually begin. +/* reg_base_offset is the amount of bytes after reg_base where the registers + * actually begin. */ #define reg_base_offset 1024 @@ -77,25 +81,26 @@ void execute_store_u32_safe(u32 address, u32 source); #define reg_rd ARMREG_R0 -// Register allocation layout for ARM and Thumb: -// Map from a GBA register to a host ARM register. -1 means load it -// from memory into one of the temp registers. +/* Register allocation layout for ARM and Thumb: + * Map from a GBA register to a host ARM register. -1 means load it + * from memory into one of the temp registers. -// The following registers are chosen based on statistical analysis -// of a few games (see below), but might not be the best ones. Results -// vary tremendously between ARM and Thumb (for obvious reasons), so -// two sets are used. Take care to not call any function which can -// overwrite any of these registers from the dynarec - only call -// trusted functions in arm_stub.S which know how to save/restore -// them and know how to transfer them to the C functions it calls -// if necessary. + * The following registers are chosen based on statistical analysis + * of a few games (see below), but might not be the best ones. Results + * vary tremendously between ARM and Thumb (for obvious reasons), so + * two sets are used. Take care to not call any function which can + * overwrite any of these registers from the dynarec - only call + * trusted functions in arm_stub.S which know how to save/restore + * them and know how to transfer them to the C functions it calls + * if necessary. -// The following define the actual registers available for allocation. -// As registers are freed up add them to this list. + * The following define the actual registers available for allocation. + * As registers are freed up add them to this list. -// Note that r15 is linked to the a0 temp reg - this register will -// be preloaded with a constant upon read, and used to link to -// indirect branch functions upon write. + * Note that r15 is linked to the a0 temp reg - this register will + * be preloaded with a constant upon read, and used to link to + * indirect branch functions upon write. + */ #define reg_x0 ARMREG_R3 #define reg_x1 ARMREG_R4 @@ -148,22 +153,22 @@ r15: 0.091287% (-- 100.000000%) s32 arm_register_allocation[] = { - reg_x0, // GBA r0 - reg_x1, // GBA r1 - mem_reg, // GBA r2 - mem_reg, // GBA r3 - mem_reg, // GBA r4 - mem_reg, // GBA r5 - reg_x2, // GBA r6 - mem_reg, // GBA r7 - mem_reg, // GBA r8 - reg_x3, // GBA r9 - mem_reg, // GBA r10 - mem_reg, // GBA r11 - reg_x4, // GBA r12 - mem_reg, // GBA r13 - reg_x5, // GBA r14 - reg_a0 // GBA r15 + reg_x0, /* GBA r0 */ + reg_x1, /* GBA r1 */ + mem_reg, /* GBA r2 */ + mem_reg, /* GBA r3 */ + mem_reg, /* GBA r4 */ + mem_reg, /* GBA r5 */ + reg_x2, /* GBA r6 */ + mem_reg, /* GBA r7 */ + mem_reg, /* GBA r8 */ + reg_x3, /* GBA r9 */ + mem_reg, /* GBA r10 */ + mem_reg, /* GBA r11 */ + reg_x4, /* GBA r12 */ + mem_reg, /* GBA r13 */ + reg_x5, /* GBA r14 */ + reg_a0 /* GBA r15 */ mem_reg, mem_reg, @@ -185,22 +190,22 @@ s32 arm_register_allocation[] = s32 thumb_register_allocation[] = { - reg_x0, // GBA r0 - reg_x1, // GBA r1 - reg_x2, // GBA r2 - reg_x3, // GBA r3 - reg_x4, // GBA r4 - reg_x5, // GBA r5 - mem_reg, // GBA r6 - mem_reg, // GBA r7 - mem_reg, // GBA r8 - mem_reg, // GBA r9 - mem_reg, // GBA r10 - mem_reg, // GBA r11 - mem_reg, // GBA r12 - mem_reg, // GBA r13 - mem_reg, // GBA r14 - reg_a0 // GBA r15 + reg_x0, /* GBA r0 */ + reg_x1, /* GBA r1 */ + reg_x2, /* GBA r2 */ + reg_x3, /* GBA r3 */ + reg_x4, /* GBA r4 */ + reg_x5, /* GBA r5 */ + mem_reg, /* GBA r6 */ + mem_reg, /* GBA r7 */ + mem_reg, /* GBA r8 */ + mem_reg, /* GBA r9 */ + mem_reg, /* GBA r10 */ + mem_reg, /* GBA r11 */ + mem_reg, /* GBA r12 */ + mem_reg, /* GBA r13 */ + mem_reg, /* GBA r14 */ + reg_a0 /* GBA r15 */ mem_reg, mem_reg, @@ -220,19 +225,16 @@ s32 thumb_register_allocation[] = mem_reg, }; - - #define arm_imm_lsl_to_rot(value) \ (32 - value) \ - u32 arm_disect_imm_32bit(u32 imm, u32 *stores, u32 *rotations) { u32 store_count = 0; u32 left_shift = 0; - // Otherwise it'll return 0 things to store because it'll never - // find anything. + /* Otherwise it'll return 0 things to store because it'll never + * find anything. */ if(imm == 0) { rotations[0] = 0; @@ -240,7 +242,7 @@ u32 arm_disect_imm_32bit(u32 imm, u32 *stores, u32 *rotations) return 1; } - // Find chunks of non-zero data at 2 bit alignments. + /* Find chunks of non-zero data at 2 bit alignments. */ while(1) { for(; left_shift < 32; left_shift += 2) @@ -249,20 +251,19 @@ u32 arm_disect_imm_32bit(u32 imm, u32 *stores, u32 *rotations) break; } + /* We've hit the end of the useful data. */ if(left_shift == 32) - { - // We've hit the end of the useful data. return store_count; - } - // Hit the end, it might wrap back around to the beginning. + /* Hit the end, it might wrap back around to the beginning. */ if(left_shift >= 24) { - // Make a mask for the residual bits. IE, if we have - // 5 bits of data at the end we can wrap around to 3 - // bits of data in the beginning. Thus the first - // thing, after being shifted left, has to be less - // than 111b, 0x7, or (1 << 3) - 1. + /* Make a mask for the residual bits. IE, if we have + * 5 bits of data at the end we can wrap around to 3 + * bits of data in the beginning. Thus the first + * thing, after being shifted left, has to be less + * than 111b, 0x7, or (1 << 3) - 1. + */ u32 top_bits = 32 - left_shift; u32 residual_bits = 8 - top_bits; u32 residual_mask = (1 << residual_bits) - 1; @@ -270,8 +271,8 @@ u32 arm_disect_imm_32bit(u32 imm, u32 *stores, u32 *rotations) if((store_count > 1) && (left_shift > 24) && ((stores[0] << ((32 - rotations[0]) & 0x1F)) < residual_mask)) { - // Then we can throw out the last bit and tack it on - // to the first bit. + /* Then we can throw out the last bit and tack it on + * to the first bit. */ stores[0] = (stores[0] << ((top_bits + (32 - rotations[0])) & 0x1F)) | ((imm >> left_shift) & 0xFF); @@ -281,7 +282,7 @@ u32 arm_disect_imm_32bit(u32 imm, u32 *stores, u32 *rotations) } else { - // There's nothing to wrap over to in the beginning + /* There's nothing to wrap over to in the beginning */ stores[store_count] = (imm >> left_shift) & 0xFF; rotations[store_count] = (32 - left_shift) & 0x1F; return store_count + 1; @@ -372,7 +373,7 @@ u32 arm_disect_imm_32bit(u32 imm, u32 *stores, u32 *rotations) #define generate_exit_block() \ ARM_BX(0, ARMREG_LR) \ -// The branch target is to be filled in later (thus a 0 for now) +/* The branch target is to be filled in later (thus a 0 for now) */ #define generate_branch_filler(condition_code, writeback_location) \ (writeback_location) = translation_ptr; \ @@ -412,9 +413,10 @@ u32 arm_disect_imm_32bit(u32 imm, u32 *stores, u32 *rotations) *((u32 *)(dest)) = (*((u32 *)dest) & 0xFF000000) | \ arm_relative_offset(dest, offset) \ -// A different function is called for idle updates because of the relative -// location of the embedded PC. The idle version could be optimized to put -// the CPU into halt mode too, however. +/* A different function is called for idle updates because of the relative + * location of the embedded PC. The idle version could be optimized to put + * the CPU into halt mode too, however. + */ #define generate_branch_idle_eliminate(writeback_location, new_pc, mode) \ generate_function_call(arm_update_gba_idle_##mode); \ @@ -443,7 +445,7 @@ u32 arm_disect_imm_32bit(u32 imm, u32 *stores, u32 *rotations) generate_cycle_update(); \ generate_branch_no_cycle_update(writeback_location, new_pc, mode) \ -// a0 holds the destination +/* a0 holds the destination */ #define generate_indirect_branch_no_cycle_update(type) \ ARM_B(0, arm_relative_offset(translation_ptr, arm_indirect_branch_##type)) \ @@ -455,7 +457,7 @@ u32 arm_disect_imm_32bit(u32 imm, u32 *stores, u32 *rotations) #define generate_block_prologue() \ #define generate_block_extra_vars_arm() \ - void generate_indirect_branch_arm() \ + void generate_indirect_branch_arm(void) \ { \ if(condition == 0x0E) \ { \ @@ -639,9 +641,10 @@ u32 arm_disect_imm_32bit(u32 imm, u32 *stores, u32 *rotations) #define block_prologue_size 0 -// It should be okay to still generate result flags, spsr will overwrite them. -// This is pretty infrequent (returning from interrupt handlers, et al) so -// probably not worth optimizing for. +/* It should be okay to still generate result flags, spsr will overwrite them. + * This is pretty infrequent (returning from interrupt handlers, et al) so + * probably not worth optimizing for. + */ #define check_for_interrupts() \ if((io_registers[REG_IE] & io_registers[REG_IF]) && \ @@ -927,9 +930,10 @@ u32 execute_spsr_restore_body(u32 pc) #define generate_op_mvns_reg_immshift(_rd, _rn, _rm, shift_type, shift) \ generate_op_reg_immshift_uflags(MVNS, _rd, _rm, shift_type, shift) \ -// The reg operand is in reg_rm, not reg_rn like expected, so rsbs isn't -// being used here. When rsbs is fully inlined it can be used with the -// apropriate operands. +/* The reg operand is in reg_rm, not reg_rn like expected, so rsbs isn't + * being used here. When rsbs is fully inlined it can be used with the + * apropriate operands. + */ #define generate_op_neg_reg_immshift(_rd, _rn, _rm, shift_type, shift) \ { \ @@ -1092,7 +1096,7 @@ u32 execute_spsr_restore_body(u32 pc) #define arm_generate_op_reg_flags(name, load_op, store_op, flags_op) \ arm_generate_op_reg(name, load_op, store_op, flags_op) \ -// imm will be loaded by the called function if necessary. +/* imm will be loaded by the called function if necessary. */ #define arm_generate_op_imm(name, load_op, store_op, flags_op) \ arm_decode_data_proc_imm(opcode); \ @@ -1203,8 +1207,9 @@ u32 execute_spsr_restore_body(u32 pc) #define arm_psr_read(op_type, psr_reg) \ arm_psr_read_##psr_reg() \ -// This function's okay because it's called from an ASM function that can -// wrap it correctly. +/* This function's okay because it's called from an ASM function that can + * wrap it correctly. + */ u32 execute_store_cpsr_body(u32 _cpsr, u32 store_mask, u32 address) { @@ -1251,9 +1256,10 @@ u32 execute_store_cpsr_body(u32 _cpsr, u32 store_mask, u32 address) arm_psr_##transfer_type(op_type, psr_reg); \ } \ -// TODO: loads will need the PC passed as well for open address, however can -// eventually be rectified with a hash table on the memory accesses -// (same with the stores) +/* TODO: loads will need the PC passed as well for open address, however can + * eventually be rectified with a hash table on the memory accesses + * (same with the stores) + */ #define arm_access_memory_load(mem_type) \ cycle_count += 2; \ @@ -1267,7 +1273,7 @@ u32 execute_store_cpsr_body(u32 _cpsr, u32 store_mask, u32 address) generate_function_call(execute_store_##mem_type); \ write32((pc + 4)) \ -// Calculate the address into a0 from _rn, _rm +/* Calculate the address into a0 from _rn, _rm */ #define arm_access_memory_adjust_reg_sh_up(ireg) \ ARM_ADD_REG_IMMSHIFT(0, ireg, _rn, _rm, ((opcode >> 5) & 0x03), \ @@ -1365,7 +1371,7 @@ u32 execute_store_cpsr_body(u32 _cpsr, u32 store_mask, u32 address) printf("sbit on %s %s %s %s\n", #access_type, #pre_op, #post_op, #wb) \ -// TODO: Make these use cached registers. Implement iwram_stack_optimize. +/* TODO: Make these use cached registers. Implement iwram_stack_optimize. */ #define arm_block_memory_load() \ generate_function_call(execute_load_u32); \ @@ -1416,7 +1422,7 @@ u32 execute_store_cpsr_body(u32 _cpsr, u32 store_mask, u32 address) #define arm_block_memory_writeback_no() -// Only emit writeback if the register is not in the list +/* Only emit writeback if the register is not in the list */ #define arm_block_memory_writeback_load(writeback_type) \ if(!((reg_list >> rn) & 0x01)) \ @@ -1625,7 +1631,7 @@ u32 execute_store_cpsr_body(u32 _cpsr, u32 store_mask, u32 address) complete_store_reg(__rd, rd); \ } \ -// Operation types: imm, mem_reg, mem_imm +/* Operation types: imm, mem_reg, mem_imm */ #define thumb_access_memory_load(mem_type, _rd) \ cycle_count += 2; \ @@ -1663,7 +1669,7 @@ u32 execute_store_cpsr_body(u32 _cpsr, u32 store_mask, u32 address) thumb_access_memory_##access_type(mem_type, _rd); \ } \ -// TODO: Make these use cached registers. Implement iwram_stack_optimize. +/* TODO: Make these use cached registers. Implement iwram_stack_optimize. */ #define thumb_block_address_preadjust_up() \ generate_add_imm(reg_s0, (bit_count[reg_list] * 4), 0) \ @@ -1898,19 +1904,19 @@ u8 swi_hle_handle[256] = 0x0 // SWI 2A: SoundGetJumpList }; -void execute_swi_hle_div_arm(); -void execute_swi_hle_div_thumb(); +void execute_swi_hle_div_arm(void); +void execute_swi_hle_div_thumb(void); -void execute_swi_hle_div_c() +void execute_swi_hle_div_c(void) { - if (reg[1] == 0) - // real BIOS supposedly locks up, but game can recover on interrupt - return; - s32 result = (s32)reg[0] / (s32)reg[1]; - reg[1] = (s32)reg[0] % (s32)reg[1]; - reg[0] = result; - - reg[3] = (result ^ (result >> 31)) - (result >> 31); + /* real BIOS supposedly locks up, but game can recover on interrupt */ + if (reg[1] == 0) + return; + s32 result = (s32)reg[0] / (s32)reg[1]; + reg[1] = (s32)reg[0] % (s32)reg[1]; + reg[0] = result; + + reg[3] = (result ^ (result >> 31)) - (result >> 31); } #define generate_swi_hle_handler(_swi_number, mode) \ |