duskos

dusk os fork
git clone git://git.alexwennerberg.com/duskos
Log | Files | Refs | README | LICENSE

commit 4c835bdde89fbd1cd8c6e18f13b5102c1096266b
parent b350f881361d93aa87b572355b12cc2c5714d9a2
Author: Virgil Dupras <hsoft@hardcoded.net>
Date:   Wed,  7 Sep 2022 08:52:38 -0400

cvm: add little disassembler tool

it helps be with debugging CC output for the Forth VM...

Diffstat:
M.gitignore | 1+
MMakefile | 5++++-
Aposix/dis.c | 176+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 181 insertions(+), 1 deletion(-)

diff --git a/.gitignore b/.gitignore @@ -1,4 +1,5 @@ /dusk +/dis /memdump /fs/init.fs /posix/boot.fs diff --git a/Makefile b/Makefile @@ -1,4 +1,4 @@ -TARGETS = dusk +TARGETS = dusk dis BOOTFS_SRC = fs/xcomp/bootlo.fs posix/glue.fs fs/xcomp/boothi.fs ALLSRCS = $(shell find fs) all: $(TARGETS) @@ -12,6 +12,9 @@ posix/boot.fs: $(BOOTFS_SRC) dusk: posix/vm.c posix/boot.fs fs/init.fs $(CC) posix/vm.c -Wall -o $@ +dis: posix/dis.c + $(CC) posix/dis.c -Wall -o $@ + pc.img: dusk $(ALLSRCS) dd if=/dev/zero of=$@ bs=1M count=1 ./dusk < buildpc.fs diff --git a/posix/dis.c b/posix/dis.c @@ -0,0 +1,176 @@ +/* Disassembler for the CVM bytecode + +Because of Forth's very dynamic nature, this disassembler can't hope to +disassemble a whole memory space. As soon as we hit a cell or a does, we can't +continue. However, this can be useful to disassemble small pieces of code such +as the ones compiled by the Forth backend of CC. +*/ +#include <stdio.h> + + +#define ARGNONE 0 +#define ARGBYTE 1 +#define ARGINT 2 +#define ARGSTR 3 +#define ARGERR 4 // can't continue, arg size unknown + +struct op { + char *name; // NULL= no op + int arg; +}; + +#define OPCNT 0x6b +static struct op ops[OPCNT] = { + {"JUMP", ARGINT}, + {"CALL", ARGINT}, + {"RET", ARGNONE}, + {"LIT", ARGINT}, + {"BYE", ARGNONE}, + {"BYEFAIL", ARGNONE}, + {"QUIT", ARGNONE}, + {"ABORT", ARGNONE}, + {"EXECUTE", ARGNONE}, + {"CELL", ARGERR}, + {"DOES", ARGERR}, + {"SLIT", ARGSTR}, + {"BR", ARGINT}, + {"CBR", ARGINT}, + {"NEXT", ARGINT}, + {NULL, ARGERR}, + + {"PSADD", ARGBYTE}, + {"PSADDWR", ARGNONE}, + {"PSADDR", ARGBYTE}, + {"PSADDRWR", ARGNONE}, + {"BOOTRD", ARGNONE}, + {"STDOUT", ARGNONE}, + {"KEY", ARGNONE}, + {NULL, ARGERR}, + {"DUP", ARGNONE}, + {"CDUP", ARGNONE}, + {"SWAP", ARGNONE}, + {"OVER", ARGNONE}, + {"ROT", ARGNONE}, + {"ROTR", ARGNONE}, + {"NIP", ARGNONE}, + {"TUCK", ARGNONE}, + + {"RSADD", ARGBYTE}, + {"RSADDWR", ARGNONE}, + {"RSADDR", ARGBYTE}, + {"RSADDRWR", ARGNONE}, + {"SCNT", ARGNONE}, + {"RCNT", ARGNONE}, + {"SET16B", ARGNONE}, + {"SET8B", ARGNONE}, + {"FETCH", ARGNONE}, + {"STORE", ARGNONE}, + {"ADDSTORE", ARGNONE}, + {"FETCHSTORE", ARGNONE}, + {"FETCHADD", ARGNONE}, + {"STOREADD", ARGNONE}, + {"IFETCHADD", ARGNONE}, + {"ISTOREADD", ARGNONE}, + + {"WRITE", ARGNONE}, + {NULL, ARGNONE}, + {NULL, ARGNONE}, + {NULL, ARGNONE}, + {"SETBW", ARGNONE}, + {NULL, ARGNONE}, + {NULL, ARGNONE}, + {NULL, ARGNONE}, + {"INC", ARGNONE}, + {"DEC", ARGNONE}, + {"ADD", ARGNONE}, + {"SUB", ARGNONE}, + {"MUL", ARGNONE}, + {"DIVMOD", ARGNONE}, + {"AND", ARGNONE}, + {NULL, ARGNONE}, + + {"OR", ARGNONE}, + {"XOR", ARGNONE}, + {"BOOL", ARGNONE}, + {"NOT", ARGNONE}, + {"LT", ARGNONE}, + {"SHLC", ARGNONE}, + {"SHRC", ARGNONE}, + {"LSHIFT", ARGNONE}, + {"RSHIFT", ARGNONE}, + {"LITN", ARGNONE}, + {"EXECUTEWR", ARGNONE}, + {"EXITWR", ARGNONE}, + {"MOVE", ARGNONE}, + {"MOVEWR", ARGNONE}, + {"RTYPE", ARGNONE}, + {"WNF", ARGNONE}, + + {"STACKCHK", ARGNONE}, + {"MAYBEWORD", ARGNONE}, + {"WORD", ARGNONE}, + {"PARSE", ARGNONE}, + {"REQ", ARGNONE}, + {"FIND", ARGNONE}, + {"APOS", ARGNONE}, + {"COMPILING", ARGNONE}, + {"SWR", ARGNONE}, + {"STARTCOMP", ARGNONE}, + {"STOPCOMP", ARGNONE}, + {"COMPWORD", ARGNONE}, + {"RUNWORD", ARGNONE}, + {NULL, ARGNONE}, + {NULL, ARGNONE}, + {NULL, ARGNONE}, + + {"FCHILD", ARGNONE}, + {"FOPEN", ARGNONE}, + {"FREADBUF", ARGNONE}, + {"FCLOSE", ARGNONE}, + {"FINFO", ARGNONE}, + {"FITER", ARGNONE}, + {NULL, ARGNONE}, + {NULL, ARGNONE}, + {"MOUNTDRV", ARGNONE}, + {"DRVRD", ARGNONE}, + {"DRVWR", ARGNONE}}; + +int main() { + int c = getchar(); + int n; + while (c != EOF) { + if ((c >= OPCNT) || (ops[c].name == NULL)) { + fprintf(stderr, "Invalid opcode %x\n", c); + return 1; + } + fputs(ops[c].name, stdout); + switch (ops[c].arg) { + case ARGNONE: break; + case ARGBYTE: + n = getchar(); + printf("\t%x", n); + break; + case ARGINT: + n = 0; + for (int i=0; i<4; i++) { + n |= getchar() << (i*8); + } + printf("\t%x", n); + break; + case ARGSTR: + n = getchar() & 0xff; + for (int i=0; i<n; i++) { + putchar(getchar()); + } + break; + case ARGERR: + fprintf(stderr, "Can't parse this op's arg\n"); + return 1; + default: + fprintf(stderr, "Something's wrong\n"); + return 1; + } + putchar('\n'); + c = getchar(); + } +}