Skip to content
OddByteForFunPublic

About

Motorola 68000 (M68k) CPU emulator core in Zig 0.16 — full instruction set, MAME single-step tests (317,500 cases), targeting Sega Mega Drive / Genesis accuracy. Émulateur du Motorola 68000.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

8 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Émulateur CPU Motorola 68000 en Zig

Zig Version

Description

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.

Composition du projet

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.

Compilation

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

Résultats des tests JSON MAME

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
Opcode Tests Réussite Échecs Taux Paires Impaire
ABCD 2500 2500 0 Complet Complet —
ADD.b 2500 2500 0 Complet Complet Complet
ADD.l 2500 2171 5282 86.8% Complet 0.0%
ADD.w 2500 2162 5363 86.5% Complet 0.0%
ADDA.l 2500 2500 0 Complet Complet Complet
ADDA.w 2500 2500 0 Complet Complet Complet
ADDX.b 2500 2236 783 89.4% 89.4% —
ADDX.l 2500 1671 14464 66.8% Complet 0.0%
ADDX.w 2500 1683 13515 67.3% Complet 0.0%
AND.b 2500 2500 0 Complet Complet Complet
AND.l 2500 1500 16464 60.0% Complet 0.0%
AND.w 2500 1431 17411 57.2% Complet 0.0%
ANDItoCCR 2500 2500 0 Complet Complet Complet
ANDItoSR 2500 1293 9507 51.7% 51.7% —
ASL.b 2500 2491 9 99.6% 99.6% —
ASL.l 2500 2487 13 99.5% 99.5% —
ASL.w 2500 1908 5529 76.3% 89.1% 0.0%
ASR.b 2500 2488 12 99.5% 99.5% —
ASR.l 2500 2491 9 99.6% 99.6% —
ASR.w 2500 1934 5526 77.4% 90.1% 0.0%
Bcc 2500 1824 9824 73.0% 73.0% —
BCHG 2500 2500 0 Complet Complet Complet
BCLR 2500 2500 0 Complet Complet Complet
BSET 2500 2500 0 Complet Complet Complet
BSR 2500 1229 18631 49.2% 49.2% —
BTST 2500 2442 87 97.7% 97.7% —
CHK 2500 2306 194 92.2% 92.2% 92.2%
CLR.b 2500 2500 0 Complet Complet Complet
CLR.l 2500 1529 15537 61.2% Complet 0.0%
CLR.w 2500 1481 16147 59.2% Complet 0.0%
CMP.b 2500 2224 1325 89.0% 89.0% —
CMP.l 2500 1465 14933 58.6% 85.6% 0.0%
CMP.w 2500 1462 14701 58.5% 84.9% 0.0%
CMPA.l 2500 1670 13271 66.8% Complet 0.0%
CMPA.w 2500 1664 13215 66.6% Complet 0.0%
DBcc 2500 1868 9908 74.7% 74.7% —
DIVS 2500 493 13480 19.7% 32.5% 0.0%
DIVU 2500 859 12778 34.4% 55.6% 0.0%
EOR.b 2500 2132 1090 85.3% 85.3% —
EOR.l 2500 1346 16695 53.8% 92.6% 0.0%
EOR.w 2500 1290 16583 51.6% 89.7% 0.0%
EORItoCCR 2500 2500 0 Complet Complet Complet
EORItoSR 2500 22 10905 0.9% 0.9% —
EXG 2500 834 6021 33.4% 33.4% —
EXT.l 2500 0 3805 0.0% 0.0% —
EXT.w 2500 0 12322 0.0% 0.0% —
ILLEGAL_LINEA 2500 2500 0 Complet Complet Complet
ILLEGAL_LINEF 2500 2500 0 Complet Complet Complet
JMP 2500 1272 19017 50.9% 50.9% —
JSR 2500 1341 16868 53.6% 53.6% —
LEA 2500 2500 0 Complet Complet Complet
LINK 2500 2174 335 87.0% 87.0% —
LSL.b 2500 2486 14 99.4% 99.4% —
LSL.l 2500 2493 7 99.7% 99.7% —
LSL.w 2500 1944 5132 77.8% 89.5% 0.0%
LSR.b 2500 2494 6 99.8% 99.8% —
LSR.l 2500 2488 12 99.5% 99.5% —
LSR.w 2500 1938 5588 77.5% 90.0% 0.0%
MOVE.b 2500 2500 0 Complet Complet Complet
MOVE.l 2500 1658 1792 66.3% 66.3% —
MOVE.q 2500 2500 0 Complet Complet Complet
MOVE.w 2500 1938 564 77.5% 77.5% —
MOVEA.l 2500 1655 14070 66.2% Complet 0.0%
MOVEA.w 2500 1658 13901 66.3% Complet 0.0%
MOVEfromSR 2500 1522 15278 60.9% Complet 0.0%
MOVEfromUSP 2500 0 12108 0.0% 0.0% —
MOVEM.l 2500 1150 24358 46.0% 88.2% 0.0%
MOVEM.w 2500 1161 23244 46.4% 88.1% 0.0%
MOVEP.l 2500 0 8099 0.0% 0.0% —
MOVEP.w 2500 0 5306 0.0% 0.0% —
MOVEtoCCR 2500 0 19785 0.0% 0.0% 0.0%
MOVEtoSR 2500 15 18342 0.6% 1.0% 0.0%
MOVEtoUSP 2500 0 13274 0.0% 0.0% —
MULS 2500 1 17538 0.0% 0.1% 0.0%
MULU 2500 1 18264 0.0% 0.1% 0.0%
NBCD 2500 2500 0 Complet Complet —
NEG.b 2500 1247 1253 49.9% 49.9% —
NEG.l 2500 797 15994 31.9% 51.5% 0.0%
NEG.w 2500 767 15952 30.7% 49.7% 0.0%
NEGX.b 2500 2500 0 Complet Complet Complet
NEGX.l 2500 1543 15315 61.7% Complet 0.0%
NEGX.w 2500 1537 15239 61.5% Complet 0.0%
NOP 2500 2500 0 Complet Complet Complet
NOT.b 2500 2500 0 Complet Complet Complet
NOT.l 2500 2500 0 Complet Complet Complet
NOT.w 2500 2500 0 Complet Complet Complet
OR.b 2500 2500 0 Complet Complet Complet
OR.l 2500 1423 17087 56.9% Complet 0.0%
OR.w 2500 1438 16673 57.5% Complet 0.0%
ORItoCCR 2500 2500 0 Complet Complet Complet
ORItoSR 2500 14 11449 0.6% 0.6% —
PEA 2500 2500 0 Complet Complet Complet
RESET 2500 1233 10000 49.3% 49.3% —
ROL.b 2500 2500 0 Complet Complet —
ROL.l 2500 2500 0 Complet Complet —
ROL.w 2500 2209 4598 88.4% 88.4% 0.0%
ROR.b 2500 2500 0 Complet Complet —
ROR.l 2500 2500 0 Complet Complet —
ROR.w 2500 2203 4700 88.1% 88.1% 0.0%
ROXL.b 2500 175 4047 7.0% 7.0% —
ROXL.l 2500 196 3748 7.8% 7.8% —
ROXL.w 2500 188 8216 7.5% 8.7% 0.0%
ROXR.b 2500 184 4247 7.4% 7.4% —
ROXR.l 2500 177 4246 7.1% 7.1% —
ROXR.w 2500 165 8579 6.6% 7.6% 0.0%
RTE 2500 2500 0 Complet Complet Complet
RTR 2500 153 20981 6.1% 6.1% —
RTS 2500 1263 12365 50.5% 50.5% —
SBCD 2500 2500 0 Complet Complet —
Scc 2500 2500 0 Complet Complet Complet
STOP 2500 2500 0 Complet Complet —
SUB.b 2500 2500 0 Complet Complet Complet
SUB.l 2500 1599 14441 64.0% Complet 0.0%
SUB.w 2500 1579 14589 63.2% Complet 0.0%
SUBX.b 2500 2230 800 89.2% 89.2% —
SUBX.l 2500 1673 14450 66.9% Complet 0.0%
SUBX.w 2500 1646 14118 65.8% Complet 0.0%
SWAP 2500 2500 0 Complet Complet Complet
TAS 2500 2500 0 Complet Complet Complet
TRAP 2500 2500 0 Complet Complet Complet
TRAPV 2500 2500 0 Complet Complet Complet
TST.b 2500 2500 0 Complet Complet Complet
TST.l 2500 1524 15655 61.0% Complet 0.0%
TST.w 2500 1507 15714 60.3% Complet 0.0%
UNLINK 2500 7 20557 0.3% 0.5% 0.0%

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 par decode.zig), donc tous leurs tests sont classés Paires.

Résultats des tests de timing

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 ✅

Fonctionnalités implémentées

Architecture du CPU

  • Registres D0–D7, A0–A7, PC, SR, USP/SSP
  • Mode Superviseur / Utilisateur avec bascule via sr.s et 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 exception empilant 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 et modes d'adressage

  • 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

About

Motorola 68000 (M68k) CPU emulator core in Zig 0.16 — full instruction set, MAME single-step tests (317,500 cases), targeting Sega Mega Drive / Genesis accuracy. Émulateur du Motorola 68000.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages