summary refs log tree commit diff
path: root/rv64/emit.c
diff options
context:
space:
mode:
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