-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathmk8.nim
94 lines (84 loc) · 2.45 KB
/
mk8.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
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
# mk8: mk7 with stack and memory addressing
import strformat
import vimes/sio
import vimes/load
import bench
include mk8_opcodes
include mk8_opnames
type Word = int16
var pc: Word # program counter
var sp: Word # stack pointer
var acc: Word # accumulator
var cc: int64 # cycle counter
var mem: seq[Word] = @[] # memory
var code: seq[Word] = @[] # program
var stack: seq[Word] = @[] # return stack
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} | {opname:>4} {a:2} | {acc:3} | {va:3} | """.fmt
proc debug() =
echo "pc:", pc, " acc:", acc, " cc:", cc
proc run() =
while true:
let opc = code[pc]
let op = cast[Instr](opc)
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
# MK8
of CAL: stack[sp]=pc; sp+=1; pc=a
of RET: sp-=1; pc=stack[sp]
of LPA: acc = mem[mem[a]]
of SPA: mem[mem[a]] = acc
of ASR: acc = ashr(acc,a).Word
of NOP: discard
# EXTENSION
of JP:
if acc>0: pc=a
of PUSH: mem[a]+=1; mem[mem[a]]=acc
of POP: acc=mem[mem[a]]; mem[a]-=1
# EXTENSION 2
of JZP:
if acc>=0: pc=a
of JZN:
if acc<=0: pc=a
# EXTENSION 3
of LPAO:
b = code[pc]; pc+=1
acc = mem[mem[a]+b]
of SPAO:
b = code[pc]; pc+=1
mem[mem[a]+b] = acc
else:
quit("unknown opcode op:" & $op, 1)
include cli
if is_main_module:
cli()