mirror of
https://github.com/mauiaaron/apple2.git
synced 2025-02-21 05:29:07 +00:00
Improve timing conformance in Mockingboard
- Correctly calculate 7 cycles for handling IRQs - More frequent calls to MB_UpdateCycles() - Correctly calculate timing for MB_EndOfVideoFrame() when testing/tracing/debugging
This commit is contained in:
parent
4fd6a87340
commit
ccd05e52fe
@ -74,13 +74,12 @@
|
||||
|
||||
|
||||
#define CPUStatsReset \
|
||||
SYM(r1, cpu65_opcode); \
|
||||
strb r0, [r1]; /* r0 should be next opcode */ \
|
||||
eor r9, r9, r9; \
|
||||
SYM(r1, cpu65_opcycles); \
|
||||
strb r9, [r1]; \
|
||||
SYM(r1, cpu65_rw); \
|
||||
strb r9, [r1];
|
||||
|
||||
#define CPUStatsSetRead \
|
||||
SYM(r1, cpu65_rw); \
|
||||
ldrb r9, [r1]; \
|
||||
@ -153,7 +152,8 @@
|
||||
#define JumpNextInstruction \
|
||||
TRACE_PROLOGUE \
|
||||
GetFromPC_B \
|
||||
CPUStatsReset \
|
||||
SYM(r1, cpu65_opcode); \
|
||||
strb r0, [r1]; /* r0 should be next opcode */ \
|
||||
SYM(r1, cpu65__opcodes); \
|
||||
ldr r1, [r1, r0, LSL PTR_SHIFT]; \
|
||||
bx r1;
|
||||
@ -2431,19 +2431,33 @@ continue:
|
||||
add r9, r9, cycles_exe
|
||||
str r9, [r1]
|
||||
|
||||
SYM(r1, cpu65_cycles_to_execute)
|
||||
SYM(r1, irqCheckTimeout) // AppleWin : CheckInterruptSources()
|
||||
ldr r9, [r1]
|
||||
subs r9, r9, cycles_exe
|
||||
str r9, [r1]
|
||||
bmi irq_checkpoint
|
||||
|
||||
continue1: SYM(r1, cpu65_cycles_to_execute)
|
||||
ldr r9, [r1]
|
||||
subs r9, r9, cycles_exe
|
||||
str r9, [r1]
|
||||
bmi exit_cpu65_run
|
||||
beq exit_cpu65_run
|
||||
|
||||
continue1: SYM(r1, cpu65__signal)
|
||||
continue2: SYM(r1, cpu65__signal)
|
||||
ldrb r0, [r1]
|
||||
orrs r0, r0, r0
|
||||
bne exception
|
||||
CPUStatsReset
|
||||
JumpNextInstruction
|
||||
|
||||
irq_checkpoint:
|
||||
bl CALL(cpu_irqCheck);
|
||||
SYM(r1, irqCheckTimeout)
|
||||
eor r9, r9, r9
|
||||
str r9, [r1]
|
||||
b continue1
|
||||
|
||||
/* -------------------------------------------------------------------------
|
||||
Exception handlers
|
||||
------------------------------------------------------------------------- */
|
||||
@ -2466,10 +2480,12 @@ ex_reset: eor r0, r0, r0
|
||||
ldrh EffectiveAddr, [EffectiveAddr]
|
||||
GetFromEA_W
|
||||
mov PC_Reg, r0
|
||||
CPUStatsReset
|
||||
JumpNextInstruction
|
||||
|
||||
ex_irq: tst F_Reg, #I_Flag // Already interrupted?
|
||||
beq 1f
|
||||
CPUStatsReset
|
||||
JumpNextInstruction // Yes (ignored) ...
|
||||
1: TRACE_IRQ // No (handle IRQ) ...
|
||||
mov r0, PC_Reg
|
||||
@ -2486,6 +2502,11 @@ ex_irq: tst F_Reg, #I_Flag // Already interrupt
|
||||
ldrh EffectiveAddr, [EffectiveAddr]
|
||||
GetFromEA_W
|
||||
mov PC_Reg, r0
|
||||
CPUStatsReset
|
||||
SYM(r1, cpu65_opcycles)
|
||||
ldrb r0, [r1]
|
||||
add r0, r0, #7 // IRQ handling will take additional 7 cycles
|
||||
strb r0, [r1]
|
||||
JumpNextInstruction
|
||||
|
||||
/* -------------------------------------------------------------------------
|
||||
@ -2517,7 +2538,7 @@ ENTRY(cpu65_run)
|
||||
eorne r0, r0, r0
|
||||
STRBNE r0, [r1]
|
||||
bne ex_reset
|
||||
b continue1
|
||||
b continue2
|
||||
|
||||
/* -------------------------------------------------------------------------
|
||||
65c02 CPU processing loop exit point
|
||||
|
@ -73,6 +73,8 @@ void cpu65_trace_checkpoint(void);
|
||||
|
||||
#endif /* !__ASSEMBLER__ */
|
||||
|
||||
#define IRQ_CHECK_CYCLES 128
|
||||
|
||||
#define ResetSig 0x02
|
||||
#define IRQ6522 0x08
|
||||
#define IRQSpeech 0x10
|
||||
|
27
src/timing.c
27
src/timing.c
@ -54,6 +54,7 @@ unsigned long cycles_count_total = 0; // Running at spec ~1MHz, this w
|
||||
int cycles_speaker_feedback = 0;
|
||||
int32_t cpu65_cycles_to_execute = 0; // cycles-to-execute by cpu65_run()
|
||||
int32_t cpu65_cycle_count = 0; // cycles currently excuted by cpu65_run()
|
||||
int32_t irqCheckTimeout = IRQ_CHECK_CYCLES;
|
||||
static int32_t cycles_checkpoint_count = 0;
|
||||
static unsigned int g_dwCyclesThisFrame = 0;
|
||||
|
||||
@ -147,6 +148,8 @@ void reinitialize(void) {
|
||||
#endif
|
||||
|
||||
cycles_count_total = 0;
|
||||
g_dwCyclesThisFrame = 0;
|
||||
irqCheckTimeout = IRQ_CHECK_CYCLES;
|
||||
#if TESTING
|
||||
extern unsigned long (*testing_getCyclesCount)(void);
|
||||
if (testing_getCyclesCount) {
|
||||
@ -343,7 +346,7 @@ cpu_runloop:
|
||||
|
||||
MB_StartOfCpuExecute();
|
||||
if (is_debugging) {
|
||||
debugging_cycles = cpu65_cycles_to_execute;
|
||||
debugging_cycles = cpu65_cycles_to_execute;
|
||||
}
|
||||
|
||||
do {
|
||||
@ -354,10 +357,15 @@ cpu_runloop:
|
||||
cpu65_cycle_count = 0;
|
||||
cycles_checkpoint_count = 0;
|
||||
cpu65_run(); // run emulation for cpu65_cycles_to_execute cycles ...
|
||||
#if DEBUG_TIMING
|
||||
dbg_cycles_executed += cpu65_cycle_count;
|
||||
#endif
|
||||
g_dwCyclesThisFrame += cpu65_cycle_count;
|
||||
|
||||
if (is_debugging) {
|
||||
debugging_cycles -= cpu65_cycle_count;
|
||||
timing_checkpoint_cycles();
|
||||
|
||||
if (c_debugger_should_break() || (debugging_cycles <= 0)) {
|
||||
int err = 0;
|
||||
if ((err = pthread_cond_signal(&dbg_thread_cond))) {
|
||||
@ -370,18 +378,15 @@ cpu_runloop:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (emul_reinitialize) {
|
||||
pthread_mutex_unlock(&interface_mutex);
|
||||
goto cpu_runloop;
|
||||
}
|
||||
}
|
||||
} while (is_debugging);
|
||||
#if DEBUG_TIMING
|
||||
dbg_cycles_executed += cpu65_cycle_count;
|
||||
#endif
|
||||
g_dwCyclesThisFrame += cpu65_cycle_count;
|
||||
|
||||
MB_UpdateCycles(); // update 6522s (NOTE: do this before updating cycles_count_total)
|
||||
MB_UpdateCycles();
|
||||
|
||||
timing_checkpoint_cycles();
|
||||
|
||||
@ -536,6 +541,8 @@ void timing_stopCPU(void) {
|
||||
}
|
||||
|
||||
unsigned int CpuGetCyclesThisVideoFrame(void) {
|
||||
assert(pthread_self() == cpu_thread_id);
|
||||
|
||||
timing_checkpoint_cycles();
|
||||
return g_dwCyclesThisFrame + cycles_checkpoint_count;
|
||||
}
|
||||
@ -546,11 +553,11 @@ void timing_checkpoint_cycles(void) {
|
||||
|
||||
const int32_t d = cpu65_cycle_count - cycles_checkpoint_count;
|
||||
assert(d >= 0);
|
||||
#if TESTING
|
||||
unsigned long previous_cycles_count_total = cycles_count_total;
|
||||
#endif
|
||||
#if !TESTING
|
||||
cycles_count_total += d;
|
||||
#else
|
||||
unsigned long previous_cycles_count_total = cycles_count_total;
|
||||
cycles_count_total += d;
|
||||
#if TESTING
|
||||
if (UNLIKELY(cycles_count_total < previous_cycles_count_total)) {
|
||||
extern void (*testing_cyclesOverflow)(void);
|
||||
if (testing_cyclesOverflow) {
|
||||
|
6
src/vm.c
6
src/vm.c
@ -918,6 +918,12 @@ GLUE_C_READ(debug_illegal_bcd)
|
||||
return 0;
|
||||
}
|
||||
|
||||
GLUE_C_WRITE(cpu_irqCheck)
|
||||
{
|
||||
MB_UpdateCycles();
|
||||
// TODO : other peripheral card interrupt handling
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
static void _initialize_iie_switches(void) {
|
||||
|
@ -90,12 +90,14 @@
|
||||
CALL_IND(cpu65_vmem_r,EffectiveAddr_X,SZ_PTR); \
|
||||
TRACE_ARG1;
|
||||
|
||||
#define CPUStatsReset \
|
||||
REG2MEM(movb, $0, cpu65_opcycles); \
|
||||
REG2MEM(movb, $0, cpu65_rw);
|
||||
|
||||
#define JumpNextInstruction \
|
||||
TRACE_PROLOGUE; \
|
||||
GetFromPC_B \
|
||||
REG2MEM(movb, %al, cpu65_opcode); \
|
||||
REG2MEM(movb, $0, cpu65_opcycles); \
|
||||
REG2MEM(movb, $0, cpu65_rw); \
|
||||
JUMP_IND(cpu65__opcodes,_XAX,SZ_PTR);
|
||||
|
||||
#define GetFromEA_B \
|
||||
@ -2160,14 +2162,21 @@ continue:
|
||||
REG2MEM(addl, %eax, cpu65_cycle_count)
|
||||
REG2MEM(subl, %eax, gc_cycles_timer_0)
|
||||
REG2MEM(subl, %eax, gc_cycles_timer_1)
|
||||
REG2MEM(subl, %eax, cpu65_cycles_to_execute)
|
||||
REG2MEM(subl, %eax, irqCheckTimeout)
|
||||
jl irq_checkpoint // AppleWin : CheckInterruptSources()
|
||||
continue1: REG2MEM(subl, %eax, cpu65_cycles_to_execute)
|
||||
jle exit_cpu65_run
|
||||
|
||||
continue1: xorLQ _XAX, _XAX
|
||||
continue2: xorLQ _XAX, _XAX
|
||||
MEM2REG(orb, cpu65__signal, %al)
|
||||
jnz exception
|
||||
CPUStatsReset
|
||||
JumpNextInstruction
|
||||
|
||||
irq_checkpoint:
|
||||
CALL_FN(callLQ, cpu_irqCheck, 0x4)
|
||||
REG2MEM(movl, $IRQ_CHECK_CYCLES, irqCheckTimeout)
|
||||
jmp continue1
|
||||
|
||||
/* -------------------------------------------------------------------------
|
||||
Exception handlers
|
||||
------------------------------------------------------------------------- */
|
||||
@ -2184,10 +2193,12 @@ ex_reset: REG2MEM(movb, $0, cpu65__signal)
|
||||
GetFromEA_W
|
||||
movw %ax, PC_Reg
|
||||
xorb %ah, %ah
|
||||
CPUStatsReset
|
||||
JumpNextInstruction
|
||||
|
||||
ex_irq: testb $I_Flag, F_Reg // Already interrupted?
|
||||
jz 1f
|
||||
CPUStatsReset
|
||||
JumpNextInstruction // Yes (ignored) ...
|
||||
1: TRACE_IRQ // No (handle IRQ) ...
|
||||
movw PC_Reg, %ax
|
||||
@ -2210,6 +2221,8 @@ ex_irq: testb $I_Flag, F_Reg // Already interrupt
|
||||
GetFromEA_W
|
||||
movw %ax, PC_Reg
|
||||
xorb %ah, %ah
|
||||
CPUStatsReset
|
||||
REG2MEM(addb, $7, cpu65_opcycles); // IRQ handling will take additional 7 cycles
|
||||
JumpNextInstruction
|
||||
|
||||
/* -------------------------------------------------------------------------
|
||||
@ -2256,7 +2269,7 @@ ENTRY(cpu65_run)
|
||||
#endif
|
||||
REG2MEM(cmpb, $0, emul_reinitialize)
|
||||
jnz enter_reinit
|
||||
jmp continue1
|
||||
jmp continue2
|
||||
|
||||
enter_reinit: REG2MEM(movb, $0, emul_reinitialize)
|
||||
jmp ex_reset
|
||||
|
Loading…
x
Reference in New Issue
Block a user