Version
SDCC : z80 4.6.4 #17075 (MSVC) from the official 2026-10-23 snapshot. The problem also
reproduces with released SDCC 4.5.0 and 4.6.0.
sdcc -mz80 --opt-code-size --max-allocs-per-node 3000 -S sdcc-iy-live-global-reproducer.c
In the second checksum expression, generated code reads actors[index].mode and .hits through
IY after IY has been reassigned to the global checksum. The compiler therefore reads bytes 4
and 5 after checksum, not bytes 4 and 5 of the selected ActorState.
Representative invalid output from the larger runtime fixture:
ld iy,#_actors
add iy,de
; reads x, y and timer
ld iy,#_checksum
; updates checksum
push iy
pop de
ld hl,#4
add hl,de
ld e,(hl) ; reads checksum+4, not actor->mode
ld l,5(iy) ; reads checksum+5, not actor->hits
The full ColecoVision runtime oracle expects world state 1, 13 collisions, score 425 and checksum
src/z80/ralloc2.cc:IYinst_ok() returns true for + and non-pointer = before applying its own
protection against using IY as a pointer register for a direct/global operand. Restricting those
two broad allowances when an unrelated live allocation occupies IY prevents the overwrite. See
sdcc-iy-live-global-fix.patch.
An exact local build of unmodified revision 17075 reproduces checksum 1742. Rebuilding the same
source with this patch produces checksum 1478. Runtime validation also passes at allocation-node
budgets 500, 1000, 2000, 3000, 5000 and 10000. At 3000 nodes the valid cartridge occupies 2253
bytes; the invalid one occupied 2248 bytes.
This candidate patch is deliberately narrow. A budget of only 100 nodes exposes a separate result
mismatch and is not claimed fixed here.
Originally discovered while compiling the devkitSMS Gameplay State Update benchmark for ColecoVision, but the attached standalone C reproducer has no devkitSMS dependency. The defect is in SDCC’s Z80 register allocator.
Hello, Daniel. More than 25 years ago, I first saw a ColecoVision at a friend, then looked into writing my own games for it, and reading your documentation. Which then got me to start improving the z80 backend of SDCC, and becoming an SDCC developer.
This bug should be fixed in [r17093]. The approach used is differnet from your patch, since adding restrictions in the register allocator tends to have a higher code quality cost vs. improvements in code generation.
Related
Commit: [r17093]