diff options
-rw-r--r-- | arm64/emit.c | 65 | ||||
-rw-r--r-- | arm64/isel.c | 31 | ||||
-rw-r--r-- | emit.c | 28 |
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 |