RISC-V: Fix FPR saves below SP with Zcmp
RISC-V code generation for Zcmp extension avoids corrupted callee-saved FPRs on interrupt.
This change corrects how callee-saved floating-point registers (FPRs) are saved on the stack when using the RISC-V Zcmp extension and optimizing for size (-Os). Previously, the prologue could incorrectly calculate the space needed for these registers, leading to them being stored below the stack pointer without sufficient allocation. This could cause an interrupt to overwrite these registers before they were properly saved, corrupting program state. The fix ensures that only as many FPRs are folded into the cm.push reserve as can be physically stored.
In Details
The RISC-V cm.push instruction reserves stack space for callee-saved FPRs. With -Os, the prologue might fold FPRs into this reserved space. A bug in get_multi_push_fpr_mask caused it to calculate a mask that allowed more FPRs than the reserved byte count could hold, especially when dividing by UNITS_PER_WORD (4 bytes) for 8-byte FPRs. Surplus FPRs were stored at negative offsets below SP, relying on a later addi sp, sp, -N. This commit corrects the calculation in riscv_expand_prologue and riscv_expand_epilogue to only fold as many FPRs as the reserved space permits, preventing u…