diff options
| author | Kimplul <kimi.h.kuparinen@gmail.com> | 2023-11-19 19:59:53 +0200 |
|---|---|---|
| committer | Kimplul <kimi.h.kuparinen@gmail.com> | 2023-11-19 19:59:53 +0200 |
| commit | 17a27d445295bbaf7c7c470b1e4648635af2f0a3 (patch) | |
| tree | 2749eacfe577afc1902826a99a4437bfc8419f05 /src/asm.c | |
| parent | 8f754f8b13e55e4bb92d72f105c5aaaba1754b7d (diff) | |
| download | ek-17a27d445295bbaf7c7c470b1e4648635af2f0a3.tar.gz ek-17a27d445295bbaf7c7c470b1e4648635af2f0a3.zip | |
first runnable test program
+ tests/pointer_literal.ek compiles down to very simple assembly that
tasm can assemble and triscv run with correct results. Whopee
+ Did notice that void return functions should still have implicit return statements added
Diffstat (limited to 'src/asm.c')
| -rw-r--r-- | src/asm.c | 96 |
1 files changed, 96 insertions, 0 deletions
diff --git a/src/asm.c b/src/asm.c new file mode 100644 index 0000000..4102265 --- /dev/null +++ b/src/asm.c @@ -0,0 +1,96 @@ +#include <ek/ops.h> +#include <stdio.h> +#include <stdlib.h> +#include <assert.h> + +/* I guess using the zero register might be okay in some scenarios, but for now + * I'll just keep it an illegal register */ +#define ASSERT_REG(x) {assert(x->kind == LOC_REG); assert(x->reg > 0 && x->reg < 81);} +#define ASSERT_MEM(x) {assert(x->kind == LOC_MEM); assert(x->reg > 0 && x->reg < 81);} + +static int print_comment(struct op *op, FILE *f) +{ + fprintf(f, "/* %s */\n", op->string); + return 0; +} + +static int print_label(struct op *op, FILE *f) +{ + fprintf(f, "%s:\n", op->string); + return 0; +} + +static int print_li(struct op *op, FILE *f) +{ + struct loc *o = &op->outputs; + assert(o->next == NULL); + /* unsure if this will always hold, but for now */ + ASSERT_REG(o); + + fprintf(f, "li x%zd, %lld\n", o->reg, op->constant); + return 0; +} + +static int print_mv(struct op *op, FILE *f) +{ + struct loc *i = &op->inputs; + struct loc *o = &op->outputs; + assert(i->next == NULL); + assert(o->next == NULL); + ASSERT_REG(i); + ASSERT_REG(o); + + fprintf(f, "mv x%zd, x%zd\n", o->reg, i->reg); + return 0; +} + +static int print_stt(struct op *op, FILE *f) +{ + struct loc *i = &op->inputs; + struct loc *o = &op->outputs; + assert(i->next == NULL); + assert(o->next == NULL); + ASSERT_REG(i); + ASSERT_MEM(o); + + fprintf(f, "st t, x%zd, %lld(x%zd)\n", i->reg, o->off, o->reg); + return 0; +} + +static int print_op(struct op *op, FILE *f) +{ + int ret = 0; + switch (op->opcode) { + case OP_COMMENT: ret = print_comment(op, f); break; + case OP_LABEL: ret = print_label(op, f); break; + case OP_LI: ret = print_li(op, f); break; + case OP_MV: ret = print_mv(op, f); break; + case OP_STT: ret = print_stt(op, f); break; + default: abort(); + } + + return ret; +} + +int print_asm(struct ops *ops, const char *output) +{ + FILE *f = fopen(output, "w"); + + /* main should probably be mangled here as well */ + fprintf(f, "jal x0, main\n"); + int ret = 0; + struct op *op = ops->base; + while (op) { + if ((ret = print_op(op, f))) + break; + + op = op->next; + } + + /* tell simulator to turn off (very much temp) */ + fprintf(f, "li x1, 3\n"); + fprintf(f, "csrrw mpower, x0, x1\n"); + + fclose(f); + return ret; +} |
