diff --git a/source/ilo-fast.c b/source/ilo-fast.c new file mode 100644 index 0000000..48106c8 --- /dev/null +++ b/source/ilo-fast.c @@ -0,0 +1,180 @@ +/*************************************************************** + 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 +#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 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; +}