vsm

virtual stack machine for plan9
git clone git://nsmpr.xyz/vsm.git
Log | Files | Refs

commit 7e58ad3d90671acdfb916c029c20f648dbb8e421
Author: Pavel Renev <an2qzavok@gmail.com>
Date:   Mon, 22 Mar 2021 07:53:15 +0000

initial commit

Diffstat:
Aasm.c | 169+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Ahw.va | 7+++++++
Amkfile | 12++++++++++++
Arun.c | 38++++++++++++++++++++++++++++++++++++++
Avsm.c | 208+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
5 files changed, 434 insertions(+), 0 deletions(-)

diff --git a/asm.c b/asm.c @@ -0,0 +1,169 @@ +#include <u.h> +#include <libc.h> + +#include "vsm.h" + +typedef struct Label Label; +struct Label { + char *name; + CELL addr; +}; + +Label *labels = nil; +long lc = 0; + +char **tokens = nil; +long memc = 0; + +void +usage(void) +{ + fprint(2, "usage: %s code.va\n", argv0); + exits("usage"); +} + +void +pushtoken(char *t) +{ + tokens = realloc(tokens, (memc + 1) * sizeof(char*)); + tokens[memc] = strdup(t); + memc++; +} + +void +pushtokens(char *buf) +{ + char **argv; + int i, argc; + argv = malloc(sizeof(char*) * 32); + argc = tokenize(buf, argv, 32); + for (i = 0; i < argc; i++) pushtoken(argv[i]); + free(argv); +} + +void +pushlabel(char *name, CELL addr) +{ + labels = realloc(labels, sizeof(Label) * (lc+1)); + labels[lc].name = strdup(name); + labels[lc].addr = addr; + lc++; +} + +void +pass1(char *fname) +{ + int fid; + int lcount; + char buf[256], *bp; + fid = open(fname, OREAD); + if (fid < 0) { + fprint(2, "failed to open file %s\n", fname); + exits("no file"); + } + lcount = 1; + bp = buf; + while((read(fid, bp, 1)) > 0) + { + if (*bp == '\n'){ + *bp = 0; + switch(buf[0]){ + case 0: + /* empty line, do nothing */ + case '`': + /* comment, do nothing */ + break; + case ':': + /* label */ + pushlabel(buf + 2, memc); + break; + case '\t': + case ' ': + /* tokens */ + pushtokens(buf); + break; + default: + fprint(2, "%s:%d unknown directive: %s\n", + fname, lcount, buf); + exits("bad source"); + } + lcount++; + bp = buf; + } + else { + bp++; + } + } + close(fid); +} + +int +label(char *s) +{ + int i; + for (i = 0; i < lc; i++) { + if (strncmp(s, labels[i].name, 2) == 0) { + write(1, &labels[i].addr, sizeof(CELL)); + return 0; + } + } + return -1; +} + +int +number(char *s) +{ + CELL n; + char *p; + n = strtol(s, &p, 10); + if (p == s) return -1; + write(1, &n, sizeof(CELL)); + return 0; +} + +void +pass2(void) +{ + int i; + for (i = 0; i < memc; i++) { + if (label(tokens[i]) == 0) continue; + if (number(tokens[i]) < 0) { + fprint(2, "addr:%d not a number: %s\n", + i, tokens[i]); + exits("bad source"); + } + } +} + +void +main(int argc, char **argv) +{ + ARGBEGIN{ + default: + usage(); + break; + }ARGEND + if (argc != 1) usage(); + + pushlabel("no", VSM_NOP); + pushlabel("ad", VSM_ADD); + pushlabel("su", VSM_SUB); + pushlabel("an", VSM_AND); + pushlabel("or", VSM_OR); + pushlabel("xo", VSM_XOR); + pushlabel("dr", VSM_DROP); + pushlabel("du", VSM_DUP); + pushlabel("ov", VSM_OVER); + pushlabel("sw", VSM_SWAP); + pushlabel("to", VSM_TOR); + pushlabel("fr", VSM_FROMR); + pushlabel("st", VSM_STORE); + pushlabel("fe", VSM_FETCH); + pushlabel("li", VSM_LIT); + pushlabel("if", VSM_IF); + pushlabel("ca", VSM_CALL); + pushlabel("ex", VSM_EXIT); + + pass1(argv[0]); + pass2(); +} diff --git a/hw.va b/hw.va @@ -0,0 +1,7 @@ +` hello world program + + li 3 + li 2 + li 1 + ad + ad diff --git a/mkfile b/mkfile @@ -0,0 +1,12 @@ +</$objtype/mkfile + +TARG=run\ + asm + +OFILES=\ + vsm.$O\ + +HFILES=vsm.h + +BIN=/$objtype/bin +</sys/src/cmd/mkmany diff --git a/run.c b/run.c @@ -0,0 +1,38 @@ +#include <u.h> +#include <libc.h> + +#include "vsm.h" +void +usage(void) +{ + fprint(2, "usage: %s imgfile\n", argv0); + exits("usage"); +} + +void +stackdump(CELL *st, CELL *sp) +{ + for (st++; st <= sp; st++) { + print("%d ", *st); + } +} + +void +main(int argc, char **argv) +{ + ARGBEGIN{ + default: + usage(); + break; + }ARGEND + if (argc != 1) usage(); + vsm_readimage(argv[0]); + vsm_reset(); + vsm_run(); + print("dstack:\n "); + stackdump(dstack, dsp); + print("\nrstack:\n "); + stackdump(rstack, rsp); + print("\n"); + +} diff --git a/vsm.c b/vsm.c @@ -0,0 +1,208 @@ +#include <u.h> +#include <libc.h> + +#include "vsm.h" + +/* Instructions */ +void i_NOP(void) +{ +} + +/* ALU: */ +void i_ADD(void) +{ + *(dsp - 1) += *dsp; + dsp--; +} + +void i_SUB(void) +{ + *(dsp - 1) -= *dsp; + dsp--; +} + +void i_AND(void) +{ + *(dsp - 1) &= *dsp; + dsp++; +} + +void i_OR(void) +{ + *(dsp - 1) |= *dsp; + dsp++; +} + +void i_XOR(void) +{ + *(dsp - 1) ^= *dsp; + dsp++; +} + + +/* Stack Manipulation: */ +void i_DROP(void) +{ + dsp--; +} + +void i_DUP(void) +{ + *(dsp + 1) = *dsp; + dsp++; +} + +void i_OVER(void) +{ + *(dsp + 1) = *(dsp - 1); + dsp++; +} + +void i_SWAP(void) +{ + *(rsp + 1) = *dsp; + *dsp = *(dsp - 1); + *(dsp - 1) = *(rsp + 1); +} + +void i_TOR(void) +{ + *(rsp + 1) = *dsp; + rsp++; + dsp--; +} + +void i_FROMR(void) +{ + *(dsp + 1) = *rsp; + rsp--; + dsp++; +} + +/* Memory Management: */ +void i_STORE(void) +{ + ram[*dsp] = *(dsp - 1); + dsp -= 2; +} + +void i_FETCH(void) +{ + *dsp = ram[*dsp]; +} + +/* Literals: */ +void i_LIT(void) +{ + *(dsp + 1) = ram[pc + 1]; + dsp++; + pc++; +} + +/* Conditional Branching: */ +void i_IF(void) +{ + if (dsp == 0) pc = ram[pc]; + else pc++; + dsp--; +} + +/* Subroutine Calls: */ +void i_CALL(void) +{ + *(rsp + 1) = pc; + rsp++; + pc = *dsp; + dsp--; +} + +void i_EXIT(void) +{ + pc = *rsp; + rsp--; +} + +instruction instructions[128] = { + [VSM_NOP] i_NOP, + [VSM_ADD] i_ADD, + [VSM_SUB] i_SUB, + [VSM_AND] i_AND, + [VSM_OR] i_OR, + [VSM_XOR] i_XOR, + [VSM_DROP] i_DROP, + [VSM_DUP] i_DUP, + [VSM_OVER] i_OVER, + [VSM_SWAP] i_SWAP, + [VSM_TOR] i_TOR, + [VSM_FROMR] i_FROMR, + [VSM_STORE] i_STORE, + [VSM_FETCH] i_FETCH, + [VSM_LIT] i_LIT, + [VSM_IF] i_IF, + [VSM_CALL] i_CALL, + [VSM_EXIT] i_EXIT, +}; + +/* VMS Control */ + +void +vsm_reset(void) +{ + //CELL i; + //for (i = 0; i < IMAGE_SIZE; i++) ram[i] = VSM_NOP; + pc = 0; + dsp = dstack; + rsp = rstack; +} + +void +vsm_exec(CELL op) +{ + instructions[op](); + pc++; +} + +void +vsm_halt(void) +{ +} + +void +vsm_run(void) +{ + for (;;) { + /* TODO: put more sanity checks here */ + CELL op = ram[pc]; + if (op >= NUM_OPS) { + fprint(2, "invalid op == %x\n", op); + vsm_halt(); + return; + } + if (pc >= IMAGE_SIZE) { + fprint(2, "pc reached end of the image\n"); + vsm_halt(); + return; + } + vsm_exec(op); + } +} + +int +vsm_readimage(char *path) +{ + char buf[64]; + CELL n; + CELL *mp; + int fd; + fd = open(path, OREAD); + if (fd <= 0) return -1; + mp = ram; + while((n = read(fd, buf, 64)) > 0){ + memcpy(mp, buf, n); + mp += n/sizeof(CELL); + if (mp >= ram + IMAGE_SIZE) + sysfatal("file bigger than image size"); + } + close(fd); + return 0; +}