241 lines
4.8 KiB
Nim
241 lines
4.8 KiB
Nim
# **************************************************************
|
|
# crc's _ _
|
|
# (_) | ___
|
|
# | | |/ _ \ a tiny virtual computer
|
|
# | | | (_) | 64kw RAM, 32-bit, Dual Stack, MISC
|
|
# |_|_|\___/ ilo.nim (c) charles childers
|
|
# **************************************************************
|
|
|
|
# nim c -r vm/ilo.nim
|
|
|
|
{.push overflowChecks: off.}
|
|
|
|
var
|
|
ip, sp, rp: int32
|
|
s: array[33, int32]
|
|
r: array[257, int32]
|
|
m: array[65536, int32]
|
|
|
|
let
|
|
rom = "ilo.rom"
|
|
blocks = "ilo.blocks"
|
|
|
|
proc load_image() =
|
|
let f = open(rom)
|
|
defer: f.close()
|
|
discard f.readBuffer(addr m[0], sizeof(m))
|
|
|
|
proc read_block() =
|
|
let f = open(blocks)
|
|
let buf = s[sp]
|
|
let blk = s[sp - 1]
|
|
sp = sp - 2
|
|
defer: f.close()
|
|
f.setFilePos(blk * 4096)
|
|
discard f.readBuffer(addr m[buf], 4096)
|
|
|
|
proc write_block() =
|
|
let f = open(blocks, fmReadWriteExisting)
|
|
let buf = s[sp]
|
|
let blk = s[sp - 1]
|
|
sp = sp - 2
|
|
defer: f.close()
|
|
f.setFilePos(blk * 4096)
|
|
discard f.writeBuffer(addr m[buf], 4096)
|
|
|
|
proc save_image() =
|
|
return
|
|
|
|
proc opcode(o: int32) =
|
|
case o:
|
|
of 0: # ..
|
|
return
|
|
of 1: # li
|
|
ip = ip + 1
|
|
sp = sp + 1
|
|
s[sp] = m[ip]
|
|
of 2: # du
|
|
sp = sp + 1
|
|
s[sp] = s[sp - 1]
|
|
of 3: # dr
|
|
sp = sp - 1
|
|
of 4: # sw
|
|
let a = s[sp]
|
|
let b = s[sp - 1]
|
|
s[sp] = b
|
|
s[sp - 1] = a
|
|
of 5: # pu
|
|
rp = rp + 1
|
|
r[rp] = s[sp]
|
|
sp = sp - 1
|
|
of 6: # po
|
|
sp = sp + 1
|
|
s[sp] = r[rp]
|
|
rp = rp - 1
|
|
of 7: # ju
|
|
ip = s[sp] - 1
|
|
sp = sp - 1
|
|
of 8: # ca
|
|
rp = rp + 1
|
|
r[rp] = ip
|
|
ip = s[sp] - 1
|
|
sp = sp - 1
|
|
of 9: # cc
|
|
let target = s[sp]
|
|
let flag = s[sp - 1]
|
|
sp = sp - 2
|
|
if flag != 0:
|
|
rp = rp + 1
|
|
r[rp] = ip
|
|
ip = target - 1
|
|
of 10: # cj
|
|
let target = s[sp]
|
|
let flag = s[sp - 1]
|
|
sp = sp - 2
|
|
if flag != 0:
|
|
ip = target - 1
|
|
of 11: # re
|
|
ip = r[rp]
|
|
rp = rp - 1
|
|
of 12: # eq
|
|
let b = s[sp]
|
|
let a = s[sp - 1]
|
|
sp = sp - 1
|
|
if a == b:
|
|
s[sp] = -1
|
|
else:
|
|
s[sp] = 0
|
|
of 13: # ne
|
|
let b = s[sp]
|
|
let a = s[sp - 1]
|
|
sp = sp - 1
|
|
if a != b:
|
|
s[sp] = -1
|
|
else:
|
|
s[sp] = 0
|
|
of 14: # lt
|
|
let b = s[sp]
|
|
let a = s[sp - 1]
|
|
sp = sp - 1
|
|
if a < b:
|
|
s[sp] = -1
|
|
else:
|
|
s[sp] = 0
|
|
of 15: # gt
|
|
let b = s[sp]
|
|
let a = s[sp - 1]
|
|
sp = sp - 1
|
|
if a > b:
|
|
s[sp] = -1
|
|
else:
|
|
s[sp] = 0
|
|
of 16: # fe
|
|
s[sp] = m[s[sp]]
|
|
of 17: # st
|
|
m[s[sp]] = s[sp - 1]
|
|
sp = sp - 2
|
|
of 18: # ad
|
|
s[sp - 1] = s[sp - 1] + s[sp]
|
|
sp = sp - 1
|
|
of 19: # su
|
|
s[sp - 1] = s[sp - 1] - s[sp]
|
|
sp = sp - 1
|
|
of 20: # mu
|
|
s[sp - 1] = s[sp - 1] * s[sp]
|
|
sp = sp - 1
|
|
of 21: # di
|
|
let b = s[sp]
|
|
let a = s[sp - 1]
|
|
s[sp] = a div b
|
|
s[sp - 1] = a mod b
|
|
of 22: # an
|
|
s[sp - 1] = s[sp - 1] and s[sp]
|
|
sp = sp - 1
|
|
of 23: # or
|
|
s[sp - 1] = s[sp - 1] or s[sp]
|
|
sp = sp - 1
|
|
of 24: # xo
|
|
s[sp - 1] = s[sp - 1] xor s[sp]
|
|
sp = sp - 1
|
|
of 25: # sl
|
|
s[sp - 1] = s[sp - 1] shl s[sp]
|
|
sp = sp - 1
|
|
of 26: # sr
|
|
s[sp - 1] = s[sp - 1] shr s[sp]
|
|
sp = sp - 1
|
|
of 27: # cp
|
|
var length: int32 = s[sp]
|
|
var dest: int32 = s[sp - 1]
|
|
var src: int32 = s[sp - 2]
|
|
var flag: int32 = -1
|
|
sp = sp - 2
|
|
while length != 0:
|
|
if m[dest] != m[src]:
|
|
flag = 0
|
|
dest = dest + 1
|
|
src = src + 1
|
|
length = length - 1
|
|
s[sp] = flag
|
|
of 28: # cy
|
|
var length: int32 = s[sp]
|
|
var dest: int32 = s[sp - 1]
|
|
var src: int32 = s[sp - 2]
|
|
sp = sp - 3
|
|
while length != 0:
|
|
m[dest] = m[src]
|
|
dest = dest + 1
|
|
src = src + 1
|
|
length = length - 1
|
|
of 29: # io
|
|
let dev = s[sp]
|
|
sp = sp - 1
|
|
case dev:
|
|
of 0:
|
|
if s[sp] != 0:
|
|
stdout.write $(char(s[sp]))
|
|
sp = sp - 1
|
|
of 1:
|
|
var buf: array[1, byte]
|
|
discard stdin.readBytes(buf, 0, 1)
|
|
sp = sp + 1
|
|
s[sp] = int32(buf[0])
|
|
of 2:
|
|
read_block()
|
|
of 3:
|
|
write_block()
|
|
of 4:
|
|
echo "save_image()"
|
|
of 5:
|
|
load_image()
|
|
ip = 0
|
|
sp = 0
|
|
rp = 0
|
|
of 6:
|
|
ip = 65536
|
|
of 7:
|
|
sp = sp + 1
|
|
s[sp] = sp - 1
|
|
sp = sp + 1
|
|
s[sp] = rp
|
|
else:
|
|
echo "unsupported io:", dev
|
|
else:
|
|
echo "wtf?"
|
|
|
|
proc process() =
|
|
while ip < 65536:
|
|
let a = m[ip] and 255
|
|
let b = (m[ip] shr 8) and 255
|
|
let c = (m[ip] shr 16) and 255
|
|
let d = (m[ip] shr 24) and 255
|
|
opcode(a)
|
|
opcode(b)
|
|
opcode(c)
|
|
opcode(d)
|
|
ip = ip + 1
|
|
|
|
ip = 0
|
|
sp = 0
|
|
rp = 0
|
|
load_image()
|
|
process()
|