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:
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();
+ }
+}