A modern PL/M-80 compiler targeting Intel 8080 and Zilog Z80 assembly language.
PL/M-80 was the primary systems programming language for CP/M and other
8080/Z80 operating systems. This compiler can rebuild original CP/M utilities
from their PL/M source code.
Repository:
https://github.com/avwohl/uplm80PyPI:
https://pypi.org/project/uplm80/License: GPL-3.0-or-later
FEATURES
- Full PL/M-80 language support
- Targets both 8080 and Z80 instruction sets
- Multiple optimization passes (peephole, post-assembly tail merging)
- Generates relocatable object files compatible with standard CP/M linkers
- Produces code competitive with the original Digital Research compiler
CODE QUALITY
Compiled output is comparable to the original Digital Research PL/M-80 compiler:
Program DR PL/M-80 uplm80 Difference
PIP.COM 7424 bytes 7127 bytes -4.0%
INSTALLATION
Install from PyPI:
pip install uplm80
Or install from source:
git clone
https://github.com/avwohl/uplm80.git cd uplm80
pip install -e .
USAGE
Compile PL/M-80 to Assembly:
uplm80 input.plm -o output.mac
Or run as a module:
python -m uplm80.compiler input.plm -o output.mac
Options:
-t 8080 or -t z80 Target CPU (default: Z80)
-o output.mac Output file name
Post-Assembly Optimization (Optional):
python -m uplm80.postopt output.mac -o output_opt.mac
Performs multi-pass tail merging and skip trick optimizations.
Assemble and Link:
Use your preferred 8080/Z80 assembler and linker. Example with um80/ul80:
um80 output.mac # Assemble to .rel
ul80 -o
program.com output.rel runtime.rel # Link to CP/M .com
LANGUAGE REFERENCE
PL/M-80 is a typed systems programming language with:
- Data types: BYTE (8-bit), ADDRESS (16-bit)
- Variables: Scalars, arrays, structures, BASED variables (pointers)
- Control flow: DO/END, DO WHILE, DO CASE, IF/THEN/ELSE
- Procedures: With parameters, local variables, recursion
- Built-in functions: HIGH, LOW, DOUBLE, SHL, SHR, ROL, ROR, etc.
- I/O: INPUT, OUTPUT for port access
Example:
hello: DO;
DECLARE message DATA ('Hello, World!$');
DECLARE i BYTE;
print: PROCEDURE(addr) PUBLIC;
DECLARE addr ADDRESS;
/* CP/M BDOS print string */
CALL mon1(9, addr);
END print;
CALL print(.message);
END hello;
RUNTIME LIBRARY
The compiler generates calls to these runtime routines (provide in a
separate .rel file):
Routine Description
??MUL 16-bit unsigned multiply
??DIV 16-bit unsigned divide
??MOD 16-bit unsigned modulo
??SHL 16-bit shift left
??SHR 16-bit logical shift right
??SHRS 16-bit arithmetic shift right
??MOVE Block memory move
CP/M PROGRAMS
For CP/M programs, provide stubs for:
- MON1, MON2, MON3 - BDOS calls
- BOOT - Warm boot
- BDISK, MAXB, FCB, BUFF, IOBYTE - System variables
PROJECT STRUCTURE
uplm80/
compiler.py Main compiler driver
lexer.py Tokenizer
parser.py PL/M-80 parser
ast_nodes.py AST definitions
codegen.py Code generator
peephole.py Peephole optimizer
postopt.py Post-assembly optimizer
symbols.py Symbol table
LICENSE
This project is licensed under the GNU General Public License v3.0 or later.
See the LICENSE file for details.
CONTRIBUTING
Contributions are welcome! Please feel free to submit issues and pull requests.
ACKNOWLEDGMENTS
- Intel for creating PL/M-80
- Digital Research for creating CP/M
- The CP/M source code preservation efforts that made the original PL/M
sources available