#### 9.33.1.3 Relocations

ELF relocations are available as defined in the OpenRISC architecture specification.

`R_OR1K_HI_16_IN_INSN` is obtained using ‘`hi`’ and `R_OR1K_LO_16_IN_INSN` and `R_OR1K_SLO16` are obtained using ‘`lo`’. For signed offsets `R_OR1K_AHI16` is obtained from ‘`ha`’. For example:

    l.movhi r5, hi(symbol)
    l.ori   r5, r5, lo(symbol)

    l.movhi r5, ha(symbol)
    l.addi  r5, r5, lo(symbol)

These “high” mnemonics extract bits 31:16 of their operand, and the “low” mnemonics extract bits 15:0 of their operand.

The PC relative relocation `R_OR1K_GOTPC_HI16` can be obtained by enclosing an operand inside of ‘`gotpchi`’. Likewise, the `R_OR1K_GOTPC_LO16` relocation can be obtained using ‘`gotpclo`’. These are mostly used when assembling PIC code. For example, the standard PIC sequence on OpenRISC to get the base of the global offset table, PC relative, into a register, can be performed as:

    l.jal   0x8
     l.movhi r17, gotpchi(_GLOBAL_OFFSET_TABLE_-4)
    l.ori   r17, r17, gotpclo(_GLOBAL_OFFSET_TABLE_+0)
    l.add   r17, r17, r9

Several relocations exist to allow the link editor to perform GOT data references. The `R_OR1K_GOT16` relocation can obtained by enclosing an operand inside of ‘`got`’. For example, assuming the GOT base is in register `r17`.

    l.lwz   r19, got(a)(r17)
    l.lwz   r21, 0(r19)

Also, several relocations exist for local GOT references. The `R_OR1K_GOTOFF_AHI16` relocation can obtained by enclosing an operand inside of ‘`gotoffha`’. Likewise, `R_OR1K_GOTOFF_LO16` and `R_OR1K_GOTOFF_SLO16` can be obtained by enclosing an operand inside of ‘`gotofflo`’. For example, assuming the GOT base is in register `rl7`:

    l.movhi r19, gotoffha(symbol)
    l.add   r19, r19, r17
    l.lwz   r19, gotofflo(symbol)(r19)

The above PC relative relocations use a `l.jal` (jump) instruction and reading of the link register to load the PC. OpenRISC also supports page offset PC relative locations without a jump instruction using the `l.adrp` instruction. By default the `l.adrp` instruction will create an `R_OR1K_PCREL_PG21` relocation. Likewise, `BFD_RELOC_OR1K_LO13` and `BFD_RELOC_OR1K_SLO13` can be obtained by enclosing an operand inside of ‘`po`’. For example:

    l.adrp  r3, symbol
    l.ori   r4, r3, po(symbol)
    l.lbz   r5, po(symbol)(r3)
    l.sb    po(symbol)(r3), r6

Likewise the page offset relocations can be used with GOT references. The relocation `R_OR1K_GOT_PG21` can be obtained by enclosing an `l.adrp` immediate operand inside of ‘`got`’. Likewise, `R_OR1K_GOT_LO13` can be obtained by enclosing an operand inside of ‘`gotpo`’. For example to load the value of a GOT symbol into register ‘`r5`’ we can do:

    l.adrp  r17, got(_GLOBAL_OFFSET_TABLE_)
    l.lwz   r5, gotpo(symbol)(r17)

There are many relocations that can be requested for access to thread local storage variables. All of the OpenRISC TLS mnemonics are supported:

- `R_OR1K_TLS_GD_HI16` is requested using ‘`tlsgdhi`’.
- `R_OR1K_TLS_GD_LO16` is requested using ‘`tlsgdlo`’.
- `R_OR1K_TLS_GD_PG21` is requested using ‘`tldgd`’.
- `R_OR1K_TLS_GD_LO13` is requested using ‘`tlsgdpo`’.
- `R_OR1K_TLS_LDM_HI16` is requested using ‘`tlsldmhi`’.
- `R_OR1K_TLS_LDM_LO16` is requested using ‘`tlsldmlo`’.
- `R_OR1K_TLS_LDM_PG21` is requested using ‘`tldldm`’.
- `R_OR1K_TLS_LDM_LO13` is requested using ‘`tlsldmpo`’.
- `R_OR1K_TLS_LDO_HI16` is requested using ‘`dtpoffhi`’.
- `R_OR1K_TLS_LDO_LO16` is requested using ‘`dtpofflo`’.
- `R_OR1K_TLS_IE_HI16` is requested using ‘`gottpoffhi`’.
- `R_OR1K_TLS_IE_AHI16` is requested using ‘`gottpoffha`’.
- `R_OR1K_TLS_IE_LO16` is requested using ‘`gottpofflo`’.
- `R_OR1K_TLS_IE_PG21` is requested using ‘`gottp`’.
- `R_OR1K_TLS_IE_LO13` is requested using ‘`gottppo`’.
- `R_OR1K_TLS_LE_HI16` is requested using ‘`tpoffhi`’.
- `R_OR1K_TLS_LE_AHI16` is requested using ‘`tpoffha`’.
- `R_OR1K_TLS_LE_LO16` is requested using ‘`tpofflo`’.
- `R_OR1K_TLS_LE_SLO16` also is requested using ‘`tpofflo`’ depending on the instruction format.

Here are some example TLS model sequences.

First, General Dynamic:

    l.movhi r17, tlsgdhi(symbol)
    l.ori   r17, r17, tlsgdlo(symbol)
    l.add   r17, r17, r16
    l.or    r3, r17, r17
    l.jal   plt(__tls_get_addr)
     l.nop

Initial Exec:

    l.movhi r17, gottpoffhi(symbol)
    l.add   r17, r17, r16
    l.lwz   r17, gottpofflo(symbol)(r17)
    l.add   r17, r17, r10
    l.lbs   r17, 0(r17)

And finally, Local Exec:

    l.movhi r17, tpoffha(symbol)
    l.add   r17, r17, r10
    l.addi  r17, r17, tpofflo(symbol)
    l.lbs   r17, 0(r17)