/*********************************** ilo-plan9.c (C) Jim Taylor Example compilation (amd64): 6c ilo-plan9.c 6l -o ilo ilo-plan9.6 May want to run it with vt. ***********************************/ #include #include #define T ds[sp] /* Top of Data Stack */ #define N ds[sp-1] /* Next on Data Stack */ #define R as[rp] /* Top of Address Stack */ #define INST(c_name); void c_name(void) /* Shorthand for VM INSTructions */ int ip, /* instruction pointer */ sp, /* data stack pointer */ rp, /* address stack pointer */ ds[33], /* data stack */ as[257], /* address stack */ m[65536]; /* memory */ char *blocks, /* name of block file (ilo.blocks) */ *rom; /* name of image (ilo.rom) */ int a, b, fd, s, d, l; char i[1]; void push(int v) { ds[sp+1] = v; sp += 1; } int pop(void) { sp -= 1; return ds[sp+1]; } void load_image(void) { fd = open(rom, OREAD); if(!fd) return; read(fd, &m, 65536*4); close(fd); ip = sp = rp = 0; } void save_image(void) { fd = open(rom, OWRITE); write(fd, &m, 65536*4); close(fd); } void block_common(void) { b = pop(); /* block buffer */ a = pop(); /* block number */ seek(fd, 4096*a, 0); } void read_block(void) { fd = open(blocks, OREAD); block_common(); read(fd, m+b, 4096); close(fd); } void write_block(void) { fd = open(blocks, OWRITE); block_common(); write(fd, m+b, 4096); close(fd); } void save_ip(void) { rp += 1; R = ip; } void symmetric(void) { if (b >= 0 && N < 0) { T += 1; N -= b; } } INST(li) { ip += 1; push(m[ip]); } INST(du) { push(T); } INST(dr) { ds[sp] = 0; sp -= 1; } INST(sw) { a = T; T = N; N = a; } INST(pu) { rp += 1; R = pop(); } INST(po) { push(R); rp -= 1; } INST(ju) { ip = pop() - 1; } INST(ca) { save_ip(); ip = pop() - 1; } INST(cc) { a = pop(); if (pop()) { save_ip(); ip = a - 1; } } INST(cj) { a = pop(); if (pop()) { ip = a - 1; } } INST(re) { ip = R; rp -= 1; } INST(eq) { N = (N == T) ? -1 : 0; sp -= 1; } INST(ne) { N = (N != T) ? -1 : 0; sp -= 1; } INST(lt) { N = (N < T) ? -1 : 0; sp -= 1; } INST(gt) { N = (N > T) ? -1 : 0; sp -= 1; } INST(fe) { T = m[T]; } INST(st) { m[T] = N; sp -= 2; } INST(ad) { N += T; sp -= 1; } INST(su) { N -= T; sp -= 1; } INST(mu) { N *= T; sp -= 1; } INST(di) { a = T; b = N; T = b / a; N = b % a; symmetric(); } INST(an) { N = T & N; sp -= 1; } INST(or) { N = T | N; sp -= 1; } INST(xo) { N = T ^ N; sp -= 1; } INST(sl) { N = N << T; sp -= 1; } INST(sr) { N = N >> T; sp -= 1; } INST(cp) { l = pop(); d = pop(); s = T; T = -1; while(l) { if (m[d] != m[s]) T = 0; l -= 1; s += 1; d += 1; } } INST(cy) { l = pop(); d = pop(); s = pop(); while(l) { m[d] = m[s]; l -= 1; s += 1; d += 1; } } INST(ioa) { i[0] = (char)pop(); write(1, &i, 1); } INST(iob) { read(0, &i, 1); push(i[0]); } INST(ioc) { read_block(); } INST(iod) { write_block(); } INST(ioe) { save_image(); } INST(iof) { load_image(); ip = -1; } INST(iog) { ip = 65536; } INST(ioh) { push(sp); push(rp); } INST(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; } } 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(void) { while(ip < 65536) { process_bundle(m[ip]); ip += 1; } } void main() { blocks = "ilo.blocks"; rom = "ilo.rom"; load_image(); execute(); exits(nil); }