gcc gp (global pointer) register

7,012 views
Skip to first unread message

Liviu Ionescu

unread,
Aug 2, 2017, 5:32:13 AM8/2/17
to RISC-V SW Dev
I'm trying to understand the RISC-V startup procedure, and I have difficulties to find any details about the gp register.

the Table 20.1 in volume I defines it as x3, and the linker script I found initialises it in a quite strange way (`PROVIDE( __global_pointer$ = . + 0x800 );`).

attempts to locate references to gp in the code generated for my tests failed.


is this register used by the bare metal compiler? if so, how should it be initialised?


regards,

Liviu



Kito Cheng

unread,
Aug 2, 2017, 6:19:04 AM8/2/17
to Liviu Ionescu, RISC-V SW Dev
It's used for relax in bare metal toolchain for saving code size,
and it's initialized at crt0.o which provide by newlib/libgloss [1]
Here is a simple example: a lui and lw pair could be relaxed into a lw with gp instruction.
However, you can disable this by -Wl,--no-relax, but GCC still can't use gp :P

Full example:
$ cat main.c 
int i;
int main(){
  return i;
}

$ riscv32-unknown-elf-gcc  main.c --save-temps
$ cat main.s
...
lui a5,%hi(i)
lw a5,%lo(i)(a5)
...
$ riscv32-unknown-elf-objdump -d a.out
...
   101b4:       8341a783                lw      a5,-1996(gp) # 11fdc <i>
...





--
You received this message because you are subscribed to the Google Groups "RISC-V SW Dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to sw-dev+unsubscribe@groups.riscv.org.
To post to this group, send email to sw-...@groups.riscv.org.
Visit this group at https://groups.google.com/a/groups.riscv.org/group/sw-dev/.
To view this discussion on the web visit https://groups.google.com/a/groups.riscv.org/d/msgid/sw-dev/87EC4D87-21F2-4023-8F48-D90301F38042%40livius.net.

Peter Ashenden

unread,
Aug 2, 2017, 8:04:37 AM8/2/17
to sw-...@groups.riscv.org
Here's my init code for gp:

la gp, _gp

Cheers,

PA
--
Peter Ashenden, CTO IC Design, ASTC

Liviu Ionescu

unread,
Aug 2, 2017, 9:14:01 AM8/2/17
to Kito Cheng, RISC-V SW Dev

> On 2 Aug 2017, at 13:18, Kito Cheng <kito....@gmail.com> wrote:
>
> It's used for relax in bare metal toolchain for saving code size,
> and it's initialized at crt0.o which provide by newlib/libgloss [1]
> [1] https://github.com/riscv/riscv-newlib/blob/riscv-newlib-2.5.0/libgloss/riscv/crt0.S#L12

yes, I know this, a similar code is present in the SiFive SDK examples.

> Here is a simple example: a lui and lw pair could be relaxed into a lw with gp instruction.
> However, you can disable this by -Wl,--no-relax, but GCC still can't use gp :P
>
> Full example:
> $ cat main.c
> int i;
> int main(){
> return i;
> }
>
> $ riscv32-unknown-elf-gcc main.c --save-temps
> $ cat main.s
> ...
> lui a5,%hi(i)
> lw a5,%lo(i)(a5)
> ...
> $ riscv32-unknown-elf-objdump -d a.out
> ...
> 101b4: 8341a783 lw a5,-1996(gp) # 11fdc <i>
> ...

ok, thank you for the explanation, but neither the link to crt0.S nor these code samples respond to the question: what is the purpose of the gp register and what value should be stored in it during startup?

the newlib crt0.S and the SiFive examples load gp with __global_pointer$, which is defined in the linker script somewhere in the data section as

__global_pointer$ = . + 0x800;

in other words, a RAM address, 2K past the end of the initialised data section. (for SiFive devices, the address is like 0x800011a0, right in the middle of nowhere)

what does this mean? and why 2K?


my feeling is that this comes via a careless copy/paste from some unix configuration, but it does not make much sense here.


Palmer? any comments?


regards,

Liviu

Liviu Ionescu

unread,
Aug 2, 2017, 9:16:55 AM8/2/17
to Peter Ashenden, sw-...@groups.riscv.org

> On 2 Aug 2017, at 15:04, Peter Ashenden <peter.a...@astc-design.com> wrote:
>
> Here's my init code for gp:
>
> la gp, _gp

yes, thank you, Peter, but could you elaborate and also share the definition of the _gp symbol? I guess it is a linker script definition.

regards,

Liviu

Bruce Hoult

