|
|
@@ -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
|
|
|
@@ -228,26 +224,45 @@ 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
|