aboutsummaryrefslogtreecommitdiff
path: root/arm64
diff options
context:
space:
mode:
authorQuentin Carbonneaux <[email protected]>2024-10-01 19:38:15 +0200
committerQuentin Carbonneaux <[email protected]>2024-10-01 19:42:50 +0200
commit90050202f57b22243f5d3dd434a81df2f89de9ed (patch)
treed72a890222adcf345e6cbfa1b1d7ac2639cc9a0d /arm64
parent626f0b278137ff6f8b7d910d9b3fc3cbdfbb39fc (diff)
fix various codegen bugs on arm64
- dynamic allocations could generate bad 'and' instructions (for the and with -16 in salloc()). - symbols used in w context would generate adrp and add instructions on wN registers while they seem to only work on xN registers. Thanks to Rosie for reporting them.
Diffstat (limited to 'arm64')
-rw-r--r--arm64/emit.c19
1 files changed, 14 insertions, 5 deletions
diff --git a/arm64/emit.c b/arm64/emit.c
index ffdc178..28cd6a5 100644
--- a/arm64/emit.c
+++ b/arm64/emit.c
@@ -160,7 +160,8 @@ emitf(char *s, Ins *i, E *e)
Ref r;
int k, c;
Con *pc;
- uint n, sp;
+ uint64_t n;
+ uint sp;
fputc('\t', e->f);
@@ -217,10 +218,17 @@ emitf(char *s, Ins *i, E *e)
pc = &e->fn->con[r.val];
n = pc->bits.i;
assert(pc->type == CBits);
- if (n & 0xfff000)
- fprintf(e->f, "#%u, lsl #12", n>>12);
- else
- fprintf(e->f, "#%u", n);
+ if (n >> 24) {
+ assert(arm64_logimm(n, k));
+ fprintf(e->f, "#%"PRIu64, n);
+ } else if (n & 0xfff000) {
+ assert(!(n & ~0xfff000ull));
+ fprintf(e->f, "#%"PRIu64", lsl #12",
+ n>>12);
+ } else {
+ assert(!(n & ~0xfffull));
+ fprintf(e->f, "#%"PRIu64, n);
+ }
break;
}
break;
@@ -304,6 +312,7 @@ loadcon(Con *c, int r, int k, E *e)
rn = rname(r, k);
n = c->bits.i;
if (c->type == CAddr) {
+ rn = rname(r, Kl);
loadaddr(c, rn, e);
return;
}