************************************************ * Profiler code Color Computer 3 * copyright Chris Lomont 2006 www.lomont.org ************************************************ ************************************************ * This file supports a instruction cycle profiler * the two functions of use are StartProfiler and * StopProfiler. * Call EnableProfiler and DisableProfiler before and after ************************************************ ************************************************ * EnableProfiler - enables the profiler by using * the FIRQ interrupt and the timer at 279 ns * also sets fast speed poke at $FFD9 * Registers changed: none ************************************************ oldInt fcb 0,0,0 old interrupt address (had JMP =0x7E then 16 bit addr) EnableProfiler pshs a,x clr $FFD9 high speed poke (todo - undo at end?) lda $FF91 get timer and other control ora #%00100000 sta $FF91 set 279 ns clock lda $FEF4 store old instructions at FEF4 sta oldInt ldx $FEF5 interrupt vector stx oldInt+1 3 bytes stored lda #$7E opcode for long jump instruction sta $FEF4 ldx #ProfilerInterrupt jump to our interrupt stx $FEF5 address lda $FF93 ora #%00100000 set bit 5 sta $FF93 enable FIRQ on timer overflow lda $FF90 ora #%00010000 bit 4 is FIRQ in CoCo3 mode as we need it sta $FF90 andcc #%10111111 clear bit 6, enables FIRQ puls a,x rts ************************************************ * DisableProfiler - call this when deon to stop profiler * stops timer and resets FIRQ address * Registers changed: none ************************************************ DisableProfiler pshs d,x bsr StopProfiler end any action orcc #%01000000 set bit 6, disables FIRQ lda $FF90 anda #%11101111 bit 4 is FIRQ in CoCo2 as it was?! sta $FF90 lda $FF93 anda #%11011110 disable timer on FIRQ sta $FF93 stop FIRQ on timer overflow lda oldInt sta $FEF4 ldx oldInt+1 stx $FEF5 restore old interrupt puls d,x rts ************************************************ * StartProfiler - Starts the profiler, resets count to 0 * Registers changed: none ************************************************ StartProfiler pshs d ldd #0 std profileCounter reset this ldd #$30 much faster and machine hangs from too many interrupts bsr SetTimerCount puls d *todo - use sync here? rts ************************************************ * StopProfiler - stops the profiler from counting * returns approx cycle count / 8 in REGD * Registers changed: REGD ************************************************ StopProfiler ldd #0 bsr SetTimerCount stops timer from counting ldd profileCounter get this for return bsr ProfileCountToCycles rts ************************************************ * ProfileCountToCycles - from testing this converts * profile count in REGD to cycles / 8 (approx) in REGD * Registers changed: REGD ************************************************ * formula is (d-5) ProfileCountToCycles subd #5 rts ************************************************ * SetTimerCount - set the timer value * REGD - value start at (counts down) * Registers changed: none ************************************************ SetTimerCount pshs a anda #15 only bottom 4 bits allowed stb $FF95 LSB of timer sta $FF94 MSB, starts timer puls a rts ************************************************ * ProfilerInterrupt - this is a FIRQ interrupt * so store any registers needed * Registers changed: none ************************************************ profileCounter fcb 0,0 16 bit instruction count counter ProfilerInterrupt if 1 inc profileCounter+1 6 - low byte bne done 3 - jump if no rollover inc profileCounter 6 - if rollover, inc high byte done tst $FF93 2 - cause a read rti 6 - 17 cycles on 255/256 of the time, else 23 endif if 0 std profileTemp 5 save register lda $FF93 4 sees what triggered FIRQ, and is REQUIRED READ ldd profileCounter 5 cycles addd #1 4 cycles std profileCounter 5 cycles andcc #%10111111 3 clear bit 6, enables FIRQ ldd profileTemp 5 restore register rti 6 return from interrupt *37 cycles total profileTemp fcb 0,0 endif ************************************************ * Testing space * if 1 todo - remove from final code ************************************************ * TestProfiler - call this and walk through in debugger to * see how profiler works * Registers changed: All ************************************************ TestProfiler lbsr EnableProfiler ldu #profileData store results here * counts are with removing ProfileCountToCycles lbsr StartProfiler lbsr StopProfiler std ,u++ save result $05 lbsr StartProfiler lbsr Delay each call to Delay is 9 + 55 = 64 cycles lbsr StopProfiler std ,u++ save result $1A lbsr StartProfiler lbsr Delay lbsr Delay lbsr StopProfiler std ,u++ save result $2C lbsr StartProfiler lbsr Delay lbsr Delay lbsr Delay lbsr StopProfiler std ,u++ save result $3D lbsr StartProfiler lbsr Delay lbsr Delay lbsr Delay lbsr Delay lbsr StopProfiler std ,u++ save result $52 lbsr StartProfiler lbsr Delay lbsr Delay lbsr Delay lbsr Delay lbsr Delay lbsr StopProfiler std ,u++ save result $64 lbsr StartProfiler lbsr Delay lbsr Delay lbsr Delay lbsr Delay lbsr Delay lbsr Delay lbsr StopProfiler std ,u++ save result $75 lbsr StartProfiler lbsr Delay lbsr Delay lbsr Delay lbsr Delay lbsr Delay lbsr Delay lbsr Delay lbsr StopProfiler std ,u++ save result $8A lbsr StartProfiler lbsr Delay lbsr Delay lbsr Delay lbsr Delay lbsr Delay lbsr Delay lbsr Delay lbsr Delay lbsr StopProfiler std ,u++ save result $9C lbsr StartProfiler lbsr Delay lbsr Delay lbsr Delay lbsr Delay lbsr Delay lbsr Delay lbsr Delay lbsr Delay lbsr Delay lbsr StopProfiler std ,u++ save result $AD lbsr StartProfiler lbsr Delay lbsr Delay lbsr Delay lbsr Delay lbsr Delay lbsr Delay lbsr Delay lbsr Delay lbsr Delay lbsr Delay lbsr StopProfiler std ,u++ save result $C2 lbsr DisableProfiler lbra TestProfiler * now clean up data - subtract off first value from rest, and then * compute differences ldy #profileData+2 ! ldd ,y subd profileData std ,y++ cmpy #profileData+2*10 blt < ! ldd ,y subd -2,y std ,y leay -2,y cmpy #profileData bgt < lbra TestProfiler rts profileData rmb 2*12 space to store results * delay 92 cycles Delay ldd #6 3 cycles ! subd #1 4 cycles * 6 bne < 3 cycles * 6 ldd #1 3 cycles lda #1 2 cycles rts 5 cycles, 55 cycles total * endif ************************************************ ************************************************ * END OF FILE ************************************************