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 <[email protected]>
Signed-off-by: Brian Cain <[email protected]>
---
 target/hexagon/cpu.h       |  1 +
 target/hexagon/translate.h |  2 ++
 target/hexagon/cpu.c       |  2 ++
 target/hexagon/translate.c | 11 +++++++++++
 4 files changed, 16 insertions(+)

diff --git a/target/hexagon/cpu.h b/target/hexagon/cpu.h
index b1533680bd7..97f689fda22 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.h b/target/hexagon/translate.h
index d8628383f1d..b87a2b20e2f 100644
--- a/target/hexagon/translate.h
+++ b/target/hexagon/translate.h
@@ -89,6 +89,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;
 
diff --git a/target/hexagon/cpu.c b/target/hexagon/cpu.c
index fad526ccfb5..19486e0f741 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/translate.c b/target/hexagon/translate.c
index fd1de87405c..0cb3dbe5420 100644
--- a/target/hexagon/translate.c
+++ b/target/hexagon/translate.c
@@ -720,6 +720,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)
@@ -1239,6 +1247,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
 }
 
-- 
2.34.1

Reply via email to