ilo-vm/source/ilo.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()