i860 emu: pfgt/pfle exact semantics (R bit selects gt/le, pipelined retire+advance); IGC consumption resets page write-index for reuse
- pfgt/pfle/pfeq are always pipelined: fdest <- A-pipe retire, push undefined; bit7 selects pfle (inverted CC sense) -- was misread as result precision. 316 pipelined compares in the firmware previously desynced the A-pipe. - h_igcwait now models full consumption: done-status nonzero AND write-index reset (+0x7f8=0), otherwise queue pages saturate at 0x7f0 across frames and enqueueing silently stops (observed: even the per-frame marker item stopped binning by cmd ~4300). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -594,10 +594,20 @@ class I860:
|
||||
self.fwr(b0 | 1, (iv >> 32) & 0xFFFFFFFF)
|
||||
else:
|
||||
self.fwr(dest, iv & 0xFFFFFFFF)
|
||||
elif sub == 0x34: # fgt: CC = src1 > src2
|
||||
self.set_cc(self.rdf(src1, sp) > self.rdf(src2, sp))
|
||||
elif sub == 0x35: # feq: CC = src1 == src2
|
||||
self.set_cc(self.rdf(src1, sp) == self.rdf(src2, sp))
|
||||
elif sub in (0x34, 0x35): # pfgt/pfle (0x34) / pfeq (0x35)
|
||||
# MAME-validated: bit7 (the "R" bit) selects pfgt (0) vs pfle (1) --
|
||||
# NOT result precision. pfle CLEARS CC when src1 <= src2. These are
|
||||
# always pipelined: fdest <- A-pipe retire; push undefined (0.0).
|
||||
v1 = self.rdf(src1, sp); v2 = self.rdf(src2, sp)
|
||||
if sub == 0x35:
|
||||
self.set_cc(v1 == v2)
|
||||
elif w & 0x80: # pfle
|
||||
self.set_cc(not (v1 <= v2))
|
||||
else: # pfgt
|
||||
self.set_cc(v1 > v2)
|
||||
ap, mp = self._fp_pipes()
|
||||
self._retire(dest, ap[2])
|
||||
self._padv(ap, 0.0, sp, 3)
|
||||
elif sub == 0x21: # fmlow.dd -- i860 FP-unit INTEGER multiply.
|
||||
# The i860 has no imul: ints are ixfr'd into FP regs, fmlow.dd multiplies,
|
||||
# and the low 32 bits (fdest) are fxfr/fst'd back. Operands are the low
|
||||
|
||||
@@ -113,8 +113,12 @@ class MainRunner:
|
||||
def h_igcwait(self, cpu):
|
||||
# Post-flush drain wait: the firmware polls [page] until the IGC writes a
|
||||
# NONZERO completion status after consuming it (loop at 0xf0421504: exits
|
||||
# the per-page wait when [r16] != 0). We are the IGC: complete instantly.
|
||||
cpu.mem.w32(cpu.rd(16), 1)
|
||||
# the per-page wait when [r16] != 0). We are the IGC: complete instantly,
|
||||
# and RESET the page's write index (+0x7f8) so the page is reusable --
|
||||
# otherwise pages fill at 0x7f0 across frames and enqueueing silently dies.
|
||||
page = cpu.rd(16)
|
||||
cpu.mem.w32(page, 1)
|
||||
cpu.mem.w32(page + 0x7f8, 0)
|
||||
cpu.step()
|
||||
return True
|
||||
|
||||
|
||||
Reference in New Issue
Block a user