diff mbox series

[v3,07/30] tcg/loongarch64: Implement necessary relocation operations

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

Commit Message

WANG Xuerui Sept. 22, 2021, 6:09 p.m. UTC
Signed-off-by: WANG Xuerui <git@xen0n.name>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
---
 tcg/loongarch64/tcg-target.c.inc | 66 ++++++++++++++++++++++++++++++++
 1 file changed, 66 insertions(+)

Comments

Philippe Mathieu-Daudé Sept. 22, 2021, 6:41 p.m. UTC | #1
On 9/22/21 20:09, WANG Xuerui wrote:
> Signed-off-by: WANG Xuerui <git@xen0n.name>
> Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
> ---
>   tcg/loongarch64/tcg-target.c.inc | 66 ++++++++++++++++++++++++++++++++
>   1 file changed, 66 insertions(+)

> +/* Field Sk16, shifted right by 2; suitable for conditional jumps */
> +#define R_LOONGARCH_BR_SK16     256
> +/* Field Sd10k16, shifted right by 2; suitable for B and BL */
> +#define R_LOONGARCH_BR_SD10K16  257
> +
> +static bool reloc_br_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 & 3) == 0);
> +    offset >>= 2;
> +    if (offset == sextreg(offset, 0, 16)) {
> +        *src_rw |= (offset << 10) & 0x3fffc00;

Alternatively easier to read:

            *src_rw = deposit64(*src_rw , 10, 16, offset);

> +        return true;
> +    }
> +
> +    return false;
> +}
WANG Xuerui Sept. 22, 2021, 6:55 p.m. UTC | #2
Hi Philippe,

On 9/23/21 02:41, Philippe Mathieu-Daudé wrote:
> On 9/22/21 20:09, WANG Xuerui wrote:
>> Signed-off-by: WANG Xuerui <git@xen0n.name>
>> Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
>> ---
>>   tcg/loongarch64/tcg-target.c.inc | 66 ++++++++++++++++++++++++++++++++
>>   1 file changed, 66 insertions(+)
>
>> +/* Field Sk16, shifted right by 2; suitable for conditional jumps */
>> +#define R_LOONGARCH_BR_SK16     256
>> +/* Field Sd10k16, shifted right by 2; suitable for B and BL */
>> +#define R_LOONGARCH_BR_SD10K16  257
>> +
>> +static bool reloc_br_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 & 3) == 0);
>> +    offset >>= 2;
>> +    if (offset == sextreg(offset, 0, 16)) {
>> +        *src_rw |= (offset << 10) & 0x3fffc00;
>
> Alternatively easier to read:
>
>            *src_rw = deposit64(*src_rw , 10, 16, offset);
Hmm, this helper could surely be reused at multiple places... I'll try 
to replace other operations like this in v4.
>
>> +        return true;
>> +    }
>> +
>> +    return false;
>> +}
diff mbox series

Patch

diff --git a/tcg/loongarch64/tcg-target.c.inc b/tcg/loongarch64/tcg-target.c.inc
index f0930f77ef..69e882ba5d 100644
--- a/tcg/loongarch64/tcg-target.c.inc
+++ b/tcg/loongarch64/tcg-target.c.inc
@@ -168,3 +168,69 @@  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
+ * 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, shifted right by 2; suitable for conditional jumps */
+#define R_LOONGARCH_BR_SK16     256
+/* Field Sd10k16, shifted right by 2; suitable for B and BL */
+#define R_LOONGARCH_BR_SD10K16  257
+
+static bool reloc_br_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 & 3) == 0);
+    offset >>= 2;
+    if (offset == sextreg(offset, 0, 16)) {
+        *src_rw |= (offset << 10) & 0x3fffc00;
+        return true;
+    }
+
+    return false;
+}
+
+static bool reloc_br_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 & 3) == 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 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_BR_SK16:
+        return reloc_br_sk16(code_ptr, (tcg_insn_unit *)value);
+    case R_LOONGARCH_BR_SD10K16:
+        return reloc_br_sd10k16(code_ptr, (tcg_insn_unit *)value);
+    default:
+        g_assert_not_reached();
+    }
+}