Commit 9fa3e90f01 for qemu.org

commit 9fa3e90f01dc41f4dfabdba34b111b1168b62394
Author: Brian Cain <brian.cain@oss.qualcomm.com>
Date:   Tue Sep 15 09:30:37 2026 -0700

    tests/tcg/hexagon: add bit interleave and convergent rounding tests

    Test the interleave/deinterleave 64-bit bit-manipulation instructions
    and the cround instruction.

    Reviewed-by: Sid Manning <sid.manning@oss.qualcomm.com>
    Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>

diff --git a/tests/tcg/hexagon/meson.build b/tests/tcg/hexagon/meson.build
index e3017db24f..6935d02802 100644
--- a/tests/tcg/hexagon/meson.build
+++ b/tests/tcg/hexagon/meson.build
@@ -69,6 +69,7 @@ tests += {
   'test_abs.S': {'cflags': asmflags},
   'test_bitcnt.S': {'cflags': asmflags},
   'test_bitsplit.S': {'cflags': asmflags},
+  'test_bitops.c': {'cflags': cflags},
   'test_call.S': {'cflags': asmflags},
   'test_clobber.S': {'cflags': asmflags},
   'test_cmp.S': {'cflags': asmflags},
diff --git a/tests/tcg/hexagon/test_bitops.c b/tests/tcg/hexagon/test_bitops.c
new file mode 100644
index 0000000000..3e9274dddd
--- /dev/null
+++ b/tests/tcg/hexagon/test_bitops.c
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+/*
+ * Test bit interleave/deinterleave and convergent rounding.
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <hexagon_protos.h>
+
+int err;
+
+#include "hex_test.h"
+
+static void check_interleave(void)
+{
+    uint64_t input;
+    uint64_t inter;
+    uint64_t deinter;
+
+    /*
+     * interleave takes the 32 even bits and 32 odd bits of Rss and
+     * interleaves them: even[0] goes to bit 0, odd[0] to bit 1,
+     * even[1] to bit 2, odd[1] to bit 3, etc.
+     *
+     * Input:  low 32 bits (even half), high 32 bits (odd half)
+     * If low = 0xFFFFFFFF, high = 0x00000000:
+     *   result has every even bit set, every odd bit clear
+     *   = 0x5555555555555555
+     */
+    input = 0x00000000FFFFFFFFULL;
+    inter = Q6_P_interleave_P(input);
+    check64(inter, 0x5555555555555555ULL);
+
+    /* All ones should stay all ones */
+    input = 0xFFFFFFFFFFFFFFFFULL;
+    inter = Q6_P_interleave_P(input);
+    check64(inter, 0xFFFFFFFFFFFFFFFFULL);
+
+    /* All zeros should stay all zeros */
+    input = 0x0000000000000000ULL;
+    inter = Q6_P_interleave_P(input);
+    check64(inter, 0x0000000000000000ULL);
+
+    /*
+     * deinterleave is the inverse of interleave.
+     * deinterleave(interleave(x)) should equal x.
+     */
+    input = 0xDEADBEEFCAFEBABEULL;
+    inter = Q6_P_interleave_P(input);
+    deinter = Q6_P_deinterleave_P(inter);
+    check64(deinter, input);
+
+    /* deinterleave of 0x5555...5555 -> low half all 1s, high half all 0s */
+    deinter = Q6_P_deinterleave_P(0x5555555555555555ULL);
+    check64(deinter, 0x00000000FFFFFFFFULL);
+}
+
+static void check_cround(void)
+{
+    /*
+     * cround(0x300, #8) -> 3 (exact shift, no rounding needed).
+     * 0x300 >> 8 = 3
+     */
+    check32(Q6_R_cround_RI(0x300, 8), 3);
+
+    /*
+     * cround(0x380, #8) -> 4 (0x380 >> 8 = 3.5, rounds to even = 4)
+     */
+    check32(Q6_R_cround_RI(0x380, 8), 4);
+
+    /*
+     * cround(0x280, #8) -> 2 (0x280 >> 8 = 2.5, rounds to even = 2)
+     */
+    check32(Q6_R_cround_RI(0x280, 8), 2);
+
+    /*
+     * cround(0x3C0, #8) -> 4 (0x3C0 >> 8 = 3.75, rounds up to 4)
+     */
+    check32(Q6_R_cround_RI(0x3C0, 8), 4);
+
+    /*
+     * Shift by 0 -> return the input unchanged.
+     */
+    check32(Q6_R_cround_RI(42, 0), 42);
+}
+
+int main(void)
+{
+    check_interleave();
+    check_cround();
+
+    puts(err ? "FAIL" : "PASS");
+    return err ? 1 : 0;
+}