summary refs log tree commit diff
path: root/arm64/emit.c
diff options
context:
space:
mode:
Diffstat (limited to 'arm64/emit.c')
-rw-r--r--arm64/emit.c58
1 files changed, 38 insertions, 20 deletions
diff --git a/arm64/emit.c b/arm64/emit.c
index 55f5ce6..18c19d2 100644
--- a/arm64/emit.c
+++ b/arm64/emit.c
@@ -7,6 +7,7 @@ struct E {
 	Fn *fn;
 	uint64_t frame;
 	uint padding;
+	int apple;
 };
 
 #define CMP(X) \
@@ -144,10 +145,10 @@ slot(int s, E *e)
 	if (s == -1)
 		return 16 + e->frame;
 	if (s < 0) {
-		if (e->fn->vararg)
-			return 16 + e->frame + 192 - (s+2)*8;
+		if (e->fn->vararg && !e->apple)
+			return 16 + e->frame + 192 - (s+2);
 		else
-			return 16 + e->frame - (s+2)*8;
+			return 16 + e->frame - (s+2);
 	} else
 		return 16 + e->padding + 4 * s;
 }
@@ -243,8 +244,16 @@ emitf(char *s, Ins *i, E *e)
 }
 
 static void
-loadcon(Con *c, int r, int k, FILE *f)
+loadcon(Con *c, int r, int k, 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 *rn, *l, *p, off[32];
 	int64_t n;
 	int w, sh;
@@ -261,24 +270,22 @@ loadcon(Con *c, int r, int k, FILE *f)
 			off[0] = 0;
 		l = str(c->label);
 		p = c->local ? T.asloc : l[0] == '"' ? "" : T.assym;
-		fprintf(f, "\tadrp\t%s, %s%s%s\n",
-			rn, p, l, off);
-		fprintf(f, "\tadd\t%s, %s, #:lo12:%s%s%s\n",
-			rn, rn, p, l, off);
+		fprintf(e->f, ldsym[e->apple][0], rn, p, l, off);
+		fprintf(e->f, ldsym[e->apple][1], rn, rn, p, l, off);
 		return;
 	}
 	assert(c->type == CBits);
 	if (!w)
 		n = (int32_t)n;
 	if ((n | 0xffff) == -1 || arm64_logimm(n, k)) {
-		fprintf(f, "\tmov\t%s, #%"PRIi64"\n", rn, n);
+		fprintf(e->f, "\tmov\t%s, #%"PRIi64"\n", rn, n);
 	} else {
-		fprintf(f, "\tmov\t%s, #%d\n",
+		fprintf(e->f, "\tmov\t%s, #%d\n",
 			rn, (int)(n & 0xffff));
 		for (sh=16; n>>=16; sh+=16) {
 			if ((!w && sh == 32) || sh == 64)
 				break;
-			fprintf(f, "\tmovk\t%s, #0x%x, lsl #%d\n",
+			fprintf(e->f, "\tmovk\t%s, #0x%x, lsl #%d\n",
 				rn, (uint)(n & 0xffff), sh);
 		}
 	}
@@ -358,7 +365,7 @@ emitins(Ins *i, E *e)
 		switch (rtype(i->arg[0])) {
 		case RCon:
 			c = &e->fn->con[i->arg[0].val];
-			loadcon(c, i->to.val, i->cls, e->f);
+			loadcon(c, i->to.val, i->cls, e);
 			break;
 		case RSlot:
 			i->op = Oload;
@@ -450,8 +457,8 @@ framelayout(E *e)
 
 */
 
-void
-arm64_emitfn(Fn *fn, FILE *out)
+static void
+emitfn(E *e)
 {
 	static char *ctoa[] = {
 	#define X(c, s) [c] = s,
@@ -463,13 +470,11 @@ arm64_emitfn(Fn *fn, FILE *out)
 	uint64_t o;
 	Blk *b, *t;
 	Ins *i;
-	E *e;
 
-	emitlnk(fn->name, &fn->lnk, ".text", out);
-	e = &(E){.f = out, .fn = fn};
+	emitlnk(e->fn->name, &e->fn->lnk, ".text", e->f);
 	framelayout(e);
 
-	if (e->fn->vararg) {
+	if (e->fn->vararg && !e->apple) {
 		for (n=7; n>=0; n--)
 			fprintf(e->f, "\tstr\tq%d, [sp, -16]!\n", n);
 		for (n=7; n>=0; n-=2)
@@ -531,7 +536,7 @@ arm64_emitfn(Fn *fn, FILE *out)
 			if (e->fn->dynalloc)
 				fputs("\tmov sp, x29\n", e->f);
 			o = e->frame + 16;
-			if (e->fn->vararg)
+			if (e->fn->vararg && !e->apple)
 				o += 192;
 			if (o <= 504)
 				fprintf(e->f,
@@ -589,5 +594,18 @@ arm64_emitfn(Fn *fn, FILE *out)
 		}
 	}
 	id0 += e->fn->nblk;
-	elf_emitfnfin(e->fn->name, e->f);
+}
+
+void
+arm64_emitfn(Fn *fn, FILE *out)
+{
+	emitfn(&(E){.f = out, .fn = fn, .apple = 0});
+	elf_emitfnfin(fn->name, out);
+}
+
+void
+apple_emitfn(Fn *fn, FILE *out)
+{
+	fn->lnk.align = 4;
+	emitfn(&(E){.f = out, .fn = fn, .apple = 1});
 }