142 lines
3.7 KiB
C
142 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();
|
||
|
}
|