ilo-vm/source/ilo-windows.c

141 lines
3.7 KiB
C

/* ilo-windows.c (c) 2022, charles childers */
#include <stdio.h>
#include <fcntl.h>
int ip, sp, rp, data[33], address[257], memory[65536];
char *blocks, *rom;
#define T data[sp]
#define N data[sp-1]
#define R address[rp]
int pop() { return data[(--sp) + 1]; }
void push(int value) { data[++sp] = value; }
void prepare_vm() { ip = sp = rp = 0; }
void load_image() {
int fp;
fp = open(rom, O_RDONLY, 0666);
if (!fp) return;
read(fp, &memory, 65536 * sizeof(int));
close(fp);
prepare_vm();
}
void save_image() {
int fp;
fp = open(rom, O_WRONLY, 0666);
write(fp, &memory, 65536 * sizeof(int));
close(fp);
}
void read_block() {
int f, block, buffer;
buffer = pop();
block = pop();
f = open(blocks, O_RDONLY, 0666);
lseek(f, 4096 * block, SEEK_SET);
read(f, memory + buffer, 1024 * 4);
close(f);
}
void write_block() {
int f, block, buffer;
buffer = pop();
block = pop();
f = open(blocks, O_WRONLY, 0666);
lseek(f, 4096 * block, SEEK_SET);
write(f, memory + buffer, 4096);
close(f);
}
void process(int o) {
int a, b, target, src, dest, len;
switch (o) {
case 0: break;
case 1: ip++; push(memory[ip]); break;
case 2: push(T); break;
case 3: data[sp] = 0; sp--; break;
case 4: a = T; T = N; N = a; break;
case 5: rp++; R = pop(); break;
case 6: push(R); rp--; break;
case 7: ip = pop() - 1; break;
case 8: rp++; R = ip; ip = pop() - 1; break;
case 9: target = pop();
if (pop() != 0) { rp++; R = ip; ip = target - 1; }
break;
case 10: target = pop();
if (pop() != 0) ip = target - 1; break;
case 11: ip = R; rp--; break;
case 12: N = (N == T) ? -1 : 0; sp--; break;
case 13: N = (N != T) ? -1 : 0; sp--; break;
case 14: N = (N < T) ? -1 : 0; sp--; break;
case 15: N = (N > T) ? -1 : 0; sp--; break;
case 16: T = memory[T]; break;
case 17: memory[T] = N; sp--; sp--; break;
case 18: N += T; sp--; break;
case 19: N -= T; sp--; break;
case 20: N *= T; sp--; break;
case 21: a = T; b = N; T = b / a; N = b % a; break;
case 22: N = T & N; sp--; break;
case 23: N = T | N; sp--; break;
case 24: N = T ^ N; sp--; break;
case 25: N = N << T; sp--; break;
case 26: N = N >> T; sp--; break;
case 27: len = pop(); dest = pop();
src = pop(); push(-1);
while (len) {
if (memory[dest] != memory[src]) T = 0;
len -= 1; src += 1; dest += 1;
}
break;
case 28: len = pop(); dest = pop();
src = pop();
while (len) {
memory[dest] = memory[src];
len -= 1; src += 1; dest += 1;
}
break;
case 29: switch (pop()) {
case 0: putc(pop(), stdout); break;
case 1: push(getc(stdin)); break;
case 2: read_block(); break;
case 3: write_block(); break;
case 4: save_image(); break;
case 5: load_image(); ip = -1; break;
case 6: ip = 65536; break;
case 7: push(sp); push(rp); break;
default: break;
}
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[ip]);
ip++;
}
}
void dump_stack() {
for (; sp > 0; sp--) printf(" %d", data[sp]); printf("\n");
}
int main(int argc, char **argv) {
blocks = (argc > 1) ? argv[1] : "ilo.blocks";
rom = (argc > 2) ? argv[2] : "ilo.rom";
load_image();
execute();
dump_stack();
}