summary refs log tree commit diff
diff options
context:
space:
mode:
authorMichael Forney <mforney@mforney.org>2022-05-08 12:28:45 -0700
committerQuentin Carbonneaux <quentin@c9x.me>2022-05-10 11:51:47 +0200
commit4ac7d770d6f064cd49c336c6e88c068a1d1f10c6 (patch)
tree9e1c8589ded662e5a6ad5cb4286a66556993e061
parent2caa26e388b1c904d2f12fb09f84df7e761d8331 (diff)
downloadroux-4ac7d770d6f064cd49c336c6e88c068a1d1f10c6.tar.gz
arm64: fix maximum immediate size for small loads/stores
The maximum immediate size for 1, 2, 4, and 8 byte loads/stores is
4095, 8190, 16380, and 32760 respectively[0][1][2].

[0] https://developer.arm.com/documentation/dui0802/a/A64-Data-Transfer-Instructions/LDRB--immediate-
[1] https://developer.arm.com/documentation/dui0802/a/A64-Data-Transfer-Instructions/LDRH--immediate-
[2] https://developer.arm.com/documentation/dui0802/a/A64-Data-Transfer-Instructions/LDR--immediate-
-rw-r--r--arm64/emit.c8
1 files changed, 4 insertions, 4 deletions
diff --git a/arm64/emit.c b/arm64/emit.c
index 47097b7..2506eea 100644
--- a/arm64/emit.c
+++ b/arm64/emit.c
@@ -285,7 +285,7 @@ loadcon(Con *c, int r, int k, FILE *f)
 static void emitins(Ins *, E *);
 
 static void
-fixarg(Ref *pr, E *e)
+fixarg(Ref *pr, int sz, E *e)
 {
 	Ins *i;
 	Ref r;
@@ -294,7 +294,7 @@ fixarg(Ref *pr, E *e)
 	r = *pr;
 	if (rtype(r) == RSlot) {
 		s = slot(r.val, e);
-		if (s > 32760) {
+		if (s > sz * 4095u) {
 			i = &(Ins){Oaddr, Kl, TMP(IP0), {r}};
 			emitins(i, e);
 			*pr = TMP(IP0);
@@ -313,9 +313,9 @@ emitins(Ins *i, E *e)
 	switch (i->op) {
 	default:
 		if (isload(i->op))
-			fixarg(&i->arg[0], e);
+			fixarg(&i->arg[0], loadsz(i), e);
 		if (isstore(i->op))
-			fixarg(&i->arg[1], e);
+			fixarg(&i->arg[1], storesz(i), e);
 	Table:
 		/* most instructions are just pulled out of
 		 * the table omap[], some special cases are