Commit 78c6b6010c for qemu.org

commit 78c6b6010ce7cfa54874dda514e694640b76f1e4
Author: Peter Maydell <peter.maydell@linaro.org>
Date:   Thu Feb 12 15:07:53 2026 +0000

    target/ppc/translate: Fix TCG debug assert translating CLRBWIBC

    The test case in the ppe42 functional test triggers a TCG debug
    assertion, which causes the test to fail in an --enable-debug
    build or when the sanitizers are enabled:

    #6  0x00007ffff4a3b517 in __assert_fail
        (assertion=0x5555562e7589 "!temp_readonly(ots)", file=0x5555562e5b23 "../../tcg/tcg.c", line=4928, function=0x5555562e8900 <__PRETTY_FUNCTION__.23> "tcg_reg_alloc_mov") at ./assert/assert.c:105
    #7  0x0000555555cc2189 in tcg_reg_alloc_mov (s=0x7fff60000b70, op=0x7fff600126f8) at ../../tcg/tcg.c:4928
    #8  0x0000555555cc74e0 in tcg_gen_code (s=0x7fff60000b70, tb=0x7fffa802f540, pc_start=4294446080) at ../../tcg/tcg.c:6667
    #9  0x0000555555d02abe in setjmp_gen_code
        (env=0x555556cbe610, tb=0x7fffa802f540, pc=4294446080, host_pc=0x7fffeea00c00, max_insns=0x7fffee9f9d74, ti=0x7fffee9f9d90)
        at ../../accel/tcg/translate-all.c:257
    #10 0x0000555555d02d75 in tb_gen_code (cpu=0x555556cba590, s=...) at ../../accel/tcg/translate-all.c:325
    #11 0x0000555555cf5922 in cpu_exec_loop (cpu=0x555556cba590, sc=0x7fffee9f9ee0) at ../../accel/tcg/cpu-exec.c:970
    #12 0x0000555555cf5aae in cpu_exec_setjmp (cpu=0x555556cba590, sc=0x7fffee9f9ee0) at ../../accel/tcg/cpu-exec.c:1016
    #13 0x0000555555cf5b4b in cpu_exec (cpu=0x555556cba590) at ../../accel/tcg/cpu-exec.c:1042
    #14 0x0000555555d1e7ab in tcg_cpu_exec (cpu=0x555556cba590) at ../../accel/tcg/tcg-accel-ops.c:82
    #15 0x0000555555d1ff97 in rr_cpu_thread_fn (arg=0x555556cba590) at ../../accel/tcg/tcg-accel-ops-rr.c:285
    #16 0x00005555561586c9 in qemu_thread_start (args=0x555556ee3c90) at ../../util/qemu-thread-posix.c:393
    #17 0x00007ffff4a9caa4 in start_thread (arg=<optimized out>) at ./nptl/pthread_create.c:447
    #18 0x00007ffff4b29c6c in clone3 () at ../sysdeps/unix/sysv/linux/x86_64/clone3.S:78

    This can be reproduced "by hand":

     ./build/clang/qemu-system-ppc -display none -vga none \
        -machine ppe42_machine -serial stdio \
        -device loader,file=$HOME/.cache/qemu/download/03c1ac0fb7f6c025102a02776a93b35101dae7c14b75e4eab36a337e39042ea8 \
        -device loader,addr=0xfff80040,cpu-num=0

    (assuming you have the image file from the functional test
    in your local cache).

    This happens for this input:

    IN:
    0xfff80c00:  07436004  .byte    0x07, 0x43, 0x60, 0x04

    which generates (among other things):

     not_i32 $0x80000,$0x80000

    which the TCG optimization pass turns into:

     mov_i32 $0x80000,$0xfff7ffff             dead: 1  pref=0xffff

    and where we then assert because we tried to write to a constant.

    This happens for the CLRBWIBC instruction which ends up in
    do_mask_branch() with rb_is_gpr false and invert true.  In this case
    we will generate code that sets mask to a tcg_constant_tl() but then
    uses it as the LHS in tcg_gen_not_tl().

    Fix the assertion by doing the invert in the translate time C code
    for the "mask is constant" case.

    Cc: qemu-stable@nongnu.org
    Fixes: f7ec91c23906 ("target/ppc: Add IBM PPE42 special instructions")
    Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
    Reviewed-by: Glenn Miles <milesg@linux.ibm.com>
    Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
    Link: https://lore.kernel.org/qemu-devel/20260212150753.1749448-1-peter.maydell@linaro.org
    Signed-off-by: Harsh Prateek Bora <harshpb@linux.ibm.com>

diff --git a/target/ppc/translate/ppe-impl.c.inc b/target/ppc/translate/ppe-impl.c.inc
index 0a0590344e..1c27facb89 100644
--- a/target/ppc/translate/ppe-impl.c.inc
+++ b/target/ppc/translate/ppe-impl.c.inc
@@ -424,11 +424,15 @@ static bool do_mask_branch(DisasContext *ctx, arg_FCB * a, bool invert,
         shift = tcg_temp_new();
         tcg_gen_andi_tl(shift, cpu_gpr[a->rb], 0x1f);
         tcg_gen_shr_tl(mask, tcg_constant_tl(0x80000000), shift);
+        if (invert) {
+            tcg_gen_not_tl(mask, mask);
+        }
     } else {
-        mask = tcg_constant_tl(PPC_BIT32(a->rb));
-    }
-    if (invert) {
-        tcg_gen_not_tl(mask, mask);
+        target_ulong mask_const = PPC_BIT32(a->rb);
+        if (invert) {
+            mask_const = ~mask_const;
+        }
+        mask = tcg_constant_tl(mask_const);
     }

     /* apply mask to ra */