first commit

This commit is contained in:
yoyo
2024-11-03 06:24:26 +09:00
parent b8ffc0632a
commit f4b991f953
24 changed files with 5316 additions and 0 deletions

222
vm/dec.c Normal file
View 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
View 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
View 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
View 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);