aboutsummaryrefslogtreecommitdiff
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