Remove COMPLETED_FRAME flag to simplify things
This commit is contained in:
parent
5f3e0a88cf
commit
1d1c719372
9 changed files with 53 additions and 51 deletions
|
@ -57,7 +57,7 @@ _##symbol:
|
||||||
#define REG_Z_FLAG (21 * 4)
|
#define REG_Z_FLAG (21 * 4)
|
||||||
#define REG_C_FLAG (22 * 4)
|
#define REG_C_FLAG (22 * 4)
|
||||||
#define REG_V_FLAG (23 * 4)
|
#define REG_V_FLAG (23 * 4)
|
||||||
#define COMPLETED_FRAME (24 * 4)
|
#define REG_UNUSED_1 (24 * 4)
|
||||||
#define OAM_UPDATED (25 * 4)
|
#define OAM_UPDATED (25 * 4)
|
||||||
#define REG_SAVE (26 * 4)
|
#define REG_SAVE (26 * 4)
|
||||||
|
|
||||||
|
@ -153,14 +153,13 @@ defsymbl(a64_update_gba)
|
||||||
mov w0, reg_cycles // load remaining cycles
|
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
|
tbnz w0, #31, return_to_main // exit if a new frame is ready
|
||||||
cbnz w1, return_to_main
|
|
||||||
|
|
||||||
// Resume execution (perhaps from a new PC)
|
// Resume execution (perhaps from a new PC)
|
||||||
and reg_cycles, w0, 0x7fff // load new cycle count
|
and reg_cycles, w0, 0x7fff // load new cycle count
|
||||||
extract_flags(w2) // reload flag cache bits
|
extract_flags(w2) // reload flag cache bits
|
||||||
|
|
||||||
tbnz w0, #31, 1f // check if PC changed
|
tbnz w0, #30, 1f // check if PC changed
|
||||||
|
|
||||||
ldr lr, [reg_base, #REG_SAVE] // Restore return point
|
ldr lr, [reg_base, #REG_SAVE] // Restore return point
|
||||||
load_registers() // reload registers
|
load_registers() // reload registers
|
||||||
|
@ -714,8 +713,7 @@ cpu_sleep_loop:
|
||||||
mov w0, reg_cycles // load remaining cycles
|
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
|
||||||
|
|
||||||
ldr w1, [reg_base, #COMPLETED_FRAME] // Check whether a frame was completed
|
tbnz w0, #31, return_to_main // a frame has been completed -> exit
|
||||||
cbnz w1, return_to_main // and return to caller function.
|
|
||||||
|
|
||||||
// At this point the CPU must be active, otherwise we sping in update_gba
|
// At this point the CPU must be active, otherwise we sping in update_gba
|
||||||
|
|
||||||
|
|
|
@ -39,7 +39,7 @@ _##symbol:
|
||||||
#define REG_Z_FLAG (21 * 4)
|
#define REG_Z_FLAG (21 * 4)
|
||||||
#define REG_C_FLAG (22 * 4)
|
#define REG_C_FLAG (22 * 4)
|
||||||
#define REG_V_FLAG (23 * 4)
|
#define REG_V_FLAG (23 * 4)
|
||||||
#define COMPLETED_FRAME (24 * 4)
|
#define REG_UNUSED_1 (24 * 4)
|
||||||
#define OAM_UPDATED (25 * 4)
|
#define OAM_UPDATED (25 * 4)
|
||||||
|
|
||||||
#define CPU_ALERT_HALT (1 << 0)
|
#define CPU_ALERT_HALT (1 << 0)
|
||||||
|
@ -195,14 +195,13 @@ defsymbl(arm_update_gba_##name) ;\
|
||||||
cycles_##return_op() /* remaining cycles in arg0 */;\
|
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 */;\
|
cmp r0, #0 /* check MSB for frame completion*/;\
|
||||||
cmp r1, #0 ;\
|
blt return_to_main ;\
|
||||||
bne return_to_main ;\
|
|
||||||
;\
|
;\
|
||||||
bic reg_cycles, r0, #0x80000000 /* clear MSB, not part of count */;\
|
bic reg_cycles, r0, #0xF0000000 /* clear MSB, not part of count */;\
|
||||||
mvn reg_cycles, reg_cycles /* we count negative to zero */;\
|
mvn reg_cycles, reg_cycles /* we count negative to zero */;\
|
||||||
;\
|
;\
|
||||||
tst r0, #0x80000000 /* set if PC changed */;\
|
tst r0, #0x40000000 /* set if PC changed */;\
|
||||||
bne 1f /* go jump/translate */;\
|
bne 1f /* go jump/translate */;\
|
||||||
;\
|
;\
|
||||||
load_registers_##mode() /* reload registers */;\
|
load_registers_##mode() /* reload registers */;\
|
||||||
|
@ -698,11 +697,11 @@ write_epilogue:
|
||||||
|
|
||||||
cpu_sleep_loop:
|
cpu_sleep_loop:
|
||||||
call_c_function(update_gba) @ update GBA until CPU isn't halted
|
call_c_function(update_gba) @ update GBA until CPU isn't halted
|
||||||
bic r0, r0, #0x80000000 @ clear MSB, not part of count
|
|
||||||
|
|
||||||
ldr r1, [reg_base, #COMPLETED_FRAME] @ Check whether a frame was completed
|
cmp r0, #0
|
||||||
cmp r1, #0
|
blt return_to_main @ New frame if bit 31 is set. Exit
|
||||||
bne return_to_main
|
|
||||||
|
bic r0, r0, #0xF0000000 @ clear MSB, not part of count
|
||||||
|
|
||||||
@ The cpu is active again, go ahead and resume execution at current PC
|
@ The cpu is active again, go ahead and resume execution at current PC
|
||||||
mvn reg_cycles, r0 @ load new cycle count
|
mvn reg_cycles, r0 @ load new cycle count
|
||||||
|
|
22
cpu.c
22
cpu.c
|
@ -1535,6 +1535,7 @@ void execute_arm(u32 cycles)
|
||||||
u8 *pc_address_block = memory_map_read[pc_region];
|
u8 *pc_address_block = memory_map_read[pc_region];
|
||||||
u32 new_pc_region;
|
u32 new_pc_region;
|
||||||
s32 cycles_remaining;
|
s32 cycles_remaining;
|
||||||
|
u32 update_ret;
|
||||||
cpu_alert_type cpu_alert;
|
cpu_alert_type cpu_alert;
|
||||||
|
|
||||||
u32 old_pc;
|
u32 old_pc;
|
||||||
|
@ -1549,11 +1550,12 @@ void execute_arm(u32 cycles)
|
||||||
while(1)
|
while(1)
|
||||||
{
|
{
|
||||||
/* Do not execute until CPU is active */
|
/* Do not execute until CPU is active */
|
||||||
while(reg[CPU_HALT_STATE] != CPU_ACTIVE) {
|
if (reg[CPU_HALT_STATE] != CPU_ACTIVE) {
|
||||||
cycles_remaining = update_gba_cycles(cycles_remaining);
|
u32 ret = update_gba(cycles_remaining);
|
||||||
|
if (completed_frame(ret))
|
||||||
if (reg[COMPLETED_FRAME])
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
cycles_remaining = cycles_to_run(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
cpu_alert = CPU_ALERT_NONE;
|
cpu_alert = CPU_ALERT_NONE;
|
||||||
|
@ -3146,9 +3148,10 @@ skip_instruction:
|
||||||
} while(cycles_remaining > 0);
|
} while(cycles_remaining > 0);
|
||||||
|
|
||||||
collapse_flags();
|
collapse_flags();
|
||||||
cycles_remaining = update_gba_cycles(cycles_remaining);
|
update_ret = update_gba(cycles_remaining);
|
||||||
if (reg[COMPLETED_FRAME])
|
if (completed_frame(update_ret))
|
||||||
return;
|
return;
|
||||||
|
cycles_remaining = cycles_to_run(update_ret);
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
do
|
do
|
||||||
|
@ -3665,9 +3668,10 @@ thumb_loop:
|
||||||
} while(cycles_remaining > 0);
|
} while(cycles_remaining > 0);
|
||||||
|
|
||||||
collapse_flags();
|
collapse_flags();
|
||||||
cycles_remaining = update_gba_cycles(cycles_remaining);
|
update_ret = update_gba(cycles_remaining);
|
||||||
if (reg[COMPLETED_FRAME])
|
if (completed_frame(update_ret))
|
||||||
return;
|
return;
|
||||||
|
cycles_remaining = cycles_to_run(update_ret);
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
alert:
|
alert:
|
||||||
|
|
2
cpu.h
2
cpu.h
|
@ -91,7 +91,7 @@ typedef enum
|
||||||
REG_Z_FLAG = 21,
|
REG_Z_FLAG = 21,
|
||||||
REG_C_FLAG = 22,
|
REG_C_FLAG = 22,
|
||||||
REG_V_FLAG = 23,
|
REG_V_FLAG = 23,
|
||||||
COMPLETED_FRAME = 24,
|
REG_UNUSED_1 = 24,
|
||||||
OAM_UPDATED = 25,
|
OAM_UPDATED = 25,
|
||||||
REG_SAVE = 26,
|
REG_SAVE = 26,
|
||||||
REG_SAVE2 = 27,
|
REG_SAVE2 = 27,
|
||||||
|
|
10
main.c
10
main.c
|
@ -107,6 +107,7 @@ void init_main(void)
|
||||||
u32 function_cc update_gba(int remaining_cycles)
|
u32 function_cc update_gba(int remaining_cycles)
|
||||||
{
|
{
|
||||||
u32 changed_pc = 0;
|
u32 changed_pc = 0;
|
||||||
|
u32 frame_complete = 0;
|
||||||
irq_type irq_raised = IRQ_NONE;
|
irq_type irq_raised = IRQ_NONE;
|
||||||
int dma_cycles;
|
int dma_cycles;
|
||||||
trace_update_gba(remaining_cycles);
|
trace_update_gba(remaining_cycles);
|
||||||
|
@ -122,7 +123,6 @@ u32 function_cc update_gba(int remaining_cycles)
|
||||||
cpu_ticks += completed_cycles;
|
cpu_ticks += completed_cycles;
|
||||||
|
|
||||||
remaining_cycles = 0;
|
remaining_cycles = 0;
|
||||||
reg[COMPLETED_FRAME] = 0;
|
|
||||||
|
|
||||||
// Timers can trigger DMA (usually sound) and consume cycles
|
// Timers can trigger DMA (usually sound) and consume cycles
|
||||||
dma_cycles = update_timers(&irq_raised, completed_cycles);
|
dma_cycles = update_timers(&irq_raised, completed_cycles);
|
||||||
|
@ -217,7 +217,7 @@ u32 function_cc update_gba(int remaining_cycles)
|
||||||
render_gbc_sound();
|
render_gbc_sound();
|
||||||
|
|
||||||
// We completed a frame, tell the dynarec to exit to the main thread
|
// We completed a frame, tell the dynarec to exit to the main thread
|
||||||
reg[COMPLETED_FRAME] = 1;
|
frame_complete = 0x80000000;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Vcount trigger (flag) and IRQ if enabled
|
// Vcount trigger (flag) and IRQ if enabled
|
||||||
|
@ -241,7 +241,7 @@ u32 function_cc update_gba(int remaining_cycles)
|
||||||
|
|
||||||
// Raise any pending interrupts. This changes the CPU mode.
|
// Raise any pending interrupts. This changes the CPU mode.
|
||||||
if (check_and_raise_interrupts())
|
if (check_and_raise_interrupts())
|
||||||
changed_pc = 0x80000000;
|
changed_pc = 0x40000000;
|
||||||
|
|
||||||
// Figure out when we need to stop CPU execution. The next event is
|
// Figure out when we need to stop CPU execution. The next event is
|
||||||
// a video event or a timer event, whatever happens first.
|
// a video event or a timer event, whatever happens first.
|
||||||
|
@ -253,13 +253,13 @@ u32 function_cc update_gba(int remaining_cycles)
|
||||||
timer[i].count < execute_cycles)
|
timer[i].count < execute_cycles)
|
||||||
execute_cycles = timer[i].count;
|
execute_cycles = timer[i].count;
|
||||||
}
|
}
|
||||||
} while(reg[CPU_HALT_STATE] != CPU_ACTIVE && !reg[COMPLETED_FRAME]);
|
} while(reg[CPU_HALT_STATE] != CPU_ACTIVE && !frame_complete);
|
||||||
|
|
||||||
// We voluntarily limit this. It is not accurate but it would be much harder.
|
// We voluntarily limit this. It is not accurate but it would be much harder.
|
||||||
dma_cycles = MIN(64, dma_cycles);
|
dma_cycles = MIN(64, dma_cycles);
|
||||||
dma_cycles = MIN(execute_cycles, dma_cycles);
|
dma_cycles = MIN(execute_cycles, dma_cycles);
|
||||||
|
|
||||||
return (execute_cycles - dma_cycles) | changed_pc;
|
return (execute_cycles - dma_cycles) | changed_pc | frame_complete;
|
||||||
}
|
}
|
||||||
|
|
||||||
void reset_gba(void)
|
void reset_gba(void)
|
||||||
|
|
3
main.h
3
main.h
|
@ -77,7 +77,8 @@ 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];
|
||||||
|
|
||||||
#define update_gba_cycles(c) (update_gba(c) & 0x7FFF)
|
#define cycles_to_run(c) ((c) & 0x7FFF)
|
||||||
|
#define completed_frame(c) ((c) & 0x80000000)
|
||||||
u32 function_cc update_gba(int remaining_cycles);
|
u32 function_cc update_gba(int remaining_cycles);
|
||||||
void reset_gba(void);
|
void reset_gba(void);
|
||||||
|
|
||||||
|
|
|
@ -104,7 +104,7 @@ symbol:
|
||||||
.equ REG_Z_FLAG, (21 * 4)
|
.equ REG_Z_FLAG, (21 * 4)
|
||||||
.equ REG_C_FLAG, (22 * 4)
|
.equ REG_C_FLAG, (22 * 4)
|
||||||
.equ REG_V_FLAG, (23 * 4)
|
.equ REG_V_FLAG, (23 * 4)
|
||||||
.equ COMPLETED_FRAME, (24 * 4)
|
.equ REG_UNUSED_1, (24 * 4)
|
||||||
.equ OAM_UPDATED, (25 * 4)
|
.equ OAM_UPDATED, (25 * 4)
|
||||||
.equ REG_SAVE, (26 * 4)
|
.equ REG_SAVE, (26 * 4)
|
||||||
.equ REG_SAVE2, (27 * 4)
|
.equ REG_SAVE2, (27 * 4)
|
||||||
|
@ -248,12 +248,12 @@ defsymbl(mips_update_gba)
|
||||||
move $4, reg_cycles # Remaining cycles as asg0
|
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
|
bltz $2, return_to_main # Exit if a frame is complete (bit 31 is set)
|
||||||
bne $1, $0, return_to_main # Return to main thread now
|
|
||||||
|
|
||||||
and reg_cycles, $2, 0x7FFF # update new cycle count (ret value)
|
and reg_cycles, $2, 0x7FFF # update new cycle count (ret value)
|
||||||
|
|
||||||
bltz $2, lookup_pc
|
sll $1, $2, 1 # Check bit 30 now (PC changed)
|
||||||
|
bltz $1, lookup_pc
|
||||||
lw $ra, REG_SAVE2($16) # restore return address
|
lw $ra, REG_SAVE2($16) # restore return address
|
||||||
|
|
||||||
restore_registers
|
restore_registers
|
||||||
|
@ -344,8 +344,7 @@ cpu_sleep_loop:
|
||||||
move $4, reg_cycles # Remaining cycles as asg0
|
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
|
bltz $2, return_to_main # Exit if a frame is complete (bit 31 is set)
|
||||||
bne $1, $0, return_to_main # Return to main thread now
|
|
||||||
|
|
||||||
# since no frame was completed, this means CPU is active again.
|
# since no frame was completed, this means CPU is active again.
|
||||||
# Fall through to lookup_pc to resume execution
|
# Fall through to lookup_pc to resume execution
|
||||||
|
|
|
@ -107,7 +107,6 @@ bool gba_load_state(const void* src)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
instruction_count = 0;
|
instruction_count = 0;
|
||||||
reg[COMPLETED_FRAME] = 0;
|
|
||||||
reg[OAM_UPDATED] = 1;
|
reg[OAM_UPDATED] = 1;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -95,7 +95,7 @@ _##symbol:
|
||||||
.equ REG_Z_FLAG, (21 * 4)
|
.equ REG_Z_FLAG, (21 * 4)
|
||||||
.equ REG_C_FLAG, (22 * 4)
|
.equ REG_C_FLAG, (22 * 4)
|
||||||
.equ REG_V_FLAG, (23 * 4)
|
.equ REG_V_FLAG, (23 * 4)
|
||||||
.equ COMPLETED_FRAME, (24 * 4)
|
.equ REG_UNUSED_1, (24 * 4)
|
||||||
.equ OAM_UPDATED, (25 * 4)
|
.equ OAM_UPDATED, (25 * 4)
|
||||||
.equ REG_SAVE, (26 * 4)
|
.equ REG_SAVE, (26 * 4)
|
||||||
|
|
||||||
|
@ -170,17 +170,19 @@ defsymbl(x86_update_gba)
|
||||||
|
|
||||||
mov REG_CYCLES, CARG1_REG # Load remaining cycles as arg0
|
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
|
||||||
|
|
||||||
|
# did we just complete a frame? go back to main then
|
||||||
|
test %eax, %eax # Bit 31 set, means new frame completed
|
||||||
|
js return_to_main
|
||||||
|
|
||||||
|
# Load new cycle counter
|
||||||
mov %eax, REG_CYCLES # new cycle count
|
mov %eax, REG_CYCLES # new cycle count
|
||||||
and $0x7fff, REG_CYCLES # in the lowest bits
|
and $0x7fff, REG_CYCLES # in the lowest bits
|
||||||
|
|
||||||
# did we just complete a frame? go back to main then
|
# did the PC change? Bit 30 will be set
|
||||||
cmpl $0, COMPLETED_FRAME(REG_BASE)
|
test $0x40000000, %eax
|
||||||
jne return_to_main
|
jne lookup_pc
|
||||||
|
ret # otherwise, go back to caller (resume)
|
||||||
# did the PC change?
|
|
||||||
test %eax, %eax # Bit 31 set, means need to re-fetch
|
|
||||||
js lookup_pc
|
|
||||||
ret # otherwise, go back to caller
|
|
||||||
|
|
||||||
# Perform this on an indirect branch that will definitely go to
|
# Perform this on an indirect branch that will definitely go to
|
||||||
# ARM code, IE anything that changes the PC in ARM mode except
|
# ARM code, IE anything that changes the PC in ARM mode except
|
||||||
|
@ -265,9 +267,9 @@ cpu_sleep_loop:
|
||||||
mov REG_CYCLES, CARG1_REG # Load remaining cycles as arg0
|
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
|
||||||
|
|
||||||
# did we just complete a frame? go back to main then
|
# did we just complete a frame (MSB set)? go back to main then
|
||||||
cmpl $0, COMPLETED_FRAME(REG_BASE)
|
test %eax, %eax
|
||||||
jne return_to_main
|
js return_to_main
|
||||||
|
|
||||||
// if we are out of update_gba and did not complete a frame, cpu is active
|
// if we are out of update_gba and did not complete a frame, cpu is active
|
||||||
mov %eax, REG_CYCLES # load new cycle count
|
mov %eax, REG_CYCLES # load new cycle count
|
||||||
|
|
Loading…
Add table
Reference in a new issue