commit f86b3b6be24d5cfedceb4fb18bf379235a95ee73
parent 576d20cfb943575f9614b9c022c7032172e2887a
Author: Ryan Sepassi <rsepassi@gmail.com>
Date: Thu, 30 Apr 2026 00:02:53 -0700
riscv64: support large ADDI immediates in p1_addi and p1_enter
rv_addi encodes a 12-bit signed immediate (-2048..2047) and silently
truncates anything outside that range. Functions with large stack frames
(e.g. cc__next_nomacro1, ~5 KB) produced a frame smaller than requested,
corrupting later stack-slot accesses — the same structural bug fixed
recently for aarch64.
Add rv_addi_any: when the immediate fits in 12 bits, emit a plain ADDI;
otherwise materialise the value into the per-expansion `scratch`
register via the existing 64-bit literal-pool prefix and combine with
an R-type ADD. Wire p1_addi and both rv_addi calls in p1_enter through
the _any helper.
Regression: the existing arch-portable tests/p1/large-addi.P1pp now
passes on riscv64 (it failed before this commit with `BAD`).
Diffstat:
1 file changed, 19 insertions(+), 3 deletions(-)
diff --git a/P1/P1-riscv64.M1pp b/P1/P1-riscv64.M1pp
@@ -201,6 +201,22 @@
%rv_i_type(0x00000013, rd, ra, imm12)
%endm
+# rv_addi with arbitrary 64-bit signed immediate. Falls back to a
+# 64-bit literal load into `scratch` followed by an R-type ADD when the
+# immediate doesn't fit in ADDI's 12-bit signed field. `scratch` (t5/x30)
+# is per-expansion and never live across ops, so clobbering it is safe.
+%macro rv_addi_any(rd, ra, imm)
+%select((>= imm -2048),
+ %select((<= imm 2047),
+ %rv_addi(rd, ra, imm),
+ %rv_lit64_prefix(scratch)
+ $(imm)
+ %rv_r_type(0x00000033, rd, ra, scratch)),
+ %rv_lit64_prefix(scratch)
+ $(imm)
+ %rv_r_type(0x00000033, rd, ra, scratch))
+%endm
+
%macro rv_ld(rd, ra, imm12)
%rv_i_type(0x00003003, rd, ra, imm12)
%endm
@@ -342,7 +358,7 @@ $(imm)
%endm
%macro p1_addi(rd, ra, imm)
-%rv_addi(rd, ra, imm)
+%rv_addi_any(rd, ra, imm)
%endm
%macro p1_logi_ANDI(rd, ra, imm)
@@ -473,9 +489,9 @@ $(imm)
%endm
%macro p1_enter(size)
-%rv_addi(sp, sp, (- 0 (& (+ (+ 16 size) 15) -16)))
+%rv_addi_any(sp, sp, (- 0 (& (+ (+ 16 size) 15) -16)))
%rv_sd(ra, sp, 0)
-%rv_addi(fp, sp, (& (+ (+ 16 size) 15) -16))
+%rv_addi_any(fp, sp, (& (+ (+ 16 size) 15) -16))
%rv_sd(fp, sp, 8)
%endm