Skip to main content

cpu-vm1

KR580VM1 (КР580ВМ1) for z88dk: 8080-compatible plus RS/MB prefixes, H1L1, dual 64K banks, OF/MF flags, and ten extra ops. Use when writing or reviewing vm1 library asm, +test -clib=vm1 / +z80 -clib=vm1, -mvm1, pop-af bank traps, DSUB/LHLX/SHLX/DCMP, or /cpu-vm1. Not 8085 — LDSI/RDEL/ARHL encodings differ.

Source facts

Repository
z88dk/z88dk
Last source activity
October 13, 2026 at 04:37
Detected SKILL.md language
English
Stars
1,152
Forks
212

Install options

The review-first prompt is selected by default. You can switch to a direct command or download a local copy.

Review the source files

Read SKILL.md and any companion files shown by SkillsMP before deciding whether to install.

Showing SKILL.md

SKILL.md
Source instructions · Read-only preview
name
cpu-vm1
description
KR580VM1 (КР580ВМ1) for z88dk: 8080-compatible plus RS/MB prefixes, H1L1, dual 64K banks, OF/MF flags, and ten extra ops. Use when writing or reviewing vm1 library asm, +test -clib=vm1 / +z80 -clib=vm1, -mvm1, pop-af bank traps, DSUB/LHLX/SHLX/DCMP, or /cpu-vm1. Not 8085 — LDSI/RDEL/ARHL encodings differ.
# CPU — KR580VM1 Soviet 8080 extension of the KR580VM80A. **Binary compatible with the 8080.** Every 8080 program runs unchanged. It is **not** an 8085: the two chips reuse the same undocumented opcode slots for different instructions. z88dk writes **Zilog** mnemonics. The Russian document uses Intel-style names (DSUB, LHLX, ANX). Translate on the way in. Classic path `libsrc/l/sccz80/7-vm1/`, products `vm1_crt0.lib` / `testvm1_clib.lib` / `vm1_clib.lib`. Assemble `-mvm1`. `zcc +test -clib=vm1` or `+z80 -clib=vm1`. From **v2.5**, **`-lm`** links `math32_vm1.lib` (`asm/vm1/`), the same selection as **`--math32`**. Before v2.5 the documented default was **`--math-mbf32`** (`mbf32_vm1.lib`); that alias is still the Microsoft 32-bit opt-in. No math16 vm1 product — those 8085 cores use `ld de,sp+*` and `rl de`, which are **prefixes** on this CPU. **This skill is complete for vm1 work.** Load `cpu-8080` only when the binary must also run on a plain 8080. Do not load `cpu-8085` for this CPU. ## Conventions (always follow) 1. **Never `pop af` unless the word is a previous `push af`.** Unknown bits in F bit 3 load MF and **swap the data RAM bank**. Matched `push af` … `pop af` is safe. Detail below. 2. **Mnemonics are Zilog** (`ld a,b`, `sub hl,bc`, `andl (hl)`). Do not emit Intel `MOV` / `DSUB` / `LHLX` in tree sources (fixtures may list Intel for compat). 3. **Opcode bytes and timings are 8080 + VM1 extras**, not Z80 or 8085. 4. Immediate forms: `*` = d8, `**` = d16/a16. Placeholders only. 5. Conditional cycle counts: the Russian tables list **taken only**. z88dk uses 8080 not-taken (`jp` always 10; `call` 17/11; `ret` 11/5). 6. Each prefix byte adds **4T**. Base timings match the 8080. 7. One major function per file under `libsrc`. Human page of record: `doc/kr580vm1.md`. When that page and an external Russian source disagree, **the local page wins** (it already folds the errata). Assembler last resort: `cpu_test_vm1_ok.asm`. ## Sources | Topic | Source | |-------|--------| | ISA, prefixes, flags, timings, errata | **`doc/kr580vm1.md`** (primary) | | Secondary Russian | [emuverse КР580ВМ1/Система_команд](https://emuverse.ru/wiki/КР580ВМ1/Система_команд) | | Raw radio86 wiki (JS shell — fetch storage) | `https://storage.googleapis.com/google-code-archive/v2/code.google.com/radio86/wiki/KP580BM1.wiki` | | z80asm source forms | `src/z80asm/dev/cpu/cpu_test_vm1_ok.asm` / `_strict_ok.asm` | | sccz80 overrides | `libsrc/l/sccz80/7-vm1/` | | Emulator | `src/ticks/vm1_inst.c`, `-mvm1` in `ticks.c` | 8080-portable sequences, stack frames, and `jr`→`jp` synthetics: **`cpu-8080`**. This skill is the extras, the prefixes, MF, and the traps. ### Errata in the original Russian document Resolved in `doc/kr580vm1.md` against emuverse and 8085 precedent. **Use the local encodings.** | Claim in the radio86 / emuverse tables | Truth | |----------------------------------------|--------| | SHLX listed as `11001101` (`$CD`, 8080 `CALL`) | **`$D9`**, same as 8085 SHLX | | SMF0/SMF1 tables show prefix `$38` (RS) | Prefix is **MB `$28`**: `smf0` = `$28 $00`, `smf1` = `$28 $7F` | | JOF / cond. `jp` / cond. `call` “ELSE PC ← PC+1” | Address field is two bytes; skip both (z88dk `pc += 2` after the opcode) | | ACI listed as `$EE` (that is `xri *`) | 8080 **`$CE`** | | RAR listed as `$17` (that is `rla`) | 8080 **`$1F`** | | CMA algorithm `A ← A` | Invert: `cpl` | LHLX at `$ED` is listed correctly in the original. ## Registers 8080 set plus one extra pointer pair. No IX/IY, no `exx`, no AF′/BC′/DE′. ``` 15 ...... 8 7 ...... 0 A F B C D E H L → HL (pointer pair) H' L' → HL' (H1L1; z88dk `h'` `l'` `hl'`) 15 ............... 0 SP PC ``` H1L1 is **not** a Z80 shadow bank. There is no exchange. The **RS** prefix selects H1L1 as source, destination, or `(hl)` pointer for **one** following instruction. `ex de,hl` always uses real HL (document gives no RS form). z88dk ticks parks HL′ in the unused Z80 `h_`/`l_` for the duration of one prefixed instruction. ## Flag register (F) 8080 layout plus OF and MF in bits the 8080 left constant / copies of A: | Bit | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | |-----|---|---|---|---|---|---|---|---| | | S | Z | **OF** | AC | **MF** | P | 1 | CY | | Flag | Meaning | |------|---------| | **S** | Sign | | **Z** | Zero | | **OF** | Signed overflow (carry into bit 7 xor carry out of bit 7). **Not** 8085 K | | **AC** | Half-carry | | **MF** | Data bank: 0 = main, 1 = additional | | **P** | Parity (even). **Always parity**, not Z80 P/V | | **1** | Unused; permanently 1 | | **CY** | Carry | OF occupies the same bit as 8085 **K**. They are not the same flag. Do not use `jp k` / `jp nk` — those encodings are DCMP D / JOF on this CPU. Condition codes: `nz` `z` `nc` `c` `po` `pe` `p` `m`, plus **`of`** (`jp of,**`). ### Flag rules agents must not get wrong Base 8080 ops keep 8080 SZAPC behaviour, plus OF as below. Bit 1 stays 1. MF only changes on `smf0` / `smf1` / `pop af`. | Group | S Z OF AC P CY | Notes | |-------|----------------|-------| | 8-bit `add`/`adc`/`sub`/`sbc`/`inc`/`dec`/`cp` (and immediates) | ● ● ● ● ● ● (`inc`/`dec`: CY unchanged) | OF is 8-bit signed overflow | | 8-bit `and`/`xor`/`or` (and immediates) | ● ● — 0 ● 0 | **Leave OF.** CY and AC cleared | | `rlca`/`rrca`/`rla`/`rra` | — — ? — — ● | **C only** on 8080. Russian tables mark OF written; do not `jp of` after a rotate | | `add hl,rp` (DAD) | — — — — — ● | **CY only.** CS form (`adc hl,rp`) same mask | | `sub hl,bc/de` (DSUB) | ● ● — — — ● | **No OF.** S from bit 15. CS form consumes CY | | `cp hl,bc/de` (DCMP) | ● ● — — — ● | Result discarded. **No OF.** CS form consumes CY | | `andl`/`orl`/`xorl` (ANX/ORX/XRX) | ● ● — — ● 0 | CY cleared. OF and AC unchanged | | `inc`/`dec` **16-bit** | — — ? — — — | Russian tables mark OF. **Z is not written.** Never `dec bc; jp nz`. Never `inc bc; jp of` as a count test | | `daa` | 8080 SZAPC | Russian table (Z+CY only) is incomplete | | `cpl` | — — — — — — | No flags | | `scf`/`ccf` | — — — — — ● | | | `smf0`/`smf1` | — — — — — — | **MF only** | | `pop af` | all | Restores S Z OF AC **MF** P CY | DSUB/DCMP **do not** set OF. Signed 16-bit order cannot use `jp of` the way 8085 uses `jp k` after `sub hl,bc`. ## Memory and MF Two 64K banks. **Instructions fetch only from the main bank.** Data uses the bank named by MF. The MB prefix flips the bank for the **next** instruction only. `smf0` / `smf1` set MF until changed. The document does not except the stack. z88dk therefore lets `push` / `pop` / `call` / `ret` follow MF. That is an inference. Changing MF between a `call` and its `ret` will not work. ## Hard rule: do not `pop af` of unknown contents `pop af` loads **MF from bit 3** of the flags byte. MF selects the data RAM bank for **every** later data access (loads, stores, pushes, pops, `call`, `ret`). If that bit is not the MF you pushed, the CPU **switches bank**. | Allowed | Forbidden (unknown F, so unknown MF) | |---------|--------------------------------------| | `push af` … later `pop af` of **that same word** (MF round-trips) | `pop af` to **discard** a stack slot | | | `push bc` / `push de` / `push hl` then `pop af` as a 16-bit **move** | | | `pop af` of a **return address** or any other non-PSW word | The test is: **do you know this word is a PSW you pushed?** If not, do not pop it into AF. Bit 3 of arbitrary data is effectively random, so the bank swap is data-dependent and easy to miss in testing. `sccz80` and `80cc` already suppress the unsafe idiom (`CPU_POP_AF_IS_SAFE()`). Hand-written asm must not invent it. Discard or move through BC/DE/HL. A `pop af` of a **return address** is also broken on 8080/8085/gbz80 (hardwired flag bits). On VM1 it is worse: it can switch banks as well. Keep return addresses in BC/DE/HL. ## Prefixes Up to two prefix bytes before any opcode. Opcode byte must not be `$28` or `$38`. A run of prefixes does not cancel. Interrupts are held off between a prefix and its instruction (same idea as Rabbit `altd`). ### RS — `$38`, 4T Substitute HL′ for HL in the next instruction. ```asm ld a,(hl') ; 38 7E ld a,h' ld hl',nn push hl' add hl',bc ``` ### MB / CS — `$28`, 4T **MB** in front of a memory op: access the **other** data bank. ```asm mb ld a,(hl) ; 28 7E A ← other bank at HL ``` **CS** in front of `add hl,rp` / `sub hl,rp` / `cp hl,rp`: consume carry. z88dk folds CS into the mnemonic (no separate `cs` word in the source): | Bare | Prefixed | Meaning | |------|----------|---------| | `add hl,bc` (`09`) | `adc hl,bc` (`28 09`) | HL ← HL + BC + CY | | `sub hl,bc` (`08`) | `sbc hl,bc` (`28 08`) | HL ← HL − BC − CY | | `cp hl,bc` (`CB`) | `cpc hl,bc` (`28 CB`) | flags from HL − BC − CY | `cpc` is a **z88dk name**; the document has no Zilog spelling for compare-with-borrow. Both prefixes: the human page shows **MB then RS** (`28 38 08` = `sbc hl',bc`). z80asm currently emits **RS then MB** for the CS+HL′ forms (`38 28 08`). Both orders are equivalent: one prefix selects the pair, the other consumes carry. ## Added instructions Timings are **bare**; add 4T per prefix. | Op | Zilog (write this) | Doc | T | Effect | |----|--------------------|-----|--:|--------| | `08` | `sub hl,bc` | DSUB B | 10 | HL ← HL − BC | | `18` | `sub hl,de` | DSUB D | 10 | HL ← HL − DE | | `10` | `andl (hl)` | ANX | 10 | (HL) ← (HL) & A | | `20` | `orl (hl)` | ORX | 10 | (HL) ← (HL) \| A | | `30` | `xorl (hl)` | XRX | 10 | (HL) ← (HL) ^ A | | `CB` | `cp hl,bc` | DCMP B | 10 | flags from HL − BC | | `DD` | `cp hl,de` | DCMP D | 10 | flags from HL − DE |
View on GitHub
This SKILL.md is very large, so SkillsMP previews the first section here. View on GitHub