Measure the finer chain tail: 84/120 becomes 18/120, and the derivation was right by cancellation
blit.s gains v7 -- v6's 24-pixel movem chain plus a second chain whose unit is
one `move.l (a0)+,(a2)+`. Measured over 13 span lengths by span.sh, every config
pixel-exact:
cycles = 66.0 per span + 9.143 per COARSE pixel + 9.978 per FINE pixel
fitting all 13 to within 0.2%. v5 and v6 re-measure to FINDINGS 30 exactly, so
the harness has not drifted underneath the new variant.
Rescored against the same scsi window and the same additive model, v7 takes
84/120 frames over budget to 18/120 -- exactly what FINDINGS 39.4 derived, and
that agreement is two cancelling errors: the derivation's 2-register movem tail
is 29% too dear per pixel, and its "nothing per span" for the second chain entry
is 22.3 clocks too cheap. The plain post-incrementing move.l is the right tail
instruction, and it makes the padding quantum 2 pixels, which a run of 4x4
blocks pads to exactly zero.
The DMAC stays dropped on a measurement now rather than an argument: v7 takes
back 37 of the 43 frames the array chain would, with no reserved channel and no
timing neither emulator here can verify. Break-even against all-V1 moves from
L=4 blocks to L=2.
The fine displacement is carried mid-stream rather than in the span record, so
the decoder holds nothing across the copy and keeps all 12 payload registers --
which is the whole reason the coarse unit is 24 pixels.
span.sh is now -seconds_to_run 200 (30 s wall, 36 configs) and takes its
expected snapshot count from the generated metadata instead of a literal 23.
Claude-Session: https://claude.ai/code/session_01194oWYW8DQXK1SZ2DnChW6
This commit is contained in:
@@ -69,6 +69,27 @@
|
||||
; And with row and remainder handling gone, 12 registers are free again
|
||||
; (d0-d6/a1/a3-a6), which is why the unit is 24 pixels and not V5's 16.
|
||||
;
|
||||
; V7 v6 with a SECOND, finer chain for the tail (FINDINGS 39.4). v6 pays for
|
||||
; its 24-pixel quantum in padding: an average span wastes ~11 pixels, and
|
||||
; FINDINGS 39.3 attributes 86% of the DMAC array-chain's advantage over v6
|
||||
; to exactly that. V7 keeps the 24-pixel coarse chain and appends a chain
|
||||
; of 2-pixel units, so a span is 24*c + 2*f pixels and the padding is at
|
||||
; most one pixel -- ZERO for the real case, where a span is a run of 4x4
|
||||
; blocks and its length is a multiple of 4.
|
||||
;
|
||||
; The fine unit is `move.l (a0)+,(a2)+` (20 cycles, 2 pixels), NOT a
|
||||
; 2-register movem: movem.l (a0)+,d0-d1 plus movem.l d0-d1,(a2) plus the
|
||||
; lea is 52+8 cycles for 4 pixels, so the obvious "smaller movem" tail is
|
||||
; 50% dearer per pixel than the plainest instruction on the machine.
|
||||
;
|
||||
; The second entry point costs a second dispatch, and the trick that pays
|
||||
; for it is that the fine displacement is NOT in the span record: it sits
|
||||
; in the STREAM, after the coarse pixels and before the fine ones. The
|
||||
; coarse chain falls out into `move.w (a0)+,d0 / jmp`, by which point d0
|
||||
; is dead payload and a0 is pointing exactly at it. So v7 holds nothing
|
||||
; extra across the copy and keeps all 12 payload registers -- a record is
|
||||
; still {u32 address, u16 displacement}, with one more u16 mid-span.
|
||||
;
|
||||
; 12 registers per movem burst (d0-d7/a2-a5 = 48 bytes) is the maximum
|
||||
; available: a0=src, a1=dst, a6=end sentinel. The row counter lives in the
|
||||
; a1-vs-a6 compare rather than a d-register for exactly this reason.
|
||||
@@ -88,6 +109,10 @@ DSTE = $C38000 ; GVRAM + 224*1024 (one past last)
|
||||
ROWS = 192 ; picture rows a V5 stream describes
|
||||
V6UNIT = 12 ; bytes of code per V6 chain unit
|
||||
V6MAX = 11 ; chain units = 11*24 = 264 pixels >= one row
|
||||
V7CU = 12 ; bytes of code per V7 COARSE unit (24 px)
|
||||
V7CN = 11 ; coarse units: 11*24 = 264 px >= one row
|
||||
V7FU = 2 ; bytes of code per V7 FINE unit (2 px)
|
||||
V7FN = 11 ; fine units: 11*2 = 22 px > one coarse unit
|
||||
|
||||
org $10000
|
||||
start:
|
||||
@@ -103,6 +128,8 @@ start:
|
||||
beq v5
|
||||
cmp.l #6,d0
|
||||
beq v6
|
||||
cmp.l #7,d0
|
||||
beq v7
|
||||
bra v3
|
||||
|
||||
; ---------------------------------------------------------------- V1
|
||||
@@ -282,5 +309,68 @@ v6ch:
|
||||
bne v6
|
||||
bra done
|
||||
|
||||
; ---------------------------------------------------------------- V7
|
||||
; a0 stream, a2 destination, d7 spans remaining; everything else is payload.
|
||||
; Stream per span: u32 dest, u16 coarse disp, c*48 B pixels,
|
||||
; u16 fine disp, f*4 B pixels.
|
||||
v7: move.l SPTR.l,a0
|
||||
move.w (a0)+,d7 ; total spans in the frame
|
||||
subq.w #1,d7
|
||||
v7span: move.l (a0)+,a2 ; absolute GVRAM destination
|
||||
move.w (a0)+,d0 ; (V7CN - coarse) * V7CU
|
||||
jmp v7ch(pc,d0.w)
|
||||
v7ch:
|
||||
movem.l (a0)+,d0-d6/a1/a3-a6
|
||||
movem.l d0-d6/a1/a3-a6,(a2)
|
||||
lea 48(a2),a2
|
||||
movem.l (a0)+,d0-d6/a1/a3-a6
|
||||
movem.l d0-d6/a1/a3-a6,(a2)
|
||||
lea 48(a2),a2
|
||||
movem.l (a0)+,d0-d6/a1/a3-a6
|
||||
movem.l d0-d6/a1/a3-a6,(a2)
|
||||
lea 48(a2),a2
|
||||
movem.l (a0)+,d0-d6/a1/a3-a6
|
||||
movem.l d0-d6/a1/a3-a6,(a2)
|
||||
lea 48(a2),a2
|
||||
movem.l (a0)+,d0-d6/a1/a3-a6
|
||||
movem.l d0-d6/a1/a3-a6,(a2)
|
||||
lea 48(a2),a2
|
||||
movem.l (a0)+,d0-d6/a1/a3-a6
|
||||
movem.l d0-d6/a1/a3-a6,(a2)
|
||||
lea 48(a2),a2
|
||||
movem.l (a0)+,d0-d6/a1/a3-a6
|
||||
movem.l d0-d6/a1/a3-a6,(a2)
|
||||
lea 48(a2),a2
|
||||
movem.l (a0)+,d0-d6/a1/a3-a6
|
||||
movem.l d0-d6/a1/a3-a6,(a2)
|
||||
lea 48(a2),a2
|
||||
movem.l (a0)+,d0-d6/a1/a3-a6
|
||||
movem.l d0-d6/a1/a3-a6,(a2)
|
||||
lea 48(a2),a2
|
||||
movem.l (a0)+,d0-d6/a1/a3-a6
|
||||
movem.l d0-d6/a1/a3-a6,(a2)
|
||||
lea 48(a2),a2
|
||||
movem.l (a0)+,d0-d6/a1/a3-a6
|
||||
movem.l d0-d6/a1/a3-a6,(a2)
|
||||
lea 48(a2),a2
|
||||
v7cx: move.w (a0)+,d0 ; (V7FN - fine) * V7FU, from mid-stream
|
||||
jmp v7fh(pc,d0.w)
|
||||
v7fh:
|
||||
move.l (a0)+,(a2)+
|
||||
move.l (a0)+,(a2)+
|
||||
move.l (a0)+,(a2)+
|
||||
move.l (a0)+,(a2)+
|
||||
move.l (a0)+,(a2)+
|
||||
move.l (a0)+,(a2)+
|
||||
move.l (a0)+,(a2)+
|
||||
move.l (a0)+,(a2)+
|
||||
move.l (a0)+,(a2)+
|
||||
move.l (a0)+,(a2)+
|
||||
move.l (a0)+,(a2)+
|
||||
dbra d7,v7span
|
||||
subq.l #1,ITER.l
|
||||
bne v7
|
||||
bra done
|
||||
|
||||
done: move.l #$FF,FLAG.l ; timer stops here
|
||||
halt: bra.s halt
|
||||
|
||||
Reference in New Issue
Block a user