]> git.proxmox.com Git - qemu.git/commitdiff
Fix rfi instruction: do not depend on current execution mode
authorj_mayer <j_mayer@c046a42c-6fe2-441c-8c8c-71466251a162>
Fri, 30 Mar 2007 10:22:46 +0000 (10:22 +0000)
committerj_mayer <j_mayer@c046a42c-6fe2-441c-8c8c-71466251a162>
Fri, 30 Mar 2007 10:22:46 +0000 (10:22 +0000)
 but on the execution mode that will be effective after the return.
Add rfci, rfdi and rfmci for BookE PowerPC.
Extend mfdcr / mtdcr and implement mfdrcx / mtdcrx.

git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2544 c046a42c-6fe2-441c-8c8c-71466251a162

target-ppc/op.c
target-ppc/op_helper.c
target-ppc/op_helper.h
target-ppc/translate.c

index 8bbbd62d47bbb94888697a1c6559e2c8fda2b100..b284798dc79e06fa73e7584e0e09f1d381dc52ec 100644 (file)
@@ -1821,23 +1821,11 @@ void OPPROTO op_rfi (void)
 }
 
 #if defined(TARGET_PPC64)
-void OPPROTO op_rfi_32 (void)
-{
-    do_rfi_32();
-    RETURN();
-}
-
 void OPPROTO op_rfid (void)
 {
     do_rfid();
     RETURN();
 }
-
-void OPPROTO op_rfid_32 (void)
-{
-    do_rfid_32();
-    RETURN();
-}
 #endif
 #endif
 
@@ -2309,28 +2297,46 @@ void OPPROTO op_405_check_satu (void)
 }
 
 #if !defined(CONFIG_USER_ONLY)
-void OPPROTO op_4xx_load_dcr (void)
+void OPPROTO op_load_dcr (void)
 {
-    do_4xx_load_dcr(PARAM1);
+    do_load_dcr();
     RETURN();
 }
 
-void OPPROTO op_4xx_store_dcr (void)
+void OPPROTO op_store_dcr (void)
 {
-    do_4xx_store_dcr(PARAM1);
+    do_store_dcr();
     RETURN();
 }
 
 /* Return from critical interrupt :
  * same as rfi, except nip & MSR are loaded from SRR2/3 instead of SRR0/1
  */
-void OPPROTO op_4xx_rfci (void)
+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_4xx_rfci();
+    do_rfmci();
     RETURN();
 }
 
