riscv-non-isa / riscv-elf-psabi-doc

A RISC-V ELF psABI Document
https://jira.riscv.org/browse/RVG-4
Creative Commons Attribution 4.0 International
660 stars 157 forks source link

Calling convention for big-endian #265

Open kito-cheng opened 2 years ago

kito-cheng commented 2 years ago

Review comment come from @anderslindgren-iar and Anders Berg(IAR) https://lists.riscv.org/g/tech-toolchain-runtime/message/344

Scalars that are 2×XLEN bits wide are passed in a pair of argument registers, with the low-order XLEN bits in the lower-numbered register and the high-order XLEN bits in the higher-numbered register. If no argument registers are available, the scalar is passed on the stack by value. If exactly one register is available, the loworder XLEN bits are passed in the register and the high-order XLEN bits are passed on the stack.

Anders: What about big endian? Should not big endian have the low-order bits in the high-numbered register and the high-order bits in the low-numbered register?

jrtc27 commented 2 years ago

Well what does the big-endian toolchain currently do, if such a thing exists? This probably does need changing though to make varargs work nicely? Fixed arguments don't matter either way round really.

kito-cheng commented 2 years ago

Marcus Comstedt has contribute big-endian support on GNU toolchain (GCC+binutils) last year, and LLVM didn't support that yet.

Big endian stuffs are low priority for now, so I would suggest add NOTE to mention big-endian ABI isn't stable yet.

kito-cheng commented 2 years ago

Reply from SEGGER - Paul Curtis

Regarding calling conventions you say:

What about big endian? Should not big endian have the low-order bits in the high-numbered register and the high-order bits in the low-numbered register?

As far as I can tell, low-order units are always in the low-numbered register irrespective of processor byte order. This matches the the P extension specification here: https://github.com/riscv/riscv-p-spec/blob/master/P-ext-proposal.adoc#7-detailed-instruction-descriptions-for-zpn-extension-both-rv32--rv64 which states:

Regardless of endianness, the lower-numbered register holds the low-order bits, and the higher- numbered register holds the high-order bits: e.g., bits 31:0 of a 64-bit operand might be held in register x14, with bits 63:32 of that operand held in x15.

It would not really make sense to have to swap register order in CG to conform to Arm-style big-endian calling conventions. Then again, I have not seen any big-endian RV32 devices in the wild.

asb commented 2 years ago

Marcus Comstedt has contribute big-endian support on GNU toolchain (GCC+binutils) last year, and LLVM didn't support that yet.

Big endian stuffs are low priority for now, so I would suggest add NOTE to mention big-endian ABI isn't stable yet.

IMHO it would be really helpful for the big-endian ABI to be documented in this repo alongside patches that implement it (even if explicitly marked as not yet final etc).

ptomsich commented 2 years ago

@kito-cheng Please add a note that the document does not include a big-endian ABI, as defining a stable big-endian ABI will happen in a future version of the psABI.

This should be added to the requirements/tasks for the next major update of the psABI (1.2/2.0/…) document.

kito-cheng commented 2 years ago

I will add NOTE to mention NOT include bit-endian ABI first, and then gonna document what we have for big-endian ABI after public review, I believe that's important to having a doc for that, but I just didn't have enough throughput for now :(

kito-cheng commented 1 year ago

Added note, move to post 1.0 issue

aswaterman commented 1 month ago

Revisiting this issue two years later.

In RV32_Zdinx, the 32 LSBs of a 64b value are in the lower-numbered register, regardless of endianness. (This is ratified.) Zilsd, which is defined in part to speed up Zdinx (as well as forthcoming Zpa), adds loads and stores that are consistent: the LSBs of the 64b type (i.e. memory bytes 0-3 in little-endian, or memory bytes 4-7 in big-endian) go to the lower-numbered register.

For obvious reasons, it's best for the calling convention to match: otherwise Zilsd won't be usable for argument passing/return. Unfortunately, I see that GCC has adopted a de facto big-endian calling convention that has the opposite property. But, fortunately, we have a good opportunity to rectify this, since the calling convention we ratified is little-endian-only (and so the GCC big-endian calling convention is nonstandard). I suggest we work on defining a big-endian calling convention eventually, and that we craft it to maximize performance for Zdinx + Zpa + Zilsd.

jrtc27 commented 1 month ago

Very much in favour of a future ratified big-endian calling convention being well-aligned with the realities of the ISA. Is this something SiFive is intending to commit resources to nailing down, or just with your set of RVI hats on?

aswaterman commented 1 month ago

I'm here representing the RVIA Architecture Review Committee, rather than SiFive. I don't think it's too likely that I could get SiFive to allocate resources to this project, given we don't (to my knowledge) have big-endian projects on the roadmap. But of course we'd be willing to help review proposals and specs.

jrtc27 commented 1 month ago

From our perspective if this is to be on our roadmap we really need someone who's going to own the proof-of-concept work and figuring out all the corner cases. Nobody so far has come forward saying their company wants to ship a big-endian system and thus needs a psABI and toolchain.

aswaterman commented 1 month ago

Of course. I only meant to remark that, when this project is eventually tackled, it should be done in context of the extensions I mentioned. I'm not trying to goad the ABI group to put this on the roadmap sooner than would have naturally occurred.