Message ID | 20241212151412.570454-7-mark.cave-ayland@ilande.co.uk (mailing list archive) |
---|---|
State | New |
Headers | show |
Series | target/ppc: implement legacy address-swizzling MSR_LE support | expand |
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 <mark.cave-ayland@ilande.co.uk> > --- > 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~
diff --git a/target/ppc/translate.c b/target/ppc/translate.c index 1211435039..ddc0f85fb7 100644 --- a/target/ppc/translate.c +++ b/target/ppc/translate.c @@ -2561,6 +2561,24 @@ static TCGv do_ea_calc(DisasContext *ctx, int ra, TCGv displ) return ea; } +/* + * 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 + * 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) +{ + 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); +} + #if defined(TARGET_PPC64) /* EA <- (ra == 0) ? 0 : GPR[ra] */ static TCGv do_ea_calc_ra(DisasContext *ctx, int ra) @@ -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); } } @@ -2629,6 +2651,10 @@ static void gen_st_tl(DisasContext *ctx, TCGv val, TCGv addr, TCGArg idx, { if (!need_addrswizzle_le(ctx)) { tcg_gen_qemu_st_tl(val, addr, idx, memop); + } else { + TCGv taddr = tcg_temp_new(); + gen_addr_swizzle_le(taddr, addr, memop); + tcg_gen_qemu_st_tl(val, taddr, idx, memop); } }
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 <mark.cave-ayland@ilande.co.uk> --- target/ppc/translate.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+)