Highly optimizing PL/M-80 compiler targeting 8080/Z80
Project description
uplm80 - PL/M-80 Compiler
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/uplm80
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
Quick install from PyPI:
pip install uplm80 um80 upeep80
Platform-specific guides:
- Raspberry Pi: See README_RASPBERRY_PI.md
- General/Development: See INSTALL.md
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 8080or-t z80- Target CPU (default: Z80)-m cpmor-m bare- Runtime mode (default: cpm)cpm: CP/M program with stack from BDOS, returns to OS on exitbare: Bare metal program with local stack, original Intel PL/M style
-o output.mac- Output file name-O 0|1|2|3- Optimization level (default: 2)
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;
See examples/hello_cpm.plm for a complete working example.
For more on CP/M BDOS usage, see docs/BDOS_REFERENCE.md.
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 |
Runtime Modes
CP/M Mode (default: -m cpm)
For CP/M programs that run under the CP/M operating system:
- Program starts with
ORG 100H(CP/M TPA) - Stack is set from BDOS address at location 0006H:
LD HL,(6)/LD SP,HL - Entry code calls main procedure with
CALL MAIN - Returns to CP/M with
JP 0(warm boot) when main returns - Requires CP/M stubs:
MON1,MON2,MON3,BOOT - System variables:
BDISK,MAXB,FCB,BUFF,IOBYTE
Bare Metal Mode (-m bare)
For standalone programs or original Intel PL/M compatibility:
- Uses locally-defined stack (64 bytes by default)
- Entry code sets
SPto??STACKlabel (top of local stack buffer) - Compatible with original Intel PL/M-80 programs
- Program can define custom entry point via DATA declarations
- No OS return code (program may need explicit HALT or loop)
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
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file uplm80-0.2.8.tar.gz.
File metadata
- Download URL: uplm80-0.2.8.tar.gz
- Upload date:
- Size: 118.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
00da0e406deb368d8a7c03593458c5788a92f8c61ea56161f608888cbd89b93b
|
|
| MD5 |
c18b891b71dbb168656f5638f10cc11d
|
|
| BLAKE2b-256 |
5255c8053cb43ea7b7a4ec98530efedfbd66730d2e3b0835817a5c6c0432a22b
|
File details
Details for the file uplm80-0.2.8-py3-none-any.whl.
File metadata
- Download URL: uplm80-0.2.8-py3-none-any.whl
- Upload date:
- Size: 119.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
096f92d05a3e05ab83d69a8c078b1507e6be34936cb5e660ebb31afcee595dcc
|
|
| MD5 |
bb57eb38e4783be5083b02431ba29840
|
|
| BLAKE2b-256 |
371a257fb7c93aac1fdf355385a5eae32fb7f4073db5a360ae3ef84758b7100e
|