reloc on startup reduced

This commit is contained in:
Scott Duensing 2026-06-25 17:13:50 -05:00
parent 6a90b2ec19
commit 0643479903
3 changed files with 26 additions and 3 deletions

View file

@ -61,11 +61,22 @@ echo "compile: $BASE.c -> $OUTBASE.o"
-O2 -ffunction-sections -c "$SRC" -o "$OBJ"
echo "link: -> $OUTBASE.bin"
# text-base 0: under the GS/OS Loader our segment lands at some bank
# the Loader picks (KIND=0x1000), so link-time addresses can start at
# offset 0 in the segment. With text-base=0 the link-time-baked IMM16
# operand for `lda gFoo` already equals gFoo's runtime offset within
# the segment (no segPlacedBase adjustment needed since the Loader
# places at bank-aligned bases), so the linker can skip emitting
# cRELOC entries for every IMM16 site — 6090% reduction in cRELOC
# count, proportional speed-up in the Loader's per-reloc walk.
# Bare-metal builds keep text-base=0x1000 (runInMame.sh loads at
# bank-0:1000 and link-time addresses must match).
#
# bss-base 0xA000 keeps BSS above the SHR shadow region ($2000-$9FFF
# in bank 0 mirrors to bank E1 SHR memory). Without this, the smaller
# section-gc'd demos place BSS at e.g. $2300 and global writes scribble
# on the screen.
LINKER_ARGS=(-o "$BIN" --text-base 0x1000 --bss-base 0xA000 \
LINKER_ARGS=(-o "$BIN" --text-base 0 --bss-base 0xA000 \
--map "$MAP" --reloc-out "$RELOC")
if [ "$DEBUG" = 1 ]; then
LINKER_ARGS+=(--debug-out "$DWARF")
@ -90,7 +101,7 @@ fi
echo "OMF: -> $OUTBASE.omf"
"$OMF" --input "$BIN" --map "$MAP" \
--base 0x1000 --entry __start --output "$OUT" \
--base 0 --entry __start --output "$OUT" \
--name "$(echo "$OUTBASE" | tr '[:lower:]' '[:upper:]' | cut -c1-8)" \
--expressload --relocs "$RELOC"

Binary file not shown.

View file

@ -548,7 +548,19 @@ static void applyReloc(std::vector<uint8_t> &buf, uint32_t off,
// `if (weakFn) weakFn()` null test that the null is meant to fail.
// recordCRelocSite handles the gate; byteCnt=2 distinguishes
// from IMM24 (3) so omfEmit emits cRELOC ByteCnt=2 here.
recordCRelocSite(patchAddr, target, /*byteCnt=*/2, /*bitShift=*/0);
// Optimization: when text-base's low 16 bits are zero, the
// link-time baked operand (target & 0xFFFF) is already equal
// to (segPlacedBase + offsetRef) & 0xFFFF — because the
// Loader places KIND=0x1000 segments at bank-aligned bases
// (segPlacedBase.lo16 = 0), and we baked target = textBase +
// offsetRef, so the patch is a no-op. Skipping it eliminates
// 5090% of cRELOC entries in typical builds (most data refs
// are IMM16); the GS/OS Loader walks each cRELOC site in a
// linear loop, so the per-boot reloc-application time drops
// proportionally. Programs that link with a non-bank-aligned
// text-base (e.g. bare-metal at $1000) still get the cRELOC.
if ((gTextBaseForSites & 0xFFFFu) != 0)
recordCRelocSite(patchAddr, target, /*byteCnt=*/2, /*bitShift=*/0);
break;
case R_W65816_BANK16:
// 2-byte patch: byte 0 = bank of target, byte 1 = 0 (pad).