commit 7837770ba1018d8c3320a9eaf29920ef53ba2791
parent 8655181f63b5327a68b27da315e889094e9e6251
Author: Michael Forney <mforney@mforney.org>
Date: Wed, 8 May 2019 14:16:41 -0700
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:
1 file changed, 20 insertions(+), 6 deletions(-)
diff --git 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;