Compiler — zsdcc
SkillDev toolszsdcc (SDCC-based) compiler path in z88dk: -clib=sdcc_ix / sdcc_iy, newlib integration, and regenerating src/zsdcc/sdcc-z88dk.patch for SDCC upgrades (ABI 0, version string, ChangeLog revision, peep specials, c1-mode adb). Use when building with SDCC, debugging sdcc calling conventions, or upgrading the zsdcc pin / patch / tarball.
Available today. Use it from your connected AI after setup.
No other account needed.
Connect ahel once, and every AI you use reads what you have installed.
Then ask your AI: use the Compiler — zsdcc skill
What this skill tells your AI
The instructions your AI receives, as published by z88dk/z88dk in .agents/skills/compiler-zsdcc/SKILL.md and read by ahel’s review.
Binary: z88dk-zsdcc (via zcc -compiler=sdcc or target -clib=sdcc_*).
Sources / patches: src/zsdcc/. Pin: root Makefile SDCC_VERSION.
Agent facts
| Topic | Detail |
|---|---|
| Common clibs | sdcc_ix, sdcc_iy (IY reserved in many newlib configs) |
| World | Prefer newlib (-clib=new / sdcc clibs), not classic 8085 |
| Calling | Do not mix sccz80 and sdcc objects carelessly |
| Opts | SDCC-specific peephole rules under lib/sdcc/ |
| Preprocessor | ucpp (not stock sdcpp) |
Version (this tree)
| Item | Value |
|---|---|
| SDCC baseline | 4.6.0 r16639 (final release tag; changelog.txt v2.5) |
| Current patch | src/zsdcc/sdcc-z88dk.patch |
| Snapshot name | src/zsdcc/sdcc-16639-z88dk.patch |
| Makefile pin | SDCC_VERSION=16639 |
| CI / HTTP tarball | zsdcc_r16639_src.tar.gz (nightly http://nightly.z88dk.org/zsdcc/) |
Historical snapshots stay under src/zsdcc/sdcc-*-z88dk.patch for rebuild of older pins. Human notes: src/zsdcc/readme.md.
Select via zcc
| Flag | Meaning |
|---|---|
-clib=sdcc_iy | Preferred on many targets; adds --reserve-regs-iy |
-clib=sdcc_ix | SDCC with IX frame conventions as defined by cfg |
zcc +cpm -clib=sdcc_iy -vn hi.c -o hi
Limits
- Intended for Z80-class work in this toolchain.
- For 8080 / 8085 / gbz80 classic products, prefer sccz80 (or 80cc), not zsdcc.
- Library directory is often still
lib/clibs/sdcc_ixeven forsdcc_iy. Readlib/config/<target>.cfg. - Vanilla SDCC (
sdccfrom svn,__sdcccall(1), banner#16608) is a different toolchain. Bench recipes:methodology-sdcc-vanilla. Do not write vanilla numbers into zsdcc RESULT blocks.
Generating / upgrading the zsdcc patch
Use this when SDCC releases (or z88dk moves pin). Product docs: issue #2974 / PR class “prepare patch and tarball”.
Layout
| Path | Role |
|---|---|
Makefile SDCC_VERSION | svn revision checked out or tarball name |
src/zsdcc/sdcc-z88dk.patch | Default patch applied by make (non-HTTP build) |
src/zsdcc/sdcc-<rev>-z88dk.patch | Frozen copy for that rev (keep previous revs) |
src/sdcc-build/ | Working tree (gitignored); svn checkout or tarball extract |
zsdcc_r<rev>_src.tar.gz | Pre-patched sources for CI (BUILD_SDCC_HTTP=1); gitignored unless force-added for upload |
Build without HTTP: svn checkout -r $(SDCC_VERSION) …/trunk/sdcc then patch -p0 < sdcc-z88dk.patch.
HTTP: extract tarball (already patched).
Required patch components (keep all of these)
These are z88dk-specific; they do not belong upstream as a unit.
1. ABI revision = 0 (src/z80/main.c)
Every Z80-family port descriptor must use:
0, /* ABI revision */ /* was 1 */
Stock SDCC defaults to ABI 1 (__sdcccall(1)). z88dk libraries and classic/newlib bridges expect ABI 0 (traditional stack / __z88dk_callee / __z88dk_fastcall world with __sdcccall(0)).
Do not “fix” PORT stack vectors when regenerating — only the ABI field is intentional. Context lines around { -1, 0, 0, 4, 0, 3, 0 } etc. may move between SDCC revs; they are not z88dk edits.
Optional parity with older patches: first vector may keep // Stack options comment.
2. User-facing version string (src/SDCCmain.c printVersionInfo)
Replace stock “SDCC : port/port …” banner with z88dk identity, for example:
ZSDCC IS A MODIFICATION OF SDCC FOR Z88DK
Build: <SDCC_VERSION_STR> #<build> (env) <date>
sdcc website: https://sourceforge.net/projects/sdcc/
patch details: https://github.com/z88dk/z88dk/blob/master/src/zsdcc/sdcc-z88dk.patch
#<build> comes from SDCC’s build-number machinery (see ChangeLog below).
3. ChangeLog $Revision$ — fix the reported build number
Important: SDCC’s svn tree does not update ChangeLog’s $Revision: … $ keyword on every commit. The tag/checkout revision (e.g. 16639) often disagrees with the string at the end of ChangeLog (e.g. 16608).
version.awk / getBuildNumber() read that keyword → z88dk-zsdcc --version shows the wrong #NNNN unless the patch forces it.
Always add a ChangeLog hunk that sets:
$Revision: <SDCC_VERSION> $
to the same revision as Makefile SDCC_VERSION (the pin you actually build).
Historical example: sdcc-14648-z88dk.patch header. If svn diff ignores the keyword edit, hand-write the unified hunk (keyword expansion can hide the change from svn status).
4. z88dk intrinsic / special call awareness (src/z80/peep.c)
Stock peep does not know z88dk helper register contracts. The patch inserts special_funcs[][3]:
| Column | Meaning |
|---|---|
[0] | Exact asm call text, e.g. "call\t____sdcc_ll_…" |
[1] | Input regs used as parms (dehl, bcdehl, …) |
[2] | Regs preserved across the call |
Hooks in z80MightBeParmInCallFromCurrentFunction / destroy/preserve helpers so peep does not break around:
____sdcc_ll_*— long long load/store/shift/add/sub helpers____sdcc_4_*/____sdcc_2_*— 32/16-bit mem helpers____sdcc_ldi*,____sdcc_outi*— block move / I/O____sdcc_cpu_push_di/____sdcc_cpu_pop_ei____sdcc_lib_setmem_hl,____sdcc_load_*,____sdcc_store_*
When regenerating: re-apply the whole table; only extend it when new z88dk runtime helpers appear. Upstream may rename ISINST → lineIsInst — attach hooks to the current API, do not resurrect old macro names blindly.
5. Other required hunks (carry forward)
| File | Change |
|---|---|
src/SDCCasm.c | Temp labels l%N_%05d$; extern → .globl |
src/SDCCglue.c | Emit/track externs; skip !ds for pure externs |
src/SDCCopt.c | Builtin memcpy name _memcpy (not ___memcpy) — both call sites |
src/z80/main.c | legacyBanking: port->stack.banked_overhead = 0 in _finaliseOptions |
src/SDCCmain.c | c1-mode adb: if (options.debug && (fullSrcFileName || options.c1mode)) so --c1mode + debug still writes .adb |
6. Optional / historical
| Item | Note |
|---|---|
sdas/linksrc/aslink.h elf(int i) | Fedora / GCC C23 fix (#2717). Already fixed in SDCC 4.6.0 (void elf(int i)). Re-check on new revs; only re-add if upstream regresses. Prefer this tiny prototype fix over forcing -std=c17 on the whole build. |
Procedure (new pin)
# 1. Pin
# Edit Makefile SDCC_VERSION=<rev> # e.g. 16639
# 2. Clean tree
rm -rf src/sdcc-build
svn checkout -r <rev> https://svn.code.sf.net/p/sdcc/code/trunk/sdcc -q src/sdcc-build
# 3. Apply previous patch (may need fuzz/offsets)
patch -d src/sdcc-build -p0 < src/zsdcc/sdcc-z88dk.patch
# Fix rejects; ensure every component above is present.
# 4. Force ChangeLog revision string to <rev>
# Edit last $Revision: … $ line → $Revision: <rev> $
# 5. Regenerate unified patch from clean base
cd src/sdcc-build
svn revert -R . # if regenerating from edits; or diff working tree vs pristine
# Prefer: start from pristine checkout, re-apply all edits, then:
svn diff src/SDCCasm.c src/SDCCglue.c src/SDCCmain.c src/SDCCopt.c \
src/z80/main.c src/z80/peep.c > /tmp/zsdcc-body.patch
# Hand-prepend ChangeLog hunk if svn omits keyword-only ChangeLog.
# Install:
cp /tmp/zsdcc-full.patch ../../src/zsdcc/sdcc-z88dk.patch
cp /tmp/zsdcc-full.patch ../../src/zsdcc/sdcc-<rev>-z88dk.patch
# 6. Round-trip
svn revert -R .
patch -p0 --dry-run < ../../src/zsdcc/sdcc-z88dk.patch # must be clean
patch -p0 < ../../src/zsdcc/sdcc-z88dk.patch
# 7. Tarball for nightly / CI (from z88dk root; no .o/.a)
cd ../..
tar --exclude=.svn --exclude='*.o' --exclude='*.a' \
-czf zsdcc_r<rev>_src.tar.gz src/sdcc-build
# Upload to nightly server; force-add only if packaging in git: git add -f zsdcc_r<rev>_src.tar.gz
# 8. Smoke
# configure (same flags as Makefile BUILD_SDCC), make -j2
# ./src/sdcc-build/src/sdcc --version # expect #=<rev>
# cp to bin/z88dk-zsdcc
Checklist before calling the upgrade done
-
SDCC_VERSION== snapshot filename rev == ChangeLog$Revision$==--version#NNNN - All Z80-family ports: ABI field 0
-
printVersionInfoz88dk banner + patch URL -
special_funcstable present; peep hooks compile - legacyBanking overhead fix present
- c1-mode adb condition present
- SDCCasm / glue / opt memcpy hunks present
-
patch -p0clean on pristine checkout - Tarball extracts to
src/sdcc-build/and configures -
changelog.txt+src/zsdcc/readme.mdversion lines updated
Pitfalls
- Diff of old patch vs new patch looks like PORT vectors “changed” — usually context only; only ABI
1→0is required. - Skipping ChangeLog → wrong
#NNNNin CI reports and support mail. - Tarball full of
.oafter a local build → runmake distclean/ delete objects before packing. - Dropping legacyBanking or peep table when “regenerating from RC” — re-diff against last good
sdcc-*-z88dk.patchnet adds. - Untracked local
.agents/can blockgit merge master(master owns.agents/). Move or remove incomplete local trees first.
Related
src/zsdcc/readme.md, rootMakefile(BUILD_SDCC,BUILD_SDCC_HTTP)tool/zcc,library/newlib,lib/sdcc/- Wiki:
wiki/tools/Tool---zsdcc.md(keep baseline in sync) library-newlib,tool-zcc, wikilearning/Compilers.md
Signals
- GitHub stars
- 1k
- Forks
- 206
- Last commit
- Sep 2026
Advanced
- Catalog kind
- skill
- Gateway key
compiler-zsdcc- Source
- github.com/z88dk/z88dk