206 lines
4.4 KiB
C
206 lines
4.4 KiB
C
|
/***********************************
|
||
|
ilo-plan9.c (C) Jim Taylor
|
||
|
|
||
|
Example compilation (amd64):
|
||
|
6c ilo-plan9.c
|
||
|
6l -o ilo ilo-plan9.6
|
||
|
|
||
|
May want to run it with vt.
|
||
|
***********************************/
|
||
|
|
||
|
#include <u.h>
|
||
|
#include <libc.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 INST(c_name); void c_name(void) /* Shorthand for VM INSTructions */
|
||
|
|
||
|
int ip, /* instruction pointer */
|
||
|
sp, /* data stack pointer */
|
||
|
rp, /* address stack pointer */
|
||
|
ds[33], /* data stack */
|
||
|
as[257], /* address stack */
|
||
|
m[65536]; /* memory */
|
||
|
|
||
|
char *blocks, /* name of block file (ilo.blocks) */
|
||
|
*rom; /* name of image (ilo.rom) */
|
||
|
|
||
|
int a, b, fd, s, d, l;
|
||
|
char i[1];
|
||
|
|
||
|
void
|
||
|
push(int v)
|
||
|
{
|
||
|
ds[sp+1] = v;
|
||
|
sp += 1;
|
||
|
}
|
||
|
|
||
|
int
|
||
|
pop(void)
|
||
|
{
|
||
|
sp -= 1;
|
||
|
return ds[sp+1];
|
||
|
}
|
||
|
|
||
|
void
|
||
|
load_image(void)
|
||
|
{
|
||
|
fd = open(rom, OREAD);
|
||
|
if(!fd)
|
||
|
return;
|
||
|
read(fd, &m, 65536*4);
|
||
|
close(fd);
|
||
|
ip = sp = rp = 0;
|
||
|
}
|
||
|
|
||
|
void
|
||
|
save_image(void)
|
||
|
{
|
||
|
fd = open(rom, OWRITE);
|
||
|
write(fd, &m, 65536*4);
|
||
|
close(fd);
|
||
|
}
|
||
|
|
||
|
void
|
||
|
block_common(void)
|
||
|
{
|
||
|
b = pop(); /* block buffer */
|
||
|
a = pop(); /* block number */
|
||
|
seek(fd, 4096*a, 0);
|
||
|
}
|
||
|
|
||
|
void
|
||
|
read_block(void)
|
||
|
{
|
||
|
fd = open(blocks, OREAD);
|
||
|
block_common();
|
||
|
read(fd, m+b, 4096);
|
||
|
close(fd);
|
||
|
}
|
||
|
|
||
|
void
|
||
|
write_block(void)
|
||
|
{
|
||
|
fd = open(blocks, OWRITE);
|
||
|
block_common();
|
||
|
write(fd, m+b, 4096);
|
||
|
close(fd);
|
||
|
}
|
||
|
|
||
|
void save_ip(void) { rp += 1; R = ip; }
|
||
|
void symmetric(void) { if (b >= 0 && N < 0) { T += 1; N -= b; } }
|
||
|
|
||
|
INST(li) { ip += 1; push(m[ip]); }
|
||
|
INST(du) { push(T); }
|
||
|
INST(dr) { ds[sp] = 0; sp -= 1; }
|
||
|
INST(sw) { a = T; T = N; N = a; }
|
||
|
INST(pu) { rp += 1; R = pop(); }
|
||
|
INST(po) { push(R); rp -= 1; }
|
||
|
INST(ju) { ip = pop() - 1; }
|
||
|
INST(ca) { save_ip(); ip = pop() - 1; }
|
||
|
INST(cc) { a = pop(); if (pop()) { save_ip(); ip = a - 1; } }
|
||
|
INST(cj) { a = pop(); if (pop()) { ip = a - 1; } }
|
||
|
INST(re) { ip = R; rp -= 1; }
|
||
|
INST(eq) { N = (N == T) ? -1 : 0; sp -= 1; }
|
||
|
INST(ne) { N = (N != T) ? -1 : 0; sp -= 1; }
|
||
|
INST(lt) { N = (N < T) ? -1 : 0; sp -= 1; }
|
||
|
INST(gt) { N = (N > T) ? -1 : 0; sp -= 1; }
|
||
|
INST(fe) { T = m[T]; }
|
||
|
INST(st) { m[T] = N; sp -= 2; }
|
||
|
INST(ad) { N += T; sp -= 1; }
|
||
|
INST(su) { N -= T; sp -= 1; }
|
||
|
INST(mu) { N *= T; sp -= 1; }
|
||
|
INST(di) { a = T; b = N; T = b / a; N = b % a; symmetric(); }
|
||
|
INST(an) { N = T & N; sp -= 1; }
|
||
|
INST(or) { N = T | N; sp -= 1; }
|
||
|
INST(xo) { N = T ^ N; sp -= 1; }
|
||
|
INST(sl) { N = N << T; sp -= 1; }
|
||
|
INST(sr) { N = N >> T; sp -= 1; }
|
||
|
INST(cp)
|
||
|
{
|
||
|
l = pop(); d = pop();
|
||
|
s = T; T = -1;
|
||
|
while(l) {
|
||
|
if (m[d] != m[s])
|
||
|
T = 0;
|
||
|
l -= 1; s += 1; d += 1;
|
||
|
}
|
||
|
}
|
||
|
INST(cy)
|
||
|
{
|
||
|
l = pop(); d = pop(); s = pop();
|
||
|
while(l) {
|
||
|
m[d] = m[s]; l -= 1; s += 1; d += 1;
|
||
|
}
|
||
|
}
|
||
|
INST(ioa) { i[0] = (char)pop(); write(1, &i, 1); }
|
||
|
INST(iob) { read(0, &i, 1); push(i[0]); }
|
||
|
INST(ioc) { read_block(); }
|
||
|
INST(iod) { write_block(); }
|
||
|
INST(ioe) { save_image(); }
|
||
|
INST(iof) { load_image(); ip = -1; }
|
||
|
INST(iog) { ip = 65536; }
|
||
|
INST(ioh) { push(sp); push(rp); }
|
||
|
INST(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;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void
|
||
|
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;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void
|
||
|
process_bundle(int opcode)
|
||
|
{
|
||
|
process(opcode & 0xFF);
|
||
|
process((opcode >> 8) & 0xFF);
|
||
|
process((opcode >> 16) & 0xFF);
|
||
|
process((opcode >> 24) & 0xFF);
|
||
|
}
|
||
|
|
||
|
void
|
||
|
execute(void)
|
||
|
{
|
||
|
while(ip < 65536) {
|
||
|
process_bundle(m[ip]);
|
||
|
ip += 1;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void
|
||
|
main()
|
||
|
{
|
||
|
blocks = "ilo.blocks";
|
||
|
rom = "ilo.rom";
|
||
|
load_image();
|
||
|
execute();
|
||
|
exits(nil);
|
||
|
}
|