igc_exec: SCMEMA (screen-address seed) + gated sweep-pair adds

Verified flowing on the bench tile: s145 holds per-pixel x, scalar region
packs it, SCAintoMEM constants land in eofr/eofb. Bars chain now breaks at
the texz seed = the op-0x48-with-len family (0x3a804820 targets texz) --
FCMEMA, next to implement.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Cyd
2026-07-18 01:51:17 -05:00
co-authored by Claude Opus 4.8
parent 6451b739bd
commit 6c3dc2e954
+33 -5
View File
@@ -70,6 +70,8 @@ _reg(0x49, None, 'OP49', 1)
_reg(0x30, None, 'OP30', 1)
_reg(0x75, None, 'OP75', 1)
_reg(0xdb, None, 'OPDB', 0)
_reg(0x39, None, 'SCMEMA', 1) # write pixel screen-address into mem (seed)
_reg(0xec, None, 'SCMEMA_IMM', 0) # bare .8-fixed immediate rider (e.g. 0xec00=236.0)
def parse(words):
@@ -254,21 +256,47 @@ class Tile:
for i in range(NPIX):
if not self.enab[i]:
self.mem[i][a >> 3] &= ~(1 << (a & 7))
elif m == 'SCMEMA':
# seed: write the pixel's GLOBAL X screen address into mem[addr:len]
_, addr, ln, operand = ins
ln = max(1, min(20, ln if ln > 0 else 8))
mask = (1 << ln) - 1
for y in range(TILE_H):
ybase = y * TILE_W
for x in range(TILE_W):
i = x + ybase
if self.enab[i]:
self._wr(self.mem[i], addr, ln, (x + self.ox) & mask)
elif m == 'SWEEP21':
# latch the src bit (secondary carry latch, does not clobber enable)
_, dst, ln, operand = ins
if operand is not None:
src = operand & 0xff
self._latch = [ (self.mem[i][src >> 3] >> (src & 7)) & 1
for i in range(NPIX) ]
elif m == 'SWEEP25':
# bit-serial accumulate step: dst-field += src bit (best-effort:
# treat the pair as part of a field ADD; the paired SWEEP21 reads
# the src bit into the carry -- we implement the NET effect when
# the operand gives {src,dst,len}: dst[0:len] += src bit << k is
# approximated by a single-bit OR into dst (first pass).
# gated add: if the latched src bit is set, add 1<<k into the
# 20-bit dst field, where k = 20 - len2 (the emitter counts len2
# down from 20) => net effect over the pair-cascade = dst += src.
_, dst, ln, operand = ins
if operand is None:
continue
src = operand & 0xff
len2 = (operand >> 16) & 0x7f
k = max(0, 20 - len2)
latch = getattr(self, '_latch', None)
if latch is None:
continue
add = 1 << k
mask20 = (1 << 20) - 1
for i in range(NPIX):
if self.enab[i]:
b = (self.mem[i][src >> 3] >> (src & 7)) & 1
if b:
self.mem[i][dst >> 3] |= 1 << (dst & 7)
if self.enab[i] and latch[i]:
v = (self._rd(self.mem[i], dst, 20) + add) & mask20
self._wr(self.mem[i], dst, 20, v)
else:
unhandled.add(m)
return unhandled