diff mbox series

[07/30] tcg/loongarch: Implement necessary relocation operations

Message ID 20210920080451.408655-8-git@xen0n.name (mailing list archive)
State New, archived
Headers show
Series 64-bit LoongArch port of QEMU TCG | expand

Commit Message

WANG Xuerui Sept. 20, 2021, 8:04 a.m. UTC
Signed-off-by: WANG Xuerui <git@xen0n.name>
---
 tcg/loongarch/tcg-target.c.inc | 84 ++++++++++++++++++++++++++++++++++
 1 file changed, 84 insertions(+)

Comments

Richard Henderson Sept. 20, 2021, 2:36 p.m. UTC | #1
On 9/20/21 1:04 AM, WANG Xuerui wrote:
> +static bool reloc_call(tcg_insn_unit *src_rw, const tcg_insn_unit *target)
> +{
> +    const tcg_insn_unit *src_rx = tcg_splitwx_to_rx(src_rw);
> +    intptr_t offset = (intptr_t)target - (intptr_t)src_rx;
> +    int32_t lo = sextreg(offset, 0, 12);
> +    int32_t hi = offset - lo;
> +
> +    tcg_debug_assert((offset & 2) == 0);
> +    if (offset == hi + lo) {
> +        hi >>= 12;
> +        src_rw[0] |= (hi << 5) & 0x1ffffe0; /* pcaddu12i's Sj20 imm */
> +        lo >>= 2;
> +        src_rw[1] |= (lo << 10) & 0x3fffc00; /* jirl's Sk16 imm */
> +        return true;
> +    }
> +
> +    return false;
> +}

This doesn't seem to belong as a "reloc".
Certainly it doesn't seem like something that can simply be allowed to fail.


r~
WANG Xuerui Sept. 20, 2021, 5:15 p.m. UTC | #2
Hi Richard,

On 9/20/21 22:36, Richard Henderson wrote:
> On 9/20/21 1:04 AM, WANG Xuerui wrote:
>> +static bool reloc_call(tcg_insn_unit *src_rw, const tcg_insn_unit 
>> *target)
>> +{
>> +    const tcg_insn_unit *src_rx = tcg_splitwx_to_rx(src_rw);
>> +    intptr_t offset = (intptr_t)target - (intptr_t)src_rx;
>> +    int32_t lo = sextreg(offset, 0, 12);
>> +    int32_t hi = offset - lo;
>> +
>> +    tcg_debug_assert((offset & 2) == 0);
>> +    if (offset == hi + lo) {
>> +        hi >>= 12;
>> +        src_rw[0] |= (hi << 5) & 0x1ffffe0; /* pcaddu12i's Sj20 imm */
>> +        lo >>= 2;
>> +        src_rw[1] |= (lo << 10) & 0x3fffc00; /* jirl's Sk16 imm */
>> +        return true;
>> +    }
>> +
>> +    return false;
>> +}
>
> This doesn't seem to belong as a "reloc".
> Certainly it doesn't seem like something that can simply be allowed to 
> fail.
>
Yes, you're right on this; on closer look at the riscv port they 
actually reused this logic once (the riscv port drops large constants to 
pool, hence need some PC-relative hackery). For LoongArch the only usage 
of this code is for generating calls, so I'll just merge this into the 
commit doing tcg_out_call, and inline if the resulting code is still 
readable.

And it's 1 a.m. here in China, so I'll be processing the other review 
comments after getting some sleep. (Today's in the middle of the 3-day 
Mid-Autumn Festival holiday here, and that's why I can work on this 
hobby project like it's $DAY_JOB!) I'll send the v2 hopefully at 
afternoon local time (tomorrow in your timezone).

>
> r~
diff mbox series

Patch

diff --git a/tcg/loongarch/tcg-target.c.inc b/tcg/loongarch/tcg-target.c.inc
index 594b434b47..8be34f8275 100644
--- a/tcg/loongarch/tcg-target.c.inc
+++ b/tcg/loongarch/tcg-target.c.inc
@@ -164,3 +164,87 @@  static bool tcg_target_const_match(int64_t val, TCGType type, int ct)
     }
     return 0;
 }
+
+/*
+ * Relocations
+ */
+
+/*
+ * Relocation records defined in LoongArch ELF psABI v1.00 is way too much
+ * complicated; a whopping stack machine is needed to stuff the fields, at
+ * the very least one SOP_PUSH and one SOP_POP (of the correct format) are
+ * needed.
+ *
+ * Hence, define our own simpler relocation types. Numbers are chosen as to
+ * not collide with potential future additions to the true ELF relocation
+ * type enum.
+ */
+
+/* Field Sk16; suitable for conditional jumps */
+#define R_LOONGARCH_SK16    256
+/* Field Sd10k16; suitable for B and BL */
+#define R_LOONGARCH_SD10K16 257
+
+static bool reloc_sk16(tcg_insn_unit *src_rw, const tcg_insn_unit *target)
+{
+    const tcg_insn_unit *src_rx = tcg_splitwx_to_rx(src_rw);
+    intptr_t offset = (intptr_t)target - (intptr_t)src_rx;
+
+    tcg_debug_assert((offset & 2) == 0);
+    offset >>= 2;
+    if (offset == sextreg(offset, 0, 16)) {
+        *src_rw |= (offset << 10) & 0x3fffc00;
+        return true;
+    }
+
+    return false;
+}
+
+static bool reloc_sd10k16(tcg_insn_unit *src_rw, const tcg_insn_unit *target)
+{
+    const tcg_insn_unit *src_rx = tcg_splitwx_to_rx(src_rw);
+    intptr_t offset = (intptr_t)target - (intptr_t)src_rx;
+
+    tcg_debug_assert((offset & 2) == 0);
+    offset >>= 2;
+    if (offset == sextreg(offset, 0, 26)) {
+        *src_rw |= (offset >> 16) & 0x3ff; /* slot d10 */
+        *src_rw |= ((offset & 0xffff) << 10) & 0x3fffc00; /* slot k16 */
+        return true;
+    }
+
+    return false;
+}
+
+static bool reloc_call(tcg_insn_unit *src_rw, const tcg_insn_unit *target)
+{
+    const tcg_insn_unit *src_rx = tcg_splitwx_to_rx(src_rw);
+    intptr_t offset = (intptr_t)target - (intptr_t)src_rx;
+    int32_t lo = sextreg(offset, 0, 12);
+    int32_t hi = offset - lo;
+
+    tcg_debug_assert((offset & 2) == 0);
+    if (offset == hi + lo) {
+        hi >>= 12;
+        src_rw[0] |= (hi << 5) & 0x1ffffe0; /* pcaddu12i's Sj20 imm */
+        lo >>= 2;
+        src_rw[1] |= (lo << 10) & 0x3fffc00; /* jirl's Sk16 imm */
+        return true;
+    }
+
+    return false;
+}
+
+static bool patch_reloc(tcg_insn_unit *code_ptr, int type,
+                        intptr_t value, intptr_t addend)
+{
+    tcg_debug_assert(addend == 0);
+    switch (type) {
+    case R_LOONGARCH_SK16:
+        return reloc_sk16(code_ptr, (tcg_insn_unit *)value);
+    case R_LOONGARCH_SD10K16:
+        return reloc_sd10k16(code_ptr, (tcg_insn_unit *)value);
+    default:
+        g_assert_not_reached();
+    }
+}