RISC-V gp全局指針寄存器說明
gp,global pointer,全局指針寄存器,RISC-V 32個寄存器之一,為了優化±2KB內全局變量的訪問。
gp寄存器在啟動代碼中加載為__global_pointer$的地址,並且之后不能被改變。
linker時使用__global_pointer$來比較全局變量的地址,如果在范圍內,就替換掉lui或puipc指令的 absolute/pc-relative尋址,變為gp-relative尋址,使得代碼效率更高。該過程被稱為linker relaxation(鏈接器松弛),也可以使用-Wl,--no-relax來disable此功能。
如:需要讀取全局變量 tao_global的值,地址位0x20000100,gp指針地址為0x20000800;
- 普通調用方式為:
lui a5,0x20000 /* 將0x20000100高20位0x20000 左移12位賦給a5寄存器 */
lw a5,256(a5) /* 加載a5+256(0x100,0x20000100低12位)的值至a5寄存器 */
- gp指針優化調用方式:
lw a5,-1792(gp) /* 加載gp-1792地址處的值至a5,即0x20000100處的值*/
通過gp指針,訪問其值±2KB,即4KB范圍內的全局變量,可以節約一條指令。
4KB區域可以位於尋址內存中任意位置,但是為了使優化更有效率,最好覆蓋最頻繁使用的RAM區域。對於標准的newlib應用程序,這是分配.sdata部分的區域,因為它包含了諸如_impure_ptr、malloc_sbrk_base等變量。因此,定義應該被放在.sdata部分之前。具體分配在ld文件中定義:
.data :
{
*(.gnu.linkonce.r.*)
*(.data .data.*)
*(.gnu.linkonce.d.*)
. = ALIGN(8);
PROVIDE( __global_pointer$ = . + 0x800 ); /* __global_pointer地址*/
*(.sdata .sdata.*)
*(.sdata2.*)
*(.gnu.linkonce.s.*)
. = ALIGN(8);
*(.srodata.cst16)
*(.srodata.cst8)
*(.srodata.cst4)
*(.srodata.cst2)
*(.srodata .srodata.*)
. = ALIGN(4);
PROVIDE( _edata = .);
} >RAM AT>FLASH
