commit 7e58ad3d90671acdfb916c029c20f648dbb8e421
Author: Pavel Renev <an2qzavok@gmail.com>
Date: Mon, 22 Mar 2021 07:53:15 +0000
initial commit
Diffstat:
A | asm.c | | | 169 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
A | hw.va | | | 7 | +++++++ |
A | mkfile | | | 12 | ++++++++++++ |
A | run.c | | | 38 | ++++++++++++++++++++++++++++++++++++++ |
A | vsm.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;
+}