4.2.5.3 BaseReg+Offset Operands

Load and store operations select the memory location using a BaseReg+Offset operand. For an operand of this type, the effective address is formed by adding the 32-bit signed offset to the contents of a base register. A PIC32M data sheet shows this type of operand as Mem[R+offset].

The following example shows Assembly Source Code with BaseReg+Offset Operands.
#include <xc.h>
        .data
        .align 4
MY_WORD_DATA:
        .word 0x10203040, 0x8090a0b0
        .text
        .global example
        /* Store Word */
example:
        la   v0, MY_WORD_DATA
        lui         v1,0x1111
        ori         v1,v1,0x4432
        lui         a0,0x5555
        ori         a0,a0,0x1123
        sw v1, 0(v0)     /* Mem[GPR[v0]+0] <- GPR[v1] */
        sw a0, 4(v0)     /* Mem[GPR[v0]+4] <- GPR[a0] */
        lw a1, 0(v0)     /* GPR[a1] <- Mem[GPR[v0]+0] */
        b .

The C compiler supports global-pointer relative (GP-relative) addressing. Loads and stores to data lying within 32 KB of either side of the address stored in the gp register (64 KB total) can be performed in a single instruction using the gp register as the base register. The C compiler's -G option lets you change the maximum size of global and static data items that can be addressed in one instruction instead of two from the default value of 8 bytes, which is large enough to hold all simple scalar variables.

The following example shows assembly source code with GP-relative addressing.
   .align		2
   .globl		foo
   .set		nomips32
   .ent		foo
foo:
   .set		noreorder
   .set		nomacro

   lw		$3,%gp_rel(testval)($28)
   addiu		$2,$3,1
   sw		$2,%gp_rel(testval)($28)
   j		$31
   nop

   .set		macro
   .set		reorder
   .end		foo
Note: To utilize GP-relative addressing, the compiler and assembler must group all of the “small” variables and constants into one of the “small” sections. See the MPLAB® XC32 C/C++ Compiler User's Guidefor more information on the global pointer and the -G option.

There are a few potential pitfalls to using GP-relative addressing:

  • You must take special care when writing assembler code to declare global (i.e., public or external) data items correctly:
    • Writable, initialized data of not more than the number of bytes specified by the -G option must be put explicitly into the .sdata section, for example:
                 .sdata
      small:     .word  0x12345678
    • Global common data must be declared with the correct size, for example:
                 .comm small, 4
                 .comm big, 100
    • Small external variables must also be declared correctly, for example:
                 .extern smallext, 4
  • If your program has a very large number of small data items or constants, the C compiler's -G8 option may still try to push more than 64 KB of data into the ''small'' region; the symptom will be obscure relocation errors (''relocation truncated'') when linking. Fix it by disabling GP-relative addressing with the compiler's -G0 option and/or reducing the space reserved in the small data sections (i.e. .sbss and .sdata) in your assembly code.