summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBobby Bingham <koorogi@koorogi.info>2017-01-14 19:07:49 -0600
committerBobby Bingham <koorogi@koorogi.info>2017-01-15 23:19:28 -0600
commit9acd6ce40559c59ca55899215aa9d7e781b5a8b7 (patch)
treef787d6c61ac2fd5c16f9219bc652f076ac8fdf39
parentf91057644c1f1813bf1373b5158e6b658210d570 (diff)
nqdasm: Add disassembler
-rw-r--r--.gitignore1
-rw-r--r--Makefile7
-rw-r--r--mnemonics.c70
-rw-r--r--mnemonics.h3
-rw-r--r--nqdasm.c43
5 files changed, 87 insertions, 37 deletions
diff --git a/.gitignore b/.gitignore
index 75d471d..0a0e818 100644
--- a/.gitignore
+++ b/.gitignore
@@ -5,3 +5,4 @@ parser.c
parser.h
*.o
nqasm
+nqdasm
diff --git a/Makefile b/Makefile
index d509c92..4668fad 100644
--- a/Makefile
+++ b/Makefile
@@ -5,7 +5,7 @@ GENSRCS = lexer.c parser.c
GENHDRS = lexer.h parser.h
SRCS = $(sort $(wildcard *.c) $(GENSRCS))
OBJS = $(SRCS:.c=.o)
-TARGET = nqasm
+TARGET = nqasm nqdasm
all: $(TARGET)
@@ -24,7 +24,10 @@ parser.o: lexer.h
%.o: %.c
$(CC) $(CFLAGS) -c $< -o $@
-$(TARGET): $(OBJS)
+nqasm: $(filter-out nqdasm.o,$(OBJS))
+nqdasm: mnemonics.o nqdasm.o
+
+$(TARGET):
$(CC) $(CFLAGS) $^ -o $@
.PHONY: all clean
diff --git a/mnemonics.c b/mnemonics.c
index 38a35f8..b65e110 100644
--- a/mnemonics.c
+++ b/mnemonics.c
@@ -1,40 +1,40 @@
#include "mnemonics.h"
const struct mnemonic mnemonics[] = {
- { "add", 0x0000, { {REG, 9}, {REG, 5}, {REG, 2} } }, /* add */
- { "sub", 0x0001, { {REG, 9}, {REG, 5}, {REG, 2} } }, /* subtract */
- { "mul", 0x0002, { {REG, 9}, {REG, 5}, {REG, 2} } }, /* multiply */
- { "div", 0x0003, { {REG, 9}, {REG, 5}, {REG, 2} } }, /* divide */
- { "and", 0x0100, { {REG, 9}, {REG, 5}, {REG, 2} } }, /* bitwise and */
- { "or", 0x0101, { {REG, 9}, {REG, 5}, {REG, 2} } }, /* bitwise or */
- { "xor", 0x0102, { {REG, 9}, {REG, 5}, {REG, 2} } }, /* bitwise exclusive or */
- { "lsl", 0x1000, { {REG, 9}, {REG, 5}, {REG, 2} } }, /* logical shift left */
- { "lsr", 0x1100, { {REG, 9}, {REG, 5}, {REG, 2} } }, /* logical shift right */
- { "asl", 0x1002, { {REG, 9}, {REG, 5}, {REG, 2} } }, /* arithmetic shift left (fills with lsb) */
- { "asr", 0x1102, { {REG, 9}, {REG, 5}, {REG, 2} } }, /* arithmetic shift right (fills with msb) */
- { "rol", 0x1003, { {REG, 9}, {REG, 5}, {REG, 2} } }, /* rotate left */
- { "ror", 0x1103, { {REG, 9}, {REG, 5}, {REG, 2} } }, /* rotate right */
- { "not", 0x2000, { {REG, 9}, {REG, 2} } }, /* bitwise inverse */
- { "neg", 0x2100, { {REG, 9}, {REG, 2} } }, /* negate */
- { "btc", 0x3000, { {REG, 9}, {REG, 2} } }, /* bit clear */
- { "bts", 0x3100, { {REG, 9}, {REG, 2} } }, /* bit set */
- { "mov", 0x4004, { {REG, 9}, {REG, 5} } }, /* register move */
- { "st.b", 0x4100, { {REGPTR, 9}, {REG, 5} } }, /* store byte */
- { "st.w", 0x4104, { {REGPTR, 9}, {REG, 5} } }, /* store word */
- { "ld.bl", 0x4101, { {REG, 9}, {REGPTR, 5} } }, /* load byte into low byte of register */
- { "ld.bh", 0x4111, { {REG, 9}, {REGPTR, 5} } }, /* load byte into high byte of register */
- { "ld.w", 0x4105, { {REG, 9}, {REGPTR, 5} } }, /* load word */
- { "ldi.bl", 0x5000, { {REG, 9}, {IMM, 0} } }, /* load immediate into low byte of register */
- { "ldi.bh", 0x5100, { {REG, 9}, {IMM, 0} } }, /* load immediate into high byte of register */
- { "beq", 0x6000, { {PCOFF, 0}, } }, /* branch if equal */
- { "bne", 0x6200, { {PCOFF, 0}, } }, /* branch if not equal */
- { "bgt", 0x6400, { {PCOFF, 0}, } }, /* branch if greater than */
- { "bge", 0x6600, { {PCOFF, 0}, } }, /* branch if greater than or equal */
- { "blt", 0x6800, { {PCOFF, 0}, } }, /* branch if less than */
- { "ble", 0x6a00, { {PCOFF, 0}, } }, /* branch if less than or equal */
- { "bra", 0x6e00, { {PCOFF, 0}, } }, /* branch always */
- { "jmp", 0x7000, { {REGPTR, 5}, } }, /* branch always */
- { "addpc", 0x8000, { {REG, 9}, {PCOFF, 0} } }, /* add program counter and immediate */
- { "nop", 0xffff, { } }, /* no operation */
+ { "add", 0x0000, 0xf103, { {REG, 9}, {REG, 5}, {REG, 2} } }, /* add */
+ { "sub", 0x0001, 0xf103, { {REG, 9}, {REG, 5}, {REG, 2} } }, /* subtract */
+ { "mul", 0x0002, 0xf103, { {REG, 9}, {REG, 5}, {REG, 2} } }, /* multiply */
+ { "div", 0x0003, 0xf103, { {REG, 9}, {REG, 5}, {REG, 2} } }, /* divide */
+ { "and", 0x0100, 0xf103, { {REG, 9}, {REG, 5}, {REG, 2} } }, /* bitwise and */
+ { "or", 0x0101, 0xf103, { {REG, 9}, {REG, 5}, {REG, 2} } }, /* bitwise or */
+ { "xor", 0x0102, 0xf103, { {REG, 9}, {REG, 5}, {REG, 2} } }, /* bitwise exclusive or */
+ { "lsl", 0x1000, 0xf103, { {REG, 9}, {REG, 5}, {REG, 2} } }, /* logical shift left */
+ { "lsr", 0x1100, 0xf103, { {REG, 9}, {REG, 5}, {REG, 2} } }, /* logical shift right */
+ { "asl", 0x1002, 0xf103, { {REG, 9}, {REG, 5}, {REG, 2} } }, /* arithmetic shift left (fills with lsb) */
+ { "asr", 0x1102, 0xf103, { {REG, 9}, {REG, 5}, {REG, 2} } }, /* arithmetic shift right (fills with msb) */
+ { "rol", 0x1003, 0xf103, { {REG, 9}, {REG, 5}, {REG, 2} } }, /* rotate left */
+ { "ror", 0x1103, 0xf103, { {REG, 9}, {REG, 5}, {REG, 2} } }, /* rotate right */
+ { "not", 0x2000, 0xf1e3, { {REG, 9}, {REG, 2} } }, /* bitwise inverse */
+ { "neg", 0x2100, 0xf1e3, { {REG, 9}, {REG, 2} } }, /* negate */
+ { "btc", 0x3000, 0xf11f, { {REG, 9}, {REG, 2} } }, /* bit clear */
+ { "bts", 0x3100, 0xf11f, { {REG, 9}, {REG, 2} } }, /* bit set */
+ { "mov", 0x4004, 0xf11f, { {REG, 9}, {REG, 5} } }, /* register move */
+ { "st.b", 0x4100, 0xf11f, { {REGPTR, 9}, {REG, 5} } }, /* store byte */
+ { "st.w", 0x4104, 0xf11f, { {REGPTR, 9}, {REG, 5} } }, /* store word */
+ { "ld.bl", 0x4101, 0xf11f, { {REG, 9}, {REGPTR, 5} } }, /* load byte into low byte of register */
+ { "ld.bh", 0x4111, 0xf11f, { {REG, 9}, {REGPTR, 5} } }, /* load byte into high byte of register */
+ { "ld.w", 0x4105, 0xf11f, { {REG, 9}, {REGPTR, 5} } }, /* load word */
+ { "ldi.bl", 0x5000, 0xf100, { {REG, 9}, {IMM, 0} } }, /* load immediate into low byte of register */
+ { "ldi.bh", 0x5100, 0xf100, { {REG, 9}, {IMM, 0} } }, /* load immediate into high byte of register */
+ { "beq", 0x6000, 0xff00, { {PCOFF, 0}, } }, /* branch if equal */
+ { "bne", 0x6200, 0xff00, { {PCOFF, 0}, } }, /* branch if not equal */
+ { "bgt", 0x6400, 0xff00, { {PCOFF, 0}, } }, /* branch if greater than */
+ { "bge", 0x6600, 0xff00, { {PCOFF, 0}, } }, /* branch if greater than or equal */
+ { "blt", 0x6800, 0xff00, { {PCOFF, 0}, } }, /* branch if less than */
+ { "ble", 0x6a00, 0xff00, { {PCOFF, 0}, } }, /* branch if less than or equal */
+ { "bra", 0x6e00, 0xff00, { {PCOFF, 0}, } }, /* branch always */
+ { "jmp", 0x7000, 0xff1f, { {REGPTR, 5}, } }, /* branch always */
+ { "addpc", 0x8000, 0xf100, { {REG, 9}, {PCOFF, 0} } }, /* add program counter and immediate */
+ { "nop", 0xf000, 0xf000, { } }, /* no operation */
};
diff --git a/mnemonics.h b/mnemonics.h
index 969926e..9ab6e8c 100644
--- a/mnemonics.h
+++ b/mnemonics.h
@@ -45,6 +45,8 @@ enum {
MNEM_JMP,
MNEM_ADDPC,
MNEM_NOP,
+
+ MNEM_LAST
};
struct operand {
@@ -55,6 +57,7 @@ struct operand {
struct mnemonic {
const char *mnem;
uint16_t bits;
+ uint16_t mask;
struct operand operands[3];
};
diff --git a/nqdasm.c b/nqdasm.c
new file mode 100644
index 0000000..4969f47
--- /dev/null
+++ b/nqdasm.c
@@ -0,0 +1,43 @@
+#include <stdio.h>
+
+#include "mnemonics.h"
+
+static const struct mnemonic *match_instruction(unsigned bits)
+{
+ for (int i = 0; i < MNEM_LAST; i++) {
+ const struct mnemonic *m = mnemonics + i;
+ if ((bits & m->mask) == m->bits) return m;
+ }
+ return NULL;
+}
+
+static void print_operand(unsigned bits, const struct operand *op)
+{
+ switch (op->type) {
+ case REG: printf( "r%d", 7 & (bits >> op->shift)); break;
+ case REGPTR: printf("@r%d", 7 & (bits >> op->shift)); break;
+ case IMM: printf( "%d", (uint8_t)(bits >> op->shift)); break;
+ case PCOFF: printf( "%d", (int8_t)(bits >> op->shift)); break;
+ }
+}
+
+int main()
+{
+ unsigned bits;
+ while (scanf(" %x\n", &bits) > 0) {
+ const struct mnemonic *m = match_instruction(bits);
+ if (!m) {
+ fprintf(stderr, "could not decode instruction 0x%04x\n", bits);
+ continue;
+ }
+
+ printf("\t%s", m->mnem);
+ for (int i = 0; i < 3 && m->operands[i].type; i++) {
+ printf("%s", i ? ", " : " ");
+ print_operand(bits, m->operands + i);
+ }
+ printf("\n");
+ }
+ return 0;
+}
+