Commit 6ccd5ff3e8 for qemu.org
commit 6ccd5ff3e8328b393d0efc31ecb6ad82ddfb5585
Author: Brian Cain <brian.cain@oss.qualcomm.com>
Date: Wed Sep 23 10:15:13 2026 -0700
target/hexagon: raise an exception for HVX with SSR:XE clear
SSR:XE gates access to the HVX coprocessor: executing an HVX instruction
while it is clear must raise a precise exception with cause 0x16,
NO_COPROC_ENABLE.
Carry SSR:XE in a TB flag and emit the exception for the
first HVX packet of a TB when the coprocessor is disabled.
Reviewed-by: Marco Liebel <marco.liebel@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 fad526ccfb..19486e0f74 100644
--- a/target/hexagon/cpu.c
+++ b/target/hexagon/cpu.c
@@ -340,6 +340,8 @@ static TCGTBCPUState hexagon_get_tb_cpu_state(CPUState *cs)
hex_flags = FIELD_DP32(hex_flags, TB_FLAGS, MMU_INDEX,
cpu_mmu_index(env_cpu(env), false));
hex_flags = FIELD_DP32(hex_flags, TB_FLAGS, PCYCLE_ENABLED, 1);
+ hex_flags = FIELD_DP32(hex_flags, TB_FLAGS, HVX_COPROC_ENABLED,
+ GET_SSR_FIELD(SSR_XE, env->t_sreg[HEX_SREG_SSR]));
#else
hex_flags = FIELD_DP32(hex_flags, TB_FLAGS, MMU_INDEX, MMU_USER_IDX);
#endif
diff --git a/target/hexagon/cpu.h b/target/hexagon/cpu.h
index b1533680bd..97f689fda2 100644
--- a/target/hexagon/cpu.h
+++ b/target/hexagon/cpu.h
@@ -207,6 +207,7 @@ struct ArchCPU {
FIELD(TB_FLAGS, IS_TIGHT_LOOP, 0, 1)
FIELD(TB_FLAGS, MMU_INDEX, 1, 3)
FIELD(TB_FLAGS, PCYCLE_ENABLED, 4, 1)
+FIELD(TB_FLAGS, HVX_COPROC_ENABLED, 5, 1)
G_NORETURN void hexagon_raise_exception_err(CPUHexagonState *env,
uint32_t exception,
diff --git a/target/hexagon/translate.c b/target/hexagon/translate.c
index 8561cec4e4..bf92166e0f 100644
--- a/target/hexagon/translate.c
+++ b/target/hexagon/translate.c
@@ -766,6 +766,14 @@ static void gen_start_packet(DisasContext *ctx)
i = find_next_bit(ctx->predicated_tmp_vregs, NUM_VREGS, i + 1);
}
}
+
+#ifndef CONFIG_USER_ONLY
+ if (ctx->pkt.pkt_has_hvx && !ctx->hvx_coproc_enabled &&
+ !ctx->hvx_check_emitted) {
+ gen_precise_exception(HEX_CAUSE_NO_COPROC_ENABLE, ctx->pkt.pc);
+ ctx->hvx_check_emitted = true;
+ }
+#endif
}
bool is_gather_store_insn(DisasContext *ctx)
@@ -1289,6 +1297,9 @@ static void hexagon_tr_init_disas_context(DisasContextBase *dcbase,
#ifndef CONFIG_USER_ONLY
ctx->num_cycles = 0;
ctx->pcycle_enabled = FIELD_EX32(hex_flags, TB_FLAGS, PCYCLE_ENABLED);
+ ctx->hvx_coproc_enabled =
+ FIELD_EX32(hex_flags, TB_FLAGS, HVX_COPROC_ENABLED);
+ ctx->hvx_check_emitted = false;
#endif
}
diff --git a/target/hexagon/translate.h b/target/hexagon/translate.h
index b90f7fff1c..b33d5dbdbe 100644
--- a/target/hexagon/translate.h
+++ b/target/hexagon/translate.h
@@ -98,6 +98,8 @@ typedef struct DisasContext {
TCGv branch_taken;
TCGv dczero_addr;
bool pcycle_enabled;
+ bool hvx_coproc_enabled;
+ bool hvx_check_emitted;
uint32_t num_cycles;
} DisasContext;