ilo-vm/source/ilo.cxx

187 lines
4.9 KiB
C++

/***************************************************************
crc's _ _
(_) | ___
| | |/ _ \ a tiny virtual computer
| | | (_) | 64kw RAM, 32-bit, Dual Stack, MISC
|_|_|\___/ ilo.cxx (c) charles childers
**************************************************************/
#include <iostream>
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
/* ip instruction pointer
sp data stack pointer
rp address stack pointer
ds data stack (32 values)
as address stack (256 values)
m memory (65,536 values)
rom name of image (default to ilo.rom)
blocks name of block file (default to ilo.blocks)
the other variables are used by the various functions for
misc. purposes
*/
int ip, sp, rp, ds[33], as[257], m[65536];
int a, b, t, fp, block, buffer, src, dest, len;
char *blocks, *rom, iob[2];
/* T is top of stack
N is next on stack
R is top of address stack
V is void
*/
#define T ds[sp]
#define N ds[sp-1]
#define R as[rp]
#define V void
int pop() { sp -= 1; return ds[sp + 1]; }
V push(int value) { sp += 1; ds[sp] = value; }
V prepare_vm() { ip = sp = rp = 0; }
V load_image() {
fp = open(rom, O_RDONLY, 0666);
if (!fp) { return; };
read(fp, &m, 65536 * 4);
close(fp);
prepare_vm();
}
V save_image() {
fp = open(rom, O_WRONLY, 0666);
write(fp, &m, 65536 * 4);
close(fp);
}
V block_common() {
buffer = pop();
block = pop();
lseek(fp, 4096 * block, SEEK_SET);
}
V read_block() {
fp = open(blocks, O_RDONLY, 0666);
block_common();
read(fp, m + buffer, 4096);
close(fp);
}
V write_block() {
fp = open(blocks, O_WRONLY, 0666);
block_common();
write(fp, m + buffer, 4096);
close(fp);
}
V save_ip() { rp += 1; R = ip; }
V symmetric() { if (b >= 0 && N < 0) { T++; N -= b; } }
V li() { ip += 1; push(m[ip]); }
V du() { push(T); }
V dr() { ds[sp] = 0; sp -= 1; }
V sw() { a = T; T = N; N = a; }
V pu() { rp += 1; R = pop(); }
V po() { push(R); rp -= 1; }
V ju() { ip = pop() - 1; }
V ca() { save_ip(); ip = pop() - 1; }
V cc() { t = pop(); if (pop()) { save_ip(); ip = t - 1; } }
V cj() { t = pop(); if (pop()) { ip = t - 1; } }
V re() { ip = R; rp -= 1; }
V eq() { N = (N == T) ? -1 : 0; sp -= 1; }
V ne() { N = (N != T) ? -1 : 0; sp -= 1; }
V lt() { N = (N < T) ? -1 : 0; sp -= 1; }
V gt() { N = (N > T) ? -1 : 0; sp -= 1; }
V fe() { T = m[T]; }
V st() { m[T] = N; sp -= 2; }
V ad() { N += T; sp -= 1; }
V su() { N -= T; sp -= 1; }
V mu() { N *= T; sp -= 1; }
V di() { a = T; b = N; T = b / a; N = b % a; symmetric(); }
V an() { N = T & N; sp -= 1; }
V or_() { N = T | N; sp -= 1; }
V xo() { N = T ^ N; sp -= 1; }
V sl() { N = N << T; sp -= 1; }
V sr() { N = N >> T; sp -= 1; }
V cp() { len = pop(); dest = pop(); src = pop(); push(-1);
while (len) {
if (m[dest] != m[src]) { T = 0; }
len -= 1; src += 1; dest += 1;
}
}
V cy() { len = pop(); dest = pop(); src = pop();
while (len) {
m[dest] = m[src];
len -= 1; src += 1; dest += 1;
}
}
V iowr() { iob[0] = pop(); write(1, &iob, 1); }
V iord() { read(0, &iob, 1); push(iob[0]); }
V iorb() { read_block(); }
V iowb() { write_block(); }
V iosi() { save_image(); }
V ioli() { load_image(); ip = -1; }
V ioen() { ip = 65536; }
V iost() { push(sp); push(rp); }
V io() {
switch (pop()) {
case 0: iowr(); break; case 1: iord(); break;
case 2: iorb(); break; case 3: iowb(); break;
case 4: iosi(); break; case 5: ioli(); break;
case 6: ioen(); break; case 7: iost(); break;
default: break;
}
}
/* Using a switch here instead of a jump table to avoid */
/* some issues w/relocation stuff when building w/o libc */
V 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;
}
}
V process_bundle(int opcode) {
process(opcode & 0xFF);
process((opcode >> 8) & 0xFF);
process((opcode >> 16) & 0xFF);
process((opcode >> 24) & 0xFF);
}
V execute() {
while (ip < 65536) {
process_bundle(m[ip]);
ip += 1;
}
}
int main(int argc, char **argv) {
blocks = (argc > 1) ? argv[1] : (char *)"ilo.blocks";
rom = (argc > 2) ? argv[2] : (char *)"ilo.rom";
load_image();
execute();
for (; sp > 0; sp -= 1)
std::cout << ds[sp] << ' ';
std::cout << '\n';
return 0;
}