All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH] Inline mfc0 instruction emulation
@ 2006-02-28 16:03 Thiemo Seufer
  0 siblings, 0 replies; only message in thread
From: Thiemo Seufer @ 2006-02-28 16:03 UTC (permalink / raw)
  To: qemu-devel

Hello All,

this patch inlines MIPS mfc0 instruction emulation into the TB.


Thiemo


Index: qemu-work/target-mips/exec.h
===================================================================
--- qemu-work.orig/target-mips/exec.h	2006-02-19 16:25:20.000000000 +0000
+++ qemu-work/target-mips/exec.h	2006-02-19 18:07:58.000000000 +0000
@@ -61,7 +61,8 @@
 #endif
 void do_mfc0_random(void);
 void do_mfc0_count(void);
-void do_mtc0(int reg, int sel);
+void do_mtc0_status_debug(uint32_t old, uint32_t val);
+void do_mtc0_status_irqraise_debug(void);
 void do_tlbwi (void);
 void do_tlbwr (void);
 void do_tlbp (void);
Index: qemu-work/target-mips/op.c
===================================================================
--- qemu-work.orig/target-mips/op.c	2006-02-19 16:25:20.000000000 +0000
+++ qemu-work/target-mips/op.c	2006-02-19 18:04:58.000000000 +0000
@@ -712,12 +712,189 @@
     RETURN();
 }
 
-void op_mtc0 (void)
+void op_mtc0_index (void)
 {
-    CALL_FROM_TB2(do_mtc0, PARAM1, PARAM2);
+    env->CP0_index = (env->CP0_index & 0x80000000) | (T0 & 0x0000000F);
     RETURN();
 }
 
+void op_mtc0_entrylo0 (void)
+{
+    env->CP0_EntryLo0 = T0 & 0x3FFFFFFF;
+    RETURN();
+}
+
+void op_mtc0_entrylo1 (void)
+{
+    env->CP0_EntryLo1 = T0 & 0x3FFFFFFF;
+    RETURN();
+}
+
+void op_mtc0_context (void)
+{
+    env->CP0_Context = (env->CP0_Context & 0xFF800000) | (T0 & 0x007FFFF0);
+    RETURN();
+}
+
+void op_mtc0_pagemask (void)
+{
+    env->CP0_PageMask = T0 & 0x01FFE000;
+    RETURN();
+}
+
+void op_mtc0_wired (void)
+{
+    env->CP0_Wired = T0 & 0x0000000F;
+    RETURN();
+}
+
+void op_mtc0_count (void)
+{
+    CALL_FROM_TB2(cpu_mips_store_count, env, T0);
+    RETURN();
+}
+
+void op_mtc0_entryhi (void)
+{
+    uint32_t old, val;
+
+    val = T0 & 0xFFFFE0FF;
+    old = env->CP0_EntryHi;
+    env->CP0_EntryHi = val;
+    /* If the ASID changes, flush qemu's TLB.  */
+    if ((old & 0xFF) != (val & 0xFF))
+        CALL_FROM_TB2(tlb_flush, env, 1);
+    RETURN();
+}
+
+void op_mtc0_compare (void)
+{
+    CALL_FROM_TB2(cpu_mips_store_compare, env, T0);
+    RETURN();
+}
+
+void op_mtc0_status (void)
+{
+    uint32_t val, old, mask;
+
+    val = T0 & 0xFA78FF01;
+    old = env->CP0_Status;
+    if (T0 & (1 << CP0St_UM))
+        env->hflags |= MIPS_HFLAG_UM;
+    else
+        env->hflags &= ~MIPS_HFLAG_UM;
+    if (T0 & (1 << CP0St_ERL))
+        env->hflags |= MIPS_HFLAG_ERL;
+    else
+        env->hflags &= ~MIPS_HFLAG_ERL;
+    if (T0 & (1 << CP0St_EXL))
+        env->hflags |= MIPS_HFLAG_EXL;
+    else
+        env->hflags &= ~MIPS_HFLAG_EXL;
+    env->CP0_Status = val;
+    /* If we unmasked an asserted IRQ, raise it */
+    mask = 0x0000FF00;
+    if (loglevel & CPU_LOG_TB_IN_ASM)
+	CALL_FROM_TB2(do_mtc0_status_debug, old, val);
+    if ((val & (1 << CP0St_IE)) && !(old & (1 << CP0St_IE)) &&
+        !(env->hflags & MIPS_HFLAG_EXL) &&
+        !(env->hflags & MIPS_HFLAG_ERL) &&
+        !(env->hflags & MIPS_HFLAG_DM) &&
+        (env->CP0_Status & env->CP0_Cause & mask)) {
+        env->interrupt_request |= CPU_INTERRUPT_HARD;
+	if (logfile)
+	    CALL_FROM_TB0(do_mtc0_status_irqraise_debug);
+    } else if (!(val & (1 << CP0St_IE)) && (old & (1 << CP0St_IE))) {
+        env->interrupt_request &= ~CPU_INTERRUPT_HARD;
+    }
+    RETURN();
+}
+
+void op_mtc0_cause (void)
+{
+    uint32_t val, old;
+
+    val = (env->CP0_Cause & 0xB000F87C) | (T0 & 0x000C00300);
+    old = env->CP0_Cause;
+    env->CP0_Cause = val;
+#if 0
+    {
+        int i, mask;
+
+	/* Check if we ever asserted a software IRQ */
+        for (i = 0; i < 2; i++) {
+            mask = 0x100 << i;
+            if ((val & mask) & !(old & mask))
+                CALL_FROM_TB1(mips_set_irq, i);
+        }
+    }
+#endif
+    RETURN();
+}
+
+void op_mtc0_epc (void)
+{
+    env->CP0_EPC = T0;
+    RETURN();
+}
+
+void op_mtc0_config0 (void)
+{
+#if defined(MIPS_USES_R4K_TLB)
+    env->CP0_Config0 = (env->CP0_Config0 & 0x8017FF80) | (T0 & 0x7E000001);
+#else
+    env->CP0_Config0 = (env->CP0_Config0 & 0xFE17FF80) | (T0 & 0x00000001);
+#endif
+    RETURN();
+}
+
+void op_mtc0_watchlo (void)
+{
+    env->CP0_WatchLo = T0;
+    RETURN();
+}
+
+void op_mtc0_watchhi (void)
+{
+    env->CP0_WatchHi = T0 & 0x40FF0FF8;
+    RETURN();
+}
+
+void op_mtc0_debug (void)
+{
+    env->CP0_Debug = (env->CP0_Debug & 0x8C03FC1F) | (T0 & 0x13300120);
+    if (T0 & (1 << CP0DB_DM))
+        env->hflags |= MIPS_HFLAG_DM;
+    else
+        env->hflags &= ~MIPS_HFLAG_DM;
+    RETURN();
+}
+
+void op_mtc0_depc (void)
+{
+    env->CP0_DEPC = T0;
+    RETURN();
+}
+
+void op_mtc0_taglo (void)
+{
+    env->CP0_TagLo = T0 & 0xFFFFFCF6;
+    RETURN();
+}
+
+void op_mtc0_errorepc (void)
+{
+    env->CP0_ErrorEPC = T0;
+    RETURN();
+}
+
+void op_mtc0_desave (void)
+{
+    env->CP0_DESAVE = T0;
+    RETURN();
+}
+
+
 #if defined(MIPS_USES_R4K_TLB)
 void op_tlbwi (void)
 {
Index: qemu-work/target-mips/op_helper.c
===================================================================
--- qemu-work.orig/target-mips/op_helper.c	2006-02-19 16:25:20.000000000 +0000
+++ qemu-work/target-mips/op_helper.c	2006-02-19 18:15:37.000000000 +0000
@@ -142,9 +142,24 @@
     cpu_abort(env, "mfc0 count\n");
 }
 
-void do_mtc0 (int reg, int sel)
+void cpu_mips_store_count(CPUState *env, uint32_t value)
 {
-    cpu_abort(env, "mtc0 reg=%d sel=%d\n", reg, sel);
+    cpu_abort(env, "mtc0 count\n");
+}
+
+void cpu_mips_store_compare(CPUState *env, uint32_t value)
+{
+    cpu_abort(env, "mtc0 compare\n");
+}
+
+void do_mtc0_status_debug(uint32_t old, uint32_t val)
+{
+    cpu_abort(env, "mtc0 status\n");
+}
+
+void do_mtc0_status_irqraise_debug(void)
+{
+    cpu_abort(env, "mtc0 status\n");
 }
 
 void do_tlbwi (void)
