diff options
author | David Phillips <david@sighup.nz> | 2019-08-01 23:12:34 +1200 |
---|---|---|
committer | David Phillips <david@sighup.nz> | 2019-08-03 12:44:12 +1200 |
commit | 28d6a88c02f10b75fb4c5cb46178d2ef71629494 (patch) | |
tree | ecea67672dfc7cb638e9c8bd474850094ca5064b /output_asm.c | |
parent | 15b556038033821aa85392f4013d68999f14e231 (diff) | |
download | toy-cpu-assembler-28d6a88c02f10b75fb4c5cb46178d2ef71629494.tar.xz |
Refactor disassembler to move data through instruction list
This refactors the disassembler into two stages with the list of struct
instruction (currently also output by the parse stage) as an "intermediate
language" between disassembly and assembler output. This should make these
units, especially the "machine code => IL" section, more reusable for future
soft emulation work.
Diffstat (limited to 'output_asm.c')
-rw-r--r-- | output_asm.c | 134 |
1 files changed, 134 insertions, 0 deletions
diff --git a/output_asm.c b/output_asm.c new file mode 100644 index 0000000..b1ccfc9 --- /dev/null +++ b/output_asm.c @@ -0,0 +1,134 @@ +#include <stdio.h> +#include <stdint.h> +#include <string.h> + +#include "parse.h" +#include "util.h" + +static size_t inst_sizes[] = { + [INST_TYPE_R] = 2, + [INST_TYPE_NI] = 2, + [INST_TYPE_WI] = 4, + [INST_TYPE_JR] = 2, + [INST_TYPE_JI] = 4, + [INST_TYPE_B] = 2, +}; + +void emit_single_r_type(FILE *f, struct r_type inst) +{ + const char *oper = get_asm_from_oper(inst.oper); + const char *dest = get_asm_from_reg(inst.dest); + const char *left = get_asm_from_reg(inst.left); + const char *right = get_asm_from_reg(inst.right); + + fprintf(f, "%s %s, %s, %s\n", oper, dest, left, right); +} + +void emit_single_i_type(FILE *f, struct i_type inst) +{ + const char *oper = get_asm_from_oper(inst.oper); + const char *dest = get_asm_from_reg(inst.dest); + const char *left = get_asm_from_reg(inst.left); + + fprintf(f, "%si %s, %s, 0x%x\n", oper, dest, left, inst.imm.value); +} + +/*void emit_single_wi_type(FILE *f, struct i_type inst) +{ + const char *oper = get_asm_from_oper(inst.oper); + const char *dest = get_asm_from_oper(inst.dest); + const char *left = get_asm_from_oper(inst.left); + + fprintf(f, "%si %s, %s, 0x%s\n", oper, dest, left, inst.imm.value); +}*/ + +void emit_single_ji_type(FILE *f, struct ji_type inst) +{ + const char *cond = get_asm_from_j(inst.cond); + + fprintf(f, "%s %s\n", cond, inst.imm.value); +} + +void emit_single_jr_type(FILE *f, struct jr_type inst) +{ + const char *cond = get_asm_from_j(inst.cond); + const char *reg = get_asm_from_reg(inst.reg); + + fprintf(f, "%s %s\n", cond, reg); +} + +void emit_single_b_type(FILE *f, struct b_type inst) +{ + const char *cond = get_asm_from_b(inst.cond); + + fprintf(f, "%s 0x%x\n", cond, inst.imm.value); +} + + +int look_up_label(struct label *labels, size_t labels_count, uint16_t *val, const char *label) +{ + size_t i = 0; + + for (i = 0; i < labels_count; i++) { + if (strcmp(labels[i].name, label) == 0) { + *val = labels[i].byte_offset; + return 0; + } + } + + /* FIXME emit */ + fprintf(stderr, "Reference to undefined label `%s'\n", label); + return 1; +} + +int output_single(FILE *f, size_t *cur_byte, struct label *labels, size_t labels_count, struct instruction inst) +{ + switch (inst.type) { + case INST_TYPE_R: + emit_single_r_type(f, inst.inst.r); + break; + case INST_TYPE_NI: + case INST_TYPE_WI: + if ( inst.inst.i.imm_is_ident + && look_up_label(labels, labels_count, &inst.inst.i.imm.value, inst.inst.i.imm.label)) + return 1; + + emit_single_i_type(f, inst.inst.i); + break; + case INST_TYPE_JR: + emit_single_jr_type(f, inst.inst.jr); + break; + case INST_TYPE_JI: + if ( inst.inst.ji.imm_is_ident + && look_up_label(labels, labels_count, &inst.inst.ji.imm.value, inst.inst.ji.imm.label)) + return 1; + + emit_single_ji_type(f, inst.inst.ji); + break; + case INST_TYPE_B: + if ( inst.inst.b.imm_is_ident + && look_up_label(labels, labels_count, &inst.inst.b.imm.value, inst.inst.b.imm.label)) + return 1; + emit_single_b_type(f, inst.inst.b); + break; + default: + fprintf(stderr, "Internal error: unhandled instruction type\n"); + break; + } + + *cur_byte += inst_sizes[inst.type]; + + return 0; +} + +int output_asm(FILE *fout, struct label *labels, size_t label_count, struct instruction *insts, size_t insts_count) +{ + size_t i = 0; + size_t cur_byte = 0; + + for (i = 0; i < insts_count; i++) + if (output_single(fout, &cur_byte, labels, label_count, insts[i])) + return 1; + + return 0; +} |