Hi Pan, Andrew I'm trying to understand the semantics of FRM as it intersects with calling convention. psABI is not explicit about it and refers to C standard [1]
> On 2/14/25 03:39, Li, Pan2 wrote: [snip] > With option "-march=rv64gcv_zvfh -O3" > > 10 │ vxrm: > 11 │ csrwi vxrm,2 // Just set rm directly > ... > 17 │ vle16.v v2,0(a4) > 18 │ vle16.v v1,0(a3) > ... > 21 │ vaaddu.vv v1,v1,v2 > 22 │ vse16.v v1,0(a4) > 23 │ tail call_external > 28 │ frm: > 29 │ frrm a2 // backup > 30 │ fsrmi 2 // set rm > ... > 35 │ vle16.v v1,0(a3) > 36 │ addi a5,a5,%lo(bf) > 37 │ vfnmadd.vv v1,v1,v1 > 38 │ vse16.v v1,0(a5) > 39 │ fsrm a2 // restore > 40 │ tail call_external [snip] > If instead we want to set a global register to a specific local value, > the sequence would be: > > call foo > TMP := FIXED_REG > FIXED_REG := ... > ...use FIXED_REG... > FIXED_REG := TMP > call bar > > It sounds like this is the correct sequence for FRM and it seemed to be > what the port was generating in the PR. So from above msg snippets and commit 46a508ec7aee503 and its numerous tests, I'm summarizing the following > 1. The static frm before call should not pollute the frm value in call. In simple terms: Before a call, if FRM is clobbered, it needs to be restored before making the call (to "retain the global value") > 2. The updated frm value in call should be sticky after call completed. After a call (which can potentially set a FRM globally), if the caller clobbers FRM, it needs to be restored back (by reading the value right after the call). So in some convoluted way both the above scenarios have callee-saved semantics for FRM, except for the leaf function which unconditionally sets FRM where this save/restore is not done. Is the above understanding correct, or is there more to it. Thx, -Vineet [1] https://github.com/riscv-non-isa/riscv-elf-psabi-doc/blob/master/riscv-cc.adoc