@@ -180,222 +195,17 @@
     T0 = cpu_mips_get_count(env);
 }
 
-void do_mtc0 (int reg, int sel)
+void do_mtc0_status_debug(uint32_t old, uint32_t val)
 {
-    const unsigned char *rn;
-    uint32_t val, old, mask;
+    const uint32_t mask = 0x0000FF00;
+    fprintf(logfile, "Status %08x => %08x Cause %08x (%08x %08x %08x)\n",
+            old, val, env->CP0_Cause, old & mask, val & mask,
+            env->CP0_Cause & mask);
+}
 
-    if (sel != 0 && reg != 16 && reg != 28) {
-        val = -1;
-        old = -1;
-        rn = "invalid";
-        goto print;
-    }
-    switch (reg) {
-    case 0:
-        val = (env->CP0_index & 0x80000000) | (T0 & 0x0000000F);
-        old = env->CP0_index;
-        env->CP0_index = val;
-        rn = "Index";
-        break;
-    case 2:
-        val = T0 & 0x3FFFFFFF;
-        old = env->CP0_EntryLo0;
-        env->CP0_EntryLo0 = val;
-        rn = "EntryLo0";
-        break;
-    case 3:
-        val = T0 & 0x3FFFFFFF;
-        old = env->CP0_EntryLo1;
-        env->CP0_EntryLo1 = val;
-        rn = "EntryLo1";
-        break;
-    case 4:
-        val = (env->CP0_Context & 0xFF800000) | (T0 & 0x007FFFF0);
-        old = env->CP0_Context;
-        env->CP0_Context = val;
-        rn = "Context";
-        break;
-    case 5:
-        val = T0 & 0x01FFE000;
-        old = env->CP0_PageMask;
-        env->CP0_PageMask = val;
-        rn = "PageMask";
-        break;
-    case 6:
-        val = T0 & 0x0000000F;
-        old = env->CP0_Wired;
-        env->CP0_Wired = val;
-        rn = "Wired";
-        break;
-    case 9:
-        val = T0;
-        old = cpu_mips_get_count(env);
-        cpu_mips_store_count(env, val);
-        rn = "Count";
-        break;
-    case 10:
-        val = T0 & 0xFFFFE0FF;
-        old = env->CP0_EntryHi;
-        env->CP0_EntryHi = val;
-	/* If the ASID changes, flush qemu's TLB.  */
-	if ((old & 0xFF) != (val & 0xFF))
-	  tlb_flush (env, 1);
-        rn = "EntryHi";
-        break;
-    case 11:
-        val = T0;
-        old = env->CP0_Compare;
-        cpu_mips_store_compare(env, val);
-        rn = "Compare";
-        break;
-    case 12:
-        val = T0 & 0xFA78FF01;
-        if (T0 & (1 << CP0St_UM))
-            env->hflags |= MIPS_HFLAG_UM;
-        else
-            env->hflags &= ~MIPS_HFLAG_UM;
-        if (T0 & (1 << CP0St_ERL))
-            env->hflags |= MIPS_HFLAG_ERL;
-        else
-            env->hflags &= ~MIPS_HFLAG_ERL;
-        if (T0 & (1 << CP0St_EXL))
-            env->hflags |= MIPS_HFLAG_EXL;
-        else
-            env->hflags &= ~MIPS_HFLAG_EXL;
-        old = env->CP0_Status;
-        env->CP0_Status = val;
-        /* If we unmasked an asserted IRQ, raise it */
-        mask = 0x0000FF00;
-        if (loglevel & CPU_LOG_TB_IN_ASM) {
-            fprintf(logfile, "Status %08x => %08x Cause %08x (%08x %08x %08x)\n",
-                    old, val, env->CP0_Cause, old & mask, val & mask,
-                    env->CP0_Cause & mask);
-        }
-        if ((val & (1 << CP0St_IE)) && !(old & (1 << CP0St_IE)) &&
-            !(env->hflags & MIPS_HFLAG_EXL) &&
-            !(env->hflags & MIPS_HFLAG_ERL) &&
-            !(env->hflags & MIPS_HFLAG_DM) &&
-            (env->CP0_Status & env->CP0_Cause & mask)) {
-            if (logfile)
-                fprintf(logfile, "Raise pending IRQs\n");
-            env->interrupt_request |= CPU_INTERRUPT_HARD;
-        } else if (!(val & (1 << CP0St_IE)) && (old & (1 << CP0St_IE))) {
-            env->interrupt_request &= ~CPU_INTERRUPT_HARD;
-        }
-        rn = "Status";
-        break;
-    case 13:
-        val = (env->CP0_Cause & 0xB000F87C) | (T0 & 0x000C00300);
-        old = env->CP0_Cause;
-        env->CP0_Cause = val;
-#if 0
-        {
-            int i;
-            /* Check if we ever asserted a software IRQ */
-            for (i = 0; i < 2; i++) {
-                mask = 0x100 << i;
-                if ((val & mask) & !(old & mask))
-                    mips_set_irq(i);
-            }
-        }
-#endif
-        rn = "Cause";
-        break;
-    case 14:
-        val = T0;
-        old = env->CP0_EPC;
-        env->CP0_EPC = val;
-        rn = "EPC";
-        break;
-    case 16:
-        switch (sel) {
-        case 0:
-#if defined(MIPS_USES_R4K_TLB)
-            val = (env->CP0_Config0 & 0x8017FF80) | (T0 & 0x7E000001);
-#else
-            val = (env->CP0_Config0 & 0xFE17FF80) | (T0 & 0x00000001);
-#endif
-            old = env->CP0_Config0;
-            env->CP0_Config0 = val;
-            rn = "Config0";
-            break;
-        default:
-            val = -1;
-            old = -1;
-            rn = "bad config selector";
-            break;
-        }
-        break;
-    case 18:
-        val = T0;
-        old = env->CP0_WatchLo;
-        env->CP0_WatchLo = val;
-        rn = "WatchLo";
-        break;
-    case 19:
-        val = T0 & 0x40FF0FF8;
-        old = env->CP0_WatchHi;
-        env->CP0_WatchHi = val;
-        rn = "WatchHi";
-        break;
-    case 23:
-        val = (env->CP0_Debug & 0x8C03FC1F) | (T0 & 0x13300120);
-        if (T0 & (1 << CP0DB_DM))
-            env->hflags |= MIPS_HFLAG_DM;
-        else
-            env->hflags &= ~MIPS_HFLAG_DM;
-        old = env->CP0_Debug;
-        env->CP0_Debug = val;
-        rn = "Debug";
-        break;
-    case 24:
-        val = T0;
-        old = env->CP0_DEPC;
-        env->CP0_DEPC = val;
-        rn = "DEPC";
-        break;
-    case 28:
-        switch (sel) {
-        case 0:
-            val = T0 & 0xFFFFFCF6;
-            old = env->CP0_TagLo;
-            env->CP0_TagLo = val;
-            rn = "TagLo";
-            break;
-        default:
-            val = -1;
-            old = -1;
-            rn = "invalid sel";
-            break;
-        }
-        break;
-    case 30:
-        val = T0;
-        old = env->CP0_ErrorEPC;
-        env->CP0_ErrorEPC = val;
-        rn = "EPC";
-        break;
-    case 31:
-        val = T0;
-        old = env->CP0_DESAVE;
-        env->CP0_DESAVE = val;
-        rn = "DESAVE";
-        break;
-    default:
-        val = -1;
-        old = -1;
-        rn = "unknown";
-        break;
-    }
- print:
-#if defined MIPS_DEBUG_DISAS
-    if (loglevel & CPU_LOG_TB_IN_ASM) {
-        fprintf(logfile, "%08x mtc0 %s %08x => %08x (%d %d %08x)\n",
-                env->PC, rn, T0, val, reg, sel, old);
-    }
-#endif
-    return;
+void do_mtc0_status_irqraise_debug(void)
+{
+    fprintf(logfile, "Raise pending IRQs\n");
 }
 
 /* TLB management */
