Hello,
Gentle ping. The fix just consist in allocating a new TCG temp for the
address if we need to modify it.
Thanks
Luc
On 09:23 Fri 10 Jul , Luc Michel wrote:
> Since 36a9529e60e0 the TCGv returned by compute_ldst_addr_type{a,b} for
> the address can be a target register or a constant. However
> do_{load,store} might modify it in the case of a reversed load/store.
>
> Fix this by factoring out the reversed access logic and copying the
> address in a new TCGv_i32 if it needs to be modified.
>
> Fixes: 36a9529e60e0 (target/microblaze: Simplify compute_ldst_addr_type{a,b})
> Signed-off-by: Luc Michel <[email protected]>
> ---
> target/microblaze/translate.c | 56 ++++++++++++++++++++---------------
> 1 file changed, 32 insertions(+), 24 deletions(-)
>
> diff --git a/target/microblaze/translate.c b/target/microblaze/translate.c
> index 8b219afb5dd..9fb84e1bf9f 100644
> --- a/target/microblaze/translate.c
> +++ b/target/microblaze/translate.c
> @@ -701,30 +701,47 @@ static void gen_alignment_check_ea(DisasContext *dc,
> TCGv_i64 ea, int rb,
> static inline MemOp mo_endian(DisasContext *dc)
> {
> return dc->cfg->endi ? MO_LE : MO_BE;
> }
>
> +static void handle_reversed_access(MemOp *mop, TCGv_i32 *addr)
> +{
> + MemOp size = *mop & MO_SIZE;
> +
> + /*
> + * When doing reverse accesses we need to do two things.
> + *
> + * 1. Reverse the address wrt endianness.
> + * 2. Byteswap the data lanes on the way back into the CPU core.
> + *
> + * Use a new TCGv_i32 to modify the address because the current one
> might be
> + * a register or a constant.
> + */
> +
> + if (size > MO_8) {
> + *mop ^= MO_BSWAP;
> + }
> +
> + if (size < MO_32) {
> + TCGv_i32 new_addr = tcg_temp_new_i32();
> +
> + tcg_gen_xori_i32(new_addr, *addr, 3 - size);
> + *addr = new_addr;
> + }
> +}
> +
> static bool do_load(DisasContext *dc, int rd, TCGv_i32 addr, MemOp mop,
> int mem_index, bool rev)
> {
> +#ifndef CONFIG_USER_ONLY
> MemOp size = mop & MO_SIZE;
> +#endif
>
> mop |= mo_endian(dc);
>
> - /*
> - * When doing reverse accesses we need to do two things.
> - *
> - * 1. Reverse the address wrt endianness.
> - * 2. Byteswap the data lanes on the way back into the CPU core.
> - */
> if (rev) {
> - if (size > MO_8) {
> - mop ^= MO_BSWAP;
> - }
> - if (size < MO_32) {
> - tcg_gen_xori_i32(addr, addr, 3 - size);
> - }
> + handle_reversed_access(&mop, &addr);
> }
>
> /*
> * For system mode, enforce alignment if the cpu configuration
> * requires it. For user-mode, the Linux kernel will have fixed up
> @@ -864,27 +881,18 @@ static bool trans_lwx(DisasContext *dc, arg_typea *arg)
> }
>
> static bool do_store(DisasContext *dc, int rd, TCGv_i32 addr, MemOp mop,
> int mem_index, bool rev)
> {
> +#ifndef CONFIG_USER_ONLY
> MemOp size = mop & MO_SIZE;
> +#endif
>
> mop |= mo_endian(dc);
>
> - /*
> - * When doing reverse accesses we need to do two things.
> - *
> - * 1. Reverse the address wrt endianness.
> - * 2. Byteswap the data lanes on the way back into the CPU core.
> - */
> if (rev) {
> - if (size > MO_8) {
> - mop ^= MO_BSWAP;
> - }
> - if (size < MO_32) {
> - tcg_gen_xori_i32(addr, addr, 3 - size);
> - }
> + handle_reversed_access(&mop, &addr);
> }
>
> /*
> * For system mode, enforce alignment if the cpu configuration
> * requires it. For user-mode, the Linux kernel will have fixed up
> --
> 2.53.0
>
--