Skip to content
/ uada80 Public

Ada compiler targeting Z80 processor and CP/M 2.2 operating system

License

Notifications You must be signed in to change notification settings

avwohl/uada80

Repository files navigation

uada80 - Ada Compiler for Z80/CP/M

Tests Pylint

An Ada compiler targeting the Z80 processor and CP/M 2.2 operating system, aiming for ACATS (Ada Conformity Assessment Test Suite) compliance.

Project Status

🔧 Alpha - Core compiler functionality implemented

Overview

uada80 is a compiler for the Ada programming language that generates code for the Z80 8-bit microprocessor running CP/M 2.2. The project aims to support a substantial subset of Ada 2012 and pass the ACATS conformance tests.

Target Platforms: CP/M 2.2 and MP/M II on Z80

  • CP/M 2.2: .com executables, single-threaded, programs load at 0x0100
  • MP/M II: .prl relocatable executables, preemptive multitasking via OS primitives
  • Access to BDOS for file I/O and console operations
  • Approximately 57K TPA on typical 64K system

Goals

  1. Compile Ada source code to Z80 assembly/machine code
  2. Generate CP/M .COM executables
  3. Pass ACATS test suite (or as many tests as feasible for Z80/CP/M)
  4. Generate efficient code suitable for CP/M systems
  5. Provide clear error messages and diagnostics

Inspiration

This project builds on experience from uplm80, a PL/M-80 compiler for Z80, reusing proven optimization techniques.

Features

Phase 1 (MVP) ✅

  • Project structure
  • Lexer and parser
  • Basic types: Integer, Boolean, Character
  • Procedures and functions
  • Control flow: if, case, loop, for
  • Arrays and records
  • Z80 code generation

Phase 2 (Expanded) ✅

  • Packages
  • Enumeration types
  • Access types (pointers)
  • Derived types
  • Unconstrained arrays
  • AST optimization

Phase 3 (ACATS Compliance) 🔧

  • Generics
  • Exception handling
  • Full attribute support
  • Representation clauses
  • Standard library (adapted for Z80)
  • ACATS test validation

Architecture

Ada Source → Lexer → Parser → AST → Semantic Analysis → Optimizer → Code Gen → Z80 Assembly

See docs/ARCHITECTURE.md for detailed design documentation.

Building

Requirements

  • Python 3.10 or later
  • um80_and_friends - Z80 assembler and linker (um80, ul80)
  • cpmemu - CP/M emulator for running compiled programs

Installation

# Clone the repository
git clone https://github.com/avwohl/uada80.git
cd uada80

# Create virtual environment
python3 -m venv venv
source venv/bin/activate

# Install in development mode
pip install -e ".[dev]"

# Install assembler/linker
pip install um80

Running Tests

pytest tests/ -v -o addopts=""

Usage

# Compile Ada to Z80 assembly
python -m uada80 hello.ada -o hello.asm

# Assemble and link
um80 -o hello.rel hello.asm
ul80 -o hello.com hello.rel -L runtime/ -l libada.lib

# Run on CP/M emulator
cpmemu --z80 hello.com

Example Programs

Hello World

with Ada.Text_IO;

procedure Hello is
begin
   Ada.Text_IO.Put_Line("Hello from Ada on Z80!");
end Hello;

Fibonacci

procedure Fibonacci is
   A, B, Temp : Integer;
   N : Integer := 10;
begin
   A := 0;
   B := 1;

   for I in 1 .. N loop
      Temp := A + B;
      A := B;
      B := Temp;
   end loop;
end Fibonacci;

See learn-ada-z80 for 99 example programs covering basics through tasking, generics, and applications.

Ada Tasking on MP/M II

Ada tasking (tasks, entries, rendezvous, protected types) runs on MP/M II using OS-native primitives for preemptive multitasking. On CP/M 2.2 (single-user), the runtime provides cooperative tasking stubs.

How It Works

Ada tasks become MP/M II subprocesses sharing one memory bank. The OS handles preemptive scheduling, and all inter-task communication uses BDOS queue operations:

Ada Construct MP/M II Primitive
Task creation P_CREATE (BDOS 144)
Entry call Q_WRITE (BDOS 139) - blocking send to queue
Accept statement Q_READ (BDOS 137) - blocking receive from queue
Select/else Q_CREAD (BDOS 138) - conditional (non-blocking) read
Protected object MX queue (mutual exclusion)
Delay P_DELAY (BDOS 141)
Abort P_ABORT (BDOS 157)

Building for MP/M II

# Compile Ada to assembly
python -m uada80 program.ada -o program.asm

# Assemble
um80 -o program.rel program.asm

# Link as PRL (relocatable for MP/M II)
ul80 --prl -p 0 -o program.prl program.rel -L runtime/ -l libada_mpm.lib