-void OPPROTO op_4xx_wrte (void)
+void OPPROTO op_wrte (void)
 {
     msr_ee = T0 >> 16;
     RETURN();
index 55b5ca5653a9fa8d83586223daf974f1c9cf658a..c21a38aea420dc43b9b53213150f17e00dc160c0 100644 (file)
@@ -881,12 +881,17 @@ void do_fcmpo (void)
 #if !defined (CONFIG_USER_ONLY)
 void do_rfi (void)
 {
-    env->nip = (target_ulong)(env->spr[SPR_SRR0] & ~0x00000003);
-    T0 = (uint32_t)(env->spr[SPR_SRR1] & ~0xFFFF0000UL);
 #if defined(TARGET_PPC64)
-    ppc_store_msr_32(env, T0);
+    if (env->spr[SPR_SRR1] & (1ULL << MSR_SF)) {
+        env->nip = (uint64_t)(env->spr[SPR_SRR0] & ~0x00000003);
+        do_store_msr(env, (uint64_t)(env->spr[SPR_SRR1] & ~0xFFFF0000UL));
+    } else {
+        env->nip = (uint32_t)(env->spr[SPR_SRR0] & ~0x00000003);
+        ppc_store_msr_32(env, (uint32_t)(env->spr[SPR_SRR1] & ~0xFFFF0000UL));
+    }
 #else
-    do_store_msr(env, T0);
+    env->nip = (uint32_t)(env->spr[SPR_SRR0] & ~0x00000003);
+    do_store_msr(env, (uint32_t)(env->spr[SPR_SRR1] & ~0xFFFF0000UL));
 #endif
 #if defined (DEBUG_OP)
     dump_rfi();
@@ -895,33 +900,15 @@ void do_rfi (void)
 }
 
 #if defined(TARGET_PPC64)
-void do_rfi_32 (void)
-{
-    env->nip = (uint32_t)(env->spr[SPR_SRR0] & ~0x00000003);
-    T0 = (uint32_t)(env->spr[SPR_SRR1] & ~0xFFFF0000UL);
-    ppc_store_msr_32(env, T0);
-#if defined (DEBUG_OP)
-    dump_rfi();
-#endif
-    env->interrupt_request |= CPU_INTERRUPT_EXITTB;
-}
-
 void do_rfid (void)
 {
-    env->nip = (target_ulong)(env->spr[SPR_SRR0] & ~0x00000003);
-    T0 = (uint64_t)(env->spr[SPR_SRR1] & ~0xFFFF0000UL);
-    do_store_msr(env, T0);
-#if defined (DEBUG_OP)
-    dump_rfi();
-#endif
-    env->interrupt_request |= CPU_INTERRUPT_EXITTB;
-}
-
-void do_rfid_32 (void)
-{
-    env->nip = (uint32_t)(env->spr[SPR_SRR0] & ~0x00000003);
-    T0 = (uint64_t)(env->spr[SPR_SRR1] & ~0xFFFF0000UL);
-    do_store_msr(env, T0);
+    if (env->spr[SPR_SRR1] & (1ULL << MSR_SF)) {
+        env->nip = (uint64_t)(env->spr[SPR_SRR0] & ~0x00000003);
+        do_store_msr(env, (uint64_t)(env->spr[SPR_SRR1] & ~0xFFFF0000UL));
+    } else {
+        env->nip = (uint32_t)(env->spr[SPR_SRR0] & ~0x00000003);
+        do_store_msr(env, (uint32_t)(env->spr[SPR_SRR1] & ~0xFFFF0000UL));
+    }
 #if defined (DEBUG_OP)
     dump_rfi();
 #endif
@@ -936,8 +923,9 @@ void do_tw (int flags)
                   ((int32_t)T0 > (int32_t)T1 && (flags & 0x08)) ||
                   ((int32_t)T0 == (int32_t)T1 && (flags & 0x04)) ||
                   ((uint32_t)T0 < (uint32_t)T1 && (flags & 0x02)) ||
-                  ((uint32_t)T0 > (uint32_t)T1 && (flags & 0x01)))))
+                  ((uint32_t)T0 > (uint32_t)T1 && (flags & 0x01))))) {
         do_raise_exception_err(EXCP_PROGRAM, EXCP_TRAP);
+    }
 }
 
 #if defined(TARGET_PPC64)
@@ -1196,34 +1184,84 @@ void do_405_check_sat (void)
 }
 
 #if !defined(CONFIG_USER_ONLY)