Index: qemu-work/target-mips/translate.c
===================================================================
--- qemu-work.orig/target-mips/translate.c	2006-02-19 16:25:20.000000000 +0000
+++ qemu-work/target-mips/translate.c	2006-02-19 17:51:44.000000000 +0000
@@ -1324,6 +1324,134 @@
     generate_exception(ctx, EXCP_RI);
 }
 
+static void gen_mtc0 (DisasContext *ctx, int reg, int sel)
+{
+    const unsigned char *rn;
+    uint32_t val, old, mask;
+
+    if (sel != 0 && reg != 16 && reg != 28) {
+        val = -1;
+        old = -1;
+        rn = "invalid";
+        goto die;
+    }
+    switch (reg) {
+    case 0:
+        gen_op_mtc0_index();
+        rn = "Index";
+        break;
+    case 2:
+        gen_op_mtc0_entrylo0();
+        rn = "EntryLo0";
+        break;
+    case 3:
+        gen_op_mtc0_entrylo1();
+        rn = "EntryLo1";
+        break;
+    case 4:
+        gen_op_mtc0_context();
+        rn = "Context";
+        break;
+    case 5:
+        gen_op_mtc0_pagemask();
+        rn = "PageMask";
+        break;
+    case 6:
+        gen_op_mtc0_wired();
+        rn = "Wired";
+        break;
+    case 9:
+        gen_op_mtc0_count();
+        rn = "Count";
+        break;
+    case 10:
+        gen_op_mtc0_entryhi();
+        rn = "EntryHi";
+        break;
+    case 11:
+        gen_op_mtc0_compare();
+        rn = "Compare";
+        break;
+    case 12:
+        gen_op_mtc0_status();
+        rn = "Status";
+        break;
+    case 13:
+        gen_op_mtc0_cause();
+        rn = "Cause";
+        break;
+    case 14:
+        gen_op_mtc0_epc();
+        rn = "EPC";
+        break;
+    case 16:
+        switch (sel) {
+        case 0:
+	    gen_op_mtc0_config0();
+            rn = "Config0";
+            break;
+        default:
+            rn = "Invalid config selector";
+            goto die;
+        }
+        break;
+    case 18:
+        gen_op_mtc0_watchlo();
+        rn = "WatchLo";
+        break;
+    case 19:
+        gen_op_mtc0_watchhi();
+        rn = "WatchHi";
+        break;
+    case 23:
+        gen_op_mtc0_debug();
+        rn = "Debug";
+        break;
+    case 24:
+        gen_op_mtc0_depc();
+        rn = "DEPC";
+        break;
+    case 28:
+        switch (sel) {
+        case 0:
+            gen_op_mtc0_taglo();
+            rn = "TagLo";
+            break;
+        default:
+            rn = "invalid sel";
+            goto die;
+        }
+        break;
+    case 30:
+        gen_op_mtc0_errorepc();
+        rn = "ErrorEPC";
+        break;
+    case 31:
+        gen_op_mtc0_desave();
+        rn = "DESAVE";
+        break;
+    default:
+        rn = "unknown";
+	goto die;
+    }
+#if defined MIPS_DEBUG_DISAS
+    if (loglevel & CPU_LOG_TB_IN_ASM) {
+        fprintf(logfile, "%08x mtc0 %s => %08x (%d %d)\n",
+                env->PC, rn, T0, reg, sel);
+    }
+#endif
+    return;
+
+die:
+#if defined MIPS_DEBUG_DISAS
+    if (loglevel & CPU_LOG_TB_IN_ASM) {
+        fprintf(logfile, "%08x mtc0 %s => %08x (%d %d)\n",
+                env->PC, rn, T0, reg, sel);
+    }
+#endif
+    generate_exception(ctx, EXCP_RI);
+}
+
 static void gen_cp0 (DisasContext *ctx, uint16_t opc, int rt, int rd)
 {
     const unsigned char *opn = "unk";
@@ -1354,7 +1482,7 @@
         save_cpu_state(ctx, 1);
         ctx->pc -= 4;
         GEN_LOAD_REG_TN(T0, rt);
-        gen_op_mtc0(rd, ctx->opcode & 0x7);
+        gen_mtc0(ctx, rd, ctx->opcode & 0x7);
         /* Stop translation as we may have switched the execution mode */
         ctx->bstate = BS_STOP;
         opn = "mtc0";

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2006-03-02  6:17 UTC | newest]

Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-02-28 16:03 [Qemu-devel] [PATCH] Inline mfc0 instruction emulation Thiemo Seufer

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.