qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [RFC] ppc: rfi and friends
@ 2008-11-29 12:08 Andreas Färber
  2008-11-29 20:04 ` [Qemu-devel] [RFC v2] " Andreas Färber
  0 siblings, 1 reply; 3+ messages in thread
From: Andreas Färber @ 2008-11-29 12:08 UTC (permalink / raw)
  To: qemu-devel; +Cc: Aurélien Jarno

[-- Attachment #1: Type: text/plain, Size: 567 bytes --]

Hello,

This patch migrates op_40x_rfci et al. to TCG. (op_40x_rfci is the  
current dyngen breakage on OSX/gcc4.)

I believe I have spotted and fixed some ops which were lacking env- 
 >spr[...] in their call to __do_rfi.

The TCG code is still untested since it still breaks for op_440_dlmzb.

Two issues remain with my patch: hreg_store_msr and cpu_dump_rfi. Is  
cpu_dump_rfi still needed at all?
hreg_store_msr is defined in helper_regs.h as always_inline - should  
we convert it to an inline TCG function or call it as a helper?

Thanks for any help,

Andreas

[-- Attachment #2: op_40x_rfci.diff --]
[-- Type: application/octet-stream, Size: 9613 bytes --]

diff --git a/target-ppc/op.c b/target-ppc/op.c
index 5d2cfa1..cecb89c 100644
--- a/target-ppc/op.c
+++ b/target-ppc/op.c
@@ -298,26 +298,6 @@ void OPPROTO op_wait (void)
 
 /* Return from interrupt */
 #if !defined(CONFIG_USER_ONLY)
-void OPPROTO op_rfi (void)
-{
-    do_rfi();
-    RETURN();
-}
-
-#if defined(TARGET_PPC64)
-void OPPROTO op_rfid (void)
-{
-    do_rfid();
-    RETURN();
-}
-
-void OPPROTO op_hrfid (void)
-{
-    do_hrfid();
-    RETURN();
-}
-#endif
-
 /* Exception vectors */
 void OPPROTO op_store_excp_prefix (void)
 {
@@ -710,12 +690,6 @@ void OPPROTO op_POWER_rac (void)
     do_POWER_rac();
     RETURN();
 }
-
-void OPPROTO op_POWER_rfsvc (void)
-{
-    do_POWER_rfsvc();
-    RETURN();
-}
 #endif
 
 /* PowerPC 602 specific instruction */
@@ -741,33 +715,6 @@ void OPPROTO op_store_dcr (void)
 }
 
 #if !defined(CONFIG_USER_ONLY)
-/* Return from critical interrupt :
- * same as rfi, except nip & MSR are loaded from SRR2/3 instead of SRR0/1
- */
-void OPPROTO op_40x_rfci (void)
-{
-    do_40x_rfci();
-    RETURN();
-}
-
-void OPPROTO op_rfci (void)
-{
-    do_rfci();
-    RETURN();
-}
-
-void OPPROTO op_rfdi (void)
-{
-    do_rfdi();
-    RETURN();
-}
-
-void OPPROTO op_rfmci (void)
-{
-    do_rfmci();
-    RETURN();
-}
-
 void OPPROTO op_wrte (void)
 {
     /* We don't call do_store_msr here as we won't trigger
diff --git a/target-ppc/op_helper.c b/target-ppc/op_helper.c
index 6addc74..c131cb8 100644
--- a/target-ppc/op_helper.c
+++ b/target-ppc/op_helper.c
@@ -1373,55 +1373,6 @@ void do_store_msr (void)
         raise_exception(env, T0);
     }
 }
-
-static always_inline void __do_rfi (target_ulong nip, target_ulong msr,
-                                    target_ulong msrm, int keep_msrh)
-{
-#if defined(TARGET_PPC64)
-    if (msr & (1ULL << MSR_SF)) {
-        nip = (uint64_t)nip;
-        msr &= (uint64_t)msrm;
-    } else {
-        nip = (uint32_t)nip;
-        msr = (uint32_t)(msr & msrm);
-        if (keep_msrh)
-            msr |= env->msr & ~((uint64_t)0xFFFFFFFF);
-    }
-#else
-    nip = (uint32_t)nip;
-    msr &= (uint32_t)msrm;
-#endif
-    /* XXX: beware: this is false if VLE is supported */
-    env->nip = nip & ~((target_ulong)0x00000003);
-    hreg_store_msr(env, msr, 1);
-#if defined (DEBUG_OP)
-    cpu_dump_rfi(env->nip, env->msr);
-#endif
-    /* No need to raise an exception here,
-     * as rfi is always the last insn of a TB
-     */
-    env->interrupt_request |= CPU_INTERRUPT_EXITTB;
-}
-
-void do_rfi (void)
-{
-    __do_rfi(env->spr[SPR_SRR0], env->spr[SPR_SRR1],
-             ~((target_ulong)0xFFFF0000), 1);
-}
-
-#if defined(TARGET_PPC64)
-void do_rfid (void)
-{
-    __do_rfi(env->spr[SPR_SRR0], env->spr[SPR_SRR1],
-             ~((target_ulong)0xFFFF0000), 0);
-}
-
-void do_hrfid (void)
-{
-    __do_rfi(env->spr[SPR_HSRR0], env->spr[SPR_HSRR1],
-             ~((target_ulong)0xFFFF0000), 0);
-}
-#endif
 #endif
 
 void helper_tw (target_ulong arg1, target_ulong arg2, uint32_t flags)
@@ -1615,11 +1566,6 @@ void do_POWER_rac (void)
     env->nb_BATs = nb_BATs;
 }
 
-void do_POWER_rfsvc (void)
-{
-    __do_rfi(env->lr, env->ctr, 0x0000FFFF, 0);
-}
-
 void do_store_hid0_601 (void)
 {
     uint32_t hid0;
@@ -1715,30 +1661,6 @@ void do_store_dcr (void)
 }
 
 #if !defined(CONFIG_USER_ONLY)
-void do_40x_rfci (void)
-{
-    __do_rfi(env->spr[SPR_40x_SRR2], env->spr[SPR_40x_SRR3],
-             ~((target_ulong)0xFFFF0000), 0);
-}
-
-void do_rfci (void)
-{
-    __do_rfi(env->spr[SPR_BOOKE_CSRR0], SPR_BOOKE_CSRR1,
-             ~((target_ulong)0x3FFF0000), 0);
-}
-
-void do_rfdi (void)
-{
-    __do_rfi(env->spr[SPR_BOOKE_DSRR0], SPR_BOOKE_DSRR1,
-             ~((target_ulong)0x3FFF0000), 0);
-}
-
-void do_rfmci (void)
-{
-    __do_rfi(env->spr[SPR_BOOKE_MCSRR0], SPR_BOOKE_MCSRR1,
-             ~((target_ulong)0x3FFF0000), 0);
-}
-
 void do_load_403_pb (int num)
 {
     T0 = env->pb[num];
diff --git a/target-ppc/op_helper.h b/target-ppc/op_helper.h
index 1c046d8..302a9fe 100644
--- a/target-ppc/op_helper.h
+++ b/target-ppc/op_helper.h
@@ -62,11 +62,6 @@ void ppc_store_dump_spr (int sprn, target_ulong val);
 /* Misc */
 #if !defined(CONFIG_USER_ONLY)
 void do_store_msr (void);
-void do_rfi (void);
-#if defined(TARGET_PPC64)
-void do_rfid (void);
-void do_hrfid (void);
-#endif
 void do_load_6xx_tlb (int is_code);
 void do_load_74xx_tlb (int is_code);
 #endif
@@ -83,7 +78,6 @@ void do_POWER_maskg (void);
 void do_POWER_mulo (void);
 #if !defined(CONFIG_USER_ONLY)
 void do_POWER_rac (void);
-void do_POWER_rfsvc (void);
 void do_store_hid0_601 (void);
 #endif
 
@@ -102,10 +96,6 @@ void do_440_tlbwe (int word);
 void do_load_dcr (void);
 void do_store_dcr (void);
 #if !defined(CONFIG_USER_ONLY)
-void do_40x_rfci (void);
-void do_rfci (void);
-void do_rfdi (void);
-void do_rfmci (void);
 void do_4xx_tlbre_lo (void);
 void do_4xx_tlbre_hi (void);
 void do_4xx_tlbwe_lo (void);
diff --git a/target-ppc/translate.c b/target-ppc/translate.c
index 95cb482..a0a0408 100644
--- a/target-ppc/translate.c
+++ b/target-ppc/translate.c
@@ -68,6 +68,7 @@ static TCGv cpu_lr;
 static TCGv cpu_xer;
 static TCGv_i32 cpu_fpscr;
 static TCGv_i32 cpu_access_type;
+static TCGv_i32 cpu_interrupt_request;
 
 /* dyngen register indexes */
 static TCGv cpu_T[3];
@@ -167,6 +168,9 @@ void ppc_translate_init(void)
     cpu_access_type = tcg_global_mem_new_i32(TCG_AREG0,
                                              offsetof(CPUState, access_type), "access_type");
 
+    cpu_interrupt_request = tcg_global_mem_new_i32(TCG_AREG0,
+                                                   offsetof(CPUState, interrupt_request), "interrupt_request");
+
     /* register helpers */
 #define GEN_HELPER 2
 #include "helper.h"
@@ -277,6 +281,40 @@ static always_inline void gen_update_nip (DisasContext *ctx, target_ulong nip)
         tcg_gen_movi_tl(cpu_nip, (uint32_t)nip);
 }
 
+static always_inline void gen_do_rfi(TCGv nip, TCGv msr, target_ulong msrm, int keep_msrh)
+{
+#if defined(TARGET_PPC64)
+	int endLabel = gen_new_label();
+    TCGv_i64 t0 = tcg_temp_new_i64();
+    tcg_gen_andi_i64(t0, msr, (1ULL << MSR_SF));
+    tcg_gen_andi_i64(msr, msr, msrm);
+	tcg_gen_brcondi_i64(TCG_COND_EQ, t0, 0, endLabel);
+    tcg_temp_free_i64(t0);
+	
+    tcg_gen_andi_i64(nip, nip, 0xFFFFFFFF);
+    tcg_gen_andi_i64(msr, msr, 0xFFFFFFFF);
+    if (keep_msrh) {
+        t0 = tcg_temp_new_i64();
+        tcg_gen_andi_i64(t0, cpu_msr, ~((uint64_t)0xFFFFFFFF);
+        tcg_gen_or_i64(msr, msr, t0);
+		tcg_temp_free_i64(t0);
+    }
+    gen_set_label(endLabel);
+#else
+    tcg_gen_andi_tl(msr, msr, msrm);
+#endif
+    /* XXX: beware: this is false if VLE is supported */
+	tcg_gen_andi_tl(cpu_nip, nip, ~((target_ulong)0x00000003);
+//    hreg_store_msr(env, msr, 1);
+#if defined (DEBUG_OP)
+    /* XXX cpu_dump_rfi(env->nip, env->msr); */
+#endif
+    /* No need to raise an exception here,
+     * as rfi is always the last insn of a TB
+     */
+    tcg_gen_ori_i32(cpu_interrupt_request, cpu_interrupt_request, CPU_INTERRUPT_EXITTB);
+}
+
 #define GEN_EXCP(ctx, excp, error)                                            \
 do {                                                                          \
     TCGv_i32 t0 = tcg_const_i32(excp);                                        \
@@ -3745,7 +3783,8 @@ GEN_HANDLER(rfi, 0x13, 0x12, 0x01, 0x03FF8001, PPC_FLOW)
         GEN_EXCP_PRIVOPC(ctx);
         return;
     }
-    gen_op_rfi();
+    gen_do_rfi(cpu_spr[SPR_SRR0], cpu_spr[SPR_SRR1],
+               ~((target_ulong)0xFFFF0000), 1);
     GEN_SYNC(ctx);
 #endif
 }
@@ -3761,7 +3800,8 @@ GEN_HANDLER(rfid, 0x13, 0x12, 0x00, 0x03FF8001, PPC_64B)
         GEN_EXCP_PRIVOPC(ctx);
         return;
     }
-    gen_op_rfid();
+    gen_do_rfi(cpu_spr[SPR_SRR0], cpu_spr[SPR_SRR1],
+               ~((target_ulong)0xFFFF0000), 0);
     GEN_SYNC(ctx);
 #endif
 }
@@ -3776,7 +3816,8 @@ GEN_HANDLER(hrfid, 0x13, 0x12, 0x08, 0x03FF8001, PPC_64H)
         GEN_EXCP_PRIVOPC(ctx);
         return;
     }
-    gen_op_hrfid();
+    gen_do_rfi(cpu_spr[SPR_HSRR0], cpu_spr[SPR_HSRR1],
+               ~((target_ulong)0xFFFF0000), 0);
     GEN_SYNC(ctx);
 #endif
 }
@@ -5087,7 +5128,7 @@ GEN_HANDLER(rfsvc, 0x13, 0x12, 0x02, 0x03FFF0001, PPC_POWER)
         GEN_EXCP_PRIVOPC(ctx);
         return;
     }
-    gen_op_POWER_rfsvc();
+    gen_do_rfi(cpu_lr, cpu_ctr, 0x0000FFFF, 0);
     GEN_SYNC(ctx);
 #endif
 }
@@ -5631,7 +5672,8 @@ GEN_HANDLER2(rfci_40x, "rfci", 0x13, 0x13, 0x01, 0x03FF8001, PPC_40x_EXCP)
         return;
     }
     /* Restore CPU state */
-    gen_op_40x_rfci();
+    gen_do_rfi(cpu_spr[SPR_40x_SRR2], cpu_spr[SPR_40x_SRR3],
+               ~((target_ulong)0xFFFF0000), 0);
     GEN_SYNC(ctx);
 #endif
 }
@@ -5646,7 +5688,8 @@ GEN_HANDLER(rfci, 0x13, 0x13, 0x01, 0x03FF8001, PPC_BOOKE)
         return;
     }
     /* Restore CPU state */
-    gen_op_rfci();
+    gen_do_rfi(cpu_spr[SPR_BOOKE_CSRR0], cpu_spr[SPR_BOOKE_CSRR1]
+               ~((target_ulong)0x3FFF0000), 0);
     GEN_SYNC(ctx);
 #endif
 }
@@ -5663,7 +5706,8 @@ GEN_HANDLER(rfdi, 0x13, 0x07, 0x01, 0x03FF8001, PPC_RFDI)
         return;
     }
     /* Restore CPU state */
-    gen_op_rfdi();
+    gen_do_rfi(cpu_spr[SPR_BOOKE_DSRR0], cpu_spr[SPR_BOOKE_DSRR1],
+               ~((target_ulong)0x3FFF0000), 0);
     GEN_SYNC(ctx);
 #endif
 }
@@ -5679,7 +5723,8 @@ GEN_HANDLER(rfmci, 0x13, 0x06, 0x01, 0x03FF8001, PPC_RFMCI)
         return;
     }
     /* Restore CPU state */
-    gen_op_rfmci();
+    gen_do_rfi(cpu_spr[SPR_BOOKE_MCSRR0], cpu_spr[SPR_BOOKE_MCSRR1],
+               ~((target_ulong)0x3FFF0000), 0);
     GEN_SYNC(ctx);
 #endif
 }

[-- Attachment #3: Type: text/plain, Size: 1 bytes --]



^ permalink raw reply related	[flat|nested] 3+ messages in thread

* [Qemu-devel] [RFC v2] ppc: rfi and friends
  2008-11-29 12:08 [Qemu-devel] [RFC] ppc: rfi and friends Andreas Färber
@ 2008-11-29 20:04 ` Andreas Färber
  2008-11-30 16:30   ` Aurélien Jarno
  0 siblings, 1 reply; 3+ messages in thread
From: Andreas Färber @ 2008-11-29 20:04 UTC (permalink / raw)
  To: qemu-devel; +Cc: Aurélien Jarno

[-- Attachment #1: Type: text/plain, Size: 17833 bytes --]


Am 29.11.2008 um 13:08 schrieb Andreas Färber:

> This patch migrates op_40x_rfci et al. to TCG. (op_40x_rfci is the  
> current dyngen breakage on OSX/gcc4.)
>
> I believe I have spotted and fixed some ops which were lacking env- 
> >spr[...] in their call to __do_rfi.
>
> The TCG code is still untested since it still breaks for op_440_dlmzb.
>
> Two issues remain with my patch: hreg_store_msr and cpu_dump_rfi. Is  
> cpu_dump_rfi still needed at all?
> hreg_store_msr is defined in helper_regs.h as always_inline - should  
> we convert it to an inline TCG function or call it as a helper?

Attached is a compile-tested update of the patch, that adds TCG  
versions of hreg_store_msr and dependencies.

Still unclear to me is what to do about a tlb_flush call, and an env- 
 >check_pow callback there.

Signed-off-by: Andreas Faerber <andreas.faerber@web.de>

Andreas

---
diff --git a/target-ppc/op.c b/target-ppc/op.c
index a26b1da..d00ebe8 100644
--- a/target-ppc/op.c
+++ b/target-ppc/op.c
@@ -298,26 +298,6 @@ void OPPROTO op_wait (void)

  /* Return from interrupt */
  #if !defined(CONFIG_USER_ONLY)
-void OPPROTO op_rfi (void)
-{
-    do_rfi();
-    RETURN();
-}
-
-#if defined(TARGET_PPC64)
-void OPPROTO op_rfid (void)
-{
-    do_rfid();
-    RETURN();
-}
-
-void OPPROTO op_hrfid (void)
-{
-    do_hrfid();
-    RETURN();
-}
-#endif
-
  /* Exception vectors */
  void OPPROTO op_store_excp_prefix (void)
  {
@@ -710,12 +690,6 @@ void OPPROTO op_POWER_rac (void)
      do_POWER_rac();
      RETURN();
  }
-
-void OPPROTO op_POWER_rfsvc (void)
-{
-    do_POWER_rfsvc();
-    RETURN();
-}
  #endif

  /* PowerPC 602 specific instruction */
@@ -741,33 +715,6 @@ void OPPROTO op_store_dcr (void)
  }

  #if !defined(CONFIG_USER_ONLY)
-/* Return from critical interrupt :
- * same as rfi, except nip & MSR are loaded from SRR2/3 instead of  
SRR0/1
- */
-void OPPROTO op_40x_rfci (void)
-{
-    do_40x_rfci();
-    RETURN();
-}
-
-void OPPROTO op_rfci (void)
-{
-    do_rfci();
-    RETURN();
-}
-
-void OPPROTO op_rfdi (void)
-{
-    do_rfdi();
-    RETURN();
-}
-
-void OPPROTO op_rfmci (void)
-{
-    do_rfmci();
-    RETURN();
-}
-
  void OPPROTO op_wrte (void)
  {
      /* We don't call do_store_msr here as we won't trigger
diff --git a/target-ppc/op_helper.c b/target-ppc/op_helper.c
index a055ee6..e158630 100644
--- a/target-ppc/op_helper.c
+++ b/target-ppc/op_helper.c
@@ -1373,55 +1373,6 @@ void do_store_msr (void)
          raise_exception(env, T0);
      }
  }
-
-static always_inline void __do_rfi (target_ulong nip, target_ulong msr,
-                                    target_ulong msrm, int keep_msrh)
-{
-#if defined(TARGET_PPC64)
-    if (msr & (1ULL << MSR_SF)) {
-        nip = (uint64_t)nip;
-        msr &= (uint64_t)msrm;
-    } else {
-        nip = (uint32_t)nip;
-        msr = (uint32_t)(msr & msrm);
-        if (keep_msrh)
-            msr |= env->msr & ~((uint64_t)0xFFFFFFFF);
-    }
-#else
-    nip = (uint32_t)nip;
-    msr &= (uint32_t)msrm;
-#endif
-    /* XXX: beware: this is false if VLE is supported */
-    env->nip = nip & ~((target_ulong)0x00000003);
-    hreg_store_msr(env, msr, 1);
-#if defined (DEBUG_OP)
-    cpu_dump_rfi(env->nip, env->msr);
-#endif
-    /* No need to raise an exception here,
-     * as rfi is always the last insn of a TB
-     */
-    env->interrupt_request |= CPU_INTERRUPT_EXITTB;
-}
-
-void do_rfi (void)
-{
-    __do_rfi(env->spr[SPR_SRR0], env->spr[SPR_SRR1],
-             ~((target_ulong)0xFFFF0000), 1);
-}
-
-#if defined(TARGET_PPC64)
-void do_rfid (void)
-{
-    __do_rfi(env->spr[SPR_SRR0], env->spr[SPR_SRR1],
-             ~((target_ulong)0xFFFF0000), 0);
-}
-
-void do_hrfid (void)
-{
-    __do_rfi(env->spr[SPR_HSRR0], env->spr[SPR_HSRR1],
-             ~((target_ulong)0xFFFF0000), 0);
-}
-#endif
  #endif

  void helper_tw (target_ulong arg1, target_ulong arg2, uint32_t flags)
@@ -1615,11 +1566,6 @@ void do_POWER_rac (void)
      env->nb_BATs = nb_BATs;
  }

-void do_POWER_rfsvc (void)
-{
-    __do_rfi(env->lr, env->ctr, 0x0000FFFF, 0);
-}
-
  void do_store_hid0_601 (void)
  {
      uint32_t hid0;
@@ -1715,30 +1661,6 @@ void do_store_dcr (void)
  }

  #if !defined(CONFIG_USER_ONLY)
-void do_40x_rfci (void)
-{
-    __do_rfi(env->spr[SPR_40x_SRR2], env->spr[SPR_40x_SRR3],
-             ~((target_ulong)0xFFFF0000), 0);
-}
-
-void do_rfci (void)
-{
-    __do_rfi(env->spr[SPR_BOOKE_CSRR0], SPR_BOOKE_CSRR1,
-             ~((target_ulong)0x3FFF0000), 0);
-}
-
-void do_rfdi (void)
-{
-    __do_rfi(env->spr[SPR_BOOKE_DSRR0], SPR_BOOKE_DSRR1,
-             ~((target_ulong)0x3FFF0000), 0);
-}
-
-void do_rfmci (void)
-{
-    __do_rfi(env->spr[SPR_BOOKE_MCSRR0], SPR_BOOKE_MCSRR1,
-             ~((target_ulong)0x3FFF0000), 0);
-}
-
  void do_load_403_pb (int num)
  {
      T0 = env->pb[num];
diff --git a/target-ppc/op_helper.h b/target-ppc/op_helper.h
index aaaba5c..db458b7 100644
--- a/target-ppc/op_helper.h
+++ b/target-ppc/op_helper.h
@@ -62,11 +62,6 @@ void ppc_store_dump_spr (int sprn, target_ulong val);
  /* Misc */
  #if !defined(CONFIG_USER_ONLY)
  void do_store_msr (void);
-void do_rfi (void);
-#if defined(TARGET_PPC64)
-void do_rfid (void);
-void do_hrfid (void);
-#endif
  void do_load_6xx_tlb (int is_code);
  void do_load_74xx_tlb (int is_code);
  #endif
@@ -83,7 +78,6 @@ void do_POWER_maskg (void);
  void do_POWER_mulo (void);
  #if !defined(CONFIG_USER_ONLY)
  void do_POWER_rac (void);
-void do_POWER_rfsvc (void);
  void do_store_hid0_601 (void);
  #endif

@@ -102,10 +96,6 @@ void do_440_tlbwe (int word);
  void do_load_dcr (void);
  void do_store_dcr (void);
  #if !defined(CONFIG_USER_ONLY)
-void do_40x_rfci (void);
-void do_rfci (void);
-void do_rfdi (void);
-void do_rfmci (void);
  void do_4xx_tlbre_lo (void);
  void do_4xx_tlbre_hi (void);
  void do_4xx_tlbwe_lo (void);
diff --git a/target-ppc/translate.c b/target-ppc/translate.c
index 59533ac..c5c7eb6 100644
--- a/target-ppc/translate.c
+++ b/target-ppc/translate.c
@@ -52,13 +52,16 @@ static char cpu_reg_names[10*3 + 22*4 /* GPR */
  #if !defined(TARGET_PPC64)
      + 10*4 + 22*5 /* SPE GPRh */
  #endif
+    + 4*6 /* tGPR */
      + 10*4 + 22*5 /* FPR */
      + 2*(10*6 + 22*7) /* AVRh, AVRl */
-    + 8*5 /* CRF */];
+    + 8*5 /* CRF */
+    + 1024*8 /* SPR */];
  static TCGv cpu_gpr[32];
  #if !defined(TARGET_PPC64)
  static TCGv cpu_gprh[32];
  #endif
+static TCGv cpu_tgpr[4];
  static TCGv_i64 cpu_fpr[32];
  static TCGv_i64 cpu_avrh[32], cpu_avrl[32];
  static TCGv_i32 cpu_crf[8];
@@ -66,8 +69,17 @@ static TCGv cpu_nip;
  static TCGv cpu_ctr;
  static TCGv cpu_lr;
  static TCGv cpu_xer;
+static TCGv cpu_msr, cpu_msr_mask;
  static TCGv_i32 cpu_fpscr;
+static TCGv cpu_spr[1024];
  static TCGv_i32 cpu_access_type;
+static TCGv_i32 cpu_interrupt_request;
+static TCGv_i32 cpu_flags;
+#if !defined(CONFIG_USER_ONLY)
+static TCGv cpu_excp_prefix;
+#endif
+static TCGv cpu_hflags, cpu_hflags_nmsr;
+static TCGv cpu_mmu_idx;

  /* dyngen register indexes */
  static TCGv cpu_T[3];
@@ -149,6 +161,13 @@ void ppc_translate_init(void)
          p += (i < 10) ? 6 : 7;
      }

+    for (i = 0; i < 4; i++) {
+        sprintf(p, "tgpr%d", i);
+        cpu_tgpr[i] = tcg_global_mem_new(TCG_AREG0,
+                                         offsetof(CPUState, tgpr[i]),  
p);
+        p += 6;
+    }
+
      cpu_nip = tcg_global_mem_new(TCG_AREG0,
                                   offsetof(CPUState, nip), "nip");

@@ -161,12 +180,44 @@ void ppc_translate_init(void)
      cpu_xer = tcg_global_mem_new(TCG_AREG0,
                                   offsetof(CPUState, xer), "xer");

+    cpu_msr = tcg_global_mem_new(TCG_AREG0,
+                                 offsetof(CPUState, msr), "msr");
+    cpu_msr_mask = tcg_global_mem_new(TCG_AREG0,
+                                      offsetof(CPUState, msr_mask),  
"msr_mask");
+
      cpu_fpscr = tcg_global_mem_new_i32(TCG_AREG0,
                                         offsetof(CPUState, fpscr),  
"fpscr");

+    for (i = 0; i < 1024; i++) {
+        sprintf(p, "SPR%d", i);
+        cpu_spr[i] = tcg_global_mem_new(TCG_AREG0,
+                                        offsetof(CPUState, spr[i]), p);
+        p += 8;
+    }
+
      cpu_access_type = tcg_global_mem_new_i32(TCG_AREG0,
                                               offsetof(CPUState,  
access_type), "access_type");

+    cpu_interrupt_request = tcg_global_mem_new_i32(TCG_AREG0,
+                                                   offsetof(CPUState,  
interrupt_request), "interrupt_request");
+
+    cpu_flags = tcg_global_mem_new_i32(TCG_AREG0,
+                                       offsetof(CPUState, flags),  
"flags");
+
+    cpu_hflags = tcg_global_mem_new(TCG_AREG0,
+                                    offsetof(CPUState, hflags),  
"hflags");
+
+    cpu_hflags_nmsr = tcg_global_mem_new(TCG_AREG0,
+                                         offsetof(CPUState,  
hflags_nmsr), "hflags_nmsr");
+
+    cpu_mmu_idx = tcg_global_mem_new(TCG_AREG0,
+                                     offsetof(CPUState, mmu_idx),  
"mmu_idx");
+
+#if !defined(CONFIG_USER_ONLY)
+    cpu_excp_prefix = tcg_global_mem_new(TCG_AREG0,
+                                         offsetof(CPUState,  
excp_prefix), "excp_prefix");
+#endif
+
      /* register helpers */
  #define GEN_HELPER 2
  #include "helper.h"
@@ -277,6 +328,165 @@ static always_inline void gen_update_nip  
(DisasContext *ctx, target_ulong nip)
          tcg_gen_movi_tl(cpu_nip, (uint32_t)nip);
  }

+static always_inline void gen_get_msr_bit(TCGv dest, TCGv src, int bit)
+{
+    tcg_gen_shri_tl(dest, src, bit);
+    tcg_gen_andi_tl(dest, dest, 1);
+}
+
+static always_inline void gen_hreg_swap_gpr_tgpr()
+{
+    int i;
+    TCGv t0 = tcg_temp_new();
+    for (i = 0; i < 4; i++) {
+        tcg_gen_mov_tl(t0, cpu_gpr[i]);
+        tcg_gen_mov_tl(cpu_gpr[i], cpu_tgpr[i]);
+        tcg_gen_mov_tl(cpu_tgpr[i], t0);
+    }
+    tcg_temp_free(t0);
+}
+
+static always_inline void gen_hreg_compute_mem_idx()
+{
+    /* Precompute MMU index */
+    TCGv t0 = tcg_temp_new();
+    gen_get_msr_bit(t0, cpu_msr, MSR_PR);
+    int elseLabel = gen_new_label();
+    tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, elseLabel);
+
+    int endLabel = gen_new_label();
+#if defined(TARGET_PPC64)
+    gen_get_msr_bit(t0, cpu_msr, MSR_SHV);
+#elif defined(PPC_EMULATE_32BITS_HYPV)
+    gen_get_msr_bit(t0, cpu_msr, MSR_THV);
+#else
+    tcg_gen_movi_tl(t0, 0);
+#endif
+    tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, endLabel);
+
+    tcg_gen_movi_tl(cpu_mmu_idx, 2);
+
+    gen_set_label(elseLabel);
+    TCGv t1 = tcg_const_tl(1);
+    gen_get_msr_bit(t0, cpu_msr, MSR_PR);
+    tcg_gen_sub_tl(cpu_mmu_idx, t1, t0);
+    tcg_gen_br(endLabel);
+    tcg_temp_free(t1);
+
+    gen_set_label(endLabel);
+    tcg_temp_free(t0);
+}
+
+static always_inline void gen_hreg_compute_hflags()
+{
+    target_ulong hflags_mask;
+    hflags_mask = (1 << MSR_VR) | (1 << MSR_AP) | (1 << MSR_SA) |
+        (1 << MSR_PR) | (1 << MSR_FP) | (1 << MSR_SE) | (1 << MSR_BE) |
+        (1 << MSR_LE);
+    hflags_mask |= (1ULL << MSR_CM) | (1ULL << MSR_SF) | MSR_HVB;
+    gen_hreg_compute_mem_idx();
+    tcg_gen_andi_tl(cpu_hflags, cpu_msr, hflags_mask);
+    /* Merge with hflags coming from other registers */
+    tcg_gen_or_tl(cpu_hflags, cpu_hflags, cpu_hflags_nmsr);
+}
+
+static always_inline void gen_hreg_store_msr(TCGv msr, int alter_hv)
+{
+    TCGv t0 = tcg_temp_new();
+    tcg_gen_and_tl(t0, msr, cpu_msr_mask);
+#if !defined(CONFIG_USER_ONLY)
+    if (!alter_hv) {
+        /* mtmsr cannot alter the hypervisor state */
+        tcg_gen_andi_tl(t0, t0, (target_ulong)~MSR_HVB);
+        TCGv t1 = tcg_temp_new();
+        tcg_gen_andi_tl(t1, cpu_msr, MSR_HVB);
+        tcg_gen_or_tl(t0, t0, t1);
+        tcg_temp_free(t1);
+    }
+
+    TCGv t1 = tcg_temp_new();
+    TCGv t2 = tcg_temp_new();
+    gen_get_msr_bit(t1, t0,      MSR_IR);
+    gen_get_msr_bit(t2, cpu_msr, MSR_IR);
+    int labelInner = gen_new_label();
+    tcg_gen_brcond_tl(TCG_COND_NE, t1, t2, labelInner);
+
+    gen_get_msr_bit(t1, t0,      MSR_DR);
+    gen_get_msr_bit(t2, cpu_msr, MSR_DR);
+    int labelEnd = gen_new_label();
+    tcg_gen_brcond_tl(TCG_COND_EQ, t1, t2, labelEnd);
+
+    gen_set_label(labelInner);
+    /* Flush all tlb when changing translation mode */
+//TODO tlb_flush(env, 1)
+    tcg_gen_ori_i32(cpu_interrupt_request, cpu_interrupt_request,  
CPU_INTERRUPT_EXITTB);
+
+    gen_set_label(labelEnd);
+    labelEnd = gen_new_label();
+    TCGv_i32 t3 = tcg_temp_new_i32();
+    tcg_gen_andi_i32(t3, cpu_flags, POWERPC_FLAG_TGPR);
+    tcg_gen_brcondi_i32(TCG_COND_EQ, t3, 0, labelEnd);
+    tcg_temp_free_i32(t3);
+
+    tcg_gen_xor_tl(t1, t0, cpu_msr);
+    tcg_gen_andi_tl(t1, t1, (1 << MSR_TGPR));
+    tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, labelEnd);
+    gen_hreg_swap_gpr_tgpr();
+
+    gen_set_label(labelEnd);
+    labelEnd = gen_new_label();
+    gen_get_msr_bit(t1, t0,      MSR_EP);
+    gen_get_msr_bit(t2, cpu_msr, MSR_EP);
+    tcg_gen_brcond_tl(TCG_COND_EQ, t1, t2, labelEnd);
+    /* Change the exception prefix on PowerPC 601 */
+    tcg_gen_muli_tl(cpu_excp_prefix, t1, 0xFFF00000);
+
+    gen_set_label(labelEnd);
+    tcg_temp_free(t1);
+    tcg_temp_free(t2);
+#endif
+    tcg_gen_mov_tl(cpu_msr, t0);
+    gen_hreg_compute_hflags();
+#if !defined(CONFIG_USER_ONLY)
+//XXX
+#endif
+    tcg_temp_free(t0);
+}
+
+static always_inline void gen_do_rfi(TCGv nip, TCGv msr, target_ulong  
msrm, int keep_msrh)
+{
+#if defined(TARGET_PPC64)
+    int endLabel = gen_new_label();
+    TCGv_i64 t0 = tcg_temp_new_i64();
+    tcg_gen_andi_i64(t0, msr, (1ULL << MSR_SF));
+    tcg_gen_andi_i64(msr, msr, msrm);
+    tcg_gen_brcondi_i64(TCG_COND_EQ, t0, 0, endLabel);
+    tcg_temp_free_i64(t0);
+
+    tcg_gen_andi_i64(nip, nip, 0xFFFFFFFF);
+    tcg_gen_andi_i64(msr, msr, 0xFFFFFFFF);
+    if (keep_msrh) {
+        t0 = tcg_temp_new_i64();
+        tcg_gen_andi_i64(t0, cpu_msr, ~((uint64_t)0xFFFFFFFF));
+        tcg_gen_or_i64(msr, msr, t0);
+        tcg_temp_free_i64(t0);
+    }
+    gen_set_label(endLabel);
+#else
+    tcg_gen_andi_tl(msr, msr, msrm);
+#endif
+    /* XXX: beware: this is false if VLE is supported */
+    tcg_gen_andi_tl(cpu_nip, nip, ~((target_ulong)0x00000003));
+    gen_hreg_store_msr(msr, 1);
+#if defined (DEBUG_OP)
+//XXX cpu_dump_rfi(env->nip, env->msr);
+#endif
+    /* No need to raise an exception here,
+     * as rfi is always the last insn of a TB
+     */
+    tcg_gen_ori_i32(cpu_interrupt_request, cpu_interrupt_request,  
CPU_INTERRUPT_EXITTB);
+}
+
  #define GEN_EXCP(ctx, excp,  
error)                                            \
  do  
{                                                                          \
      TCGv_i32 t0 =  
tcg_const_i32(excp);                                        \
@@ -3745,7 +3955,8 @@ GEN_HANDLER(rfi, 0x13, 0x12, 0x01, 0x03FF8001,  
PPC_FLOW)
          GEN_EXCP_PRIVOPC(ctx);
          return;
      }
-    gen_op_rfi();
+    gen_do_rfi(cpu_spr[SPR_SRR0], cpu_spr[SPR_SRR1],
+               ~((target_ulong)0xFFFF0000), 1);
      GEN_SYNC(ctx);
  #endif
  }
@@ -3761,7 +3972,8 @@ GEN_HANDLER(rfid, 0x13, 0x12, 0x00, 0x03FF8001,  
PPC_64B)
          GEN_EXCP_PRIVOPC(ctx);
          return;
      }
-    gen_op_rfid();
+    gen_do_rfi(cpu_spr[SPR_SRR0], cpu_spr[SPR_SRR1],
+               ~((target_ulong)0xFFFF0000), 0);
      GEN_SYNC(ctx);
  #endif
  }
@@ -3776,7 +3988,8 @@ GEN_HANDLER(hrfid, 0x13, 0x12, 0x08, 0x03FF8001,  
PPC_64H)
          GEN_EXCP_PRIVOPC(ctx);
          return;
      }
-    gen_op_hrfid();
+    gen_do_rfi(cpu_spr[SPR_HSRR0], cpu_spr[SPR_HSRR1],
+               ~((target_ulong)0xFFFF0000), 0);
      GEN_SYNC(ctx);
  #endif
  }
@@ -5087,7 +5300,7 @@ GEN_HANDLER(rfsvc, 0x13, 0x12, 0x02,  
0x03FFF0001, PPC_POWER)
          GEN_EXCP_PRIVOPC(ctx);
          return;
      }
-    gen_op_POWER_rfsvc();
+    gen_do_rfi(cpu_lr, cpu_ctr, 0x0000FFFF, 0);
      GEN_SYNC(ctx);
  #endif
  }
@@ -5631,7 +5844,8 @@ GEN_HANDLER2(rfci_40x, "rfci", 0x13, 0x13, 0x01,  
0x03FF8001, PPC_40x_EXCP)
          return;
      }
      /* Restore CPU state */
-    gen_op_40x_rfci();
+    gen_do_rfi(cpu_spr[SPR_40x_SRR2], cpu_spr[SPR_40x_SRR3],
+               ~((target_ulong)0xFFFF0000), 0);
      GEN_SYNC(ctx);
  #endif
  }
@@ -5646,7 +5860,8 @@ GEN_HANDLER(rfci, 0x13, 0x13, 0x01, 0x03FF8001,  
PPC_BOOKE)
          return;
      }
      /* Restore CPU state */
-    gen_op_rfci();
+    gen_do_rfi(cpu_spr[SPR_BOOKE_CSRR0], cpu_spr[SPR_BOOKE_CSRR1],
+               ~((target_ulong)0x3FFF0000), 0);
      GEN_SYNC(ctx);
  #endif
  }
@@ -5663,7 +5878,8 @@ GEN_HANDLER(rfdi, 0x13, 0x07, 0x01, 0x03FF8001,  
PPC_RFDI)
          return;
      }
      /* Restore CPU state */
-    gen_op_rfdi();
+    gen_do_rfi(cpu_spr[SPR_BOOKE_DSRR0], cpu_spr[SPR_BOOKE_DSRR1],
+               ~((target_ulong)0x3FFF0000), 0);
      GEN_SYNC(ctx);
  #endif
  }
@@ -5679,7 +5895,8 @@ GEN_HANDLER(rfmci, 0x13, 0x06, 0x01, 0x03FF8001,  
PPC_RFMCI)
          return;
      }
      /* Restore CPU state */
-    gen_op_rfmci();
+    gen_do_rfi(cpu_spr[SPR_BOOKE_MCSRR0], cpu_spr[SPR_BOOKE_MCSRR1],
+               ~((target_ulong)0x3FFF0000), 0);
      GEN_SYNC(ctx);
  #endif
  }



[-- Attachment #2: op_40x_rfci_2.diff --]
[-- Type: application/octet-stream, Size: 16170 bytes --]

diff --git a/target-ppc/op.c b/target-ppc/op.c
index a26b1da..d00ebe8 100644
--- a/target-ppc/op.c
+++ b/target-ppc/op.c
@@ -298,26 +298,6 @@ void OPPROTO op_wait (void)
 
 /* Return from interrupt */
 #if !defined(CONFIG_USER_ONLY)
-void OPPROTO op_rfi (void)
-{
-    do_rfi();
-    RETURN();
-}
-
-#if defined(TARGET_PPC64)
-void OPPROTO op_rfid (void)
-{
-    do_rfid();
-    RETURN();
-}
-
-void OPPROTO op_hrfid (void)
-{
-    do_hrfid();
-    RETURN();
-}
-#endif
-
 /* Exception vectors */
 void OPPROTO op_store_excp_prefix (void)
 {
@@ -710,12 +690,6 @@ void OPPROTO op_POWER_rac (void)
     do_POWER_rac();
     RETURN();
 }
-
-void OPPROTO op_POWER_rfsvc (void)
-{
-    do_POWER_rfsvc();
-    RETURN();
-}
 #endif
 
 /* PowerPC 602 specific instruction */
@@ -741,33 +715,6 @@ void OPPROTO op_store_dcr (void)
 }
 
 #if !defined(CONFIG_USER_ONLY)
-/* Return from critical interrupt :
- * same as rfi, except nip & MSR are loaded from SRR2/3 instead of SRR0/1
- */
-void OPPROTO op_40x_rfci (void)
-{
-    do_40x_rfci();
-    RETURN();
-}
-
-void OPPROTO op_rfci (void)
-{
-    do_rfci();
-    RETURN();
-}
-
-void OPPROTO op_rfdi (void)
-{
-    do_rfdi();
-    RETURN();
-}
-
-void OPPROTO op_rfmci (void)
-{
-    do_rfmci();
-    RETURN();
-}
-
 void OPPROTO op_wrte (void)
 {
     /* We don't call do_store_msr here as we won't trigger
diff --git a/target-ppc/op_helper.c b/target-ppc/op_helper.c
index a055ee6..e158630 100644
--- a/target-ppc/op_helper.c
+++ b/target-ppc/op_helper.c
@@ -1373,55 +1373,6 @@ void do_store_msr (void)
         raise_exception(env, T0);
     }
 }
-
-static always_inline void __do_rfi (target_ulong nip, target_ulong msr,
-                                    target_ulong msrm, int keep_msrh)
-{
-#if defined(TARGET_PPC64)
-    if (msr & (1ULL << MSR_SF)) {
-        nip = (uint64_t)nip;
-        msr &= (uint64_t)msrm;
-    } else {
-        nip = (uint32_t)nip;
-        msr = (uint32_t)(msr & msrm);
-        if (keep_msrh)
-            msr |= env->msr & ~((uint64_t)0xFFFFFFFF);
-    }
-#else
-    nip = (uint32_t)nip;
-    msr &= (uint32_t)msrm;
-#endif
-    /* XXX: beware: this is false if VLE is supported */
-    env->nip = nip & ~((target_ulong)0x00000003);
-    hreg_store_msr(env, msr, 1);
-#if defined (DEBUG_OP)
-    cpu_dump_rfi(env->nip, env->msr);
-#endif
-    /* No need to raise an exception here,
-     * as rfi is always the last insn of a TB
-     */
-    env->interrupt_request |= CPU_INTERRUPT_EXITTB;
-}
-
-void do_rfi (void)
-{
-    __do_rfi(env->spr[SPR_SRR0], env->spr[SPR_SRR1],
-             ~((target_ulong)0xFFFF0000), 1);
-}
-
-#if defined(TARGET_PPC64)
-void do_rfid (void)
-{
-    __do_rfi(env->spr[SPR_SRR0], env->spr[SPR_SRR1],
-             ~((target_ulong)0xFFFF0000), 0);
-}
-
-void do_hrfid (void)
-{
-    __do_rfi(env->spr[SPR_HSRR0], env->spr[SPR_HSRR1],
-             ~((target_ulong)0xFFFF0000), 0);
-}
-#endif
 #endif
 
 void helper_tw (target_ulong arg1, target_ulong arg2, uint32_t flags)
@@ -1615,11 +1566,6 @@ void do_POWER_rac (void)
     env->nb_BATs = nb_BATs;
 }
 
-void do_POWER_rfsvc (void)
-{
-    __do_rfi(env->lr, env->ctr, 0x0000FFFF, 0);
-}
-
 void do_store_hid0_601 (void)
 {
     uint32_t hid0;
@@ -1715,30 +1661,6 @@ void do_store_dcr (void)
 }
 
 #if !defined(CONFIG_USER_ONLY)
-void do_40x_rfci (void)
-{
-    __do_rfi(env->spr[SPR_40x_SRR2], env->spr[SPR_40x_SRR3],
-             ~((target_ulong)0xFFFF0000), 0);
-}
-
-void do_rfci (void)
-{
-    __do_rfi(env->spr[SPR_BOOKE_CSRR0], SPR_BOOKE_CSRR1,
-             ~((target_ulong)0x3FFF0000), 0);
-}
-
-void do_rfdi (void)
-{
-    __do_rfi(env->spr[SPR_BOOKE_DSRR0], SPR_BOOKE_DSRR1,
-             ~((target_ulong)0x3FFF0000), 0);
-}
-
-void do_rfmci (void)
-{
-    __do_rfi(env->spr[SPR_BOOKE_MCSRR0], SPR_BOOKE_MCSRR1,
-             ~((target_ulong)0x3FFF0000), 0);
-}
-
 void do_load_403_pb (int num)
 {
     T0 = env->pb[num];
diff --git a/target-ppc/op_helper.h b/target-ppc/op_helper.h
index aaaba5c..db458b7 100644
--- a/target-ppc/op_helper.h
+++ b/target-ppc/op_helper.h
@@ -62,11 +62,6 @@ void ppc_store_dump_spr (int sprn, target_ulong val);
 /* Misc */
 #if !defined(CONFIG_USER_ONLY)
 void do_store_msr (void);
-void do_rfi (void);
-#if defined(TARGET_PPC64)
-void do_rfid (void);
-void do_hrfid (void);
-#endif
 void do_load_6xx_tlb (int is_code);
 void do_load_74xx_tlb (int is_code);
 #endif
@@ -83,7 +78,6 @@ void do_POWER_maskg (void);
 void do_POWER_mulo (void);
 #if !defined(CONFIG_USER_ONLY)
 void do_POWER_rac (void);
-void do_POWER_rfsvc (void);
 void do_store_hid0_601 (void);
 #endif
 
@@ -102,10 +96,6 @@ void do_440_tlbwe (int word);
 void do_load_dcr (void);
 void do_store_dcr (void);
 #if !defined(CONFIG_USER_ONLY)
-void do_40x_rfci (void);
-void do_rfci (void);
-void do_rfdi (void);
-void do_rfmci (void);
 void do_4xx_tlbre_lo (void);
 void do_4xx_tlbre_hi (void);
 void do_4xx_tlbwe_lo (void);
diff --git a/target-ppc/translate.c b/target-ppc/translate.c
index 59533ac..c5c7eb6 100644
--- a/target-ppc/translate.c
+++ b/target-ppc/translate.c
@@ -52,13 +52,16 @@ static char cpu_reg_names[10*3 + 22*4 /* GPR */
 #if !defined(TARGET_PPC64)
     + 10*4 + 22*5 /* SPE GPRh */
 #endif
+    + 4*6 /* tGPR */
     + 10*4 + 22*5 /* FPR */
     + 2*(10*6 + 22*7) /* AVRh, AVRl */
-    + 8*5 /* CRF */];
+    + 8*5 /* CRF */
+    + 1024*8 /* SPR */];
 static TCGv cpu_gpr[32];
 #if !defined(TARGET_PPC64)
 static TCGv cpu_gprh[32];
 #endif
+static TCGv cpu_tgpr[4];
 static TCGv_i64 cpu_fpr[32];
 static TCGv_i64 cpu_avrh[32], cpu_avrl[32];
 static TCGv_i32 cpu_crf[8];
@@ -66,8 +69,17 @@ static TCGv cpu_nip;
 static TCGv cpu_ctr;
 static TCGv cpu_lr;
 static TCGv cpu_xer;
+static TCGv cpu_msr, cpu_msr_mask;
 static TCGv_i32 cpu_fpscr;
+static TCGv cpu_spr[1024];
 static TCGv_i32 cpu_access_type;
+static TCGv_i32 cpu_interrupt_request;
+static TCGv_i32 cpu_flags;
+#if !defined(CONFIG_USER_ONLY)
+static TCGv cpu_excp_prefix;
+#endif
+static TCGv cpu_hflags, cpu_hflags_nmsr;
+static TCGv cpu_mmu_idx;
 
 /* dyngen register indexes */
 static TCGv cpu_T[3];
@@ -149,6 +161,13 @@ void ppc_translate_init(void)
         p += (i < 10) ? 6 : 7;
     }
 
+    for (i = 0; i < 4; i++) {
+        sprintf(p, "tgpr%d", i);
+        cpu_tgpr[i] = tcg_global_mem_new(TCG_AREG0,
+                                         offsetof(CPUState, tgpr[i]), p);
+        p += 6;
+    }
+
     cpu_nip = tcg_global_mem_new(TCG_AREG0,
                                  offsetof(CPUState, nip), "nip");
 
@@ -161,12 +180,44 @@ void ppc_translate_init(void)
     cpu_xer = tcg_global_mem_new(TCG_AREG0,
                                  offsetof(CPUState, xer), "xer");
 
+    cpu_msr = tcg_global_mem_new(TCG_AREG0,
+                                 offsetof(CPUState, msr), "msr");
+    cpu_msr_mask = tcg_global_mem_new(TCG_AREG0,
+                                      offsetof(CPUState, msr_mask), "msr_mask");
+
     cpu_fpscr = tcg_global_mem_new_i32(TCG_AREG0,
                                        offsetof(CPUState, fpscr), "fpscr");
 
+    for (i = 0; i < 1024; i++) {
+        sprintf(p, "SPR%d", i);
+        cpu_spr[i] = tcg_global_mem_new(TCG_AREG0,
+                                        offsetof(CPUState, spr[i]), p);
+        p += 8;
+    }
+
     cpu_access_type = tcg_global_mem_new_i32(TCG_AREG0,
                                              offsetof(CPUState, access_type), "access_type");
 
+    cpu_interrupt_request = tcg_global_mem_new_i32(TCG_AREG0,
+                                                   offsetof(CPUState, interrupt_request), "interrupt_request");
+
+    cpu_flags = tcg_global_mem_new_i32(TCG_AREG0,
+                                       offsetof(CPUState, flags), "flags");
+
+    cpu_hflags = tcg_global_mem_new(TCG_AREG0,
+                                    offsetof(CPUState, hflags), "hflags");
+
+    cpu_hflags_nmsr = tcg_global_mem_new(TCG_AREG0,
+                                         offsetof(CPUState, hflags_nmsr), "hflags_nmsr");
+
+    cpu_mmu_idx = tcg_global_mem_new(TCG_AREG0,
+                                     offsetof(CPUState, mmu_idx), "mmu_idx");
+
+#if !defined(CONFIG_USER_ONLY)
+    cpu_excp_prefix = tcg_global_mem_new(TCG_AREG0,
+                                         offsetof(CPUState, excp_prefix), "excp_prefix");
+#endif
+
     /* register helpers */
 #define GEN_HELPER 2
 #include "helper.h"
@@ -277,6 +328,165 @@ static always_inline void gen_update_nip (DisasContext *ctx, target_ulong nip)
         tcg_gen_movi_tl(cpu_nip, (uint32_t)nip);
 }
 
+static always_inline void gen_get_msr_bit(TCGv dest, TCGv src, int bit)
+{
+    tcg_gen_shri_tl(dest, src, bit);
+    tcg_gen_andi_tl(dest, dest, 1);
+}
+
+static always_inline void gen_hreg_swap_gpr_tgpr()
+{
+    int i;
+    TCGv t0 = tcg_temp_new();
+    for (i = 0; i < 4; i++) {
+        tcg_gen_mov_tl(t0, cpu_gpr[i]);
+        tcg_gen_mov_tl(cpu_gpr[i], cpu_tgpr[i]);
+        tcg_gen_mov_tl(cpu_tgpr[i], t0);
+    }
+    tcg_temp_free(t0);
+}
+
+static always_inline void gen_hreg_compute_mem_idx()
+{
+    /* Precompute MMU index */
+    TCGv t0 = tcg_temp_new();
+    gen_get_msr_bit(t0, cpu_msr, MSR_PR);
+    int elseLabel = gen_new_label();
+    tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, elseLabel);
+
+    int endLabel = gen_new_label();
+#if defined(TARGET_PPC64)
+    gen_get_msr_bit(t0, cpu_msr, MSR_SHV);
+#elif defined(PPC_EMULATE_32BITS_HYPV)
+    gen_get_msr_bit(t0, cpu_msr, MSR_THV);
+#else
+    tcg_gen_movi_tl(t0, 0);
+#endif
+    tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, endLabel);
+
+    tcg_gen_movi_tl(cpu_mmu_idx, 2);
+
+    gen_set_label(elseLabel);
+    TCGv t1 = tcg_const_tl(1);
+    gen_get_msr_bit(t0, cpu_msr, MSR_PR);
+    tcg_gen_sub_tl(cpu_mmu_idx, t1, t0);
+    tcg_gen_br(endLabel);
+    tcg_temp_free(t1);
+
+    gen_set_label(endLabel);
+    tcg_temp_free(t0);
+}
+
+static always_inline void gen_hreg_compute_hflags()
+{
+    target_ulong hflags_mask;
+    hflags_mask = (1 << MSR_VR) | (1 << MSR_AP) | (1 << MSR_SA) |
+        (1 << MSR_PR) | (1 << MSR_FP) | (1 << MSR_SE) | (1 << MSR_BE) |
+        (1 << MSR_LE);
+    hflags_mask |= (1ULL << MSR_CM) | (1ULL << MSR_SF) | MSR_HVB;
+    gen_hreg_compute_mem_idx();
+    tcg_gen_andi_tl(cpu_hflags, cpu_msr, hflags_mask);
+    /* Merge with hflags coming from other registers */
+    tcg_gen_or_tl(cpu_hflags, cpu_hflags, cpu_hflags_nmsr);
+}
+
+static always_inline void gen_hreg_store_msr(TCGv msr, int alter_hv)
+{
+    TCGv t0 = tcg_temp_new();
+    tcg_gen_and_tl(t0, msr, cpu_msr_mask);
+#if !defined(CONFIG_USER_ONLY)
+    if (!alter_hv) {
+        /* mtmsr cannot alter the hypervisor state */
+        tcg_gen_andi_tl(t0, t0, (target_ulong)~MSR_HVB);
+        TCGv t1 = tcg_temp_new();
+        tcg_gen_andi_tl(t1, cpu_msr, MSR_HVB);
+        tcg_gen_or_tl(t0, t0, t1);
+        tcg_temp_free(t1);
+    }
+
+    TCGv t1 = tcg_temp_new();
+    TCGv t2 = tcg_temp_new();
+    gen_get_msr_bit(t1, t0,      MSR_IR);
+    gen_get_msr_bit(t2, cpu_msr, MSR_IR);
+    int labelInner = gen_new_label();
+    tcg_gen_brcond_tl(TCG_COND_NE, t1, t2, labelInner);
+
+    gen_get_msr_bit(t1, t0,      MSR_DR);
+    gen_get_msr_bit(t2, cpu_msr, MSR_DR);
+    int labelEnd = gen_new_label();
+    tcg_gen_brcond_tl(TCG_COND_EQ, t1, t2, labelEnd);
+
+    gen_set_label(labelInner);
+    /* Flush all tlb when changing translation mode */
+//TODO tlb_flush(env, 1)
+    tcg_gen_ori_i32(cpu_interrupt_request, cpu_interrupt_request, CPU_INTERRUPT_EXITTB);
+
+    gen_set_label(labelEnd);
+    labelEnd = gen_new_label();
+    TCGv_i32 t3 = tcg_temp_new_i32();
+    tcg_gen_andi_i32(t3, cpu_flags, POWERPC_FLAG_TGPR);
+    tcg_gen_brcondi_i32(TCG_COND_EQ, t3, 0, labelEnd);
+    tcg_temp_free_i32(t3);
+
+    tcg_gen_xor_tl(t1, t0, cpu_msr);
+    tcg_gen_andi_tl(t1, t1, (1 << MSR_TGPR));
+    tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, labelEnd);
+    gen_hreg_swap_gpr_tgpr();
+
+    gen_set_label(labelEnd);
+    labelEnd = gen_new_label();
+    gen_get_msr_bit(t1, t0,      MSR_EP);
+    gen_get_msr_bit(t2, cpu_msr, MSR_EP);
+    tcg_gen_brcond_tl(TCG_COND_EQ, t1, t2, labelEnd);
+    /* Change the exception prefix on PowerPC 601 */
+    tcg_gen_muli_tl(cpu_excp_prefix, t1, 0xFFF00000);
+    
+    gen_set_label(labelEnd);
+    tcg_temp_free(t1);
+    tcg_temp_free(t2);
+#endif
+    tcg_gen_mov_tl(cpu_msr, t0);
+    gen_hreg_compute_hflags();
+#if !defined(CONFIG_USER_ONLY)
+//XXX
+#endif
+    tcg_temp_free(t0);
+}
+
+static always_inline void gen_do_rfi(TCGv nip, TCGv msr, target_ulong msrm, int keep_msrh)
+{
+#if defined(TARGET_PPC64)
+    int endLabel = gen_new_label();
+    TCGv_i64 t0 = tcg_temp_new_i64();
+    tcg_gen_andi_i64(t0, msr, (1ULL << MSR_SF));
+    tcg_gen_andi_i64(msr, msr, msrm);
+    tcg_gen_brcondi_i64(TCG_COND_EQ, t0, 0, endLabel);
+    tcg_temp_free_i64(t0);
+
+    tcg_gen_andi_i64(nip, nip, 0xFFFFFFFF);
+    tcg_gen_andi_i64(msr, msr, 0xFFFFFFFF);
+    if (keep_msrh) {
+        t0 = tcg_temp_new_i64();
+        tcg_gen_andi_i64(t0, cpu_msr, ~((uint64_t)0xFFFFFFFF));
+        tcg_gen_or_i64(msr, msr, t0);
+        tcg_temp_free_i64(t0);
+    }
+    gen_set_label(endLabel);
+#else
+    tcg_gen_andi_tl(msr, msr, msrm);
+#endif
+    /* XXX: beware: this is false if VLE is supported */
+    tcg_gen_andi_tl(cpu_nip, nip, ~((target_ulong)0x00000003));
+    gen_hreg_store_msr(msr, 1);
+#if defined (DEBUG_OP)
+//XXX cpu_dump_rfi(env->nip, env->msr);
+#endif
+    /* No need to raise an exception here,
+     * as rfi is always the last insn of a TB
+     */
+    tcg_gen_ori_i32(cpu_interrupt_request, cpu_interrupt_request, CPU_INTERRUPT_EXITTB);
+}
+
 #define GEN_EXCP(ctx, excp, error)                                            \
 do {                                                                          \
     TCGv_i32 t0 = tcg_const_i32(excp);                                        \
@@ -3745,7 +3955,8 @@ GEN_HANDLER(rfi, 0x13, 0x12, 0x01, 0x03FF8001, PPC_FLOW)
         GEN_EXCP_PRIVOPC(ctx);
         return;
     }
-    gen_op_rfi();
+    gen_do_rfi(cpu_spr[SPR_SRR0], cpu_spr[SPR_SRR1],
+               ~((target_ulong)0xFFFF0000), 1);
     GEN_SYNC(ctx);
 #endif
 }
@@ -3761,7 +3972,8 @@ GEN_HANDLER(rfid, 0x13, 0x12, 0x00, 0x03FF8001, PPC_64B)
         GEN_EXCP_PRIVOPC(ctx);
         return;
     }
-    gen_op_rfid();
+    gen_do_rfi(cpu_spr[SPR_SRR0], cpu_spr[SPR_SRR1],
+               ~((target_ulong)0xFFFF0000), 0);
     GEN_SYNC(ctx);
 #endif
 }
@@ -3776,7 +3988,8 @@ GEN_HANDLER(hrfid, 0x13, 0x12, 0x08, 0x03FF8001, PPC_64H)
         GEN_EXCP_PRIVOPC(ctx);
         return;
     }
-    gen_op_hrfid();
+    gen_do_rfi(cpu_spr[SPR_HSRR0], cpu_spr[SPR_HSRR1],
+               ~((target_ulong)0xFFFF0000), 0);
     GEN_SYNC(ctx);
 #endif
 }
@@ -5087,7 +5300,7 @@ GEN_HANDLER(rfsvc, 0x13, 0x12, 0x02, 0x03FFF0001, PPC_POWER)
         GEN_EXCP_PRIVOPC(ctx);
         return;
     }
-    gen_op_POWER_rfsvc();
+    gen_do_rfi(cpu_lr, cpu_ctr, 0x0000FFFF, 0);
     GEN_SYNC(ctx);
 #endif
 }
@@ -5631,7 +5844,8 @@ GEN_HANDLER2(rfci_40x, "rfci", 0x13, 0x13, 0x01, 0x03FF8001, PPC_40x_EXCP)
         return;
     }
     /* Restore CPU state */
-    gen_op_40x_rfci();
+    gen_do_rfi(cpu_spr[SPR_40x_SRR2], cpu_spr[SPR_40x_SRR3],
+               ~((target_ulong)0xFFFF0000), 0);
     GEN_SYNC(ctx);
 #endif
 }
@@ -5646,7 +5860,8 @@ GEN_HANDLER(rfci, 0x13, 0x13, 0x01, 0x03FF8001, PPC_BOOKE)
         return;
     }
     /* Restore CPU state */
-    gen_op_rfci();
+    gen_do_rfi(cpu_spr[SPR_BOOKE_CSRR0], cpu_spr[SPR_BOOKE_CSRR1],
+               ~((target_ulong)0x3FFF0000), 0);
     GEN_SYNC(ctx);
 #endif
 }
@@ -5663,7 +5878,8 @@ GEN_HANDLER(rfdi, 0x13, 0x07, 0x01, 0x03FF8001, PPC_RFDI)
         return;
     }
     /* Restore CPU state */
-    gen_op_rfdi();
+    gen_do_rfi(cpu_spr[SPR_BOOKE_DSRR0], cpu_spr[SPR_BOOKE_DSRR1],
+               ~((target_ulong)0x3FFF0000), 0);
     GEN_SYNC(ctx);
 #endif
 }
@@ -5679,7 +5895,8 @@ GEN_HANDLER(rfmci, 0x13, 0x06, 0x01, 0x03FF8001, PPC_RFMCI)
         return;
     }
     /* Restore CPU state */
-    gen_op_rfmci();
+    gen_do_rfi(cpu_spr[SPR_BOOKE_MCSRR0], cpu_spr[SPR_BOOKE_MCSRR1],
+               ~((target_ulong)0x3FFF0000), 0);
     GEN_SYNC(ctx);
 #endif
 }

[-- Attachment #3: Type: text/plain, Size: 1 bytes --]



^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [Qemu-devel] [RFC v2] ppc: rfi and friends
  2008-11-29 20:04 ` [Qemu-devel] [RFC v2] " Andreas Färber