-void do_4xx_rfci (void)
+void do_40x_rfci (void)
 {
     env->nip = env->spr[SPR_40x_SRR2];
-    T0 = env->spr[SPR_40x_SRR3] & ~0xFFFF0000;
-    do_store_msr(env, T0);
+    do_store_msr(env, env->spr[SPR_40x_SRR3] & ~0xFFFF0000);
+#if defined (DEBUG_OP)
+    dump_rfi();
+#endif
+    env->interrupt_request = CPU_INTERRUPT_EXITTB;
+}
+
+void do_rfci (void)
+{
+#if defined(TARGET_PPC64)
+    if (env->spr[SPR_BOOKE_CSRR1] & (1 << MSR_CM)) {
+        env->nip = (uint64_t)env->spr[SPR_BOOKE_CSRR0];
+    } else
+#endif
+    {
+        env->nip = (uint32_t)env->spr[SPR_BOOKE_CSRR0];
+    }
+    do_store_msr(env, (uint32_t)env->spr[SPR_BOOKE_CSRR1] & ~0x3FFF0000);
+#if defined (DEBUG_OP)
+    dump_rfi();
+#endif
+    env->interrupt_request = CPU_INTERRUPT_EXITTB;
+}
+
+void do_rfdi (void)
+{
+#if defined(TARGET_PPC64)
+    if (env->spr[SPR_BOOKE_DSRR1] & (1 << MSR_CM)) {
+        env->nip = (uint64_t)env->spr[SPR_BOOKE_DSRR0];
+    } else
+#endif
+    {
+        env->nip = (uint32_t)env->spr[SPR_BOOKE_DSRR0];
+    }
+    do_store_msr(env, (uint32_t)env->spr[SPR_BOOKE_DSRR1] & ~0x3FFF0000);
+#if defined (DEBUG_OP)
+    dump_rfi();
+#endif
+    env->interrupt_request = CPU_INTERRUPT_EXITTB;
+}
+
+void do_rfmci (void)
+{
+#if defined(TARGET_PPC64)
+    if (env->spr[SPR_BOOKE_MCSRR1] & (1 << MSR_CM)) {
+        env->nip = (uint64_t)env->spr[SPR_BOOKE_MCSRR0];
+    } else
+#endif
+    {
+        env->nip = (uint32_t)env->spr[SPR_BOOKE_MCSRR0];
+    }
+    do_store_msr(env, (uint32_t)env->spr[SPR_BOOKE_MCSRR1] & ~0x3FFF0000);
 #if defined (DEBUG_OP)
     dump_rfi();
 #endif
     env->interrupt_request = CPU_INTERRUPT_EXITTB;
 }
 
-void do_4xx_load_dcr (int dcrn)
+void do_load_dcr (void)
 {
     target_ulong val;
     
     if (unlikely(env->dcr_read == NULL))
         do_raise_exception_err(EXCP_PROGRAM, EXCP_INVAL | EXCP_INVAL_INVAL);
-    else if (unlikely((*env->dcr_read)(env->dcr_env, dcrn, &val) != 0))
+    else if (unlikely((*env->dcr_read)(env->dcr_env, T0, &val) != 0))
         do_raise_exception_err(EXCP_PROGRAM, EXCP_INVAL | EXCP_PRIV_REG);
     else
         T0 = val;
 }
 
-void do_4xx_store_dcr (int dcrn)
+void do_store_dcr (void)
 {
     if (unlikely(env->dcr_write == NULL))
         do_raise_exception_err(EXCP_PROGRAM, EXCP_INVAL | EXCP_INVAL_INVAL);
-    else if (unlikely((*env->dcr_write)(env->dcr_env, dcrn, T0) != 0))
+    else if (unlikely((*env->dcr_write)(env->dcr_env, T0, T1) != 0))
         do_raise_exception_err(EXCP_PROGRAM, EXCP_INVAL | EXCP_PRIV_REG);
 }
 
index f819a0d36c0b27c8619f6d46e12c104843eeab96..abc295a4da93a33079917881768e45c455814e1d 100644 (file)
@@ -117,9 +117,7 @@ void do_td (int flags);
 #if !defined(CONFIG_USER_ONLY)
 void do_rfi (void);
 #if defined(TARGET_PPC64)
-void do_rfi_32 (void);
 void do_rfid (void);
-void do_rfid_32 (void);
 #endif
 void do_tlbia (void);
 void do_tlbie (void);
@@ -158,9 +156,12 @@ void do_op_602_mfrom (void);
 void do_405_check_ov (void);
 void do_405_check_sat (void);
 #if !defined(CONFIG_USER_ONLY)
