# ************************************************************** # crc's _ _ # (_) | ___ # | | |/ _ \ a tiny virtual computer # | | | (_) | 64kw RAM, 32-bit, Dual Stack, MISC # |_|_|\___/ ilo.py (c) charles childers # (c) arland childers # ************************************************************** import struct, io, os, sys, ctypes class Stack(): def __init__(self, size, desc): self.sp = 0 self.data = [0] * size self.desc = desc self.max = size def push(self, val): self.sp += 1 if abs(val) > 0xffffff: self.data[self.sp] = int(ctypes.c_int32(val).value) else: self.data[self.sp] = val def pop(self): self.sp -= 1 return self.data[self.sp + 1] def top(self): return self.data[self.sp] def depth(self): return self.sp ip = 0 memory = [0] input_buffer = [] data = Stack(33, 'data') address = Stack(257, 'addresses') block_pack = struct.Struct('1024i').pack block_unpack = struct.Struct('1024i').unpack def div_mod(a, b): x = abs(a) y = abs(b) q, r = divmod(x, y) if a < 0 and b < 0: r *= -1 elif a > 0 and b < 0: q *= -1 elif a < 0 and b > 0: r *= -1 q *= -1 return q, r def load_image(): global memory with open("ilo.rom", "rb") as f: memory = list(struct.unpack("65536i", f.read())) def save_image(): with open("ilo.rom", "wb") as f: f.write(struct.pack('65536i', *memory[:65536])) def read_block(): global memory, data buffer = data.pop() block = data.pop() with open("ilo.blocks", 'r+b') as f: f.seek(4096 * block, io.SEEK_SET) memory[buffer:buffer+1024] = list(block_unpack(f.read(4096))) def write_block(): global data buffer = data.pop() block = data.pop() with open("ilo.blocks", 'r+b') as f: f.seek(4096 * block, io.SEEK_SET) f.write(block_pack(*memory[buffer:buffer + 1024])) def process(c): global ip, data, address, memory, input_buffer if c == 0: return if c == 11: ip = address.pop() elif c == 8: address.push(ip) ip = data.pop() - 1 elif c == 1: ip += 1 data.push(memory[ip]) elif c == 2: data.push(data.top()) elif c == 3: data.pop() elif c == 4: a = data.pop() b = data.pop() data.push(a) data.push(b) elif c == 5: address.push(data.pop()) elif c == 6: data.push(address.pop()) elif c == 7: ip = data.pop() - 1 elif c == 9: target = data.pop() flag = data.pop() if flag != 0: address.push(ip) ip = target - 1 elif c == 10: target = data.pop() flag = data.pop() if flag != 0: ip = target - 1 elif c == 12: b = data.pop() a = data.pop() data.push(-(a == b)) elif c == 13: b = data.pop() a = data.pop() data.push(-(a != b)) elif c == 14: b = data.pop() a = data.pop() data.push(-(a < b)) elif c == 15: b = data.pop() a = data.pop() data.push(-(a > b)) elif c == 16: x = data.pop() data.push(memory[x]) elif c == 17: a = data.pop() v = data.pop() memory[a] = v elif c == 18: b = data.pop() a = data.pop() data.push(a + b) elif c == 19: b = data.pop() a = data.pop() data.push(a - b) elif c == 20: b = data.pop() a = data.pop() data.push(a * b) elif c == 21: a = data.pop() b = data.pop() data.push(div_mod(b, a)[1]) data.push(div_mod(b, a)[0]) elif c == 22: b = data.pop() a = data.pop() data.push(b & a) elif c == 23: b = data.pop() a = data.pop() data.push(b | a) elif c == 24: b = data.pop() a = data.pop() data.push(b ^ a) elif c == 25: b = data.pop() a = data.pop() data.push(a << b) elif c == 26: b = data.pop() a = data.pop() data.push(a >> b) elif c == 27: l = data.pop() dest = data.pop() src = data.pop() if memory[dest:dest + l] == memory[src:src + l]: data.push(-1) else: data.push(0) elif c == 28: l = data.pop() dest = data.pop() src = data.pop() memory[dest:dest + l] = memory[src:src + l] elif c == 29: i = data.pop() if i == 0: print(chr(data.pop()), end='') elif i == 1: if not len(input_buffer): input_buffer = ["\n"] + list(input())[::-1] data.push(ord(input_buffer.pop())) elif i == 2: read_block() elif i == 3: write_block() elif i == 4: save_image() elif i == 5: load_image() ip = -1 elif i == 6: ip = 65535 elif i == 7: data.push(data.depth()) data.push(address.depth()) else: pass def print_opcode_bundle(opcode): print(opcode & 0xFF, end=" ") print((opcode >> 8) & 0xFF, end=" ") print((opcode >> 16) & 0xFF, end=" ") print((opcode >> 24) & 0xFF, end=": ") def execute(start): global ip, data, address, memory ip = start while ip < 65536: m = memory[ip] if m == 2049: address.push(ip + 1) ip = memory[ip + 1] - 1 elif m < 30 and m > 0: process(m) elif m != 0: process(m & 0xFF) process((m >> 8) & 0xFF) process((m >> 16) & 0xFF) process((m >> 24) & 0xFF) ip += 1 def main(): load_image() execute(0) if __name__ == '__main__': main()