/*************************************************************** crc's _ _ (_) | ___ | | |/ _ \ a tiny virtual computer | | | (_) | 64kw RAM, 32-bit, Dual Stack, MISC |_|_|\___/ ilo.d (c) charles childers **************************************************************/ import std.stdio; int ip; /* instruction pointer */ int sp; /* data stack pointer */ int rp; /* address stack pointer */ int[33] ds; /* data stack */ int[257] as; /* address stack */ int[65536] m; /* memory */ FILE *file; /* file stream for block i/o */ string blocks; /* name of block file (ilo.blocks) */ string rom; /* name of image (ilo.rom) */ /* the other variables are used by the various functions for misc. purposes */ int a, b, f, s, d, l; void push(int v) { ds[sp + 1] = v; sp += 1; } int pop() { sp -= 1; return ds[sp + 1]; } void load_image() { file = fopen(rom.ptr, "rb"); if (file is null) { return; } fread(m.ptr, 1, 65536 * 4, file); fclose(file); ip = sp = rp = 0; } void save_image() { file = fopen(rom.ptr, "wb"); fwrite(m.ptr, 1, 65536 * 4, file); fclose(file); } void block_common() { b = pop(); /* block buffer */ a = pop(); /* block number */ fseek(file, 4096 * a, SEEK_SET); } void read_block() { int[1024] block; file = fopen(blocks.ptr, "rb"); if (file is null) { return; } block_common(); fread(block.ptr, 1, 4096, file); foreach(i; 0 .. 1024) { m[b + i] = block[i]; } fclose(file); } void write_block() { int[1024] block; file = fopen(blocks.ptr, "r+b"); if (file is null) { return; } block_common(); foreach(i; 0 .. 1024) { block[i] = m[b + i]; } fwrite(block.ptr, 1, 4096, file); fclose(file); } void save_ip() { rp += 1; as[rp] = ip; } void li() { ip += 1; push(m[ip]); } void du() { push(ds[sp]); } void dr() { pop(); } void sw() { a = ds[sp]; ds[sp] = ds[sp-1]; ds[sp-1] = a; } void pu() { rp += 1; as[rp] = pop(); } void po() { push(as[rp]); rp -= 1; } void ju() { ip = pop() - 1; } void ca() { save_ip(); ip = pop() - 1; } void cc() { a = pop(); if (pop()) { save_ip(); ip = a - 1; } } void cj() { a = pop(); if (pop()) { ip = a - 1; } } void re() { ip = as[rp]; rp -= 1; } void eq() { ds[sp-1] = (ds[sp-1] == ds[sp]) ? -1 : 0; sp -= 1; } void ne() { ds[sp-1] = (ds[sp-1] != ds[sp]) ? -1 : 0; sp -= 1; } void lt() { ds[sp-1] = (ds[sp-1] < ds[sp]) ? -1 : 0; sp -= 1; } void gt() { ds[sp-1] = (ds[sp-1] > ds[sp]) ? -1 : 0; sp -= 1; } void fe() { ds[sp] = m[ds[sp]]; } void st() { m[ds[sp]] = ds[sp-1]; sp -= 2; } void ad() { ds[sp-1] += ds[sp]; sp -= 1; } void su() { ds[sp-1] -= ds[sp]; sp -= 1; } void mu() { ds[sp-1] *= ds[sp]; sp -= 1; } void di() { a = ds[sp]; b = ds[sp-1]; ds[sp] = b / a; ds[sp-1] = b % a; } void an() { ds[sp-1] = ds[sp-1] & ds[sp]; sp -= 1; } void or() { ds[sp-1] = ds[sp-1] | ds[sp]; sp -= 1; } void xo() { ds[sp-1] = ds[sp-1] ^ ds[sp]; sp -= 1; } void sl() { ds[sp-1] = ds[sp-1] << ds[sp]; sp -= 1; } void sr() { ds[sp-1] = ds[sp-1] >> ds[sp]; sp -= 1; } void cp() { l = pop(); d = pop(); s = ds[sp]; ds[sp] = -1; while (l) { if (m[d] != m[s]) { ds[sp] = 0; } l -= 1; s += 1; d += 1; } } void cy() { l = pop(); d = pop(); s = pop(); while (l) { m[d] = m[s]; l -= 1; s += 1; d += 1; } } void ioa() { writef("%c", cast(char)pop()); } void iob() { 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() { push(sp); push(rp); } void io() { switch (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; } } /* Using a switch here instead of a jump table to avoid */ /* some issues w/relocation stuff when building w/o libc */ 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) { // writef("%d:%d, %d %d\n", ip, m[ip], sp, rp); process_bundle(m[ip]); ip += 1; } } void main(string[] args) { blocks = "ilo.blocks"; rom = "ilo.rom"; load_image(); execute(); foreach (i; 1 .. sp + 1) { writef(" %d", ds[sp]); sp--; } writef("\n"); }