Skip to content

Commit

Permalink
Clarify that multiple R_RISCV_LO12_I/R_RISCV_LO12_S can share one sin…
Browse files Browse the repository at this point in the history
…gle R_RISCV_HI20

This is most common on rv32 when loading a 8-byte aligned global
variable, e.g.
```
double NaturallyAlignedScalar = 5.;
double accessNaturallyAlignedScalar() { return NaturallyAlignedScalar; }
//      lui     a1, %hi(NaturallyAlignedScalar)
//      lw      a0, %lo(NaturallyAlignedScalar)(a1)
//      lw      a1, %lo(NaturallyAlignedScalar+4)(a1)

double NaturallyAlignedArray[4] = { 3., 4., 5., 6. };
double accessNaturallyAlignedArray() {
  return NaturallyAlignedArray[0] + NaturallyAlignedArray[3];
}
//      lui     a2, %hi(NaturallyAlignedArray)
//      lw      a0, %lo(NaturallyAlignedArray)(a2)
//      lw      a1, %lo(NaturallyAlignedArray+4)(a2)
//      addi    a3, a2, %lo(NaturallyAlignedArray)
//      lw      a2, 24(a3)
//      lw      a3, 28(a3)
```

The HI20 values for the multiple fragments must be identical and all the
relaxed global-pointer offsets must be in range.
  • Loading branch information
MaskRay committed Nov 22, 2023
1 parent d1743f6 commit e85a6c0
Showing 1 changed file with 40 additions and 3 deletions.
43 changes: 40 additions & 3 deletions riscv-elf.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -581,6 +581,20 @@ The following assembly and relocations show loading an absolute address:
addi a0, a0, %lo(symbol) # R_RISCV_LO12_I (symbol)
----

A symbol can be loaded in multiple fragments using different addends, where
multiple instructions associated with `R_RISCV_LO12_I`/`R_RISCV_LO12_S` share a
single `R_RISCV_HI20`. The HI20 values for the multiple fragments must be
identical.

[,asm]
----
lui a0, 0 # R_RISCV_HI20 (symbol)
lw a1, 0(a0) # R_RISCV_LO12_I (symbol)
lw a2, 0(a0) # R_RISCV_LO12_I (symbol+4)
lw a3, 0(a0) # R_RISCV_LO12_I (symbol+8)
lw a0, 0(a0) # R_RISCV_LO12_I (symbol+12)
----

==== Global Offset Table

For position independent code in dynamically linked objects, each shared
Expand Down Expand Up @@ -1533,16 +1547,39 @@ Relaxation result:
Example::
+
--
Relaxation candidate (`tX` and `tY` can be any combination of two general purpose registers):
[,asm]
----
lui tX, 0 # R_RISCV_HI20 (symbol), R_RISCV_RELAX
lw tY, 0(tX) # R_RISCV_LO12_I (symbol), R_RISCV_RELAX
----
Relaxation result:
[,asm]
----
lw tY, <gp-offset-for-symbol>(gp)
----

A symbol can be loaded in multiple fragments using different addends, where
multiple instructions associated with `R_RISCV_LO12_I`/`R_RISCV_LO12_S` share a
single `R_RISCV_HI20`. The HI20 values for the multiple fragments must be
identical and all the relaxed global-pointer offsets must be in range.

Relaxation candidate:
[,asm]
----
lui t0, 0 # R_RISCV_HI20 (symbol), R_RISCV_RELAX
lw t1, 0(t0) # R_RISCV_LO12_I (symbol), R_RISCV_RELAX
lui tX, 0 # R_RISCV_HI20 (symbol), R_RISCV_RELAX
lw tY, 0(tX) # R_RISCV_LO12_I (symbol), R_RISCV_RELAX
lw tZ, 0(tX+4) # R_RISCV_LO12_I (symbol+4), R_RISCV_RELAX
lw tW, 0(tX+8) # R_RISCV_LO12_I (symbol+8), R_RISCV_RELAX
lw tX, 0(tX+12) # R_RISCV_LO12_I (symbol+12), R_RISCV_RELAX
----
Relaxation result:
[,asm]
----
lw t1, <gp-offset-for-symbol>(gp)
lw tY, <gp-offset-for-symbol>(gp)
lw tZ, <gp-offset-for-symbol+4>(gp)
lw tW, <gp-offset-for-symbol+8>(gp)
lw tX, <gp-offset-for-symbol+12>(gp)
----
--

Expand Down

0 comments on commit e85a6c0

Please sign in to comment.