#!/usr/bin/env bash # Build the entire W65816 runtime — assemble *.s, compile *.c. # Run after editing anything under runtime/src/. set -euo pipefail PROJECT_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" LLVM_MC="$PROJECT_ROOT/tools/llvm-mos-build/bin/llvm-mc" CLANG="$PROJECT_ROOT/tools/llvm-mos-build/bin/clang" [ -x "$LLVM_MC" ] || { echo "llvm-mc not found at $LLVM_MC" >&2; exit 1; } [ -x "$CLANG" ] || { echo "clang not found at $CLANG" >&2; exit 1; } SRC="$PROJECT_ROOT/runtime/src" OUT="$PROJECT_ROOT/runtime" asm() { local s="$1" local o="$OUT/$(basename "${s%.s}").o" echo " AS $(basename "$s")" "$LLVM_MC" -arch=w65816 -filetype=obj "$s" -o "$o" } cc() { local c="$1" local o="$OUT/$(basename "${c%.c}").o" local extra=("${@:2}") echo " CC $(basename "$c")" "$CLANG" -target w65816 -O2 -ffunction-sections \ "${extra[@]}" \ -I"$PROJECT_ROOT/runtime/include" \ -c "$c" -o "$o" } asm "$SRC/crt0.s" asm "$SRC/crt0Gsos.s" asm "$SRC/libgcc.s" cc "$SRC/libc.c" cc "$SRC/strtol.c" cc "$SRC/snprintf.c" cc "$SRC/sscanf.c" cc "$SRC/qsort.c" cc "$SRC/extras.c" cc "$SRC/strtok.c" cc "$SRC/timeExt.c" -O1 # timeExt.c at -O1: -O2 generates code where strftime's directive # switch overflows the W65816's 8-bit signed stack-relative offset # range. -O1 keeps the per-function frame small enough. cc "$SRC/math.c" cc "$SRC/softFloat.c" cc "$SRC/libcxxabi.c" cc "$SRC/libcxxabiSjlj.c" asm "$SRC/iigsGsos.s" # softDouble.c builds at -O1: __muldf3's u64 live-range pressure # overflows the greedy allocator at -O2. dpack is already noinline # to reduce pressure, but dclass MUST stay inline (its pointer-arg # writes from a noinline boundary would lower to `sta (d,s),y` which # uses DBR for the bank — silently corrupted under DBR != 0, caught # by the dmul-after-bank-switch test). -O1 sidesteps this. cc "$SRC/softDouble.c" -O1 echo "runtime built: $(ls -1 "$OUT"/*.o | wc -l) objects"