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 |
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~
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 --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(); + } +}
Signed-off-by: WANG Xuerui <git@xen0n.name> --- tcg/loongarch/tcg-target.c.inc | 84 ++++++++++++++++++++++++++++++++++ 1 file changed, 84 insertions(+)