Implementing dmfc/dmtc.
authorths <ths@c046a42c-6fe2-441c-8c8c-71466251a162>
Tue, 23 Jan 2007 22:45:22 +0000 (22:45 +0000)
committerths <ths@c046a42c-6fe2-441c-8c8c-71466251a162>
Tue, 23 Jan 2007 22:45:22 +0000 (22:45 +0000)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2348 c046a42c-6fe2-441c-8c8c-71466251a162

target-mips/cpu.h
target-mips/op.c
target-mips/op_helper.c
target-mips/translate.c

index c1001c7..8781e30 100644 (file)
@@ -44,7 +44,7 @@ union fpr_t {
 typedef struct tlb_t tlb_t;
 struct tlb_t {
     target_ulong VPN;
-    uint_fast32_t PageMask;
+    uint32_t PageMask;
     uint_fast8_t ASID;
     uint_fast16_t G:1;
     uint_fast16_t C0:3;
@@ -110,20 +110,20 @@ struct CPUMIPSState {
     tlb_t tlb[MIPS_TLB_MAX];
     uint32_t tlb_in_use;
 #endif
-    uint32_t CP0_index;
-    uint32_t CP0_random;
-    uint64_t CP0_EntryLo0;
-    uint64_t CP0_EntryLo1;
-    uint64_t CP0_Context;
-    uint32_t CP0_PageMask;
-    uint32_t CP0_PageGrain;
-    uint32_t CP0_Wired;
-    uint32_t CP0_HWREna;
+    int32_t CP0_Index;
+    int32_t CP0_Random;
+    target_ulong CP0_EntryLo0;
+    target_ulong CP0_EntryLo1;
+    target_ulong CP0_Context;
+    int32_t CP0_PageMask;
+    int32_t CP0_PageGrain;
+    int32_t CP0_Wired;
+    int32_t CP0_HWREna;
     target_ulong CP0_BadVAddr;
-    uint32_t CP0_Count;
-    uint64_t CP0_EntryHi;
-    uint32_t CP0_Compare;
-    uint32_t CP0_Status;
+    int32_t CP0_Count;
+    target_ulong CP0_EntryHi;
+    int32_t CP0_Compare;
+    int32_t CP0_Status;
 #define CP0St_CU3   31
 #define CP0St_CU2   30
 #define CP0St_CU1   29
@@ -146,9 +146,10 @@ struct CPUMIPSState {
 #define CP0St_ERL   2
 #define CP0St_EXL   1
 #define CP0St_IE    0
-    uint32_t CP0_IntCtl;
-    uint32_t CP0_SRSCtl;
-    uint32_t CP0_Cause;
+    int32_t CP0_IntCtl;
+    int32_t CP0_SRSCtl;
+    int32_t CP0_SRSMap;
+    int32_t CP0_Cause;
 #define CP0Ca_BD   31
 #define CP0Ca_TI   30
 #define CP0Ca_CE   28
@@ -159,9 +160,9 @@ struct CPUMIPSState {
 #define CP0Ca_IP    8
 #define CP0Ca_EC    2
     target_ulong CP0_EPC;
-    uint32_t CP0_PRid;
+    int32_t CP0_PRid;
     target_ulong CP0_EBase;
-    uint32_t CP0_Config0;
+    int32_t CP0_Config0;
 #define CP0C0_M    31
 #define CP0C0_K23  28
 #define CP0C0_KU   25
@@ -174,7 +175,7 @@ struct CPUMIPSState {
 #define CP0C0_MT   7
 #define CP0C0_VI   3
 #define CP0C0_K0   0
-    uint32_t CP0_Config1;
+    int32_t CP0_Config1;
 #define CP0C1_M    31
 #define CP0C1_MMU  25
 #define CP0C1_IS   22
@@ -190,7 +191,7 @@ struct CPUMIPSState {
 #define CP0C1_CA   2
 #define CP0C1_EP   1
 #define CP0C1_FP   0
-    uint32_t CP0_Config2;
+    int32_t CP0_Config2;
 #define CP0C2_M    31
 #define CP0C2_TU   28
 #define CP0C2_TS   24
@@ -200,7 +201,7 @@ struct CPUMIPSState {
 #define CP0C2_SS   8
 #define CP0C2_SL   4
 #define CP0C2_SA   0
-    uint32_t CP0_Config3;
+    int32_t CP0_Config3;
 #define CP0C3_M    31
 #define CP0C3_DSPP 10
 #define CP0C3_LPA  7
@@ -211,11 +212,11 @@ struct CPUMIPSState {
 #define CP0C3_SM   1
 #define CP0C3_TL   0
     target_ulong CP0_LLAddr;
-    uint32_t CP0_WatchLo;
-    uint32_t CP0_WatchHi;
-    uint32_t CP0_XContext;
-    uint32_t CP0_Framemask;
-    uint32_t CP0_Debug;
+    target_ulong CP0_WatchLo;
+    int32_t CP0_WatchHi;
+    target_ulong CP0_XContext;
+    int32_t CP0_Framemask;
+    int32_t CP0_Debug;
 #define CPDB_DBD   31
 #define CP0DB_DM   30
 #define CP0DB_LSNM 28
@@ -235,13 +236,13 @@ struct CPUMIPSState {
 #define CP0DB_DBp  1
 #define CP0DB_DSS  0
     target_ulong CP0_DEPC;
-    uint32_t CP0_Performance0;
-    uint32_t CP0_TagLo;
-    uint32_t CP0_DataLo;
-    uint32_t CP0_TagHi;
-    uint32_t CP0_DataHi;
+    int32_t CP0_Performance0;
+    int32_t CP0_TagLo;
+    int32_t CP0_DataLo;
+    int32_t CP0_TagHi;
+    int32_t CP0_DataHi;
     target_ulong CP0_ErrorEPC;
-    uint32_t CP0_DESAVE;
+    int32_t CP0_DESAVE;
     /* Qemu */
     int interrupt_request;
     jmp_buf jmp_env;
index 0550d27..dec9f31 100644 (file)
@@ -1032,7 +1032,7 @@ void op_jnz_T2 (void)
 /* CP0 functions */
 void op_mfc0_index (void)
 {
-    T0 = (int32_t)(env->CP0_index);
+    T0 = env->CP0_Index;
     RETURN();
 }
 
@@ -1044,49 +1044,49 @@ void op_mfc0_random (void)
 
 void op_mfc0_entrylo0 (void)
 {
-    T0 = env->CP0_EntryLo0;
+    T0 = (int32_t)env->CP0_EntryLo0;
     RETURN();
 }
 
 void op_mfc0_entrylo1 (void)
 {
-    T0 = env->CP0_EntryLo1;
+    T0 = (int32_t)env->CP0_EntryLo1;
     RETURN();
 }
 
 void op_mfc0_context (void)
 {
-    T0 = env->CP0_Context;
+    T0 = (int32_t)env->CP0_Context;
     RETURN();
 }
 
 void op_mfc0_pagemask (void)
 {
-    T0 = (int32_t)env->CP0_PageMask;
+    T0 = env->CP0_PageMask;
     RETURN();
 }
 
 void op_mfc0_pagegrain (void)
 {
-    T0 = (int32_t)env->CP0_PageGrain;
+    T0 = env->CP0_PageGrain;
     RETURN();
 }
 
 void op_mfc0_wired (void)
 {
-    T0 = (int32_t)env->CP0_Wired;
+    T0 = env->CP0_Wired;
     RETURN();
 }
 
 void op_mfc0_hwrena (void)
 {
-    T0 = (int32_t)env->CP0_HWREna;
+    T0 = env->CP0_HWREna;
     RETURN();
 }
 
 void op_mfc0_badvaddr (void)
 {
-    T0 = env->CP0_BadVAddr;
+    T0 = (int32_t)env->CP0_BadVAddr;
     RETURN();
 }
 
@@ -1098,19 +1098,19 @@ void op_mfc0_count (void)
 
 void op_mfc0_entryhi (void)
 {
-    T0 = env->CP0_EntryHi;
+    T0 = (int32_t)env->CP0_EntryHi;
     RETURN();
 }
 
 void op_mfc0_compare (void)
 {
-    T0 = (int32_t)env->CP0_Compare;
+    T0 = env->CP0_Compare;
     RETURN();
 }
 
 void op_mfc0_status (void)
 {
-    T0 = (int32_t)env->CP0_Status;
+    T0 = env->CP0_Status;
     if (env->hflags & MIPS_HFLAG_UM)
         T0 |= (1 << CP0St_UM);
     if (env->hflags & MIPS_HFLAG_ERL)
@@ -1122,67 +1122,73 @@ void op_mfc0_status (void)
 
 void op_mfc0_intctl (void)
 {
-    T0 = (int32_t)env->CP0_IntCtl;
+    T0 = env->CP0_IntCtl;
     RETURN();
 }
 
 void op_mfc0_srsctl (void)
 {
-    T0 = (int32_t)env->CP0_SRSCtl;
+    T0 = env->CP0_SRSCtl;
+    RETURN();
+}
+
+void op_mfc0_srsmap (void)
+{
+    T0 = env->CP0_SRSMap;
     RETURN();
 }
 
 void op_mfc0_cause (void)
 {
-    T0 = (int32_t)env->CP0_Cause;
+    T0 = env->CP0_Cause;
     RETURN();
 }
 
 void op_mfc0_epc (void)
 {
-    T0 = env->CP0_EPC;
+    T0 = (int32_t)env->CP0_EPC;
     RETURN();
 }
 
 void op_mfc0_prid (void)
 {
-    T0 = (int32_t)env->CP0_PRid;
+    T0 = env->CP0_PRid;
     RETURN();
 }
 
 void op_mfc0_ebase (void)
 {
-    T0 = env->CP0_EBase;
+    T0 = (int32_t)env->CP0_EBase;
     RETURN();
 }
 
 void op_mfc0_config0 (void)
 {
-    T0 = (int32_t)env->CP0_Config0;
+    T0 = env->CP0_Config0;
     RETURN();
 }
 
 void op_mfc0_config1 (void)
 {
-    T0 = (int32_t)env->CP0_Config1;
+    T0 = env->CP0_Config1;
     RETURN();
 }
 
 void op_mfc0_config2 (void)
 {
-    T0 = (int32_t)env->CP0_Config2;
+    T0 = env->CP0_Config2;
     RETURN();
 }
 
 void op_mfc0_config3 (void)
 {
-    T0 = (int32_t)env->CP0_Config3;
+    T0 = env->CP0_Config3;
     RETURN();
 }
 
 void op_mfc0_lladdr (void)
 {
-    T0 = env->CP0_LLAddr >> 4;
+    T0 = (int32_t)env->CP0_LLAddr >> 4;
     RETURN();
 }
 
@@ -1194,13 +1200,13 @@ void op_mfc0_watchlo0 (void)
 
 void op_mfc0_watchhi0 (void)
 {
-    T0 = (int32_t)env->CP0_WatchHi;
+    T0 = env->CP0_WatchHi;
     RETURN();
 }
 
 void op_mfc0_xcontext (void)
 {
-    T0 = env->CP0_XContext;
+    T0 = (int32_t)env->CP0_XContext;
     RETURN();
 }
 
@@ -1212,7 +1218,7 @@ void op_mfc0_framemask (void)
 
 void op_mfc0_debug (void)
 {
-    T0 = (int32_t)env->CP0_Debug;
+    T0 = env->CP0_Debug;
     if (env->hflags & MIPS_HFLAG_DM)
         T0 |= 1 << CP0DB_DM;
     RETURN();
@@ -1220,55 +1226,55 @@ void op_mfc0_debug (void)
 
 void op_mfc0_depc (void)
 {
-    T0 = env->CP0_DEPC;
+    T0 = (int32_t)env->CP0_DEPC;
     RETURN();
 }
 
 void op_mfc0_performance0 (void)
 {
-    T0 = (int32_t)env->CP0_Performance0;
+    T0 = env->CP0_Performance0;
     RETURN();
 }
 
 void op_mfc0_taglo (void)
 {
-    T0 = (int32_t)env->CP0_TagLo;
+    T0 = env->CP0_TagLo;
     RETURN();
 }
 
 void op_mfc0_datalo (void)
 {
-    T0 = (int32_t)env->CP0_DataLo;
+    T0 = env->CP0_DataLo;
     RETURN();
 }
 
 void op_mfc0_taghi (void)
 {
-    T0 = (int32_t)env->CP0_TagHi;
+    T0 = env->CP0_TagHi;
     RETURN();
 }
 
 void op_mfc0_datahi (void)
 {
-    T0 = (int32_t)env->CP0_DataHi;
+    T0 = env->CP0_DataHi;
     RETURN();
 }
 
 void op_mfc0_errorepc (void)
 {
-    T0 = env->CP0_ErrorEPC;
+    T0 = (int32_t)env->CP0_ErrorEPC;
     RETURN();
 }
 
 void op_mfc0_desave (void)
 {
-    T0 = (int32_t)env->CP0_DESAVE;
+    T0 = env->CP0_DESAVE;
     RETURN();
 }
 
 void op_mtc0_index (void)
 {
-    env->CP0_index = (env->CP0_index & 0x80000000) | (T0 & (MIPS_TLB_NB - 1));
+    env->CP0_Index = (env->CP0_Index & 0x80000000) | (T0 & (MIPS_TLB_NB - 1));
     RETURN();
 }
 
@@ -1276,7 +1282,7 @@ void op_mtc0_entrylo0 (void)
 {
     /* Large physaddr not implemented */
     /* 1k pages not implemented */
-    env->CP0_EntryLo0 = T0 & (int32_t)0x3FFFFFFF;
+    env->CP0_EntryLo0 = (int32_t)T0 & 0x3FFFFFFF;
     RETURN();
 }
 
@@ -1284,7 +1290,7 @@ void op_mtc0_entrylo1 (void)
 {
     /* Large physaddr not implemented */
     /* 1k pages not implemented */
-    env->CP0_EntryLo1 = T0 & (int32_t)0x3FFFFFFF;
+    env->CP0_EntryLo1 = (int32_t)T0 & 0x3FFFFFFF;
     RETURN();
 }
 
@@ -1334,7 +1340,7 @@ void op_mtc0_entryhi (void)
 
     /* 1k pages not implemented */
     /* Ignore MIPS64 TLB for now */
-    val = T0 & (int32_t)0xFFFFE0FF;
+    val = (int32_t)T0 & 0xFFFFE0FF;
     old = env->CP0_EntryHi;
     env->CP0_EntryHi = val;
     /* If the ASID changes, flush qemu's TLB.  */
@@ -1353,7 +1359,7 @@ void op_mtc0_status (void)
 {
     uint32_t val, old, mask;
 
-    val = T0 & (int32_t)0xFA78FF01;
+    val = (int32_t)T0 & 0xFA78FF01;
     old = env->CP0_Status;
     if (T0 & (1 << CP0St_UM))
         env->hflags |= MIPS_HFLAG_UM;
@@ -1400,6 +1406,13 @@ void op_mtc0_srsctl (void)
     RETURN();
 }
 
+void op_mtc0_srsmap (void)
+{
+    /* shadow registers not implemented */
+    env->CP0_SRSMap = 0;
+    RETURN();
+}
+
 void op_mtc0_cause (void)
 {
     uint32_t val, old;
@@ -1423,7 +1436,7 @@ void op_mtc0_cause (void)
 
 void op_mtc0_epc (void)
 {
-    env->CP0_EPC = T0;
+    env->CP0_EPC = (int32_t)T0;
     RETURN();
 }
 
@@ -1455,7 +1468,7 @@ void op_mtc0_config2 (void)
 
 void op_mtc0_watchlo0 (void)
 {
-    env->CP0_WatchLo = T0;
+    env->CP0_WatchLo = (int32_t)T0;
     RETURN();
 }
 
@@ -1467,7 +1480,7 @@ void op_mtc0_watchhi0 (void)
 
 void op_mtc0_xcontext (void)
 {
-    env->CP0_XContext = T0; /* XXX */
+    env->CP0_XContext = (int32_t)T0; /* XXX */
     RETURN();
 }
 
@@ -1489,7 +1502,7 @@ void op_mtc0_debug (void)
 
 void op_mtc0_depc (void)
 {
-    env->CP0_DEPC = T0;
+    env->CP0_DEPC = (int32_t)T0;
     RETURN();
 }
 
@@ -1501,7 +1514,7 @@ void op_mtc0_performance0 (void)
 
 void op_mtc0_taglo (void)
 {
-    env->CP0_TagLo = T0 & (int32_t)0xFFFFFCF6;
+    env->CP0_TagLo = T0 & 0xFFFFFCF6;
     RETURN();
 }
 
@@ -1525,7 +1538,7 @@ void op_mtc0_datahi (void)
 
 void op_mtc0_errorepc (void)
 {
-    env->CP0_ErrorEPC = T0;
+    env->CP0_ErrorEPC = (int32_t)T0;
     RETURN();
 }
 
@@ -1535,6 +1548,139 @@ void op_mtc0_desave (void)
     RETURN();
 }
 
+void op_dmfc0_entrylo0 (void)
+{
+    T0 = env->CP0_EntryLo0;
+    RETURN();
+}
+
+void op_dmfc0_entrylo1 (void)
+{
+    T0 = env->CP0_EntryLo1;
+    RETURN();
+}
+
+void op_dmfc0_context (void)
+{
+    T0 = env->CP0_Context;
+    RETURN();
+}
+
+void op_dmfc0_badvaddr (void)
+{
+    T0 = env->CP0_BadVAddr;
+    RETURN();
+}
+
+void op_dmfc0_entryhi (void)
+{
+    T0 = env->CP0_EntryHi;
+    RETURN();
+}
+
+void op_dmfc0_epc (void)
+{
+    T0 = env->CP0_EPC;
+    RETURN();
+}
+
+void op_dmfc0_ebase (void)
+{
+    T0 = env->CP0_EBase;
+    RETURN();
+}
+
+void op_dmfc0_lladdr (void)
+{
+    T0 = env->CP0_LLAddr >> 4;
+    RETURN();
+}
+
+void op_dmfc0_watchlo0 (void)
+{
+    T0 = env->CP0_WatchLo;
+    RETURN();
+}
+
+void op_dmfc0_xcontext (void)
+{
+    T0 = env->CP0_XContext;
+    RETURN();
+}
+
+void op_dmfc0_depc (void)
+{
+    T0 = env->CP0_DEPC;
+    RETURN();
+}
+
+void op_dmfc0_errorepc (void)
+{
+    T0 = env->CP0_ErrorEPC;
+    RETURN();
+}
+
+void op_dmtc0_entrylo0 (void)
+{
+    /* Large physaddr not implemented */
+    /* 1k pages not implemented */
+    env->CP0_EntryLo0 = T0 & 0x3FFFFFFF;
+    RETURN();
+}
+
+void op_dmtc0_entrylo1 (void)
+{
+    /* Large physaddr not implemented */
+    /* 1k pages not implemented */
+    env->CP0_EntryLo1 = T0 & 0x3FFFFFFF;
+    RETURN();
+}
+
+void op_dmtc0_context (void)
+{
+    env->CP0_Context = (env->CP0_Context & ~0x007FFFFF) | (T0 & 0x007FFFF0);
+    RETURN();
+}
+
+void op_dmtc0_epc (void)
+{
+    env->CP0_EPC = T0;
+    RETURN();
+}
+
+void op_dmtc0_ebase (void)
+{
+    /* vectored interrupts not implemented */
+    /* Multi-CPU not implemented */
+    /* XXX: 64bit addressing broken */
+    env->CP0_EBase = (int32_t)0x80000000 | (T0 & 0x3FFFF000);
+    RETURN();
+}
+
+void op_dmtc0_watchlo0 (void)
+{
+    env->CP0_WatchLo = T0;
+    RETURN();
+}
+
+void op_dmtc0_xcontext (void)
+{
+    env->CP0_XContext = T0; /* XXX */
+    RETURN();
+}
+
+void op_dmtc0_depc (void)
+{
+    env->CP0_DEPC = T0;
+    RETURN();
+}
+
+void op_dmtc0_errorepc (void)
+{
+    env->CP0_ErrorEPC = T0;
+    RETURN();
+}
+
 #ifdef MIPS_USES_FPU
 
 #if 0
index 4326b66..bea5a90 100644 (file)
@@ -411,10 +411,10 @@ void do_tlbwi (void)
        that might be a further win.  */
     mips_tlb_flush_extra (env, MIPS_TLB_NB);
 
-    /* Wildly undefined effects for CP0_index containing a too high value and
+    /* Wildly undefined effects for CP0_Index containing a too high value and
        MIPS_TLB_NB not being a power of two.  But so does real silicon.  */
-    invalidate_tlb(env, env->CP0_index & (MIPS_TLB_NB - 1), 0);
-    fill_tlb(env->CP0_index & (MIPS_TLB_NB - 1));
+    invalidate_tlb(env, env->CP0_Index & (MIPS_TLB_NB - 1), 0);
+    fill_tlb(env->CP0_Index & (MIPS_TLB_NB - 1));
 }
 
 void do_tlbwr (void)
@@ -439,7 +439,7 @@ void do_tlbp (void)
         /* Check ASID, virtual page number & size */
         if ((tlb->G == 1 || tlb->ASID == ASID) && tlb->VPN == tag) {
             /* TLB match */
-            env->CP0_index = i;
+            env->CP0_Index = i;
             break;
         }
     }
@@ -455,7 +455,7 @@ void do_tlbp (void)
            }
        }
 
-        env->CP0_index |= 0x80000000;
+        env->CP0_Index |= 0x80000000;
     }
 }
 
@@ -465,7 +465,7 @@ void do_tlbr (void)
     uint8_t ASID;
 
     ASID = env->CP0_EntryHi & 0xFF;
-    tlb = &env->tlb[env->CP0_index & (MIPS_TLB_NB - 1)];
+    tlb = &env->tlb[env->CP0_Index & (MIPS_TLB_NB - 1)];
 
     /* If this will change the current ASID, flush qemu's TLB.  */
     if (ASID != tlb->ASID)
index a501a17..3cc8a55 100644 (file)
@@ -2827,6 +2827,1181 @@ die:
     generate_exception(ctx, EXCP_RI);
 }
 
+static void gen_dmfc0 (DisasContext *ctx, int reg, int sel)
+{
+    const char *rn = "invalid";
+
+    switch (reg) {
+    case 0:
+        switch (sel) {
+        case 0:
+           gen_op_mfc0_index();
+            rn = "Index";
+            break;
+        case 1:
+//         gen_op_dmfc0_mvpcontrol(); /* MT ASE */
+            rn = "MVPControl";
+//         break;
+        case 2:
+//         gen_op_dmfc0_mvpconf0(); /* MT ASE */
+            rn = "MVPConf0";
+//         break;
+        case 3:
+//         gen_op_dmfc0_mvpconf1(); /* MT ASE */
+            rn = "MVPConf1";
+//         break;
+        default:
+            goto die;
+        }
+        break;
+    case 1:
+        switch (sel) {
+        case 0:
+            gen_op_mfc0_random();
+            rn = "Random";
+           break;
+        case 1:
+//         gen_op_dmfc0_vpecontrol(); /* MT ASE */
+            rn = "VPEControl";
+//         break;
+        case 2:
+//         gen_op_dmfc0_vpeconf0(); /* MT ASE */
+            rn = "VPEConf0";
+//         break;
+        case 3:
+//         gen_op_dmfc0_vpeconf1(); /* MT ASE */
+            rn = "VPEConf1";
+//         break;
+        case 4:
+//         gen_op_dmfc0_YQMask(); /* MT ASE */
+            rn = "YQMask";
+//         break;
+        case 5:
+//         gen_op_dmfc0_vpeschedule(); /* MT ASE */
+            rn = "VPESchedule";
+//         break;
+        case 6:
+//         gen_op_dmfc0_vpeschefback(); /* MT ASE */
+            rn = "VPEScheFBack";
+//         break;
+        case 7:
+//         gen_op_dmfc0_vpeopt(); /* MT ASE */
+            rn = "VPEOpt";
+//         break;
+        default:
+            goto die;
+        }
+        break;
+    case 2:
+        switch (sel) {
+        case 0:
+           gen_op_dmfc0_entrylo0();
+           rn = "EntryLo0";
+           break;
+        case 1:
+//         gen_op_dmfc0_tcstatus(); /* MT ASE */
+           rn = "TCStatus";
+//         break;
+        case 2:
+//         gen_op_dmfc0_tcbind(); /* MT ASE */
+           rn = "TCBind";
+//         break;
+        case 3:
+//         gen_op_dmfc0_tcrestart(); /* MT ASE */
+           rn = "TCRestart";
+//         break;
+        case 4:
+//         gen_op_dmfc0_tchalt(); /* MT ASE */
+           rn = "TCHalt";
+//         break;
+        case 5:
+//         gen_op_dmfc0_tccontext(); /* MT ASE */
+           rn = "TCContext";
+//         break;
+        case 6:
+//         gen_op_dmfc0_tcschedule(); /* MT ASE */
+           rn = "TCSchedule";
+//         break;
+        case 7:
+//         gen_op_dmfc0_tcschefback(); /* MT ASE */
+           rn = "TCScheFBack";
+//         break;
+        default:
+            goto die;
+        }
+        break;
+    case 3:
+        switch (sel) {
+        case 0:
+           gen_op_dmfc0_entrylo1();
+           rn = "EntryLo1";
+           break;
+        default:
+            goto die;
+       }
+        break;
+    case 4:
+        switch (sel) {
+        case 0:
+           gen_op_dmfc0_context();
+           rn = "Context";
+           break;
+        case 1:
+//         gen_op_dmfc0_contextconfig(); /* SmartMIPS ASE */
+           rn = "ContextConfig";
+//         break;
+        default:
+            goto die;
+       }
+        break;
+    case 5:
+        switch (sel) {
+        case 0:
+           gen_op_mfc0_pagemask();
+           rn = "PageMask";
+           break;
+        case 1:
+           gen_op_mfc0_pagegrain();
+           rn = "PageGrain";
+           break;
+        default:
+            goto die;
+       }
+        break;
+    case 6:
+        switch (sel) {
+        case 0:
+           gen_op_mfc0_wired();
+           rn = "Wired";
+           break;
+        case 1:
+//         gen_op_dmfc0_srsconf0(); /* shadow registers */
+           rn = "SRSConf0";
+//         break;
+        case 2:
+//         gen_op_dmfc0_srsconf1(); /* shadow registers */
+           rn = "SRSConf1";
+//         break;
+        case 3:
+//         gen_op_dmfc0_srsconf2(); /* shadow registers */
+           rn = "SRSConf2";
+//         break;
+        case 4:
+//         gen_op_dmfc0_srsconf3(); /* shadow registers */
+           rn = "SRSConf3";
+//         break;
+        case 5:
+//         gen_op_dmfc0_srsconf4(); /* shadow registers */
+           rn = "SRSConf4";
+//         break;
+        default:
+            goto die;
+       }
+        break;
+    case 7:
+        switch (sel) {
+        case 0:
+           gen_op_mfc0_hwrena();
+           rn = "HWREna";
+           break;
+        default:
+            goto die;
+       }
+        break;
+    case 8:
+        switch (sel) {
+        case 0:
+           gen_op_dmfc0_badvaddr();
+           rn = "BadVaddr";
+           break;
+        default:
+            goto die;
+       }
+        break;
+    case 9:
+        switch (sel) {
+        case 0:
+           gen_op_mfc0_count();
+           rn = "Count";
+           break;
+       /* 6,7 are implementation dependent */
+        default:
+            goto die;
+       }
+        break;
+    case 10:
+        switch (sel) {
+        case 0:
+           gen_op_dmfc0_entryhi();
+           rn = "EntryHi";
+           break;
+        default:
+            goto die;
+       }
+        break;
+    case 11:
+        switch (sel) {
+        case 0:
+           gen_op_mfc0_compare();
+           rn = "Compare";
+           break;
+       /* 6,7 are implementation dependent */
+        default:
+            goto die;
+       }
+        break;
+    case 12:
+        switch (sel) {
+        case 0:
+           gen_op_mfc0_status();
+           rn = "Status";
+           break;
+        case 1:
+           gen_op_mfc0_intctl();
+           rn = "IntCtl";
+           break;
+        case 2:
+           gen_op_mfc0_srsctl();
+           rn = "SRSCtl";
+           break;
+        case 3:
+           gen_op_mfc0_srsmap(); /* shadow registers */
+           rn = "SRSMap";
+           break;
+        default:
+            goto die;
+       }
+        break;
+    case 13:
+        switch (sel) {
+        case 0:
+           gen_op_mfc0_cause();
+           rn = "Cause";
+           break;
+        default:
+            goto die;
+       }
+        break;
+    case 14:
+        switch (sel) {
+        case 0:
+           gen_op_dmfc0_epc();
+           rn = "EPC";
+           break;
+        default:
+            goto die;
+       }
+        break;
+    case 15:
+        switch (sel) {
+        case 0:
+           gen_op_mfc0_prid();
+           rn = "PRid";
+           break;
+        case 1:
+           gen_op_dmfc0_ebase();
+           rn = "EBase";
+           break;
+        default:
+            goto die;
+       }
+        break;
+    case 16:
+        switch (sel) {
+        case 0:
+           gen_op_mfc0_config0();
+            rn = "Config";
+            break;
+        case 1:
+           gen_op_mfc0_config1();
+            rn = "Config1";
+            break;
+        case 2:
+           gen_op_mfc0_config2();
+            rn = "Config2";
+            break;
+        case 3:
+           gen_op_mfc0_config3();
+            rn = "Config3";
+            break;
+       /* 6,7 are implementation dependent */
+        default:
+            goto die;
+        }
+        break;
+    case 17:
+        switch (sel) {
+        case 0:
+           gen_op_dmfc0_lladdr();
+           rn = "LLAddr";
+           break;
+        default:
+            goto die;
+        }
+        break;
+    case 18:
+        switch (sel) {
+        case 0:
+           gen_op_dmfc0_watchlo0();
+           rn = "WatchLo";
+           break;
+        case 1:
+//         gen_op_dmfc0_watchlo1();
+           rn = "WatchLo1";
+//         break;
+        case 2:
+//         gen_op_dmfc0_watchlo2();
+           rn = "WatchLo2";
+//         break;
+        case 3:
+//         gen_op_dmfc0_watchlo3();
+           rn = "WatchLo3";
+//         break;
+        case 4:
+//         gen_op_dmfc0_watchlo4();
+           rn = "WatchLo4";
+//         break;
+        case 5:
+//         gen_op_dmfc0_watchlo5();
+           rn = "WatchLo5";
+//         break;
+        case 6:
+//         gen_op_dmfc0_watchlo6();
+           rn = "WatchLo6";
+//         break;
+        case 7:
+//         gen_op_dmfc0_watchlo7();
+           rn = "WatchLo7";
+//         break;
+        default:
+            goto die;
+        }
+        break;
+    case 19:
+        switch (sel) {
+        case 0:
+           gen_op_mfc0_watchhi0();
+           rn = "WatchHi";
+           break;
+        case 1:
+//         gen_op_mfc0_watchhi1();
+           rn = "WatchHi1";
+//         break;
+        case 2:
+//         gen_op_mfc0_watchhi2();
+           rn = "WatchHi2";
+//         break;
+        case 3:
+//         gen_op_mfc0_watchhi3();
+           rn = "WatchHi3";
+//         break;
+        case 4:
+//         gen_op_mfc0_watchhi4();
+           rn = "WatchHi4";
+//         break;
+        case 5:
+//         gen_op_mfc0_watchhi5();
+           rn = "WatchHi5";
+//         break;
+        case 6:
+//         gen_op_mfc0_watchhi6();
+           rn = "WatchHi6";
+//         break;
+        case 7:
+//         gen_op_mfc0_watchhi7();
+           rn = "WatchHi7";
+//         break;
+        default:
+            goto die;
+        }
+        break;
+    case 20:
+        switch (sel) {
+        case 0:
+           /* 64 bit MMU only */
+           gen_op_dmfc0_xcontext();
+           rn = "XContext";
+           break;
+        default:
+            goto die;
+        }
+        break;
+    case 21:
+       /* Officially reserved, but sel 0 is used for R1x000 framemask */
+        switch (sel) {
+        case 0:
+           gen_op_mfc0_framemask();
+           rn = "Framemask";
+           break;
+        default:
+            goto die;
+        }
+        break;
+    case 22:
+       /* ignored */
+       rn = "'Diagnostic"; /* implementation dependent */
+       break;
+    case 23:
+        switch (sel) {
+        case 0:
+           gen_op_mfc0_debug(); /* EJTAG support */
+           rn = "Debug";
+           break;
+        case 1:
+//         gen_op_dmfc0_tracecontrol(); /* PDtrace support */
+           rn = "TraceControl";
+//         break;
+        case 2:
+//         gen_op_dmfc0_tracecontrol2(); /* PDtrace support */
+           rn = "TraceControl2";
+//         break;
+        case 3:
+//         gen_op_dmfc0_usertracedata(); /* PDtrace support */
+           rn = "UserTraceData";
+//         break;
+        case 4:
+//         gen_op_dmfc0_debug(); /* PDtrace support */
+           rn = "TraceBPC";
+//         break;
+        default:
+            goto die;
+        }
+        break;
+    case 24:
+        switch (sel) {
+        case 0:
+           gen_op_dmfc0_depc(); /* EJTAG support */
+           rn = "DEPC";
+           break;
+        default:
+            goto die;
+        }
+        break;
+    case 25:
+        switch (sel) {
+        case 0:
+           gen_op_mfc0_performance0();
+           rn = "Performance0";
+            break;
+        case 1:
+//         gen_op_dmfc0_performance1();
+           rn = "Performance1";
+//         break;
+        case 2:
+//         gen_op_dmfc0_performance2();
+           rn = "Performance2";
+//         break;
+        case 3:
+//         gen_op_dmfc0_performance3();
+           rn = "Performance3";
+//         break;
+        case 4:
+//         gen_op_dmfc0_performance4();
+           rn = "Performance4";
+//         break;
+        case 5:
+//         gen_op_dmfc0_performance5();
+           rn = "Performance5";
+//         break;
+        case 6:
+//         gen_op_dmfc0_performance6();
+           rn = "Performance6";
+//         break;
+        case 7:
+//         gen_op_dmfc0_performance7();
+           rn = "Performance7";
+//         break;
+        default:
+            goto die;
+        }
+        break;
+    case 26:
+       rn = "ECC";
+       break;
+    case 27:
+        switch (sel) {
+        /* ignored */
+        case 0 ... 3:
+           rn = "CacheErr";
+           break;
+        default:
+            goto die;
+        }
+        break;
+    case 28:
+        switch (sel) {
+        case 0:
+        case 2:
+        case 4:
+        case 6:
+            gen_op_mfc0_taglo();
+            rn = "TagLo";
+            break;
+        case 1:
+        case 3:
+        case 5:
+        case 7:
+            gen_op_mfc0_datalo();
+            rn = "DataLo";
+            break;
+        default:
+            goto die;
+        }
+        break;
+    case 29:
+        switch (sel) {
+        case 0:
+        case 2:
+        case 4:
+        case 6:
+            gen_op_mfc0_taghi();
+            rn = "TagHi";
+            break;
+        case 1:
+        case 3:
+        case 5:
+        case 7:
+            gen_op_mfc0_datahi();
+            rn = "DataHi";
+            break;
+        default:
+            goto die;
+        }
+        break;
+    case 30:
+        switch (sel) {
+        case 0:
+           gen_op_dmfc0_errorepc();
+           rn = "ErrorEPC";
+           break;
+        default:
+            goto die;
+        }
+        break;
+    case 31:
+        switch (sel) {
+        case 0:
+           gen_op_mfc0_desave(); /* EJTAG support */
+           rn = "DESAVE";
+           break;
+        default:
+            goto die;
+        }
+        break;
+    default:
+       goto die;
+    }
+#if defined MIPS_DEBUG_DISAS
+    if (loglevel & CPU_LOG_TB_IN_ASM) {
+        fprintf(logfile, "dmfc0 %s (reg %d sel %d)\n",
+                rn, reg, sel);
+    }
+#endif
+    return;
+
+die:
+#if defined MIPS_DEBUG_DISAS
+    if (loglevel & CPU_LOG_TB_IN_ASM) {
+        fprintf(logfile, "dmfc0 %s (reg %d sel %d)\n",
+                rn, reg, sel);
+    }
+#endif
+    generate_exception(ctx, EXCP_RI);
+}
+
+static void gen_dmtc0 (DisasContext *ctx, int reg, int sel)
+{
+    const char *rn = "invalid";
+
+    switch (reg) {
+    case 0:
+        switch (sel) {
+        case 0:
+            gen_op_mtc0_index();
+            rn = "Index";
+            break;
+        case 1:
+//         gen_op_dmtc0_mvpcontrol(); /* MT ASE */
+            rn = "MVPControl";
+//         break;
+        case 2:
+//         gen_op_dmtc0_mvpconf0(); /* MT ASE */
+            rn = "MVPConf0";
+//         break;
+        case 3:
+//         gen_op_dmtc0_mvpconf1(); /* MT ASE */
+            rn = "MVPConf1";
+//         break;
+        default:
+            goto die;
+        }
+        break;
+    case 1:
+        switch (sel) {
+        case 0:
+           /* ignored */
+            rn = "Random";
+           break;
+        case 1:
+//         gen_op_dmtc0_vpecontrol(); /* MT ASE */
+            rn = "VPEControl";
+//         break;
+        case 2:
+//         gen_op_dmtc0_vpeconf0(); /* MT ASE */
+            rn = "VPEConf0";
+//         break;
+        case 3:
+//         gen_op_dmtc0_vpeconf1(); /* MT ASE */
+            rn = "VPEConf1";
+//         break;
+        case 4:
+//         gen_op_dmtc0_YQMask(); /* MT ASE */
+            rn = "YQMask";
+//         break;
+        case 5:
+//         gen_op_dmtc0_vpeschedule(); /* MT ASE */
+            rn = "VPESchedule";
+//         break;
+        case 6:
+//         gen_op_dmtc0_vpeschefback(); /* MT ASE */
+            rn = "VPEScheFBack";
+//         break;
+        case 7:
+//         gen_op_dmtc0_vpeopt(); /* MT ASE */
+            rn = "VPEOpt";
+//         break;
+        default:
+            goto die;
+        }
+        break;
+    case 2:
+        switch (sel) {
+        case 0:
+           gen_op_dmtc0_entrylo0();
+           rn = "EntryLo0";
+           break;
+        case 1:
+//         gen_op_dmtc0_tcstatus(); /* MT ASE */
+           rn = "TCStatus";
+//         break;
+        case 2:
+//         gen_op_dmtc0_tcbind(); /* MT ASE */
+           rn = "TCBind";
+//         break;
+        case 3:
+//         gen_op_dmtc0_tcrestart(); /* MT ASE */
+           rn = "TCRestart";
+//         break;
+        case 4:
+//         gen_op_dmtc0_tchalt(); /* MT ASE */
+           rn = "TCHalt";
+//         break;
+        case 5:
+//         gen_op_dmtc0_tccontext(); /* MT ASE */
+           rn = "TCContext";
+//         break;
+        case 6:
+//         gen_op_dmtc0_tcschedule(); /* MT ASE */
+           rn = "TCSchedule";
+//         break;
+        case 7:
+//         gen_op_dmtc0_tcschefback(); /* MT ASE */
+           rn = "TCScheFBack";
+//         break;
+        default:
+            goto die;
+        }
+        break;
+    case 3:
+        switch (sel) {
+        case 0:
+           gen_op_dmtc0_entrylo1();
+           rn = "EntryLo1";
+           break;
+        default:
+            goto die;
+       }
+        break;
+    case 4:
+        switch (sel) {
+        case 0:
+           gen_op_dmtc0_context();
+           rn = "Context";
+           break;
+        case 1:
+//         gen_op_dmtc0_contextconfig(); /* SmartMIPS ASE */
+           rn = "ContextConfig";
+//         break;
+        default:
+            goto die;
+       }
+        break;
+    case 5:
+        switch (sel) {
+        case 0:
+           gen_op_mtc0_pagemask();
+           rn = "PageMask";
+           break;
+        case 1:
+           gen_op_mtc0_pagegrain();
+           rn = "PageGrain";
+           break;
+        default:
+            goto die;
+       }
+        break;
+    case 6:
+        switch (sel) {
+        case 0:
+           gen_op_mtc0_wired();
+           rn = "Wired";
+           break;
+        case 1:
+//         gen_op_dmtc0_srsconf0(); /* shadow registers */
+           rn = "SRSConf0";
+//         break;
+        case 2:
+//         gen_op_dmtc0_srsconf1(); /* shadow registers */
+           rn = "SRSConf1";
+//         break;
+        case 3:
+//         gen_op_dmtc0_srsconf2(); /* shadow registers */
+           rn = "SRSConf2";
+//         break;
+        case 4:
+//         gen_op_dmtc0_srsconf3(); /* shadow registers */
+           rn = "SRSConf3";
+//         break;
+        case 5:
+//         gen_op_dmtc0_srsconf4(); /* shadow registers */
+           rn = "SRSConf4";
+//         break;
+        default:
+            goto die;
+       }
+        break;
+    case 7:
+        switch (sel) {
+        case 0:
+           gen_op_mtc0_hwrena();
+           rn = "HWREna";
+           break;
+        default:
+            goto die;
+       }
+        break;
+    case 8:
+        /* ignored */
+        rn = "BadVaddr";
+        break;
+    case 9:
+        switch (sel) {
+        case 0:
+           gen_op_mtc0_count();
+           rn = "Count";
+           break;
+       /* 6,7 are implementation dependent */
+        default:
+            goto die;
+       }
+       /* Stop translation as we may have switched the execution mode */
+       ctx->bstate = BS_STOP;
+        break;
+    case 10:
+        switch (sel) {
+        case 0:
+           gen_op_mtc0_entryhi();
+           rn = "EntryHi";
+           break;
+        default:
+            goto die;
+       }
+        break;
+    case 11:
+        switch (sel) {
+        case 0:
+           gen_op_mtc0_compare();
+           rn = "Compare";
+           break;
+       /* 6,7 are implementation dependent */
+        default:
+            goto die;
+       }
+       /* Stop translation as we may have switched the execution mode */
+       ctx->bstate = BS_STOP;
+        break;
+    case 12:
+        switch (sel) {
+        case 0:
+           gen_op_mtc0_status();
+           rn = "Status";
+           break;
+        case 1:
+           gen_op_mtc0_intctl();
+           rn = "IntCtl";
+           break;
+        case 2:
+           gen_op_mtc0_srsctl();
+           rn = "SRSCtl";
+           break;
+        case 3:
+         gen_op_mtc0_srsmap(); /* shadow registers */
+           rn = "SRSMap";
+         break;
+        default:
+            goto die;
+       }
+       /* Stop translation as we may have switched the execution mode */
+       ctx->bstate = BS_STOP;
+        break;
+    case 13:
+        switch (sel) {
+        case 0:
+           gen_op_mtc0_cause();
+           rn = "Cause";
+           break;
+        default:
+            goto die;
+       }
+       /* Stop translation as we may have switched the execution mode */
+       ctx->bstate = BS_STOP;
+        break;
+    case 14:
+        switch (sel) {
+        case 0:
+           gen_op_dmtc0_epc();
+           rn = "EPC";
+           break;
+        default:
+            goto die;
+       }
+        break;
+    case 15:
+        switch (sel) {
+        case 0:
+           /* ignored */
+           rn = "PRid";
+           break;
+        case 1:
+           gen_op_dmtc0_ebase();
+           rn = "EBase";
+           break;
+        default:
+            goto die;
+       }
+        break;
+    case 16:
+        switch (sel) {
+        case 0:
+            gen_op_mtc0_config0();
+            rn = "Config";
+            break;
+        case 1:
+           /* ignored */
+            rn = "Config1";
+            break;
+        case 2:
+            gen_op_mtc0_config2();
+            rn = "Config2";
+            break;
+        case 3:
+           /* ignored */
+            rn = "Config3";
+            break;
+        /* 6,7 are implementation dependent */
+        default:
+            rn = "Invalid config selector";
+            goto die;
+        }
+        /* Stop translation as we may have switched the execution mode */
+        ctx->bstate = BS_STOP;
+        break;
+    case 17:
+        switch (sel) {
+        case 0:
+           /* ignored */
+           rn = "LLAddr";
+           break;
+        default:
+            goto die;
+        }
+        break;
+    case 18:
+        switch (sel) {
+        case 0:
+           gen_op_dmtc0_watchlo0();
+           rn = "WatchLo";
+           break;
+        case 1:
+//         gen_op_dmtc0_watchlo1();
+           rn = "WatchLo1";
+//         break;
+        case 2:
+//         gen_op_dmtc0_watchlo2();
+           rn = "WatchLo2";
+//         break;
+        case 3:
+//         gen_op_dmtc0_watchlo3();
+           rn = "WatchLo3";
+//         break;
+        case 4:
+//         gen_op_dmtc0_watchlo4();
+           rn = "WatchLo4";
+//         break;
+        case 5:
+//         gen_op_dmtc0_watchlo5();
+           rn = "WatchLo5";
+//         break;
+        case 6:
+//         gen_op_dmtc0_watchlo6();
+           rn = "WatchLo6";
+//         break;
+        case 7:
+//         gen_op_dmtc0_watchlo7();
+           rn = "WatchLo7";
+//         break;
+        default:
+            goto die;
+        }
+        break;
+    case 19:
+        switch (sel) {
+        case 0:
+           gen_op_mtc0_watchhi0();
+           rn = "WatchHi";
+           break;
+        case 1:
+//         gen_op_dmtc0_watchhi1();
+           rn = "WatchHi1";
+//         break;
+        case 2:
+//         gen_op_dmtc0_watchhi2();
+           rn = "WatchHi2";
+//         break;
+        case 3:
+//         gen_op_dmtc0_watchhi3();
+           rn = "WatchHi3";
+//         break;
+        case 4:
+//         gen_op_dmtc0_watchhi4();
+           rn = "WatchHi4";
+//         break;
+        case 5:
+//         gen_op_dmtc0_watchhi5();
+           rn = "WatchHi5";
+//         break;
+        case 6:
+//         gen_op_dmtc0_watchhi6();
+           rn = "WatchHi6";
+//         break;
+        case 7:
+//         gen_op_dmtc0_watchhi7();
+           rn = "WatchHi7";
+//         break;
+        default:
+            goto die;
+        }
+        break;
+    case 20:
+        switch (sel) {
+        case 0:
+           /* 64 bit MMU only */
+           gen_op_dmtc0_xcontext();
+           rn = "XContext";
+           break;
+        default:
+            goto die;
+        }
+        break;
+    case 21:
+       /* Officially reserved, but sel 0 is used for R1x000 framemask */
+        switch (sel) {
+        case 0:
+           gen_op_mtc0_framemask();
+           rn = "Framemask";
+           break;
+        default:
+            goto die;
+        }
+        break;
+    case 22:
+        /* ignored */
+        rn = "Diagnostic"; /* implementation dependent */
+       break;
+    case 23:
+        switch (sel) {
+        case 0:
+           gen_op_mtc0_debug(); /* EJTAG support */
+           rn = "Debug";
+           break;
+        case 1:
+//         gen_op_dmtc0_tracecontrol(); /* PDtrace support */
+           rn = "TraceControl";
+//         break;
+        case 2:
+//         gen_op_dmtc0_tracecontrol2(); /* PDtrace support */
+           rn = "TraceControl2";
+//         break;
+        case 3:
+//         gen_op_dmtc0_usertracedata(); /* PDtrace support */
+           rn = "UserTraceData";
+//         break;
+        case 4:
+//         gen_op_dmtc0_debug(); /* PDtrace support */
+           rn = "TraceBPC";
+//         break;
+        default:
+            goto die;
+        }
+       /* Stop translation as we may have switched the execution mode */
+       ctx->bstate = BS_STOP;
+        break;
+    case 24:
+        switch (sel) {
+        case 0:
+           gen_op_dmtc0_depc(); /* EJTAG support */
+           rn = "DEPC";
+           break;
+        default:
+            goto die;
+        }
+        break;
+    case 25:
+        switch (sel) {
+        case 0:
+           gen_op_mtc0_performance0();
+           rn = "Performance0";
+           break;
+        case 1:
+//         gen_op_dmtc0_performance1();
+           rn = "Performance1";
+//         break;
+        case 2:
+//         gen_op_dmtc0_performance2();
+           rn = "Performance2";
+//         break;
+        case 3:
+//         gen_op_dmtc0_performance3();
+           rn = "Performance3";
+//         break;
+        case 4:
+//         gen_op_dmtc0_performance4();
+           rn = "Performance4";
+//         break;
+        case 5:
+//         gen_op_dmtc0_performance5();
+           rn = "Performance5";
+//         break;
+        case 6:
+//         gen_op_dmtc0_performance6();
+           rn = "Performance6";
+//         break;
+        case 7:
+//         gen_op_dmtc0_performance7();
+           rn = "Performance7";
+//         break;
+        default:
+            goto die;
+        }
+       break;
+    case 26:
+       /* ignored */
+        rn = "ECC";
+       break;
+    case 27:
+        switch (sel) {
+        case 0 ... 3:
+           /* ignored */
+           rn = "CacheErr";
+           break;
+        default:
+            goto die;
+        }
+       break;
+    case 28:
+        switch (sel) {
+        case 0:
+        case 2:
+        case 4:
+        case 6:
+            gen_op_mtc0_taglo();
+            rn = "TagLo";
+            break;
+        case 1:
+        case 3:
+        case 5:
+        case 7:
+           gen_op_mtc0_datalo();
+            rn = "DataLo";
+            break;
+        default:
+            goto die;
+        }
+        break;
+    case 29:
+        switch (sel) {
+        case 0:
+        case 2:
+        case 4:
+        case 6:
+            gen_op_mtc0_taghi();
+            rn = "TagHi";
+            break;
+        case 1:
+        case 3:
+        case 5:
+        case 7:
+           gen_op_mtc0_datahi();
+            rn = "DataHi";
+            break;
+        default:
+            rn = "invalid sel";
+            goto die;
+        }
+       break;
+    case 30:
+        switch (sel) {
+        case 0:
+           gen_op_dmtc0_errorepc();
+           rn = "ErrorEPC";
+           break;
+        default:
+            goto die;
+        }
+        break;
+    case 31:
+        switch (sel) {
+        case 0:
+           gen_op_mtc0_desave(); /* EJTAG support */
+           rn = "DESAVE";
+           break;
+        default:
+            goto die;
+        }
+       /* Stop translation as we may have switched the execution mode */
+       ctx->bstate = BS_STOP;
+        break;
+    default:
+       goto die;
+    }
+#if defined MIPS_DEBUG_DISAS
+    if (loglevel & CPU_LOG_TB_IN_ASM) {
+        fprintf(logfile, "dmtc0 %s (reg %d sel %d)\n",
+                rn, reg, sel);
+    }
+#endif
+    return;
+
+die:
+#if defined MIPS_DEBUG_DISAS
+    if (loglevel & CPU_LOG_TB_IN_ASM) {
+        fprintf(logfile, "dmtc0 %s (reg %d sel %d)\n",
+                rn, reg, sel);
+    }
+#endif
+    generate_exception(ctx, EXCP_RI);
+}
+
 static void gen_cp0 (DisasContext *ctx, uint32_t opc, int rt, int rd)
 {
     const char *opn = "unk";
@@ -2854,7 +4029,7 @@ static void gen_cp0 (DisasContext *ctx, uint32_t opc, int rt, int rd)
         break;
     case OPC_MTC0:
         /* If we get an exception, we want to restart at next instruction */
-       /* XXX: breaks for mtc in delay slot */
+        /* XXX: breaks for mtc in delay slot */
         ctx->pc += 4;
         save_cpu_state(ctx, 1);
         ctx->pc -= 4;
@@ -2862,6 +4037,25 @@ static void gen_cp0 (DisasContext *ctx, uint32_t opc, int rt, int rd)
         gen_mtc0(ctx, rd, ctx->opcode & 0x7);
         opn = "mtc0";
         break;
+    case OPC_DMFC0:
+        if (rt == 0) {
+            /* Treat as NOP */
+            return;
+        }
+        gen_dmfc0(ctx, rd, ctx->opcode & 0x7);
+        gen_op_store_T0_gpr(rt);
+        opn = "dmfc0";
+        break;
+    case OPC_DMTC0:
+        /* If we get an exception, we want to restart at next instruction */
+        /* XXX: breaks for dmtc in delay slot */
+        ctx->pc += 4;
+        save_cpu_state(ctx, 1);
+        ctx->pc -= 4;
+        GEN_LOAD_REG_TN(T0, rt);
+        gen_dmtc0(ctx, rd, ctx->opcode & 0x7);
+        opn = "dmtc0";
+        break;
 #if defined(MIPS_USES_R4K_TLB)
     case OPC_TLBWI:
         gen_op_tlbwi();
@@ -3002,6 +4196,9 @@ static void gen_cp1 (DisasContext *ctx, uint32_t opc, int rt, int fs)
         gen_op_ctc1();
         opn = "ctc1";
         break;
+    case OPC_DMFC1:
+    case OPC_DMTC1:
+        /* Not implemented, fallthrough. */
     default:
         if (loglevel & CPU_LOG_TB_IN_ASM) {
             fprintf(logfile, "Invalid CP1 opcode: %08x %03x %03x %03x\n",
@@ -3703,6 +4900,10 @@ static void decode_opc (DisasContext *ctx)
         case OPC_CFC1:
         case OPC_MTC1:
         case OPC_CTC1:
+#ifdef MIPS_HAS_MIPS64
+        case OPC_DMFC1:
+        case OPC_DMTC1:
+#endif
             gen_cp1(ctx, op1, rt, rd);
             break;
         case OPC_BC1:
@@ -4099,7 +5300,7 @@ void cpu_reset (CPUMIPSState *env)
     }
     env->PC = (int32_t)0xBFC00000;
 #if defined (MIPS_USES_R4K_TLB)
-    env->CP0_random = MIPS_TLB_NB - 1;
+    env->CP0_Random = MIPS_TLB_NB - 1;
     env->tlb_in_use = MIPS_TLB_NB;
 #endif
     env->CP0_Wired = 0;