# ************************************************************** # 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()