diff options
Diffstat (limited to 'disassembler.c')
-rw-r--r-- | disassembler.c | 202 |
1 files changed, 47 insertions, 155 deletions
diff --git a/disassembler.c b/disassembler.c index ea370ba..2ceee3f 100644 --- a/disassembler.c +++ b/disassembler.c @@ -1,179 +1,71 @@ #include <stdio.h> -#include <stdlib.h> #include <stdint.h> -#include <errno.h> +#include <string.h> -#include "util.h" +#include "instruction.h" +#include "parse.h" +#include "input_bin.h" +#include "output_asm.h" void print_help(const char *argv0) { - fprintf(stderr, "Syntax: %s <in.bin>\0 <out.asm>\n", argv0); + fprintf(stderr, "Syntax: %s <in.bin> <out.asm>\n", argv0); } -int disasm_rtype(uint16_t i, uint16_t unused) -{ - const char *oper = get_asm_from_oper(GET_OPER(i)); - const char *dest = get_asm_from_reg(GET_REG_DEST(i)); - const char *left = get_asm_from_reg(GET_REG_LEFT(i)); - const char *right = get_asm_from_reg(GET_REG_RIGHT(i)); - - /* FIXME add special cases: - * - nop - * - neg - * - mv - */ - printf("%s %s, %s, %s\n", oper, dest, left, right); - - return 0; -} - -int disasm_nitype(uint16_t i, uint16_t unused) -{ - const char *oper = get_asm_from_oper(GET_OPER(i)); - const char *dest = get_asm_from_reg(GET_REG_DEST(i)); - const char *left = get_asm_from_reg(GET_REG_LEFT(i)); - uint16_t imm = GET_NI_IMM(i); - /** FIXME add special cases: - * - ldi - */ - /* FIXME review sign around immediate value */ - printf("%si %s, %s, 0x%x\n", oper, dest, left, imm); - return 0; -} - -int disasm_witype(uint16_t i, uint16_t unused) -{ - const char *oper = get_asm_from_oper(GET_OPER(i)); - const char *dest = get_asm_from_reg(GET_REG_DEST(i)); - const char *left = get_asm_from_reg(GET_REG_LEFT(i)); - uint16_t imm = GET_NI_IMM(i); - /* FIXME handle wide imm value */ - printf("%si, %s, %s, 0x%x\n", "oper", dest, left, "?"); - return 0; -} - -int disasm_jreg(uint16_t i, uint16_t unused) -{ - const char *inst = get_asm_from_j(GET_JB_COND(i)); - const char *reg = get_asm_from_reg(GET_JUMP_REG(i)); - printf("%s %s\n", inst, reg); - return 0; -} - -int disasm_bimm(uint16_t i, uint16_t pc) -{ - const char *inst = get_asm_from_b(GET_JB_COND(i)); - struct {signed int s:10;} sign; - int offset = sign.s = GET_B_OFFSET(i); - printf("%s 0x%x\n", inst, pc + 2 * offset); - return 0; -} - -int disasm_jimm(uint16_t i, uint16_t imm) -{ - const char *inst = get_asm_from_j(GET_JB_COND(i)); - printf("%s 0x%x\n", inst, imm); - return 0; -} - -int disasm(FILE *f) +int main(int argc, char **argv) { + int error_ret = 1; int ret = 0; - size_t offs = 0; - size_t extra_read = 0; - uint16_t inst = 0; - uint16_t extra_arg = 0; - uint8_t c[2] = { 0 }; - int (*disasm_inst)(uint16_t, uint16_t); + const char *path_in = NULL; + const char *path_out = NULL; + FILE *fin = NULL; + FILE *fout = NULL; - while (!feof(f) && fread(c, sizeof(c), 1, f) == 1) { - extra_read = 0; - inst = c[0] << 8 | c[1]; - switch (GET_INST_TYPE(inst)) { - case INST_TYPE_RTYPE: - disasm_inst = disasm_rtype; - break; - case INST_TYPE_NITYPE: - disasm_inst = disasm_nitype; - break; - case INST_TYPE_WITYPE: - if (fread(c, sizeof(c), 1, f) != 1) { - ret = -errno; - break; - } - extra_read = sizeof(c); - extra_arg = c[0] << 16 | c[1]; - disasm_inst = disasm_witype; - break; - case INST_TYPE_JTYPE: - /* J Type can be split into three further subtypes: - * - branch (always immediate, 2 bytes) - * - jump reg (2 bytes) - * - jump immediate (4 bytes) - */ - if (inst & MASK_IS_BRANCH) { - disasm_inst = disasm_bimm; - extra_arg = offs; - } else { - if (inst & MASK_JR) { - disasm_inst = disasm_jreg; - } else { - if (fread(c, sizeof(c), 1, f) != 1) { - ret = -errno; - break; - } - extra_arg = c[0] << 16 | c[1]; - extra_read = sizeof(c); - disasm_inst = disasm_jimm; - } - } - break; - default: - printf("Unhandled instruction at byte %zd\n", offs); - ret = -1; - break; - } - /* Fall out of loop if picking a handler errored */ - if (ret) { - break; - } - printf("%04x:\t", offs); - ret = disasm_inst(inst, extra_arg); - if (ret < 0) { - fprintf(stderr, "Error handling instruction at byte %zd\n", offs); - break; - } - offs += sizeof(c) + extra_read; + if (argc < 3) { + print_help(argv[0]); + return 1; } - if (!feof(f)) { - perror("fread"); - ret = errno; + if (strcmp(argv[1], "-q") == 0) { + if (argc != 4) { + print_help(argv[0]); + return 0; + } + error_ret = 0; + path_in = argv[2]; + path_out = argv[3]; } else { - /* print out final, empty label */ - printf("%04x:\n", offs); + path_in = argv[1]; + path_out = argv[2]; } - return ret; -} -int main(int argc, char **argv) -{ - int ret = 0; - FILE *fin = NULL; - - if (argc < 2) { - print_help(argv[0]); - return 1; + if ((fin = fopen(path_in, "r")) == NULL) { + fprintf(stderr, "Error opening %s: ", path_in); + perror("fopen"); + return error_ret; } - if (!(fin = fopen(argv[1], "rb"))) { + if ((fout = fopen(path_out, "w")) == NULL) { + fprintf(stderr, "Error opening %s: ", path_out); perror("fopen"); - return 1; + return error_ret; } - ret = disasm(fin); +/****/ + /* FIXME package these things into `tok_result`, parse_result` etc */ + struct instruction *insts; + size_t insts_count; + struct label *labels; + size_t labels_count; + labels = NULL; + labels_count = 0; + + if (ret = disasm(fin, &insts, &insts_count)) + return error_ret && ret; - fclose(fin); - return ret; + if (ret = output_asm(fout, labels, labels_count, insts, insts_count)) + return error_ret && ret; + + return 0; } |