-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathmk7.nim
69 lines (59 loc) · 1.75 KB
/
mk7.nim
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
# mk7: register-based vm inspired by Human Resource Machine
import strformat
import vimes/sio
import vimes/load
import bench
include mk7_opcodes
include mk7_opnames
type Word = int16
var pc: Word # program counter
var acc: Word # accumulator
var cc: int64 # used only when -d:cc is passed
var mem: seq[Word] = @[] # memory
var code: seq[Word] = @[] # program
var stack: seq[Word] = @[] # return stack (not used)
proc reset(quick=false) =
pc=0; acc=0; cc=0
if quick: return
for j in low(mem)..high(mem):
mem[j] = 0
proc trace(op,a:Word) =
let opname = opnames[cast[Instr](op)]
let va = mem[a]
stderr.write_line """| {cc:3} | {pc:2} | {acc:3} | {opname:>4} {a:2} | {va:3} | """.fmt
proc debug() =
echo "pc:", pc, " acc:", acc, " cc:", cc
proc run() =
while true:
# {.computedGoto.} # 10% slower :(
let op = cast[Instr]( code[pc] )
let a = code[pc+1]
when defined(cc): cc+=1
when defined(trace): trace(opc,a)
pc += 2
case op:
# control flow
of JZ:
if acc==0: pc=a
of JN:
if acc<0: pc=a
of JMP: pc=a
# data transfer
of LDA: acc = mem[a]
of LIT: acc = a # EXTENSION
of STA: mem[a] = acc
# alu
of ADD: acc += mem[a]
of SUB: acc -= mem[a]
of INC: mem[a] += 1
of DEC: mem[a] -= 1
# stdio - TODO: as extension
of OUT: echo acc # stdout.write $acc & " "
of IN: acc = sio.read_int().Word
# misc
of HLT: return
else:
quit("unknown opcode op:" & $op, 1)
include cli
if is_main_module:
cli()