dwt/loader: COFF loader places GSPLNK images and runs them via create_process

This commit is contained in:
SDD committed 2026-10-18 15:19:44 +03:00
1 parent dcca6bee4d
commit 139d89a10c
42 files changed
+3822

No files matched your search

+3
View File
@@ -0,0 +1,3 @@
# Local SDK extraction and private emulator state; never commit.
work/
run/
+60
View File
@@ -0,0 +1,60 @@
# dwt/loader — the COFF loader half of the app loader
Loads a GSPLNK-linked COFF image that is already in RAM into a **first-class
process** on the VT1200 OS. The transport (TFTP) is separate; this half takes a
buffer and length, picks the addresses from the COFF, and calls
`create_process`.
Read `dwt/notes/LOADER.md` for the full report and
`dwt/notes/LOADER_CROSS.md` for the transport interface.
## Files
| file | purpose |
|---|---|
| `loader.asm` | the loader; linked at bit `0x01880000`, raw `.bin` 1220 B |
| `marker.asm` | acceptance app with `.text`/`.data`/`.bss` at three addresses |
| `coff.py` | TI COFF reader/dumper (`summary`, `raw`, `manifest`) |
| `build.sh` | GSPA/GSPLNK wrapper; keeps the linked COFF |
| `reldemo.sh`, `rel_a.asm`, `rel_b.asm` | relocation and position-dependence demo |
| `loader.lua` | debugger-assisted harness (no network, no rdebug) |
| `probe_os.lua` | heap-list and register-write probe used to design the harness |
| `build/` | linked loader/app COFFs, raw `.bin`s, maps, listings |
| `evidence/` | run logs, COFF dumps, the xhello window frame |
`work/` (the DOS tools extracted from the SDK floppy) and `run/` (private
NVRAM/cfg) are local scratch and ignored.
## Build
```sh
./dwt/loader/build.sh dwt/loader/loader.asm 01880000
./dwt/loader/build.sh dwt/loader/marker.asm 018C0000 018D0000 018D8000
./dwt/loader/build.sh dwt/gui/xhello.asm 01840000
./dwt/loader/reldemo.sh
```
`build.sh` takes `SOURCE.asm [TEXT_ORIGIN [DATA_ORIGIN [BSS_ORIGIN]]]`
(origins are **bit** addresses) and writes `build/<name>.coff`, `.bin`, `.map`,
`.lst`, `.obj`.
## Run (debugger-assisted, no network)
```sh
VT1200_SKIP_LEVEL1=1 LOADER_AT=2500 LOADER_END=2620 \
LOADER_COFF=dwt/loader/build/marker.coff LOADER_OUT=$PWD/dwt/loader/evidence \
/home/arti/code/k-space/mame0289/vt1200 vt1200 \
-rompath harness/mame/roms -video none -sound none -nothrottle -skip_gameinfo \
-nvram_directory $PWD/dwt/loader/run/nvram \
-cfg_directory $PWD/dwt/loader/run/cfg \
-debug -debugger none \
-autoboot_script dwt/loader/loader.lua -autoboot_delay 0
```
The script pokes the loader at `0x01880000` and the COFF at `LOADER_BUF`
(default `0x01900000`), writes the descriptor, and sets `PC`. It never uses the
network, the rdebug service or a firmware transport.
Knobs: `LOADER_MODE=1` (callable/return instead of debug-resume),
`LOADER_A8_DESC=1` (descriptor in `A8`), `LOADER_SNAP=1` (PNG at `LOADER_END`),
`LOADER_VERBOSE=1`, `LOADER_TRACE=1`.
+105
View File
@@ -0,0 +1,105 @@
#!/bin/sh
# Build a VT1200 payload/app with the 1987 TI TMS34010 SDK (GSPA/GSPLNK under
# DOSBox), keeping the linked COFF so dwt/loader/coff.py can inspect it.
#
# dwt/loader/build.sh SOURCE.asm [TEXT_ORIGIN [DATA_ORIGIN [BSS_ORIGIN]]]
#
# Origins are BIT addresses (the TMS34010 and GSPLNK's SECTIONS origins are
# bit addresses). With only TEXT_ORIGIN the linker command binds .text alone,
# exactly like dwt/gui/build.sh. With DATA_ORIGIN/BSS_ORIGIN it binds all
# three sections, which is what the marker app needs.
#
# Outputs, all under dwt/loader/build/:
# <name>.bin the linked .text bytes (convenience; not a COFF)
# <name>.coff the GSPLNK output, byte-for-byte (the loader's real input)
# <name>.map the link map
# <name>.lst the assembler listing (addresses in bits)
#
# ENTRY_SYM=<symbol> adds `-e <symbol>`; default is `_start` if the symbol
# exists, otherwise no -e (GSPLNK then writes entry = 0).
set -eu
ROOT=$(cd "$(dirname "$0")/../.." && pwd)
DIR=$(cd "$(dirname "$0")" && pwd)
SRC=${1:?usage: build.sh SOURCE.asm [TEXT_ORIGIN [DATA_ORIGIN [BSS_ORIGIN]]]}
TEXT=${2:-01800000}
DATA=${3:-}
BSS=${4:-}
NAME=$(basename "$SRC" .asm)
BASE=$(printf '%s' "$NAME" | tr 'a-z' 'A-Z')
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"
mkdir -p "$WORK" "$OUT"
if [ ! -x "$WORK/GSPA.EXE" ]; then
mcopy -s -n -i "$IMG" "::/A2/*" "$WORK/"
mcopy -s -n -i "$IMG" "::/C2/*" "$WORK/"
fi
cp "$SRC" "$WORK/$BASE.ASM"
# TI hex constants must begin with a decimal digit.
tihex() {
case "$1" in
[0-9]*) printf '%s' "$1" ;;
*) printf '0%s' "$1" ;;
esac
}
TEXT=$(tihex "$TEXT")
ENTRY=${ENTRY_SYM:-_start}
{
printf '%s\n' '-a'
printf '%s\n' '-o '"$BASE"'.out'
printf '%s\n' '-m '"$BASE"'.map'
[ -n "${ENTRY:-}" ] && printf '%s\n' '-e '"$ENTRY"
printf '%s\n' "$BASE.obj"
printf '%s\n' 'SECTIONS'
printf '%s\n' '{'
printf '%s\n' " .text ${TEXT}h: {}"
if [ -n "$DATA" ]; then
printf '%s\n' " .data $(tihex "$DATA")h: {}"
fi
if [ -n "$BSS" ]; then
printf '%s\n' " .bss $(tihex "$BSS")h: {}"
fi
printf '%s\n' '}'
} > "$WORK/$BASE.CMD"
sed -i 's/$/\r/' "$WORK/$BASE.CMD"
rm -f "$WORK/$BASE.OBJ" "$WORK/$BASE.OUT" "$WORK/$BASE.LST" \
"$WORK/$BASE.MAP" "$WORK/$BASE.HI" "$WORK/$BASE.LO"
SDL_VIDEODRIVER=dummy SDL_AUDIODRIVER=dummy \
timeout 180 dosbox -conf "$DOSBOX_CONF" -noprimaryconf -nolocalconf \
-c "mount c $WORK" -c "c:" \
-c "gspa $BASE $BASE.obj $BASE.lst -l" \
-c "gsplnk $BASE.cmd" \
-c "exit" -exit >/dev/null 2>&1
if [ ! -f "$WORK/$BASE.OUT" ]; then
echo "build.sh: GSPLNK produced no $BASE.OUT" >&2
sed 's/\r$//' "$WORK/$BASE.MAP" 2>/dev/null | tail -20 >&2 || true
exit 1
fi
if [ ! -f "$WORK/$BASE.OBJ" ]; then
echo "build.sh: GSPA produced no $BASE.OBJ" >&2
grep -n '\*\*\*\*\*' "$WORK/$BASE.LST" >&2 || true
exit 1
fi
if grep -q '\*\*\*\*\*' "$WORK/$BASE.LST"; then
echo "build.sh: assembler diagnostics:" >&2
grep -n '\*\*\*\*\*' "$WORK/$BASE.LST" >&2
exit 1
fi
cp "$WORK/$BASE.OUT" "$OUT/$NAME.coff"
cp "$WORK/$BASE.OBJ" "$OUT/$NAME.obj"
sed 's/\r$//' "$WORK/$BASE.MAP" > "$OUT/$NAME.map"
cp "$WORK/$BASE.LST" "$OUT/$NAME.lst"
python3 "$ROOT/harness/hello-world/cofextract.py" "$WORK/$BASE.OUT" "$OUT/$NAME.bin"
echo "build.sh: $OUT/$NAME.coff ($(wc -c < "$OUT/$NAME.coff") bytes); .bin $(wc -c < "$OUT/$NAME.bin") bytes at bit $TEXT"
Binary file not shown.
Binary file not shown.
+746
View File
@@ -0,0 +1,746 @@
GSP COFF Assembler, Version 2.00, 87.300 Sun Oct 18 15:19:03 2026
(c) Copyright 1985, 1987, Texas Instruments Inc.
PAGE 1
0001 ; loader.asm -- COFF loader for the VT1200 / TMS34010.
0002 ;
0003 ; Input: a TI GSP COFF image (GSPLNK `-a` output) alrea
0004 ; 16-byte descriptor (offsets in BITS, since all pointe
0005 ; addresses; the byte offsets are 0, 2, 4, 8 and 12):
0006 ;
0007 ; DESC + 0x00 bits u16 0x4C44 "LD" ) magic; both
0008 ; DESC + 0x10 bits u16 0x5231 "R1" )
0009 ; DESC + 0x20 bits u32 buf bit address of
0010 ; DESC + 0x40 bits u32 len length in byte
0011 ; DESC + 0x60 bits u32 mode 1 = return to
0012 ; 0 = debug resu
0013 ;
0014 ; The descriptor pointer is A8. If A8 is zero, or does
0015 ; descriptor, the fixed descriptor at 0x01882C00 is use
0016 ; receives a COFF over the network only has to write {b
0017 ; call the loader entry; it does not choose a load addr
0018 ; the addresses from the COFF section headers.
0019 ;
0020 ; Result block at 0x01882D00 (32-bit cells, bit address
0021 ;
0022 ; +0x000 status 0 ok, nonzero = error (see the l
0023 ; +0x020 entry bit address passed to create_pro
0024 ; +0x040 text addr .text paddr from the COFF (bits)
0025 ; +0x060 text size .text size (bits)
0026 ; +0x080 data addr .data paddr
0027 ; +0x0A0 data size .data size (bits)
0028 ; +0x0C0 bss addr .bss paddr
0029 ; +0x0E0 bss size .bss size (bits)
0030 ; +0x100 relocs relocation entries seen in the o
0031 ; +0x120 pcb create_process() return value (0
0032 ; +0x140 nscns section count from the file head
0033 ; +0x160 coflen length from the descriptor (byte
0034 ; +0x180 version loader base address, 0x01880000
0035 ;
0036 ; The image is POSITION-DEPENDENT: GSPLNK resolves ever
0037 ; nreloc = 0, so each section is copied to the bit addr
0038 ; no relocation is applied. A COFF that still carries
0039 ; refused (status 7) rather than guessed at.
0040 ;
0041 ; Safety checks before any copy:
0042 ; * size is a whole number of 16-bit words;
0043 ; * the section bytes lie inside the descriptor's (bu
0044 ; * paddr..paddr+size is inside main RAM (bits 0x100.
0045 ; * it does not overlap the loader page [01880000,018
0046 ; buffer;
0047 ; * it lies inside one block of the firmware's global
0048 ; (head at bit 0x1E8AC0, block header {u32 size_bit
0049 ; user data at block+0x40). This is a check, not a
0050 ; loader cannot make malloc hand out a chosen addre
0051 ;
0052 ; Delivered debugger-assisted for now: poke the raw .bi
0053 ; the COFF at buf, write the descriptor, then set PC =
0054 ; fine). mode = 0 resumes at LD_ORIG_PC (the harness s
0055 ; PC); mode = 1 returns to the caller and passes the st
0056 ;
GSP COFF Assembler, Version 2.00, 87.300 Sun Oct 18 15:19:03 2026
(c) Copyright 1985, 1987, Texas Instruments Inc.
PAGE 2
0057 ; Linked at bit 0x01880000; position-dependent itself.
0058
0059 .def _start
0060
0061 01880000 LOADER_BASE equ 01880000h
0062 01882800 LD_SCRATCH equ 01882800h
0063 01882C00 DESC_ADDR equ 01882C00h
0064 01882D00 RESULT_BASE equ 01882D00h
0065 01882B00 ARG_AREA equ 01882B00h
0066 01883100 RETURN_STUB equ 01883100h
0067
0068 01882800 LD_SP_AFTER equ LD_SCRATCH+000h
0069 01882820 LD_A14 equ LD_SCRATCH+020h
0070 01882840 LD_ENTRY equ LD_SCRATCH+040h
0071 01882860 LD_BUF equ LD_SCRATCH+060h
0072 01882880 LD_LEN equ LD_SCRATCH+080h
0073 018828A0 LD_MODE equ LD_SCRATCH+0A0h
0074 018828C0 LD_NSCNS equ LD_SCRATCH+0C0h
0075 018828E0 LD_RELOCS equ LD_SCRATCH+0E0h
0076 01882900 LD_SEC_PADDR equ LD_SCRATCH+100h
0077 01882920 LD_SEC_SIZE equ LD_SCRATCH+120h
0078 01882940 LD_SEC_SCNPTR equ LD_SCRATCH+140h
0079 01882960 LD_TEXT_ADDR equ LD_SCRATCH+160h
0080 01882980 LD_TEXT_SIZE equ LD_SCRATCH+180h
0081 018829A0 LD_DATA_ADDR equ LD_SCRATCH+1A0h
0082 018829C0 LD_DATA_SIZE equ LD_SCRATCH+1C0h
0083 018829E0 LD_BSS_ADDR equ LD_SCRATCH+1E0h
0084 01882A00 LD_BSS_SIZE equ LD_SCRATCH+200h
0085 01882A20 LD_ORIG_PC equ LD_SCRATCH+220h
0086
0087 01882D00 RESULT_STATUS equ RESULT_BASE+000h
0088 01882D20 RESULT_ENTRY equ RESULT_BASE+020h
0089 01882D40 RESULT_TEXT_A equ RESULT_BASE+040h
0090 01882D60 RESULT_TEXT_S equ RESULT_BASE+060h
0091 01882D80 RESULT_DATA_A equ RESULT_BASE+080h
0092 01882DA0 RESULT_DATA_S equ RESULT_BASE+0A0h
0093 01882DC0 RESULT_BSS_A equ RESULT_BASE+0C0h
0094 01882DE0 RESULT_BSS_S equ RESULT_BASE+0E0h
0095 01882E00 RESULT_RELOCS equ RESULT_BASE+100h
0096 01882E20 RESULT_PCB equ RESULT_BASE+120h
0097 01882E40 RESULT_NSCNS equ RESULT_BASE+140h
0098 01882E60 RESULT_LEN equ RESULT_BASE+160h
0099 01882E80 RESULT_VERSION equ RESULT_BASE+180h
0100
0101 00000000 .text
0102 00000000 _start:
0103 00000000 098F mmtm sp, a0,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13
00000010 FFFC
0104 00000020 078F move sp, @LD_SP_AFTER, 1
00000030 01882800
0105 00000050 078E move a14, @LD_A14, 1
00000060 01882820
0106 00000080 0550 setf 16, 0, 0
0107 00000090 0740 setf 32, 0, 1
0108
0109 ; ---- descriptor ------------------------------------
GSP COFF Assembler, Version 2.00, 87.300 Sun Oct 18 15:19:03 2026
(c) Copyright 1985, 1987, Texas Instruments Inc.
PAGE 3
0110 ; A8 points at it only if both magic words match; else
0111 000000A0 4D06 move a8, a6
0112 000000B0 4D08 move a8, a8
0113 000000C0 CA09 jreq ld_fixed_desc
0114 000000D0 84C0 move *a6, a0, 0
0115 000000E0 0B40 cmpi 4C44h, a0
000000F0 B3BB
0116 00000100 CB05 jrne ld_fixed_desc
0117 00000110 B4C0 move *a6(10h), a0, 0
00000120 0010
0118 00000130 0B40 cmpi 5231h, a0
00000140 ADCE
0119 00000150 CA0E jreq ld_have_desc
0120 00000160 ld_fixed_desc:
0121 00000160 09E6 movi DESC_ADDR, a6, L
00000170 01882C00
0122 00000190 84C0 move *a6, a0, 0
0123 000001A0 0B40 cmpi 4C44h, a0
000001B0 B3BB
0124 000001C0 CB00 jrne ld_bad_desc
000001D0 01D5
0125 000001E0 B4C0 move *a6(10h), a0, 0
000001F0 0010
0126 00000200 0B40 cmpi 5231h, a0
00000210 ADCE
0127 00000220 CB00 jrne ld_bad_desc
00000230 01CF
0128 00000240 ld_have_desc:
0129 00000240 B6C7 move *a6(20h), a7, 1 ; buf
00000250 0020
0130 00000260 B6C8 move *a6(40h), a8, 1 ; len
00000270 0040
0131 00000280 B6CC move *a6(60h), a12, 1 ; mode
00000290 0060
0132 000002A0 0787 move a7, @LD_BUF, 1
000002B0 01882860
0133 000002D0 0788 move a8, @LD_LEN, 1
000002E0 01882880
0134 00000300 078C move a12, @LD_MODE, 1
00000310 018828A0
0135 00000330 078C move a12, @RESULT_VERSION, 1 ; harmless; overwritten b
00000340 01882E80
0136 00000360 09E0 movi LOADER_BASE, a0, L
00000370 01880000
0137 00000390 0780 move a0, @RESULT_VERSION, 1
000003A0 01882E80
0138
0139 ; clear the counters we report; status stays FF until
0140 000003C0 09E0 movi 0FFFFFFFFh, a0, L
000003D0 FFFFFFFF
0141 000003F0 0780 move a0, @RESULT_STATUS, 1
00000400 01882D00
0142 00000420 4400 sub a0, a0
0143 00000430 0780 move a0, @LD_RELOCS, 1
00000440 018828E0
0144 00000460 0780 move a0, @LD_TEXT_ADDR, 1
GSP COFF Assembler, Version 2.00, 87.300 Sun Oct 18 15:19:03 2026
(c) Copyright 1985, 1987, Texas Instruments Inc.
PAGE 4
00000470 01882960
0145 00000490 0780 move a0, @LD_TEXT_SIZE, 1
000004A0 01882980
0146 000004C0 0780 move a0, @LD_DATA_ADDR, 1
000004D0 018829A0
0147 000004F0 0780 move a0, @LD_DATA_SIZE, 1
00000500 018829C0
0148 00000520 0780 move a0, @LD_BSS_ADDR, 1
00000530 018829E0
0149 00000550 0780 move a0, @LD_BSS_SIZE, 1
00000560 01882A00
0150 00000580 0780 move a0, @RESULT_ENTRY, 1
00000590 01882D20
0151 000005B0 0780 move a0, @RESULT_TEXT_A, 1
000005C0 01882D40
0152 000005E0 0780 move a0, @RESULT_TEXT_S, 1
000005F0 01882D60
0153 00000610 0780 move a0, @RESULT_DATA_A, 1
00000620 01882D80
0154 00000640 0780 move a0, @RESULT_DATA_S, 1
00000650 01882DA0
0155 00000670 0780 move a0, @RESULT_BSS_A, 1
00000680 01882DC0
0156 000006A0 0780 move a0, @RESULT_BSS_S, 1
000006B0 01882DE0
0157 000006D0 0780 move a0, @RESULT_RELOCS, 1
000006E0 01882E00
0158 00000700 0780 move a0, @RESULT_PCB, 1
00000710 01882E20
0159
0160 ; ---- file header -----------------------------------
0161 00000730 09E0 movi 20, a0, L
00000740 00000014
0162 00000760 4808 cmp a0, a8
0163 00000770 C800 jrlo ld_err_short
00000780 017E
0164 00000790 84E0 move *a7, a0, 0 ; magic
0165 000007A0 0B40 cmpi 0090h, a0
000007B0 FF6F
0166 000007C0 CB00 jrne ld_err_magic
000007D0 017D
0167 000007E0 B4E9 move *a7(10h), a9, 0 ; nscns (+2 bytes)
000007F0 0010
0168 00000800 0789 move a9, @LD_NSCNS, 1
00000810 018828C0
0169 00000830 B4E0 move *a7(10h), a0, 0
00000840 0010
0170 00000850 0789 move a9, @RESULT_NSCNS, 1
00000860 01882E40
0171 00000880 0788 move a8, @RESULT_LEN, 1
00000890 01882E60
0172
0173 ; section headers = buf + (20 + opthdr + nscns*40) byt
0174 000008B0 B4E1 move *a7(80h), a1, 0 ; opthdr (+16 bytes)
000008C0 0080
0175 000008D0 4D22 move a9, a2
GSP COFF Assembler, Version 2.00, 87.300 Sun Oct 18 15:19:03 2026
(c) Copyright 1985, 1987, Texas Instruments Inc.
PAGE 5
0176 000008E0 24A2 sll 5, a2 ; nscns*32
0177 000008F0 4D23 move a9, a3
0178 00000900 2463 sll 3, a3 ; nscns*8
0179 00000910 4062 add a3, a2 ; nscns*40
0180 00000920 4022 add a1, a2
0181 00000930 0B02 addi 20, a2 ; byte offset of section headers end
00000940 0014
0182 00000950 4848 cmp a2, a8 ; a8 - a2
0183 00000960 C800 jrlo ld_err_short
00000970 015F
0184
0185 ; secbase = buf + (20 + opthdr)*8 bits
0186 00000980 2461 sll 3, a1 ; opthdr in bits
0187 00000990 0B01 addi 160, a1 ; 20 bytes in bits
000009A0 00A0
0188 000009B0 40E1 add a7, a1
0189 000009C0 4C2A move a1, a10
0190
0191 ; ---- entry point -----------------------------------
0192 ; optional header at buf+20 bytes (0x0A0 bits): magic
0193 ; +16 bytes (0x080 bits further); textstart at +20 byt
0194 000009D0 B4E0 move *a7(0A0h), a0, 0
000009E0 00A0
0195 000009F0 0B40 cmpi 0108h, a0
00000A00 FEF7
0196 00000A10 CB07 jrne ld_no_opt
0197 00000A20 B6E5 move *a7(120h), a5, 1 ; entry (bits)
00000A30 0120
0198 00000A40 4CA5 move a5, a5
0199 00000A50 CB04 jrne ld_entry_set
0200 00000A60 B6E5 move *a7(140h), a5, 1 ; textstart (bits)
00000A70 0140
0201 00000A80 C001 jruc ld_entry_set
0202 00000A90 ld_no_opt:
0203 00000A90 44A5 sub a5, a5
0204
0205 00000AA0 ld_entry_set:
0206 00000AA0 0785 move a5, @LD_ENTRY, 1
00000AB0 01882840
0207 00000AD0 0785 move a5, @RESULT_ENTRY, 1
00000AE0 01882D20
0208
0209 ; ---- section loop ----------------------------------
0210 00000B00 456B sub a11, a11 ; section index
0211 00000B10 ld_sec_loop:
0212 00000B10 492B cmp a9, a11 ; a11 - a9
0213 00000B20 C900 jrhs ld_sec_done
00000B30 00DC
0214 00000B40 B740 move *a10(40h), a0, 1 ; paddr (bits) +8 bytes
00000B50 0040
0215 00000B60 B741 move *a10(80h), a1, 1 ; size (bits) +16
00000B70 0080
0216 00000B80 B742 move *a10(0A0h), a2, 1 ; scnptr (bytes) +20
00000B90 00A0
0217 00000BA0 B543 move *a10(100h), a3, 0 ; nreloc +32
00000BB0 0100
GSP COFF Assembler, Version 2.00, 87.300 Sun Oct 18 15:19:03 2026
(c) Copyright 1985, 1987, Texas Instruments Inc.
PAGE 6
0218 00000BC0 B744 move *a10(120h), a4, 1 ; flags +36
00000BD0 0120
0219 00000BE0 0780 move a0, @LD_SEC_PADDR, 1
00000BF0 01882900
0220 00000C10 0781 move a1, @LD_SEC_SIZE, 1
00000C20 01882920
0221 00000C40 0782 move a2, @LD_SEC_SCNPTR, 1
00000C50 01882940
0222
0223 ; record the first text/data/bss section for the resul
0224 00000C70 4C85 move a4, a5
0225 00000C80 0B85 andi 20h, a5
00000C90 FFFFFFDF
0226 00000CB0 4CA5 move a5, a5
0227 00000CC0 CA0B jreq ld_not_text
0228 00000CD0 07A5 move @LD_TEXT_ADDR, a5, 1
00000CE0 01882960
0229 00000D00 4CA5 move a5, a5
0230 00000D10 CB06 jrne ld_not_text
0231 00000D20 0780 move a0, @LD_TEXT_ADDR, 1
00000D30 01882960
0232 00000D50 0781 move a1, @LD_TEXT_SIZE, 1
00000D60 01882980
0233 00000D80 ld_not_text:
0234 00000D80 4C85 move a4, a5
0235 00000D90 0B85 andi 40h, a5
00000DA0 FFFFFFBF
0236 00000DC0 4CA5 move a5, a5
0237 00000DD0 CA0B jreq ld_not_data
0238 00000DE0 07A5 move @LD_DATA_ADDR, a5, 1
00000DF0 018829A0
0239 00000E10 4CA5 move a5, a5
0240 00000E20 CB06 jrne ld_not_data
0241 00000E30 0780 move a0, @LD_DATA_ADDR, 1
00000E40 018829A0
0242 00000E60 0781 move a1, @LD_DATA_SIZE, 1
00000E70 018829C0
0243 00000E90 ld_not_data:
0244 00000E90 4C85 move a4, a5
0245 00000EA0 0B85 andi 80h, a5
00000EB0 FFFFFF7F
0246 00000ED0 4CA5 move a5, a5
0247 00000EE0 CA0B jreq ld_not_bss
0248 00000EF0 07A5 move @LD_BSS_ADDR, a5, 1
00000F00 018829E0
0249 00000F20 4CA5 move a5, a5
0250 00000F30 CB06 jrne ld_not_bss
0251 00000F40 0780 move a0, @LD_BSS_ADDR, 1
00000F50 018829E0
0252 00000F70 0781 move a1, @LD_BSS_SIZE, 1
00000F80 01882A00
0253 00000FA0 ld_not_bss:
0254
0255 ; relocation records: count, then refuse (the linked i
0256 00000FA0 4C63 move a3, a3
0257 00000FB0 CA09 jreq ld_no_reloc
GSP COFF Assembler, Version 2.00, 87.300 Sun Oct 18 15:19:03 2026
(c) Copyright 1985, 1987, Texas Instruments Inc.
PAGE 7
0258 00000FC0 07A5 move @LD_RELOCS, a5, 1
00000FD0 018828E0
0259 00000FF0 4065 add a3, a5
0260 00001000 0785 move a5, @LD_RELOCS, 1
00001010 018828E0
0261 00001030 C000 jruc ld_err_reloc
00001040 0106
0262 00001050 ld_no_reloc:
0263
0264 ; size 0: nothing to place; size must be whole 16-bit
0265 00001050 4C21 move a1, a1
0266 00001060 CA00 jreq ld_sec_next
00001070 0082
0267 00001080 4C25 move a1, a5
0268 00001090 0B85 andi 0Fh, a5
000010A0 FFFFFFF0
0269 000010C0 4CA5 move a5, a5
0270 000010D0 CB00 jrne ld_err_size
000010E0 00F0
0271
0272 ; source range: scnptr + size/8 <= len (when there are
0273 000010F0 4C42 move a2, a2
0274 00001100 CA06 jreq ld_no_src
0275 00001110 4C25 move a1, a5
0276 00001120 2FA5 srl 3, a5 ; size in bytes
0277 00001130 40A2 add a5, a2 ; scnptr + nbytes
0278 00001140 4902 cmp a8, a2 ; a8 - a2
0279 00001150 C300 jrhi ld_err_short
00001160 00E0
0280 00001170 ld_no_src:
0281
0282 ; target range: 0x100 <= paddr and paddr+size <= 0x200
0283 00001170 07A0 move @LD_SEC_PADDR, a0, 1
00001180 01882900
0284 000011A0 0B40 cmpi 100h, a0
000011B0 FEFF
0285 000011C0 C800 jrlo ld_err_bounds
000011D0 00E5
0286 000011E0 07A1 move @LD_SEC_SIZE, a1, 1
000011F0 01882920
0287 00001210 4C03 move a0, a3
0288 00001220 4023 add a1, a3 ; target end
0289 00001230 09E5 movi 2000000h, a5, L
00001240 02000000
0290 00001260 48A3 cmp a5, a3
0291 00001270 C300 jrhi ld_err_bounds
00001280 00DA
0292
0293 ; overlap with the loader page [01880000,01883200)
0294 00001290 09E5 movi 01883200h, a5, L
000012A0 01883200
0295 000012C0 48A0 cmp a5, a0
0296 000012D0 C907 jrhs ld_ov1_done
0297 000012E0 09E5 movi 01880000h, a5, L
000012F0 01880000
0298 00001310 4865 cmp a3, a5
GSP COFF Assembler, Version 2.00, 87.300 Sun Oct 18 15:19:03 2026
(c) Copyright 1985, 1987, Texas Instruments Inc.
PAGE 8
0299 00001320 C902 jrhs ld_ov1_done
0300 00001330 C000 jruc ld_err_overlap
00001340 00D2
0301 00001350 ld_ov1_done:
0302
0303 ; overlap with the COFF buffer [buf, buf+len*8)
0304 00001350 4D05 move a8, a5
0305 00001360 2465 sll 3, a5
0306 00001370 40E5 add a7, a5 ; buffer end in bits
0307 00001380 48A0 cmp a5, a0
0308 00001390 C904 jrhs ld_ov2_done
0309 000013A0 4867 cmp a3, a7
0310 000013B0 C902 jrhs ld_ov2_done
0311 000013C0 C000 jruc ld_err_overlap
000013D0 00C9
0312 000013E0 ld_ov2_done:
0313
0314 ; ---- global free-list check ------------------------
0315 ; a block is {u32 size_bits; ...; u32 next@+0x20}; dat
0316 000013E0 0780 move a0, @LD_SEC_PADDR, 1 ; (unchanged, kept for clari
000013F0 01882900
0317 00001410 0783 move a3, @LD_SEC_SIZE, 1 ; temporarily hold target end
00001420 01882920
0318 00001440 07A6 move @1E8AC0h, a6, 1 ; global free-list head (block a
00001450 001E8AC0
0319 00001470 09E5 movi 64, a5, L
00001480 00000040
0320 000014A0 ld_free_walk:
0321 000014A0 4CC6 move a6, a6
0322 000014B0 CA00 jreq ld_err_notfree
000014C0 00C2
0323 000014D0 86C1 move *a6, a1, 1 ; block size in bits
0324 000014E0 B6C2 move *a6(20h), a2, 1 ; next block
000014F0 0020
0325 00001500 4CC0 move a6, a0
0326 00001510 0B00 addi 40h, a0 ; user start
00001520 0040
0327 00001530 07A3 move @LD_SEC_PADDR, a3, 1
00001540 01882900
0328 00001560 4803 cmp a0, a3
0329 00001570 C808 jrlo ld_free_next
0330 00001580 4CC4 move a6, a4
0331 00001590 4024 add a1, a4 ; block end
0332 000015A0 07A1 move @LD_SEC_SIZE, a1, 1 ; target end (stashed above)
000015B0 01882920
0333 000015D0 4881 cmp a4, a1
0334 000015E0 C301 jrhi ld_free_next
0335 000015F0 C004 jruc ld_free_ok
0336 00001600 ld_free_next:
0337 00001600 4C46 move a2, a6
0338 00001610 3F05 dsjs a5, ld_free_walk
0339 00001620 C000 jruc ld_err_notfree
00001630 00AB
0340 00001640 ld_free_ok:
0341
0342 ; restore size in LD_SEC_SIZE (the stash overwrote it)
GSP COFF Assembler, Version 2.00, 87.300 Sun Oct 18 15:19:03 2026
(c) Copyright 1985, 1987, Texas Instruments Inc.
PAGE 9
0343 ; target end - paddr = size
0344 00001640 07A1 move @LD_SEC_SIZE, a1, 1
00001650 01882920
0345 00001670 07A0 move @LD_SEC_PADDR, a0, 1
00001680 01882900
0346 000016A0 4401 sub a0, a1 ; a1 = size again
0347 000016B0 0781 move a1, @LD_SEC_SIZE, 1
000016C0 01882920
0348
0349 ; ---- place the section -----------------------------
0350 000016E0 07A0 move @LD_SEC_SCNPTR, a0, 1
000016F0 01882940
0351 00001710 4C00 move a0, a0
0352 00001720 CA0D jreq ld_zero_sec
0353 00001730 2460 sll 3, a0 ; file offset -> bit offset
0354 00001740 40E0 add a7, a0 ; source address
0355 00001750 07A2 move @LD_SEC_PADDR, a2, 1
00001760 01882900
0356 00001780 07A1 move @LD_SEC_SIZE, a1, 1
00001790 01882920
0357 000017B0 2F81 srl 4, a1 ; number of 16-bit words
0358 000017C0 ld_copy_words:
0359 000017C0 9404 move *a0+, a4, 0
0360 000017D0 9082 move a4, *a2+, 0
0361 000017E0 3C61 dsjs a1, ld_copy_words
0362 000017F0 C00A jruc ld_sec_next
0363
0364 00001800 ld_zero_sec:
0365 00001800 07A2 move @LD_SEC_PADDR, a2, 1
00001810 01882900
0366 00001830 07A1 move @LD_SEC_SIZE, a1, 1
00001840 01882920
0367 00001860 2F81 srl 4, a1
0368 00001870 4484 sub a4, a4
0369 00001880 ld_zero_words:
0370 00001880 9082 move a4, *a2+, 0
0371 00001890 3C41 dsjs a1, ld_zero_words
0372
0373 000018A0 ld_sec_next:
0374 000018A0 0B0A addi 140h, a10 ; 40-byte section header = 320 bits
000018B0 0140
0375 000018C0 0B0B addi 1, a11
000018D0 0001
0376 000018E0 C000 jruc ld_sec_loop
000018F0 FF21
0377
0378 00001900 ld_sec_done:
0379 00001900 07A0 move @LD_TEXT_ADDR, a0, 1
00001910 01882960
0380 00001930 0780 move a0, @RESULT_TEXT_A, 1
00001940 01882D40
0381 00001960 07A1 move @LD_TEXT_SIZE, a1, 1
00001970 01882980
0382 00001990 0781 move a1, @RESULT_TEXT_S, 1
000019A0 01882D60
0383 000019C0 07A0 move @LD_DATA_ADDR, a0, 1
GSP COFF Assembler, Version 2.00, 87.300 Sun Oct 18 15:19:03 2026
(c) Copyright 1985, 1987, Texas Instruments Inc.
PAGE 10
000019D0 018829A0
0384 000019F0 0780 move a0, @RESULT_DATA_A, 1
00001A00 01882D80
0385 00001A20 07A1 move @LD_DATA_SIZE, a1, 1
00001A30 018829C0
0386 00001A50 0781 move a1, @RESULT_DATA_S, 1
00001A60 01882DA0
0387 00001A80 07A0 move @LD_BSS_ADDR, a0, 1
00001A90 018829E0
0388 00001AB0 0780 move a0, @RESULT_BSS_A, 1
00001AC0 01882DC0
0389 00001AE0 07A1 move @LD_BSS_SIZE, a1, 1
00001AF0 01882A00
0390 00001B10 0781 move a1, @RESULT_BSS_S, 1
00001B20 01882DE0
0391 00001B40 07A0 move @LD_RELOCS, a0, 1
00001B50 018828E0
0392 00001B70 0780 move a0, @RESULT_RELOCS, 1
00001B80 01882E00
0393
0394 ; ---- create_process(entry, name, stack, 1, arg) ----
0395 00001BA0 07A0 move @LD_ENTRY, a0, 1
00001BB0 01882840
0396 00001BD0 4C00 move a0, a0
0397 00001BE0 CB01 jrne ld_have_entry
0398 00001BF0 C053 jruc ld_err_noentry
0399 00001C00 ld_have_entry:
0400 00001C00 07AE move @LD_A14, a14, 1
00001C10 01882820
0401 00001C30 07AF move @LD_SP_AFTER, sp, 1
00001C40 01882800
0402 00001C60 A3CF move a14, -*sp, 1 ; the slot the firmware callee rest
0403 00001C70 09EE movi ARG_AREA, a14, L
00001C80 01882B00
0404 00001CA0 09E0 movi 0, a0, L
00001CB0 00000000
0405 00001CD0 920E move a0, *a14+, 1 ; arg4 = 0
0406 00001CE0 09E0 movi 1, a0, L
00001CF0 00000001
0407 00001D10 920E move a0, *a14+, 1 ; arg3 = 1
0408 00001D20 09E0 movi 6000h, a0, L
00001D30 00006000
0409 00001D50 920E move a0, *a14+, 1 ; arg2 = stack bytes
0410 00001D60 09E0 movi ld_appname, a0, L
00001D70 000025E0'
0411 00001D90 920E move a0, *a14+, 1 ; arg1 = name string
0412 00001DA0 07A0 move @LD_ENTRY, a0, 1
00001DB0 01882840
0413 00001DD0 920E move a0, *a14+, 1 ; arg0 = entry (bit address)
0414 00001DE0 0D5F calla 3F706A40h ; create_process
00001DF0 3F706A40
0415 00001E10 07AF move @LD_SP_AFTER, sp, 1
00001E20 01882800
0416 00001E40 07AE move @LD_A14, a14, 1
00001E50 01882820
0417 00001E70 0550 setf 16, 0, 0
GSP COFF Assembler, Version 2.00, 87.300 Sun Oct 18 15:19:03 2026
(c) Copyright 1985, 1987, Texas Instruments Inc.
PAGE 11
0418 00001E80 0740 setf 32, 0, 1
0419 00001E90 0788 move a8, @RESULT_PCB, 1
00001EA0 01882E20
0420 00001EC0 4D08 move a8, a8
0421 00001ED0 CA29 jreq ld_err_create
0422
0423 00001EE0 4400 sub a0, a0
0424 00001EF0 0780 move a0, @RESULT_STATUS, 1
00001F00 01882D00
0425 00001F20 C036 jruc ld_finish
0426
0427 ; ---- errors ----------------------------------------
0428 00001F30 ld_bad_desc:
0429 00001F30 09E0 movi 1, a0, L
00001F40 00000001
0430 00001F60 C023 jruc ld_error
0431 00001F70 ld_err_short:
0432 00001F70 09E0 movi 2, a0, L
00001F80 00000002
0433 00001FA0 C01F jruc ld_error
0434 00001FB0 ld_err_magic:
0435 00001FB0 09E0 movi 3, a0, L
00001FC0 00000003
0436 00001FE0 C01B jruc ld_error
0437 00001FF0 ld_err_size:
0438 00001FF0 09E0 movi 4, a0, L
00002000 00000004
0439 00002020 C017 jruc ld_error
0440 00002030 ld_err_bounds:
0441 00002030 09E0 movi 5, a0, L
00002040 00000005
0442 00002060 C013 jruc ld_error
0443 00002070 ld_err_overlap:
0444 00002070 09E0 movi 6, a0, L
00002080 00000006
0445 000020A0 C00F jruc ld_error
0446 000020B0 ld_err_reloc:
0447 000020B0 09E0 movi 7, a0, L
000020C0 00000007
0448 000020E0 C00B jruc ld_error
0449 000020F0 ld_err_notfree:
0450 000020F0 09E0 movi 8, a0, L
00002100 00000008
0451 00002120 C007 jruc ld_error
0452 00002130 ld_err_noentry:
0453 00002130 09E0 movi 9, a0, L
00002140 00000009
0454 00002160 C003 jruc ld_error
0455 00002170 ld_err_create:
0456 00002170 09E0 movi 10, a0, L
00002180 0000000A
0457 000021A0 ld_error:
0458 000021A0 0780 move a0, @RESULT_STATUS, 1
000021B0 01882D00
0459 000021D0 07A0 move @LD_NSCNS, a0, 1
000021E0 018828C0
GSP COFF Assembler, Version 2.00, 87.300 Sun Oct 18 15:19:03 2026
(c) Copyright 1985, 1987, Texas Instruments Inc.
PAGE 12
0460 00002200 0780 move a0, @RESULT_NSCNS, 1
00002210 01882E40
0461 00002230 07A0 move @LD_RELOCS, a0, 1
00002240 018828E0
0462 00002260 0780 move a0, @RESULT_RELOCS, 1
00002270 01882E00
0463
0464 00002290 ld_finish:
0465 00002290 07A0 move @LD_ENTRY, a0, 1
000022A0 01882840
0466 000022C0 0780 move a0, @RESULT_ENTRY, 1
000022D0 01882D20
0467 000022F0 07A0 move @LD_NSCNS, a0, 1
00002300 018828C0
0468 00002320 0780 move a0, @RESULT_NSCNS, 1
00002330 01882E40
0469 00002350 07A0 move @LD_LEN, a0, 1
00002360 01882880
0470 00002380 0780 move a0, @RESULT_LEN, 1
00002390 01882E60
0471 000023B0 09E0 movi LOADER_BASE, a0, L
000023C0 01880000
0472 000023E0 0780 move a0, @RESULT_VERSION, 1
000023F0 01882E80
0473
0474 ; ---- return or spin --------------------------------
0475 00002410 07A0 move @LD_MODE, a0, 1
00002420 018828A0
0476 00002440 4C00 move a0, a0
0477 00002450 CB0C jrne ld_return
0478 ; mode 0 (debugger entry): restore the interrupted sta
0479 ; the PC the harness hijacked. Returning to the OS id
0480 ; scheduler run the created child.
0481 00002460 07AF move @LD_SP_AFTER, sp, 1
00002470 01882800
0482 00002490 07AE move @LD_A14, a14, 1
000024A0 01882820
0483 000024C0 09AF mmfm sp, a0,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13
000024D0 3FFF
0484 000024E0 07A0 move @LD_ORIG_PC, a0, 1
000024F0 01882A20
0485 00002510 0160 jump a0
0486
0487 00002520 ld_return:
0488 00002520 07AF move @LD_SP_AFTER, sp, 1
00002530 01882800
0489 00002550 07AE move @LD_A14, a14, 1
00002560 01882820
0490 00002580 09AF mmfm sp, a0,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13
00002590 3FFF
0491 000025A0 07A8 move @RESULT_STATUS, a8, 1 ; 0 = ok, else the error co
000025B0 01882D00
0492 000025D0 0960 rets
0493
0494 000025E0 ld_appname:
0495 000025E0 4C .byte "LOADER", 0
GSP COFF Assembler, Version 2.00, 87.300 Sun Oct 18 15:19:03 2026
(c) Copyright 1985, 1987, Texas Instruments Inc.
PAGE 13
000025E8 4F
000025F0 41
000025F8 44
00002600 45
00002608 52
00002610 00
0496 .end
No Errors, No Warnings
+35
View File
@@ -0,0 +1,35 @@
*****************************************************
GSP COFF Linker, Version 2.00, 87.300
*****************************************************
Sun Oct 18 15:19:03 2026
OUTPUT FILE NAME: <LOADER.out>
ENTRY POINT SYMBOL: "_start" address: 01880000
SECTION ALLOCATION MAP
output attributes/
section page origin length input sections
-------- ---- ---------- ---------- ----------------
.data 0 00000000 00000000
.bss 0 00000000 00000000 UNINITIALIZED
.text 0 01880000 00002620
01880000 00002620 LOADER.obj (.text)
GLOBAL SYMBOLS
address name address name
-------- ---- -------- ----
00000000 .bss 00000000 edata
00000000 .data 00000000 .bss
01880000 .text 00000000 end
01880000 _start 00000000 .data
00000000 edata 01880000 _start
00000000 end 01880000 .text
01882620 etext 01882620 etext
[7 symbols]
Binary file not shown.
Binary file not shown.
Binary file not shown.
+90
View File
@@ -0,0 +1,90 @@
GSP COFF Assembler, Version 2.00, 87.300 Sun Oct 18 15:08:14 2026
(c) Copyright 1985, 1987, Texas Instruments Inc.
PAGE 1
0001 ; marker.asm -- loader acceptance app.
0002 ;
0003 ; Built by dwt/loader/build.sh with three separate sect
0004 ; .text 018C0000h (byte 0x318000)
0005 ; .data 018D0000h (byte 0x31A000)
0006 ; .bss 018D8000h (byte 0x31B000)
0007 ;
0008 ; It is the *COFF image* that the loader must place; it
0009 ; raw blob. The loader parses the COFF, copies .text a
0010 ; and calls create_process() with the image's entry poi
0011 ;
0012 ; Evidence cells (32-bit, bit addresses; outside every
0013 ; 018E0000 _start address at run time (must be 018C0
0014 ; 018E0020 d_magic read from .data (must be DEADBEE
0015 ; 018E0040 d_two read from .data (must be 1234567
0016 ; 018E0060 b_zero read from .bss (must be 0; the
0017 ; 018E0080 b_counter, incremented forever (proves th
0018 ;
0019 ; The harness pre-fills the whole .bss range with A5A5A
0020 ; a zero at 018E0060 is the loader's zero-fill, not a f
0021
0022 .def _start
0023 00000000 .text
0024 00000000 _start:
0025 00000000 0550 setf 16, 0, 0
0026 00000010 0740 setf 32, 0, 1
0027
0028 ; Run-time address of this code: position dependence,
0029 00000020 09E2 movi _start, a2, L
00000030 00000000'
0030 00000050 0782 move a2, @018E0000h, 1
00000060 018E0000
0031
0032 ; Initialised .data must have been copied by the loade
0033 00000080 07A0 move @d_magic, a0, 1
00000090 00000000"
0034 000000B0 0780 move a0, @018E0020h, 1
000000C0 018E0020
0035
0036 000000E0 07A1 move @d_two, a1, 1
000000F0 00000020"
0037 00000110 0781 move a1, @018E0040h, 1
00000120 018E0040
0038
0039 ; .bss must have been zeroed by the loader (harness pr
0040 00000140 07A3 move @b_zero, a3, 1
00000150 00000000+
0041 00000170 0783 move a3, @018E0060h, 1
00000180 018E0060
0042
0043 ; A live counter: a created process, not a one-shot ju
0044 000001A0 4484 sub a4, a4
0045 000001B0 loop:
0046 000001B0 0B04 addi 1, a4
000001C0 0001
0047 000001D0 0784 move a4, @b_counter, 1
GSP COFF Assembler, Version 2.00, 87.300 Sun Oct 18 15:08:14 2026
(c) Copyright 1985, 1987, Texas Instruments Inc.
PAGE 2
000001E0 00000020+
0048 00000200 0784 move a4, @018E0080h, 1
00000210 018E0080
0049 00000230 09E5 movi 2000h, a5, L
00000240 00002000
0050 00000260 delay:
0051 00000260 3C25 dsjs a5, delay
0052 00000270 C0F3 jruc loop
0053
0054 ; Kept to leave a call in the image (and a relocation
0055 .global sub
0056 00000280 sub:
0057 00000280 0960 rets
0058
0059 00000000 .data
0060 00000000 DEADBEEF d_magic: .long 0DEADBEEFh
0061 00000020 12345678 d_two: .long 012345678h
0062
0063 00000000 .bss b_zero, 32, 1
0064 00000020 .bss b_counter, 32, 1
0065
0066 .end
No Errors, No Warnings
+38
View File
@@ -0,0 +1,38 @@
*****************************************************
GSP COFF Linker, Version 2.00, 87.300
*****************************************************
Sun Oct 18 15:08:14 2026
OUTPUT FILE NAME: <MARKER.out>
ENTRY POINT SYMBOL: "_start" address: 018C0000
SECTION ALLOCATION MAP
output attributes/
section page origin length input sections
-------- ---- ---------- ---------- ----------------
.text 0 018C0000 00000290
018C0000 00000290 MARKER.obj (.text)
.data 0 018D0000 00000040
018D0000 00000040 MARKER.obj (.data)
.bss 0 018D8000 00000040 UNINITIALIZED
018D8000 00000040 MARKER.obj (.bss)
GLOBAL SYMBOLS
address name address name
-------- ---- -------- ----
018D8000 .bss 018C0000 .text
018D0000 .data 018C0000 _start
018C0000 .text 018C0280 sub
018C0000 _start 018C0290 etext
018D0040 edata 018D0000 .data
018D8040 end 018D0040 edata
018C0290 etext 018D8000 .bss
018C0280 sub 018D8040 end
[8 symbols]
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+229
View File
@@ -0,0 +1,229 @@
GSP COFF Assembler, Version 2.00, 87.300 Sun Oct 18 15:04:44 2026
(c) Copyright 1985, 1987, Texas Instruments Inc.
PAGE 1
0001 ; xhello.asm -- open a *new* X connection and create/ma
0002 ; DWT X server.
0003 ;
0004 ; Run as a first-class process created by xlaunch.asm (
0005 ; the rdebug dispatcher's context: a connect made from
0006 ; accepted at the service layer but the server never re
0007 ; XOpenDisplay returns an unusable Display. A fresh pr
0008 ;
0009 ; Calling convention (the one the firmware itself uses;
0010 ; 07F57044 and the TM at 07E5D2B4):
0011 ;
0012 ; MOVE A14,-*SP,1 ; reserve the slot the ca
0013 ; MOVI argN,A0 / MOVE A0,*A14+,1 ; last argument
0014 ; ...
0015 ; MOVI arg0,A0 / MOVE A0,*A14+,1 ; first argumen
0016 ; CALLA target
0017 ;
0018 ; Xlib clobbers the CPU's SETF field state, so the ABI'
0019 ; re-established after every call. The Display pointer
0020 ; kept in a11/a10 (both callee-saved by every Xlib entr
0021 ; be overwritten by the new process's stack, a register
0022 ;
0023 ; Xlib entry points (Ghidra address -> bit address):
0024 ; 7F384AE XOpenDisplay(name) -> 3F9C2570
0025 ; 7FA8372 XCreateSimpleWindow(...) -> 3FD41B90
0026 ; 7FAC8B6 XMapWindow(display,window) -> 3FD645B0
0027 ; 7FB3ED6 XSync(display,discard) -> 3FD9F6B0
0028 ; 7F68B1A strlen(s) -> 3FB458D0
0029 ;
0030 ; Markers (32-bit cells, bit addresses; diagnostic only
0031 ; 01890100 display pointer
0032 ; 01890110 root window
0033 ; 01890120 window id
0034 ; 01890130 XSync return
0035 ; 01890140 stage counter
0036 ; 01890160 strlen("0::0") -- must be 4; if not, we s
0037
0038 00000000 .text
0039 00000000 _start:
0040 00000000 0550 setf 16, 0, 0
0041 00000010 0740 setf 32, 0, 1
0042 00000020 098F mmtm sp, a0,a1,a2,a3,a4,a5,a6,a7
00000030 FF00
0043
0044 00000040 078F move sp, @01890420h, 1 ; entry SP
00000050 01890420
0045 00000070 078E move a14, @01890400h, 1 ; entry A14
00000080 01890400
0046
0047 000000A0 09E0 movi 1, a0, L
000000B0 00000001
0048 000000D0 0780 move a0, @01890140h, 1 ; stage = 1
000000E0 01890140
0049
0050 ; ---- convention check: strlen("0::0") == 4 ---------
0051 00000100 A3CF move a14, -*sp, 1
GSP COFF Assembler, Version 2.00, 87.300 Sun Oct 18 15:04:44 2026
(c) Copyright 1985, 1987, Texas Instruments Inc.
PAGE 2
0052 00000110 09EE movi 01892000h, a14, L
00000120 01892000
0053 00000140 09E0 movi 3FACE948h, a0, L ; ROM "0::0"
00000150 3FACE948
0054 00000170 920E move a0, *a14+, 1 ; arg0
0055 00000180 0D5F calla 3FB458D0h ; strlen
00000190 3FB458D0
0056 000001B0 07AF move @01890420h, sp, 1
000001C0 01890420
0057 000001E0 07AE move @01890400h, a14, 1
000001F0 01890400
0058 00000210 0550 setf 16, 0, 0 ; Xlib leaves the field sizes changed;
0059 00000220 0740 setf 32, 0, 1 ; re-establish the ABI's 32-bit field 1
0060 00000230 0788 move a8, @01890160h, 1 ; MARK strlen
00000240 01890160
0061 00000260 09E0 movi 4, a0, L
00000270 00000004
0062 00000290 4808 cmp a0, a8
0063 000002A0 CB00 jrne done
000002B0 0091
0064
0065 000002C0 09E0 movi 2, a0, L
000002D0 00000002
0066 000002F0 0780 move a0, @01890140h, 1
00000300 01890140
0067
0068 ; ---- display = XOpenDisplay("0::0") ----------------
0069 00000320 A3CF move a14, -*sp, 1
0070 00000330 09EE movi 01892000h, a14, L
00000340 01892000
0071 00000360 09E0 movi 3FACE948h, a0, L
00000370 3FACE948
0072 00000390 920E move a0, *a14+, 1 ; arg0 = name
0073 000003A0 0D5F calla 3F9C2570h ; XOpenDisplay
000003B0 3F9C2570
0074 000003D0 07AF move @01890420h, sp, 1
000003E0 01890420
0075 00000400 07AE move @01890400h, a14, 1
00000410 01890400
0076 00000430 0550 setf 16, 0, 0
0077 00000440 0740 setf 32, 0, 1
0078 00000450 4D0B move a8, a11 ; keep the Display in a callee-saved re
0079 00000460 078B move a11, @01890100h, 1 ; MARK display
00000470 01890100
0080 00000490 4D6B move a11, a11
0081 000004A0 CA72 jreq done
0082
0083 000004B0 09E0 movi 3, a0, L
000004C0 00000003
0084 000004E0 0780 move a0, @01890140h, 1
000004F0 01890140
0085
0086 ; ---- root = *(*(display+0x480)+0x40) ---------------
0087 00000510 B76A move *a11(0480h), a10, 1
00000520 0480
0088 00000530 B74A move *a10(040h), a10, 1
GSP COFF Assembler, Version 2.00, 87.300 Sun Oct 18 15:04:44 2026
(c) Copyright 1985, 1987, Texas Instruments Inc.
PAGE 3
00000540 0040
0089 00000550 078A move a10, @01890110h, 1 ; MARK root
00000560 01890110
0090
0091 ; ---- XCreateSimpleWindow(display,root,100,100,400,20
0092 00000580 A3CF move a14, -*sp, 1
0093 00000590 09EE movi 01892000h, a14, L
000005A0 01892000
0094 000005C0 09E0 movi 0, a0, L
000005D0 00000000
0095 000005F0 920E move a0, *a14+, 1 ; background = 0 (black)
0096 00000600 920E move a0, *a14+, 1 ; border = 0
0097 00000610 09E0 movi 2, a0, L
00000620 00000002
0098 00000640 920E move a0, *a14+, 1 ; border width
0099 00000650 09E0 movi 200, a0, L
00000660 000000C8
0100 00000680 920E move a0, *a14+, 1 ; height
0101 00000690 09E0 movi 400, a0, L
000006A0 00000190
0102 000006C0 920E move a0, *a14+, 1 ; width
0103 000006D0 09E0 movi 100, a0, L
000006E0 00000064
0104 00000700 920E move a0, *a14+, 1 ; y
0105 00000710 920E move a0, *a14+, 1 ; x
0106 00000720 934E move a10, *a14+, 1 ; parent = root
0107 00000730 936E move a11, *a14+, 1 ; display
0108 00000740 0D5F calla 3FD41B90h ; XCreateSimpleWindow
00000750 3FD41B90
0109 00000770 07AF move @01890420h, sp, 1
00000780 01890420
0110 000007A0 07AE move @01890400h, a14, 1
000007B0 01890400
0111 000007D0 0550 setf 16, 0, 0
0112 000007E0 0740 setf 32, 0, 1
0113 000007F0 4D0A move a8, a10 ; window id (root no longer needed)
0114 00000800 078A move a10, @01890120h, 1 ; MARK window
00000810 01890120
0115
0116 00000830 09E0 movi 4, a0, L
00000840 00000004
0117 00000860 0780 move a0, @01890140h, 1
00000870 01890140
0118
0119 ; ---- XMapWindow(display, window) -------------------
0120 00000890 A3CF move a14, -*sp, 1
0121 000008A0 09EE movi 01892000h, a14, L
000008B0 01892000
0122 000008D0 934E move a10, *a14+, 1 ; window
0123 000008E0 936E move a11, *a14+, 1 ; display
0124 000008F0 0D5F calla 3FD645B0h ; XMapWindow
00000900 3FD645B0
0125 00000920 07AF move @01890420h, sp, 1
00000930 01890420
0126 00000950 07AE move @01890400h, a14, 1
00000960 01890400
GSP COFF Assembler, Version 2.00, 87.300 Sun Oct 18 15:04:44 2026
(c) Copyright 1985, 1987, Texas Instruments Inc.
PAGE 4
0127 00000980 0550 setf 16, 0, 0
0128 00000990 0740 setf 32, 0, 1
0129
0130 000009A0 09E0 movi 5, a0, L
000009B0 00000005
0131 000009D0 0780 move a0, @01890140h, 1
000009E0 01890140
0132
0133 ; ---- XSync(display, 0) -----------------------------
0134 00000A00 A3CF move a14, -*sp, 1
0135 00000A10 09EE movi 01892000h, a14, L
00000A20 01892000
0136 00000A40 09E0 movi 0, a0, L
00000A50 00000000
0137 00000A70 920E move a0, *a14+, 1 ; discard = 0
0138 00000A80 936E move a11, *a14+, 1 ; display
0139 00000A90 0D5F calla 3FD9F6B0h ; XSync
00000AA0 3FD9F6B0
0140 00000AC0 07AF move @01890420h, sp, 1
00000AD0 01890420
0141 00000AF0 07AE move @01890400h, a14, 1
00000B00 01890400
0142 00000B20 0550 setf 16, 0, 0
0143 00000B30 0740 setf 32, 0, 1
0144 00000B40 0788 move a8, @01890130h, 1 ; MARK sync
00000B50 01890130
0145
0146 00000B70 09E0 movi 6, a0, L
00000B80 00000006
0147 00000BA0 0780 move a0, @01890140h, 1
00000BB0 01890140
0148
0149 00000BD0 done:
0150 00000BD0 09AF mmfm sp, a0,a1,a2,a3,a4,a5,a6,a7
00000BE0 00FF
0151 00000BF0 09E8 movi 0, a8, L
00000C00 00000000
0152 00000C20 0960 rets
0153 .end
No Errors, No Warnings
+34
View File
@@ -0,0 +1,34 @@
*****************************************************
GSP COFF Linker, Version 2.00, 87.300
*****************************************************
Sun Oct 18 15:04:44 2026
OUTPUT FILE NAME: <XHELLO.out>
ENTRY POINT SYMBOL: 0
SECTION ALLOCATION MAP
output attributes/
section page origin length input sections
-------- ---- ---------- ---------- ----------------
.data 0 00000000 00000000
.bss 0 00000000 00000000 UNINITIALIZED
.text 0 01840000 00000C30
01840000 00000C30 XHELLO.obj (.text)
GLOBAL SYMBOLS
address name address name
-------- ---- -------- ----
00000000 .bss 00000000 edata
00000000 .data 00000000 .bss
01840000 .text 00000000 end
00000000 edata 00000000 .data
00000000 end 01840000 .text
01840C30 etext 01840C30 etext
[6 symbols]
Binary file not shown.
+200
View File
@@ -0,0 +1,200 @@
#!/usr/bin/env python3
"""coff.py -- TI TMS34010 GSP COFF reader for the VT1200 loader work.
GSPLNK 2.00 emits the "TI COFF" described in the 1987 Assembler Tools guide,
Appendix A. All section addresses and sizes in the section headers are in
BITS (the TMS34010 is bit-addressed); file offsets (scnptr/relptr/symptr) are
in BYTES.
Commands
coff.py summary FILE... dump header, optional header, sections,
symbols (with aux entries) and relocations
coff.py raw ABS1 ABS2 extract each section from two absolute
outputs and report byte differences
coff.py manifest FILE print shell-ish KEY=VALUE lines for one file
The loader itself parses the same structures in assembly; this script is the
reference and the evidence generator.
"""
import struct
import sys
MAGIC = 0x0090
OPTHDR_MAGIC = 0x0108
RELOC_NAMES = {
0x00: "R-ABS",
0x10: "R-RELWORD",
0x11: "R-RELLONG",
0x18: "R-OCRLONG",
0x19: "R-GSPPCR16",
}
SECTION_FLAGS = {
0x20: "text",
0x40: "data",
0x80: "bss",
}
class CoffError(Exception):
pass
def parse(path):
d = open(path, "rb").read()
if len(d) < 20:
raise CoffError("%s: shorter than a COFF file header" % path)
magic, nscns, timdat, symptr, nsyms, opthdr, flags = struct.unpack_from(
"<HHIIIHH", d, 0)
if magic != MAGIC:
raise CoffError("%s: magic %#06x, expected %#06x"
% (path, magic, MAGIC))
opt = None
if opthdr:
if 20 + opthdr > len(d):
raise CoffError("%s: optional header past EOF" % path)
# TI COFF optional header: magic, vstamp, textsize, datasize, bsssize,
# entry, textstart, datastart (all sizes/addresses in bits).
opt = struct.unpack_from("<HHIIIIII", d, 20)
base = 20 + opthdr
secs = []
for i in range(nscns):
off = base + i * 40
if off + 40 > len(d):
raise CoffError("%s: section header %d past EOF" % (path, i))
raw = d[off:off + 40]
name = raw[:8].rstrip(b"\0").decode("latin1")
(paddr, vaddr, size, scnptr, relptr, lnnoptr, nreloc, nlnno,
sflags) = struct.unpack_from("<IIIIIIHHI", d, off + 8)
relocs = []
for r in range(nreloc):
ro = relptr + r * 10
if ro + 10 > len(d):
raise CoffError("%s: relocation %d past EOF" % (path, r))
raddr, symidx, rtype = struct.unpack_from("<IIH", d, ro)
relocs.append((raddr, symidx, rtype))
secs.append(dict(index=i + 1, name=name, paddr=paddr, vaddr=vaddr,
size=size, scnptr=scnptr, relptr=relptr,
lnnoptr=lnnoptr, nreloc=nreloc, nlnno=nlnno,
flags=sflags, relocs=relocs, raw=raw))
syms = []
i = 0
while i < nsyms:
off = symptr + i * 18
if off + 18 > len(d):
raise CoffError("%s: symbol %d past EOF" % (path, i))
e = d[off:off + 18]
name = e[:8].rstrip(b"\0").decode("latin1", "replace")
val, secno, stype, sclass, naux = struct.unpack_from("<IHhBB", e, 8)
aux = d[off + 18:off + 18 + naux * 18]
syms.append(dict(index=i, name=name, value=val, secno=secno,
type=stype, sclass=sclass, naux=naux, aux=aux))
i += 1 + naux
return dict(path=path, size=len(d), magic=magic, nscns=nscns,
timdat=timdat, symptr=symptr, nsyms=nsyms, opthdr=opthdr,
flags=flags, opt=opt, sections=secs, symbols=syms, data=d)
def summary(path):
c = parse(path)
print("== %s (%d bytes)" % (path, c["size"]))
print(" file hdr: magic=%#06x nscns=%d symptr=%#x nsyms=%d "
"opthdr=%d flags=%#06x"
% (c["magic"], c["nscns"], c["symptr"], c["nsyms"], c["opthdr"],
c["flags"]))
if c["opt"]:
magic, vstamp, tsize, dsize, bsize, entry, tstart, dstart = c["opt"]
print(" optional: magic=%#06x vstamp=%#06x text=%#x bits "
"data=%#x bits bss=%#x bits entry=%#010x textstart=%#010x "
"datastart=%#010x"
% (magic, vstamp, tsize, dsize, bsize, entry, tstart, dstart))
print(" optional: sizes in bytes text=%d data=%d bss=%d; "
"entry in bits=%s"
% (tsize // 8, dsize // 8, bsize // 8,
"0 (no -e global symbol)" if entry == 0 else hex(entry)))
for s in c["sections"]:
fl = ",".join(v for k, v in SECTION_FLAGS.items() if s["flags"] & k)
print(" sec %d %-8s paddr=%010x vaddr=%010x size=%#x bits (%d B) "
"scnptr=%#x nreloc=%d flags=%#x%s"
% (s["index"], s["name"], s["paddr"], s["vaddr"], s["size"],
s["size"] // 8, s["scnptr"], s["nreloc"], s["flags"],
(" [" + fl + "]") if fl else ""))
for raddr, symidx, rtype in s["relocs"]:
print(" reloc at %#x sym=%d type=%#x %s"
% (raddr, symidx, rtype,
RELOC_NAMES.get(rtype, "?")))
for sym in c["symbols"]:
if sym["naux"]:
print(" sym[%d] %-10s value=%010x sec=%d class=%d naux=%d"
% (sym["index"], sym["name"], sym["value"], sym["secno"],
sym["sclass"], sym["naux"]))
else:
print(" sym[%d] %-10s value=%010x sec=%d class=%d"
% (sym["index"], sym["name"], sym["value"], sym["secno"],
sym["sclass"]))
print()
def section_bytes(c, name):
for s in c["sections"]:
if s["name"] == name:
return s, c["data"][s["scnptr"]:s["scnptr"] + s["size"] // 8]
return None, None
def raw(paths):
if len(paths) != 2:
raise SystemExit("coff.py raw: need exactly two files")
a, b = parse(paths[0]), parse(paths[1])
for name in (".text", ".data", ".bss"):
sa, ba = section_bytes(a, name)
sb, bb = section_bytes(b, name)
if sa is None or sb is None:
continue
print("== %s: %d vs %d bytes" % (name, len(ba), len(bb)))
n = min(len(ba), len(bb))
bad = [i for i in range(n) if ba[i] != bb[i]]
print(" differing bytes: %d" % (len(bad) + abs(len(ba) - len(bb))))
for i in bad[:24]:
print(" %#06x: %02x -> %02x" % (i, ba[i], bb[i]))
print()
def manifest(path):
c = parse(path)
print("COFF=%s" % path)
print("SIZE=%d" % c["size"])
print("NSECTIONS=%d" % c["nscns"])
if c["opt"]:
_, _, tsize, dsize, bsize, entry, tstart, dstart = c["opt"]
print("ENTRY=%#010x" % entry)
print("TEXTSTART=%#010x" % tstart)
print("DATASTART=%#010x" % dstart)
print("TEXTSIZE_BITS=%d" % tsize)
print("DATASIZE_BITS=%d" % dsize)
print("BSSSIZE_BITS=%d" % bsize)
for s in c["sections"]:
key = s["name"].lstrip(".").upper() or ("SEC%d" % s["index"])
print("%s_PADDR=%#010x" % (key, s["paddr"]))
print("%s_SIZE_BITS=%d" % (key, s["size"]))
print("%s_NRELOC=%d" % (key, s["nreloc"]))
def main(argv):
if len(argv) < 3:
raise SystemExit(__doc__)
cmd = argv[1]
if cmd == "summary":
for p in argv[2:]:
summary(p)
elif cmd == "raw":
raw(argv[2:])
elif cmd == "manifest":
manifest(argv[2])
else:
raise SystemExit(__doc__)
if __name__ == "__main__":
main(sys.argv)
+68
View File
@@ -0,0 +1,68 @@
=== marker.coff hexdump (first 176 bytes) ===
00000000: 90 00 03 00 de e0 d4 6a 02 01 00 00 0e 00 00 00 .......j........
00000010: 1c 00 03 01 08 01 c7 00 90 02 00 00 40 00 00 00 ............@...
00000020: 40 00 00 00 00 00 8c 01 00 00 8c 01 00 00 8d 01 @...............
00000030: 2e 74 65 78 74 00 00 00 00 00 8c 01 00 00 8c 01 .text...........
00000040: 90 02 00 00 a8 00 00 00 00 00 00 00 00 00 00 00 ................
00000050: 00 00 00 00 20 00 00 00 2e 64 61 74 61 00 00 00 .... ....data...
00000060: 00 00 8d 01 00 00 8d 01 40 00 00 00 fa 00 00 00 ........@.......
00000070: 00 00 00 00 00 00 00 00 00 00 00 00 40 00 00 00 ............@...
00000080: 2e 62 73 73 00 00 00 00 00 80 8d 01 00 80 8d 01 .bss............
00000090: 40 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 @...............
000000a0: 00 00 00 00 80 00 00 00 50 05 40 07 e2 09 00 00 ........P.@.....
=== marker.coff parsed ===
== dwt/loader/build/marker.coff (510 bytes)
file hdr: magic=0x0090 nscns=3 symptr=0x102 nsyms=14 opthdr=28 flags=0x0103
optional: magic=0x0108 vstamp=0x00c7 text=0x290 bits data=0x40 bits bss=0x40 bits entry=0x018c0000 textstart=0x018c0000 datastart=0x018d0000
optional: sizes in bytes text=82 data=8 bss=8; entry in bits=0x18c0000
sec 1 .text paddr=00018c0000 vaddr=00018c0000 size=0x290 bits (82 B) scnptr=0xa8 nreloc=0 flags=0x20 [text]
sec 2 .data paddr=00018d0000 vaddr=00018d0000 size=0x40 bits (8 B) scnptr=0xfa nreloc=0 flags=0x40 [data]
sec 3 .bss paddr=00018d8000 vaddr=00018d8000 size=0x40 bits (8 B) scnptr=0x0 nreloc=0 flags=0x80 [bss]
sym[0] .text value=00018c0000 sec=1 class=3 naux=1
sym[2] .data value=00018d0000 sec=2 class=3 naux=1
sym[4] .bss value=00018d8000 sec=3 class=3 naux=1
sym[6] sub value=00018c0280 sec=1 class=2
sym[7] _start value=00018c0000 sec=1 class=2
sym[8] .text value=00018c0000 sec=1 class=2
sym[9] etext value=00018c0290 sec=1 class=2
sym[10] .data value=00018d0000 sec=2 class=2
sym[11] edata value=00018d0040 sec=2 class=2
sym[12] .bss value=00018d8000 sec=3 class=2
sym[13] end value=00018d8040 sec=3 class=2
=== xhello.coff parsed ===
== dwt/loader/build/xhello.coff (774 bytes)
file hdr: magic=0x0090 nscns=3 symptr=0x22e nsyms=12 opthdr=28 flags=0x0103
optional: magic=0x0108 vstamp=0x00c7 text=0xc30 bits data=0x0 bits bss=0x0 bits entry=0x00000000 textstart=0x01840000 datastart=0x00000000
optional: sizes in bytes text=390 data=0 bss=0; entry in bits=0 (no -e global symbol)
sec 1 .data paddr=0000000000 vaddr=0000000000 size=0x0 bits (0 B) scnptr=0xa8 nreloc=0 flags=0x40 [data]
sec 2 .bss paddr=0000000000 vaddr=0000000000 size=0x0 bits (0 B) scnptr=0x0 nreloc=0 flags=0x80 [bss]
sec 3 .text paddr=0001840000 vaddr=0001840000 size=0xc30 bits (390 B) scnptr=0xa8 nreloc=0 flags=0x20 [text]
sym[0] .text value=0001840000 sec=3 class=3 naux=1
sym[2] .data value=0000000000 sec=1 class=3 naux=1
sym[4] .bss value=0000000000 sec=2 class=3 naux=1
sym[6] .text value=0001840000 sec=3 class=2
sym[7] etext value=0001840c30 sec=3 class=2
sym[8] .data value=0000000000 sec=1 class=2
sym[9] edata value=0000000000 sec=1 class=2
sym[10] .bss value=0000000000 sec=2 class=2
sym[11] end value=0000000000 sec=2 class=2
=== marker.obj (assembler output: relocations present) ===
== dwt/loader/build/marker.obj (424 bytes)
file hdr: magic=0x0090 nscns=3 symptr=0x118 nsyms=8 opthdr=0 flags=0x0100
sec 1 .text paddr=0000000000 vaddr=0000000000 size=0x290 bits (82 B) scnptr=0x8c nreloc=5 flags=0x20 [text]
reloc at 0x30 sym=65535 type=0x11 R-RELLONG
reloc at 0x90 sym=2 type=0x11 R-RELLONG
reloc at 0xf0 sym=2 type=0x11 R-RELLONG
reloc at 0x150 sym=4 type=0x11 R-RELLONG
reloc at 0x1e0 sym=4 type=0x11 R-RELLONG
sec 2 .data paddr=0000000000 vaddr=0000000000 size=0x40 bits (8 B) scnptr=0xde nreloc=0 flags=0x40 [data]
sec 3 .bss paddr=0000000000 vaddr=0000000000 size=0x40 bits (8 B) scnptr=0x0 nreloc=0 flags=0x80 [bss]
sym[0] .text value=0000000000 sec=1 class=3 naux=1
sym[2] .data value=0000000000 sec=2 class=3 naux=1
sym[4] .bss value=0000000000 sec=3 class=3 naux=1
sym[6] sub value=0000000280 sec=1 class=2
sym[7] _start value=0000000000 sec=1 class=2
+17
View File
@@ -0,0 +1,17 @@
=== ELF in the 1987 SDK documentation ===
grep -ni elf harness/sdk-scratch/asmguide.txt harness/sdk-scratch/cguide.txt
harness/sdk-scratch/cguide.txt:903: • The preprocessor produces self-explanatory error messages. The line
harness/sdk-scratch/cguide.txt:1830: ever, the structure or array itself begins at a 16-bit boundary. In the case
harness/sdk-scratch/asmguide.txt:2047: A label on a line by itself is a valid statement. It assigns the current value of
harness/sdk-scratch/asmguide.txt:2058: When a label appears on a line by itself, it usually points to the instruction on
harness/sdk-scratch/asmguide.txt:4828: listing page. The .title directive itself is not printed, but the line counter is
harness/sdk-scratch/asmguide.txt:9927: TMS34010 simulator; the messages are self explanatory.
harness/sdk-scratch/asmguide.txt:10244: and then executes the contents of buffer 1. A buffer can even reference itself
harness/sdk-scratch/asmguide.txt:11230:Syntax elF
harness/sdk-scratch/asmguide.txt:14123: example, if bytes 18 and 19 are set to 0003h, then F-RELFLG and F-EXEC
harness/sdk-scratch/asmguide.txt:14129: F-RELFLG 0001h Relocation information was stripped from
The SDK's documented object formats (asmguide §1.2 / §10):
569: The object format converter converts a COFF object file into Intel
No ELF writer or ELF reader exists in the toolchain: COFF is the only linker output.
Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

+88
View File
@@ -0,0 +1,88 @@
Warning: -video none doesn't make much sense without -seconds_to_run
vt1200: screen_update#1 frame=0 clip_y=0..0 screen=1280x901
LOADER: payload dwt/loader/build/loader.bin (1220 B) -> bit 01880000
LOADER: COFF dwt/loader/build/marker.coff (510 B) -> bit 01900000
LOADER: file magic=0090 nscns=3 opthdr=28 optmagic=0108 entry=018C0000 textstart=018C0000
LOADER: sec .text paddr=018C0000 size=656 bits (82 B) scnptr=0xa8 flags=0x20
LOADER: sec .data paddr=018D0000 size=64 bits (8 B) scnptr=0xfa flags=0x40
LOADER: sec .bss paddr=018D8000 size=64 bits (8 B) scnptr=0 flags=0x80
vt1200: screen_update#2 frame=0 clip_y=1..900 screen=1280x901
vt1200: scanline#1 line=1 enabled=1
vt1200: guard#1 frame=0 dump_frame=-1 dump_ram=-1
vt1200: screen_update#3 frame=1 clip_y=0..0 screen=1280x901
vt1200: scanline#2 line=0 enabled=1
vt1200: screen_update#4 frame=1 clip_y=1..1 screen=1280x901
vt1200: scanline#3 line=1 enabled=1
vt1200: scanline#4 line=2 enabled=1
LOADER: loader poked 610 words, readback 0 bad at 01880000
LOADER: COFF poked 255 words, readback 0 bad at 01900000
LOADER: pre-filled .bss 018D8000..018D8040 with A5A5
LOADER: descriptor @01882C00 magic=4C44/5231 buf=01900000 len=510 mode=1
LOADER: will resume at 3F579970 after create_process
LOADER: frame 2500: entered loader at 01880000 (caller SP=007F5290)
LOADER: marker counter 1431655765 -> 5 (child running)
LOADER: marker counter 5 -> 11 (child running)
LOADER: marker counter 11 -> 16 (child running)
LOADER: marker counter 16 -> 21 (child running)
LOADER: marker counter 21 -> 26 (child running)
LOADER: marker counter 26 -> 31 (child running)
LOADER: marker counter 31 -> 36 (child running)
LOADER: marker counter 36 -> 41 (child running)
LOADER: marker counter 41 -> 47 (child running)
LOADER: marker counter 47 -> 52 (child running)
LOADER: marker counter 52 -> 57 (child running)
LOADER: marker counter 57 -> 62 (child running)
LOADER: marker counter 62 -> 67 (child running)
LOADER: marker counter 67 -> 72 (child running)
LOADER: marker counter 72 -> 77 (child running)
LOADER: marker counter 77 -> 83 (child running)
LOADER: marker counter 83 -> 88 (child running)
LOADER: marker counter 88 -> 93 (child running)
LOADER: marker counter 93 -> 98 (child running)
LOADER: marker counter 98 -> 103 (child running)
LOADER: marker counter 103 -> 108 (child running)
LOADER: marker counter 108 -> 114 (child running)
LOADER: marker counter 114 -> 119 (child running)
LOADER: marker counter 119 -> 124 (child running)
LOADER: marker counter 124 -> 129 (child running)
LOADER: marker counter 129 -> 134 (child running)
LOADER: marker counter 134 -> 139 (child running)
LOADER: marker counter 139 -> 145 (child running)
LOADER: marker counter 145 -> 150 (child running)
LOADER: marker counter 150 -> 155 (child running)
LOADER: marker counter 155 -> 160 (child running)
LOADER: marker counter 160 -> 165 (child running)
LOADER: marker counter 165 -> 170 (child running)
LOADER: marker counter 170 -> 176 (child running)
LOADER: marker counter 176 -> 181 (child running)
LOADER: marker counter 181 -> 186 (child running)
LOADER: marker counter 186 -> 191 (child running)
LOADER: marker counter 191 -> 196 (child running)
LOADER: marker counter 196 -> 201 (child running)
LOADER: marker counter 201 -> 207 (child running)
LOADER: marker counter 207 -> 212 (child running)
LOADER: marker counter 212 -> 217 (child running)
LOADER: marker counter 217 -> 222 (child running)
LOADER: marker counter 222 -> 227 (child running)
LOADER: marker counter 227 -> 232 (child running)
LOADER: marker counter 232 -> 238 (child running)
LOADER: marker counter 238 -> 243 (child running)
LOADER: marker counter 243 -> 248 (child running)
LOADER: marker counter 248 -> 253 (child running)
LOADER: marker counter 253 -> 258 (child running)
LOADER: marker counter 258 -> 263 (child running)
LOADER: marker counter 263 -> 269 (child running)
LOADER: marker counter 269 -> 274 (child running)
LOADER: marker counter 274 -> 279 (child running)
LOADER: marker counter 279 -> 284 (child running)
LOADER: marker counter 284 -> 289 (child running)
LOADER: marker counter 289 -> 294 (child running)
LOADER: marker counter 294 -> 299 (child running)
LOADER: marker counter 299 -> 305 (child running)
LOADER: marker counter 305 -> 310 (child running)
LOADER: result status=0 (OK) entry=018C0000 text=018C0000/656 bits data=018D0000/64 bits bss=018D8000/64 bits relocs=0 pcb=003FFBD0 nscns=3 len=510
LOADER: placed .text at 018C0000: 82 bytes, 0 differing
LOADER: placed .data at 018D0000: 8 bytes, 0 differing
LOADER: marker app: start=018C0000 data=DEADBEEF data2=12345678 bss=00000000 count=310
LOADER: PC at inspection = 018C0260
Average speed: 332.37% (35 seconds)
+128
View File
@@ -0,0 +1,128 @@
Warning: -video none doesn't make much sense without -seconds_to_run
vt1200: screen_update#1 frame=0 clip_y=0..0 screen=1280x901
LOADER: payload dwt/loader/build/loader.bin (1220 B) -> bit 01880000
LOADER: COFF dwt/loader/build/marker.coff (510 B) -> bit 01900000
LOADER: file magic=0090 nscns=3 opthdr=28 optmagic=0108 entry=018C0000 textstart=018C0000
LOADER: sec .text paddr=018C0000 size=656 bits (82 B) scnptr=0xa8 flags=0x20
LOADER: sec .data paddr=018D0000 size=64 bits (8 B) scnptr=0xfa flags=0x40
LOADER: sec .bss paddr=018D8000 size=64 bits (8 B) scnptr=0 flags=0x80
vt1200: screen_update#2 frame=0 clip_y=1..900 screen=1280x901
vt1200: scanline#1 line=1 enabled=1
vt1200: guard#1 frame=0 dump_frame=-1 dump_ram=-1
vt1200: screen_update#3 frame=1 clip_y=0..0 screen=1280x901
vt1200: scanline#2 line=0 enabled=1
vt1200: screen_update#4 frame=1 clip_y=1..1 screen=1280x901
vt1200: scanline#3 line=1 enabled=1
vt1200: scanline#4 line=2 enabled=1
LOADER: loader poked 610 words, readback 0 bad at 01880000
LOADER: COFF poked 255 words, readback 0 bad at 01900000
LOADER: pre-filled .bss 018D8000..018D8040 with A5A5
LOADER: descriptor @01882C00 magic=4C44/5231 buf=01900000 len=510 mode=1
LOADER: will resume at 3F579970 after create_process
LOADER: frame 2500: entered loader at 01880000 (caller SP=007F5290)
LOADER: marker counter 1431655765 -> 5 (child running)
LOADER: marker counter 5 -> 11 (child running)
LOADER: marker counter 11 -> 16 (child running)
LOADER: marker counter 16 -> 21 (child running)
LOADER: marker counter 21 -> 26 (child running)
LOADER: marker counter 26 -> 31 (child running)
LOADER: marker counter 31 -> 36 (child running)
LOADER: marker counter 36 -> 41 (child running)
LOADER: marker counter 41 -> 47 (child running)
LOADER: marker counter 47 -> 52 (child running)
LOADER: marker counter 52 -> 57 (child running)
LOADER: marker counter 57 -> 62 (child running)
LOADER: marker counter 62 -> 67 (child running)
LOADER: marker counter 67 -> 72 (child running)
LOADER: marker counter 72 -> 77 (child running)
LOADER: marker counter 77 -> 83 (child running)
LOADER: marker counter 83 -> 88 (child running)
LOADER: marker counter 88 -> 93 (child running)
LOADER: marker counter 93 -> 98 (child running)
LOADER: marker counter 98 -> 103 (child running)
LOADER: marker counter 103 -> 108 (child running)
LOADER: marker counter 108 -> 114 (child running)
LOADER: marker counter 114 -> 119 (child running)
LOADER: marker counter 119 -> 124 (child running)
LOADER: marker counter 124 -> 129 (child running)
LOADER: marker counter 129 -> 134 (child running)
LOADER: marker counter 134 -> 139 (child running)
LOADER: marker counter 139 -> 145 (child running)
LOADER: marker counter 145 -> 150 (child running)
LOADER: marker counter 150 -> 155 (child running)
LOADER: marker counter 155 -> 160 (child running)
LOADER: marker counter 160 -> 165 (child running)
LOADER: marker counter 165 -> 170 (child running)
LOADER: marker counter 170 -> 176 (child running)
LOADER: marker counter 176 -> 181 (child running)
LOADER: marker counter 181 -> 186 (child running)
LOADER: marker counter 186 -> 191 (child running)
LOADER: marker counter 191 -> 196 (child running)
LOADER: marker counter 196 -> 201 (child running)
LOADER: marker counter 201 -> 207 (child running)
LOADER: marker counter 207 -> 212 (child running)
LOADER: marker counter 212 -> 217 (child running)
LOADER: marker counter 217 -> 222 (child running)
LOADER: marker counter 222 -> 227 (child running)
LOADER: marker counter 227 -> 232 (child running)
LOADER: marker counter 232 -> 238 (child running)
LOADER: marker counter 238 -> 243 (child running)
LOADER: marker counter 243 -> 248 (child running)
LOADER: marker counter 248 -> 253 (child running)
LOADER: marker counter 253 -> 258 (child running)
LOADER: marker counter 258 -> 263 (child running)
LOADER: marker counter 263 -> 269 (child running)
LOADER: marker counter 269 -> 274 (child running)
LOADER: marker counter 274 -> 279 (child running)
LOADER: marker counter 279 -> 284 (child running)
LOADER: marker counter 284 -> 289 (child running)
LOADER: marker counter 289 -> 294 (child running)
LOADER: marker counter 294 -> 299 (child running)
LOADER: marker counter 299 -> 305 (child running)
LOADER: marker counter 305 -> 310 (child running)
LOADER: marker counter 310 -> 315 (child running)
LOADER: marker counter 315 -> 320 (child running)
LOADER: marker counter 320 -> 325 (child running)
LOADER: marker counter 325 -> 330 (child running)
LOADER: marker counter 330 -> 336 (child running)
LOADER: marker counter 336 -> 341 (child running)
LOADER: marker counter 341 -> 346 (child running)
LOADER: marker counter 346 -> 351 (child running)
LOADER: marker counter 351 -> 356 (child running)
LOADER: marker counter 356 -> 361 (child running)
LOADER: marker counter 361 -> 367 (child running)
LOADER: marker counter 367 -> 372 (child running)
LOADER: marker counter 372 -> 377 (child running)
LOADER: marker counter 377 -> 382 (child running)
LOADER: marker counter 382 -> 387 (child running)
LOADER: marker counter 387 -> 392 (child running)
LOADER: marker counter 392 -> 398 (child running)
LOADER: marker counter 398 -> 403 (child running)
LOADER: marker counter 403 -> 408 (child running)
LOADER: marker counter 408 -> 413 (child running)
LOADER: marker counter 413 -> 418 (child running)
LOADER: marker counter 418 -> 423 (child running)
LOADER: marker counter 423 -> 428 (child running)
LOADER: marker counter 428 -> 434 (child running)
LOADER: marker counter 434 -> 439 (child running)
LOADER: marker counter 439 -> 444 (child running)
LOADER: marker counter 444 -> 449 (child running)
LOADER: marker counter 449 -> 454 (child running)
LOADER: marker counter 454 -> 459 (child running)
LOADER: marker counter 459 -> 465 (child running)
LOADER: marker counter 465 -> 470 (child running)
LOADER: marker counter 470 -> 475 (child running)
LOADER: marker counter 475 -> 480 (child running)
LOADER: marker counter 480 -> 485 (child running)
LOADER: marker counter 485 -> 490 (child running)
LOADER: marker counter 490 -> 495 (child running)
LOADER: marker counter 495 -> 501 (child running)
LOADER: marker counter 501 -> 506 (child running)
LOADER: marker counter 506 -> 511 (child running)
LOADER: marker counter 511 -> 516 (child running)
LOADER: result status=0 (OK) entry=018C0000 text=018C0000/656 bits data=018D0000/64 bits bss=018D8000/64 bits relocs=0 pcb=003FFBD0 nscns=3 len=510
LOADER: placed .text at 018C0000: 82 bytes, 0 differing
LOADER: placed .data at 018D0000: 8 bytes, 0 differing
LOADER: marker app: start=018C0000 data=DEADBEEF data2=12345678 bss=00000000 count=516
LOADER: PC at inspection = 018C0260
Average speed: 325.97% (36 seconds)
+128
View File
@@ -0,0 +1,128 @@
Warning: -video none doesn't make much sense without -seconds_to_run
vt1200: screen_update#1 frame=0 clip_y=0..0 screen=1280x901
LOADER: payload dwt/loader/build/loader.bin (1220 B) -> bit 01880000
LOADER: COFF dwt/loader/build/marker.coff (510 B) -> bit 01900000
LOADER: file magic=0090 nscns=3 opthdr=28 optmagic=0108 entry=018C0000 textstart=018C0000
LOADER: sec .text paddr=018C0000 size=656 bits (82 B) scnptr=0xa8 flags=0x20
LOADER: sec .data paddr=018D0000 size=64 bits (8 B) scnptr=0xfa flags=0x40
LOADER: sec .bss paddr=018D8000 size=64 bits (8 B) scnptr=0 flags=0x80
vt1200: screen_update#2 frame=0 clip_y=1..900 screen=1280x901
vt1200: scanline#1 line=1 enabled=1
vt1200: guard#1 frame=0 dump_frame=-1 dump_ram=-1
vt1200: screen_update#3 frame=1 clip_y=0..0 screen=1280x901
vt1200: scanline#2 line=0 enabled=1
vt1200: screen_update#4 frame=1 clip_y=1..1 screen=1280x901
vt1200: scanline#3 line=1 enabled=1
vt1200: scanline#4 line=2 enabled=1
LOADER: loader poked 610 words, readback 0 bad at 01880000
LOADER: COFF poked 255 words, readback 0 bad at 01900000
LOADER: pre-filled .bss 018D8000..018D8040 with A5A5
LOADER: descriptor @01882C00 magic=4C44/5231 buf=01900000 len=510 mode=0
LOADER: will resume at 3F579970 after create_process
LOADER: frame 2500: entered loader at 01880000 (caller SP=007F52B0)
LOADER: marker counter 1431655765 -> 5 (child running)
LOADER: marker counter 5 -> 11 (child running)
LOADER: marker counter 11 -> 16 (child running)
LOADER: marker counter 16 -> 21 (child running)
LOADER: marker counter 21 -> 26 (child running)
LOADER: marker counter 26 -> 31 (child running)
LOADER: marker counter 31 -> 36 (child running)
LOADER: marker counter 36 -> 41 (child running)
LOADER: marker counter 41 -> 47 (child running)
LOADER: marker counter 47 -> 52 (child running)
LOADER: marker counter 52 -> 57 (child running)
LOADER: marker counter 57 -> 62 (child running)
LOADER: marker counter 62 -> 67 (child running)
LOADER: marker counter 67 -> 72 (child running)
LOADER: marker counter 72 -> 77 (child running)
LOADER: marker counter 77 -> 83 (child running)
LOADER: marker counter 83 -> 88 (child running)
LOADER: marker counter 88 -> 93 (child running)
LOADER: marker counter 93 -> 98 (child running)
LOADER: marker counter 98 -> 103 (child running)
LOADER: marker counter 103 -> 108 (child running)
LOADER: marker counter 108 -> 114 (child running)
LOADER: marker counter 114 -> 119 (child running)
LOADER: marker counter 119 -> 124 (child running)
LOADER: marker counter 124 -> 129 (child running)
LOADER: marker counter 129 -> 134 (child running)
LOADER: marker counter 134 -> 139 (child running)
LOADER: marker counter 139 -> 145 (child running)
LOADER: marker counter 145 -> 150 (child running)
LOADER: marker counter 150 -> 155 (child running)
LOADER: marker counter 155 -> 160 (child running)
LOADER: marker counter 160 -> 165 (child running)
LOADER: marker counter 165 -> 170 (child running)
LOADER: marker counter 170 -> 176 (child running)
LOADER: marker counter 176 -> 181 (child running)
LOADER: marker counter 181 -> 186 (child running)
LOADER: marker counter 186 -> 191 (child running)
LOADER: marker counter 191 -> 196 (child running)
LOADER: marker counter 196 -> 201 (child running)
LOADER: marker counter 201 -> 207 (child running)
LOADER: marker counter 207 -> 212 (child running)
LOADER: marker counter 212 -> 217 (child running)
LOADER: marker counter 217 -> 222 (child running)
LOADER: marker counter 222 -> 227 (child running)
LOADER: marker counter 227 -> 232 (child running)
LOADER: marker counter 232 -> 238 (child running)
LOADER: marker counter 238 -> 243 (child running)
LOADER: marker counter 243 -> 248 (child running)
LOADER: marker counter 248 -> 253 (child running)
LOADER: marker counter 253 -> 258 (child running)
LOADER: marker counter 258 -> 263 (child running)
LOADER: marker counter 263 -> 269 (child running)
LOADER: marker counter 269 -> 274 (child running)
LOADER: marker counter 274 -> 279 (child running)
LOADER: marker counter 279 -> 284 (child running)
LOADER: marker counter 284 -> 289 (child running)
LOADER: marker counter 289 -> 294 (child running)
LOADER: marker counter 294 -> 299 (child running)
LOADER: marker counter 299 -> 305 (child running)
LOADER: marker counter 305 -> 310 (child running)
LOADER: marker counter 310 -> 315 (child running)
LOADER: marker counter 315 -> 320 (child running)
LOADER: marker counter 320 -> 325 (child running)
LOADER: marker counter 325 -> 330 (child running)
LOADER: marker counter 330 -> 336 (child running)
LOADER: marker counter 336 -> 341 (child running)
LOADER: marker counter 341 -> 346 (child running)
LOADER: marker counter 346 -> 351 (child running)
LOADER: marker counter 351 -> 356 (child running)
LOADER: marker counter 356 -> 361 (child running)
LOADER: marker counter 361 -> 367 (child running)
LOADER: marker counter 367 -> 372 (child running)
LOADER: marker counter 372 -> 377 (child running)
LOADER: marker counter 377 -> 382 (child running)
LOADER: marker counter 382 -> 387 (child running)
LOADER: marker counter 387 -> 392 (child running)
LOADER: marker counter 392 -> 398 (child running)
LOADER: marker counter 398 -> 403 (child running)
LOADER: marker counter 403 -> 408 (child running)
LOADER: marker counter 408 -> 413 (child running)
LOADER: marker counter 413 -> 418 (child running)
LOADER: marker counter 418 -> 423 (child running)
LOADER: marker counter 423 -> 428 (child running)
LOADER: marker counter 428 -> 434 (child running)
LOADER: marker counter 434 -> 439 (child running)
LOADER: marker counter 439 -> 444 (child running)
LOADER: marker counter 444 -> 449 (child running)
LOADER: marker counter 449 -> 454 (child running)
LOADER: marker counter 454 -> 459 (child running)
LOADER: marker counter 459 -> 465 (child running)
LOADER: marker counter 465 -> 470 (child running)
LOADER: marker counter 470 -> 475 (child running)
LOADER: marker counter 475 -> 480 (child running)
LOADER: marker counter 480 -> 485 (child running)
LOADER: marker counter 485 -> 490 (child running)
LOADER: marker counter 490 -> 495 (child running)
LOADER: marker counter 495 -> 501 (child running)
LOADER: marker counter 501 -> 506 (child running)
LOADER: marker counter 506 -> 511 (child running)
LOADER: marker counter 511 -> 516 (child running)
LOADER: result status=0 (OK) entry=018C0000 text=018C0000/656 bits data=018D0000/64 bits bss=018D8000/64 bits relocs=0 pcb=003FFBD0 nscns=3 len=510
LOADER: placed .text at 018C0000: 82 bytes, 0 differing
LOADER: placed .data at 018D0000: 8 bytes, 0 differing
LOADER: marker app: start=018C0000 data=DEADBEEF data2=12345678 bss=00000000 count=516
LOADER: PC at inspection = 018C0260
Average speed: 333.33% (36 seconds)
+104
View File
@@ -0,0 +1,104 @@
== /home/arti/code/k-space/vt1200/dwt/loader/build/rela.obj (342 bytes)
file hdr: magic=0x0090 nscns=3 symptr=0xb4 nsyms=9 opthdr=0 flags=0x0100
sec 1 .text paddr=0000000000 vaddr=0000000000 size=0xa0 bits (20 B) scnptr=0x8c nreloc=2 flags=0x20 [text]
reloc at 0x10 sym=8 type=0x11 R-RELLONG
reloc at 0x70 sym=7 type=0x11 R-RELLONG
sec 2 .data paddr=0000000000 vaddr=0000000000 size=0x0 bits (0 B) scnptr=0xa0 nreloc=0 flags=0x40 [data]
sec 3 .bss paddr=0000000000 vaddr=0000000000 size=0x0 bits (0 B) scnptr=0x0 nreloc=0 flags=0x80 [bss]
sym[0] .text value=0000000000 sec=1 class=3 naux=1
sym[2] .data value=0000000000 sec=2 class=3 naux=1
sym[4] .bss value=0000000000 sec=3 class=3 naux=1
sym[6] _start value=0000000000 sec=1 class=2
sym[7] ext_func value=0000000000 sec=0 class=2
sym[8] ext_data value=0000000000 sec=0 class=2
== /home/arti/code/k-space/vt1200/dwt/loader/build/relb.obj (290 bytes)
file hdr: magic=0x0090 nscns=3 symptr=0x92 nsyms=8 opthdr=0 flags=0x0100
sec 1 .text paddr=0000000000 vaddr=0000000000 size=0x10 bits (2 B) scnptr=0x8c nreloc=0 flags=0x20 [text]
sec 2 .data paddr=0000000000 vaddr=0000000000 size=0x20 bits (4 B) scnptr=0x8e nreloc=0 flags=0x40 [data]
sec 3 .bss paddr=0000000000 vaddr=0000000000 size=0x0 bits (0 B) scnptr=0x0 nreloc=0 flags=0x80 [bss]
sym[0] .text value=0000000000 sec=1 class=3 naux=1
sym[2] .data value=0000000000 sec=2 class=3 naux=1
sym[4] .bss value=0000000000 sec=3 class=3 naux=1
sym[6] ext_func value=0000000000 sec=1 class=2
sym[7] ext_data value=0000000000 sec=2 class=2
== /home/arti/code/k-space/vt1200/dwt/loader/build/relabs.out (572 bytes)
file hdr: magic=0x0090 nscns=3 symptr=0xc2 nsyms=21 opthdr=28 flags=0x0103
optional: magic=0x0108 vstamp=0x00c7 text=0xb0 bits data=0x20 bits bss=0x0 bits entry=0x018c0000 textstart=0x018c0000 datastart=0x018d0000
optional: sizes in bytes text=22 data=4 bss=0; entry in bits=0x18c0000
sec 1 .text paddr=00018c0000 vaddr=00018c0000 size=0xb0 bits (22 B) scnptr=0xa8 nreloc=0 flags=0x20 [text]
sec 2 .data paddr=00018d0000 vaddr=00018d0000 size=0x20 bits (4 B) scnptr=0xbe nreloc=0 flags=0x40 [data]
sec 3 .bss paddr=00018d8000 vaddr=00018d8000 size=0x0 bits (0 B) scnptr=0x0 nreloc=0 flags=0x80 [bss]
sym[0] .text value=00018c0000 sec=1 class=3 naux=1
sym[2] .data value=00018d0000 sec=2 class=3 naux=1
sym[4] .bss value=00018d8000 sec=3 class=3 naux=1
sym[6] .text value=00018c00a0 sec=1 class=3 naux=1
sym[8] .data value=00018d0000 sec=2 class=3 naux=1
sym[10] .bss value=00018d8000 sec=3 class=3 naux=1
sym[12] _start value=00018c0000 sec=1 class=2
sym[13] ext_func value=00018c00a0 sec=1 class=2
sym[14] ext_data value=00018d0000 sec=2 class=2
sym[15] .text value=00018c0000 sec=1 class=2
sym[16] etext value=00018c00b0 sec=1 class=2
sym[17] .data value=00018d0000 sec=2 class=2
sym[18] edata value=00018d0020 sec=2 class=2
sym[19] .bss value=00018d8000 sec=3 class=2
sym[20] end value=00018d8000 sec=3 class=2
== /home/arti/code/k-space/vt1200/dwt/loader/build/relabs2.out (572 bytes)
file hdr: magic=0x0090 nscns=3 symptr=0xc2 nsyms=21 opthdr=28 flags=0x0103
optional: magic=0x0108 vstamp=0x00c7 text=0xb0 bits data=0x20 bits bss=0x0 bits entry=0x018e0000 textstart=0x018e0000 datastart=0x018f0000
optional: sizes in bytes text=22 data=4 bss=0; entry in bits=0x18e0000
sec 1 .text paddr=00018e0000 vaddr=00018e0000 size=0xb0 bits (22 B) scnptr=0xa8 nreloc=0 flags=0x20 [text]
sec 2 .data paddr=00018f0000 vaddr=00018f0000 size=0x20 bits (4 B) scnptr=0xbe nreloc=0 flags=0x40 [data]
sec 3 .bss paddr=00018f8000 vaddr=00018f8000 size=0x0 bits (0 B) scnptr=0x0 nreloc=0 flags=0x80 [bss]
sym[0] .text value=00018e0000 sec=1 class=3 naux=1
sym[2] .data value=00018f0000 sec=2 class=3 naux=1
sym[4] .bss value=00018f8000 sec=3 class=3 naux=1
sym[6] .text value=00018e00a0 sec=1 class=3 naux=1
sym[8] .data value=00018f0000 sec=2 class=3 naux=1
sym[10] .bss value=00018f8000 sec=3 class=3 naux=1
sym[12] _start value=00018e0000 sec=1 class=2
sym[13] ext_func value=00018e00a0 sec=1 class=2
sym[14] ext_data value=00018f0000 sec=2 class=2
sym[15] .text value=00018e0000 sec=1 class=2
sym[16] etext value=00018e00b0 sec=1 class=2
sym[17] .data value=00018f0000 sec=2 class=2
sym[18] edata value=00018f0020 sec=2 class=2
sym[19] .bss value=00018f8000 sec=3 class=2
sym[20] end value=00018f8000 sec=3 class=2
== /home/arti/code/k-space/vt1200/dwt/loader/build/reloc.out (572 bytes)
file hdr: magic=0x0090 nscns=3 symptr=0xc2 nsyms=21 opthdr=28 flags=0x0103
optional: magic=0x0108 vstamp=0x00c7 text=0xb0 bits data=0x20 bits bss=0x0 bits entry=0x00000000 textstart=0x00000000 datastart=0x000000b0
optional: sizes in bytes text=22 data=4 bss=0; entry in bits=0 (no -e global symbol)
sec 1 .text paddr=0000000000 vaddr=0000000000 size=0xb0 bits (22 B) scnptr=0xa8 nreloc=0 flags=0x20 [text]
sec 2 .data paddr=00000000b0 vaddr=00000000b0 size=0x20 bits (4 B) scnptr=0xbe nreloc=0 flags=0x40 [data]
sec 3 .bss paddr=00000000d0 vaddr=00000000d0 size=0x0 bits (0 B) scnptr=0x0 nreloc=0 flags=0x80 [bss]
sym[0] .text value=0000000000 sec=1 class=3 naux=1
sym[2] .data value=00000000b0 sec=2 class=3 naux=1
sym[4] .bss value=00000000d0 sec=3 class=3 naux=1
sym[6] .text value=00000000a0 sec=1 class=3 naux=1
sym[8] .data value=00000000b0 sec=2 class=3 naux=1
sym[10] .bss value=00000000d0 sec=3 class=3 naux=1
sym[12] _start value=0000000000 sec=1 class=2
sym[13] ext_func value=00000000a0 sec=1 class=2
sym[14] ext_data value=00000000b0 sec=2 class=2
sym[15] .text value=0000000000 sec=1 class=2
sym[16] etext value=00000000b0 sec=1 class=2
sym[17] .data value=00000000b0 sec=2 class=2
sym[18] edata value=00000000d0 sec=2 class=2
sym[19] .bss value=00000000d0 sec=3 class=2
sym[20] end value=00000000d0 sec=3 class=2
== .text: 22 vs 22 bytes
differing bytes: 2
0x0004: 8d -> 8f
0x0010: 8c -> 8e
== .data: 4 vs 4 bytes
differing bytes: 0
== .bss: 0 vs 0 bytes
differing bytes: 0
+26
View File
@@ -0,0 +1,26 @@
Warning: -video none doesn't make much sense without -seconds_to_run
vt1200: screen_update#1 frame=0 clip_y=0..0 screen=1280x901
LOADER: payload dwt/loader/build/loader.bin (1220 B) -> bit 01880000
LOADER: COFF dwt/loader/build/rela.obj (342 B) -> bit 01900000
LOADER: file magic=0090 nscns=3 opthdr=0 optmagic=none entry=00000000 textstart=00000000
LOADER: sec .text paddr=00000000 size=160 bits (20 B) scnptr=0x8c flags=0x20
LOADER: sec .data paddr=00000000 size=0 bits (0 B) scnptr=0xa0 flags=0x40
LOADER: sec .bss paddr=00000000 size=0 bits (0 B) scnptr=0 flags=0x80
vt1200: screen_update#2 frame=0 clip_y=1..900 screen=1280x901
vt1200: scanline#1 line=1 enabled=1
vt1200: guard#1 frame=0 dump_frame=-1 dump_ram=-1
vt1200: screen_update#3 frame=1 clip_y=0..0 screen=1280x901
vt1200: scanline#2 line=0 enabled=1
vt1200: screen_update#4 frame=1 clip_y=1..1 screen=1280x901
vt1200: scanline#3 line=1 enabled=1
vt1200: scanline#4 line=2 enabled=1
LOADER: loader poked 610 words, readback 0 bad at 01880000
LOADER: COFF poked 171 words, readback 0 bad at 01900000
LOADER: pre-filled .bss 00000000..00000000 with A5A5
LOADER: descriptor @01882C00 magic=4C44/5231 buf=01900000 len=342 mode=0
LOADER: will resume at 3F579970 after create_process
LOADER: frame 2500: entered loader at 01880000 (caller SP=007F52B0)
LOADER: result status=7 (relocation records present (unsupported)) entry=00000000 text=00000000/0 bits data=00000000/0 bits bss=00000000/0 bits relocs=2 pcb=00000000 nscns=3 len=342
LOADER: placed .text at 00000000: 20 bytes, 5 differing
LOADER: PC at inspection = 3F5799D0
Average speed: 335.05% (35 seconds)
+28
View File
@@ -0,0 +1,28 @@
Warning: -video none doesn't make much sense without -seconds_to_run
vt1200: screen_update#1 frame=0 clip_y=0..0 screen=1280x901
LOADER: payload dwt/loader/build/loader.bin (1220 B) -> bit 01880000
LOADER: COFF dwt/loader/build/xhello.coff (774 B) -> bit 01900000
LOADER: file magic=0090 nscns=3 opthdr=28 optmagic=0108 entry=00000000 textstart=01840000
LOADER: sec .data paddr=00000000 size=0 bits (0 B) scnptr=0xa8 flags=0x40
LOADER: sec .bss paddr=00000000 size=0 bits (0 B) scnptr=0 flags=0x80
LOADER: sec .text paddr=01840000 size=3120 bits (390 B) scnptr=0xa8 flags=0x20
vt1200: screen_update#2 frame=0 clip_y=1..900 screen=1280x901
vt1200: scanline#1 line=1 enabled=1
vt1200: guard#1 frame=0 dump_frame=-1 dump_ram=-1
vt1200: screen_update#3 frame=1 clip_y=0..0 screen=1280x901
vt1200: scanline#2 line=0 enabled=1
vt1200: screen_update#4 frame=1 clip_y=1..1 screen=1280x901
vt1200: scanline#3 line=1 enabled=1
vt1200: scanline#4 line=2 enabled=1
LOADER: loader poked 610 words, readback 0 bad at 01880000
LOADER: COFF poked 387 words, readback 0 bad at 01900000
LOADER: pre-filled .bss 00000000..00000000 with A5A5
LOADER: descriptor @01882C00 magic=4C44/5231 buf=01900000 len=774 mode=0
LOADER: will resume at 3F579970 after create_process
LOADER: frame 2500: entered loader at 01880000 (caller SP=007F52B0)
LOADER: result status=0 (OK) entry=01840000 text=01840000/3120 bits data=00000000/0 bits bss=00000000/0 bits relocs=0 pcb=003FFBD0 nscns=3 len=774
LOADER: placed .text at 01840000: 390 bytes, 0 differing
LOADER: xhello: stage=6 strlen=4 display=006BC910 root=0001006B window=00010001 sync=00060001
LOADER: PC at inspection = 3F579970
LOADER: snapshot /home/arti/code/k-space/vt1200/dwt/loader/evidence/loader_frame2650.png ok=true
Average speed: 344.05% (36 seconds)
+496
View File
@@ -0,0 +1,496 @@
; loader.asm -- COFF loader for the VT1200 / TMS34010.
;
; Input: a TI GSP COFF image (GSPLNK `-a` output) already in RAM, and a
; 16-byte descriptor (offsets in BITS, since all pointers here are bit
; addresses; the byte offsets are 0, 2, 4, 8 and 12):
;
; DESC + 0x00 bits u16 0x4C44 "LD" ) magic; both words must match
; DESC + 0x10 bits u16 0x5231 "R1" )
; DESC + 0x20 bits u32 buf bit address of the COFF image
; DESC + 0x40 bits u32 len length in bytes
; DESC + 0x60 bits u32 mode 1 = return to the caller (rets)
; 0 = debug resume at LD_ORIG_PC
;
; The descriptor pointer is A8. If A8 is zero, or does not point at a valid
; descriptor, the fixed descriptor at 0x01882C00 is used. A transport that
; receives a COFF over the network only has to write {buf,len,mode} there and
; call the loader entry; it does not choose a load address. The loader takes
; the addresses from the COFF section headers.
;
; Result block at 0x01882D00 (32-bit cells, bit addresses):
;
; +0x000 status 0 ok, nonzero = error (see the ld_err_* labels)
; +0x020 entry bit address passed to create_process
; +0x040 text addr .text paddr from the COFF (bits)
; +0x060 text size .text size (bits)
; +0x080 data addr .data paddr
; +0x0A0 data size .data size (bits)
; +0x0C0 bss addr .bss paddr
; +0x0E0 bss size .bss size (bits)
; +0x100 relocs relocation entries seen in the output COFF
; +0x120 pcb create_process() return value (0 on failure)
; +0x140 nscns section count from the file header
; +0x160 coflen length from the descriptor (bytes)
; +0x180 version loader base address, 0x01880000
;
; The image is POSITION-DEPENDENT: GSPLNK resolves every reference and emits
; nreloc = 0, so each section is copied to the bit address in its header and
; no relocation is applied. A COFF that still carries relocation records is
; refused (status 7) rather than guessed at.
;
; Safety checks before any copy:
; * size is a whole number of 16-bit words;
; * the section bytes lie inside the descriptor's (buf,len);
; * paddr..paddr+size is inside main RAM (bits 0x100..0x2000000);
; * it does not overlap the loader page [01880000,01883200) or the COFF
; buffer;
; * it lies inside one block of the firmware's global free list
; (head at bit 0x1E8AC0, block header {u32 size_bits; ...; u32 next@+0x20},
; user data at block+0x40). This is a check, not a reservation: the
; loader cannot make malloc hand out a chosen address.
;
; Delivered debugger-assisted for now: poke the raw .bin at 0x01880000, write
; the COFF at buf, write the descriptor, then set PC = 0x01880000 (A8 = 0 is
; fine). mode = 0 resumes at LD_ORIG_PC (the harness saves the interrupted
; PC); mode = 1 returns to the caller and passes the status in A8.
;
; Linked at bit 0x01880000; position-dependent itself.
.def _start
LOADER_BASE equ 01880000h
LD_SCRATCH equ 01882800h
DESC_ADDR equ 01882C00h
RESULT_BASE equ 01882D00h
ARG_AREA equ 01882B00h
RETURN_STUB equ 01883100h
LD_SP_AFTER equ LD_SCRATCH+000h
LD_A14 equ LD_SCRATCH+020h
LD_ENTRY equ LD_SCRATCH+040h
LD_BUF equ LD_SCRATCH+060h
LD_LEN equ LD_SCRATCH+080h
LD_MODE equ LD_SCRATCH+0A0h
LD_NSCNS equ LD_SCRATCH+0C0h
LD_RELOCS equ LD_SCRATCH+0E0h
LD_SEC_PADDR equ LD_SCRATCH+100h
LD_SEC_SIZE equ LD_SCRATCH+120h
LD_SEC_SCNPTR equ LD_SCRATCH+140h
LD_TEXT_ADDR equ LD_SCRATCH+160h
LD_TEXT_SIZE equ LD_SCRATCH+180h
LD_DATA_ADDR equ LD_SCRATCH+1A0h
LD_DATA_SIZE equ LD_SCRATCH+1C0h
LD_BSS_ADDR equ LD_SCRATCH+1E0h
LD_BSS_SIZE equ LD_SCRATCH+200h
LD_ORIG_PC equ LD_SCRATCH+220h
RESULT_STATUS equ RESULT_BASE+000h
RESULT_ENTRY equ RESULT_BASE+020h
RESULT_TEXT_A equ RESULT_BASE+040h
RESULT_TEXT_S equ RESULT_BASE+060h
RESULT_DATA_A equ RESULT_BASE+080h
RESULT_DATA_S equ RESULT_BASE+0A0h
RESULT_BSS_A equ RESULT_BASE+0C0h
RESULT_BSS_S equ RESULT_BASE+0E0h
RESULT_RELOCS equ RESULT_BASE+100h
RESULT_PCB equ RESULT_BASE+120h
RESULT_NSCNS equ RESULT_BASE+140h
RESULT_LEN equ RESULT_BASE+160h
RESULT_VERSION equ RESULT_BASE+180h
.text
_start:
mmtm sp, a0,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13
move sp, @LD_SP_AFTER, 1
move a14, @LD_A14, 1
setf 16, 0, 0
setf 32, 0, 1
; ---- descriptor -----------------------------------------------------
; A8 points at it only if both magic words match; else use the fixed one.
move a8, a6
move a8, a8
jreq ld_fixed_desc
move *a6, a0, 0
cmpi 4C44h, a0
jrne ld_fixed_desc
move *a6(10h), a0, 0
cmpi 5231h, a0
jreq ld_have_desc
ld_fixed_desc:
movi DESC_ADDR, a6, L
move *a6, a0, 0
cmpi 4C44h, a0
jrne ld_bad_desc
move *a6(10h), a0, 0
cmpi 5231h, a0
jrne ld_bad_desc
ld_have_desc:
move *a6(20h), a7, 1 ; buf
move *a6(40h), a8, 1 ; len
move *a6(60h), a12, 1 ; mode
move a7, @LD_BUF, 1
move a8, @LD_LEN, 1
move a12, @LD_MODE, 1
move a12, @RESULT_VERSION, 1 ; harmless; overwritten below
movi LOADER_BASE, a0, L
move a0, @RESULT_VERSION, 1
; clear the counters we report; status stays FF until this loader writes it
movi 0FFFFFFFFh, a0, L
move a0, @RESULT_STATUS, 1
sub a0, a0
move a0, @LD_RELOCS, 1
move a0, @LD_TEXT_ADDR, 1
move a0, @LD_TEXT_SIZE, 1
move a0, @LD_DATA_ADDR, 1
move a0, @LD_DATA_SIZE, 1
move a0, @LD_BSS_ADDR, 1
move a0, @LD_BSS_SIZE, 1
move a0, @RESULT_ENTRY, 1
move a0, @RESULT_TEXT_A, 1
move a0, @RESULT_TEXT_S, 1
move a0, @RESULT_DATA_A, 1
move a0, @RESULT_DATA_S, 1
move a0, @RESULT_BSS_A, 1
move a0, @RESULT_BSS_S, 1
move a0, @RESULT_RELOCS, 1
move a0, @RESULT_PCB, 1
; ---- file header ----------------------------------------------------
movi 20, a0, L
cmp a0, a8
jrlo ld_err_short
move *a7, a0, 0 ; magic
cmpi 0090h, a0
jrne ld_err_magic
move *a7(10h), a9, 0 ; nscns (+2 bytes)
move a9, @LD_NSCNS, 1
move *a7(10h), a0, 0
move a9, @RESULT_NSCNS, 1
move a8, @RESULT_LEN, 1
; section headers = buf + (20 + opthdr + nscns*40) bytes; must fit in len
move *a7(80h), a1, 0 ; opthdr (+16 bytes)
move a9, a2
sll 5, a2 ; nscns*32
move a9, a3
sll 3, a3 ; nscns*8
add a3, a2 ; nscns*40
add a1, a2
addi 20, a2 ; byte offset of section headers end
cmp a2, a8 ; a8 - a2
jrlo ld_err_short
; secbase = buf + (20 + opthdr)*8 bits
sll 3, a1 ; opthdr in bits
addi 160, a1 ; 20 bytes in bits
add a7, a1
move a1, a10
; ---- entry point ----------------------------------------------------
; optional header at buf+20 bytes (0x0A0 bits): magic 0x0108; entry at
; +16 bytes (0x080 bits further); textstart at +20 bytes.
move *a7(0A0h), a0, 0
cmpi 0108h, a0
jrne ld_no_opt
move *a7(120h), a5, 1 ; entry (bits)
move a5, a5
jrne ld_entry_set
move *a7(140h), a5, 1 ; textstart (bits)
jruc ld_entry_set
ld_no_opt:
sub a5, a5
ld_entry_set:
move a5, @LD_ENTRY, 1
move a5, @RESULT_ENTRY, 1
; ---- section loop ---------------------------------------------------
sub a11, a11 ; section index
ld_sec_loop:
cmp a9, a11 ; a11 - a9
jrhs ld_sec_done
move *a10(40h), a0, 1 ; paddr (bits) +8 bytes
move *a10(80h), a1, 1 ; size (bits) +16
move *a10(0A0h), a2, 1 ; scnptr (bytes) +20
move *a10(100h), a3, 0 ; nreloc +32
move *a10(120h), a4, 1 ; flags +36
move a0, @LD_SEC_PADDR, 1
move a1, @LD_SEC_SIZE, 1
move a2, @LD_SEC_SCNPTR, 1
; record the first text/data/bss section for the result block
move a4, a5
andi 20h, a5
move a5, a5
jreq ld_not_text
move @LD_TEXT_ADDR, a5, 1
move a5, a5
jrne ld_not_text
move a0, @LD_TEXT_ADDR, 1
move a1, @LD_TEXT_SIZE, 1
ld_not_text:
move a4, a5
andi 40h, a5
move a5, a5
jreq ld_not_data
move @LD_DATA_ADDR, a5, 1
move a5, a5
jrne ld_not_data
move a0, @LD_DATA_ADDR, 1
move a1, @LD_DATA_SIZE, 1
ld_not_data:
move a4, a5
andi 80h, a5
move a5, a5
jreq ld_not_bss
move @LD_BSS_ADDR, a5, 1
move a5, a5
jrne ld_not_bss
move a0, @LD_BSS_ADDR, 1
move a1, @LD_BSS_SIZE, 1
ld_not_bss:
; relocation records: count, then refuse (the linked image has none)
move a3, a3
jreq ld_no_reloc
move @LD_RELOCS, a5, 1
add a3, a5
move a5, @LD_RELOCS, 1
jruc ld_err_reloc
ld_no_reloc:
; size 0: nothing to place; size must be whole 16-bit words
move a1, a1
jreq ld_sec_next
move a1, a5
andi 0Fh, a5
move a5, a5
jrne ld_err_size
; source range: scnptr + size/8 <= len (when there are bytes)
move a2, a2
jreq ld_no_src
move a1, a5
srl 3, a5 ; size in bytes
add a5, a2 ; scnptr + nbytes
cmp a8, a2 ; a8 - a2
jrhi ld_err_short
ld_no_src:
; target range: 0x100 <= paddr and paddr+size <= 0x2000000 bits
move @LD_SEC_PADDR, a0, 1
cmpi 100h, a0
jrlo ld_err_bounds
move @LD_SEC_SIZE, a1, 1
move a0, a3
add a1, a3 ; target end
movi 2000000h, a5, L
cmp a5, a3
jrhi ld_err_bounds
; overlap with the loader page [01880000,01883200)
movi 01883200h, a5, L
cmp a5, a0
jrhs ld_ov1_done
movi 01880000h, a5, L
cmp a3, a5
jrhs ld_ov1_done
jruc ld_err_overlap
ld_ov1_done:
; overlap with the COFF buffer [buf, buf+len*8)
move a8, a5
sll 3, a5
add a7, a5 ; buffer end in bits
cmp a5, a0
jrhs ld_ov2_done
cmp a3, a7
jrhs ld_ov2_done
jruc ld_err_overlap
ld_ov2_done:
; ---- global free-list check ----------------------------------------
; a block is {u32 size_bits; ...; u32 next@+0x20}; data at block+0x40.
move a0, @LD_SEC_PADDR, 1 ; (unchanged, kept for clarity)
move a3, @LD_SEC_SIZE, 1 ; temporarily hold target end
move @1E8AC0h, a6, 1 ; global free-list head (block address)
movi 64, a5, L
ld_free_walk:
move a6, a6
jreq ld_err_notfree
move *a6, a1, 1 ; block size in bits
move *a6(20h), a2, 1 ; next block
move a6, a0
addi 40h, a0 ; user start
move @LD_SEC_PADDR, a3, 1
cmp a0, a3
jrlo ld_free_next
move a6, a4
add a1, a4 ; block end
move @LD_SEC_SIZE, a1, 1 ; target end (stashed above)
cmp a4, a1
jrhi ld_free_next
jruc ld_free_ok
ld_free_next:
move a2, a6
dsjs a5, ld_free_walk
jruc ld_err_notfree
ld_free_ok:
; restore size in LD_SEC_SIZE (the stash overwrote it)
; target end - paddr = size
move @LD_SEC_SIZE, a1, 1
move @LD_SEC_PADDR, a0, 1
sub a0, a1 ; a1 = size again
move a1, @LD_SEC_SIZE, 1
; ---- place the section ---------------------------------------------
move @LD_SEC_SCNPTR, a0, 1
move a0, a0
jreq ld_zero_sec
sll 3, a0 ; file offset -> bit offset
add a7, a0 ; source address
move @LD_SEC_PADDR, a2, 1
move @LD_SEC_SIZE, a1, 1
srl 4, a1 ; number of 16-bit words
ld_copy_words:
move *a0+, a4, 0
move a4, *a2+, 0
dsjs a1, ld_copy_words
jruc ld_sec_next
ld_zero_sec:
move @LD_SEC_PADDR, a2, 1
move @LD_SEC_SIZE, a1, 1
srl 4, a1
sub a4, a4
ld_zero_words:
move a4, *a2+, 0
dsjs a1, ld_zero_words
ld_sec_next:
addi 140h, a10 ; 40-byte section header = 320 bits
addi 1, a11
jruc ld_sec_loop
ld_sec_done:
move @LD_TEXT_ADDR, a0, 1
move a0, @RESULT_TEXT_A, 1
move @LD_TEXT_SIZE, a1, 1
move a1, @RESULT_TEXT_S, 1
move @LD_DATA_ADDR, a0, 1
move a0, @RESULT_DATA_A, 1
move @LD_DATA_SIZE, a1, 1
move a1, @RESULT_DATA_S, 1
move @LD_BSS_ADDR, a0, 1
move a0, @RESULT_BSS_A, 1
move @LD_BSS_SIZE, a1, 1
move a1, @RESULT_BSS_S, 1
move @LD_RELOCS, a0, 1
move a0, @RESULT_RELOCS, 1
; ---- create_process(entry, name, stack, 1, arg) --------------------
move @LD_ENTRY, a0, 1
move a0, a0
jrne ld_have_entry
jruc ld_err_noentry
ld_have_entry:
move @LD_A14, a14, 1
move @LD_SP_AFTER, sp, 1
move a14, -*sp, 1 ; the slot the firmware callee restores
movi ARG_AREA, a14, L
movi 0, a0, L
move a0, *a14+, 1 ; arg4 = 0
movi 1, a0, L
move a0, *a14+, 1 ; arg3 = 1
movi 6000h, a0, L
move a0, *a14+, 1 ; arg2 = stack bytes
movi ld_appname, a0, L
move a0, *a14+, 1 ; arg1 = name string
move @LD_ENTRY, a0, 1
move a0, *a14+, 1 ; arg0 = entry (bit address)
calla 3F706A40h ; create_process
move @LD_SP_AFTER, sp, 1
move @LD_A14, a14, 1
setf 16, 0, 0
setf 32, 0, 1
move a8, @RESULT_PCB, 1
move a8, a8
jreq ld_err_create
sub a0, a0
move a0, @RESULT_STATUS, 1
jruc ld_finish
; ---- errors ---------------------------------------------------------
ld_bad_desc:
movi 1, a0, L
jruc ld_error
ld_err_short:
movi 2, a0, L
jruc ld_error
ld_err_magic:
movi 3, a0, L
jruc ld_error
ld_err_size:
movi 4, a0, L
jruc ld_error
ld_err_bounds:
movi 5, a0, L
jruc ld_error
ld_err_overlap:
movi 6, a0, L
jruc ld_error
ld_err_reloc:
movi 7, a0, L
jruc ld_error
ld_err_notfree:
movi 8, a0, L
jruc ld_error
ld_err_noentry:
movi 9, a0, L
jruc ld_error
ld_err_create:
movi 10, a0, L
ld_error:
move a0, @RESULT_STATUS, 1
move @LD_NSCNS, a0, 1
move a0, @RESULT_NSCNS, 1
move @LD_RELOCS, a0, 1
move a0, @RESULT_RELOCS, 1
ld_finish:
move @LD_ENTRY, a0, 1
move a0, @RESULT_ENTRY, 1
move @LD_NSCNS, a0, 1
move a0, @RESULT_NSCNS, 1
move @LD_LEN, a0, 1
move a0, @RESULT_LEN, 1
movi LOADER_BASE, a0, L
move a0, @RESULT_VERSION, 1
; ---- return or spin -------------------------------------------------
move @LD_MODE, a0, 1
move a0, a0
jrne ld_return
; mode 0 (debugger entry): restore the interrupted state and resume at
; the PC the harness hijacked. Returning to the OS idle loop lets the
; scheduler run the created child.
move @LD_SP_AFTER, sp, 1
move @LD_A14, a14, 1
mmfm sp, a0,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13
move @LD_ORIG_PC, a0, 1
jump a0
ld_return:
move @LD_SP_AFTER, sp, 1
move @LD_A14, a14, 1
mmfm sp, a0,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13
move @RESULT_STATUS, a8, 1 ; 0 = ok, else the error code
rets
ld_appname:
.byte "LOADER", 0
.end
+338
View File
@@ -0,0 +1,338 @@
-- loader.lua -- debugger-assisted COFF loader acceptance harness.
--
-- Boots the firmware with VT1200_SKIP_LEVEL1=1 (the documented divergence) to
-- the OS, then at frame LOADER_AT pokes:
-- * the loader payload at bit 0x01880000 (raw dwt/loader/build/loader.bin)
-- * a GSPLNK COFF image at LOADER_BUF (default bit 0x01900000)
-- * the loader descriptor at 0x01882C00
-- and sets PC = 0x01880000. It does not use the network, the rdebug service
-- or any firmware transport: this is the debugger-assisted milestone.
--
-- The loader itself copies the COFF sections to their linked bit addresses and
-- calls create_process(entry, "LOADER", 0x6000, 1, 0). This script only pokes
-- the input and reads the result; it never writes the app's code or markers.
--
-- Env:
-- LOADER_BIN loader payload (default dwt/loader/build/loader.bin)
-- LOADER_COFF app COFF (default dwt/loader/build/marker.coff)
-- LOADER_BUF COFF buffer bit address (default 0x01900000)
-- LOADER_AT injection frame (default 2500)
-- LOADER_END inspection/exit frame (default 2700)
-- LOADER_OUT evidence directory (default dwt/loader/evidence)
-- LOADER_SNAP 1 = write a PNG at LOADER_END (default 0)
-- LOADER_VERBOSE 1 = print the result block every 25 frames
local function hex(v, w) return string.format("%0" .. (w or 8) .. "X", v) end
local machine = manager.machine
local cpu = machine.devices[':maincpu']
local dbg = machine.debugger
local prog = cpu.spaces['program']
if not dbg then
print("LOADER: debugger not enabled; pass -debug")
machine:exit()
return
end
local AT = tonumber(os.getenv("LOADER_AT") or "2500")
local ENDF = tonumber(os.getenv("LOADER_END") or "2700")
local BIN = os.getenv("LOADER_BIN") or "dwt/loader/build/loader.bin"
local COFF = os.getenv("LOADER_COFF") or "dwt/loader/build/marker.coff"
local BUF = tonumber(os.getenv("LOADER_BUF") or "0x01900000")
local OUT = os.getenv("LOADER_OUT") or "dwt/loader/evidence"
local SNAP = os.getenv("LOADER_SNAP") == "1"
local MODE = tonumber(os.getenv("LOADER_MODE") or "0")
local A8DESC = os.getenv("LOADER_A8_DESC") == "1"
local VERBOSE = os.getenv("LOADER_VERBOSE") == "1"
local LOADER_BASE = 0x01880000
local DESC = 0x01882C00
local RESULT = 0x01882D00
local RETURN_STUB = 0x01883100
local RETURN_SP = 0x01883110
local function rd(p) return io.open(p, "rb") end
local function slurp(p)
local f, err = rd(p)
if not f then error("cannot open " .. p .. ": " .. tostring(err)) end
local s = f:read("*a")
f:close()
return s
end
local function u16(s, o)
return s:byte(o + 1) + s:byte(o + 2) * 256
end
local function u32(s, o)
return s:byte(o + 1) + s:byte(o + 2) * 256
+ s:byte(o + 3) * 65536 + s:byte(o + 4) * 16777216
end
local function parse_coff(d)
local c = { data = d }
c.magic = u16(d, 0)
c.nscns = u16(d, 2)
c.opthdr = u16(d, 16)
c.sections = {}
if c.opthdr > 0 then
c.optmagic = u16(d, 20)
c.entry = u32(d, 20 + 16)
c.textstart = u32(d, 20 + 20)
c.datastart = u32(d, 20 + 24)
end
local base = 20 + c.opthdr
for i = 0, c.nscns - 1 do
local o = base + i * 40
local name = d:sub(o + 1, o + 8):gsub("%z", "")
c.sections[#c.sections + 1] = {
name = name,
paddr = u32(d, o + 8),
size = u32(d, o + 16), -- bits
scnptr = u32(d, o + 20),
flags = u32(d, o + 36),
}
end
return c
end
local function poke_bytes(bitaddr, data)
local n = math.floor((#data + 1) / 2)
for i = 0, n - 1 do
local lo = data:byte(i * 2 + 1) or 0
local hi = data:byte(i * 2 + 2) or 0
prog:write_u16(bitaddr + i * 16, lo + hi * 256)
end
return n
end
local function verify_bytes(bitaddr, data)
local n = math.floor((#data + 1) / 2)
local bad = 0
for i = 0, n - 1 do
local lo = data:byte(i * 2 + 1) or 0
local hi = data:byte(i * 2 + 2) or 0
if prog:read_u16(bitaddr + i * 16) ~= lo + hi * 256 then
bad = bad + 1
end
end
return n, bad
end
local function w32(a, v) prog:write_u32(a, v) end
local function r32(a)
local ok, v = pcall(function() return prog:read_u32(a) end)
if ok then return v end
return 0xDEADBEEF
end
local loader = slurp(BIN)
local coff = slurp(COFF)
local app = parse_coff(coff)
print(string.format("LOADER: payload %s (%d B) -> bit %s", BIN, #loader, hex(LOADER_BASE)))
print(string.format("LOADER: COFF %s (%d B) -> bit %s", COFF, #coff, hex(BUF)))
print(string.format("LOADER: file magic=%04X nscns=%d opthdr=%d optmagic=%s entry=%s textstart=%s",
app.magic, app.nscns, app.opthdr,
app.optmagic and string.format("%04X", app.optmagic) or "none",
hex(app.entry or 0), hex(app.textstart or 0)))
for _, s in ipairs(app.sections) do
print(string.format("LOADER: sec %-8s paddr=%s size=%d bits (%d B) scnptr=%#x flags=%#x",
s.name, hex(s.paddr), s.size, math.floor(s.size / 8), s.scnptr, s.flags))
end
local TRACE = os.getenv("LOADER_TRACE") == "1"
local frames = 0
local injected = false
local done = false
local last_count = -1
local function status_name(v)
local t = {
[0] = "OK",
[1] = "bad descriptor",
[2] = "truncated COFF / section headers",
[3] = "bad COFF magic",
[4] = "section size not whole words",
[5] = "target outside RAM",
[6] = "target overlaps loader page or COFF buffer",
[7] = "relocation records present (unsupported)",
[8] = "target not in a free-list block",
[9] = "no entry point",
}
return t[v] or ("error " .. tostring(v))
end
local function result_dump()
local st = r32(RESULT + 0x000)
print(string.format(
"LOADER: result status=%d (%s) entry=%s text=%s/%d bits data=%s/%d bits bss=%s/%d bits relocs=%d pcb=%s nscns=%d len=%d",
st, status_name(st), hex(r32(RESULT + 0x020)),
hex(r32(RESULT + 0x040)), r32(RESULT + 0x060),
hex(r32(RESULT + 0x080)), r32(RESULT + 0x0A0),
hex(r32(RESULT + 0x0C0)), r32(RESULT + 0x0E0),
r32(RESULT + 0x100), hex(r32(RESULT + 0x120)),
r32(RESULT + 0x140), r32(RESULT + 0x160)))
end
local function inject()
-- 1. loader itself
local n, bad = 0, 0
poke_bytes(LOADER_BASE, loader)
n, bad = verify_bytes(LOADER_BASE, loader)
print(string.format("LOADER: loader poked %d words, readback %d bad at %s",
n, bad, hex(LOADER_BASE)))
-- 2. COFF image
poke_bytes(BUF, coff)
n, bad = verify_bytes(BUF, coff)
print(string.format("LOADER: COFF poked %d words, readback %d bad at %s",
n, bad, hex(BUF)))
-- 3. pre-fill every .bss section with A5A5, so a loaded zero is meaningful
for _, s in ipairs(app.sections) do
if s.flags & 0x80 ~= 0 then
for i = 0, math.floor(s.size / 16) - 1 do
prog:write_u16(s.paddr + i * 16, 0xA5A5)
end
print(string.format("LOADER: pre-filled .bss %s..%s with A5A5",
hex(s.paddr), hex(s.paddr + s.size)))
end
end
-- 4. descriptor: magic "LD" "R1", buf, len, mode=0 (spin)
w32(DESC + 0x00, 0)
prog:write_u16(DESC + 0x00, 0x4C44)
prog:write_u16(DESC + 0x10, 0x5231)
w32(DESC + 0x20, BUF)
w32(DESC + 0x40, #coff)
w32(DESC + 0x60, MODE)
print(string.format("LOADER: descriptor @%s magic=%04X/%04X buf=%s len=%d mode=%d",
hex(DESC), prog:read_u16(DESC + 0x00), prog:read_u16(DESC + 0x10),
hex(r32(DESC + 0x20)), r32(DESC + 0x40), r32(DESC + 0x60)))
-- 5. return stub. mode 0 ignores it (the loader jumps to ORIG_PC
-- itself); mode 1 returns here, and the stub resumes the interrupted
-- PC so the caller yields and the scheduler can run the child.
local orig_pc = cpu.state['PC'].value
if MODE == 1 then
prog:write_u16(RETURN_STUB, 0xC080) -- jauc <orig_pc>
prog:write_u16(RETURN_STUB + 0x10, orig_pc & 0xFFFF)
prog:write_u16(RETURN_STUB + 0x20, math.floor(orig_pc / 0x10000) & 0xFFFF)
else
prog:write_u16(RETURN_STUB, 0xC0FF) -- jruc self
end
-- 6. enter the loader. A8=0 selects the fixed descriptor; SP points at
-- the return slot so mode=1 would return to the spin stub.
-- Leave SP alone for mode 0: the loader pushes onto the current
-- process stack, then restores it and resumes at ORIG_PC. (mode 1
-- would use the return stub.)
w32(0x01882A20, orig_pc) -- LD_ORIG_PC
print(string.format("LOADER: will resume at %s after create_process", hex(orig_pc)))
cpu.state['A8'].value = A8DESC and DESC or 0
if MODE == 1 then
-- Simulate a CALLA from the current process: push the return
-- address on the *firmware* stack (a real transport would do this).
local sp = cpu.state['SP'].value - 0x20
w32(sp, RETURN_STUB)
cpu.state['SP'].value = sp
end
cpu.state['PC'].value = LOADER_BASE
injected = true
print(string.format("LOADER: frame %d: entered loader at %s (caller SP=%s)",
frames, hex(LOADER_BASE), hex(cpu.state['SP'].value)))
end
local function inspect()
result_dump()
-- Verify the placement from RAM: .text/.data must equal the file bytes.
for _, s in ipairs(app.sections) do
if s.scnptr ~= 0 and s.size > 0 then
local nb = math.floor(s.size / 8)
local bytes = coff:sub(s.scnptr + 1, s.scnptr + nb)
local _, bad = verify_bytes(s.paddr, bytes)
print(string.format("LOADER: placed %s at %s: %d bytes, %d differing",
s.name, hex(s.paddr), nb, bad))
end
end
local base = COFF:match("([^/]+)$") or COFF
if base:find("marker") then
print(string.format("LOADER: marker app: start=%s data=%s data2=%s bss=%s count=%d",
hex(r32(0x018E0000)), hex(r32(0x018E0020)), hex(r32(0x018E0040)),
hex(r32(0x018E0060)), r32(0x018E0080)))
elseif base:find("xhello") then
print(string.format("LOADER: xhello: stage=%d strlen=%d display=%s root=%s window=%s sync=%s",
r32(0x01890140), r32(0x01890160), hex(r32(0x01890100)),
hex(r32(0x01890110)), hex(r32(0x01890120)), hex(r32(0x01890130))))
end
print(string.format("LOADER: PC at inspection = %s", hex(cpu.state['PC'].value)))
end
emu.register_frame_done(function()
frames = frames + 1
if frames == AT and not injected then
inject()
if TRACE then dbg:command("trace /tmp/opencode/ld1.tr") end
end
if injected and TRACE and frames == AT + 1 then
dbg:command("trace off")
print("LOADER: trace written to /tmp/opencode/ld.tr")
end
if injected and not done then
if TRACE and frames <= AT + 40 then
print(string.format("LOADER: trace f=%d PC=%s SP=%s A14=%s status=%s entry=%s",
frames, hex(cpu.state['PC'].value), hex(cpu.state['SP'].value),
hex(cpu.state['A14'].value), hex(r32(RESULT + 0x000)),
hex(r32(RESULT + 0x020))))
end
local st = r32(RESULT + 0x000)
-- status 0 means OK; nonzero is final too once parsing has begun
if st ~= 0xFFFFFFFF and not done then
-- The loader writes 0 on success. A nonzero status is final
-- only after it has been written once (it is 0 from power-on,
-- so require the loader to have run: PC no longer at entry or
-- the app counter moved).
end
if VERBOSE and frames % 25 == 0 then
result_dump()
end
if base_contains_marker then
local c = r32(0x018E0080)
if c ~= last_count then
if last_count ~= -1 then
print(string.format("LOADER: marker counter %d -> %d (child running)",
last_count, c))
end
last_count = c
end
end
end
if frames >= ENDF then
if injected then
done = true
inspect()
if SNAP then
local screen = nil
for _, s in pairs(machine.screens) do screen = s break end
if screen then
local out = OUT .. "/loader_frame" .. frames .. ".png"
local ok, err = pcall(function() return screen:snapshot(out) end)
print(string.format("LOADER: snapshot %s ok=%s %s",
out, tostring(ok), tostring(err or "")))
end
end
end
machine:exit()
end
end, "vt1200-loader")
-- (Lua has no forward use of a name defined later; set a small flag here.)
base_contains_marker = (COFF:match("([^/]+)$") or ""):find("marker") ~= nil
dbg.visible_cpu = cpu
dbg.execution_state = 'run'
+66
View File
@@ -0,0 +1,66 @@
; marker.asm -- loader acceptance app.
;
; Built by dwt/loader/build.sh with three separate section origins:
; .text 018C0000h (byte 0x318000)
; .data 018D0000h (byte 0x31A000)
; .bss 018D8000h (byte 0x31B000)
;
; It is the *COFF image* that the loader must place; it is never poked as a
; raw blob. The loader parses the COFF, copies .text and .data, zeroes .bss,
; and calls create_process() with the image's entry point.
;
; Evidence cells (32-bit, bit addresses; outside every app section):
; 018E0000 _start address at run time (must be 018C0000)
; 018E0020 d_magic read from .data (must be DEADBEEF)
; 018E0040 d_two read from .data (must be 12345678)
; 018E0060 b_zero read from .bss (must be 0; the harness pre-fills A5)
; 018E0080 b_counter, incremented forever (proves the child is scheduled)
;
; The harness pre-fills the whole .bss range with A5A5A5A5 before the load, so
; a zero at 018E0060 is the loader's zero-fill, not a fresh-RAM accident.
.def _start
.text
_start:
setf 16, 0, 0
setf 32, 0, 1
; Run-time address of this code: position dependence, made visible.
movi _start, a2, L
move a2, @018E0000h, 1
; Initialised .data must have been copied by the loader.
move @d_magic, a0, 1
move a0, @018E0020h, 1
move @d_two, a1, 1
move a1, @018E0040h, 1
; .bss must have been zeroed by the loader (harness pre-fills A5).
move @b_zero, a3, 1
move a3, @018E0060h, 1
; A live counter: a created process, not a one-shot jump.
sub a4, a4
loop:
addi 1, a4
move a4, @b_counter, 1
move a4, @018E0080h, 1
movi 2000h, a5, L
delay:
dsjs a5, delay
jruc loop
; Kept to leave a call in the image (and a relocation in the .obj).
.global sub
sub:
rets
.data
d_magic: .long 0DEADBEEFh
d_two: .long 012345678h
.bss b_zero, 32, 1
.bss b_counter, 32, 1
.end
+85
View File
@@ -0,0 +1,85 @@
-- probe_os.lua -- private probe for the COFF loader work.
--
-- Prints the OS-phase heap free list (global list only, as HEAP.md advises),
-- and tests whether the CPU registers can be written from a frame hook while
-- the machine is running (the debugger is attached with -debug -debugger none).
--
-- VT1200_SKIP_LEVEL1=1 <mame> vt1200 ... -autoboot_script dwt/loader/probe_os.lua
--
-- Env: PROBE_AT (frame to sample, default 2500), PROBE_END (exit frame, 2520)
local function hex(v, w) return string.format("%0" .. (w or 8) .. "X", v) end
local machine = manager.machine
local cpu = machine.devices[':maincpu']
local dbg = machine.debugger
local prog = cpu.spaces['program']
if not dbg then
print("PROBE: no debugger")
machine:exit()
return
end
local AT = tonumber(os.getenv("PROBE_AT") or "2500")
local ENDF = tonumber(os.getenv("PROBE_END") or "2520")
local frames = 0
local tested = false
local function u32(a)
local ok, v = pcall(function() return prog:read_u32(a) end)
if ok then return v end
return 0xdeadbeef
end
local function heap()
print(string.format("PROBE: free counter @1E8BA0 = %d bits (%d bytes)",
u32(0x1E8BA0), math.floor(u32(0x1E8BA0) / 8)))
local head = u32(0x1E8AC0)
print(string.format("PROBE: global free-list head @1E8AC0 = %s", hex(head)))
local b = head
for i = 0, 15 do
if b == 0 then break end
local size = u32(b)
local nextp = u32(b + 0x20)
print(string.format("PROBE: block[%d] hdr=%s size=%d bits (%d B) user=%s..%s next=%s",
i, hex(b), size, math.floor(size / 8), hex(b + 0x40),
hex(b + size), hex(nextp)))
if nextp == head then break end
b = nextp
end
end
emu.register_frame_done(function()
frames = frames + 1
if frames == AT then
print(string.format("PROBE: frame %d PC=%s SP=%s A8=%s A14=%s",
frames, hex(cpu.state['PC'].value), hex(cpu.state['SP'].value),
hex(cpu.state['A8'].value), hex(cpu.state['A14'].value)))
heap()
-- Scratch return stub test: write jruc self at 01880F00, return address
-- at 01880F10, then set SP/PC from the frame hook.
prog:write_u16(0x01880F00, 0xC0FF) -- jruc 01880F00 (short, -1 word)
prog:write_u32(0x01880F10, 0x01880F00)
prog:write_u32(0x01880F20, 0xDEADBEEF)
print(string.format("PROBE: spin word readback=%04X ret=%s",
prog:read_u16(0x01880F00), hex(prog:read_u32(0x01880F10))))
cpu.state['SP'].value = 0x01880F10
cpu.state['A8'].value = 0x01880E00
cpu.state['PC'].value = 0x01880F00
tested = true
end
if tested and frames == AT + 2 then
print(string.format("PROBE: after 2 frames PC=%s SP=%s A8=%s",
hex(cpu.state['PC'].value), hex(cpu.state['SP'].value),
hex(cpu.state['A8'].value)))
end
if frames >= ENDF then
print(string.format("PROBE: marker 01880F20=%s (should be DEADBEEF, untouched)",
hex(u32(0x01880F20))))
machine:exit()
end
end, "vt1200-loader-probe")
dbg.visible_cpu = cpu
dbg.execution_state = 'run'
+12
View File
@@ -0,0 +1,12 @@
; rel_a.asm -- reldemo caller: has a 32-bit data reference and an absolute call
; to a symbol defined in rel_b.asm.
.def _start
.ref ext_func
.ref ext_data
.text
_start:
movi ext_data, a0, L ; 32-bit direct reference (R-RELLONG)
move a0, @018F0000h, 1 ; fixed marker (not a relocation)
calla ext_func ; 32-bit absolute call
rets
.end
+10
View File
@@ -0,0 +1,10 @@
; rel_b.asm -- reldemo callee/data: ext_func and ext_data are defined here.
.def ext_func
.def ext_data
.text
ext_func:
rets
.data
ext_data:
.long 0CAFEBABEh
.end
+79
View File
@@ -0,0 +1,79 @@
#!/bin/sh
# reldemo.sh -- prove what GSPLNK does with relocations, and that the linked
# image is position-dependent.
#
# 1. assemble two objects that reference each other's symbols (ext_func,
# ext_data); the .obj files carry relocation records.
# 2. link them with `-a` (the normal app flow): the output COFF must have
# nreloc = 0 -- the image is fully resolved.
# 3. link the *same* objects at two different origin sets and diff the .text
# bytes: they differ, so the image is position-dependent.
# 4. link without `-a`: report whether GSPLNK emits a relocatable COFF.
#
# All scratch/output stays under dwt/loader/reldemo/.
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"
mkdir -p "$WORK" "$OUT"
if [ ! -x "$WORK/GSPA.EXE" ]; then
mcopy -s -n -i "$IMG" "::/A2/*" "$WORK/"
mcopy -s -n -i "$IMG" "::/C2/*" "$WORK/"
fi
cp "$DIR/rel_a.asm" "$WORK/RELA.ASM"
cp "$DIR/rel_b.asm" "$WORK/RELB.ASM"
run_dos() {
SDL_VIDEODRIVER=dummy SDL_AUDIODRIVER=dummy \
timeout 180 dosbox -conf "$DOSBOX_CONF" -noprimaryconf -nolocalconf \
-c "mount c $WORK" -c "c:" "$@" -c "exit" -exit >/dev/null 2>&1
}
printf '%s\n' \
'-a' '-o RELABS.out' '-m RELABS.map' '-e _start' \
'RELA.obj RELB.obj' \
'SECTIONS' '{' \
' .text 018C0000h: {}' \
' .data 018D0000h: {}' \
' .bss 018D8000h: {}' \
'}' > "$WORK/RELABS.CMD"
printf '%s\n' \
'-a' '-o RELABS2.out' '-m RELABS2.map' '-e _start' \
'RELA.obj RELB.obj' \
'SECTIONS' '{' \
' .text 018E0000h: {}' \
' .data 018F0000h: {}' \
' .bss 018F8000h: {}' \
'}' > "$WORK/RELABS2.CMD"
printf '%s\n' \
'-o RELOC.out' '-m RELOC.map' '-e _start' \
'RELA.obj RELB.obj' > "$WORK/RELOC.CMD"
sed -i 's/$/\r/' "$WORK"/*.CMD
rm -f "$WORK"/REL*.OBJ "$WORK"/REL*.OUT "$WORK"/REL*.LST \
"$WORK"/REL*.MAP "$WORK"/REL*.HI "$WORK"/REL*.LO
run_dos \
-c "gspa rela rela.obj -q" \
-c "gspa relb relb.obj -q" \
-c "gsplnk relabs.cmd" \
-c "gsplnk relabs2.cmd"
# A missing relocatable output is itself a result; do not fail the script.
run_dos -c "gsplnk reloc.cmd" || true
for f in "$WORK"/REL*.OUT; do
[ -f "$f" ] && cp "$f" "$OUT/$(basename "$f" | tr 'A-Z' 'a-z')"
done
for f in "$WORK"/REL*.OBJ; do
[ -f "$f" ] && cp "$f" "$OUT/$(basename "$f" | tr 'A-Z' 'a-z')"
done
python3 "$DIR/coff.py" summary "$OUT/rela.obj" "$OUT/relb.obj" \
"$OUT/relabs.out" "$OUT/relabs2.out" "$OUT/reloc.out"
echo
python3 "$DIR/coff.py" raw "$OUT/relabs.out" "$OUT/relabs2.out"