unread,
Aug 2, 2017, 9:45:57 AM8/2/17
to Liviu Ionescu, Kito Cheng, RISC-V SW Dev
2K for the stack?

( I could check on my HiFive1 but it's at home and I'm at work now)




regards,

Liviu

--
You received this message because you are subscribed to the Google Groups "RISC-V SW Dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to sw-dev+unsubscribe@groups.riscv.org.
To post to this group, send email to sw-...@groups.riscv.org.
Visit this group at https://groups.google.com/a/groups.riscv.org/group/sw-dev/.

Michael Clark

unread,
Aug 2, 2017, 9:47:25 AM8/2/17
to Liviu Ionescu, Peter Ashenden, sw-...@groups.riscv.org
RISC-V immediate values are 12-bit signed values, which is +/- 2048 in decimal or +/- 0x800 in hex.

So that global pointer relative accesses can reach their full extent, the global pointer point + 0x800 into the data section.

The linker can then relax LUI+LW, LUI+SW into gp-relative LW or SW. i.e. shorter instruction sequences.

It can only do so for objects that are within the 4KB signed range of the global pointer.

Michael Clark

unread,
Aug 2, 2017, 9:49:17 AM8/2/17
to Liviu Ionescu, Peter Ashenden, sw-...@groups.riscv.org
It’s on my to do list to add GP-relative linker relaxations to the RISC-V PS ABI docs.

Bruce Hoult

unread,
Aug 2, 2017, 9:55:04 AM8/2/17
to Liviu Ionescu, Kito Cheng, RISC-V SW Dev
Ah, belay that. As Michael points out, the GP should point into the *middle* of a 4 KB area, so both positive and negative offsets can be used.


To unsubscribe from this group and stop receiving emails from it, send an email to sw-dev+un...@groups.riscv.org.

To post to this group, send email to sw-...@groups.riscv.org.
Visit this group at https://groups.google.com/a/groups.riscv.org/group/sw-dev/.

Liviu Ionescu

unread,
Aug 2, 2017, 9:57:36 AM8/2/17
to Michael Clark, Peter Ashenden, sw-...@groups.riscv.org

> On 2 Aug 2017, at 16:47, Michael Clark <michae...@mac.com> wrote:
>
>
>> yes, thank you, Peter, but could you elaborate and also share the definition of the _gp symbol? I guess it is a linker script definition.
>
> RISC-V immediate values are 12-bit signed values, which is +/- 2048 in decimal or +/- 0x800 in hex.
>
> So that global pointer relative accesses can reach their full extent, the global pointer point + 0x800 into the data section.
>
> The linker can then relax LUI+LW, LUI+SW into gp-relative LW or SW. i.e. shorter instruction sequences.
>
> It can only do so for objects that are within the 4KB signed range of the global pointer.

great!

however I feel you are not getting the point of the question.

I have my own startup code and my own linker script, so I'm not using the newlib crt0 and linker script.

my startup code already loads gp with the address of __global_pointer$, but how should I define __global_pointer$ in the linker script?

is this the only moment when the gp register is set, or the compiler will rewrite it with something more meaningful later on?


regards,

Liviu

Liviu Ionescu

unread,
Aug 2, 2017, 10:00:27 AM8/2/17
to Bruce Hoult, Kito Cheng, RISC-V SW Dev

> On 2 Aug 2017, at 16:55, Bruce Hoult <br...@hoult.org> wrote:
>
> ... the GP should point into the *middle* of a 4 KB area, so both positive and negative offsets can be used.

