aboutsummaryrefslogtreecommitdiff
path: root/rv64/emit.c
diff options
context:
space:
mode:
authorQuentin Carbonneaux <[email protected]>2022-09-09 17:40:31 +0200
committerQuentin Carbonneaux <[email protected]>2022-10-08 21:48:42 +0200
commit00a30954aca97004cb6f586bdeeabb488f1e3c3f (patch)
tree951dc4c0a5be04fe7d5aed13f4201eb90c60f841 /rv64/emit.c
parent5cea0c20ee3573949a2c24e4b3dea65fcbf6e48b (diff)
add support for thread-local storage
The apple targets are not done yet.
Diffstat (limited to 'rv64/emit.c')
-rw-r--r--rv64/emit.c63
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