summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--nqdasm.c98
1 files changed, 33 insertions, 65 deletions
diff --git a/nqdasm.c b/nqdasm.c
index d7016fb..5449c06 100644
--- a/nqdasm.c
+++ b/nqdasm.c
@@ -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)