On 12/12/24 09:14, Mark Cave-Ayland wrote:
This function is used to swizzle the address lines to implement little endian
accesses as used by older CPUs. Add the address line swizzle to the gen_ld_tl()
and gen_st_tl() functions.
Signed-off-by: Mark Cave-Ayland <[email protected]>
---
target/ppc/translate.c | 26 ++++++++++++++++++++++++++
1 file changed, 26 insertions(+)
Right. So, this *can't* be split from patch 5.
+/*
+ * Swizzle the address lines for little endian accesses as used by older
+ * CPUs. The bottom 3 address lines are exlusive-ORed by a constant to
typo for exclusive, though "xor'ed" is probably just as readable.
+ * generate the correct address for a little endian access. For more
+ * information see https://wiki.preterhuman.net/images/f/fc/Endian.pdf
+ */
+static inline void gen_addr_swizzle_le(TCGv ret, TCGv addr, MemOp op)
Drop the inline.
+{
+ MemOp size = op & MO_SIZE;
+ TCGv aoff = tcg_temp_new();
+ static int c_swizzle[MO_SIZE] = { 0x7, 0x6, 0x4, 0x0 };
+
+ tcg_gen_andi_tl(aoff, addr, (1 << size) - 1);
+ tcg_gen_andi_tl(ret, addr, ~((1 << size) - 1));
+ tcg_gen_xori_tl(ret, ret, c_swizzle[size]);
+ tcg_gen_sub_tl(ret, ret, aoff);
+}
I believe this is just
tcg_gen_xori_tl(ret, addr, 8 - memop_size(op));
@@ -2586,6 +2604,10 @@ static void gen_ld_tl(DisasContext *ctx, TCGv val, TCGv
addr, TCGArg idx,
{
if (!need_addrswizzle_le(ctx)) {
tcg_gen_qemu_ld_tl(val, addr, idx, memop);
+ } else {
+ TCGv taddr = tcg_temp_new();
+ gen_addr_swizzle_le(taddr, addr, memop);
+ tcg_gen_qemu_ld_tl(val, taddr, idx, memop);
}
}
if (need) {
/* BLRM is only found on old ppc32; the only MO_64 should be for the
FPU. */
assert(size < MO_64);
addr = gen_addr_swizzle_le(...);
}
tcg_gen_qemu_ld_tl(...);
You'll need to handle tcg_qemu_ld_i64 as well, and for that MO_64 needs
tcg_gen_rotli_i64(val, val, 32) after the load / before the store.
r~