I just benchmarked timer B triggering on every line, and 87% CPU is free. On one paw, it's quicker because it only runs during 200 out of 313 scanlines. On the other paw, it's slower because bclr.b #0,$fffffa0f.w to clear the interrupt (necessary on timer B, not necessary on hsync interrupt).
Code: Select all
SECTION TEXT
COMMENT HEAD=1
; Go into supervisor mode
clr.l -(sp)
move.w #$20,-(sp)
trap #1
addq.l #6,sp
lea withoutstr(pc),a0
bsr.w debugprint
bsr.w benchmark
bsr.w debugprintdecu
lea withstr(pc),a0
bsr.w debugprint
move.l $68.w,d7 ; Save old ISR
lea hblrout(pc),a0 ; Set new ISR
move.l a0,$68.w
move.w sr,d6 ; Save old SR
move.w #$2100,sr ; Enable hsync
bsr.w benchmark
move.w d6,sr ; Restore old SR
move.l d7,$68.w ; Restore old ISR
bsr.w debugprintdecu
lea timerstr(pc),a0
bsr.w debugprint
move.l $120.w,d7 ; Save old ISR
move.b $fffffa07.w,d6 ; Save timerB int enable
move.b $fffffa13.w,d5 ; Save timerB int mask
move.b $fffffa1b.w,d4 ; Save timerB control
move.b $fffffa21.w,d3 ; Save timerB data
clr.b $fffffa1b.w ; Stop/reset timer
lea timerbrout(pc),a0 ; Set new ISR
move.l a0,$120.w
move.b #1,$fffffa21.w ; Set timerB data
bset.b #0,$fffffa07.w ; Enable interrupt
bset.b #0,$fffffa13.w ; Unmask interrupt
move.b #8,$fffffa1b.w ; Start timer
bsr.w benchmark
clr.b $fffffa1b.w ; Stop/reset timer
move.l d7,$120.w ; Restore old ISR
move.b d6,$fffffa07.w ; Restore timerB int enable
move.b d5,$fffffa13.w ; Restore timerB int mask
move.b d3,$fffffa21.w ; Restore timerB data
move.b d4,$fffffa1b.w ; Restore timerB control
bsr.w debugprintdecu
lea keystr(pc),a0
bsr.w debugprint
bsr.w debugwaitkey
; Exit
clr.w -(sp)
move.w #$4c,-(sp)
trap #1
hblrout:
rte
timerbrout:
bclr.b #0,$fffffa0f.w ; Clear int
rte
; Returns iterations in d0.l
benchmark:
move.l d1,-(sp)
clr.l d0
move.l $462.w,d1
add.l #100,d1
.loop: addq.l #1,d0
cmp.l $462.w,d1
bgt.b .loop
move.l (sp)+,d1
rts
; Divide d0.l by d1.l. Quotient stored in d1.l, remainder in d0.l.
; Warning: slow when dealing with large quotient outputs.
ldivide:
move.l d2,-(sp)
move.l d3,-(sp)
clr.l d2
move.l d0,d3
.loop: sub.l d1,d3
bcs.b .break
addq.l #1,d2
move.l d3,d0
bra.b .loop
.break: move.l d2,d1
move.l (sp)+,d3
move.l (sp)+,d2
rts
; Print a string in a0
debugprint:
movem.l a0-a2/d0-d2,-(sp)
move.l a0,-(sp)
move.w #9,-(sp) ; c_conws
trap #1
addq.l #6,sp
movem.l (sp)+,a0-a2/d0-d2
rts
; Write unsigned value as decimal (11 chars) to string, no terminator
; All 11 chars are written, padded with spaces.
; a0=string buffer, d0.l=value, d1.b=prefix char
; Returns with a0 pointing to first non-space char
debugprintdecstr:
movem.l d0-d3/a1-a2,-(sp)
move.l a0,a1
move.b d1,d2
lea .debugprintdectable(pc),a2
; Write all 10 chars
moveq.l #9-1,d3
.loop: move.l (a2)+,d1
bsr.w ldivide
add.b #'0',d1
move.b d1,(a1)+
dbf d3,.loop
add.b #'0',d0
move.b d0,(a1)+
; Strip leading 0s
move.l a0,a1
moveq.l #9-1,d3
.loop2: cmp.b #'0',(a0)
bne.b .break
move.b #' ',(a0)+
dbf d3,.loop2
.break:
; Prepend prefix if not space
cmp.b #' ',d2
beq.b .skip
move.b d2,-(a0)
.skip:
movem.l (sp)+,d0-d3/a1-a2
rts
.debugprintdectable:
dc.l 1000000000, 100000000, 10000000, 1000000
dc.l 100000, 10000, 1000, 100, 10
; Print all 32 bits of d0 as decimal unsigned followed by a space
debugprintdecu:
move.l a0,-(sp)
move.w d1,-(sp)
move.w #$2000,-(sp)
lea -12(sp),sp
lea 1(sp),a0
move.b #$20,d1
bsr.w debugprintdecstr
bsr.w debugprint
lea 14(sp),sp
move.w (sp)+,d1
move.l (sp)+,a0
rts
; Wait for keypress
debugwaitkey:
movem.l a0-a2/d0-d2,-(sp)
move.w #1,-(sp) ; c_conin
trap #1 ; Wait for keypress
addq.l #2,sp
movem.l (sp)+,a0-a2/d0-d2
rts
SECTION DATA
CNOP 0,4
withoutstr dc.b 10,13,"Iterations with no HBL: ",0
withstr dc.b 10,13,"Iterations with HBL: ",0
timerstr dc.b 10,13,"Iterations with Timer B: ",0
keystr dc.b 10,13,"Press any key",10,13,0