# Or link as COM (also works under MP/M)
ul80 -o program.com program.rel -L runtime/ -l libada_mpm.lib

Running on the MP/M II Emulator

The mpm2 emulator provides a full MP/M II environment with SSH terminal access:

# Start the emulator (up to 4 concurrent consoles)
mpm2_emu --no-auth -p 127.0.0.1:2222 -d A:disks/mpm2_system_work.img

# Connect via SSH
ssh -p 2222 user@localhost

# Upload and run
sftp -P 2222 user@localhost
put program.prl /A.0/PROGRAM.PRL

Runtime Libraries

Two runtime libraries are provided:

  • libada.lib - CP/M 2.2 runtime with cooperative tasking stubs
  • libada_mpm.lib - MP/M II runtime with OS-native preemptive tasking

Rebuild after changes:

cd runtime && make clean && make

Documentation

Compiler Documentation

CP/M Target Platform

Ada Language Specifications

  • specs/ - Ada language specifications and ACATS tests

Testing

ACATS End-to-End Execution

The ACATS 4.2 test suite is included in tests/acats/. Tests are compiled to Z80 assembly, assembled with um80, linked with ul80, and executed on cpmemu.

579 ACATS tests pass end-to-end (compile + assemble + link + execute on cpmemu):

$ pytest tests/test_acats_execution.py -o addopts=""
===== 257 failed, 579 passed, 624 skipped in 5197s =====
Result Count Description
Passed 579 Compiled, ran on cpmemu, output contains PASSED
Failed 257 Compiled and ran but produced wrong results (codegen bugs)
Skipped 624 Compile/link/timeout failures (multi-file deps, missing features)

ACATS Front-End

All 5,787 legal ACATS files pass parsing and semantic analysis:

$ pytest tests/test_acats.py -o addopts=""
======================= 5,787 passed in 248s =======================

learn-ada-z80 Programs

The learn-ada-z80 companion project has 99 example programs. 98 of 99 compile to Z80 assembly (full pipeline: parse, semantic analysis, lowering, code generation). One program fails due to a codegen bug with negative array bounds.

Execution Tests

End-to-end execution tests (compile + assemble + link + run on cpmemu) are in tests/test_execution.py:

pytest tests/test_execution.py -v -o addopts=""

Limitations

Due to the Z80's 8-bit architecture and limited resources:

  • Integer sizes limited to 8-bit and 16-bit (32-bit via library)
  • Software floating-point only (IEEE 754 double via float64.mac)
  • Reduced standard library
  • Tasking requires MP/M II (CP/M 2.2 provides stubs only)
  • Limited heap (small memory space)

Contributing

Contributions are welcome! Please:

  1. Fork the repository
  2. Create a feature branch
  3. Make your changes with tests
  4. Run the test suite
  5. Submit a pull request

License

This project is licensed under the GNU General Public License v2.0 - see LICENSE for details.

References

Related Projects

  • 80un - Unpacker for CP/M compression and archive formats (LBR, ARC, squeeze, crunch, CrLZH)
  • cpmdroid - Z80/CP/M emulator for Android with RomWBW HBIOS compatibility and VT100 terminal
  • cpmemu - CP/M 2.2 emulator with Z80/8080 CPU emulation and BDOS/BIOS translation to Unix filesystem
  • ioscpm - Z80/CP/M emulator for iOS and macOS with RomWBW HBIOS compatibility
  • learn-ada-z80 - Ada programming examples for the uada80 compiler targeting Z80/CP/M
  • mbasic - Modern MBASIC 5.21 Interpreter & Compilers
  • mbasic2025 - MBASIC 5.21 source code reconstruction - byte-for-byte match with original binary
  • mbasicc - C++ implementation of MBASIC 5.21
  • mbasicc_web - WebAssembly MBASIC 5.21
  • mpm2 - MP/M II multi-user CP/M emulator with SSH terminal access and SFTP file transfer
  • romwbw_emu - Hardware-level Z80 emulator for RomWBW with 512KB ROM + 512KB RAM banking and HBIOS support
  • scelbal - SCELBAL BASIC interpreter - 8008 to 8080 translation
  • ucow - Unix/Linux Cowgol to Z80 compiler
  • um80_and_friends - Microsoft MACRO-80 compatible toolchain for Linux: assembler, linker, librarian, disassembler
  • upeepz80 - Universal peephole optimizer for Z80 compilers
  • uplm80 - PL/M-80 compiler targeting Intel 8080 and Zilog Z80 assembly language
  • z80cpmw - Z80 CP/M emulator for Windows (RomWBW)

See Also

  • GNAT - For production Ada development, use GNAT or other mature Ada compilers

About

Ada compiler targeting Z80 processor and CP/M 2.2 operating system

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages