Index: hw/mips_timer.c
===================================================================
--- hw/mips_timer.c	(revision 6145)
+++ hw/mips_timer.c	(working copy)
@@ -4,25 +4,11 @@
 
 #define TIMER_FREQ	100 * 1000 * 1000
 
-/* XXX: do not use a global */
-uint32_t cpu_mips_get_random (CPUState *env)
-{
-    static uint32_t seed = 0;
-    uint32_t idx;
-    seed = seed * 314159 + 1;
-    idx = (seed >> 16) % (env->tlb->nb_tlb - env->CP0_Wired) + env->CP0_Wired;
-    return idx;
-}
-
 /* MIPS R4K timer */
 uint32_t cpu_mips_get_count (CPUState *env)
 {
-    if (env->CP0_Cause & (1 << CP0Ca_DC))
-        return env->CP0_Count;
-    else
-        return env->CP0_Count +
-            (uint32_t)muldiv64(qemu_get_clock(vm_clock),
-                               TIMER_FREQ, ticks_per_sec);
+    return (uint32_t)muldiv64(qemu_get_clock(vm_clock),
+                              TIMER_FREQ, ticks_per_sec);
 }
 
 static void cpu_mips_timer_update(CPUState *env)
Index: target-mips/cpu.h
===================================================================
--- target-mips/cpu.h	(revision 6145)
+++ target-mips/cpu.h	(working copy)
@@ -449,6 +449,8 @@
     uint32_t CP0_TCStatus_rw_bitmask; /* Read/write bits in CP0_TCStatus */
     int insn_flags; /* Supported instruction set */
 
+    void (*update_cp0_random) (struct CPUMIPSState *env);
+
     target_ulong tls_value; /* For usermode emulation */
 
     CPU_COMMON
@@ -470,6 +472,11 @@
 void r4k_do_tlbr (void);
 void mips_cpu_list (FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...));
 
+void cp0_random_each_wired (CPUMIPSState *env);
+void cp0_random_each_tlbwr (CPUMIPSState *env);
+void cp0_random_each_instr (CPUMIPSState *env);
+void cp0_random_nlu (CPUMIPSState *env);
+
 void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec,
                           int unused, int size);
 
@@ -565,7 +572,6 @@
 int cpu_mips_signal_handler(int host_signum, void *pinfo, void *puc);
 
 /* mips_timer.c */
-uint32_t cpu_mips_get_random (CPUState *env);
 uint32_t cpu_mips_get_count (CPUState *env);
 void cpu_mips_store_count (CPUState *env, uint32_t value);
 void cpu_mips_store_compare (CPUState *env, uint32_t value);
Index: target-mips/helper.c
===================================================================
--- target-mips/helper.c	(revision 6145)
+++ target-mips/helper.c	(working copy)
@@ -626,3 +626,42 @@
         }
     }
 }
+
+void cp0_random_each_wired (CPUMIPSState *env)
+{
+    uint32_t instr_count;
+    instr_count = (int32_t)cpu_mips_get_count(env);
+    instr_count /= env->CP0_Wired + 1;
+    instr_count %= env->tlb->nb_tlb - env->CP0_Wired;
+    env->CP0_Random = (int32_t)instr_count + env->CP0_Wired;
+}
+
+void cp0_random_each_tlbwr (CPUMIPSState *env)
+{
+    env->CP0_Random--;
+    if (env->CP0_Random <= env->CP0_Wired)
+        env->CP0_Random = env->tlb->nb_tlb - 1;
+}
+
+void cp0_random_each_instr (CPUMIPSState *env)
+{
+    uint32_t instr_count;
+    instr_count = (int32_t)cpu_mips_get_count(env);
+    instr_count %= env->tlb->nb_tlb - env->CP0_Wired;
+    env->CP0_Random = (int32_t)instr_count + env->CP0_Wired;
+}
+
+void cp0_random_nlu (CPUMIPSState *env)
+{
+    static uint32_t seed = 0;
+    uint32_t idx;
+    seed = seed * 314159 + 1;
+    idx = (seed >> 16) % (env->tlb->nb_tlb - env->CP0_Wired) + env->CP0_Wired;
+    if (idx == env->CP0_Random) {
+        /* prevent same value twice */
+        idx++;
+        if (idx == env->tlb->nb_tlb)
+            idx = env->CP0_Wired;
+    }
+    env->CP0_Random = idx;
+}
Index: target-mips/helper.h
===================================================================
--- target-mips/helper.h	(revision 6145)
+++ target-mips/helper.h	(working copy)
@@ -49,7 +49,6 @@
 DEF_HELPER_0(mfc0_mvpcontrol, tl)
 DEF_HELPER_0(mfc0_mvpconf0, tl)
 DEF_HELPER_0(mfc0_mvpconf1, tl)
-DEF_HELPER_0(mfc0_random, tl)
 DEF_HELPER_0(mfc0_tcstatus, tl)
 DEF_HELPER_0(mftc0_tcstatus, tl)
 DEF_HELPER_0(mfc0_tcbind, tl)
Index: target-mips/op_helper.c
===================================================================
--- target-mips/op_helper.c	(revision 6145)
+++ target-mips/op_helper.c	(working copy)
@@ -616,11 +616,6 @@
     return env->mvp->CP0_MVPConf1;
 }
 
-target_ulong do_mfc0_random (void)
-{
-    return (int32_t)cpu_mips_get_random(env);
-}
-
 target_ulong do_mfc0_tcstatus (void)
 {
     return env->active_tc.CP0_TCStatus;
@@ -728,7 +723,10 @@
 
 target_ulong do_mfc0_count (void)
 {
-    return (int32_t)cpu_mips_get_count(env);
+    if (env->CP0_Cause & (1 << CP0Ca_DC))
+        return env->CP0_Count;
+    else
+        return env->CP0_Count + (int32_t)cpu_mips_get_count(env);
 }
 
 target_ulong do_mftc0_entryhi(void)
@@ -1590,8 +1588,11 @@
 
 void r4k_do_tlbwr (void)
 {
-    int r = cpu_mips_get_random(env);
+    int r;
 
+    env->update_cp0_random(env);
+    r = env->CP0_Random;
+
     r4k_invalidate_tlb(env, r, 1);
     r4k_fill_tlb(r);
 }
Index: target-mips/translate.c
===================================================================
--- target-mips/translate.c	(revision 6145)
+++ target-mips/translate.c	(working copy)
@@ -2767,7 +2767,7 @@
     case 1:
         switch (sel) {
         case 0:
-            gen_helper_mfc0_random(t0);
+            gen_mfc0_load32(t0, offsetof(CPUState, CP0_Random));
             rn = "Random";
             break;
         case 1:
@@ -3964,7 +3964,7 @@
     case 1:
         switch (sel) {
         case 0:
-            gen_helper_mfc0_random(t0);
+            gen_mfc0_load32(t0, offsetof(CPUState, CP0_Random));
             rn = "Random";
             break;
         case 1:
Index: target-mips/translate_init.c
===================================================================
--- target-mips/translate_init.c	(revision 6145)
+++ target-mips/translate_init.c	(working copy)
@@ -62,6 +62,14 @@
     MMU_TYPE_R8000
 };
 
+enum mips_random_register_types {
+    RANDOM_TYPE_UNKNOWN,
+    RANDOM_TYPE_DECR_EACH_WIRED,
+    RANDOM_TYPE_DECR_EACH_TLBWR,
+    RANDOM_TYPE_DECR_EACH_INSTR,
+    RANDOM_TYPE_NOT_LAST_USED,
+};
+
 struct mips_def_t {
     const char *name;
     int32_t CP0_PRid;
@@ -91,6 +99,7 @@
     int32_t CP0_SRSConf4;
     int insn_flags;
     enum mips_mmu_types mmu_type;
+    enum mips_random_register_types random_type;
 };
 
 /*****************************************************************************/
@@ -113,6 +122,7 @@
         .PABITS = 32,
         .insn_flags = CPU_MIPS32 | ASE_MIPS16,
         .mmu_type = MMU_TYPE_R4000,
+        .random_type = RANDOM_TYPE_DECR_EACH_WIRED,
     },
     {
         .name = "4Km",
@@ -132,6 +142,7 @@
         .PABITS = 32,
         .insn_flags = CPU_MIPS32 | ASE_MIPS16,
         .mmu_type = MMU_TYPE_FMT,
+        .random_type = RANDOM_TYPE_DECR_EACH_WIRED,
     },
     {
         .name = "4KEcR1",
@@ -149,6 +160,7 @@
         .PABITS = 32,
         .insn_flags = CPU_MIPS32 | ASE_MIPS16,
         .mmu_type = MMU_TYPE_R4000,
+        .random_type = RANDOM_TYPE_DECR_EACH_WIRED,
     },
     {
         .name = "4KEmR1",
@@ -166,6 +178,7 @@
         .PABITS = 32,
         .insn_flags = CPU_MIPS32 | ASE_MIPS16,
         .mmu_type = MMU_TYPE_FMT,
+        .random_type = RANDOM_TYPE_DECR_EACH_WIRED,
     },
     {
         .name = "4KEc",
@@ -184,6 +197,7 @@
         .PABITS = 32,
         .insn_flags = CPU_MIPS32R2 | ASE_MIPS16,
         .mmu_type = MMU_TYPE_R4000,
+        .random_type = RANDOM_TYPE_DECR_EACH_WIRED,
     },
     {
         .name = "4KEm",
@@ -202,6 +216,7 @@
         .PABITS = 32,
         .insn_flags = CPU_MIPS32R2 | ASE_MIPS16,
         .mmu_type = MMU_TYPE_FMT,
+        .random_type = RANDOM_TYPE_DECR_EACH_WIRED,
     },
     {
         .name = "24Kc",
@@ -221,6 +236,7 @@
         .PABITS = 32,
         .insn_flags = CPU_MIPS32R2 | ASE_MIPS16,
         .mmu_type = MMU_TYPE_R4000,
+        .random_type = RANDOM_TYPE_DECR_EACH_WIRED,
     },
     {
         .name = "24Kf",
@@ -242,6 +258,7 @@
         .PABITS = 32,
         .insn_flags = CPU_MIPS32R2 | ASE_MIPS16,
         .mmu_type = MMU_TYPE_R4000,
+        .random_type = RANDOM_TYPE_DECR_EACH_WIRED,
     },
     {
         .name = "34Kf",
@@ -286,6 +303,7 @@
         .PABITS = 32,
         .insn_flags = CPU_MIPS32R2 | ASE_MIPS16 | ASE_DSP | ASE_MT,
         .mmu_type = MMU_TYPE_R4000,
+        .random_type = RANDOM_TYPE_DECR_EACH_WIRED,
     },
 #if defined(TARGET_MIPS64)
     {
@@ -304,6 +322,7 @@
         .PABITS = 36,
         .insn_flags = CPU_MIPS3,
         .mmu_type = MMU_TYPE_R4000,
+        .random_type = RANDOM_TYPE_DECR_EACH_INSTR,
     },
     {
         .name = "VR5432",
@@ -320,6 +339,7 @@
         .PABITS = 32,
         .insn_flags = CPU_VR54XX,
         .mmu_type = MMU_TYPE_R4000,
+        .random_type = RANDOM_TYPE_DECR_EACH_INSTR,
     },
     {
         .name = "5Kc",
@@ -339,6 +359,7 @@
         .PABITS = 36,
         .insn_flags = CPU_MIPS64,
         .mmu_type = MMU_TYPE_R4000,
+        .random_type = RANDOM_TYPE_DECR_EACH_TLBWR,
     },
     {
         .name = "5Kf",
@@ -361,6 +382,7 @@
         .PABITS = 36,
         .insn_flags = CPU_MIPS64,
         .mmu_type = MMU_TYPE_R4000,
+        .random_type = RANDOM_TYPE_DECR_EACH_TLBWR,
     },
     {
         .name = "20Kc",
@@ -386,6 +408,7 @@
         .PABITS = 36,
         .insn_flags = CPU_MIPS64 | ASE_MIPS3D,
         .mmu_type = MMU_TYPE_R4000,
+        .random_type = RANDOM_TYPE_NOT_LAST_USED,
     },
     {
 	/* A generic CPU providing MIPS64 Release 2 features.
@@ -413,6 +436,7 @@
         .PABITS = 36,
         .insn_flags = CPU_MIPS64R2 | ASE_MIPS3D,
         .mmu_type = MMU_TYPE_R4000,
+        .random_type = RANDOM_TYPE_NOT_LAST_USED,
     },
 #endif
 };
@@ -482,9 +506,38 @@
         default:
             cpu_abort(env, "MMU type not supported\n");
     }
-    env->CP0_Random = env->tlb->nb_tlb - 1;
     env->tlb->tlb_in_use = env->tlb->nb_tlb;
 }
+
+static void random_init (CPUMIPSState *env, const mips_def_t *def)
+{
+    switch (def->random_type) {
+        case RANDOM_TYPE_DECR_EACH_WIRED:
+            env->update_cp0_random = cp0_random_each_wired;
+            break;
+        case RANDOM_TYPE_DECR_EACH_TLBWR:
+            env->update_cp0_random = cp0_random_each_tlbwr;
+            break;
+        case RANDOM_TYPE_DECR_EACH_INSTR:
+            env->update_cp0_random = cp0_random_each_instr;
+            break;
+        case RANDOM_TYPE_NOT_LAST_USED:
+            env->update_cp0_random = cp0_random_nlu;
+            break;
+        default:
+            cpu_abort(env, "random register type not supported\n");
+    }
+
+    env->CP0_Random = env->tlb->nb_tlb - 1;
+}
+
+#else /* CONFIG_USER_ONLY */
+
+static void random_init (CPUMIPSState *env, const mips_def_t *def)
+{
+    env->CP0_Random = 0;
+}
+
 #endif /* CONFIG_USER_ONLY */
 
 static void fpu_init (CPUMIPSState *env, const mips_def_t *def)
@@ -575,6 +628,7 @@
     if (!env->user_mode_only)
         mmu_init(env, def);
 #endif
+    random_init(env, def);
     fpu_init(env, def);
     mvp_init(env, def);
     return 0;
