Browse Source

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-
Michael Forney 3 years ago
parent
commit
4ac7d770d6
1 changed files with 4 additions and 4 deletions
  1. 4 4
      arm64/emit.c

+ 4 - 4
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