Executing an HMX instruction with SSR:XE2 clear raises a NO_COPROC2_ENABLE
exception.

Log packets one as LOG_UNIMP for now.

Reviewed-by: Marco Liebel <[email protected]>
Signed-off-by: Brian Cain <[email protected]>
---
 target/hexagon/cpu.h                      |  1 +
 target/hexagon/insn.h                     |  1 +
 target/hexagon/translate.h                |  2 ++
 target/hexagon/cpu.c                      |  3 +++
 target/hexagon/decode.c                   |  3 +++
 target/hexagon/translate.c                | 21 +++++++++++++++++++++
 tests/functional/hexagon/test_systests.py |  3 +++
 7 files changed, 34 insertions(+)

diff --git a/target/hexagon/cpu.h b/target/hexagon/cpu.h
index b2931b09329..5739254f1f6 100644
--- a/target/hexagon/cpu.h
+++ b/target/hexagon/cpu.h
@@ -271,6 +271,7 @@ FIELD(TB_FLAGS, MMU_INDEX, 1, 3)
 FIELD(TB_FLAGS, HVX_COPROC_ENABLED, 5, 1)
 FIELD(TB_FLAGS, CPU_MODE, 6, 2)
 FIELD(TB_FLAGS, SS_ACTIVE, 8, 1)
+FIELD(TB_FLAGS, HMX_COPROC_ENABLED, 15, 1)
 
 G_NORETURN void hexagon_raise_exception_err(CPUHexagonState *env,
                                             uint32_t exception,
diff --git a/target/hexagon/insn.h b/target/hexagon/insn.h
index cfd40726692..0dd36d2931d 100644
--- a/target/hexagon/insn.h
+++ b/target/hexagon/insn.h
@@ -71,6 +71,7 @@ struct Packet {
     bool pkt_has_scalar_store_s1;
 
     bool pkt_has_hvx;
+    bool pkt_has_hmx;
     Insn *vhist_insn;
     bool pkt_has_hlx;
 
diff --git a/target/hexagon/translate.h b/target/hexagon/translate.h
index fa7e6272005..bc3b49ab06d 100644
--- a/target/hexagon/translate.h
+++ b/target/hexagon/translate.h
@@ -112,6 +112,8 @@ typedef struct DisasContext {
     DECLARE_BITMAP(lregs_updated, NUM_LREGS);
     DECLARE_BITMAP(lregs_multi_write, NUM_LREGS);
     DECLARE_BITMAP(lregs_updated_tmp, NUM_LREGS);
+    bool hmx_coproc_enabled;
+    bool hmx_check_emitted;
 } DisasContext;
 
 bool is_gather_store_insn(DisasContext *ctx);
diff --git a/target/hexagon/cpu.c b/target/hexagon/cpu.c
index 746aa993220..3575b31d196 100644
--- a/target/hexagon/cpu.c
+++ b/target/hexagon/cpu.c
@@ -396,6 +396,9 @@ static TCGTBCPUState hexagon_get_tb_cpu_state(CPUState *cs)
     hex_flags = FIELD_DP32(hex_flags, TB_FLAGS, SS_ACTIVE,
                            GET_SSR_FIELD(SSR_SS, env->t_sreg[HEX_SREG_SSR]) &&
                            get_cpu_mode(env) != HEX_CPU_MODE_MONITOR);
+    hex_flags = FIELD_DP32(hex_flags, TB_FLAGS, HMX_COPROC_ENABLED,
+                           cpu->hmx &&
+                           GET_SSR_FIELD(SSR_XE2, 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/decode.c b/target/hexagon/decode.c
index 0c3dc67e12c..d48630da87d 100644
--- a/target/hexagon/decode.c
+++ b/target/hexagon/decode.c
@@ -828,11 +828,14 @@ int decode_packet(DisasContext *ctx, int max_words, const 
uint32_t *words,
     pkt->encod_pkt_size_in_bytes = words_read * 4;
     pkt->pkt_has_hvx = false;
     pkt->pkt_has_hlx = false;
+    pkt->pkt_has_hmx = false;
     for (i = 0; i < num_insns; i++) {
         pkt->pkt_has_hvx |=
             GET_ATTRIB(pkt->insn[i].opcode, A_CVI);
         pkt->pkt_has_hlx |=
             GET_ATTRIB(pkt->insn[i].opcode, A_HLX);
+        pkt->pkt_has_hmx |=
+            GET_ATTRIB(pkt->insn[i].opcode, A_HMX);
     }
 
     /*
diff --git a/target/hexagon/translate.c b/target/hexagon/translate.c
index ce0f2152308..015f0958fd0 100644
--- a/target/hexagon/translate.c
+++ b/target/hexagon/translate.c
@@ -919,6 +919,24 @@ static void gen_start_packet(DisasContext *ctx)
         }
     }
 #endif
+
+    if (ctx->pkt.pkt_has_hmx) {
+        for (i = 0; i < ctx->pkt.num_insns; i++) {
+            if (GET_ATTRIB(ctx->pkt.insn[i].opcode, A_HMX)) {
+                qemu_log_mask(LOG_UNIMP, "'%s' is not implemented\n",
+                              opcode_names[ctx->pkt.insn[i].opcode]);
+            }
+        }
+    }
+
+#ifndef CONFIG_USER_ONLY
+    /* HMX needs SSR:XE2 */
+    if (ctx->pkt.pkt_has_hmx && !ctx->hmx_coproc_enabled &&
+        !ctx->hmx_check_emitted) {
+        gen_precise_exception(HEX_CAUSE_NO_COPROC2_ENABLE, ctx->pkt.pc);
+        ctx->hmx_check_emitted = true;
+    }
+#endif
 }
 
 bool is_gather_store_insn(DisasContext *ctx)
@@ -1556,6 +1574,9 @@ static void 
hexagon_tr_init_disas_context(DisasContextBase *dcbase,
         ctx->base.max_insns = 1;
         ctx->is_tight_loop = false;
     }
+    ctx->hmx_coproc_enabled =
+        FIELD_EX32(hex_flags, TB_FLAGS, HMX_COPROC_ENABLED);
+    ctx->hmx_check_emitted = false;
 #endif
 }
 
diff --git a/tests/functional/hexagon/test_systests.py 
b/tests/functional/hexagon/test_systests.py
index fb1d2454fd1..76e2480c1d3 100755
--- a/tests/functional/hexagon/test_systests.py
+++ b/tests/functional/hexagon/test_systests.py
@@ -96,6 +96,9 @@ def test_swi_touch_memory(self):
         """A semihosting read restarts after a fault on its second page."""
         self.run_exit_zero("swi_touch_memory")
 
+    def test_invalid_hmx(self):
+        self.run_exit_zero("invalid_hmx")
+
     def test_dtg_interrupt(self):
         self.run_exit_zero("dtg_interrupt")
 
-- 
2.34.1

Reply via email to