Commit c30be785e9 for qemu.org
commit c30be785e931cffca64484b6d43f91ec500de65b
Author: Brian Cain <brian.cain@oss.qualcomm.com>
Date: Sat Sep 5 12:59:50 2026 -0700
target/hexagon: fix HVX big-endian byte access
Keep HVX lanes host-native while converting byte indexes at memory
and helper boundaries.
Also place vector comparison predicate bytes according to host word order.
Suggested-by: Anton Johansson <anjo@rev.ng>
Reviewed-by: Anton Johansson <anjo@rev.ng>
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/cpu.c b/target/hexagon/cpu.c
index 912bae7b6c..1f7d8a8df7 100644
--- a/target/hexagon/cpu.c
+++ b/target/hexagon/cpu.c
@@ -192,7 +192,7 @@ static void print_vreg(FILE *f, CPUHexagonState *env, int regnum,
if (skip_if_zero) {
bool nonzero_found = false;
for (int i = 0; i < MAX_VEC_SIZE_BYTES; i++) {
- if (hex_hvx(env)->VRegs[regnum].ub[i] != 0) {
+ if (hexagon_mmvec_get_byte(&hex_hvx(env)->VRegs[regnum], i) != 0) {
nonzero_found = true;
break;
}
@@ -204,9 +204,11 @@ static void print_vreg(FILE *f, CPUHexagonState *env, int regnum,
qemu_fprintf(f, " v%d = ( ", regnum);
qemu_fprintf(f, "0x%02x",
- hex_hvx(env)->VRegs[regnum].ub[MAX_VEC_SIZE_BYTES - 1]);
+ hexagon_mmvec_get_byte(&hex_hvx(env)->VRegs[regnum],
+ MAX_VEC_SIZE_BYTES - 1));
for (int i = MAX_VEC_SIZE_BYTES - 2; i >= 0; i--) {
- qemu_fprintf(f, ", 0x%02x", hex_hvx(env)->VRegs[regnum].ub[i]);
+ qemu_fprintf(f, ", 0x%02x",
+ hexagon_mmvec_get_byte(&hex_hvx(env)->VRegs[regnum], i));
}
qemu_fprintf(f, " )\n");
}
@@ -222,7 +224,7 @@ static void print_qreg(FILE *f, CPUHexagonState *env, int regnum,
if (skip_if_zero) {
bool nonzero_found = false;
for (int i = 0; i < MAX_VEC_SIZE_BYTES / 8; i++) {
- if (hex_hvx(env)->QRegs[regnum].ub[i] != 0) {
+ if (hexagon_mmqreg_get_byte(&hex_hvx(env)->QRegs[regnum], i) != 0) {
nonzero_found = true;
break;
}
@@ -234,9 +236,11 @@ static void print_qreg(FILE *f, CPUHexagonState *env, int regnum,
qemu_fprintf(f, " q%d = ( ", regnum);
qemu_fprintf(f, "0x%02x",
- hex_hvx(env)->QRegs[regnum].ub[MAX_VEC_SIZE_BYTES / 8 - 1]);
+ hexagon_mmqreg_get_byte(&hex_hvx(env)->QRegs[regnum],
+ MAX_VEC_SIZE_BYTES / 8 - 1));
for (int i = MAX_VEC_SIZE_BYTES / 8 - 2; i >= 0; i--) {
- qemu_fprintf(f, ", 0x%02x", hex_hvx(env)->QRegs[regnum].ub[i]);
+ qemu_fprintf(f, ", 0x%02x",
+ hexagon_mmqreg_get_byte(&hex_hvx(env)->QRegs[regnum], i));
}
qemu_fprintf(f, " )\n");
}
diff --git a/target/hexagon/genptr.c b/target/hexagon/genptr.c
index e1330d8e0b..cd4ae2f683 100644
--- a/target/hexagon/genptr.c
+++ b/target/hexagon/genptr.c
@@ -1590,7 +1590,8 @@ static void vec_to_qvec(size_t size, TCGv_ptr dstbase, intptr_t dstoff,
tcg_gen_deposit_i64(mask, mask, bits, j, size);
}
- tcg_gen_st8_i64(mask, dstbase, dstoff + i);
+ tcg_gen_st8_i64(mask, dstbase,
+ dstoff + (i ^ (HOST_BIG_ENDIAN ? 3 : 0)));
}
}
diff --git a/target/hexagon/mmvec/macros.h b/target/hexagon/mmvec/macros.h
index df695d0731..5e346b7296 100644
--- a/target/hexagon/mmvec/macros.h
+++ b/target/hexagon/mmvec/macros.h
@@ -53,7 +53,7 @@
#define LOG_VTCM_BYTE(VA, MASK, VAL, IDX) \
do { \
- env->vtcm_log.data.ub[IDX] = (VAL); \
+ hexagon_mmvec_set_byte(&env->vtcm_log.data, IDX, VAL); \
if (MASK) { \
set_bit((IDX), env->vtcm_log.mask); \
} else { \
@@ -133,7 +133,8 @@
target_ulong va_high = EA + LEN; \
for (int i0 = 0; i0 < 4; i0++) { \
log_byte = (va + i0) <= va_high; \
- LOG_VTCM_BYTE(va + i0, log_byte, INC. ub[4 * IDX + i0], \
+ LOG_VTCM_BYTE(va + i0, log_byte, \
+ hexagon_mmvec_get_byte(&(INC), 4 * IDX + i0), \
4 * IDX + i0); \
} \
} while (0)
@@ -144,7 +145,8 @@
target_ulong va_high = EA + LEN; \
for (int i0 = 0; i0 < 2; i0++) { \
log_byte = (va + i0) <= va_high; \
- LOG_VTCM_BYTE(va + i0, log_byte, INC.ub[2 * IDX + i0], \
+ LOG_VTCM_BYTE(va + i0, log_byte, \
+ hexagon_mmvec_get_byte(&(INC), 2 * IDX + i0), \
2 * IDX + i0); \
} \
} while (0)
@@ -157,7 +159,8 @@
target_ulong va_high = EA + LEN; \
for (int i0 = 0; i0 < 2; i0++) { \
log_byte = (va + i0) <= va_high; \
- LOG_VTCM_BYTE(va + i0, log_byte, INC.ub[2 * IDX + i0], \
+ LOG_VTCM_BYTE(va + i0, log_byte, \
+ hexagon_mmvec_get_byte(&(INC), 2 * IDX + i0), \
2 * IDX + i0); \
} \
} while (0)
@@ -174,7 +177,8 @@
log_byte = ((va + i0) <= va_high) && QVAL; \
uint8_t B; \
B = cpu_ldub_data_ra(env, EA + i0, ra); \
- env->tmp_VRegs[0].ub[ELEMENT_SIZE * IDX + i0] = B; \
+ 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)
@@ -216,9 +220,10 @@
uint8_t val; \
val = cpu_ldub_data_ra(env, env->vtcm_log.va[i + j], ra); \
dst |= val << (8 * j); \
- inc |= env->vtcm_log.data.ub[j + i] << (8 * j); \
+ inc |= hexagon_mmvec_get_byte(&env->vtcm_log.data, j + i) \
+ << (8 * j); \
clear_bit(j + i, env->vtcm_log.mask); \
- env->vtcm_log.data.ub[j + i] = 0; \
+ hexagon_mmvec_set_byte(&env->vtcm_log.data, j + i, 0); \
} \
dst += inc; \
for (int j = 0; j < sizeof(TYPE); j++) { \
@@ -249,7 +254,9 @@
int log_byte = 0; \
for (i0 = 0; i0 < ELEM_SIZE; i0++) { \
log_byte = ((va + i0) <= va_high) && QVAL; \
- LOG_VTCM_BYTE(va + i0, log_byte, IN.ub[ELEM_SIZE * IDX + i0], \
+ LOG_VTCM_BYTE(va + i0, log_byte, \
+ hexagon_mmvec_get_byte(&(IN), \
+ ELEM_SIZE * IDX + i0), \
ELEM_SIZE * IDX + i0); \
} \
} while (0)
diff --git a/target/hexagon/mmvec/mmvec.h b/target/hexagon/mmvec/mmvec.h
index 8e72f2f6ae..662f9d1597 100644
--- a/target/hexagon/mmvec/mmvec.h
+++ b/target/hexagon/mmvec/mmvec.h
@@ -20,6 +20,7 @@
#include "exec/target_long.h"
#include "qemu/bitmap.h"
+#include "qemu/bitops.h"
#define MAX_VEC_SIZE_LOGBYTES 7
#define MAX_VEC_SIZE_BYTES (1 << MAX_VEC_SIZE_LOGBYTES)
@@ -69,6 +70,23 @@ typedef union {
int8_t b[MAX_VEC_SIZE_BYTES / 1 / 8];
} MMQReg;
+static inline uint8_t hexagon_mmvec_get_byte(const MMVector *v, size_t index)
+{
+ return extract64(v->ud[index / 8], (index % 8) * 8, 8);
+}
+
+static inline void hexagon_mmvec_set_byte(MMVector *v, size_t index,
+ uint8_t value)
+{
+ v->ud[index / 8] = deposit64(v->ud[index / 8], (index % 8) * 8, 8,
+ value);
+}
+
+static inline uint8_t hexagon_mmqreg_get_byte(const MMQReg *q, size_t index)
+{
+ return extract32(q->uw[index / 4], (index % 4) * 8, 8);
+}
+
typedef struct {
MMVector data;
DECLARE_BITMAP(mask, MAX_VEC_SIZE_BYTES);
diff --git a/target/hexagon/mmvec/system_ext_mmvec.c b/target/hexagon/mmvec/system_ext_mmvec.c
index 8351f2cc01..081cadd814 100644
--- a/target/hexagon/mmvec/system_ext_mmvec.c
+++ b/target/hexagon/mmvec/system_ext_mmvec.c
@@ -26,7 +26,7 @@ void mem_gather_store(CPUHexagonState *env, target_ulong vaddr, int slot)
env->vstore_pending[slot] = 1;
env->vstore[slot].va = vaddr;
env->vstore[slot].size = size;
- memcpy(&env->vstore[slot].data.ub[0], &env->tmp_VRegs[0], size);
+ memcpy(&env->vstore[slot].data, &env->tmp_VRegs[0], size);
/* On a gather store, overwrite the store mask to emulate dropped gathers */
bitmap_copy(env->vstore[slot].mask, env->vtcm_log.mask, size);
diff --git a/target/hexagon/op_helper.c b/target/hexagon/op_helper.c
index 47c7953b92..4f00ca773f 100644
--- a/target/hexagon/op_helper.c
+++ b/target/hexagon/op_helper.c
@@ -168,7 +168,10 @@ void HELPER(commit_hvx_stores)(CPUHexagonState *env)
int size = env->vstore[i].size;
for (int j = 0; j < size; j++) {
if (test_bit(j, env->vstore[i].mask)) {
- cpu_stb_data_ra(env, va + j, env->vstore[i].data.ub[j], ra);
+ cpu_stb_data_ra(env, va + j,
+ hexagon_mmvec_get_byte(&env->vstore[i].data,
+ j),
+ ra);
}
}
}
@@ -191,9 +194,11 @@ void HELPER(commit_hvx_stores)(CPUHexagonState *env)
for (int i = 0; i < sizeof(MMVector); i++) {
if (test_bit(i, env->vtcm_log.mask)) {
cpu_stb_data_ra(env, env->vtcm_log.va[i],
- env->vtcm_log.data.ub[i], ra);
+ hexagon_mmvec_get_byte(&env->vtcm_log.data,
+ i),
+ ra);
clear_bit(i, env->vtcm_log.mask);
- env->vtcm_log.data.ub[i] = 0;
+ hexagon_mmvec_set_byte(&env->vtcm_log.data, i, 0);
}
}
@@ -1404,7 +1409,8 @@ void HELPER(vhist)(CPUHexagonState *env)
for (int lane = 0; lane < 8; lane++) {
for (int i = 0; i < sizeof(MMVector) / 8; ++i) {
- unsigned char value = input->ub[(sizeof(MMVector) / 8) * lane + i];
+ unsigned char value = hexagon_mmvec_get_byte(input,
+ (sizeof(MMVector) / 8) * lane + i);
unsigned char regno = value >> 3;
unsigned char element = value & 7;
@@ -1420,7 +1426,8 @@ void HELPER(vhistq)(CPUHexagonState *env)
for (int lane = 0; lane < 8; lane++) {
for (int i = 0; i < sizeof(MMVector) / 8; ++i) {
- unsigned char value = input->ub[(sizeof(MMVector) / 8) * lane + i];
+ unsigned char value = hexagon_mmvec_get_byte(input,
+ (sizeof(MMVector) / 8) * lane + i);
unsigned char regno = value >> 3;
unsigned char element = value & 7;