#### 9.27.4 Controlling the use of small data accesses

It often takes several instructions to load the address of a symbol. For example, when ‘`addr`’ is a 32-bit symbol, the non-PIC expansion of ‘`dla $4,addr`’ is usually:

    lui     $4,%hi(addr)
    daddiu  $4,$4,%lo(addr)

The sequence is much longer when ‘`addr`’ is a 64-bit symbol. See Directives to override the size of symbols.

In order to cut down on this overhead, most embedded MIPS systems set aside a 64-kilobyte “small data” area and guarantee that all data of size n and smaller will be placed in that area. The limit n is passed to both the assembler and the linker using the command-line option `-G n`, see Assembler options. Note that the same value of n must be used when linking and when assembling all input files to the link; any inconsistency could cause a relocation overflow error.

The size of an object in the `.bss` section is set by the `.comm` or `.lcomm` directive that defines it. The size of an external object may be set with the `.extern` directive. For example, ‘`.extern sym,4`’ declares that the object at `sym` is 4 bytes in length, while leaving `sym` otherwise undefined.

When no `-G` option is given, the default limit is 8 bytes. The option `-G 0` prevents any data from being automatically classified as small.

It is also possible to mark specific objects as small by putting them in the special sections `.sdata` and `.sbss`, which are “small” counterparts of `.data` and `.bss` respectively. The toolchain will treat such data as small regardless of the `-G` setting.

On startup, systems that support a small data area are expected to initialize register `$28`, also known as `$gp`, in such a way that small data can be accessed using a 16-bit offset from that register. For example, when ‘`addr`’ is small data, the ‘`dla $4,addr`’ instruction above is equivalent to:

    daddiu  $4,$28,%gp_rel(addr)

Small data is not supported for SVR4-style PIC.