Files
vt1200/harness/udpstream/build-lance.sh
T
arti 895e059383 build-lance.sh: fail the build if .text overlaps the marker block
The text panel grew .text past MARK and the payload overwrote its own code
with cell() writes (illegal opcode on the unit). The build now parses
build/lance.map and aborts if the end of .text reaches MARK, printing the
remaining gap.
2026-10-30 15:58:16 +02:00

112 lines
3.8 KiB
Bash
Executable File

#!/bin/sh
# Build the raw LANCE receive probe.
#
# harness/udpstream/build.sh
#
# .text at bit 0x018C0000, .bss at 0x01C00000 (both inside the firmware's large
# free block), entry _start, no .cinit (the runtime's autoinit pass does not
# run -- see harness/c-hello/README.md).
set -eu
ROOT=$(cd "$(dirname "$0")/../.." && pwd)
DIR=$(cd "$(dirname "$0")" && pwd)
WORK="$DIR/work"
OUT="$DIR/build"
IMG="$ROOT/tools/tms34010-sdk/1987-05 TMS34010 SDK/1987-11-06 TMS34010 Simulator-C Tools-ASM Tools.img"
DOSBOX_CONF="$ROOT/harness/sdk-scratch/dosbox-bench.conf"
TEXT=018C0000
BSS=01C00000
mkdir -p "$WORK" "$OUT"
if [ ! -x "$WORK/GSPCG.EXE" ]; then
mcopy -s -n -i "$IMG" "::/A2/*" "$WORK/"
mcopy -s -n -i "$IMG" "::/C2/*" "$WORK/"
fi
SRC=${LANCE_SRC:-$DIR/lance.c}
cp "$SRC" "$WORK/LANCE.C"
cp "$DIR/romapi.h" "$WORK/ROMAPI.H"
cp "$DIR/entry.asm" "$WORK/ENTRY.ASM"
{
printf '%s\n' '-a'
printf '%s\n' '-o LANCE.out'
printf '%s\n' '-m LANCE.map'
printf '%s\n' '-e _start'
printf '%s\n' 'LANCE.obj'
printf '%s\n' 'ENTRY.obj'
printf '%s\n' '-l RTS.LIB'
printf '%s\n' 'MEMORY'
printf '%s\n' '{'
printf '%s\n' " prog: origin = ${TEXT}h, length = 20000h"
printf '%s\n' " ram: origin = ${BSS}h, length = 40000h"
printf '%s\n' '}'
printf '%s\n' 'SECTIONS'
printf '%s\n' '{'
printf '%s\n' ' .text: {} > prog'
printf '%s\n' ' .data: {} > prog'
printf '%s\n' ' .cinit: {} > prog'
printf '%s\n' ' .bss: {} > ram'
printf '%s\n' '}'
} > "$WORK/LANCE.CMD"
sed -i 's/$/\r/' "$WORK/LANCE.CMD"
rm -f "$WORK"/LANCE.OBJ "$WORK"/LANCE.OUT "$WORK"/LANCE.LST \
"$WORK"/LANCE.MAP "$WORK"/LANCE.ASM "$WORK"/LANCE.CPP \
"$WORK"/LANCE.IF "$WORK"/ENTRY.OBJ "$WORK"/ENTRY.LST
SDL_VIDEODRIVER=dummy SDL_AUDIODRIVER=dummy \
timeout 240 dosbox -conf "$DOSBOX_CONF" -noprimaryconf -nolocalconf \
-c "mount c $WORK" -c "c:" \
-c "gspcpp LANCE" \
-c "gspcc LANCE" \
-c "gspcg LANCE" \
-c "gspa LANCE LANCE.obj LANCE.lst -l" \
-c "gspa ENTRY ENTRY.obj ENTRY.lst -l" \
-c "gsplnk LANCE.cmd" \
-c "exit" -exit > "$WORK/dosbox.log" 2>&1
if [ ! -f "$WORK/LANCE.OUT" ]; then
echo "build.sh: GSPLNK produced no LANCE.OUT" >&2
sed 's/\r$//' "$WORK/LANCE.MAP" 2>/dev/null | tail -20 >&2 || true
for f in LANCE.LST ENTRY.LST; do
sed 's/\r$//' "$WORK/$f" 2>/dev/null | grep -i 'error' | grep -vi 'no errors' >&2 || true
done
exit 1
fi
for f in LANCE.LST ENTRY.LST; do
if sed 's/\r$//' "$WORK/$f" | grep -i 'error' | grep -qvi 'no errors'; then
echo "build.sh: $f diagnostics:" >&2
sed 's/\r$//' "$WORK/$f" | grep -in 'error' | grep -vi 'no errors' >&2
exit 1
fi
done
OUTNAME=${LANCE_OUT:-lance.coff}
cp "$WORK/LANCE.OUT" "$OUT/$OUTNAME"
sed 's/\r$//' "$WORK/LANCE.MAP" > "$OUT/lance.map"
# Guard: the marker block (MARK in the source) must sit clear of .text, or the
# payload overwrites its own code with cell() writes (an illegal-opcode crash).
python3 - "$SRC" "$OUT/lance.map" <<'PYCHK'
import re, sys
src, mp = sys.argv[1], sys.argv[2]
m = re.search(r'#define\s+MARK\s+(0x[0-9A-Fa-f]+)', open(src).read())
if m:
mark = int(m.group(1), 16)
for ln in open(mp):
f = ln.split()
if len(f) >= 4 and f[0] == '.text':
start, size = int(f[2], 16), int(f[3], 16)
end = start + size
if end > mark:
sys.stderr.write("build: ERROR .text ends at 0x%X, past MARK 0x%X\n" % (end, mark))
sys.exit(1)
print("build: .text ends 0x%X, MARK 0x%X (%d bytes clear)" % (end, mark, (mark - end) // 8))
PYCHK
sed 's/\r$//' "$WORK/LANCE.LST" > "$OUT/lance.lst"
sed 's/\r$//' "$WORK/ENTRY.LST" > "$OUT/entry.lst"
echo "build.sh: $OUT/$OUTNAME ($(wc -c < "$OUT/lance.coff") bytes)"
grep -E "ENTRY POINT|^\.(text|cinit|bss)" "$OUT/lance.map" | head -8