From e79368a04ae4bd3a128c023660115e67409b0331 Mon Sep 17 00:00:00 2001 From: David Montero Date: Wed, 3 Jun 2026 20:11:01 +0200 Subject: [PATCH] fix(c-compile): drop --code-loc 0x100 that overwrote SDCC's crt0 init (Z80) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit SDCC's z80 crt0 puts the reset vector at 0x0000 (jp init) and the init stub (set SP, call _main) at an absolute .org 0x100. Passing `--code-loc 0x100` relocated the _CODE segment on top of that init stub, so on reset the CPU jumped into __clock/_exit (rst 0x08 then ret with a garbage stack) and derailed into NOP land before ever reaching main — every Z80 C program ran but drove nothing (z80-led-chaser-c compiled yet the LEDs never moved). Verified via a standalone chip-WASM harness: with the flag the chaser does 0 LED writes; without it, it walks the bit (8 writes). Pairs with the z80-cpu RAM map now covering 0x8000-0xFFFF so the crt0's SP=0 stack is real RAM. Co-Authored-By: Claude Opus 4.8 --- backend/app/services/c_compile.py | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/backend/app/services/c_compile.py b/backend/app/services/c_compile.py index 6bee4d27..f3adc347 100644 --- a/backend/app/services/c_compile.py +++ b/backend/app/services/c_compile.py @@ -146,12 +146,17 @@ async def compile_c(source: str, target: CTarget) -> dict: c_path = tmp / "program.c" c_path.write_text(source, encoding="utf-8") - # Let SDCC link its default crt0 at 0x0000 — it places a small init - # stub there which sets SP and jumps to _main(). User code lives - # right after the stub (typically <0x80 bytes in). + # Do NOT pass --code-loc. SDCC's z80 crt0 hard-codes the reset vector + # at 0x0000 (`jp init`) and its init stub at `.org 0x100` (sets SP, + # calls _main). Forcing `--code-loc 0x100` placed the relocatable + # _CODE segment ON TOP of that absolute init stub, so reset jumped + # straight into __clock/_exit (rst 0x08 → ret with a garbage stack) + # and every Z80 C program derailed before reaching main — the LEDs + # never moved. Letting SDCC place _CODE after the crt0 header keeps + # the init stub intact. --data-loc 0x8000 matches the z80-cpu chip's + # RAM window (which spans 0x8000-0xFFFF so the crt0's SP=0 stack works). cmd = [ sdcc, flag, - "--code-loc", "0x0100", "--data-loc", "0x8000", "-o", str(tmp / "program.ihx"), str(c_path),