Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Clarifying the behaviour of "callee-save" floating point registers in the soft-float ABI #51

Closed
asb opened this issue Oct 29, 2017 · 5 comments

Comments

@asb
Copy link
Collaborator

asb commented Oct 29, 2017

This document should clarify whether fs0-fs11 should be considered callee-save when compiling for the soft-float ABI. e.g. -march=rv32imaf -mabi=ilp32.

I would suggest that all floating point registers must be considered temporaries when compiling for the soft float ABI. Consider linking object file F.o compiled with -march=rv32imaf -mabi=ilp32 and D.o compiled with -march=rv32imafd -mabi=ilp32. If code in D.o stores a double in fs0 and code in F.o attempts to spill it, the value would obviously be corrupted. We could of course define new bits in e_flags and linker behaviour to try catch these problems at link time (ensuring code compiled with FLEN=0 is only linked with code compiled with one other FLEN value, e.g. a mix of objects with flen=0 and flen=32 is fine, but not flen=0 and flen=32 and flen=64).

@aswaterman
Copy link
Contributor

I think we are already doing this: "For the purposes of this section, FLEN refers to the width of a floating-point register in the ABI. ... Floating-point registers fs0-fs11 shall be preserved across procedure calls, provided they hold values no more than FLEN bits wide."

So it follows that when the ABI FLEN is 0 that fs0-fs11 are not preserved across calls at all. Do you think we need to add a sentence clarifying this fact?

(FYI, GCC is doing something overly conservative here: it disallows holding values wider than the ABI FLEN in fs0-fs11 altogether. In the RV32D + ILP32F case, I'm not sure how to tell GCC that the registers are callee-saved for F values but call-clobbered for D values, so I think we will keep this conservative implementation. But in the ILP32 case, GCC should just treat fs0-fs11 as temporaries.)

@aswaterman
Copy link
Contributor

The GCC behavior has been fixed to allow use of fs0-fs11 as call-clobbered registers in the ILP32 case. This doesn't break the ABI because, as I mentioned, the implementation previously disallowed the use of fs0-fs11 in soft-float code. riscvarchive/riscv-gcc#103

@asb
Copy link
Collaborator Author

asb commented Oct 31, 2017

And even more explicit under the "base" integer calling convention: "No floating-point registers, if present, are preserved across calls." Sorry for the noise, I'd thought the tables under the "register map" were the only reference on callee-save registers and didn't re-check that assumption - sorry for missing that.

I think it is handy for the register tables to indicate which registers are callee-save. What do you think of a patch that changes the entry in the FPR tables to "Yes*" and an explanation:
"*: Values are only preserved if they are no larger than the width of a floating-point register in the targeted ABI. Therefore, these registers can always be considered temporaries if targeting the base integer calling convention."

There is obviously some repetition vs the other sections, but it seems if we're going to duplicate some information (which registers are preserved), we might as well add in the extra couple of sentences that explicitly clarify the situation.

@aswaterman
Copy link
Contributor

aswaterman commented Oct 31, 2017

Makes sense to me. I've made the change; make sure it doesn't get clobbered when the large refactoring PR gets merged :)

@asb
Copy link
Collaborator Author

asb commented Nov 1, 2017

Thanks, closing this issue.

@asb asb closed this as completed Nov 1, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants