vsm

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

vsm.c (2833B)


      1 #include <u.h>
      2 #include <libc.h>
      3 
      4 #include "vsm.h"
      5 
      6 /* Instructions */
      7 void i_NOP(void)
      8 {
      9 }
     10 
     11 /* ALU: */
     12 void i_ADD(void)
     13 {
     14 	*(dsp - 1) += *dsp;
     15 	dsp--;
     16 }
     17 
     18 void i_SUB(void)
     19 {
     20 	*(dsp - 1) -= *dsp;
     21 	dsp--;
     22 }
     23 
     24 void i_AND(void)
     25 {
     26 	*(dsp - 1) &= *dsp;
     27 	dsp++;
     28 }
     29 
     30 void i_OR(void)
     31 {
     32 	*(dsp - 1) |= *dsp;
     33 	dsp++;
     34 }
     35 
     36 void i_XOR(void)
     37 {
     38 	*(dsp - 1) ^= *dsp;
     39 	dsp++;
     40 }
     41 
     42 
     43 /* Stack Manipulation: */
     44 void i_DROP(void)
     45 {
     46 	dsp--;
     47 }
     48 
     49 void i_DUP(void)
     50 {
     51 	*(dsp + 1) = *dsp;
     52 	dsp++;
     53 }
     54 
     55 void i_OVER(void)
     56 {
     57 	*(dsp + 1) = *(dsp - 1);
     58 	dsp++;
     59 }
     60 
     61 void i_SWAP(void)
     62 {
     63 	*(rsp + 1) = *dsp;
     64 	*dsp = *(dsp - 1);
     65 	*(dsp - 1) = *(rsp + 1);
     66 }
     67 
     68 void i_TOR(void)
     69 {
     70 	*(rsp + 1) = *dsp;
     71 	rsp++;
     72 	dsp--;
     73 }
     74 
     75 void i_FROMR(void)
     76 {
     77 	*(dsp + 1) = *rsp;
     78 	rsp--;
     79 	dsp++;
     80 }
     81 
     82 /* Memory Management: */
     83 void i_STORE(void)
     84 {
     85 	mapset(*dsp, dsp - 1);
     86 	dsp -= 2;
     87 }
     88 
     89 void i_FETCH(void)
     90 {
     91 	CELL *r;
     92 	r = mapget(*dsp);
     93 	if (r != nil) *dsp = *r;
     94 	else *dsp = 0;
     95 }
     96 
     97 /* Literals: */
     98 void i_LIT(void)
     99 {
    100 	CELL *r;
    101 	r = mapget(pc + 1);
    102 	if (r != nil) *(dsp + 1) = *r;
    103 	else {
    104 		*(dsp + 1) = 0;
    105 	}
    106 	dsp++;
    107 	pc++;
    108 }
    109 
    110 /* Conditional Branching: */
    111 void i_IF(void)
    112 {
    113 	if (*dsp == 0) pc = *(dsp - 1) - 1;
    114 	dsp -= 2;
    115 }
    116 
    117 /* Subroutine Calls: */
    118 void i_CALL(void)
    119 {
    120 	*(rsp + 1) = pc;
    121 	rsp++;
    122 	pc = *dsp;
    123 	dsp--;
    124 }
    125 
    126 void i_EXIT(void)
    127 {
    128 	pc = *rsp;
    129 	rsp--;	
    130 }
    131 
    132 /* "Hardware" IO */
    133 
    134 void i_PUTC(void)
    135 {
    136 	write(1, dsp--, 1);
    137 }
    138 
    139 void i_GETC(void)
    140 {
    141 	read(0, ++dsp, 1);
    142 }
    143 
    144 instruction instructions[128] = {
    145 	[VSM_NOP] i_NOP,
    146 	[VSM_ADD] i_ADD,
    147 	[VSM_SUB] i_SUB,
    148 	[VSM_AND] i_AND,
    149 	[VSM_OR] i_OR,
    150 	[VSM_XOR] i_XOR,
    151 	[VSM_DROP] i_DROP,
    152 	[VSM_DUP] i_DUP,
    153 	[VSM_OVER] i_OVER,
    154 	[VSM_SWAP] i_SWAP,
    155 	[VSM_TOR] i_TOR,
    156 	[VSM_FROMR] i_FROMR,
    157 	[VSM_STORE] i_STORE,
    158 	[VSM_FETCH] i_FETCH,
    159 	[VSM_LIT] i_LIT,
    160 	[VSM_IF] i_IF,
    161 	[VSM_CALL] i_CALL,
    162 	[VSM_EXIT] i_EXIT,
    163 	[VSM_PUTC] i_PUTC,
    164 	[VSM_GETC] i_GETC,
    165 };
    166 
    167 /* VMS Control */
    168 
    169 void
    170 vsm_reset(void)
    171 {
    172 	pc = 0;
    173 	dsp = dstack;
    174 	rsp = rstack;
    175 }
    176 
    177 void
    178 vsm_exec(CELL op)
    179 {
    180 	instructions[op]();
    181 	pc++;
    182 }
    183 
    184 
    185 void
    186 vsm_run(void)
    187 {
    188 	CELL op;
    189 	for (;;) {
    190 		/* TODO: put more sanity checks here */
    191 		if (dsp < dstack) {
    192 			fprint(2, "dstack underflow\n");
    193 			return;
    194 		}
    195 		if (rsp < rstack) {
    196 			fprint(2, "rstack underflow\n");
    197 			return;
    198 		}
    199 		if (pc >= IMAGE_SIZE) {
    200 			fprint(2, "pc reached end of the image\n");
    201 			return;
    202 		}
    203 
    204 		op = ram[pc];
    205 
    206 
    207 		if (op >= NUM_OPS) {
    208 			fprint(2, "invalid op == %d\n", op);
    209 			return;
    210 		}
    211 		vsm_exec(op);
    212 	}
    213 }
    214 
    215 int
    216 vsm_readimage(char *path)
    217 {
    218 	char buf[64];
    219 	CELL n;
    220 	CELL *mp;
    221 	int fd;
    222 	fd = open(path, OREAD);
    223 	if (fd <= 0) return -1;
    224 	mp = ram;
    225 	while((n = read(fd, buf, 64)) > 0){
    226 		if (mp + n/sizeof(CELL) >= ram + IMAGE_SIZE)
    227 			sysfatal("file bigger than image size");
    228 
    229 		memcpy(mp, buf, n);
    230 		mp += n/sizeof(CELL);
    231 	}
    232 	close(fd);
    233 
    234 	int i;
    235 	for (i = 0; i < IMAGE_SIZE; i++) {
    236 		if (ram[i] == 0) break;
    237 		mapset(i, ram + i);
    238 	}
    239 
    240 	return 0;
    241 }