-void do_4xx_load_dcr (int dcrn);
-void do_4xx_store_dcr (int dcrn);
-void do_4xx_rfci (void);
+void do_load_dcr (void);
+void do_store_dcr (void);
+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_tlbsx (void);
index 7d382d6cab24f0f991ae130bb8dd3b104dc36b98..2d9a346ed58643cbe2bf14e1cf366a5834d4324e 100644 (file)
@@ -2861,12 +2861,7 @@ GEN_HANDLER(rfi, 0x13, 0x12, 0x01, 0x03FF8001, PPC_FLOW)
         RET_PRIVOPC(ctx);
         return;
     }
-#if defined(TARGET_PPC64)
-    if (!ctx->sf_mode)
-        gen_op_rfi_32();
-    else
-#endif
-        gen_op_rfi();
+    gen_op_rfi();
     RET_CHG_FLOW(ctx);
 #endif
 }
@@ -2882,10 +2877,7 @@ GEN_HANDLER(rfid, 0x13, 0x12, 0x00, 0x03FF8001, PPC_FLOW)
         RET_PRIVOPC(ctx);
         return;
     }
-    if (!ctx->sf_mode)
-        gen_op_rfid_32();
-    else
-        gen_op_rfid();
+    gen_op_rfid();
     RET_CHG_FLOW(ctx);
 #endif
 }
@@ -4423,7 +4415,8 @@ GEN_HANDLER(mfdcr, 0x1F, 0x03, 0x0A, 0x00000001, PPC_EMB_COMMON)
         RET_PRIVREG(ctx);
         return;
     }
-    gen_op_4xx_load_dcr(dcrn);
+    gen_op_set_T0(dcrn);
+    gen_op_load_dcr();
     gen_op_store_T0_gpr(rD(ctx->opcode));
 #endif
 }
@@ -4440,8 +4433,41 @@ GEN_HANDLER(mtdcr, 0x1F, 0x03, 0x0E, 0x00000001, PPC_EMB_COMMON)
         RET_PRIVREG(ctx);
         return;
     }
-    gen_op_load_gpr_T0(rS(ctx->opcode));
-    gen_op_4xx_store_dcr(dcrn);
+    gen_op_set_T0(dcrn);
+    gen_op_load_gpr_T1(rS(ctx->opcode));
+    gen_op_store_dcr();
+#endif
+}
+
+/* mfdcrx */
+GEN_HANDLER(mfdcrx, 0x1F, 0x03, 0x08, 0x00000001, PPC_BOOKE)
+{
+#if defined(CONFIG_USER_ONLY)
+    RET_PRIVREG(ctx);
+#else
+    if (unlikely(!ctx->supervisor)) {
+        RET_PRIVREG(ctx);
+        return;
+    }
+    gen_op_load_gpr_T0(rA(ctx->opcode));
+    gen_op_load_dcr();
+    gen_op_store_T0_gpr(rD(ctx->opcode));
+#endif
+}
+
+/* mtdcrx */
+GEN_HANDLER(mtdcrx, 0x1F, 0x03, 0x0C, 0x00000001, PPC_BOOKE)
+{
+#if defined(CONFIG_USER_ONLY)
+    RET_PRIVREG(ctx);
+#else
+    if (unlikely(!ctx->supervisor)) {
+        RET_PRIVREG(ctx);
+        return;
+    }
+    gen_op_load_gpr_T0(rA(ctx->opcode));
+    gen_op_load_gpr_T1(rS(ctx->opcode));
+    gen_op_store_dcr();
 #endif
 }
 
@@ -4513,7 +4539,38 @@ GEN_HANDLER(icread, 0x1F, 0x06, 0x1F, 0x03E00001, PPC_4xx_COMMON)
 }
 
 /* rfci (supervisor only) */
