the CPU can change the privilege level by writing the corresponding bits
in PSW. If this happens all instructions after this 'mtcr' in the TB are
translated with the wrong privilege level. So we have to exit to the
cpu_loop() and start translating again with the new privilege level.

Signed-off-by: Bastian Koppelmann <kbast...@mail.uni-paderborn.de>
---
 target/tricore/op_helper.c | 11 +++++++++++
 target/tricore/translate.c |  2 ++
 2 files changed, 13 insertions(+)

diff --git a/target/tricore/op_helper.c b/target/tricore/op_helper.c
index 026e15f3e0..17b78c501c 100644
--- a/target/tricore/op_helper.c
+++ b/target/tricore/op_helper.c
@@ -2839,7 +2839,18 @@ void helper_rslcx(CPUTriCoreState *env)
 
 void helper_psw_write(CPUTriCoreState *env, uint32_t arg)
 {
+    uint32_t old_priv, new_priv;
+    CPUState *cs;
+
+    old_priv = extract32(env->PSW, 10, 2);
     psw_write(env, arg);
+    new_priv = extract32(env->PSW, 10, 2);
+
+    if (old_priv != new_priv) {
+        cs = env_cpu(env);
+        env->PC = env->PC + 4;
+        cpu_loop_exit(cs);
+    }
 }
 
 uint32_t helper_psw_read(CPUTriCoreState *env)
diff --git a/target/tricore/translate.c b/target/tricore/translate.c
index edbc319fa1..baf13fc205 100644
--- a/target/tricore/translate.c
+++ b/target/tricore/translate.c
@@ -331,6 +331,7 @@ static void gen_swapmsk(DisasContext *ctx, int reg, TCGv ea)
     tcg_gen_mov_tl(cpu_gpr_d[reg], temp);
 }
 
+static inline void gen_save_pc(target_ulong pc);
 
 /* We generate loads and store to core special function register (csfr) through
    the function gen_mfcr and gen_mtcr. To handle access permissions, we use 3
@@ -378,6 +379,7 @@ static inline void gen_mtcr(DisasContext *ctx, TCGv r1,
     if (ctx->priv == TRICORE_PRIV_SM) {
         /* since we're caching PSW make this a special case */
         if (offset == 0xfe04) {
+            gen_save_pc(ctx->base.pc_next);
             gen_helper_psw_write(cpu_env, r1);
         } else {
             switch (offset) {
-- 
2.40.1


Reply via email to