[PATCH] target/microblaze/translate: fix reversed load/store translation

Luc Michel posted 1 patch 1 day, 16 hours ago
Patches applied successfully (tree, apply log)
git fetch https://github.com/patchew-project/qemu tags/patchew/20260710072348.3575-1-luc.michel@amd.com
Maintainers: "Edgar E. Iglesias" <edgar.iglesias@gmail.com>
target/microblaze/translate.c | 56 ++++++++++++++++++++---------------
1 file changed, 32 insertions(+), 24 deletions(-)
[PATCH] target/microblaze/translate: fix reversed load/store translation
Posted by Luc Michel 1 day, 16 hours ago
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 <luc.michel@amd.com>
---
 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