From f5e9ae987d1b588adb1a72adfa3e68623d4d5a77 Mon Sep 17 00:00:00 2001 From: Cyd Date: Wed, 15 Jul 2026 09:40:33 -0500 Subject: [PATCH] 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 --- emulator/firmware-decomp/emu860.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/emulator/firmware-decomp/emu860.py b/emulator/firmware-decomp/emu860.py index 7c6d643..ff374aa 100644 --- a/emulator/firmware-decomp/emu860.py +++ b/emulator/firmware-decomp/emu860.py @@ -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