← Back to context

Comment by twic

2 years ago

Random RISC-V question: how do you make function calls in RV64?

I have read that 'call' in assembly is a pseudo-instruction, which uses auipc and jalr to build the destination address.

But surely that can only supply 32 bits of address? Is there a different sequence on 64 bit RISC-V? Or have I fundamentally misunderstood?

Direct function calls are usually done relative to the program counter (pc in auipc). So you get 32 bits of displacement, which is fine as long as your code is less than 4GB, and you get position-independent code for free. This is the same as on x86-64 and aarch64 too, which also have ~32 bits for call target immediates. (also, compilers have "code model" options for choosing the size of code to support)

  • I assume there's also support for a kind of calculated long jump done at elf load time? I know that's done as part of the relocations on aarch64.

My understanding is that AUIPC builds the destination address by adding a 32 bit offset to the current PC, i.e. it is relative, and that this works with both 32 and 64 bit addresses. The difference is that, on 32-bit systems this allows to immediately access any address while on 64-bit systems you are limited to this relative 32-bit window.

Either: "jal lr, dest" or "jalr lr, offset(reg)"

Both save the address of the next instruction in lr, the first is a relative branch the second is to the address pointed by a register plus an offset

Use "jalr r0, 0(lr)" to return

Anything else is just syntactic sugar in the assembler to set up the reg for jalr