Better cycle accounting, taking remainders partially into account
This commit is contained in:
parent
7b181cb6ff
commit
3a6ca8d941
|
@ -259,6 +259,7 @@ u32 arm_to_a64_reg[] =
|
|||
#define generate_branch_no_cycle_update(writeback_location, new_pc) \
|
||||
if(pc == idle_loop_target_pc) \
|
||||
{ \
|
||||
generate_load_imm(reg_cycles, 0); \
|
||||
generate_load_pc(reg_a0, new_pc); \
|
||||
generate_function_call(a64_update_gba); \
|
||||
emit_branch_filler(writeback_location); \
|
||||
|
|
|
@ -149,6 +149,7 @@ defsymbl(a64_update_gba)
|
|||
consolidate_flags(w0) // update the CPSR
|
||||
store_registers() // save out registers
|
||||
|
||||
mov w0, reg_cycles // load remaining cycles
|
||||
bl update_gba // update GBA state
|
||||
|
||||
ldr w1, [reg_base, #COMPLETED_FRAME] // return to main if new frame
|
||||
|
@ -682,7 +683,9 @@ write_epilogue:
|
|||
beq smc_write // if so, goto SMC handler
|
||||
|
||||
alert_loop:
|
||||
mov w0, reg_cycles // load remaining cycles
|
||||
bl update_gba // update GBA until CPU isn't halted
|
||||
mov reg_cycles, w0 // load new cycle count
|
||||
|
||||
ldr w1, [reg_base, #COMPLETED_FRAME] // Check whether a frame was completed
|
||||
cbnz w1, return_to_main // and return to caller function.
|
||||
|
@ -690,7 +693,6 @@ alert_loop:
|
|||
ldr w1, [reg_base, #CPU_HALT_STATE] // Check whether the CPU is halted
|
||||
cbnz w1, alert_loop // and keep looping until it is
|
||||
|
||||
mov reg_cycles, w0 // load new cycle count
|
||||
ldr w0, [reg_base, #REG_PC] // load new PC
|
||||
b lookup_pc // Resume execution at that PC
|
||||
|
||||
|
|
|
@ -163,18 +163,14 @@ _##symbol:
|
|||
@ Input:
|
||||
@ r0: current PC
|
||||
|
||||
#define return_straight() ;\
|
||||
bx lr ;\
|
||||
#define return_straight() bx lr
|
||||
#define return_add() add pc, lr, #4
|
||||
|
||||
#define return_add() ;\
|
||||
add pc, lr, #4 ;\
|
||||
|
||||
#define load_pc_straight() ;\
|
||||
ldr r0, [lr, #-12] ;\
|
||||
|
||||
#define load_pc_add() ;\
|
||||
ldr r0, [lr] ;\
|
||||
#define load_pc_straight() ldr r0, [lr, #-12]
|
||||
#define load_pc_add() ldr r0, [lr]
|
||||
|
||||
#define cycles_straight() mvn r0, reg_cycles
|
||||
#define cycles_add() mov r0, #0
|
||||
|
||||
#define arm_update_gba_builder(name, mode, return_op) ;\
|
||||
;\
|
||||
|
@ -186,6 +182,7 @@ defsymbl(arm_update_gba_##name) ;\
|
|||
collapse_flags(r0) /* update the flags */;\
|
||||
;\
|
||||
store_registers_##mode() /* save out registers */;\
|
||||
cycles_##return_op() /* remaining cycles in arg0 */;\
|
||||
call_c_function(update_gba) /* update GBA state */;\
|
||||
;\
|
||||
ldr r1, [reg_base, #COMPLETED_FRAME] /* return if new frame */;\
|
||||
|
|
8
cpu.c
8
cpu.c
|
@ -1635,7 +1635,7 @@ void execute_arm(u32 cycles)
|
|||
{
|
||||
/* Do not execute until CPU is active */
|
||||
while(reg[CPU_HALT_STATE] != CPU_ACTIVE) {
|
||||
cycles_remaining = update_gba();
|
||||
cycles_remaining = update_gba(cycles_remaining);
|
||||
|
||||
if (reg[COMPLETED_FRAME])
|
||||
return;
|
||||
|
@ -3225,7 +3225,7 @@ skip_instruction:
|
|||
} while(cycles_remaining > 0);
|
||||
|
||||
collapse_flags();
|
||||
cycles_remaining = update_gba();
|
||||
cycles_remaining = update_gba(cycles_remaining);
|
||||
if (reg[COMPLETED_FRAME])
|
||||
return;
|
||||
continue;
|
||||
|
@ -3738,7 +3738,7 @@ thumb_loop:
|
|||
} while(cycles_remaining > 0);
|
||||
|
||||
collapse_flags();
|
||||
cycles_remaining = update_gba();
|
||||
cycles_remaining = update_gba(cycles_remaining);
|
||||
if (reg[COMPLETED_FRAME])
|
||||
return;
|
||||
continue;
|
||||
|
@ -3749,7 +3749,7 @@ thumb_loop:
|
|||
collapse_flags();
|
||||
|
||||
while(reg[CPU_HALT_STATE] != CPU_ACTIVE) {
|
||||
cycles_remaining = update_gba();
|
||||
cycles_remaining = update_gba(cycles_remaining);
|
||||
if (reg[COMPLETED_FRAME])
|
||||
return;
|
||||
}
|
||||
|
|
19
main.c
19
main.c
|
@ -39,7 +39,7 @@ char save_path[512];
|
|||
|
||||
void trigger_ext_event(void);
|
||||
|
||||
static void update_timers(irq_type *irq_raised)
|
||||
static void update_timers(irq_type *irq_raised, unsigned completed_cycles)
|
||||
{
|
||||
unsigned i;
|
||||
for (i = 0; i < 4; i++)
|
||||
|
@ -49,7 +49,7 @@ static void update_timers(irq_type *irq_raised)
|
|||
|
||||
if(timer[i].status != TIMER_CASCADE)
|
||||
{
|
||||
timer[i].count -= execute_cycles;
|
||||
timer[i].count -= completed_cycles;
|
||||
/* io_registers accessors range: REG_TM0D, REG_TM1D, REG_TM2D, REG_TM3D */
|
||||
write_ioreg(REG_TM0D + (i * 2), -(timer[i].count > timer[i].prescale));
|
||||
}
|
||||
|
@ -106,15 +106,20 @@ void init_main(void)
|
|||
#endif
|
||||
}
|
||||
|
||||
u32 update_gba(void)
|
||||
u32 update_gba(int remaining_cycles)
|
||||
{
|
||||
irq_type irq_raised = IRQ_NONE;
|
||||
remaining_cycles = MAX(remaining_cycles, -64);
|
||||
|
||||
do
|
||||
{
|
||||
unsigned i;
|
||||
cpu_ticks += execute_cycles;
|
||||
// Number of cycles we ask to run - cycles that we did not execute
|
||||
// (remaining_cycles can be negative and should be close to zero)
|
||||
unsigned completed_cycles = execute_cycles - remaining_cycles;
|
||||
cpu_ticks += completed_cycles;
|
||||
|
||||
remaining_cycles = 0;
|
||||
reg[CHANGED_PC_STATUS] = 0;
|
||||
reg[COMPLETED_FRAME] = 0;
|
||||
|
||||
|
@ -125,9 +130,9 @@ u32 update_gba(void)
|
|||
gbc_sound_update = 0;
|
||||
}
|
||||
|
||||
update_timers(&irq_raised);
|
||||
update_timers(&irq_raised, completed_cycles);
|
||||
|
||||
video_count -= execute_cycles;
|
||||
video_count -= completed_cycles;
|
||||
|
||||
if(video_count <= 0)
|
||||
{
|
||||
|
@ -235,7 +240,7 @@ u32 update_gba(void)
|
|||
if(irq_raised)
|
||||
raise_interrupt(irq_raised);
|
||||
|
||||
execute_cycles = video_count;
|
||||
execute_cycles = MAX(video_count, 0);
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
|
|
2
main.h
2
main.h
|
@ -76,7 +76,7 @@ extern u32 flush_ram_count;
|
|||
extern char main_path[512];
|
||||
extern char save_path[512];
|
||||
|
||||
u32 update_gba(void);
|
||||
u32 update_gba(int remaining_cycles);
|
||||
void reset_gba(void);
|
||||
|
||||
void init_main(void);
|
||||
|
|
|
@ -231,6 +231,7 @@ u32 arm_to_mips_reg[] =
|
|||
if(pc == idle_loop_target_pc) \
|
||||
{ \
|
||||
generate_load_pc(reg_a0, new_pc); \
|
||||
mips_emit_lui(reg_cycles, 0); \
|
||||
generate_function_call_swap_delay(mips_update_gba); \
|
||||
mips_emit_j_filler(writeback_location); \
|
||||
mips_emit_nop(); \
|
||||
|
|
|
@ -119,6 +119,8 @@ symbol:
|
|||
.equ FNPTRS_MEMOPS, (REGMODE_BASE + 196)
|
||||
.equ FNPTRS_BASE, (FNPTRS_MEMOPS + 960*2)
|
||||
|
||||
#define reg_cycles $17
|
||||
|
||||
.set noat
|
||||
.set noreorder
|
||||
|
||||
|
@ -240,12 +242,13 @@ defsymbl(mips_update_gba)
|
|||
collapse_flags # update cpsr
|
||||
save_registers # save registers
|
||||
sw $0, CHANGED_PC_STATUS($16)
|
||||
move $4, reg_cycles # Remaining cycles as asg0
|
||||
cfncall update_gba, 0 # process the next event
|
||||
|
||||
lw $1, COMPLETED_FRAME($16) # Check whether we completed a frame
|
||||
bne $1, $0, return_to_main # Return to main thread now
|
||||
|
||||
addu $17, $2, $0 # $17 = new cycle count (ret value)
|
||||
move reg_cycles, $2 # update new cycle count (ret value)
|
||||
|
||||
lw $ra, REG_SAVE2($16) # restore return address
|
||||
|
||||
|
@ -327,7 +330,9 @@ defsymbl(write_io_epilogue)
|
|||
|
||||
|
||||
alert_loop:
|
||||
move $4, reg_cycles # Remaining cycles as asg0
|
||||
cfncall update_gba, 0 # process the next event
|
||||
move reg_cycles, $2 # update new cycle count (ret value)
|
||||
|
||||
lw $1, COMPLETED_FRAME($16) # Check whether we completed a frame
|
||||
bne $1, $0, return_to_main # Return to main thread now
|
||||
|
@ -336,7 +341,6 @@ alert_loop:
|
|||
bne $1, $0, alert_loop # see if it hasn't changed
|
||||
nop
|
||||
|
||||
addu $17, $2, $0 # $17 = new cycle counter
|
||||
lw $4, REG_PC($16) # $4 = new PC
|
||||
|
||||
j lookup_pc
|
||||
|
@ -522,7 +526,7 @@ defsymbl(execute_arm_translate_internal)
|
|||
move $16, $5
|
||||
REG_S $28, GP_SAVE($16)
|
||||
|
||||
addu $17, $4, $0 # load cycle counter register
|
||||
move reg_cycles, $4 # load cycle counter register
|
||||
|
||||
extract_flags # load flag variables
|
||||
|
||||
|
|
|
@ -585,6 +585,7 @@ typedef enum
|
|||
#define generate_branch_no_cycle_update(writeback_location, new_pc) \
|
||||
if(pc == idle_loop_target_pc) \
|
||||
{ \
|
||||
generate_load_imm(cycles, 0); \
|
||||
x86_emit_mov_reg_imm(eax, new_pc); \
|
||||
generate_function_call(x86_update_gba); \
|
||||
x86_emit_jmp_filler(writeback_location); \
|
||||
|
|
|
@ -166,8 +166,8 @@ defsymbl(x86_update_gba)
|
|||
mov %eax, REG_PC(REG_BASE) # current PC = eax
|
||||
collapse_flags # update cpsr, trashes ecx and edx
|
||||
|
||||
mov REG_CYCLES, CARG1_REG # Load remaining cycles as arg0
|
||||
CALL_FUNC(update_gba) # process the next event
|
||||
|
||||
mov %eax, REG_CYCLES # new cycle count
|
||||
|
||||
# did we just complete a frame? go back to main then
|
||||
|
@ -246,7 +246,9 @@ write_epilogue:
|
|||
je smc_write
|
||||
|
||||
alert_loop:
|
||||
mov REG_CYCLES, CARG1_REG # Load remaining cycles as arg0
|
||||
CALL_FUNC(update_gba) # process the next event
|
||||
mov %eax, REG_CYCLES # load new cycle count
|
||||
|
||||
# did we just complete a frame? go back to main then
|
||||
cmpl $0, COMPLETED_FRAME(REG_BASE)
|
||||
|
@ -258,7 +260,6 @@ alert_loop:
|
|||
cmp $0, %edx # 0 means it has
|
||||
jnz alert_loop # if not go again
|
||||
|
||||
mov %eax, REG_CYCLES # load new cycle count
|
||||
jmp lookup_pc # pc has definitely changed
|
||||
|
||||
no_alert:
|
||||
|
|
Loading…
Reference in New Issue