summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--arm64/emit.c65
-rw-r--r--arm64/isel.c31
-rw-r--r--emit.c28
3 files changed, 92 insertions, 32 deletions
diff --git a/arm64/emit.c b/arm64/emit.c
index 7316f78..292dc79 100644
--- a/arm64/emit.c
+++ b/arm64/emit.c
@@ -245,33 +245,50 @@ emitf(char *s, Ins *i, E *e)
 static void
 loadaddr(Con *c, char *rn, E *e)
 {
-	static char *ldsym[][2] = {
-		/* arm64 */
-		[0][0] = "\tadrp\t%s, %s%s%s\n",
-		[0][1] = "\tadd\t%s, %s, #:lo12:%s%s%s\n",
-		/* apple */
-		[1][0] = "\tadrp\t%s, %s%s@page%s\n",
-		[1][1] = "\tadd\t%s, %s, %s%s@pageoff%s\n",
-	};
-	char *p, *l, off[32];
+	char *p, *l, *s;
+
+	switch (c->reloc) {
+	default:
+		die("unreachable");
+	case RelDef:
+		if (T.apple)
+			s = "\tadrp\tR, S@pageO\n"
+			    "\tadd\tR, R, S@pageoffO\n";
+		else
+			s = "\tadrp\tR, SO\n"
+			    "\tadd\tR, R, #:lo12:SO\n";
+		break;
+	case RelThr:
+		if (T.apple)
+			s = "\tadrp\tR, S@tlvppage\n"
+			    "\tldr\tR, [R, S@tlvppageoff]\n";
+		else
+			s = "\tmrs\tR, tpidr_el0\n"
+			    "\tadd\tR, R, #:tprel_hi12:SO, lsl #12\n"
+			    "\tadd\tR, R, #:tprel_lo12_nc:SO\n";
+		break;
+	}
 
-	if (c->bits.i)
-		/* todo, handle large offsets */
-		sprintf(off, "+%"PRIi64, c->bits.i);
-	else
-		off[0] = 0;
 	l = str(c->label);
 	p = l[0] == '"' ? "" : T.assym;
-	if (c->reloc == RelThr) {
-		fprintf(e->f, "\tmrs\t%s, tpidr_el0\n", rn);
-		fprintf(e->f, "\tadd\t%s, %s, #:tprel_hi12:%s%s%s, lsl #12\n",
-			rn, rn, p, l, off);
-		fprintf(e->f, "\tadd\t%s, %s, #:tprel_lo12_nc:%s%s%s\n",
-			rn, rn, p, l, off);
-	} else {
-		fprintf(e->f, ldsym[T.apple != 0][0], rn, p, l, off);
-		fprintf(e->f, ldsym[T.apple != 0][1], rn, rn, p, l, off);
-	}
+	for (; *s; s++)
+		switch (*s) {
+		default:
+			fputc(*s, e->f);
+			break;
+		case 'R':
+			fputs(rn, e->f);
+			break;
+		case 'S':
+			fputs(p, e->f);
+			fputs(l, e->f);
+			break;
+		case 'O':
+			if (c->bits.i)
+				/* todo, handle large offsets */
+				fprintf(e->f, "+%"PRIi64, c->bits.i);
+			break;
+		}
 }
 
 static void
diff --git a/arm64/isel.c b/arm64/isel.c
index 320cf33..a8d36fa 100644
--- a/arm64/isel.c
+++ b/arm64/isel.c
@@ -70,20 +70,45 @@ static void
 fixarg(Ref *pr, int k, int phi, Fn *fn)
 {
 	char buf[32];
-	Ref r0, r1, r2;
+	Ref r0, r1, r2, r3;
 	int s, n;
-	Con *c;
+	Con *c, cc;
 
 	r0 = *pr;
 	switch (rtype(r0)) {
 	case RCon:
+		c = &fn->con[r0.val];
+		if (T.apple
+		&& c->type == CAddr
+		&& c->reloc == RelThr) {
+			r1 = newtmp("isel", Kl, fn);
+			*pr = r1;
+			if (c->bits.i) {
+				r2 = newtmp("isel", Kl, fn);
+				cc = (Con){.type = CBits};
+				cc.bits.i = c->bits.i;
+				r3 = newcon(&cc, fn);
+				emit(Oadd, Kl, r1, r2, r3);
+				r1 = r2;
+			}
+			emit(Ocopy, Kl, r1, TMP(R0), R);
+			r1 = newtmp("isel", Kl, fn);
+			r2 = newtmp("isel", Kl, fn);
+			emit(Ocall, 0, R, r1, CALL(33));
+			emit(Ocopy, Kl, TMP(R0), r2, R);
+			emit(Oload, Kl, r1, r2, R);
+			cc = *c;
+			cc.bits.i = 0;
+			r3 = newcon(&cc, fn);
+			emit(Ocopy, Kl, r2, r3, R);
+			break;
+		}
 		if (KBASE(k) == 0 && phi)
 			return;
 		r1 = newtmp("isel", k, fn);
 		if (KBASE(k) == 0) {
 			emit(Ocopy, k, r1, r0, R);
 		} else {
-			c = &fn->con[r0.val];
 			n = stashbits(&c->bits, KWIDE(k) ? 8 : 4);
 			vgrow(&fn->con, ++fn->ncon);
 			c = &fn->con[fn->ncon-1];
diff --git a/emit.c b/emit.c
index 5e0f452..017c461 100644
--- a/emit.c
+++ b/emit.c
@@ -17,8 +17,27 @@ emitlnk(char *n, Lnk *l, int s, FILE *f)
 		[1][SecData] = ".section .tdata,\"awT\"",
 		[1][SecBss] = ".section .tbss,\"awT\"",
 	};
-	char *p;
-
+	char *pfx, *sfx;
+
+	pfx = n[0] == '"' ? "" : T.assym;
+	sfx = "";
+	if (T.apple && l->thread) {
+		l->sec = "__DATA";
+		l->secf = "__thread_data,thread_local_regular";
+		sfx = "$tlv$init";
+		fputs(
+			".section __DATA,__thread_vars,"
+			"thread_local_variables\n",
+			f
+		);
+		fprintf(f, "%s%s:\n", pfx, n);
+		fprintf(f,
+			"\t.quad __tlv_bootstrap\n"
+			"\t.quad 0\n"
+			"\t.quad %s%s%s\n\n",
+			pfx, n, sfx
+		);
+	}
 	if (l->sec) {
 		fprintf(f, ".section %s", l->sec);
 		if (l->secf)
@@ -28,10 +47,9 @@ emitlnk(char *n, Lnk *l, int s, FILE *f)
 	fputc('\n', f);
 	if (l->align)
 		fprintf(f, ".balign %d\n", l->align);
-	p = n[0] == '"' ? "" : T.assym;
 	if (l->export)
-		fprintf(f, ".globl %s%s\n", p, n);
-	fprintf(f, "%s%s:\n", p, n);
+		fprintf(f, ".globl %s%s\n", pfx, n);
+	fprintf(f, "%s%s%s:\n", pfx, n, sfx);
 }
 
 void