From e85a6c039f4c7184fc250f68c22c4e6530e12bbc Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Wed, 22 Nov 2023 08:51:50 -0800 Subject: [PATCH 1/2] Clarify that multiple R_RISCV_LO12_I/R_RISCV_LO12_S can share one single 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. --- riscv-elf.adoc | 43 ++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 40 insertions(+), 3 deletions(-) diff --git a/riscv-elf.adoc b/riscv-elf.adoc index fb405113..a7477f08 100644 --- a/riscv-elf.adoc +++ b/riscv-elf.adoc @@ -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 @@ -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) +---- + +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) + lw tY, (gp) + lw tZ, (gp) + lw tW, (gp) + lw tX, (gp) ---- -- From 9daab92c72deee878cddd148692156cdbb0f2e33 Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Wed, 6 Dec 2023 20:01:00 -0800 Subject: [PATCH 2/2] Add "a condition met when the symbol is sufficiently aligned." --- riscv-elf.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/riscv-elf.adoc b/riscv-elf.adoc index a7477f08..c94979c8 100644 --- a/riscv-elf.adoc +++ b/riscv-elf.adoc @@ -584,7 +584,7 @@ The following assembly and relocations show loading an absolute address: 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. +identical, a condition met when the symbol is sufficiently aligned. [,asm] ----