diff options
author | Bobby Bingham <koorogi@koorogi.info> | 2017-01-14 19:07:49 -0600 |
---|---|---|
committer | Bobby Bingham <koorogi@koorogi.info> | 2017-01-15 23:19:28 -0600 |
commit | 9acd6ce40559c59ca55899215aa9d7e781b5a8b7 (patch) | |
tree | f787d6c61ac2fd5c16f9219bc652f076ac8fdf39 | |
parent | f91057644c1f1813bf1373b5158e6b658210d570 (diff) |
nqdasm: Add disassembler
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | Makefile | 7 | ||||
-rw-r--r-- | mnemonics.c | 70 | ||||
-rw-r--r-- | mnemonics.h | 3 | ||||
-rw-r--r-- | nqdasm.c | 43 |
5 files changed, 87 insertions, 37 deletions
@@ -5,3 +5,4 @@ parser.c parser.h *.o nqasm +nqdasm @@ -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; +} + |