From 22575e056586a7810007952c717eff4e9e005bdb Mon Sep 17 00:00:00 2001 From: David Phillips Date: Sat, 3 Aug 2019 14:44:12 +1200 Subject: File input and output routines away --- Makefile | 26 ++++--- asmcat.c | 2 +- assembler.c | 4 +- bincat.c | 8 +-- disassembler.c | 6 +- input/input_bin.c | 173 +++++++++++++++++++++++++++++++++++++++++++++ input/input_bin.h | 6 ++ input_bin.c | 176 --------------------------------------------- input_bin.h | 6 -- output.c | 200 ---------------------------------------------------- output.h | 6 -- output/output_asm.c | 134 +++++++++++++++++++++++++++++++++++ output/output_asm.h | 6 ++ output/output_bin.c | 200 ++++++++++++++++++++++++++++++++++++++++++++++++++++ output/output_bin.h | 6 ++ output_asm.c | 134 ----------------------------------- output_asm.h | 6 -- 17 files changed, 553 insertions(+), 546 deletions(-) create mode 100644 input/input_bin.c create mode 100644 input/input_bin.h delete mode 100644 input_bin.c delete mode 100644 input_bin.h delete mode 100644 output.c delete mode 100644 output.h create mode 100644 output/output_asm.c create mode 100644 output/output_asm.h create mode 100644 output/output_bin.c create mode 100644 output/output_bin.h delete mode 100644 output_asm.c delete mode 100644 output_asm.h diff --git a/Makefile b/Makefile index d361fc5..b6d1e6d 100644 --- a/Makefile +++ b/Makefile @@ -1,14 +1,17 @@ -CFLAGS = -Wall -Wextra -Wpedantic - EXECUTABLES = assembler disassembler asmcat bincat -ASM_OBJECTS = assembler.o lex.o parse.o output.o util.o -DISASM_OBJECTS = disassembler.o input_bin.o output_asm.o util.o -ASMCAT_OBJECTS = asmcat.o lex.o parse.o output_asm.o util.o -BINCAT_OBJECTS = bincat.o input_bin.o output.o util.o +ASM_OBJECTS = assembler.o lex.o parse.o output/output_bin.o util.o +DISASM_OBJECTS = disassembler.o input/input_bin.o output/output_asm.o util.o +ASMCAT_OBJECTS = asmcat.o lex.o parse.o output/output_asm.o util.o +BINCAT_OBJECTS = bincat.o input/input_bin.o output/output_bin.o util.o + +INCLUDE += -I. + +CFLAGS += $(INCLUDE) -Wall -Wextra -Wpedantic all: $(EXECUTABLES) +# Main executables assembler: $(ASM_OBJECTS) disassembler: $(DISASM_OBJECTS) @@ -17,14 +20,21 @@ asmcat: $(ASMCAT_OBJECTS) bincat: $(BINCAT_OBJECTS) +# Utils: FIXME lex and parse should be input? lex.o: lex.h parse.o: lex.h parse.h instruction.h util.h -output.o: parse.h - util.o: lex.h instruction.h +# Output modules +output/output_bin.o: output/output_bin.h parse.h + +output/output_asm.o: output/output_asm.h parse.h util.h + +# Intput modules +input/input_bin.o: input/input_bin.h parse.h + .PHONY: clean test clean: - rm -f $(EXECUTABLES) $(ASM_OBJECTS) $(DISASM_OBJECTS) $(ASMCAT_OBJECTS) $(BINCAT_OBJECTS) diff --git a/asmcat.c b/asmcat.c index 2791443..0acbfe3 100644 --- a/asmcat.c +++ b/asmcat.c @@ -5,7 +5,7 @@ #include "lex.h" #include "parse.h" #include "instruction.h" -#include "output_asm.h" +#include "output/output_asm.h" void print_help(const char *argv0) { diff --git a/assembler.c b/assembler.c index 36f3f03..9ffdb85 100644 --- a/assembler.c +++ b/assembler.c @@ -5,7 +5,7 @@ #include "lex.h" #include "parse.h" #include "instruction.h" -#include "output.h" +#include "output/output_bin.h" void print_help(const char *argv0) { @@ -70,7 +70,7 @@ int main(int argc, char **argv) /* FIXME insert optional pass for optimisation */ - if ((ret = output(fout, labels, labels_count, insts, insts_count))) + if ((ret = output_bin(fout, labels, labels_count, insts, insts_count))) return error_ret && ret; return 0; diff --git a/bincat.c b/bincat.c index fcda22e..bccb10d 100644 --- a/bincat.c +++ b/bincat.c @@ -4,8 +4,8 @@ #include "instruction.h" #include "parse.h" -#include "input_bin.h" -#include "output.h" +#include "input/input_bin.h" +#include "output/output_bin.h" void print_help(const char *argv0) { @@ -60,10 +60,10 @@ int main(int argc, char **argv) labels = NULL; labels_count = 0; - if ((ret = disasm(fin, &insts, &insts_count))) + if ((ret = input_bin(fin, &insts, &insts_count))) return error_ret && ret; - if ((ret = output(fout, labels, labels_count, insts, insts_count))) + if ((ret = output_bin(fout, labels, labels_count, insts, insts_count))) return error_ret && ret; return 0; diff --git a/disassembler.c b/disassembler.c index 9b3d54c..8da5a38 100644 --- a/disassembler.c +++ b/disassembler.c @@ -4,8 +4,8 @@ #include "instruction.h" #include "parse.h" -#include "input_bin.h" -#include "output_asm.h" +#include "input/input_bin.h" +#include "output/output_asm.h" void print_help(const char *argv0) { @@ -61,7 +61,7 @@ int main(int argc, char **argv) labels = NULL; labels_count = 0; - if ((ret = disasm(fin, &insts, &insts_count))) + if ((ret = input_bin(fin, &insts, &insts_count))) return error_ret && ret; if ((ret = output_asm(fout, labels, labels_count, insts, insts_count))) diff --git a/input/input_bin.c b/input/input_bin.c new file mode 100644 index 0000000..e1c9d0d --- /dev/null +++ b/input/input_bin.c @@ -0,0 +1,173 @@ +#include +#include +#include +#include + +#include "parse.h" + +static void disasm_rtype(uint16_t i, uint16_t unused, struct instruction *inst) +{ + (void)unused; + inst->type = INST_TYPE_R; + inst->inst.r.oper = GET_OPER(i); + inst->inst.r.dest = GET_REG_DEST(i); + inst->inst.r.left = GET_REG_LEFT(i); + inst->inst.r.right = GET_REG_RIGHT(i); +} + +static void disasm_nitype(uint16_t i, uint16_t unused, struct instruction *inst) +{ + (void)unused; + inst->type = INST_TYPE_NI; + inst->inst.i.oper = GET_OPER(i); + inst->inst.i.dest = GET_REG_DEST(i); + inst->inst.i.left = GET_REG_LEFT(i); + inst->inst.i.imm.value = GET_NI_IMM(i); + inst->inst.i.imm_is_ident = 0; +} + +static void disasm_witype(uint16_t i, uint16_t imm, struct instruction *inst) +{ + inst->type = INST_TYPE_WI; + inst->inst.i.oper = GET_OPER(i); + inst->inst.i.dest = GET_REG_DEST(i); + inst->inst.i.left = GET_REG_LEFT(i); + inst->inst.i.imm.value = imm; + inst->inst.i.imm_is_ident = 0; +} + +static void disasm_jreg(uint16_t i, uint16_t unused, struct instruction *inst) +{ + (void)unused; + inst->type = INST_TYPE_JR; + inst->inst.jr.cond = GET_JB_COND(i); + inst->inst.jr.reg = GET_JUMP_REG(i); +} + +static void disasm_jimm(uint16_t i, uint16_t imm, struct instruction *inst) +{ + inst->type = INST_TYPE_JI; + inst->inst.ji.cond= GET_JB_COND(i); + inst->inst.ji.imm.value = imm; + inst->inst.ji.imm_is_ident = 0; +} + +static void disasm_bimm(uint16_t i, uint16_t pc, struct instruction *inst) +{ + struct { signed int s:10; } sign; + int offset = sign.s = GET_B_OFFSET(i); + inst->type = INST_TYPE_B; + inst->inst.b.cond = GET_JB_COND(i); + inst->inst.b.imm.value = pc + 2 * offset; + inst->inst.b.imm_is_ident = 0; +} + + +/** + * FIXME move and factor out with parse.c */ +static struct instruction *insts = NULL; +static size_t insts_count = 0; +static int add_instruction(struct instruction inst) +{ + struct instruction *old_insts = insts; + insts = realloc(insts, (insts_count + 1) * sizeof(struct instruction)); + if (!insts) { + free(old_insts); + perror("realloc"); + return 1; + } + + insts[insts_count] = inst; + + insts_count++; + return 0; +} + +static int disasm_file(FILE *f) +{ + int ret = 0; + size_t offs = 0; + uint16_t inst = 0; + uint8_t c[2] = { 0 }; + size_t extra_read = 0; + uint16_t extra_arg = 0; + struct instruction i = { 0 }; + void (*disasm_inst)(uint16_t, uint16_t, struct instruction*); + + 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; + } + disasm_inst(inst, extra_arg, &i); + if (ret < 0) { + fprintf(stderr, "Error handling instruction at byte %zd\n", offs); + break; + } + if (add_instruction(i)) + return 1; + offs += sizeof(c) + extra_read; + } + if (!feof(f)) { + perror("fread"); + ret = -errno; + } + return ret; +} + +int input_bin(FILE *f, struct instruction **i, size_t *i_count) +{ + int ret = 0; + + ret = disasm_file(f); + *i = insts; + *i_count = insts_count; + + return ret; +} diff --git a/input/input_bin.h b/input/input_bin.h new file mode 100644 index 0000000..00e296c --- /dev/null +++ b/input/input_bin.h @@ -0,0 +1,6 @@ +#ifndef INPUT_BIN_H +#define INPUT_BIN_H + +int input_bin(FILE *f, struct instruction **i, size_t *i_count); + +#endif /* INPUT_BIN_H */ diff --git a/input_bin.c b/input_bin.c deleted file mode 100644 index c914cd1..0000000 --- a/input_bin.c +++ /dev/null @@ -1,176 +0,0 @@ -#include -#include -#include -#include - -#include "parse.h" - -static void disasm_rtype(uint16_t i, uint16_t unused, struct instruction *inst) -{ - (void)unused; - inst->type = INST_TYPE_R; - inst->inst.r.oper = GET_OPER(i); - inst->inst.r.dest = GET_REG_DEST(i); - inst->inst.r.left = GET_REG_LEFT(i); - inst->inst.r.right = GET_REG_RIGHT(i); -} - -static void disasm_nitype(uint16_t i, uint16_t unused, struct instruction *inst) -{ - (void)unused; - inst->type = INST_TYPE_NI; - inst->inst.i.oper = GET_OPER(i); - inst->inst.i.dest = GET_REG_DEST(i); - inst->inst.i.left = GET_REG_LEFT(i); - inst->inst.i.imm.value = GET_NI_IMM(i); - inst->inst.i.imm_is_ident = 0; -} - -static void disasm_witype(uint16_t i, uint16_t imm, struct instruction *inst) -{ - inst->type = INST_TYPE_WI; - inst->inst.i.oper = GET_OPER(i); - inst->inst.i.dest = GET_REG_DEST(i); - inst->inst.i.left = GET_REG_LEFT(i); - inst->inst.i.imm.value = imm; - inst->inst.i.imm_is_ident = 0; -} - -static void disasm_jreg(uint16_t i, uint16_t unused, struct instruction *inst) -{ - (void)unused; - inst->type = INST_TYPE_JR; - inst->inst.jr.cond = GET_JB_COND(i); - inst->inst.jr.reg = GET_JUMP_REG(i); -} - -static void disasm_jimm(uint16_t i, uint16_t imm, struct instruction *inst) -{ - inst->type = INST_TYPE_JI; - inst->inst.ji.cond= GET_JB_COND(i); - inst->inst.ji.imm.value = imm; - inst->inst.ji.imm_is_ident = 0; -} - -static void disasm_bimm(uint16_t i, uint16_t pc, struct instruction *inst) -{ - struct { signed int s:10; } sign; - int offset = sign.s = GET_B_OFFSET(i); - inst->type = INST_TYPE_B; - inst->inst.b.cond = GET_JB_COND(i); - inst->inst.b.imm.value = pc + 2 * offset; - inst->inst.b.imm_is_ident = 0; -} - - -/** - * FIXME move and factor out with parse.c */ -static struct instruction *insts = NULL; -static size_t insts_count = 0; -static int add_instruction(struct instruction inst) -{ - struct instruction *old_insts = insts; - insts = realloc(insts, (insts_count + 1) * sizeof(struct instruction)); - if (!insts) { - free(old_insts); - perror("realloc"); - return 1; - } - - insts[insts_count] = inst; - - insts_count++; - return 0; -} - - - -/* FIXME needs whatsit arguments. f, tok, tok length */ -static int disasm_file(FILE *f) -{ - int ret = 0; - size_t offs = 0; - uint16_t inst = 0; - uint8_t c[2] = { 0 }; - size_t extra_read = 0; - uint16_t extra_arg = 0; - struct instruction i = { 0 }; - void (*disasm_inst)(uint16_t, uint16_t, struct instruction*); - - 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; - } - disasm_inst(inst, extra_arg, &i); - if (ret < 0) { - fprintf(stderr, "Error handling instruction at byte %zd\n", offs); - break; - } - if (add_instruction(i)) - return 1; - offs += sizeof(c) + extra_read; - } - if (!feof(f)) { - perror("fread"); - ret = -errno; - } - return ret; -} - -int disasm(FILE *f, struct instruction **i, size_t *i_count) -{ - int ret = 0; - - ret = disasm_file(f); - *i = insts; - *i_count = insts_count; - - return ret; -} diff --git a/input_bin.h b/input_bin.h deleted file mode 100644 index 7683835..0000000 --- a/input_bin.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef INPUT_BIN_H -#define INPUT_BIN_H - -int disasm(FILE *f, struct instruction **i, size_t *i_count); - -#endif /* INPUT_BIN_H */ diff --git a/output.c b/output.c deleted file mode 100644 index d536b7e..0000000 --- a/output.c +++ /dev/null @@ -1,200 +0,0 @@ -#include -#include -#include - -#include "parse.h" - -static size_t cur_byte; - -int generate_single_r_type(uint32_t *dest, struct r_type inst) -{ - uint32_t i = 0; - - i |= MASK_INST_RTYPE; - i |= MASK_OPER(inst.oper); - i |= MASK_REG_DEST(inst.dest); - i |= MASK_REG_LEFT(inst.left); - i |= MASK_REG_RIGHT(inst.right); - - *dest = i; - return 1; -} -int generate_single_ni_type(uint32_t *dest, struct i_type inst) -{ - uint32_t i = 0; - - i |= MASK_INST_NITYPE; - i |= MASK_OPER(inst.oper); - i |= MASK_REG_DEST(inst.dest); - i |= MASK_REG_LEFT(inst.left); - i |= MASK_NI_IMM(inst.imm.value); - - *dest = i; - return 1; -} - -int generate_single_wi_type(uint32_t *dest, struct i_type inst) -{ - uint32_t i = 0; - - i |= MASK_INST_WITYPE; - i |= MASK_OPER(inst.oper); - i |= MASK_REG_DEST(inst.dest); - i |= MASK_REG_LEFT(inst.left); - - /* two-word instruction - make room for the immediate */ - i <<= 16; - - i |= inst.imm.value; - - *dest = i; - return 2; -} - -int generate_single_ji_type(uint32_t *dest, struct ji_type inst) -{ - uint32_t i = 0; - - i |= MASK_INST_JTYPE; - i |= MASK_IS_JUMP; - i |= MASK_JB_COND(inst.cond); - i |= MASK_JI; - - /* two-word instruction - make room for the immediate */ - i <<= 16; - - i |= inst.imm.value; - - *dest = i; - return 2; -} - -int generate_single_jr_type(uint32_t *dest, struct jr_type inst) -{ - uint32_t i = 0; - - i |= MASK_INST_JTYPE; - i |= MASK_IS_JUMP; - i |= MASK_JB_COND(inst.cond); - i |= MASK_JR; - i |= MASK_JUMP_REGISTER(inst.reg); - - *dest = i; - return 1; -} - -int generate_single_b_type(uint32_t *dest, struct b_type inst) -{ - uint32_t i = 0; - - i |= MASK_INST_JTYPE; - i |= MASK_IS_BRANCH; - i |= MASK_JB_COND(inst.cond); - i |= MASK_B_OFFSET(inst.imm.value); - - *dest = i; - return 1; -} - - -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, struct label *labels, size_t labels_count, struct instruction inst) -{ - int len = 0; - uint32_t i = 0; - - switch (inst.type) { - case INST_TYPE_R: - len = generate_single_r_type(&i, inst.inst.r); - break; - case INST_TYPE_NI: - 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; - - len = generate_single_ni_type(&i, inst.inst.i); - break; - 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; - - len = generate_single_wi_type(&i, inst.inst.i); - break; - case INST_TYPE_JR: - len = generate_single_jr_type(&i, 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; - - len = generate_single_ji_type(&i, 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; - inst.inst.b.imm.value -= cur_byte; - if (inst.inst.b.imm.value % 2 != 0) { - fprintf(stderr, "Internal error: branch offset %d not a multiple of 2\n", inst.inst.b.imm.value); - } - inst.inst.b.imm.value /= 2; - - len = generate_single_b_type(&i, inst.inst.b); - break; - default: - fprintf(stderr, "Internal error: unhandled instruction type\n"); - break; - } - - if (len == 2) { -#define RAW -#ifdef RAW - fputc(0xFF & (i >> 24), f); - fputc(0xFF & (i >> 16), f); -#else - fprintf(f, "%04x ", i >> 16); -#endif - } -#ifdef RAW - fputc(0xFF & (i >> 8), f); - fputc(0xFF & (i >> 0), f); -#else - fprintf(f, "%04x ", 0xFFFF & i); -#endif - - cur_byte += 2 * len; - return 0; -} - -int output(FILE *fout, struct label *labels, size_t label_count, struct instruction *insts, size_t insts_count) -{ - size_t i = 0; - cur_byte = 0; - -#ifndef RAW - fprintf(fout, "v2.0 raw\n"); -#endif - - for (i = 0; i < insts_count; i++) - if (output_single(fout, labels, label_count, insts[i])) - return 1; - - return 0; -} diff --git a/output.h b/output.h deleted file mode 100644 index c5edc97..0000000 --- a/output.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef OUTPUT_H -#define OUTPUT_H - -int output(FILE *fout, struct label *labels, size_t label_count, struct instruction *insts, size_t insts_count); - -#endif /* OUTPUT_H */ diff --git a/output/output_asm.c b/output/output_asm.c new file mode 100644 index 0000000..fd9f792 --- /dev/null +++ b/output/output_asm.c @@ -0,0 +1,134 @@ +#include +#include +#include + +#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 0x%x\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; +} diff --git a/output/output_asm.h b/output/output_asm.h new file mode 100644 index 0000000..b4afd2a --- /dev/null +++ b/output/output_asm.h @@ -0,0 +1,6 @@ +#ifndef OUTPUT_ASM_H +#define OUTPUT_ASM_H + +int output_asm(FILE *fout, struct label *labels, size_t label_count, struct instruction *insts, size_t insts_count); + +#endif /* OUTPUT_ASM_H */ diff --git a/output/output_bin.c b/output/output_bin.c new file mode 100644 index 0000000..1c7b961 --- /dev/null +++ b/output/output_bin.c @@ -0,0 +1,200 @@ +#include +#include +#include + +#include "parse.h" + +static size_t cur_byte; + +int generate_single_r_type(uint32_t *dest, struct r_type inst) +{ + uint32_t i = 0; + + i |= MASK_INST_RTYPE; + i |= MASK_OPER(inst.oper); + i |= MASK_REG_DEST(inst.dest); + i |= MASK_REG_LEFT(inst.left); + i |= MASK_REG_RIGHT(inst.right); + + *dest = i; + return 1; +} +int generate_single_ni_type(uint32_t *dest, struct i_type inst) +{ + uint32_t i = 0; + + i |= MASK_INST_NITYPE; + i |= MASK_OPER(inst.oper); + i |= MASK_REG_DEST(inst.dest); + i |= MASK_REG_LEFT(inst.left); + i |= MASK_NI_IMM(inst.imm.value); + + *dest = i; + return 1; +} + +int generate_single_wi_type(uint32_t *dest, struct i_type inst) +{ + uint32_t i = 0; + + i |= MASK_INST_WITYPE; + i |= MASK_OPER(inst.oper); + i |= MASK_REG_DEST(inst.dest); + i |= MASK_REG_LEFT(inst.left); + + /* two-word instruction - make room for the immediate */ + i <<= 16; + + i |= inst.imm.value; + + *dest = i; + return 2; +} + +int generate_single_ji_type(uint32_t *dest, struct ji_type inst) +{ + uint32_t i = 0; + + i |= MASK_INST_JTYPE; + i |= MASK_IS_JUMP; + i |= MASK_JB_COND(inst.cond); + i |= MASK_JI; + + /* two-word instruction - make room for the immediate */ + i <<= 16; + + i |= inst.imm.value; + + *dest = i; + return 2; +} + +int generate_single_jr_type(uint32_t *dest, struct jr_type inst) +{ + uint32_t i = 0; + + i |= MASK_INST_JTYPE; + i |= MASK_IS_JUMP; + i |= MASK_JB_COND(inst.cond); + i |= MASK_JR; + i |= MASK_JUMP_REGISTER(inst.reg); + + *dest = i; + return 1; +} + +int generate_single_b_type(uint32_t *dest, struct b_type inst) +{ + uint32_t i = 0; + + i |= MASK_INST_JTYPE; + i |= MASK_IS_BRANCH; + i |= MASK_JB_COND(inst.cond); + i |= MASK_B_OFFSET(inst.imm.value); + + *dest = i; + return 1; +} + + +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, struct label *labels, size_t labels_count, struct instruction inst) +{ + int len = 0; + uint32_t i = 0; + + switch (inst.type) { + case INST_TYPE_R: + len = generate_single_r_type(&i, inst.inst.r); + break; + case INST_TYPE_NI: + 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; + + len = generate_single_ni_type(&i, inst.inst.i); + break; + 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; + + len = generate_single_wi_type(&i, inst.inst.i); + break; + case INST_TYPE_JR: + len = generate_single_jr_type(&i, 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; + + len = generate_single_ji_type(&i, 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; + inst.inst.b.imm.value -= cur_byte; + if (inst.inst.b.imm.value % 2 != 0) { + fprintf(stderr, "Internal error: branch offset %d not a multiple of 2\n", inst.inst.b.imm.value); + } + inst.inst.b.imm.value /= 2; + + len = generate_single_b_type(&i, inst.inst.b); + break; + default: + fprintf(stderr, "Internal error: unhandled instruction type\n"); + break; + } + + if (len == 2) { +#define RAW +#ifdef RAW + fputc(0xFF & (i >> 24), f); + fputc(0xFF & (i >> 16), f); +#else + fprintf(f, "%04x ", i >> 16); +#endif + } +#ifdef RAW + fputc(0xFF & (i >> 8), f); + fputc(0xFF & (i >> 0), f); +#else + fprintf(f, "%04x ", 0xFFFF & i); +#endif + + cur_byte += 2 * len; + return 0; +} + +int output_bin(FILE *fout, struct label *labels, size_t label_count, struct instruction *insts, size_t insts_count) +{ + size_t i = 0; + cur_byte = 0; + +#ifndef RAW + fprintf(fout, "v2.0 raw\n"); +#endif + + for (i = 0; i < insts_count; i++) + if (output_single(fout, labels, label_count, insts[i])) + return 1; + + return 0; +} diff --git a/output/output_bin.h b/output/output_bin.h new file mode 100644 index 0000000..d57326b --- /dev/null +++ b/output/output_bin.h @@ -0,0 +1,6 @@ +#ifndef OUTPUT_H +#define OUTPUT_H + +int output_bin(FILE *fout, struct label *labels, size_t label_count, struct instruction *insts, size_t insts_count); + +#endif /* OUTPUT_H */ diff --git a/output_asm.c b/output_asm.c deleted file mode 100644 index fd9f792..0000000 --- a/output_asm.c +++ /dev/null @@ -1,134 +0,0 @@ -#include -#include -#include - -#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 0x%x\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; -} diff --git a/output_asm.h b/output_asm.h deleted file mode 100644 index b4afd2a..0000000 --- a/output_asm.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef OUTPUT_ASM_H -#define OUTPUT_ASM_H - -int output_asm(FILE *fout, struct label *labels, size_t label_count, struct instruction *insts, size_t insts_count); - -#endif /* OUTPUT_ASM_H */ -- cgit v1.1