diff options
author | Bobby Bingham <koorogi@koorogi.info> | 2017-01-15 23:05:23 -0600 |
---|---|---|
committer | Bobby Bingham <koorogi@koorogi.info> | 2017-01-15 23:19:47 -0600 |
commit | 19458565441227f4981681a8de126517d734da3e (patch) | |
tree | 64fc42d34af602409701494cd19abb8d9211b4d0 | |
parent | 578d71ea830823bd6bd27c9529075fbf18957c3b (diff) |
nqdasm: use a static buffer for input lines
Simplifies buffer handling and searches for lines by address.
-rw-r--r-- | nqdasm.c | 98 |
1 files changed, 33 insertions, 65 deletions
@@ -24,12 +24,15 @@ const char *progname; perror(str); \ } while (0) -struct line { +static struct line { const struct mnemonic *mnem; - uint16_t addr; uint16_t value; int label; -}; +} lines[0x7fff]; + +static size_t maxpc; + +#define LINE(addr) &lines[(uint16_t)(addr) >> 1] static const struct mnemonic *match_instruction(unsigned bits) { @@ -52,29 +55,23 @@ static inline int get_argvalue(const struct line *line, int argidx) assert(0); } -static int cmp_line_addr(const void *a, const void *b) -{ - const struct line *la = (const struct line*)a; - const struct line *lb = (const struct line*)b; - return la->addr < lb->addr ? -1 : la->addr == lb->addr ? 0 : 1; -} - -static struct line *get_pcoff_target(const struct line *lines, size_t count, const struct line *inst, int argidx) +static struct line *get_pcoff_target(uint16_t pc, int argidx) { - uint16_t targetaddr = inst->addr + get_argvalue(inst, argidx); - return bsearch(&(struct line){ .addr = targetaddr }, lines, count, sizeof *lines, cmp_line_addr); + struct line *l = LINE(pc + get_argvalue(LINE(pc), argidx)); + return l - lines >= 2*maxpc ? NULL : l; } -static void assign_labels(struct line *lines, size_t count) +static void assign_labels(void) { /* mark those addresses that need a label */ - for (size_t i = 0; i < count; i++) { - if (!lines[i].mnem) continue; + for (size_t pc = 0; pc < maxpc; pc += 2) { + const struct line *l = LINE(pc); + if (!l->mnem) continue; - const struct operand *ops = lines[i].mnem->operands; + const struct operand *ops = l->mnem->operands; for (int j = 0; j < 3 && ops[j].type; j++) { if (ops[j].type == PCOFF) { - struct line *target = get_pcoff_target(lines, count, lines + i, j); + struct line *target = get_pcoff_target(pc, j); if (target) target->label = 1; } } @@ -82,14 +79,15 @@ static void assign_labels(struct line *lines, size_t count) /* assign labels in ascending order */ int label = 0; - for (size_t i = 0; i < count; i++) { - lines[i].label = lines[i].label ? label++ : -1; + for (size_t pc = 0; pc < maxpc; pc += 2) { + struct line *l = LINE(pc); + l->label = l->label ? label++ : -1; } } -static void print_operand(FILE *out, const struct line *lines, size_t count, size_t lineidx, size_t argidx) +static void print_operand(FILE *out, size_t pc, size_t argidx) { - const struct line *inst = lines + lineidx; + const struct line *inst = LINE(pc); const struct operand *op = inst->mnem->operands + argidx; switch (op->type) { @@ -97,7 +95,7 @@ static void print_operand(FILE *out, const struct line *lines, size_t count, siz case REGPTR: fprintf(out, "@r%d", get_argvalue(inst, argidx)); break; case IMM: fprintf(out, "%d", get_argvalue(inst, argidx)); break; case PCOFF: { - const struct line *target = get_pcoff_target(lines, count, inst, argidx); + const struct line *target = get_pcoff_target(pc, argidx); if (target && target->label >= 0) fprintf(out, "L%d", target->label); else @@ -108,59 +106,31 @@ static void print_operand(FILE *out, const struct line *lines, size_t count, siz } } -static int resize_lines(struct line **lines, size_t alloc) +static int read_lines(FILE *in) { - struct line *result = realloc(*lines, alloc * sizeof **lines); - if (result) *lines = result; - else PERROR("Error allocating memory"); - return !result; -} - -static struct line *read_lines(FILE *in, size_t *count) -{ - size_t alloc = 16; - struct line *lines = NULL; - - *count = 0; - if (resize_lines(&lines, alloc)) goto fail; - - unsigned bits, addr = 0; - while (fscanf(in, " %x\n", &bits) > 0) { - if (addr > 0xffff) { + unsigned bits; + for (maxpc = 0; fscanf(in, " %x\n", &bits) > 0; maxpc += 2) { + if (maxpc > 0xffff) { ERROR("Input exceeds 16-bit address space"); - goto fail; - } - if (*count >= alloc && resize_lines(&lines, alloc *= 2)) { - goto fail; + return 1; } - lines[*count] = (struct line) { + *LINE(maxpc) = (struct line) { .mnem = match_instruction(bits), .value = bits, - .addr = addr, }; - - addr += 2; - *count += 1; } - return lines; - -fail: - free(lines); - return NULL; + return 0; } static void disassemble(FILE *in, FILE *out) { - size_t count; - struct line *lines = read_lines(in, &count); - if (!lines) return; + if (read_lines(in)) return; + assign_labels(); - assign_labels(lines, count); - - for (size_t i = 0; i < count; i++) { - const struct line *line = lines + i; + for (size_t pc = 0; pc < maxpc; pc += 2) { + const struct line *line = LINE(pc); unsigned bits = line->value; const struct mnemonic *m = line->mnem; @@ -175,12 +145,10 @@ static void disassemble(FILE *in, FILE *out) for (int j = 0; j < 3 && m->operands[j].type; j++) { if (j) fprintf(out, ", "); else fprintf(out, "%*s", 8 - (int)strlen(m->mnem), ""); - print_operand(out, lines, count, i, j); + print_operand(out, pc, j); } fprintf(out, "\n"); } - - free(lines); } static void usage(const char *progname) |