-GEN_HANDLER(rfci, 0x13, 0x13, 0x01, 0x03FF8001, PPC_EMB_COMMON)
+GEN_HANDLER(rfci_40x, 0x13, 0x13, 0x01, 0x03FF8001, PPC_40x_EXCP)
+{
+#if defined(CONFIG_USER_ONLY)
+    RET_PRIVOPC(ctx);
+#else
+    if (unlikely(!ctx->supervisor)) {
+        RET_PRIVOPC(ctx);
+        return;
+    }
+    /* Restore CPU state */
+    gen_op_40x_rfci();
+    RET_CHG_FLOW(ctx);
+#endif
+}
+
+GEN_HANDLER(rfci, 0x13, 0x13, 0x01, 0x03FF8001, PPC_BOOKE)
+{
+#if defined(CONFIG_USER_ONLY)
+    RET_PRIVOPC(ctx);
+#else
+    if (unlikely(!ctx->supervisor)) {
+        RET_PRIVOPC(ctx);
+        return;
+    }
+    /* Restore CPU state */
+    gen_op_rfci();
+    RET_CHG_FLOW(ctx);
+#endif
+}
+
+/* BookE specific */
+GEN_HANDLER(rfdi, 0x13, 0x07, 0x01, 0x03FF8001, PPC_BOOKE)
 {
 #if defined(CONFIG_USER_ONLY)
     RET_PRIVOPC(ctx);
@@ -4523,14 +4580,28 @@ GEN_HANDLER(rfci, 0x13, 0x13, 0x01, 0x03FF8001, PPC_EMB_COMMON)
         return;
     }
     /* Restore CPU state */
-    gen_op_4xx_rfci();
+    gen_op_rfdi();
     RET_CHG_FLOW(ctx);
 #endif
 }
 
+GEN_HANDLER(rfmci, 0x13, 0x06, 0x01, 0x03FF8001, PPC_BOOKE)
+{
+#if defined(CONFIG_USER_ONLY)
+    RET_PRIVOPC(ctx);
+#else
+    if (unlikely(!ctx->supervisor)) {
+        RET_PRIVOPC(ctx);
+        return;
+    }
+    /* Restore CPU state */
+    gen_op_rfmci();
+    RET_CHG_FLOW(ctx);
+#endif
+}
 /* TLB management - PowerPC 405 implementation */
 /* tlbre */
-GEN_HANDLER(tlbre, 0x1F, 0x12, 0x1D, 0x00000001, PPC_EMB_COMMON)
+GEN_HANDLER(tlbre, 0x1F, 0x12, 0x1D, 0x00000001, PPC_40x_SPEC)
 {
 #if defined(CONFIG_USER_ONLY)
     RET_PRIVOPC(ctx);
@@ -4558,7 +4629,7 @@ GEN_HANDLER(tlbre, 0x1F, 0x12, 0x1D, 0x00000001, PPC_EMB_COMMON)
 }
 
 /* tlbsx - tlbsx. */
-GEN_HANDLER(tlbsx, 0x1F, 0x12, 0x1C, 0x00000000, PPC_EMB_COMMON)
+GEN_HANDLER(tlbsx, 0x1F, 0x12, 0x1C, 0x00000000, PPC_40x_SPEC)
 {
 #if defined(CONFIG_USER_ONLY)
     RET_PRIVOPC(ctx);
@@ -4615,7 +4686,7 @@ GEN_HANDLER(wrtee, 0x1F, 0x03, 0x04, 0x000FFC01, PPC_EMB_COMMON)
         return;
     }
     gen_op_load_gpr_T0(rD(ctx->opcode));
-    gen_op_4xx_wrte();
+    gen_op_wrte();
     RET_EXCP(ctx, EXCP_MTMSR, 0);
 #endif
 }
@@ -4631,7 +4702,7 @@ GEN_HANDLER(wrteei, 0x1F, 0x03, 0x05, 0x000EFC01, PPC_EMB_COMMON)
         return;
     }
     gen_op_set_T0(ctx->opcode & 0x00010000);
-    gen_op_4xx_wrte();
+    gen_op_wrte();
     RET_EXCP(ctx, EXCP_MTMSR, 0);
 #endif
 }