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;