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