unfortunately I cannot encode such a vague statement in a linker script. :-(

which 4 KB area?


regards,

Liviu

Liviu Ionescu

unread,
Aug 2, 2017, 10:07:11 AM8/2/17
to Bruce Hoult, Kito Cheng, RISC-V SW Dev

> On 2 Aug 2017, at 16:45, Bruce Hoult <br...@hoult.org> wrote:
>
> 2K for the stack?

on HiFive1 samples the stack is right at the end of the 16K RAM region (0x80004000), while the gp is initially set at addresses like 0x800011a0.

I cannot find a relationship between these two addresses.


regards,

Liviu

PkmX

unread,
Aug 2, 2017, 10:10:29 AM8/2/17
to Liviu Ionescu, RISC-V SW Dev
You can set __global_pointer$ to pretty much everywhere in the linker
script, and the linker will attempt (with some limitations) to relax
absolute/pc-relative addressing into gp-relative if the symbol is
within +/- 2KiB range of __global_pointer$. The common definition is
.data + 0x800.

--
PkmX

Liviu Ionescu

unread,
Aug 2, 2017, 10:29:21 AM8/2/17
to PkmX, RISC-V SW Dev

> On 2 Aug 2017, at 17:09, PkmX <pkm...@gmail.com> wrote:
>
> You can set __global_pointer$ to pretty much everywhere in the linker
> script, and the linker will attempt (with some limitations) to relax
> absolute/pc-relative addressing into gp-relative if the symbol is
> within +/- 2KiB range of __global_pointer$.

you mean the linker compares the actual address with the address of the __global_pointer$ variable and if within range it optimises the code to gp relative?

> The common definition is
> .data + 0x800.

in other words it gives a better chance to a 4K window starting at .data?

the linker script that I have places this window at the beginning of .sdata section, where are allocated variables like _impure_ptr, __malloc_sbrk_base, etc.


regards,

Liviu

PkmX

unread,
Aug 2, 2017, 1:54:48 PM8/2/17
to Liviu Ionescu, RISC-V SW Dev
On Wed, Aug 2, 2017 at 10:29 PM, Liviu Ionescu <i...@livius.net> wrote:
>
>> On 2 Aug 2017, at 17:09, PkmX <pkm...@gmail.com> wrote:
>>
>> You can set __global_pointer$ to pretty much everywhere in the linker
>> script, and the linker will attempt (with some limitations) to relax
>> absolute/pc-relative addressing into gp-relative if the symbol is
>> within +/- 2KiB range of __global_pointer$.
>
> you mean the linker compares the actual address with the address of the __global_pointer$ variable and if within range it optimises the code to gp relative?
>

Exactly.

>> The common definition is
>> .data + 0x800.
>
> in other words it gives a better chance to a 4K window starting at .data?
>
> the linker script that I have places this window at the beginning of .sdata section, where are allocated variables like _impure_ptr, __malloc_sbrk_base, etc.
>

Yes, I was supposed to mean .sdata + 0x800.

> regards,
>
> Liviu
>

--
PkmX

Liviu Ionescu

unread,
Aug 2, 2017, 2:08:47 PM8/2/17
to PkmX, RISC-V SW Dev

> On 2 Aug 2017, at 20:54, PkmX <pkm...@gmail.com> wrote:
>
>
> Exactly ... Yes, I was supposed to mean .sdata + 0x800.

ok, it makes sense, I'll keep this setting.

regards,

Liviu

Peter Ashenden

unread,
Aug 2, 2017, 7:47:50 PM8/2/17
to sw-...@groups.riscv.org
I did a quick google and found a reference to the default linker scripts
in /opt/riscv/riscv64-unknown-elf/lib/ldscripts (or wherever your
toolchain installation is located). I found definition of _gp there.

Cheers,

PA

Andrew Waterman

unread,
Aug 2, 2017, 7:51:44 PM8/2/17
to Peter Ashenden, RISC-V SW Dev
Be aware that the symbol was renamed thanks to feedback we received in
the binutils upstreaming process. It is now __global_pointer$, not
_gp.
> --
> You received this message because you are subscribed to the Google Groups
> "RISC-V SW Dev" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to sw-dev+un...@groups.riscv.org.
> To post to this group, send email to sw-...@groups.riscv.org.
> Visit this group at
> https://groups.google.com/a/groups.riscv.org/group/sw-dev/.
> To view this discussion on the web visit
> https://groups.google.com/a/groups.riscv.org/d/msgid/sw-dev/2036b5df-20dd-f152-165b-8e7cf67d5350%40astc-design.com.

Liviu Ionescu

unread,
Aug 3, 2017, 3:53:20 AM8/3/17
to RISC-V SW Dev

> On 2 Aug 2017, at 16:13, Liviu Ionescu <i...@livius.net> wrote:
>
> ... what is the purpose of the gp register and what value should be stored in it during startup?

since it took about 10 messages from 5 people to get an answer, I added a new section to the RISC-V corner of my GNU MCU Eclipse site with a possible explanation:

https://gnu-mcu-eclipse.github.io/arch/riscv/programmer/#the-gp-global-pointer-register

feel free to suggest improvements, if necessary.


regards,

Liviu

Liviu Ionescu

unread,
Aug 3, 2017, 11:05:25 AM8/3/17
to Frédéric Pétrot, RISC-V SW Dev

> On 3 Aug 2017, at 17:43, Frédéric Pétrot <frederi...@univ-grenoble-alpes.fr> wrote:
>
> ... it seems that by default the
> maximum size of the data put in that section is 8 and that it can be changed
> with the -msmall-data-limit=N compiler option.

does this mean that **any** static variable shorter than N is automatically allocated in the .sdata section?

does this happen regardless of the optimisation level?


regards,

Liviu

Liviu Ionescu

unread,
Aug 4, 2017, 6:24:01 AM8/4/17
to Frédéric Pétrot, RISC-V SW Dev

> On 4 Aug 2017, at 13:12, Frédéric Pétrot <frederi...@univ-grenoble-alpes.fr> wrote:
>
> On 03/08/2017 17:05, Liviu Ionescu wrote:
>>
>> does this mean that **any** static variable shorter than N is automatically allocated in the .sdata section?
>
> ... Since the small date area size is limited by the offset range of the load
> and store instruction, it cannot be in general.

in this case I'm afraid I don't know what explanation to add to the web page.

perhaps the compiler gurus can clarify what `-msmall-data-limit=N` does and if there are other cases when the compiler/linker automatically allocate something into the .sdata section.


regards,

Liviu

Nelson Ribeiro

unread,
Aug 4, 2017, 6:33:11 AM8/4/17
to Liviu Ionescu, Frédéric Pétrot, RISC-V SW Dev
Hi, 
BTW I am not a compiler guru.

But looking at: 
I also did not got a good explanation.

Does this switch does the same as the switch   -G num in MIPS processors?


Regards,
Nelson


On Fri, Aug 4, 2017 at 11:23 AM, Liviu Ionescu <i...@livius.net> wrote:


regards,

Liviu

--
You received this message because you are subscribed to the Google Groups "RISC-V SW Dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to sw-dev+unsubscribe@groups.riscv.org.
To post to this group, send email to sw-...@groups.riscv.org.
Visit this group at https://groups.google.com/a/groups.riscv.org/group/sw-dev/.

Michael Chapman

unread,
Aug 4, 2017, 6:34:02 AM8/4/17
to Liviu Ionescu, Frédéric Pétrot, RISC-V SW Dev


On 03-Aug-17 17:05, Liviu Ionescu wrote:
>> On 3 Aug 2017, at 17:43, Frédéric Pétrot <frederi...@univ-grenoble-alpes.fr> wrote:
>>
>> ... it seems that by default the
>> maximum size of the data put in that section is 8 and that it can be changed
>> with the -msmall-data-limit=N compiler option.
> does this mean that **any** static variable shorter than N is automatically allocated in the .sdata section?

Yes. Unless you have explicitly placed it in some other section.

>
> does this happen regardless of the optimisation level?

Yes.

This also applies to MIPS, Cortus and several other architectures.

Andrew Waterman

unread,
Aug 4, 2017, 1:28:49 PM8/4/17
to Liviu Ionescu, Frédéric Pétrot, RISC-V SW Dev
On Fri, Aug 4, 2017 at 3:23 AM, Liviu Ionescu <i...@livius.net> wrote:
>
>> On 4 Aug 2017, at 13:12, Frédéric Pétrot <frederi...@univ-grenoble-alpes.fr> wrote:
>>
>> On 03/08/2017 17:05, Liviu Ionescu wrote:
>>>
>>> does this mean that **any** static variable shorter than N is automatically allocated in the .sdata section?
>>
>> ... Since the small date area size is limited by the offset range of the load
>> and store instruction, it cannot be in general.
>
> in this case I'm afraid I don't know what explanation to add to the web page.

What Frédéric wrote is true for MIPS but not for RISC-V. Since RISC-V
uses linker relaxations for the global pointer, it's actually OK if
the small data sections grow beyond the offset range of the load and
store instructions. If this happens, it affects performance, not
correctness.

So, -msmall-data=N does mean that any static variable shorter than N
defaults to the sdata/sbss sections. It is a tuning parameter.

>
> perhaps the compiler gurus can clarify what `-msmall-data-limit=N` does and if there are other cases when the compiler/linker automatically allocate something into the .sdata section.
>
>
> regards,
>
> Liviu
>
> --
> You received this message because you are subscribed to the Google Groups "RISC-V SW Dev" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to sw-dev+un...@groups.riscv.org.
> To post to this group, send email to sw-...@groups.riscv.org.
> Visit this group at https://groups.google.com/a/groups.riscv.org/group/sw-dev/.
> To view this discussion on the web visit https://groups.google.com/a/groups.riscv.org/d/msgid/sw-dev/C98A3383-6C1A-43A7-8779-DB33446EB645%40livius.net.
Reply all
Reply to author
Forward
0 new messages