diff options
author | Michael Forney <mforney@mforney.org> | 2021-03-01 17:41:35 -0800 |
---|---|---|
committer | Quentin Carbonneaux <quentin@c9x.me> | 2021-03-02 08:32:38 +0100 |
commit | 2feb742b6911b385fc80177f8df77315fef9cd37 (patch) | |
tree | fe6677429caa622ad88c40d9be32488fcac67fe7 | |
parent | 4756643e58965eb21e0bf2ddb45ddb24b9f8bf03 (diff) | |
download | roux-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.
-rw-r--r-- | arm64/emit.c | 16 |
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; } } |