Commit 6fe0379302 for qemu.org

commit 6fe0379302c0f092147f34071deffd84f133278c
Author: Brian Cain <brian.cain@oss.qualcomm.com>
Date:   Sat Sep 5 12:59:51 2026 -0700

    target/hexagon: fix HVX scatter/gather region-length check

    The region-length bounds check compared (EA + i0) <= (EA + LEN),
    which reduces to i0 <= LEN and never actually depends on the region
    base. This let vgather/vscatter keep elements whose offset was
    beyond the declared region instead of dropping them. Compare the
    offset to the region length directly instead.

    Only load bytes for gather lanes that are kept. A dropped or
    predicate-false lane must not access memory and raise an exception.

    Reviewed-by: Matheus Tavares Bernardino <matheus.bernardino@oss.qualcomm.com>
    Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>

diff --git a/target/hexagon/mmvec/macros.h b/target/hexagon/mmvec/macros.h
index 5e346b7296..f85d99735d 100644
--- a/target/hexagon/mmvec/macros.h
+++ b/target/hexagon/mmvec/macros.h
@@ -130,9 +130,9 @@
     do { \
         int log_byte = 0; \
         target_ulong va = EA; \
-        target_ulong va_high = EA + LEN; \
+        int in_region = (OFFSET) <= (LEN); \
         for (int i0 = 0; i0 < 4; i0++) { \
-            log_byte = (va + i0) <= va_high; \
+            log_byte = in_region; \
             LOG_VTCM_BYTE(va + i0, log_byte, \
                            hexagon_mmvec_get_byte(&(INC), 4 * IDX + i0), \
                           4 * IDX + i0); \
@@ -142,9 +142,9 @@
     do { \
         int log_byte = 0; \
         target_ulong va = EA; \
-        target_ulong va_high = EA + LEN; \
+        int in_region = (OFFSET) <= (LEN); \
         for (int i0 = 0; i0 < 2; i0++) { \
-            log_byte = (va + i0) <= va_high; \
+            log_byte = in_region; \
             LOG_VTCM_BYTE(va + i0, log_byte, \
                            hexagon_mmvec_get_byte(&(INC), 2 * IDX + i0), \
                           2 * IDX + i0); \
@@ -156,9 +156,9 @@
     do { \
         int log_byte = 0; \
         target_ulong va = EA; \
-        target_ulong va_high = EA + LEN; \
+        int in_region = (OFFSET) <= (LEN); \
         for (int i0 = 0; i0 < 2; i0++) { \
-            log_byte = (va + i0) <= va_high; \
+            log_byte = in_region; \
             LOG_VTCM_BYTE(va + i0, log_byte, \
                            hexagon_mmvec_get_byte(&(INC), 2 * IDX + i0), \
                           2 * IDX + i0); \
@@ -170,15 +170,18 @@
     do { \
         int i0; \
         target_ulong va = EA; \
-        target_ulong va_high = EA + LEN; \
         uintptr_t ra = GETPC(); \
         int log_byte = 0; \
+        int in_region = (OFFSET) <= (LEN); \
         for (i0 = 0; i0 < ELEMENT_SIZE; i0++) { \
-            log_byte = ((va + i0) <= va_high) && QVAL; \
-            uint8_t B; \
-            B = cpu_ldub_data_ra(env, EA + i0, ra); \
-            hexagon_mmvec_set_byte(&env->tmp_VRegs[0], \
-                                   ELEMENT_SIZE * IDX + i0, B); \
+            uint8_t B = 0; \
+            \
+            log_byte = in_region && QVAL; \
+            if (log_byte) { \
+                B = cpu_ldub_data_ra(env, va + i0, ra); \
+                hexagon_mmvec_set_byte(&env->tmp_VRegs[0], \
+                                       ELEMENT_SIZE * IDX + i0, B); \
+            } \
             LOG_VTCM_BYTE(va + i0, log_byte, B, ELEMENT_SIZE * IDX + i0); \
         } \
     } while (0)
@@ -250,10 +253,10 @@
     do { \
         int i0; \
         target_ulong va = EA; \
-        target_ulong va_high = EA + LEN; \
         int log_byte = 0; \
+        int in_region = (OFFSET) <= (LEN); \
         for (i0 = 0; i0 < ELEM_SIZE; i0++) { \
-            log_byte = ((va + i0) <= va_high) && QVAL; \
+            log_byte = in_region && QVAL; \
             LOG_VTCM_BYTE(va + i0, log_byte, \
                            hexagon_mmvec_get_byte(&(IN), \
                                                     ELEM_SIZE * IDX + i0), \