64 bits m-code virtual machine with interpreter and conrsion program
|
|
7 tuntia sitten | |
|---|---|---|
| MC4 | 3 viikkoa sitten | |
| docs | 3 viikkoa sitten | |
| Console.def | 3 viikkoa sitten | |
| Console.mod | 3 viikkoa sitten | |
| Console.o | 3 viikkoa sitten | |
| Extended.def | 3 viikkoa sitten | |
| Extended.mod | 3 viikkoa sitten | |
| Extended.o | 3 viikkoa sitten | |
| FileIO.def | 3 viikkoa sitten | |
| FileIO.mod | 3 viikkoa sitten | |
| FileIO.o | 3 viikkoa sitten | |
| Global.def | 3 viikkoa sitten | |
| Global.mod | 3 viikkoa sitten | |
| Global.o | 3 viikkoa sitten | |
| Instruction.def | 3 viikkoa sitten | |
| Instruction.mod | 3 viikkoa sitten | |
| Instruction.o | 3 viikkoa sitten | |
| Interpreter.def | 3 viikkoa sitten | |
| Interpreter.mod | 3 viikkoa sitten | |
| Interpreter.o | 3 viikkoa sitten | |
| Loader2.def | 3 viikkoa sitten | |
| Loader2.mod | 3 viikkoa sitten | |
| Loader2.o | 3 viikkoa sitten | |
| Local.def | 3 viikkoa sitten | |
| Local.mod | 3 viikkoa sitten | |
| Local.o | 3 viikkoa sitten | |
| M2c-git instructions.txt | 3 viikkoa sitten | |
| MC64.mod | 3 viikkoa sitten | |
| MC64.o | 3 viikkoa sitten | |
| Memory.def | 3 viikkoa sitten | |
| Memory.mod | 3 viikkoa sitten | |
| Memory.o | 3 viikkoa sitten | |
| README.md | 7 tuntia sitten | |
| SESSION.MD5.trans8to64 | 3 viikkoa sitten | |
| Stack.def | 3 viikkoa sitten | |
| Stack.mod | 3 viikkoa sitten | |
| Stack.o | 3 viikkoa sitten | |
| gnu-m2-grammar.txt | 3 viikkoa sitten | |
| img1.png | 3 viikkoa sitten | |
| mc64 | 3 viikkoa sitten | |
| mcd.o | 3 viikkoa sitten | |
| mcint | 3 viikkoa sitten | |
| mcint.mod | 3 viikkoa sitten | |
| mcint.o | 3 viikkoa sitten | |
| mkdemo | 3 viikkoa sitten | |
| mkdemo.mod | 3 viikkoa sitten | |
| mkdemo.o | 3 viikkoa sitten | |
| mkdep | 3 viikkoa sitten | |
| mkdep.mod | 3 viikkoa sitten | |
| mkdep.o | 3 viikkoa sitten | |
| mkdtest | 3 viikkoa sitten | |
| mkdtest.mod | 3 viikkoa sitten | |
| mkdtest.o | 3 viikkoa sitten | |
| mkread | 3 viikkoa sitten | |
| mkread.mod | 3 viikkoa sitten | |
| mkread.o | 3 viikkoa sitten | |
| skills.html | 3 viikkoa sitten | |
| skills.jpeg | 3 viikkoa sitten | |
| skills.md | 3 viikkoa sitten | |
| skills.pdf | 3 viikkoa sitten | |
| skills.png | 3 viikkoa sitten | |
| trans8to64 | 3 viikkoa sitten | |
| trans8to64.mod | 3 viikkoa sitten | |
| trans8to64.o | 3 viikkoa sitten | |
| trans8to64dbg | 3 viikkoa sitten | |
| tutorial.md | 7 tuntia sitten |
MC64 is a 64-bit generalization of the MCode virtual machine that Borland
Turbo Modula-2 for CP/M executed on the Z80. The machine word — the unit of
the stack, frame cells and global cells — is widened from 16 to 64 bits,
the address space becomes flat and byte-addressable, and the 256-entry opcode
map is preserved 1:1: only operand widths and the scalar type mapping differ.
The normative reference is docs/mc64-spec.md, §14 of
which contains the row-by-row MCode/16 → MC64 migration table.
The machine loads .MC4 image files (a 64-byte "MC64" header + a module
descriptor + code + a procedure table) and boots them with the mcint
launcher. It is the execution target of the experimental Modula-2 compilers in
MyWork/ — V1 (M2c), V2 (M2comp) and V3 — whose code generators emit
.MC4 images that this interpreter runs. As of this writing the loader is at
the dependency-chain milestone: a guest module can name up to 32
dependencies and call across module boundaries through the 256-slot module
table (MTBL).
The repository ships prebuilt executables and ready-made sample images, so the first run takes one command:
./mkdemo # writes boot.MC4 in the current directory
./mcint boot.MC4 # prints "Hello MC64!" and exits 0
A stack machine with a single stack shared by values and activation frames,
growing down (Push = SP -= 8).
| Register | Meaning |
|---|---|
IP |
instruction pointer — byte address of the next opcode |
SP |
stack pointer — byte address of the top word |
FP |
frame pointer — base of the current activation frame |
GP |
global pointer — base of the current module's data window |
OFP |
outer frame pointer — static chain / display link |
MTBL |
module table — MTBL[i] = data base of loaded module i |
| Modula-2 type | Width | Stack slots | Notes |
|---|---|---|---|
| BYTE, CHAR, BOOLEAN | 8 bits | 1 | held in the low bits of a slot |
| CARDINAL | 32 bits | 1 | unsigned, zero-extended |
| INTEGER | 32 bits | 1 | two's complement, sign-extended |
| SET | 64 bits | 1 | elements 0..63 |
| LONGINT / LONGCARD | 64 bits | 1 | signed / unsigned 64-bit arithmetic |
| REAL | 64 bits | 1 | IEEE 754 binary64 (double) |
| LONGREAL | 128 bits | 2 | IEEE 754 binary128 (quad) |
| pointer / address | 64 bits | 1 | byte address |
Stack slots are always 64 bits; 32-bit values live in the low 32 bits (CARDINAL zero-extended, INTEGER sign-extended), so 32↔64-bit widening is a value no-op. Memory is little-endian everywhere.
Locals live at FP[-1], FP[-2], …; parameter k at FP[k+2]; arguments are
pushed in reverse declaration order. ENTER k reserves (255−k)×8 bytes of
locals (k=0FFH → none). EXTERN_CALL mod,proc switches GP to
MTBL[mod] and jumps through the callee module's procedure table.
.MC4)A module file is a 64-byte header followed by the image: the module descriptor, its code, a procedure table and (optionally) a dependency-name table.
"MC64" at offset 0; the descriptor itself sits at
image offset 0 (i.e. immediately after the 64-byte header) in the
generator images.| offset | field |
|---|---|
| 0 | dependencies — 256 bytes of module-base pointers |
| 256 | link — next module in chain |
| 264 | name — 16 chars, NUL-padded |
| 280 | loadAddr |
| 288 | checksum — u32 |
| 292 | flags (bit 2 = TOINIT) |
| 293 | varCount |
| 294 | depCount |
| 295 | pad |
| 296 | procsAddr — location of the procedure table |
| 304 | varSizes — varCount × u64 byte sizes |
N contiguous 64-bit relative byte offsets:
procedureAddress(k) = procsAddr + k*8 + table[k].depCount names appended at the image tail (8 NUL-padded
bytes each); the loader loads dependency modules into low MTBL slots first
(extern module 0 = the first import), then the main module.The loader places the image at ArenaBase (1 MiB) and allocates the module's
globals (varSizes bytes per entry, zero-filled) in an 8-byte-aligned data
window right after the image. Historically these files were called .MCD; the
64-bit format was renamed to .MC4 per spec sections 8 and 14.
| Tool | Purpose | Sample |
|---|---|---|
mcint |
interpreter launcher — boots a single-module image or the main module of a dependency chain | ./mcint boot.MC4 |
mc64 |
demo wrapper — boots boot.MC4 then prints [vm end] |
./mc64 |
mkdemo |
writes boot.MC4 ("Hello MC64!" via the SYSTEM write-string service) |
./mkdemo |
mkdtest |
writes example.MC4, a 24-instruction opcode/composite exercise |
./mkdtest && ./mcint example.MC4 |
mkread |
writes readtest.MC4, which reads two stdin lines and echoes them back |
printf 'a\nb\n' \| ./mcint readtest.MC4 |
mkdep |
writes STAK.MC4 + DEP.MC4, a two-module cross-module dependency-call demo |
./mkdep && ./mcint DEP.MC4 |
trans8to64 |
translates a classic 16-bit Turbo Modula-2 .MCD binary into a 64-bit .MC4 image |
./trans8to64 in.MCD out.MC4 |
mcint takes the image path as its first program argument; exit status is 0
when the guest reaches end_program (SYSTEM service 0), 1 when the loader
or a guest trap aborts. With no argument it prints its usage line.
Everything is ISO Modula-2, compiled with GNU Modula-2:
# in a build directory containing the sources (cp src/*.mod src/*.def .)
for m in Memory Local Global Stack Instruction Extended Interpreter Loader2 \
Console FileIO; do
gm2 -fiso -c "$m.mod"
done
gm2 -fiso -o mcint mcint.mod \
Loader2.o Interpreter.o Extended.o Instruction.o Stack.o Global.o Local.o \
Memory.o Console.o FileIO.o
gm2 -fiso -o mc64 MC64.mod \
Stack.o Memory.o Console.o Global.o Loader2.o Interpreter.o Extended.o \
Instruction.o Local.o FileIO.o
gm2 -fiso -o mkdemo mkdemo.mod FileIO.o Console.o
gm2 -fiso -o mkdtest mkdtest.mod FileIO.o Console.o
gm2 -fiso -o mkread mkread.mod FileIO.o Console.o
gm2 -fiso -o mkdep mkdep.mod FileIO.o Console.o
gm2 -fiso -o trans8to64 trans8to64.mod FileIO.o Console.o
One build rule matters (see spec §16.1): only the program module is passed
to the link step; library modules are given as their precompiled .o. Passing
several .mod files at once makes gm2 emit one main per module and the link
fails with duplicate-main errors — and linking all *.o indiscriminately
runs every module's init body at startup.
src/ VM library modules (Memory, Local, Global, Stack, Instruction,
Extended, Interpreter, Loader2, Console, FileIO) and the seven
tool programs (mcint, MC64, mkdemo, mkdtest, mkread, mkdep,
trans8to64) — .mod/.def sources
MC4/ generated sample images (boot.MC4, example.MC4, readtest.MC4,
STAK.MC4, DEP.MC4)
docs/ mc64-spec.md (normative spec), session-summary.md, SESSION.md,
m-code-summary-64.md, m-code-summary.md, porting-plan-m2sp.md
root built executables, *.o, reference files (skills.*,
gnu-m2-grammar.txt, M2c-git instructions.txt, SESSION.MD5.trans8to64)
docs/mc64-spec.md — the normative specification: memory model,
registers, types, frames, addressing, module linkage, the on-disk format
(§8), the host interface (§9.3), the extended and quad sub-dispatches (§10),
the 256-opcode instruction-set reference (§11), the MCode/16 → MC64
migration table (§14) and the GNU Modula-2 build notes (§16).docs/m-code-summary-64.md — condensed summary of the 64-bit machine.docs/session-summary.md — day-by-day log of loader/interpreter
milestones: build recipes, verified behaviors, hard-won tools-and-gotchas.docs/porting-plan-m2sp.md — plan for porting Niklaus Wirth's M2SP
single-pass compiler to ISO gm2 with an MC4 code generator.docs/SESSION.md — working notes.All of the following are green with the freshly built binaries:
./mkdemo → boot.MC4; ./mcint boot.MC4 → Hello MC64! (0);
./mc64 → Hello MC64! + [vm end] (0);
./mcint → usage (0); ./mcint nope.MC4 → loader fatal (1)../mkdtest → example.MC4; ./mcint example.MC4 — 24/24 checks:
g after 10*2+1 = 2047, add/sub/mul/div/mod, bit_and/or/xor, power2, the
extended 0x40 sub-dispatch (uc_add/uc_mul/uc_div/uc_mod, long_negate,
build_field_mask), real_add 3.5+2.25 = 5, dup/swap, global/local dword
loads, copy_block → abc (0)../mkread → readtest.MC4; printf 'a\nb\n' | ./mcint readtest.MC4
echoes both lines through SYSTEM service 2 (0)../mkdep → STAK.MC4 + DEP.MC4; ./mcint DEP.MC4 executes an extern
call into STAK through MTBL[0] and prints cross-module ok (0).Siblings in MyWork/:
m2compiler-V1 — M2c, the single-pass compiler (Coco/R M2c.atg +
SymTab/MGen), step 11, 158/158 tests; the original .MC4 consumer.m2compiler-V2 — M2comp, the Blaise front/back (AST) compiler, step 7,
65/65 tests; its run_tests.sh defaults to MCINT=../m-code-64/mcint.m2compiler-V3 — the larger successor generation.m-code — the original 16-bit Turbo Modula-2 reference material and
MCode sources (used only as Modula-2 sources, never binary analysis).CocoGm2 — the GNU-Modula-2 port of Coco/R (CR) used to build the
compiler front ends.docs/mc64-spec.md only — no
disassembly or analysis of classic .MCD binaries.gm2 -fiso).mkd*.mod generators are
the known-good .MC4 encoders used as ground truth for the compilers.SESSION.MD5.trans8to64 stores a baseline MD5 of trans8to64.mod: any step
that rewrites that file without updating the lock note is a session bug.