diff options
Diffstat (limited to 'rv64/emit.c')
-rw-r--r-- | rv64/emit.c | 63 |
1 files changed, 43 insertions, 20 deletions
diff --git a/rv64/emit.c b/rv64/emit.c index 1fdc4b2..a176c11 100644 --- a/rv64/emit.c +++ b/rv64/emit.c @@ -129,14 +129,10 @@ slot(int s, Fn *fn) static void emitaddr(Con *c, FILE *f) { - char off[32], *p; - + assert(c->rel == RelDef); + fputs(str(c->label), f); if (c->bits.i) - sprintf(off, "+%"PRIi64, c->bits.i); - else - off[0] = 0; - p = c->local ? ".L" : ""; - fprintf(f, "%s%s%s", p, str(c->label), off); + fprintf(f, "+%"PRIi64, c->bits.i); } static void @@ -229,25 +225,44 @@ emitf(char *s, Ins *i, Fn *fn, FILE *f) } static void +loadaddr(Con *c, char *rn, FILE *f) +{ + char off[32]; + + if (c->rel == RelThr) { + if (c->bits.i) + sprintf(off, "+%"PRIi64, c->bits.i); + else + off[0] = 0; + fprintf(f, "\tlui %s, %%tprel_hi(%s)%s\n", + rn, str(c->label), off); + fprintf(f, "\tadd %s, %s, tp, %%tprel_add(%s)%s\n", + rn, rn, str(c->label), off); + fprintf(f, "\taddi %s, %s, %%tprel_lo(%s)%s\n", + rn, rn, str(c->label), off); + } else { + fprintf(f, "\tla %s, ", rn); + emitaddr(c, f); + fputc('\n', f); + } +} + +static void loadcon(Con *c, int r, int k, FILE *f) { char *rn; int64_t n; - int w; - w = KWIDE(k); rn = rname[r]; switch (c->type) { case CAddr: - fprintf(f, "\tla %s, ", rn); - emitaddr(c, f); - fputc('\n', f); + loadaddr(c, rn, f); break; case CBits: n = c->bits.i; - if (!w) + if (!KWIDE(k)) n = (int32_t)n; - fprintf(f, "\tli %s, %"PRIu64"\n", rn, n); + fprintf(f, "\tli %s, %"PRIi64"\n", rn, n); break; default: die("invalid constant"); @@ -255,12 +270,20 @@ loadcon(Con *c, int r, int k, FILE *f) } static void -fixslot(Ref *pr, Fn *fn, FILE *f) +fixmem(Ref *pr, Fn *fn, FILE *f) { Ref r; int64_t s; + Con *c; r = *pr; + if (rtype(r) == RCon) { + c = &fn->con[r.val]; + if (c->type == CAddr && c->rel == RelThr) { + loadcon(c, T6, Kl, f); + *pr = TMP(T6); + } + } if (rtype(r) == RSlot) { s = slot(r.val, fn); if (s < -2048 || s > 2047) { @@ -282,9 +305,9 @@ emitins(Ins *i, Fn *fn, FILE *f) switch (i->op) { default: if (isload(i->op)) - fixslot(&i->arg[0], fn, f); + fixmem(&i->arg[0], fn, f); else if (isstore(i->op)) - fixslot(&i->arg[1], fn, f); + fixmem(&i->arg[1], fn, f); Table: /* most instructions are just pulled out of * the table omap[], some special cases are @@ -321,7 +344,7 @@ emitins(Ins *i, Fn *fn, FILE *f) case Ks: i->op = Ostores; break; case Kd: i->op = Ostored; break; } - fixslot(&i->arg[1], fn, f); + fixmem(&i->arg[1], fn, f); goto Table; } break; @@ -333,7 +356,7 @@ emitins(Ins *i, Fn *fn, FILE *f) break; case RSlot: i->op = Oload; - fixslot(&i->arg[0], fn, f); + fixmem(&i->arg[0], fn, f); goto Table; default: assert(isreg(i->arg[0])); @@ -415,7 +438,7 @@ rv64_emitfn(Fn *fn, FILE *f) Blk *b, *s; Ins *i; - emitlnk(fn->name, &fn->lnk, ".text", f); + emitfnlnk(fn->name, &fn->lnk, f); if (fn->vararg) { /* TODO: only need space for registers |