/*************************************************************** crc's _ _ (_) | ___ | | |/ _ \ a tiny virtual computer | | | (_) | 64kw RAM, 32-bit, Dual Stack, MISC |_|_|\___/ ilo.d (c) charles childers **************************************************************/ import std.stdio; Stack data, addr; /* data & address stacks */ RAM memory; /* system memory */ int ip; /* instruction pointer */ string blocks; /* name of block file (ilo.blocks) */ string rom; /* name of image (ilo.rom) */ void load_image() { data = new Stack(33); addr = new Stack(257); memory = new RAM(); FILE *file = fopen(rom.ptr, "rb"); if (file is null) { return; } fread(memory.pointer(), 1, 65536 * 4, file); fclose(file); ip = 0; } void save_image() { FILE *file = fopen(rom.ptr, "wb"); fwrite(memory.pointer(), 1, 65536 * 4, file); fclose(file); } void read_block() { int[1024] block; FILE *file = fopen(blocks.ptr, "rb"); if (file is null) { return; } int b = data.pop(); /* block buffer */ int a = data.pop(); /* block number */ fseek(file, 4096 * a, SEEK_SET); fread(block.ptr, 1, 4096, file); foreach(i; 0 .. 1024) { memory.store(b + i, block[i]); } fclose(file); } void write_block() { int[1024] block; FILE *file = fopen(blocks.ptr, "r+b"); if (file is null) { return; } int b = data.pop(); /* block buffer */ int a = data.pop(); /* block number */ fseek(file, 4096 * a, SEEK_SET); foreach(i; 0 .. 1024) { block[i] = memory.fetch(b + i); } fwrite(block.ptr, 1, 4096, file); fclose(file); } void li() { ip += 1; data.push(memory.fetch(ip)); } void du() { data.dup(); } void dr() { data.pop(); } void sw() { data.swap(); } void pu() { addr.push(data.pop()); } void po() { data.push(addr.pop()); } void ju() { ip = data.pop() - 1; } void ca() { addr.push(ip); ip = data.pop() - 1; } void cc() { int a = data.pop(); if (data.pop()) { addr.push(ip); ip = a - 1; } } void cj() { int a = data.pop(); if (data.pop()) { ip = a - 1; } } void re() { ip = addr.pop(); } void eq() { data.swap(); data.push((data.pop() == data.pop()) ? -1 : 0); } void ne() { data.swap(); data.push((data.pop() != data.pop()) ? -1 : 0); } void lt() { data.swap(); data.push((data.pop() < data.pop()) ? -1 : 0); } void gt() { data.swap(); data.push((data.pop() > data.pop()) ? -1 : 0); } void fe() { data.push(memory.fetch(data.pop())); } void st() { int a = data.pop(); memory.store(a, data.pop()); } void ad() { data.swap(); data.push(data.pop() + data.pop()); } void su() { data.swap(); data.push(data.pop() - data.pop()); } void mu() { data.swap(); data.push(data.pop() * data.pop()); } void di() { int a = data.pop(); int b = data.pop(); data.push(b % a); data.push(b / a); } void an() { data.push(data.pop() & data.pop()); } void or() { data.push(data.pop() | data.pop()); } void xo() { data.push(data.pop() ^ data.pop()); } void sl() { data.swap(); data.push(data.pop() << data.pop()); } void sr() { data.swap(); data.push(data.pop() >> data.pop()); } void cp() { int l = data.pop(); int d = data.pop(); int s = data.pop(); data.push(-1); while (l) { if (memory.fetch(d) != memory.fetch(s)) { data.pop(); data.push(0); } l -= 1; s += 1; d += 1; } } void cy() { int l = data.pop(); int d = data.pop(); int s = data.pop(); while (l) { memory.store(d, memory.fetch(s)); l -= 1; s += 1; d += 1; } } void ioa() { writef("%c", cast(char)data.pop()); } void iob() { data.push(getchar()); } void ioc() { read_block(); } void iod() { write_block(); } void ioe() { save_image(); } void iof() { load_image(); ip = -1; } void iog() { ip = 65536; } void ioh() { data.push(data.depth()); data.push(addr.depth()); } void io() { switch (data.pop()) { case 0: ioa(); break; case 1: iob(); break; case 2: ioc(); break; case 3: iod(); break; case 4: ioe(); break; case 5: iof(); break; case 6: iog(); break; case 7: ioh(); break; default: break; } } void process(int o) { switch (o) { case 0: break; case 1: li(); break; case 2: du(); break; case 3: dr(); break; case 4: sw(); break; case 5: pu(); break; case 6: po(); break; case 7: ju(); break; case 8: ca(); break; case 9: cc(); break; case 10: cj(); break; case 11: re(); break; case 12: eq(); break; case 13: ne(); break; case 14: lt(); break; case 15: gt(); break; case 16: fe(); break; case 17: st(); break; case 18: ad(); break; case 19: su(); break; case 20: mu(); break; case 21: di(); break; case 22: an(); break; case 23: or(); break; case 24: xo(); break; case 25: sl(); break; case 26: sr(); break; case 27: cp(); break; case 28: cy(); break; case 29: io(); break; default: break; } } void process_bundle(int opcode) { process(opcode & 0xFF); process((opcode >> 8) & 0xFF); process((opcode >> 16) & 0xFF); process((opcode >> 24) & 0xFF); } void execute() { while (ip < 65536) { process_bundle(memory.fetch(ip)); ip += 1; } } void main(string[] args) { blocks = "ilo.blocks"; rom = "ilo.rom"; load_image(); execute(); data.print(); writef("\n"); } class RAM { private int[65536] data; this() { } int fetch(int a) { if (a < 0 || a > 65535) throw new Exception("Invalid memory access"); return data[a]; } void store(int a, int v) { if (a < 0 || a > 65535) throw new Exception("Invalid memory access"); data[a] = v; } int* pointer() { return data.ptr; } } class Stack { private int[] stack; private int top; private int capacity; this(int capacity) { this.capacity = capacity; stack = new int[capacity]; top = -1; } bool isEmpty() { return top == -1; } bool isFull() { return top == capacity - 1; } void push(int value) { if (isFull()) throw new Exception("Stack overflow"); stack[++top] = value; } int pop() { if (isEmpty()) throw new Exception("Stack underflow"); return stack[top--]; } void dup() { if (isEmpty()) throw new Exception("Stack is empty"); if (isFull()) throw new Exception("Stack overflow"); push(stack[top]); } void swap() { if (top < 1) throw new Exception("Insufficient elements to swap"); int temp = stack[top]; stack[top] = stack[top - 1]; stack[top - 1] = temp; } int depth() { return top + 1; } void print() { for (int i = top; i >= 0; i--) { writeln(stack[i]); } } }