mirror of https://github.com/xemu-project/xemu.git
tcg/loongarch64: Implement necessary relocation operations
Signed-off-by: WANG Xuerui <git@xen0n.name> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org> Message-Id: <20211221054105.178795-8-git@xen0n.name> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
parent
ba0cdd8040
commit
bf8c1c8140
|
@ -168,3 +168,69 @@ static bool tcg_target_const_match(int64_t val, TCGType type, int ct)
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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 = deposit64(*src_rw, 10, 16, offset);
|
||||||
|
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 = deposit64(*src_rw, 0, 10, offset >> 16); /* slot d10 */
|
||||||
|
*src_rw = deposit64(*src_rw, 10, 16, offset); /* 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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue