{"id":34095006,"url":"https://github.com/avwohl/uplm80","last_synced_at":"2026-04-02T02:08:20.606Z","repository":{"id":329262633,"uuid":"1108105546","full_name":"avwohl/uplm80","owner":"avwohl","description":"PL/M-80 compiler targeting Zilog Z80 assembly language","archived":false,"fork":false,"pushed_at":"2026-03-16T18:32:22.000Z","size":158747,"stargazers_count":5,"open_issues_count":1,"forks_count":3,"subscribers_count":4,"default_branch":"main","last_synced_at":"2026-03-17T05:31:12.576Z","etag":null,"topics":["8080","compiler","cpm","plm","plm-80","python","retro-computing","z80"],"latest_commit_sha":null,"homepage":"https://github.com/avwohl/uplm80","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/avwohl.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-12-02T03:05:26.000Z","updated_at":"2026-03-16T18:32:27.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/avwohl/uplm80","commit_stats":null,"previous_names":["avwohl/uplm80"],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/avwohl/uplm80","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/avwohl%2Fuplm80","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/avwohl%2Fuplm80/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/avwohl%2Fuplm80/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/avwohl%2Fuplm80/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/avwohl","download_url":"https://codeload.github.com/avwohl/uplm80/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/avwohl%2Fuplm80/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31294398,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-02T01:43:37.129Z","status":"online","status_checked_at":"2026-04-02T02:00:08.535Z","response_time":89,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["8080","compiler","cpm","plm","plm-80","python","retro-computing","z80"],"created_at":"2025-12-14T15:07:12.818Z","updated_at":"2026-04-02T02:08:20.593Z","avatar_url":"https://github.com/avwohl.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# uplm80 - PL/M-80 Compiler\n\n[![PyPI version](https://badge.fury.io/py/uplm80.svg)](https://pypi.org/project/uplm80/)\n[![Tests](https://github.com/avwohl/uplm80/actions/workflows/pytest.yml/badge.svg)](https://github.com/avwohl/uplm80/actions/workflows/pytest.yml)\n[![Pylint](https://github.com/avwohl/uplm80/actions/workflows/pylint.yml/badge.svg)](https://github.com/avwohl/uplm80/actions/workflows/pylint.yml)\n[![License: GPL v3](https://img.shields.io/badge/License-GPLv3-blue.svg)](https://www.gnu.org/licenses/gpl-3.0)\n\nA modern PL/M-80 compiler targeting Zilog Z80 assembly language.\n\nPL/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.\n\n**Repository:** https://github.com/avwohl/uplm80\n\n## Features\n\n- Full PL/M-80 language support\n- Targets Z80 instruction\n- Multi-file compilation with cross-module optimization\n- Multiple optimization passes (peephole, post-assembly tail merging)\n- Generates relocatable object files compatible with standard CP/M linkers\n- Produces code competitive with the original Digital Research compiler\n\n## Code Quality\n\nCompiled output is comparable to the original Digital Research PL/M-80 compiler:\n\n| Program | DR PL/M-80 | uplm80 | Difference |\n|---------|------------|--------|------------|\n| PIP.COM | 7424 bytes | 7127 bytes | -4.0% |\n\n## Installation\n\nQuick install from PyPI:\n\n```bash\npip install uplm80 um80 upeepz80\n```\n\n**Platform-specific guides:**\n- **Raspberry Pi**: See [README_RASPBERRY_PI.md](README_RASPBERRY_PI.md)\n- **General/Development**: See [INSTALL.md](INSTALL.md)\n\nOr install from source:\n\n```bash\ngit clone https://github.com/avwohl/uplm80.git\ncd uplm80\npip install -e .\n```\n\n## Usage\n\n### Compile PL/M-80 to Assembly\n\n```bash\nuplm80 input.plm -o output.mac\n```\n\nOr run as a module:\n\n```bash\npython -m uplm80.compiler input.plm -o output.mac\n```\n\nOptions:\n- `-m cpm` or `-m bare` - Runtime mode (default: cpm)\n  - `cpm`: For new PL/M programs, maximum stack under BDOS\n  - `bare`: Original Digital Research compatible (jump to start-3)\n- `-o output.mac` - Output file name\n- `-O 0|1|2|3` - Optimization level (default: 2)\n- `-D SYMBOL` - Define conditional compilation symbol (can be repeated)\n\n### Multi-File Compilation\n\nCompile multiple source files together for optimal cross-module optimization:\n\n```bash\nuplm80 main.plm helper.plm library.plm -o output.mac\n```\n\nWhen multiple files are provided:\n- All files are parsed together before code generation\n- A unified call graph is built across all modules\n- Local variable storage (`??AUTO`) is optimally allocated based on which procedures can be active simultaneously across module boundaries\n- A single combined output file is generated\n\nThis produces better code than compiling files separately, as the compiler can share local variable storage between procedures in different modules that never call each other.\n\n### Assemble and Link\n\nUse your preferred Z80 assembler and linker. Example with um80/ul80:\n\n```bash\num80 output.mac                              # Assemble to .rel\nul80 -o program.com output.rel runtime.rel   # Link to CP/M .com\n```\n\n## Language Reference\n\nPL/M-80 is a typed systems programming language with:\n\n- **Data types**: BYTE (8-bit), ADDRESS (16-bit)\n- **Variables**: Scalars, arrays, structures, BASED variables (pointers)\n- **Control flow**: DO/END, DO WHILE, DO CASE, IF/THEN/ELSE\n- **Procedures**: With parameters, local variables, recursion\n- **Built-in functions**: HIGH, LOW, DOUBLE, SHL, SHR, ROL, ROR, etc.\n- **I/O**: INPUT, OUTPUT for port access\n\nExample:\n\n```plm\nhello: DO;\n    DECLARE message DATA ('Hello, World!$');\n    DECLARE i BYTE;\n\n    print: PROCEDURE(addr) PUBLIC;\n        DECLARE addr ADDRESS;\n        /* CP/M BDOS print string */\n        CALL mon1(9, addr);\n    END print;\n\n    CALL print(.message);\nEND hello;\n```\n\nSee [examples/hello_cpm.plm](examples/hello_cpm.plm) for a complete working example.\n\nFor more on CP/M BDOS usage, see [docs/BDOS_REFERENCE.md](docs/BDOS_REFERENCE.md).\n\n## Conditional Compilation\n\nLater versions of PL/M-80 added conditional compilation directives embedded in comments. This allows the same source to be compiled for different configurations (e.g., CP/M 2.2 vs CP/M 3, single-user vs MP/M).\n\n### Directives\n\n| Directive | Description |\n|-----------|-------------|\n| `/** $set (NAME) **/` | Define a symbol |\n| `/** $reset (NAME) **/` | Undefine a symbol |\n| `/** $cond **/` | Enable conditional compilation |\n| `/** $if NAME **/` | Include following code if NAME is defined |\n| `/** $else **/` | Else branch |\n| `/** $endif **/` | End conditional block |\n\n### Example\n\n```plm\n/** $set (CPM3) **/\n/** $cond **/\n\nDECLARE\n/** $if CPM3 **/\n    VERSION LITERALLY '30H',\n/** $else **/\n    VERSION LITERALLY '22H',\n/** $endif **/\n    MAXFILES BYTE;\n```\n\n### Command Line\n\nSymbols can also be defined from the command line:\n\n```bash\nuplm80 pip.plm -D CPM3 -D MPM -o pip.mac\n```\n\n## Runtime Library\n\nThe compiler generates calls to these runtime routines (provide in a separate .rel file):\n\n| Routine | Description |\n|---------|-------------|\n| `??MUL` | 16-bit unsigned multiply |\n| `??DIV` | 16-bit unsigned divide |\n| `??MOD` | 16-bit unsigned modulo |\n| `??SHL` | 16-bit shift left |\n| `??SHR` | 16-bit logical shift right |\n| `??SHRS` | 16-bit arithmetic shift right |\n| `??MOVE` | Block memory move |\n\n## Runtime Modes\n\n### CP/M Mode (default: `-m cpm`)\n\nFor new PL/M programs. Provides maximum stack space by using the area under BDOS:\n\n- Program starts with `ORG 100H` (CP/M TPA)\n- Stack is set from BDOS address at location 0006H: `LD HL,(6)` / `LD SP,HL`\n- Maximum available stack (all memory between program end and BDOS)\n- Entry code calls main procedure with `CALL MAIN`\n- Returns to CP/M with `JP 0` (warm boot) when main returns\n- Requires CP/M stubs: `MON1`, `MON2`, `MON3`, `BOOT`\n- System variables: `BDISK`, `MAXB`, `FCB`, `BUFF`, `IOBYTE`\n\n### Bare Metal Mode (`-m bare`)\n\nFor original Digital Research PL/M-80 compatibility. Programs begin with a jump to start-3:\n\n- Entry begins with `JP ??START` to jump over local stack buffer\n- Uses locally-defined stack (64 bytes in program image)\n- Entry code at `??START` sets `SP` to `??STACK` label, then calls `MAIN`\n- Compatible with original Digital Research programs (ED.PLM, PIP.PLM, etc.)\n- Program can define custom entry point via DATA declarations\n- No automatic OS return (program controls its own exit behavior)\n\n## Project Structure\n\n```\nuplm80/\n├── compiler.py    # Main compiler driver\n├── lexer.py       # Tokenizer\n├── parser.py      # PL/M-80 parser\n├── ast_nodes.py   # AST definitions\n├── codegen.py     # Code generator\n├── peephole.py    # Peephole optimizer\n└── symbols.py     # Symbol table\n```\n\n## License\n\nThis project is licensed under the GNU General Public License v3.0 or later - see the [LICENSE](LICENSE) file for details.\n\n## Contributing\n\nContributions are welcome! Please feel free to submit issues and pull requests.\n## Related Projects\n\n- [80un](https://github.com/avwohl/80un) - Unpacker for CP/M compression and archive formats (LBR, ARC, squeeze, crunch, CrLZH)\n- [cpmdroid](https://github.com/avwohl/cpmdroid) - Z80/CP/M emulator for Android with RomWBW HBIOS compatibility and VT100 terminal\n- [cpmemu](https://github.com/avwohl/cpmemu) - CP/M 2.2 emulator with Z80/8080 CPU emulation and BDOS/BIOS translation to Unix filesystem\n- [ioscpm](https://github.com/avwohl/ioscpm) - Z80/CP/M emulator for iOS and macOS with RomWBW HBIOS compatibility\n- [learn-ada-z80](https://github.com/avwohl/learn-ada-z80) - Ada programming examples for the uada80 compiler targeting Z80/CP/M\n- [mbasic](https://github.com/avwohl/mbasic) - Modern MBASIC 5.21 Interpreter \u0026 Compilers\n- [mbasic2025](https://github.com/avwohl/mbasic2025) - MBASIC 5.21 source code reconstruction - byte-for-byte match with original binary\n- [mbasicc](https://github.com/avwohl/mbasicc) - C++ implementation of MBASIC 5.21\n- [mbasicc_web](https://github.com/avwohl/mbasicc_web) - WebAssembly MBASIC 5.21\n- [mpm2](https://github.com/avwohl/mpm2) - MP/M II multi-user CP/M emulator with SSH terminal access and SFTP file transfer\n- [romwbw_emu](https://github.com/avwohl/romwbw_emu) - Hardware-level Z80 emulator for RomWBW with 512KB ROM + 512KB RAM banking and HBIOS support\n- [scelbal](https://github.com/avwohl/scelbal) - SCELBAL BASIC interpreter - 8008 to 8080 translation\n- [uada80](https://github.com/avwohl/uada80) - Ada compiler targeting Z80 processor and CP/M 2.2 operating system\n- [uc80](https://github.com/avwohl/uc80) - ANSI C compiler targeting Z80 processor and CP/M 2.2 operating system\n- [ucow](https://github.com/avwohl/ucow) - Unix/Linux Cowgol to Z80 compiler\n- [um80_and_friends](https://github.com/avwohl/um80_and_friends) - Microsoft MACRO-80 compatible toolchain for Linux: assembler, linker, librarian, disassembler\n- [upeepz80](https://github.com/avwohl/upeepz80) - Universal peephole optimizer for Z80 compilers\n- [z80cpmw](https://github.com/avwohl/z80cpmw) - Z80 CP/M emulator for Windows (RomWBW)\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Favwohl%2Fuplm80","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Favwohl%2Fuplm80","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Favwohl%2Fuplm80/lists"}