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;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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
Block a user