Files
SDD af7d3565a5 dis34: print long relative JR as jr and surface B-file SP as b15
The 16-bit-displacement jump (low byte 0x00, two words) is JRcc, not the
three-word JAcc (low byte 0x80).  Printing it as ja made linear
disassembly report the wrong control flow and made every such branch grow
by a word when reassembled.

Register 15 is the stack pointer in either file: 0x0F is A15 and 0x1F is
B15.  The disassembler printed both as sp, hiding B-file stack-pointer
code.  Print b15 when the R bit selects the B file.

Validated with the 1987 TI GSPA/GSPLNK/GSPROM round trip: the 32 KB region
at bit 3F208000 still reassembles byte-for-byte (md5
43adb6669571041985f3e26fd9ff7cb9), as do the 4 KB and 16 KB spans and the
0x8000/3F240000 region.  The converter no longer needs its ja->jr or
sp->b15 rewrites (5 fixups -> 3); a whole-ROM diff contains only those two
output categories.  The ROM is unchanged
(b46a3e442ccb86134d2356bd70d22fd2).
2026-10-18 00:54:34 +03:00

110 lines
3.1 KiB
Bash
Executable File

#!/bin/sh
# Assemble a region of the VT1200 ROM with the 1987 TI TMS34010 toolchain
# (GSPA/GSPLNK/GSPROM, run under DOSBox) and compare the result byte-for-byte
# with the original.
#
# Usage: roundtrip.sh OFFSET SIZE BASE_BIT
# OFFSET byte offset into vt1200_v22.bin
# SIZE region size in bytes
# BASE_BIT bit address the region is linked at (e.g. 3F208000)
#
# Example: roundtrip.sh 0x1000 16384 3F208000
#
# The ROM is only read. All work happens in this directory.
#
# Set DIS34=/path/to/dis34 to test a different build (used for the pre-fix
# control run: it should FAIL, because the converter no longer rewrites
# long-relative JA back to JR).
set -eu
ROOT=$(cd "$(dirname "$0")/../.." && pwd)
DIR=$(cd "$(dirname "$0")" && pwd)
WORK="$DIR/work"
ROM="$ROOT/vt1200_v22.bin"
DIS="${DIS34:-$ROOT/tools/smart34010/dis34}"
DOSBOX_CONF="$ROOT/harness/sdk-scratch/dosbox.conf"
OFF=${1:?offset}
SIZE=${2:?size}
BASE=${3:?base bit address}
OFF=$((OFF))
SIZE=$((SIZE))
mkdir -p "$WORK"
# tools: extract once from the 1987-11-06 floppy image
if [ ! -x "$WORK/GSPA.EXE" ]; then
IMG="$ROOT/tools/tms34010-sdk/1987-05 TMS34010 SDK/1987-11-06 TMS34010 Simulator-C Tools-ASM Tools.img"
mcopy -s -n -i "$IMG" "::/A2/*" "$WORK/"
mcopy -s -n -i "$IMG" "::/C2/*" "$WORK/"
fi
# TI hex constants must begin with a decimal digit
TBASE=$BASE
case "$TBASE" in
[0-9]*) ;;
*) TBASE="0$TBASE" ;;
esac
dd if="$ROM" of="$WORK/rt.bin" bs=1 skip="$OFF" count="$SIZE" 2>/dev/null
"$DIS" -b "$BASE" -o "$WORK/rt.bin" > "$WORK/rt.dis"
python3 "$DIR/dis2as34.py" "$BASE" "$SIZE" "$WORK/rt.dis" > "$WORK/RT.ASM"
sed -i '1i .text' "$WORK/RT.ASM"
echo '.end' >> "$WORK/RT.ASM"
cat > "$WORK/RT.CMD" <<EOF
-a
-o rt.out
-m rt.map
rt.obj
SECTIONS
{
.text ${TBASE}h: {}
}
EOF
sed -i 's/$/\r/' "$WORK/RT.CMD"
rm -f "$WORK"/RT.OBJ "$WORK"/RT.OUT "$WORK"/RT.LST "$WORK"/RTHI.HI "$WORK"/RTLO.LO
SDL_VIDEODRIVER=dummy SDL_AUDIODRIVER=dummy \
timeout 180 dosbox -conf "$DOSBOX_CONF" -noprimaryconf -nolocalconf \
-c "mount c $WORK" -c "c:" \
-c "gspa rt rt.obj rt.lst -l" \
-c "gsplnk rt.cmd" \
-c "gsprom -i rt.out rthi rtlo" \
-c "exit" -exit >/dev/null 2>&1
python3 - "$WORK" "$SIZE" <<'EOF'
import sys
work, size = sys.argv[1], int(sys.argv[2])
def readhex(p):
d = {}
for line in open(p):
line = line.strip()
if not line.startswith(':'):
continue
b = bytes.fromhex(line[1:])
if b[3] != 0:
continue
a = (b[1] << 8) | b[2]
for i, x in enumerate(b[4:4 + b[0]]):
d[a + i] = x
return d
hi = readhex(work + "/RTHI.HI")
lo = readhex(work + "/RTLO.LO")
out = bytearray()
for a in sorted(hi):
out.append(lo[a])
out.append(hi[a])
orig = open(work + "/rt.bin", "rb").read()
n = min(len(orig), len(out))
bad = [i for i in range(n) if orig[i] != out[i]]
print("assembled %d bytes, original %d bytes, %d differing" % (len(out), len(orig), len(bad)))
if len(out) != len(orig) or bad:
print("FAIL")
for i in bad[:5]:
print(" %#x: orig %s out %s" % (i, orig[i:i+8].hex(), out[i:i+8].hex()))
sys.exit(1)
print("md5 " + __import__('hashlib').md5(out).hexdigest() + " BYTE-EXACT")
EOF