All of lore.kernel.org
 help / color / mirror / Atom feed
From: Thiemo Seufer <ths@networkno.de>
To: qemu-devel@nongnu.org
Subject: [Qemu-devel] [PATCH 6/8] Mips improvements
Date: Mon, 15 May 2006 02:34:36 +0100	[thread overview]
Message-ID: <20060515013436.GJ800@networkno.de> (raw)

Hello All,

this patch takes the mtc0 operations out of line. It does this even
for relatively large functions, a followup patch in this set moves
them back. I didn't change the presumably broken interrupt handling
in mtc0_status, since a) it doesn't fail for me, and b) it would
inflate the patch set even further.


Thiemo


Index: qemu-work/target-mips/exec.h
===================================================================
--- qemu-work.orig/target-mips/exec.h	2006-05-15 01:30:34.000000000 +0100
+++ qemu-work/target-mips/exec.h	2006-05-15 01:30:41.000000000 +0100
@@ -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-05-15 01:30:34.000000000 +0100
+++ qemu-work/target-mips/op.c	2006-05-15 01:30:41.000000000 +0100
@@ -714,12 +714,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-05-15 01:30:34.000000000 +0100
+++ qemu-work/target-mips/op_helper.c	2006-05-15 01:32:06.000000000 +0100
@@ -141,9 +141,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)
@@ -179,222 +194,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-05-15 01:30:34.000000000 +0100
+++ qemu-work/target-mips/translate.c	2006-05-15 01:30:41.000000000 +0100
@@ -1197,6 +1197,8 @@
         rn = "EntryLo0";
         break;
     case 3:
+//
+       /* also CONF */
         gen_op_mfc0_entrylo1();
         rn = "EntryLo1";
         break;
@@ -1212,6 +1214,10 @@
         gen_op_mfc0_wired();
         rn = "Wired";
         break;
+    case 7:
+//        gen_op_mfc0_info();
+        rn = "Info";
+        break;
     case 8:
         gen_op_mfc0_badvaddr();
         rn = "BadVaddr";
@@ -1271,6 +1277,19 @@
         gen_op_mfc0_watchhi();
         rn = "WatchHi";
         break;
+    case 20:
+       /* 64 bit only */
+//        gen_op_mfc0_xcontext();
+        rn = "XContext";
+        break;
+    case 21:
+//        gen_op_mfc0_framemask();
+        rn = "Framemask";
+        break;
+    case 22:
+//        gen_op_mfc0_diagnostic();
+        rn = "'Diagnostic";
+        break;
     case 23:
         gen_op_mfc0_debug();
         rn = "Debug";
@@ -1279,6 +1298,18 @@
         gen_op_mfc0_depc();
         rn = "DEPC";
         break;
+    case 25:
+//        gen_op_mfc0_performance();
+        rn = "Performance";
+        break;
+    case 26:
+//        gen_op_mfc0_ecc();
+        rn = "ECC";
+        break;
+    case 27:
+//        gen_op_mfc0_cacheerr();
+        rn = "CacheErr";
+        break;
     case 28:
         switch (sel) {
         case 0:
@@ -1294,6 +1325,10 @@
             goto die;
         }
         break;
+    case 29:
+//        gen_op_mfc0_taghi();
+        rn = "TagHi";
+        break;
     case 30:
         gen_op_mfc0_errorepc();
         rn = "ErrorEPC";
@@ -1324,6 +1359,183 @@
     generate_exception(ctx, EXCP_RI);
 }
 
+static void gen_mtc0 (DisasContext *ctx, int reg, int sel)
+{
+    const unsigned char *rn;
+    uint32_t val, old;
+
+    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 1:
+// ignore or except?
+        rn = "Random";
+        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 7:
+// ignore or except?
+        rn = "Info";
+        break;
+    case 8:
+// ignore or except?
+        rn = "BadVaddr";
+        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 15:
+// ignore or except?
+        rn = "PRid";
+        break;
+    case 16:
+        switch (sel) {
+        case 0:
+           gen_op_mtc0_config0();
+            rn = "Config0";
+            break;
+        default:
+            rn = "Invalid config selector";
+            goto die;
+        }
+        break;
+    case 17:
+// ignore or except?
+        rn = "LLaddr";
+        break;
+    case 18:
+        gen_op_mtc0_watchlo();
+        rn = "WatchLo";
+        break;
+    case 19:
+        gen_op_mtc0_watchhi();
+        rn = "WatchHi";
+        break;
+    case 20:
+       /* 64 bit only */
+//     gen_op_mtc0_xcontext();
+        rn = "XContext";
+        break;
+    case 21:
+//        gen_op_mtc0_framemask();
+        rn = "Framemask";
+       break;
+    case 22:
+// ignore or except?
+        rn = "Diagnostic";
+       break;
+    case 23:
+        gen_op_mtc0_debug();
+        rn = "Debug";
+        break;
+    case 24:
+        gen_op_mtc0_depc();
+        rn = "DEPC";
+        break;
+    case 25:
+// ignore or except?
+        rn = "Performance";
+       break;
+    case 26:
+// ignore or except?
+        rn = "ECC";
+       break;
+    case 27:
+// ignore or except?
+        rn = "CacheErr";
+       break;
+    case 28:
+        switch (sel) {
+        case 0:
+            gen_op_mtc0_taglo();
+            rn = "TagLo";
+            break;
+        default:
+            rn = "invalid sel";
+            goto die;
+        }
+        break;
+    case 29:
+//     gen_op_mtc0_taghi();
+        rn = "TagHi";
+       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 +1566,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";

                 reply	other threads:[~2006-05-15  1:34 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20060515013436.GJ800@networkno.de \
    --to=ths@networkno.de \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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.