Properly declare and use risc-v global pointer
In our current mockturtle firmware, we declare the global pointer position like this, just before the .sdata
section:
/* Have _gp point to middle of sdata/sbss to maximize displacement range */
. = ALIGN(16);
_gp = . + 0x800;
And then we initialise the register like this:
la gp, _gp /* Initialize global pointer */
There are several issues with the above approach:
- The most important, it seems that "recent" versions of the toolchain (I tested with gcc 7.3 and binutils 2.30) expect the label
__global_pointer$
, not_gp
. As long as we use the old name, the toolchain does not recognise this as the "global pointer", which is a software convention and will not try to perform any gp-based relaxations. Here's the relevant output fromld -verbose
that shows what is actually expected:
.sdata :
{
__global_pointer$ = . + 0x800;
*(.srodata.cst16) *(.srodata.cst8) *(.srodata.cst4) *(.srodata.cst2) *(.srodata .srodata.*)
*(.sdata .sdata.* .gnu.linkonce.s.*)
}
- Also, note in the above example that the global pointer location is defined inside
.sdata
. We do it before and we risk again having the wrong address, as in !3 (merged) - Finally, it is strongly recommended to "protect" the initialisation of the global pointer register. See slide 7 of the following presentation: https://riscv.org/wp-content/uploads/2019/03/11.15-Shiva-Chen-Compiler-Support-For-Linker-Relaxation-in-RISC-V-2019-03-13.pdf