# RISC-V Linker PC-GP Relaxation
## Small Data Section and GP
In RISC-V, small global data are collected in a special section, called small data section (`.sdata`). The section can be accessed through a special register: `gp` (globl pointer).
`gp` always points to the middle of the `.sdata`, which is determined in linker script. And `gp` is set at program initialization in crt0.S.
The linker script looks like:
```
---- begin of .sdata section (__global_pointer - 0x800)
|
|
|
| <---- __global_pointer
|
|
|
---- end of .sdata section (__global_pointer + 0x800)
```
In crt0.S, the initialization looks like:
```
auipc gp, %pcrel_hi(__global_pointer$)
addi gp, gp, %pcrel_lo(1b)
```
Where the symbole `__global_pointer` is exposed from linker script.
After `gp` is set, programs can access data in `.sdata` with only one instruction. For example, the following instruction saves data to address `gp - 1944`.
```
lw a5,-200(gp) # 80001fc0 <foo>
```
The magic number 0x800 above and below `__global_pointer` is because the S-type RISC-V has 12-bit immediate field, which allows signed 12-bit offsets from `__global_pointer` to access both ends of `.sdata`.
## PC-GP Relaxation
Normally, if data are stored in `.data` section, a data access combines auipc + load/store instruction. For example:
```
auipc a4,0x3fc00
lw a4,-142(a4) # 800007a0 <foo>
```
With small data section described above, the two instructions can be replaced with one load instruction with GP:
```
lw a5,-200(gp) # 80007a0 <foo>
```
This is one of the relaxation performed by the GNU linker.