diff options
author | Michael Forney <mforney@mforney.org> | 2019-05-08 14:16:41 -0700 |
---|---|---|
committer | Quentin Carbonneaux <quentin@c9x.me> | 2019-05-15 11:43:50 +0200 |
commit | 7837770ba1018d8c3320a9eaf29920ef53ba2791 (patch) | |
tree | 737c67fd04f63ccaec288920fd1217a7abe94d58 /arm64 | |
parent | 8655181f63b5327a68b27da315e889094e9e6251 (diff) | |
download | roux-7837770ba1018d8c3320a9eaf29920ef53ba2791.tar.gz |
arm64: Handle stack allocations larger than 4095 bytes
In this case, the immediate is too large to use directly in the add/sub instructions, so move it into a temporary register first. Also, for clarity, rearrange the if-conditions so that they match the constraints of the instructions that immediately follow.
Diffstat (limited to 'arm64')
-rw-r--r-- | arm64/emit.c | 26 |
1 files changed, 20 insertions, 6 deletions
diff --git a/arm64/emit.c b/arm64/emit.c index 7c5b2b6..59e1aae 100644 --- a/arm64/emit.c +++ b/arm64/emit.c @@ -382,7 +382,12 @@ arm64_emitfn(Fn *fn, FILE *out) fprintf(e->f, "\tstr\tx%d, [sp, -8]!\n", n); } - if (e->frame + 16 > 512) + if (e->frame + 16 <= 512) + fprintf(e->f, + "\tstp\tx29, x30, [sp, -%"PRIu64"]!\n", + e->frame + 16 + ); + else if (e->frame <= 4095) fprintf(e->f, "\tsub\tsp, sp, #%"PRIu64"\n" "\tstp\tx29, x30, [sp, -16]!\n", @@ -390,8 +395,10 @@ arm64_emitfn(Fn *fn, FILE *out) ); else fprintf(e->f, - "\tstp\tx29, x30, [sp, -%"PRIu64"]!\n", - e->frame + 16 + "\tmov\tx16, #%"PRIu64"\n" + "\tsub\tsp, sp, x16\n" + "\tstp\tx29, x30, [sp, -16]!\n", + e->frame ); fputs("\tadd\tx29, sp, 0\n", e->f); for (o=e->frame+16, r=arm64_rclob; *r>=0; r++) @@ -418,7 +425,12 @@ arm64_emitfn(Fn *fn, FILE *out) o = e->frame + 16; if (e->fn->vararg) o += 192; - if (o > 504) + if (o <= 504) + fprintf(e->f, + "\tldp\tx29, x30, [sp], %"PRIu64"\n", + o + ); + else if (o - 16 <= 4095) fprintf(e->f, "\tldp\tx29, x30, [sp], 16\n" "\tadd\tsp, sp, #%"PRIu64"\n", @@ -426,8 +438,10 @@ arm64_emitfn(Fn *fn, FILE *out) ); else fprintf(e->f, - "\tldp\tx29, x30, [sp], %"PRIu64"\n", - o + "\tldp\tx29, x30, [sp], 16\n" + "\tmov\tx16, #%"PRIu64"\n" + "\tadd\tsp, sp, x16\n", + o - 16 ); fprintf(e->f, "\tret\n"); break; |