A modern development toolchain for the MEGA65 (45GS02) home computer. It consists of:
- cc45 — C compiler (C source to assembly or
.o45relocatable objects) - ca45 — 45GS02 assembler (assembly to binary or
.o45relocatable objects) - ln45 — Linker (links
.o45objects and.libarchives into flat binaries or PRG executables) - ar45 — Archiver (creates
.libstatic library archives from.o45objects) - nm45 — Symbol lister for
.o45/.o65object files - objdump45 — Object file inspector and 45GS02 disassembler
- cp45 — C preprocessor (standalone)
The goal of this suite is to provide a C-based development environment that leverages the advanced features of the MEGA65, such as its 32-bit registers (Q-mode), 28-bit flat memory addressing, and stack-relative addressing. Unlike traditional 6502 compilers, this toolchain is designed from the ground up to support modern calling conventions and procedural abstractions directly at the assembly level.
The compilation process follows a multi-pass pipeline:
- cc45 (Source to Assembly): Translates C source code into high-level 45GS02 assembly. It performs lexical analysis, builds an Abstract Syntax Tree (AST), and generates assembly code using an optimized procedure system.
- ca45 (Assembly to Binary): Processes the assembly output, resolves symbols, manages stack offsets for procedures, and emits the final machine code binary.
- Procedural Abstraction: Function calls are treated as first-class citizens with named parameters and automated stack cleanup.
- Hierarchical Scoping: Supports nested local scopes for labels and variables within procedures and
{}blocks, preventing namespace pollution and allowing safe label reuse. - Optimizations: Includes advanced compiler optimizations such as:
-
Strength Reduction: Converts expensive operations (e.g., multiplication by a power of 2) into faster equivalents (e.g., bit shifts).
-
Constant Propagation: Substitutes variables with known constant values into expressions at compile time. The optimizer is branch-aware, performing constant state merging across
if/elsepaths to ensure safe invalidation on reassignments. -
ZP-Safe Standard Library: All standard library functions are designed to be disjoint from the compiler's temporary register pool ($02-$0A). Functions utilize the 45GS02 hardware stack and the Z-scratch restoration pattern (
plz/stz) to preserve both zero page integrity and 32-bit return values (AXYZ). -
Dead Variable Elimination: Removes stack allocation and initialization for local variables that are initialized with constants and not subsequently used in the function.
-
- Volatile Keyword Support: The
volatilekeyword is fully supported, preventing unintended compiler optimizations on variables that may be changed by external factors (e.g., hardware, interrupts). - MEGA65 First: Special emphasis is placed on supporting the 45GS02 instruction set enhancements, including a high-level expression engine (
expr) that handles constant folding and register arithmetic. - Compatibility: Supports KickAssembler-style syntax (comments,
* =,.cpu) for easier porting of existing MEGA65 codebases. - Inline Assembly: Standard C
asm()and__asm__()support for direct hardware control from C source. - Compound Literals: C99 compound literals for anonymous temporary values:
(struct Point){1, 2},(int){42},(int[]){1,2,3}. - Bitfields: C-standard bitfield support in structs and unions with automatic packing into 8-bit or 16-bit storage units. Optimized codegen uses 45GS02 TRB/TSB instructions for atomic read-modify-write on ZP and absolute targets.
- 32-bit Long Type: Native
longandunsigned longsupport using the 45GS02 Q register (AXYZ). All arithmetic, comparison, shift, and bitwise operations leverage native Q instructions. - Explicit Casts & Narrowing Warnings: C-style cast expressions
(type)exprwith compile-time warnings for implicit narrowing conversions. - ZP Calling Convention: Optional zero-page parameter passing (
-fzpcall) for faster function calls. Parameters are placed in a fixed ZP region instead of the stack, eliminating TSX overhead. Includes caller-save semantics, address-of spill, and per-function metadata (.zp_uses,.zp_clobbers,.reg_clobbers) in.o45objects for interprocedural optimization. - Extensibility: The toolchain uses a visitor-based architecture in C++, making it easy to add new optimizations, language features, or hardware targets.
Compile C to assembly, then assemble to a PRG:
./bin/cc45 input.c -o output.s # Compile to assembly
./bin/ca45 output.s -o output.prg # Assemble to PRG binaryCompile C files to .o45 relocatable objects for separate compilation and linking:
./bin/cc45 -c main.c -o main.o45 # Compile to object
./bin/cc45 -c math.c -o math.o45 # Compile to object
./bin/nm45 main.o45 # Inspect symbols
./bin/objdump45 -d main.o45 # Disassemble
./bin/ln45 -prg main.o45 math.o45 -o app.prg # Link into PRG
# Or create a library and link against it:
./bin/ar45 c math.lib math.o45 # Create library
./bin/ln45 -prg main.o45 math.lib -o app.prg # Link with selective pullingAssembly files can also produce .o45 objects directly:
./bin/ca45 -c module.s -o module.o45 # Assemble to objectFor a full list of command-line options, use the -? flag:
./bin/cc45 -?
./bin/ca45 -?
./bin/nm45 -?Install the toolchain binaries, standard library, C headers, and man pages:
make install # Install to /usr/local (may need sudo)
make install_local # Install to ~/.local
make install PREFIX=/opt/mega65 # Install to a custom prefix
make uninstall # Remove installed filesThe install targets build everything (including lib) automatically. Installed layout:
| Component | Path |
|---|---|
| Binaries | $(PREFIX)/bin/ |
Libraries (c45.lib, c45_zp.lib) |
$(PREFIX)/lib/cc45/ |
| C headers | $(PREFIX)/include/cc45/ |
| Man pages | $(PREFIX)/share/man/man1/ |
After make install_local, ensure ~/.local/bin is on your PATH.
In addition to the Markdown files in the doc/ directory, you can generate and view standard Unix man pages for both tools:
make man
man ./man/cc45.1
man ./man/ca45.1Note: This requires pandoc to be installed on your system.
The suite includes a set of automated tests to verify the compiler and assembler. You can run all tests from the project root:
make testThis compiles C source files from src/test-resources/, assembles them, and execution-validates them on a 45GS02 emulator. Outputs are stored in the build/test/ directory.
Prerequisite: The emulator-based tests (make test-mmemu) require mmemu-cli to be installed and available on your PATH.
For detailed information on each tool, refer to:
- doc/cc45.md — Compiler Usage and Features
- doc/ca45.md — Assembler Syntax and Reference
- doc/nm45.md — Symbol Lister for
.o45Object Files - doc/objdump45.md — Object File Inspector and Disassembler
- doc/cp45.md — Preprocessor Features and Usage
- doc/opcodes.md — 45GS02 Instruction Reference
- doc/lib45.md —
.o45Relocatable Object Format Specification - doc/ln45.md — Linker Usage and Reference
- doc/ar45.md — Archiver Usage and Reference