EEVblog Electronics Community Forum

Products => Computers => Programming => Topic started by: HwAoRrDk on July 25, 2023, 11:57:53 pm

Title: GCC's RISC-V -msmall-data-limit option
Post by: HwAoRrDk on July 25, 2023, 11:57:53 pm
When compiling code for the WCH CH32V RISC-V series of microcontrollers, I see that some people use (including I believe the WCH MounRiver Studio default options) the GCC option -msmall-data-limit=8. The GCC documentation isn't particularly illuminating on the effect of this option. It just says:

Quote
Put global and static data smaller than n bytes into a special section (on some targets).

What is this 'special' section? Which targets does this apply to? Why would you want to put global/static data smaller than 8 bytes into a special section? What is the significance of the threshold of 8 bytes?
Title: Re: GCC's RISC-V -msmall-data-limit option
Post by: brucehoult on July 26, 2023, 12:20:07 am
Global data is stored in memory with .sdata at lower addresses and .data following it.

The GP register is initialized to 2048 bytes past the start of .sdata.

Global variables from GP-2048 to GP+2047 can be accessed using just 1 instruction. If .sdata is smaller than 4K then all of .sdata can be accessed with a single instruction, and some of the start of .data too.

Title: Re: GCC's RISC-V -msmall-data-limit option
Post by: langwadt on July 26, 2023, 12:30:18 am
I'm guessing the the special section is just an area of memory you keep a pointer to so you can save some code address it relative to that pointer

I assume the 8 bytes is just  a compromise of not using up the area you can easily address with large variables, where loading an address isn't much overhead compared to the variable itself
Title: Re: GCC's RISC-V -msmall-data-limit option
Post by: HwAoRrDk on July 26, 2023, 12:38:21 am
Ah, so it's a code-size optimisation?

If I'm understanding correctly, by giving this option with a size of 8 bytes, you're effectively saying try to put as many initialised uint64_t-or-smaller global/static variables into the .sdata section as possible, which means that they have priority of residence in lower addresses than other global/static variables.

So if you have less than 4K of variables in .data full stop then this option will have no effect? I tried adding the option to a small project of mine that only uses 16 bytes in .data and it had no effect on the .text size. But then on something like the CH32V003 where there is only 2KB of RAM anyway, I suppose you'll never have any variables in .data outside the offset range from GP anyway. ;D
Title: Re: GCC's RISC-V -msmall-data-limit option
Post by: brucehoult on July 26, 2023, 01:08:29 am
So if you have less than 4K of variables in .data full stop then this option will have no effect?

No *practical* effect. Some things may end up at different addresses.

Quote
on something like the CH32V003 where there is only 2KB of RAM anyway, I suppose you'll never have any variables in .data outside the offset range from GP anyway. ;D

Indeed so, but WCH do use the same IDE for larger chips.

Of course .bss is somewhere in that area too. I don't recall the exact ordering compared to .data.  There is also .sbss.
Title: Re: GCC's RISC-V -msmall-data-limit option
Post by: HwAoRrDk on July 26, 2023, 08:28:16 pm
Of course .bss is somewhere in that area too. I don't recall the exact ordering compared to .data.  There is also .sbss.

This is the section of the linker script (as provided by WCH) concerning .data and .bss:

Code: [Select]
    .data :
    {
      . = ALIGN(4);
      *(.gnu.linkonce.r.*)
      *(.data .data.*)
      *(.gnu.linkonce.d.*)
      . = ALIGN(8);
      PROVIDE( __global_pointer$ = . + 0x800 );
      *(.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

    .bss :
    {
      . = ALIGN(4);
      PROVIDE( _sbss = .);
      *(.sbss*)
      *(.gnu.linkonce.sb.*)
      *(.bss*)
      *(.gnu.linkonce.b.*)   
      *(COMMON*)
      . = ALIGN(4);
      PROVIDE( _ebss = .);
    } >RAM AT>FLASH

Indeed there is also .sbss. But, am I missing something here, or does the script specify that .data comes before .sdata? ??? I am not too familiar with GNU linker script syntax.
Title: Re: GCC's RISC-V -msmall-data-limit option
Post by: ejeffrey on July 26, 2023, 09:06:36 pm
Yes, the order is something like:


.data
.sdata
.sbss
.bss

so that sdata and sbss are adjacent and ideally both within range of gp.  It also has a .srodata for small read-only data in there.  I don't see a regular .rodata. I guess that probably is in flash and part of the linker script not shown.