@ 2008-11-30 16:30   ` Aurélien Jarno
  0 siblings, 0 replies; 3+ messages in thread
From: Aurélien Jarno @ 2008-11-30 16:30 UTC (permalink / raw)
  To: Andreas Färber; +Cc: qemu-devel

On Sat, Nov 29, 2008 at 09:04:23PM +0100, Andreas Färber wrote:
> 
> Am 29.11.2008 um 13:08 schrieb Andreas Färber:
> 
> >This patch migrates op_40x_rfci et al. to TCG. (op_40x_rfci is the  
> >current dyngen breakage on OSX/gcc4.)
> >
> >I believe I have spotted and fixed some ops which were lacking env- 
> >>spr[...] in their call to __do_rfi.
> >
> >The TCG code is still untested since it still breaks for op_440_dlmzb.
> >
> >Two issues remain with my patch: hreg_store_msr and cpu_dump_rfi. Is  
> >cpu_dump_rfi still needed at all?
> >hreg_store_msr is defined in helper_regs.h as always_inline - should  
> >we convert it to an inline TCG function or call it as a helper?
> 
> Attached is a compile-tested update of the patch, that adds TCG  
> versions of hreg_store_msr and dependencies.
> 
> Still unclear to me is what to do about a tlb_flush call, and an env- 
> >check_pow callback there.
> 

Converting a function to TCG if in fine it needs to call an helper
(tlb_flush) is very inefficient. It is a lot better to keep the whole
function as an helper.

I have converted those functions to TCG in revision 5832.

> ---
> diff --git a/target-ppc/op.c b/target-ppc/op.c
> index a26b1da..d00ebe8 100644
> --- a/target-ppc/op.c
> +++ b/target-ppc/op.c
> @@ -298,26 +298,6 @@ void OPPROTO op_wait (void)
> 
>  /* Return from interrupt */
>  #if !defined(CONFIG_USER_ONLY)
> -void OPPROTO op_rfi (void)
> -{
> -    do_rfi();
> -    RETURN();
> -}
> -
> -#if defined(TARGET_PPC64)
> -void OPPROTO op_rfid (void)
> -{
> -    do_rfid();
> -    RETURN();
> -}
> -
> -void OPPROTO op_hrfid (void)
> -{
> -    do_hrfid();
> -    RETURN();
> -}
> -#endif
> -
>  /* Exception vectors */
>  void OPPROTO op_store_excp_prefix (void)
>  {
> @@ -710,12 +690,6 @@ void OPPROTO op_POWER_rac (void)
>      do_POWER_rac();
>      RETURN();
>  }
> -
> -void OPPROTO op_POWER_rfsvc (void)
> -{
> -    do_POWER_rfsvc();
> -    RETURN();
> -}
>  #endif
> 
>  /* PowerPC 602 specific instruction */
> @@ -741,33 +715,6 @@ void OPPROTO op_store_dcr (void)
>  }
> 
>  #if !defined(CONFIG_USER_ONLY)
> -/* Return from critical interrupt :
> - * same as rfi, except nip & MSR are loaded from SRR2/3 instead of  
> SRR0/1
> - */
> -void OPPROTO op_40x_rfci (void)
> -{
> -    do_40x_rfci();
> -    RETURN();
> -}
> -
> -void OPPROTO op_rfci (void)
> -{
> -    do_rfci();
> -    RETURN();
> -}
> -
> -void OPPROTO op_rfdi (void)
> -{
> -    do_rfdi();
> -    RETURN();
> -}
> -
> -void OPPROTO op_rfmci (void)
> -{
> -    do_rfmci();
> -    RETURN();
> -}
> -
>  void OPPROTO op_wrte (void)
>  {
>      /* We don't call do_store_msr here as we won't trigger
> diff --git a/target-ppc/op_helper.c b/target-ppc/op_helper.c
> index a055ee6..e158630 100644
> --- a/target-ppc/op_helper.c
> +++ b/target-ppc/op_helper.c
> @@ -1373,55 +1373,6 @@ void do_store_msr (void)
>          raise_exception(env, T0);
>      }
>  }
> -
> -static always_inline void __do_rfi (target_ulong nip, target_ulong msr,
> -                                    target_ulong msrm, int keep_msrh)
> -{
> -#if defined(TARGET_PPC64)
> -    if (msr & (1ULL << MSR_SF)) {
> -        nip = (uint64_t)nip;
> -        msr &= (uint64_t)msrm;
> -    } else {
> -        nip = (uint32_t)nip;
> -        msr = (uint32_t)(msr & msrm);
> -        if (keep_msrh)
> -            msr |= env->msr & ~((uint64_t)0xFFFFFFFF);
> -    }
> -#else
> -    nip = (uint32_t)nip;
> -    msr &= (uint32_t)msrm;
> -#endif
> -    /* XXX: beware: this is false if VLE is supported */
> -    env->nip = nip & ~((target_ulong)0x00000003);
> -    hreg_store_msr(env, msr, 1);
> -#if defined (DEBUG_OP)
> -    cpu_dump_rfi(env->nip, env->msr);
> -#endif
> -    /* No need to raise an exception here,
> -     * as rfi is always the last insn of a TB
> -     */
> -    env->interrupt_request |= CPU_INTERRUPT_EXITTB;
> -}
> -
> -void do_rfi (void)
> -{
> -    __do_rfi(env->spr[SPR_SRR0], env->spr[SPR_SRR1],
> -             ~((target_ulong)0xFFFF0000), 1);
> -}
> -
> -#if defined(TARGET_PPC64)
> -void do_rfid (void)
> -{
> -    __do_rfi(env->spr[SPR_SRR0], env->spr[SPR_SRR1],
> -             ~((target_ulong)0xFFFF0000), 0);
> -}
> -
> -void do_hrfid (void)
> -{
> -    __do_rfi(env->spr[SPR_HSRR0], env->spr[SPR_HSRR1],
> -             ~((target_ulong)0xFFFF0000), 0);
> -}
> -#endif
>  #endif
> 
>  void helper_tw (target_ulong arg1, target_ulong arg2, uint32_t flags)
> @@ -1615,11 +1566,6 @@ void do_POWER_rac (void)
>      env->nb_BATs = nb_BATs;
>  }
> 
> -void do_POWER_rfsvc (void)
> -{
> -    __do_rfi(env->lr, env->ctr, 0x0000FFFF, 0);
> -}
> -
>  void do_store_hid0_601 (void)
>  {
>      uint32_t hid0;
> @@ -1715,30 +1661,6 @@ void do_store_dcr (void)
>  }
> 
>  #if !defined(CONFIG_USER_ONLY)
> -void do_40x_rfci (void)
> -{
> -    __do_rfi(env->spr[SPR_40x_SRR2], env->spr[SPR_40x_SRR3],
> -             ~((target_ulong)0xFFFF0000), 0);
> -}
> -
> -void do_rfci (void)
> -{
> -    __do_rfi(env->spr[SPR_BOOKE_CSRR0], SPR_BOOKE_CSRR1,
> -             ~((target_ulong)0x3FFF0000), 0);
> -}
> -
> -void do_rfdi (void)
> -{
> -    __do_rfi(env->spr[SPR_BOOKE_DSRR0], SPR_BOOKE_DSRR1,
> -             ~((target_ulong)0x3FFF0000), 0);
> -}
> -
> -void do_rfmci (void)
> -{
> -    __do_rfi(env->spr[SPR_BOOKE_MCSRR0], SPR_BOOKE_MCSRR1,
> -             ~((target_ulong)0x3FFF0000), 0);
> -}
> -
>  void do_load_403_pb (int num)
>  {
>      T0 = env->pb[num];
> diff --git a/target-ppc/op_helper.h b/target-ppc/op_helper.h
> index aaaba5c..db458b7 100644
> --- a/target-ppc/op_helper.h
> +++ b/target-ppc/op_helper.h
> @@ -62,11 +62,6 @@ void ppc_store_dump_spr (int sprn, target_ulong val);
>  /* Misc */
>  #if !defined(CONFIG_USER_ONLY)
>  void do_store_msr (void);
> -void do_rfi (void);
> -#if defined(TARGET_PPC64)
> -void do_rfid (void);
> -void do_hrfid (void);
> -#endif
>  void do_load_6xx_tlb (int is_code);
>  void do_load_74xx_tlb (int is_code);
>  #endif
> @@ -83,7 +78,6 @@ void do_POWER_maskg (void);
>  void do_POWER_mulo (void);
>  #if !defined(CONFIG_USER_ONLY)
>  void do_POWER_rac (void);
> -void do_POWER_rfsvc (void);
>  void do_store_hid0_601 (void);
>  #endif
> 
> @@ -102,10 +96,6 @@ void do_440_tlbwe (int word);
>  void do_load_dcr (void);
>  void do_store_dcr (void);
>  #if !defined(CONFIG_USER_ONLY)
> -void do_40x_rfci (void);
> -void do_rfci (void);
> -void do_rfdi (void);
> -void do_rfmci (void);
>  void do_4xx_tlbre_lo (void);
>  void do_4xx_tlbre_hi (void);
>  void do_4xx_tlbwe_lo (void);
> diff --git a/target-ppc/translate.c b/target-ppc/translate.c
> index 59533ac..c5c7eb6 100644
> --- a/target-ppc/translate.c
> +++ b/target-ppc/translate.c
> @@ -52,13 +52,16 @@ static char cpu_reg_names[10*3 + 22*4 /* GPR */
>  #if !defined(TARGET_PPC64)
>      + 10*4 + 22*5 /* SPE GPRh */
>  #endif
> +    + 4*6 /* tGPR */
>      + 10*4 + 22*5 /* FPR */
>      + 2*(10*6 + 22*7) /* AVRh, AVRl */
> -    + 8*5 /* CRF */];
> +    + 8*5 /* CRF */
> +    + 1024*8 /* SPR */];
>  static TCGv cpu_gpr[32];
>  #if !defined(TARGET_PPC64)
>  static TCGv cpu_gprh[32];
>  #endif
> +static TCGv cpu_tgpr[4];
>  static TCGv_i64 cpu_fpr[32];
>  static TCGv_i64 cpu_avrh[32], cpu_avrl[32];
>  static TCGv_i32 cpu_crf[8];
> @@ -66,8 +69,17 @@ static TCGv cpu_nip;
>  static TCGv cpu_ctr;
>  static TCGv cpu_lr;
>  static TCGv cpu_xer;
> +static TCGv cpu_msr, cpu_msr_mask;
>  static TCGv_i32 cpu_fpscr;
> +static TCGv cpu_spr[1024];
>  static TCGv_i32 cpu_access_type;
> +static TCGv_i32 cpu_interrupt_request;
> +static TCGv_i32 cpu_flags;
> +#if !defined(CONFIG_USER_ONLY)
> +static TCGv cpu_excp_prefix;
> +#endif
> +static TCGv cpu_hflags, cpu_hflags_nmsr;
> +static TCGv cpu_mmu_idx;
> 
>  /* dyngen register indexes */
>  static TCGv cpu_T[3];
> @@ -149,6 +161,13 @@ void ppc_translate_init(void)
>          p += (i < 10) ? 6 : 7;
>      }
> 
> +    for (i = 0; i < 4; i++) {
> +        sprintf(p, "tgpr%d", i);
> +        cpu_tgpr[i] = tcg_global_mem_new(TCG_AREG0,
> +                                         offsetof(CPUState, tgpr[i]),  
> p);
> +        p += 6;
> +    }
> +
>      cpu_nip = tcg_global_mem_new(TCG_AREG0,
>                                   offsetof(CPUState, nip), "nip");
> 
> @@ -161,12 +180,44 @@ void ppc_translate_init(void)
>      cpu_xer = tcg_global_mem_new(TCG_AREG0,
>                                   offsetof(CPUState, xer), "xer");
> 
> +    cpu_msr = tcg_global_mem_new(TCG_AREG0,
> +                                 offsetof(CPUState, msr), "msr");
> +    cpu_msr_mask = tcg_global_mem_new(TCG_AREG0,
> +                                      offsetof(CPUState, msr_mask),  
> "msr_mask");
> +
>      cpu_fpscr = tcg_global_mem_new_i32(TCG_AREG0,
>                                         offsetof(CPUState, fpscr),  
> "fpscr");
> 
> +    for (i = 0; i < 1024; i++) {
> +        sprintf(p, "SPR%d", i);
> +        cpu_spr[i] = tcg_global_mem_new(TCG_AREG0,
> +                                        offsetof(CPUState, spr[i]), p);
> +        p += 8;
> +    }
> +
>      cpu_access_type = tcg_global_mem_new_i32(TCG_AREG0,
>                                               offsetof(CPUState,  
> access_type), "access_type");
> 
> +    cpu_interrupt_request = tcg_global_mem_new_i32(TCG_AREG0,
> +                                                   offsetof(CPUState,  
> interrupt_request), "interrupt_request");
> +
> +    cpu_flags = tcg_global_mem_new_i32(TCG_AREG0,
> +                                       offsetof(CPUState, flags),  
> "flags");
> +
> +    cpu_hflags = tcg_global_mem_new(TCG_AREG0,
> +                                    offsetof(CPUState, hflags),  
> "hflags");
> +
> +    cpu_hflags_nmsr = tcg_global_mem_new(TCG_AREG0,
> +                                         offsetof(CPUState,  
> hflags_nmsr), "hflags_nmsr");
> +
> +    cpu_mmu_idx = tcg_global_mem_new(TCG_AREG0,
> +                                     offsetof(CPUState, mmu_idx),  
> "mmu_idx");
> +
> +#if !defined(CONFIG_USER_ONLY)
> +    cpu_excp_prefix = tcg_global_mem_new(TCG_AREG0,
> +                                         offsetof(CPUState,  
> excp_prefix), "excp_prefix");
> +#endif
> +
>      /* register helpers */
>  #define GEN_HELPER 2
>  #include "helper.h"
> @@ -277,6 +328,165 @@ static always_inline void gen_update_nip  
> (DisasContext *ctx, target_ulong nip)
>          tcg_gen_movi_tl(cpu_nip, (uint32_t)nip);
>  }
> 
> +static always_inline void gen_get_msr_bit(TCGv dest, TCGv src, int bit)
> +{
> +    tcg_gen_shri_tl(dest, src, bit);
> +    tcg_gen_andi_tl(dest, dest, 1);
> +}
> +
> +static always_inline void gen_hreg_swap_gpr_tgpr()
> +{
> +    int i;
> +    TCGv t0 = tcg_temp_new();
> +    for (i = 0; i < 4; i++) {
> +        tcg_gen_mov_tl(t0, cpu_gpr[i]);
> +        tcg_gen_mov_tl(cpu_gpr[i], cpu_tgpr[i]);
> +        tcg_gen_mov_tl(cpu_tgpr[i], t0);
> +    }
> +    tcg_temp_free(t0);
> +}
> +
> +static always_inline void gen_hreg_compute_mem_idx()
> +{
> +    /* Precompute MMU index */
> +    TCGv t0 = tcg_temp_new();
> +    gen_get_msr_bit(t0, cpu_msr, MSR_PR);
> +    int elseLabel = gen_new_label();
> +    tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, elseLabel);
> +
> +    int endLabel = gen_new_label();
> +#if defined(TARGET_PPC64)
> +    gen_get_msr_bit(t0, cpu_msr, MSR_SHV);
> +#elif defined(PPC_EMULATE_32BITS_HYPV)
> +    gen_get_msr_bit(t0, cpu_msr, MSR_THV);
> +#else
> +    tcg_gen_movi_tl(t0, 0);
> +#endif
> +    tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, endLabel);
> +
> +    tcg_gen_movi_tl(cpu_mmu_idx, 2);
> +
> +    gen_set_label(elseLabel);
> +    TCGv t1 = tcg_const_tl(1);
> +    gen_get_msr_bit(t0, cpu_msr, MSR_PR);
> +    tcg_gen_sub_tl(cpu_mmu_idx, t1, t0);
> +    tcg_gen_br(endLabel);
> +    tcg_temp_free(t1);
> +
> +    gen_set_label(endLabel);
> +    tcg_temp_free(t0);
> +}
> +
> +static always_inline void gen_hreg_compute_hflags()
> +{
> +    target_ulong hflags_mask;
> +    hflags_mask = (1 << MSR_VR) | (1 << MSR_AP) | (1 << MSR_SA) |
> +        (1 << MSR_PR) | (1 << MSR_FP) | (1 << MSR_SE) | (1 << MSR_BE) |
> +        (1 << MSR_LE);
> +    hflags_mask |= (1ULL << MSR_CM) | (1ULL << MSR_SF) | MSR_HVB;
> +    gen_hreg_compute_mem_idx();
> +    tcg_gen_andi_tl(cpu_hflags, cpu_msr, hflags_mask);
> +    /* Merge with hflags coming from other registers */
> +    tcg_gen_or_tl(cpu_hflags, cpu_hflags, cpu_hflags_nmsr);
> +}
> +
> +static always_inline void gen_hreg_store_msr(TCGv msr, int alter_hv)
> +{
> +    TCGv t0 = tcg_temp_new();
> +    tcg_gen_and_tl(t0, msr, cpu_msr_mask);
> +#if !defined(CONFIG_USER_ONLY)
> +    if (!alter_hv) {
> +        /* mtmsr cannot alter the hypervisor state */
> +        tcg_gen_andi_tl(t0, t0, (target_ulong)~MSR_HVB);
> +        TCGv t1 = tcg_temp_new();
> +        tcg_gen_andi_tl(t1, cpu_msr, MSR_HVB);
> +        tcg_gen_or_tl(t0, t0, t1);
> +        tcg_temp_free(t1);
> +    }
> +
> +    TCGv t1 = tcg_temp_new();
> +    TCGv t2 = tcg_temp_new();
> +    gen_get_msr_bit(t1, t0,      MSR_IR);
> +    gen_get_msr_bit(t2, cpu_msr, MSR_IR);
> +    int labelInner = gen_new_label();
> +    tcg_gen_brcond_tl(TCG_COND_NE, t1, t2, labelInner);
> +
> +    gen_get_msr_bit(t1, t0,      MSR_DR);
> +    gen_get_msr_bit(t2, cpu_msr, MSR_DR);
> +    int labelEnd = gen_new_label();
> +    tcg_gen_brcond_tl(TCG_COND_EQ, t1, t2, labelEnd);
> +
> +    gen_set_label(labelInner);
> +    /* Flush all tlb when changing translation mode */
> +//TODO tlb_flush(env, 1)
> +    tcg_gen_ori_i32(cpu_interrupt_request, cpu_interrupt_request,  
> CPU_INTERRUPT_EXITTB);
> +
> +    gen_set_label(labelEnd);
> +    labelEnd = gen_new_label();
> +    TCGv_i32 t3 = tcg_temp_new_i32();
> +    tcg_gen_andi_i32(t3, cpu_flags, POWERPC_FLAG_TGPR);
> +    tcg_gen_brcondi_i32(TCG_COND_EQ, t3, 0, labelEnd);
> +    tcg_temp_free_i32(t3);
> +
> +    tcg_gen_xor_tl(t1, t0, cpu_msr);
> +    tcg_gen_andi_tl(t1, t1, (1 << MSR_TGPR));
> +    tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, labelEnd);
> +    gen_hreg_swap_gpr_tgpr();
> +
> +    gen_set_label(labelEnd);
> +    labelEnd = gen_new_label();
> +    gen_get_msr_bit(t1, t0,      MSR_EP);
> +    gen_get_msr_bit(t2, cpu_msr, MSR_EP);
> +    tcg_gen_brcond_tl(TCG_COND_EQ, t1, t2, labelEnd);
> +    /* Change the exception prefix on PowerPC 601 */
> +    tcg_gen_muli_tl(cpu_excp_prefix, t1, 0xFFF00000);
> +
> +    gen_set_label(labelEnd);
> +    tcg_temp_free(t1);
> +    tcg_temp_free(t2);
> +#endif
> +    tcg_gen_mov_tl(cpu_msr, t0);
> +    gen_hreg_compute_hflags();
> +#if !defined(CONFIG_USER_ONLY)
> +//XXX
> +#endif
> +    tcg_temp_free(t0);
> +}
> +
> +static always_inline void gen_do_rfi(TCGv nip, TCGv msr, target_ulong  
> msrm, int keep_msrh)
> +{
> +#if defined(TARGET_PPC64)
> +    int endLabel = gen_new_label();
> +    TCGv_i64 t0 = tcg_temp_new_i64();
> +    tcg_gen_andi_i64(t0, msr, (1ULL << MSR_SF));
> +    tcg_gen_andi_i64(msr, msr, msrm);
> +    tcg_gen_brcondi_i64(TCG_COND_EQ, t0, 0, endLabel);
> +    tcg_temp_free_i64(t0);
> +
> +    tcg_gen_andi_i64(nip, nip, 0xFFFFFFFF);
> +    tcg_gen_andi_i64(msr, msr, 0xFFFFFFFF);
> +    if (keep_msrh) {
> +        t0 = tcg_temp_new_i64();
> +        tcg_gen_andi_i64(t0, cpu_msr, ~((uint64_t)0xFFFFFFFF));
> +        tcg_gen_or_i64(msr, msr, t0);
> +        tcg_temp_free_i64(t0);
> +    }
> +    gen_set_label(endLabel);
> +#else
> +    tcg_gen_andi_tl(msr, msr, msrm);
> +#endif
> +    /* XXX: beware: this is false if VLE is supported */
> +    tcg_gen_andi_tl(cpu_nip, nip, ~((target_ulong)0x00000003));
> +    gen_hreg_store_msr(msr, 1);
> +#if defined (DEBUG_OP)
> +//XXX cpu_dump_rfi(env->nip, env->msr);
> +#endif
> +    /* No need to raise an exception here,
> +     * as rfi is always the last insn of a TB
> +     */
> +    tcg_gen_ori_i32(cpu_interrupt_request, cpu_interrupt_request,  
> CPU_INTERRUPT_EXITTB);
> +}
> +
>  #define GEN_EXCP(ctx, excp,  
> error)                                            \
>  do  
> {                                                                          \
>      TCGv_i32 t0 =  
> tcg_const_i32(excp);                                        \
> @@ -3745,7 +3955,8 @@ GEN_HANDLER(rfi, 0x13, 0x12, 0x01, 0x03FF8001,  
> PPC_FLOW)
>          GEN_EXCP_PRIVOPC(ctx);
>          return;
>      }
> -    gen_op_rfi();
> +    gen_do_rfi(cpu_spr[SPR_SRR0], cpu_spr[SPR_SRR1],
> +               ~((target_ulong)0xFFFF0000), 1);
>      GEN_SYNC(ctx);
>  #endif
>  }
> @@ -3761,7 +3972,8 @@ GEN_HANDLER(rfid, 0x13, 0x12, 0x00, 0x03FF8001,  
> PPC_64B)
>          GEN_EXCP_PRIVOPC(ctx);
>          return;
>      }
> -    gen_op_rfid();
> +    gen_do_rfi(cpu_spr[SPR_SRR0], cpu_spr[SPR_SRR1],
> +               ~((target_ulong)0xFFFF0000), 0);
>      GEN_SYNC(ctx);
>  #endif
>  }
> @@ -3776,7 +3988,8 @@ GEN_HANDLER(hrfid, 0x13, 0x12, 0x08, 0x03FF8001,  
> PPC_64H)
>          GEN_EXCP_PRIVOPC(ctx);
>          return;
>      }
> -    gen_op_hrfid();
> +    gen_do_rfi(cpu_spr[SPR_HSRR0], cpu_spr[SPR_HSRR1],
> +               ~((target_ulong)0xFFFF0000), 0);
>      GEN_SYNC(ctx);
>  #endif
>  }
> @@ -5087,7 +5300,7 @@ GEN_HANDLER(rfsvc, 0x13, 0x12, 0x02,  
> 0x03FFF0001, PPC_POWER)
>          GEN_EXCP_PRIVOPC(ctx);
>          return;
>      }
> -    gen_op_POWER_rfsvc();
> +    gen_do_rfi(cpu_lr, cpu_ctr, 0x0000FFFF, 0);
>      GEN_SYNC(ctx);
>  #endif
>  }
> @@ -5631,7 +5844,8 @@ GEN_HANDLER2(rfci_40x, "rfci", 0x13, 0x13, 0x01,  
> 0x03FF8001, PPC_40x_EXCP)
>          return;
>      }
>      /* Restore CPU state */
> -    gen_op_40x_rfci();
> +    gen_do_rfi(cpu_spr[SPR_40x_SRR2], cpu_spr[SPR_40x_SRR3],
> +               ~((target_ulong)0xFFFF0000), 0);
>      GEN_SYNC(ctx);
>  #endif
>  }
> @@ -5646,7 +5860,8 @@ GEN_HANDLER(rfci, 0x13, 0x13, 0x01, 0x03FF8001,  
> PPC_BOOKE)
>          return;
>      }
>      /* Restore CPU state */
> -    gen_op_rfci();
> +    gen_do_rfi(cpu_spr[SPR_BOOKE_CSRR0], cpu_spr[SPR_BOOKE_CSRR1],
> +               ~((target_ulong)0x3FFF0000), 0);
>      GEN_SYNC(ctx);
>  #endif
>  }
> @@ -5663,7 +5878,8 @@ GEN_HANDLER(rfdi, 0x13, 0x07, 0x01, 0x03FF8001,  
> PPC_RFDI)
>          return;
>      }
>      /* Restore CPU state */
> -    gen_op_rfdi();
> +    gen_do_rfi(cpu_spr[SPR_BOOKE_DSRR0], cpu_spr[SPR_BOOKE_DSRR1],
> +               ~((target_ulong)0x3FFF0000), 0);
>      GEN_SYNC(ctx);
>  #endif
>  }
> @@ -5679,7 +5895,8 @@ GEN_HANDLER(rfmci, 0x13, 0x06, 0x01, 0x03FF8001,  
> PPC_RFMCI)
>          return;
>      }
>      /* Restore CPU state */
> -    gen_op_rfmci();
> +    gen_do_rfi(cpu_spr[SPR_BOOKE_MCSRR0], cpu_spr[SPR_BOOKE_MCSRR1],
> +               ~((target_ulong)0x3FFF0000), 0);
>      GEN_SYNC(ctx);
>  #endif
>  }
> 
> 


> 


-- 
  .''`.  Aurelien Jarno	            | GPG: 1024D/F1BCDB73
 : :' :  Debian developer           | Electrical Engineer
 `. `'   aurel32@debian.org         | aurelien@aurel32.net
   `-    people.debian.org/~aurel32 | www.aurel32.net

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2008-11-30 16:30 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-11-29 12:08 [Qemu-devel] [RFC] ppc: rfi and friends Andreas Färber
2008-11-29 20:04 ` [Qemu-devel] [RFC v2] " Andreas Färber
2008-11-30 16:30   ` Aurélien Jarno

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).