181 lines
5.4 KiB
C
181 lines
5.4 KiB
C
|
/***************************************************************
|
||
|
crc's _ _
|
||
|
(_) | ___
|
||
|
| | |/ _ \ a tiny virtual computer
|
||
|
| | | (_) | 64kw RAM, 32-bit, Dual Stack, MISC
|
||
|
|_|_|\___/ ilo.c (c) charles childers
|
||
|
|
||
|
ilo-fast.c modifications (c) 2024 Christopher Leonard
|
||
|
|
||
|
Recommended compiler flags:
|
||
|
|
||
|
-O3 -fomit-frame-pointer -funroll-loops
|
||
|
-march=native -ftree-vectorize
|
||
|
|
||
|
**************************************************************/
|
||
|
|
||
|
#include <stdio.h>
|
||
|
#include <fcntl.h>
|
||
|
#include <unistd.h>
|
||
|
|
||
|
#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 V static void
|
||
|
#define I int
|
||
|
#define C char
|
||
|
|
||
|
static C *blocks, /* name of block file (ilo.blocks) */
|
||
|
*rom; /* name of image (ilo.rom) */
|
||
|
|
||
|
#define push(v) { ds[sp + 1] = (v); sp += 1; }
|
||
|
#define pop() ( sp -= 1, ds[sp + 1] )
|
||
|
|
||
|
#define load_image() { \
|
||
|
f = open(rom, O_RDONLY, 0666); \
|
||
|
if (!f) { return; }; \
|
||
|
read(f, &m, 65536 * 4); \
|
||
|
close(f); \
|
||
|
ip = sp = rp = 0; \
|
||
|
}
|
||
|
|
||
|
#define save_image() { \
|
||
|
f = open(rom, O_WRONLY, 0666); \
|
||
|
write(f, &m, 65536 * 4); \
|
||
|
close(f); \
|
||
|
}
|
||
|
|
||
|
#define block_common() { \
|
||
|
b = pop(); /* block buffer */ \
|
||
|
a = pop(); /* block number */ \
|
||
|
lseek(f, 4096 * a, SEEK_SET); \
|
||
|
}
|
||
|
|
||
|
#define read_block() { \
|
||
|
f = open(blocks, O_RDONLY, 0666); \
|
||
|
block_common(); \
|
||
|
read(f, m + b, 4096); \
|
||
|
close(f); \
|
||
|
}
|
||
|
|
||
|
#define write_block() { \
|
||
|
f = open(blocks, O_WRONLY, 0666); \
|
||
|
block_common(); \
|
||
|
write(f, m + b, 4096); \
|
||
|
close(f); \
|
||
|
}
|
||
|
|
||
|
#define save_ip() { rp += 1; R = ip; }
|
||
|
#define symmetric() { if (b >= 0 && N < 0) { T += 1; N -= b; } }
|
||
|
|
||
|
#define li() { ip += 1; push(m[ip]); }
|
||
|
#define du() { push(T); }
|
||
|
#define dr() { ds[sp] = 0; sp -= 1; }
|
||
|
#define sw() { a = T; T = N; N = a; }
|
||
|
#define pu() { rp += 1; R = pop(); }
|
||
|
#define po() { push(R); rp -= 1; }
|
||
|
#define ju() { ip = pop() - 1; }
|
||
|
#define ca() { save_ip(); ip = pop() - 1; }
|
||
|
#define cc() { a = pop(); if (pop()) { save_ip(); ip = a - 1; } }
|
||
|
#define cj() { a = pop(); if (pop()) { ip = a - 1; } }
|
||
|
#define re() { ip = R; rp -= 1; }
|
||
|
#define eq() { N = (N == T) ? -1 : 0; sp -= 1; }
|
||
|
#define ne() { N = (N != T) ? -1 : 0; sp -= 1; }
|
||
|
#define lt() { N = (N < T) ? -1 : 0; sp -= 1; }
|
||
|
#define gt() { N = (N > T) ? -1 : 0; sp -= 1; }
|
||
|
#define fe() { T = m[T]; }
|
||
|
#define st() { m[T] = N; sp -= 2; }
|
||
|
#define ad() { N += T; sp -= 1; }
|
||
|
#define su() { N -= T; sp -= 1; }
|
||
|
#define mu() { N *= T; sp -= 1; }
|
||
|
#define di() { a = T; b = N; T = b / a; N = b % a; symmetric(); }
|
||
|
#define an() { N = T & N; sp -= 1; }
|
||
|
#define or() { N = T | N; sp -= 1; }
|
||
|
#define xo() { N = T ^ N; sp -= 1; }
|
||
|
#define sl() { N = N << T; sp -= 1; }
|
||
|
#define sr() { N = N >> T; sp -= 1; }
|
||
|
#define cp() { l = pop(); d = pop(); s = T; T = -1; \
|
||
|
while (l) { if (m[d] != m[s]) { T = 0; } \
|
||
|
l -= 1; s += 1; d += 1; } }
|
||
|
#define cy() { l = pop(); d = pop(); s = pop(); \
|
||
|
while (l) { m[d] = m[s]; l -= 1; s += 1; d += 1; } }
|
||
|
#define ioa() { i[0] = (char)pop(); write(1, &i, 1); }
|
||
|
#define iob() { read(0, &i, 1); push(i[0]); }
|
||
|
#define ioc() { read_block(); }
|
||
|
#define iod() { write_block(); }
|
||
|
#define ioe() { save_image(); }
|
||
|
#define iof() { load_image(); ip = -1; }
|
||
|
#define iog() { ip = 65536; }
|
||
|
#define ioh() { push(sp); push(rp); }
|
||
|
#define 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 */
|
||
|
|
||
|
V execute() {
|
||
|
|
||
|
I ip, /* instruction pointer */
|
||
|
sp, /* data stack pointer */
|
||
|
rp, /* address stack pointer */
|
||
|
ds[33], /* data stack */
|
||
|
as[257], /* address stack */
|
||
|
m[65536]; /* memory */
|
||
|
|
||
|
/* the other variables are used by the various
|
||
|
functions for misc. purposes */
|
||
|
|
||
|
I a, b, f, s, d, l;
|
||
|
C i[1];
|
||
|
load_image();
|
||
|
for (; ip < 65536; ip++) {
|
||
|
I opcode = m[ip];
|
||
|
I bundle;
|
||
|
for (bundle = 0; bundle < 4; bundle++) {
|
||
|
I o = (opcode >> (8*bundle)) & 0xFF;
|
||
|
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;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
#if 0
|
||
|
#ifndef NOSTDLIB
|
||
|
for (; sp > 0; sp -= 1) printf(" %d", ds[sp]); printf("\n");
|
||
|
#endif
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
I main(I argc, C **argv) {
|
||
|
#ifndef NOSTDLIB
|
||
|
blocks = (argc > 1) ? argv[1] : "ilo.blocks";
|
||
|
rom = (argc > 2) ? argv[2] : "ilo.rom";
|
||
|
#else
|
||
|
blocks = "ilo.blocks";
|
||
|
rom = "ilo.rom";
|
||
|
#endif
|
||
|
execute();
|
||
|
return 0;
|
||
|
}
|