i860 emu: add EMU_DATA_BASE / EMU_INDEXED experiment hooks (default off)

Env-gated hooks to continue the create()/jump-table investigation without
changing default behavior:
- EMU_DATA_BASE (default 0): overrides I860.DATA_BASE for the .data link base.
- EMU_INDEXED=1 (default off): makes EVEN integer load opcodes register-indexed
  (EA = base + index), per the ground-truth `ld.l r30(r31),r31` in VR_REMOT.S.

Sweep finding (EMU_INDEXED=1): create() RETURNS at DATA_BASE=0xff0 making real
subroutine calls, confirming register-indexed loads + a ~0x1000 data base are
correct. Residual: do_init derails to (DATA_BASE+0x30) for base >= 0xfe0 while
create needs >= ~0xfe0 -- a single flat base can't satisfy both yet, pointing
to a segment/relocation nuance (or a separate do_init jump-table derail).
Details + repro in the tier-0 memory. Default behavior unchanged.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Cyd
2026-07-15 09:40:33 -05:00
co-authored by Claude Opus 4.8
parent ef4a0b67ac
commit f5e9ae987d
+7 -4
View File
@@ -16,6 +16,7 @@ import dis860
PAGE = 1 << 16
MASK32 = 0xFFFFFFFF
_INDEXED = os.environ.get('EMU_INDEXED', '0') == '1' # experiment: register-indexed even loads
def s16(v): return v - 0x10000 if v & 0x8000 else v
def s26(v): return v - 0x4000000 if v & 0x2000000 else v
@@ -108,7 +109,7 @@ CTRL_NAMES = {0: 'fir', 1: 'psr', 2: 'dirbase', 3: 'db', 4: 'fsr', 5: 'epsr'}
class I860:
DATA_BASE = 0x00000000 # .data/.bss linked low (code refs span 0xebc4..0x22644)
DATA_BASE = int(os.environ.get('EMU_DATA_BASE', '0'), 0) # .data/.bss link base (experiment: sweep)
def __init__(self, trace=0, logf=None):
self.r = [0] * 32 # integer regs (r0 == 0)
@@ -199,9 +200,11 @@ class I860:
# pair): EA = base(src2) + s16(offset). Indexing is done by pre-computing
# base+index into a register, then loading at offset 0. dest = bits20:16.
if op in (0x00, 0x01, 0x04, 0x05, 0x08, 0x09):
m = 0xffff if op < 0x04 else (0xfff8 if op >= 0x08 else 0xfffc)
off = s16(imm & m)
ea = self.rd(src2) + off
if _INDEXED and not (op & 1): # EVEN opcode = register-indexed (VR_REMOT.S)
ea = self.rd(src2) + self.rd(src1)
else:
m = 0xffff if op < 0x04 else (0xfff8 if op >= 0x08 else 0xfffc)
ea = self.rd(src2) + s16(imm & m)
if op in (0x00, 0x01): self.wr(dest, self.mem.r8(ea)) # ld.b (byte)
elif op in (0x04, 0x05): self.wr(dest, self.mem.r32(ea)) # ld.l
else: self.fwr(dest, self.mem.r32(ea)) # fld.l