Implement the guest virtual instructions SPSWAP, GETIE, SETIE and RTE.

Signed-off-by: Brian Cain <[email protected]>
---
 target/hexagon/hexswi.h      |  1 +
 target/hexagon/sys_macros.h  | 33 +++++++++++++++++++++++++++------
 target/hexagon/hexswi.c      | 28 ++++++++++++++++++++++++++++
 target/hexagon/hex_common.py |  2 +-
 4 files changed, 57 insertions(+), 7 deletions(-)

diff --git a/target/hexagon/hexswi.h b/target/hexagon/hexswi.h
index 587f790414c..da11bea2b23 100644
--- a/target/hexagon/hexswi.h
+++ b/target/hexagon/hexswi.h
@@ -13,6 +13,7 @@
 void hexagon_cpu_do_interrupt(CPUState *cpu);
 void register_trap_exception(CPUHexagonState *env, int type, int imm,
                              uint32_t PC);
+void hexagon_vmrte(CPUHexagonState *env);
 
 #define HEX_GEVB_HW_ERROR      (HEX_EVENT_PRECISE << 2)
 #define HEX_GEVB_HW_TRAP0      (HEX_EVENT_TRAP0 << 2)
diff --git a/target/hexagon/sys_macros.h b/target/hexagon/sys_macros.h
index b896ee1c81b..270aa0c411f 100644
--- a/target/hexagon/sys_macros.h
+++ b/target/hexagon/sys_macros.h
@@ -79,15 +79,36 @@
 #define fFRAMECHECK(ADDR, EA) gen_framecheck(ctx, ADDR, EA)
 #endif
 
-#define fVIRTINSN_SPSWAP(IMM, REG)
-#define fVIRTINSN_GETIE(IMM, REG) { REG = 0xdeafbeef; }
-#define fVIRTINSN_SETIE(IMM, REG)
-#define fVIRTINSN_RTE(IMM, REG)
+#define fVIRTINSN_SPSWAP(IMM, REG) \
+    do { \
+        if (GET_FIELD(GSR_UM, env->greg[HEX_GREG_GSR])) { \
+            uint32_t tmp = (REG); \
+            (REG) = env->greg[HEX_GREG_GOSP]; \
+            env->greg[HEX_GREG_GOSP] = tmp; \
+        } \
+        env->gpr[HEX_REG_PC] = next_PC; \
+    } while (0)
+#define fVIRTINSN_GETIE(IMM, REG) \
+    do { \
+        (REG) = CCR_FIELD_SET(env, CCR_GIE); \
+        env->gpr[HEX_REG_PC] = next_PC; \
+    } while (0)
+#define fVIRTINSN_SETIE(IMM, REG) \
+    do { \
+        uint32_t old_gie = CCR_FIELD_SET(env, CCR_GIE); \
+        uint32_t new_gie = (REG) & 1; \
+        SET_SYSTEM_FIELD(env, HEX_SREG_CCR, CCR_GIE, new_gie); \
+        (REG) = old_gie; \
+        env->gpr[HEX_REG_PC] = next_PC; \
+    } while (0)
+#define fVIRTINSN_RTE(IMM, REG) hexagon_vmrte(env)
 #define fGRE_ENABLED() \
     GET_FIELD(CCR_GRE, env->t_sreg[HEX_SREG_CCR])
+/* Virtual instructions execute only in guest mode. */
 #define fTRAP1_VIRTINSN(IMM) \
-    (fGRE_ENABLED() && \
-        (((IMM) == 1) || ((IMM) == 3) || ((IMM) == 4) || ((IMM) == 6)))
+    (get_cpu_mode(env) == HEX_CPU_MODE_GUEST && fGRE_ENABLED() && \
+        (((IMM) == 1) || ((IMM) == 3) || ((IMM) == 4) || \
+         ((IMM) == 6)))
 
 /* Not modeled in qemu */
 
diff --git a/target/hexagon/hexswi.c b/target/hexagon/hexswi.c
index 9d94eef96a7..e2d8233701d 100644
--- a/target/hexagon/hexswi.c
+++ b/target/hexagon/hexswi.c
@@ -821,6 +821,34 @@ static void guest_event_entry(CPUHexagonState *env, 
uint32_t cause,
     env->gpr[HEX_REG_PC] = gevb + vec_offset;
 }
 
+void hexagon_vmrte(CPUHexagonState *env)
+{
+    uint32_t gsr = env->greg[HEX_GREG_GSR];
+    uint32_t old_ssr = env->t_sreg[HEX_SREG_SSR];
+    CPUState *cs = env_cpu(env);
+
+    if (GET_FIELD(GSR_UM, gsr)) {
+        uint32_t sp = env->gpr[HEX_REG_SP];
+
+        env->gpr[HEX_REG_SP] = env->greg[HEX_GREG_GOSP];
+        env->greg[HEX_GREG_GOSP] = sp;
+    }
+    SET_SYSTEM_FIELD(env, HEX_SREG_SSR, SSR_SS,
+                     GET_FIELD(GSR_SS, gsr));
+    SET_SYSTEM_FIELD(env, HEX_SREG_SSR, SSR_GM,
+                     !GET_FIELD(GSR_UM, gsr));
+    {
+        BQL_LOCK_GUARD();
+        hexagon_modify_ssr(env, env->t_sreg[HEX_SREG_SSR], old_ssr);
+    }
+    SET_SYSTEM_FIELD(env, HEX_SREG_CCR, CCR_GIE,
+                      GET_FIELD(GSR_IE, gsr));
+    env->cfi_active = GET_FIELD(GSR_CFI, gsr);
+    fSET_FIELD(env->greg[HEX_GREG_GSR], GSR_CFI, 0);
+    env->gpr[HEX_REG_PC] = env->greg[HEX_GREG_GELR] & ~3;
+    cpu_loop_exit(cs);
+}
+
 void hexagon_cpu_do_interrupt(CPUState *cs)
 
 {
diff --git a/target/hexagon/hex_common.py b/target/hexagon/hex_common.py
index 94e70b8657d..0c78b4044ef 100755
--- a/target/hexagon/hex_common.py
+++ b/target/hexagon/hex_common.py
@@ -288,7 +288,7 @@ def need_PC(tag):
 
 
 def need_next_PC(tag):
-    return "A_CALL" in attribdict[tag]
+    return "A_CALL" in attribdict[tag] or tag == "J2_trap1"
 
 
 def need_pkt_has_multi_cof(tag):
-- 
2.34.1

Reply via email to