I don't get how JAL works in RISC-V as I've been seeing multiple conflicting definitions. For example, if I refer to this website: https://rv8.io/isa.html
It says that:
JAL rd,offset
has the 3rd argument as the offset, but there are some cases that shows JAL rd, imm
instead. What is the difference?
It seems that JAL is supposed to take a function and return its output in rd (which I don't know why some sources has called it ra
and rd
at the same time). But if that's the case, what is the subroutine or the function? rd
seems to be defined as the register destination, and imm
seems to be just an integer..
Really confused please help.
In the jal
instruction imm
(or imm20
) is a 20 bit binary number.
offset
is the interpretation of imm
by the jal
instruction: the contents of imm
are shifted left by 1 position and then sign-extended to the size of an address (32 or 64 bits, currently), thus making an integer with a value of -1 million (approximately) to +1 million.
This offset
integer is added to the address of the jal
instruction itself to get the address of the function you want to call. This new address is put into the PC and program execution resumes with whatever instruction is located at that address.
At the same time, the address of the instruction following the jal
is stored into CPU register rd
. The function being called will presumably later use this to return, using a jalr rn
instruction.
The RISC-V hardware allows any of the 32 integer registers to be given as rd
. If register 0 (x0) is given as rd
then the return address is discarded and you effectively have a +/1 MB goto
rather than a function call.
The standard RISC-V ABI (a software convention, nothing to do with hardware) specifies that for normal functions rd
should be register 1 (x1), which is then commonly known as ra
(Return Address). Register 5 (x5) is also commonly used for special runtime library functions, such as special functions to save and restore registers at the start and end of functions.
The RISC-V instruction set manual suggests that CPU designers might choose to add special hardware (a return address stack
) to make strictly nested pairs of jal x1/x5,offset
and `jalr x1/x5' run more quickly than would otherwise be expected, so there can be an advantage to following the standard ABI. However, the program will work correctly even if other registers are used.