summary refs log tree commit diff
path: root/arm64
diff options
context:
space:
mode:
authorMichael Forney <mforney@mforney.org>2021-03-01 17:41:35 -0800
committerQuentin Carbonneaux <quentin@c9x.me>2021-03-02 08:32:38 +0100
commit2feb742b6911b385fc80177f8df77315fef9cd37 (patch)
treefe6677429caa622ad88c40d9be32488fcac67fe7 /arm64
parent4756643e58965eb21e0bf2ddb45ddb24b9f8bf03 (diff)
downloadroux-2feb742b6911b385fc80177f8df77315fef9cd37.tar.gz
arm64: handle stack offsets >=4096 in Oaddr
The immediate in the add instruction is only 12 bits. If the offset
does not fit, we must move it into a register first.
Diffstat (limited to 'arm64')
-rw-r--r--arm64/emit.c16
1 files changed, 13 insertions, 3 deletions
diff --git a/arm64/emit.c b/arm64/emit.c
index 892d027..cd0a2b1 100644
--- a/arm64/emit.c
+++ b/arm64/emit.c
@@ -271,6 +271,8 @@ static void
 emitins(Ins *i, E *e)
 {
 	int o;
+	char *rn;
+	uint64_t s;
 
 	switch (i->op) {
 	default:
@@ -302,9 +304,17 @@ emitins(Ins *i, E *e)
 		break;
 	case Oaddr:
 		assert(rtype(i->arg[0]) == RSlot);
-		fprintf(e->f, "\tadd\t%s, x29, #%"PRIu64"\n",
-			rname(i->to.val, Kl), slot(i->arg[0].val, e)
-		);
+		rn = rname(i->to.val, Kl);
+		s = slot(i->arg[0].val, e);
+		if (s <= 4095) {
+			fprintf(e->f, "\tadd\t%s, x29, #%"PRIu64"\n", rn, s);
+		} else {
+			fprintf(e->f,
+				"\tmov\t%s, #%"PRIu64"\n"
+				"\tadd\t%s, x29, %s\n",
+				rn, s, rn, rn
+			);
+		}
 		break;
 	}
 }