Projet d'émulation du Motorola 68000.
Il s'agit d'un projet plus global visant à émuler la console Sega Mega Drive / Genesis.
L'objectif est d'atteindre une précision compatible avec les jeux commerciaux.
Motorola 68000 (M68k) CPU emulator core in Zig. Keywords: Motorola 68000, M68K, Mega Drive, Genesis, Sega, emulator, CPU, Zig.
m68k/
├── src/
│ ├── m68k.zig # Structure du CPU (registres, SR, interruptions, reset, step())
│ ├── decode.zig # Décodeur principal + helpers d'adressage (EA)
│ └── decode/
│ ├── bloc0.zig # OR, SBCD, DIVU, DIVS
│ ├── bloc1.zig # NOP, TRAP, SWAP, MOVEM, EXT, Scc, JSR, JMP, RESET, STOP, RTE, RTR
│ ├── bloc2.zig # ADDQ, SUBQ, shifts/rotates immédiats
│ ├── bloc3.zig # Shifts/rotates par registre, NBCD, TAS, MOVE, LEA, PEA
│ ├── bloc6.zig # Bcc, BSR, DBcc, SUB, SUBA, SUBX
│ ├── bloc7.zig # MOVEQ, OR, AND, SUB, ADD, CMP, Scc, shifts/rotates, bit ops
│ ├── bloc8.zig # OR, SBCD, DIVU, DIVS (bloc 8 et 0 partagent des encodings)
│ ├── bloc10.zig # AND, ADD, shifts/rotates mémoire
│ ├── bloc11.zig # CMP, CMPA, CMPI, CMPM, EOR, AND
│ ├── bloc13.zig # ADD, ADDA, ADDX, AND, OR, shifts/rotates, bit ops
│ └── blocC.zig # ABCD, AND, OR, MULU, MULS, EXG
├── tests/
│ ├── cpu_test.zig # Tests unitaires opcode par opcode
│ ├── cpu_json_test.zig # Harness de tests via JSON MAME (317 500 cas)
│ └── json_opcodes/ # 127 fichiers JSON MAME (2 500 cas chacun)
└── build.zig # Build : `zig build test-cpu-{opcodes,json}`
L'émulateur est indépendant de tout système hôte : src/m68k.zig expose une structure CPU avec step(bus). Le bus est une interface générique (lecture/écriture mémoire, signaux d'interruption). Il peut être branché à n'importe quel système.
Binaire : zig build -Doptimize=ReleaseFast
Execution test MAME : zig build -Doptimize=ReleaseFast test-cpu-json --summary all
Exécution tests : zig build -Doptimize=ReleaseFast test-cpu-opcodes --summary all
Test de timing : zig build -Doptimize=ReleaseFast test-cpu-timing
Tests exécutés via zig build test-cpu-json -Doptimize=ReleaseFast — 127 fichiers JSON, 2 500 test cases par fichier, soit 317 500 séquences validant l'état complet du CPU (registres, SR, mémoire) après chaque instruction.
Ces tests proviennent de https://github.com/SingleStepTests/m68000.git.
Ils sont générés depuis MAME.
Ils sont convertis puis copiés dans tests/json_opcodes/.
git clone https://github.com/SingleStepTests/m68000.git
python ./decode
Total : 317 500 tests — 912 093 échecs d'assertions.
Note : Le tableau décompose les résultats entre adresses paires (colonne Paires) et impaires (colonne Impaire) via l'analyse automatisée du trafic mémoire.
La détection des accès impairs couvre les lectures/écritures 16/32 bits sur adresse impaire et le PC impair après exécution.
Les opcodes marqués Complet en Paires passent 100% de leurs tests sur adresses paires ; les échecs résiduels sont soit des bugs réels sur adresses paires (score < 100%), soit des cas d'adresse impaire (colonne Impaire).
Les instructions de saut (JMP, JSR, BSR) ne déclenchent pas d'accès mémoire à la cible impaire dans notre CPU (le PC est aligné post-exécution pardecode.zig), donc tous leurs tests sont classés Paires.
51 opcodes testés via zig build test-cpu-timing -Doptimize=ReleaseFast, comparant les cycles émulés aux cycles attendus (M68000PM).
51/51 ✅ — 0 échec
| Catégorie | Instructions | Résultat |
|---|---|---|
| Instructions registre | ADD, SUB, CMP, MOVE, NEG, NOT, CLR, TST, EXT, SWAP, NOP, MOVEQ, MOVEA | ✅ |
| Instructions de contrôle | RTS, RTE, RTR, STOP, TRAP, TRAPV, ILLEGAL, LINK, UNLK | ✅ |
| Instructions mémoire | LEA, PEA, JMP, JSR | ✅ |
| Flags et SR | ANDI/ORI/EORI CCR/SR, MOVE SR | ✅ |
| Arithmétique complexe | NBCD, TAS, MULU, DIVU, DIVS, CHK | ✅ |
| ADDX/SUBX registre | ADDX, SUBX | ✅ |
- Registres D0–D7, A0–A7, PC, SR, USP/SSP
- Mode Superviseur / Utilisateur avec bascule via
sr.set sauvegarde USP/SSP - Registre d'état (SR) : champs T, S, I2–I0, X, N, Z, V, C avec getters/setters
- Reset : lit SSP (0x000000) et PC (0x000004), SR = 0x2700
- Interruptions :
checkInterrupt,dispatchInterrupt, sauvegarde PC+SR, mise à jour IPL, appel vecteur(24+level)*4 - Exceptions : fonction
exceptionempilant PC+SR, passage superviseur, lecture vecteur - STOP / HALT : retourne 4 cycles si le CPU est arrêté
- Vérification alignement PC : force alignement mot si PC impair
- Décodeur complet : 12 blocs d'opcodes couvrant tout le jeu d'instructions 68000
- Modes d'adressage : Dn, An, (An), (An)+, -(An), (d16,An), (d8,An,Xn), absolute short/long, (d16,PC), (d8,PC,Xn), immédiat
- Helpers arithmétiques/mémoire :
addSigned,signExtend*,isNegative,readMem/writeMem,mergeValue,updateNZ