first commit
This commit is contained in:
222
vm/dec.c
Normal file
222
vm/dec.c
Normal file
@@ -0,0 +1,222 @@
|
||||
#include "vm.h"
|
||||
// 000 LO(MP) offset indirect from MP
|
||||
// 001 LO(FP) offset indirect from FP
|
||||
// 010 $OP 30 bit immediate
|
||||
// 011 none no operand
|
||||
// 100 SO(SO(MP)) double indirect from MP
|
||||
// 101 SO(SO(FP)) double indirect from FP
|
||||
// 110 reserved
|
||||
// 111 reserved
|
||||
|
||||
#define DIND(reg, xxx) (u8*)((*(WORD*)(R.reg+R.PC->xxx.f))+R.PC->xxx.s)
|
||||
|
||||
static void
|
||||
D09(void)
|
||||
{
|
||||
R.s = R.FP+R.PC->s.ind;
|
||||
R.d = R.FP+R.PC->d.ind;
|
||||
R.m = R.d;
|
||||
}
|
||||
static void
|
||||
D0A(void)
|
||||
{
|
||||
R.s = R.FP+R.PC->s.ind;
|
||||
R.d = (u8*)&R.PC->d.imm;
|
||||
R.m = R.d;
|
||||
}
|
||||
static void
|
||||
D0B(void)
|
||||
{
|
||||
R.s = R.FP+R.PC->s.ind;
|
||||
}
|
||||
static void
|
||||
D0D(void)
|
||||
{
|
||||
R.s = R.FP+R.PC->s.ind;
|
||||
R.d = DIND(FP, d);
|
||||
R.m = R.d;
|
||||
}
|
||||
static void
|
||||
D0F(void)
|
||||
{
|
||||
R.s = R.FP+R.PC->s.ind;
|
||||
}
|
||||
static void
|
||||
D11(void)
|
||||
{
|
||||
R.s = (u8*)&R.PC->s.imm;
|
||||
R.d = R.FP+R.PC->d.ind;
|
||||
R.m = R.d;
|
||||
}
|
||||
static void
|
||||
D15(void)
|
||||
{
|
||||
R.s = (u8*)&R.PC->s.imm;
|
||||
R.d = DIND(FP, d);
|
||||
R.m = R.d;
|
||||
}
|
||||
static void
|
||||
D1A(void)
|
||||
{
|
||||
R.d = (u8*)&R.PC->d.imm;
|
||||
R.m = R.d;
|
||||
}
|
||||
static void
|
||||
D1B(void) /* 11 011 */
|
||||
{
|
||||
}
|
||||
static void
|
||||
D29(void)
|
||||
{
|
||||
R.s = DIND(FP, s);
|
||||
R.d = R.FP+R.PC->d.ind;
|
||||
R.m = R.d;
|
||||
}
|
||||
static void
|
||||
D2D(void)
|
||||
{
|
||||
R.s = DIND(FP, s);
|
||||
R.d = DIND(FP, d);
|
||||
R.m = R.d;
|
||||
}
|
||||
static void
|
||||
D32(void)
|
||||
{
|
||||
R.d = (u8*)&R.PC->d.imm;
|
||||
R.m = R.d;
|
||||
}
|
||||
static void
|
||||
D49(void)
|
||||
{
|
||||
R.s = R.FP+R.PC->s.ind;
|
||||
R.d = R.FP+R.PC->d.ind;
|
||||
R.t = (i16)R.PC->reg;
|
||||
R.m = &R.t;
|
||||
}
|
||||
static void
|
||||
D4A(void)
|
||||
{
|
||||
R.s = R.FP+R.PC->s.ind;
|
||||
R.d = (u8*)&R.PC->d.imm;
|
||||
R.t = (i16)R.PC->reg;
|
||||
R.m = &R.t;
|
||||
}
|
||||
static void
|
||||
D4D(void)
|
||||
{
|
||||
R.s = R.FP+R.PC->s.ind;
|
||||
R.d = DIND(FP, d);
|
||||
R.t = (i16)R.PC->reg;
|
||||
R.m = &R.t;
|
||||
}
|
||||
static void
|
||||
D51(void)
|
||||
{
|
||||
R.s = (i8*)&R.PC->s.imm;
|
||||
R.d = R.FP+R.PC->d.ind;
|
||||
R.t = (i16)R.PC->reg;
|
||||
R.m = &R.t;
|
||||
}
|
||||
static void
|
||||
D52(void)
|
||||
{
|
||||
R.s = (u8*)&R.PC->s.imm;
|
||||
R.d = (u8*)&R.PC->d.imm;
|
||||
R.t = (i16)R.PC->reg;
|
||||
R.m = &R.t;
|
||||
}
|
||||
static void
|
||||
D55(void)
|
||||
{
|
||||
R.s = (u8*)&R.PC->s.imm;
|
||||
R.d = DIND(FP, d);
|
||||
R.t = (i16)R.PC->reg;
|
||||
R.m = &R.t;
|
||||
}
|
||||
static void
|
||||
D69(void)
|
||||
{
|
||||
R.s = DIND(FP, s);
|
||||
R.d = R.FP+R.PC->d.ind;
|
||||
R.t = (i16)R.PC->reg;
|
||||
R.m = &R.t;
|
||||
}
|
||||
static void
|
||||
D89(void)
|
||||
{
|
||||
R.s = R.FP+R.PC->s.ind;
|
||||
R.d = R.FP+R.PC->d.ind;
|
||||
R.m = R.FP+R.PC->reg;
|
||||
}
|
||||
static void
|
||||
D8A(void)
|
||||
{
|
||||
R.s = R.FP+R.PC->s.ind;
|
||||
R.d = (u8*)&R.PC->d.imm;
|
||||
R.m = R.FP+R.PC->reg;
|
||||
}
|
||||
static void
|
||||
D8D(void)
|
||||
{
|
||||
R.s = R.FP+R.PC->s.ind;
|
||||
R.d = DIND(FP, d);
|
||||
R.m = R.FP+R.PC->reg;
|
||||
}
|
||||
static void
|
||||
D91(void)
|
||||
{
|
||||
R.s = (u8*)&R.PC->s.imm;
|
||||
R.d = R.FP+R.PC->d.ind;
|
||||
R.m = R.FP+R.PC->reg;
|
||||
}
|
||||
static void
|
||||
D95(void)
|
||||
{
|
||||
R.s = (u8*)&R.PC->s.imm;
|
||||
R.d = DIND(FP, d);
|
||||
R.m = R.FP+R.PC->reg;
|
||||
}
|
||||
static void
|
||||
DA9(void)
|
||||
{
|
||||
R.s = DIND(FP, s);
|
||||
R.d = R.FP+R.PC->d.ind;
|
||||
R.m = R.FP+R.PC->reg;
|
||||
}
|
||||
static void
|
||||
DAD(void)
|
||||
{
|
||||
R.s = DIND(FP, s);
|
||||
R.d = DIND(FP, d);
|
||||
R.m = R.FP+R.PC->reg;
|
||||
}
|
||||
|
||||
void (*dec[])(void) =
|
||||
{
|
||||
[0x09] = D09,
|
||||
[0x0A] = D0A,
|
||||
[0x0B] = D0B,
|
||||
[0x0D] = D0D,
|
||||
[0x0F] = D0F,
|
||||
[0x11] = D11,
|
||||
[0x15] = D15,
|
||||
[0x1B] = D1B,
|
||||
[0x1A] = D1A,
|
||||
[0x29] = D29,
|
||||
[0x2D] = D2D,
|
||||
[0x32] = D32,
|
||||
[0x49] = D49,
|
||||
[0x4A] = D4A,
|
||||
[0x4D] = D4D,
|
||||
[0x51] = D51,
|
||||
[0x52] = D52,
|
||||
[0x55] = D55,
|
||||
[0x69] = D69,
|
||||
[0x89] = D89,
|
||||
[0x8A] = D8A,
|
||||
[0x8D] = D8D,
|
||||
[0x91] = D91,
|
||||
[0x95] = D95,
|
||||
[0xA9] = DA9,
|
||||
[0xAD] = DAD,
|
||||
};
|
||||
12
vm/makefile
Normal file
12
vm/makefile
Normal file
@@ -0,0 +1,12 @@
|
||||
CFLAGS= -g -O0 -std=c99 -Wall -Wextra -I ../
|
||||
|
||||
SRCS=$(wildcard *.c)
|
||||
OBJS=$(SRCS:.c=.o)
|
||||
|
||||
run: $(OBJS)
|
||||
$(CC) $(CFLAGS) -o $@ $^
|
||||
|
||||
$(OBJS): vm.h ../isa.h
|
||||
|
||||
clean:
|
||||
rm -f run $(OBJS)
|
||||
278
vm/vm.c
Normal file
278
vm/vm.c
Normal file
@@ -0,0 +1,278 @@
|
||||
#include "vm.h"
|
||||
|
||||
static u8 end[1];
|
||||
u32 ninst;
|
||||
Inst *inst;
|
||||
REG R;
|
||||
|
||||
#define OP(fn) void fn(void)
|
||||
#define B(r) *((i8*)(R.r))
|
||||
#define F(r) ((WORD*)(R.r))
|
||||
#define A(r) ((Array*)(R.r))
|
||||
#define P(r) *((WORD**)(R.r))
|
||||
#define W(r) *((WORD*)(R.r))
|
||||
#define T(r) *((void**)(R.r))
|
||||
#define JMP(r) R.PC = *(Inst**)(R.r)
|
||||
|
||||
void
|
||||
printbin(u8 x)
|
||||
{
|
||||
u8 arr[8] = {
|
||||
[0] = x & 128,
|
||||
[1] = x & 64,
|
||||
[2] = x & 32,
|
||||
[3] = x & 16,
|
||||
[4] = x & 8,
|
||||
[5] = x & 4,
|
||||
[6] = x & 2,
|
||||
[7] = x & 1,
|
||||
};
|
||||
printf("op %x %d: ",x, x);
|
||||
printf("%d%d ", arr[0]!=0,arr[1]!=0);
|
||||
printf("%d%d%d ", arr[2]!=0,arr[3]!=0,arr[4]!=0);
|
||||
printf("%d%d%d\n", arr[5]!=0,arr[6]!=0,arr[7]!=0);
|
||||
}
|
||||
|
||||
u8
|
||||
rd1(FILE *f)
|
||||
{
|
||||
u8 v = 0;
|
||||
assert(fread(&v, 1, 1, f) == 1);
|
||||
return v;
|
||||
}
|
||||
u16
|
||||
rd2(FILE *f)
|
||||
{
|
||||
u16 v = 0;
|
||||
assert(fread(&v, 1, 2, f) == 2);
|
||||
return v;
|
||||
}
|
||||
u32
|
||||
rd4(FILE *f)
|
||||
{
|
||||
u32 v = 0;
|
||||
assert(fread(&v, 1, 4, f) == 4);
|
||||
return v;
|
||||
}
|
||||
|
||||
void
|
||||
newstack(int sz)
|
||||
{
|
||||
Stack *s = calloc(1, sizeof(s)+sz);
|
||||
R.EX = s->stack;
|
||||
R.TS = s->stack + sz;
|
||||
R.SP = s->fu + sz;
|
||||
R.FP = s->fu;
|
||||
}
|
||||
|
||||
void
|
||||
initprog(int ss)
|
||||
{
|
||||
newstack(ss);
|
||||
WORD *p = (WORD*)&R.FP[32];
|
||||
*p = (WORD)&end;
|
||||
|
||||
}
|
||||
OP(nop) {}
|
||||
OP(jmp) {JMP(d);}
|
||||
OP(lea) {W(d) = (WORD)R.s;}
|
||||
OP(movw) {W(d) = W(s);}
|
||||
OP(movm) {memmove(R.d,R.s,W(m));}
|
||||
OP(addw) {W(d) = W(m) + W(s);}
|
||||
OP(subw) {W(d) = W(m) - W(s);}
|
||||
OP(mulw) {W(d) = W(m) * W(s);}
|
||||
OP(beqw) {if(W(s) == W(m)) JMP(d);}
|
||||
OP(bneqw) {if(W(s) != W(m)) JMP(d);}
|
||||
OP(ltw) {W(d) = (W(s) < W(m));}
|
||||
OP(leqw) {W(d) = (W(s) <= W(m));}
|
||||
OP(eqw) {W(d) = (W(s) == W(m));}
|
||||
OP(frame){
|
||||
Stack *s;
|
||||
Frame *f;
|
||||
int sz;
|
||||
|
||||
sz = W(s);
|
||||
s = calloc(1, sizeof(Stack) + sz);
|
||||
s->sz = sz;
|
||||
s->SP = R.SP;
|
||||
s->TS = R.TS;
|
||||
s->EX = R.EX;
|
||||
f = s->fr;
|
||||
R.s = f;
|
||||
R.EX = s;
|
||||
R.TS = s->stack + sizeof(Stack)+sz;
|
||||
R.SP = s->fu + sz;
|
||||
T(d) = R.s;
|
||||
}
|
||||
OP(call){
|
||||
Frame *f = T(s);
|
||||
f->lr = R.PC;
|
||||
f->fp = R.FP;
|
||||
R.FP = (u8*)f;
|
||||
JMP(d);
|
||||
}
|
||||
OP(ret) {
|
||||
Frame *f = (Frame*)R.FP;
|
||||
R.FP = f->fp;
|
||||
if(R.FP == NULL){
|
||||
printf("result %ld\n", W(d));
|
||||
exit(0);
|
||||
}
|
||||
R.SP = (u8*)f;
|
||||
R.PC = f->lr;
|
||||
|
||||
u8 *x = (u8*)f-IBY2WD*4;
|
||||
Stack *s = x;
|
||||
R.SP = s->SP;
|
||||
R.TS = s->TS;
|
||||
R.EX = s->EX;
|
||||
free(s);
|
||||
}
|
||||
OP(len){
|
||||
Array *a = A(s);
|
||||
W(d) = a->len;
|
||||
}
|
||||
OP(array){
|
||||
WORD *s = R.s;
|
||||
WORD m = W(m);
|
||||
WORD *d = R.d;
|
||||
if(m){
|
||||
*d = (WORD)&d[ArrHead/IBY2WD];
|
||||
memcpy(d+1, s+1, m-IBY2WD);
|
||||
}else
|
||||
assert(0);
|
||||
}
|
||||
OP(slice){
|
||||
WORD s1 = W(s);
|
||||
WORD s2 = W(m);
|
||||
Array *a = A(d);
|
||||
|
||||
if(s2 == -1)
|
||||
s2 = a->len;
|
||||
assert(s1 >= 0 && s1 < a->len);
|
||||
assert(s2 >= 0 && s2 < a->len);
|
||||
Array d = *a;
|
||||
d.len = s2 - s1;
|
||||
d.cap = s2 - s1;
|
||||
d.arr = a->arr + s1*a->size;
|
||||
*a = d;
|
||||
}
|
||||
static void (*optab[])(void) = {
|
||||
[INOP] = nop,
|
||||
[ILEA] = lea,
|
||||
[IFRAME] = frame,
|
||||
[ICALL] = call,
|
||||
[IJMP] = jmp,
|
||||
[IRET] = ret,
|
||||
[ILEN] = len,
|
||||
[ISLICE] = slice,
|
||||
[IARRAY] = array,
|
||||
[IADDW] = addw,
|
||||
[ISUBW] = subw,
|
||||
[IMOVW] = movw,
|
||||
[IMULW] = mulw,
|
||||
[IMOVM] = movm,
|
||||
[IBEQW] = beqw,
|
||||
[IBNEQW] = bneqw,
|
||||
[IEQW] = eqw,
|
||||
[ILEQW] = leqw,
|
||||
[ILTW] = ltw,
|
||||
};
|
||||
|
||||
void
|
||||
xec(void)
|
||||
{
|
||||
while(1){
|
||||
Inst in = *R.PC;
|
||||
u8 op = in.op;
|
||||
if(dec[in.add] == 0){
|
||||
printbin(in.add);
|
||||
exit(1);
|
||||
}
|
||||
if(optab[in.op]==0){
|
||||
printf("op 0X%x %d\n", in.op, in.op);
|
||||
exit(1);
|
||||
}
|
||||
dec[in.add]();
|
||||
R.PC++;
|
||||
optab[op]();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
bpatch(Inst *i)
|
||||
{
|
||||
static int tab[IEND] = {
|
||||
[ICALL]=1,[IBEQW]=1,[IBNEQW]=1,[IJMP]=1,
|
||||
};
|
||||
if(tab[i->op] == 0)
|
||||
return;
|
||||
assert(i->d.imm >= 0 && i->d.imm < ninst);
|
||||
i->d.imm = (WORD)&inst[i->d.imm];
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
rdinst(FILE *f, Inst *in)
|
||||
{
|
||||
in->op = rd1(f);
|
||||
assert(in->op != EOF);
|
||||
in->add = rd1(f);
|
||||
switch(in->add & ARM) {
|
||||
case AXIMM:
|
||||
case AXINF:
|
||||
case AXINM:
|
||||
in->reg = rd4(f);
|
||||
break;
|
||||
}
|
||||
switch(UXSRC(in->add)) {
|
||||
case SRC(AFP):
|
||||
case SRC(AMP):
|
||||
case SRC(AIMM):
|
||||
in->s.ind = rd4(f);
|
||||
break;
|
||||
case SRC(AIND|AFP):
|
||||
case SRC(AIND|AMP):
|
||||
in->s.f = rd2(f);
|
||||
in->s.s = rd2(f);
|
||||
break;
|
||||
}
|
||||
switch(UXDST(in->add)) {
|
||||
case DST(AFP):
|
||||
case DST(AMP):
|
||||
in->d.ind = rd4(f);
|
||||
break;
|
||||
case DST(AIMM):
|
||||
in->d.ind = rd4(f);
|
||||
bpatch(in);
|
||||
break;
|
||||
case DST(AIND|AFP):
|
||||
case DST(AIND|AMP):
|
||||
in->d.f = rd2(f);
|
||||
in->d.s = rd2(f);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
load(char *fname)
|
||||
{
|
||||
FILE *f = fopen(fname, "r");
|
||||
assert(f != 0);
|
||||
initprog(1024);
|
||||
ninst = rd4(f);
|
||||
inst = calloc(sizeof(Inst), ninst);
|
||||
|
||||
for(u32 i = 0; i < ninst; ++i){
|
||||
rdinst(f, inst+i);
|
||||
}
|
||||
R.PC = inst;
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
load(argv[1]);
|
||||
xec();
|
||||
}
|
||||
76
vm/vm.h
Normal file
76
vm/vm.h
Normal file
@@ -0,0 +1,76 @@
|
||||
#include "isa.h"
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
typedef struct Inst Inst;
|
||||
typedef union Adr Adr;
|
||||
typedef struct REG REG;
|
||||
typedef struct Array Array;
|
||||
typedef struct Frame Frame;
|
||||
typedef union Stack Stack;
|
||||
|
||||
union Adr
|
||||
{
|
||||
WORD imm;
|
||||
WORD ind;
|
||||
Inst* ins;
|
||||
struct {
|
||||
u16 f; /* First */
|
||||
u16 s; /* Second */
|
||||
};
|
||||
};
|
||||
|
||||
struct Inst
|
||||
{
|
||||
u8 op;
|
||||
u8 add;
|
||||
u16 reg;
|
||||
Adr s;
|
||||
Adr d;
|
||||
};
|
||||
|
||||
struct Frame
|
||||
{
|
||||
Inst *lr;
|
||||
u8 *fp;
|
||||
};
|
||||
|
||||
union Stack
|
||||
{
|
||||
u8 stack[1];
|
||||
struct{
|
||||
int sz;
|
||||
u8 *SP;
|
||||
u8 *TS;
|
||||
u8 *EX;
|
||||
union{
|
||||
u8 fu[1];
|
||||
Frame fr[1];
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
struct REG
|
||||
{
|
||||
Inst *PC;
|
||||
u8 *FP;
|
||||
u8 *SP;
|
||||
u8 *TS;
|
||||
u8 *EX;
|
||||
void *s, *d, *m;
|
||||
int t, dt ,mt;
|
||||
};
|
||||
|
||||
struct Array
|
||||
{
|
||||
u8 *arr;
|
||||
WORD len;
|
||||
WORD cap;
|
||||
WORD size;
|
||||
};
|
||||
|
||||
extern REG R;
|
||||
extern void (*dec[])(void);
|
||||
Reference in New Issue
Block a user