aboutsummaryrefslogtreecommitdiff
path: root/assemble.c
diff options
context:
space:
mode:
authortomsmeding <tom.smeding@gmail.com>2018-01-06 21:38:40 +0100
committertomsmeding <tom.smeding@gmail.com>2018-01-06 21:38:40 +0100
commitf4b60f43cf636d48f8857676b072371f1575a5b2 (patch)
treed185ecd5d15b379e64474030bad8a2ab386c4284 /assemble.c
parentc4a376d1c7263993f13e9cf276ebd9e530fd419c (diff)
Working compiler
Diffstat (limited to 'assemble.c')
-rw-r--r--assemble.c117
1 files changed, 117 insertions, 0 deletions
diff --git a/assemble.c b/assemble.c
new file mode 100644
index 0000000..cdc584c
--- /dev/null
+++ b/assemble.c
@@ -0,0 +1,117 @@
+#include <stdlib.h>
+#include <assert.h>
+#include "assemble.h"
+
+
+static void aRef(struct ref ref, FILE *f) {
+ char buf[40];
+ ref_show(ref, buf);
+ fprintf(f, "%s", buf);
+}
+
+static void assemble_ins(const struct irins *ins, FILE *f) {
+ switch (ins->type) {
+ case INS_ADD:
+ assert(ref_equal(ins->r0, ins->r1));
+ fprintf(f, "\tadd "); aRef(ins->r1, f); fprintf(f, ", "); aRef(ins->r2, f); fprintf(f, "\n");
+ break;
+
+ case INS_SUB:
+ assert(ref_equal(ins->r0, ins->r1));
+ fprintf(f, "\tsub "); aRef(ins->r1, f); fprintf(f, ", "); aRef(ins->r2, f); fprintf(f, "\n");
+ break;
+
+ case INS_MUL:
+ assert(ref_equal(ins->r0, ref_reg(REG_A)));
+ assert(ref_equal(ins->r0, ins->r1));
+ fprintf(f, "\tmul "); aRef(ins->r2, f); fprintf(f, "\n");
+ break;
+
+ case INS_DIV:
+ fprintf(stderr, "DIV not implemented...\n"); exit(1);
+ assert(ref_equal(ins->r0, ins->r1));
+ fprintf(f, "\tdiv "); aRef(ins->r1, f); fprintf(f, ", "); aRef(ins->r2, f); fprintf(f, "\n");
+ break;
+
+ case INS_MOD:
+ fprintf(stderr, "MOD not implemented...\n"); exit(1);
+ assert(ref_equal(ins->r0, ins->r1));
+ fprintf(f, "\tmod "); aRef(ins->r1, f); fprintf(f, ", "); aRef(ins->r2, f); fprintf(f, "\n");
+ break;
+
+ case INS_NEG:
+ fprintf(f, "\tneg "); aRef(ins->r1, f); fprintf(f, "\n");
+ break;
+
+ case INS_NOT:
+ fprintf(f, "\tnot "); aRef(ins->r1, f); fprintf(f, "\n");
+ break;
+
+ case INS_TEST:
+ fprintf(f, "\ttest "); aRef(ins->r1, f); fprintf(f, ", "); aRef(ins->r2, f); fprintf(f, "\n");
+ break;
+
+ case INS_PUSH:
+ fprintf(f, "\tpush "); aRef(ins->r1, f); fprintf(f, "\n");
+ break;
+
+ case INS_POP:
+ fprintf(f, "\tpop "); aRef(ins->r0, f); fprintf(f, "\n");
+ break;
+
+ case INS_CMP:
+ fprintf(f, "\tcmp "); aRef(ins->r1, f); fprintf(f, ", "); aRef(ins->r2, f); fprintf(f, "\n");
+ break;
+
+ case INS_LBL:
+ fprintf(f, "%s:\n", ins->name);
+ break;
+
+ case INS_JMP:
+ fprintf(f, "\tjmp %s\n", ins->name);
+ break;
+
+ case INS_JCC:
+ fprintf(f, "\tj%s %s\n", condcode_show(ins->condcode), ins->name);
+ break;
+
+ case INS_CALL:
+ fprintf(f, "\tcall %s\n", ins->name);
+ break;
+
+ case INS_RET:
+ fprintf(f, "\tret\n");
+ break;
+
+ case INS_MOV:
+ fprintf(f, "\tmov "); aRef(ins->r0, f); fprintf(f, ", "); aRef(ins->r1, f); fprintf(f, "\n");
+ break;
+
+ case INS_BRK:
+ fprintf(f, "\tbrk\n");
+ break;
+
+ case INS_CALLV:
+ case INS_RETV:
+ assert(false);
+
+ default:
+ assert(false);
+ }
+}
+
+void assemble(const struct ir *ir, FILE *f) {
+ if (ir->globspace > 0) {
+ fprintf(f, ".data\n\tdw ");
+ for (int i = 0; i < ir->globspace; i++) {
+ if (i != 0) fprintf(f, ", ");
+ fprintf(f, "0");
+ }
+ fprintf(f, "\n");
+ }
+ fprintf(f, ".text\n");
+
+ for (int i = 0; i < ir->len; i++) {
+ assemble_ins(ir->inss[i], f);
+ }
+}