aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--hw/mips_timer.c2
-rw-r--r--target-mips/cpu.h10
-rw-r--r--target-mips/op_helper.c86
-rw-r--r--target-mips/translate.c3
4 files changed, 92 insertions, 9 deletions
diff --git a/hw/mips_timer.c b/hw/mips_timer.c
index bb3c3e4..6bae90b 100644
--- a/hw/mips_timer.c
+++ b/hw/mips_timer.c
@@ -103,7 +103,7 @@ static void mips_timer_cb (void *opaque)
void cpu_mips_clock_init (CPUState *env)
{
- env->timer = qemu_new_timer(vm_clock, &mips_timer_cb, env);
+ env->timer = qemu_new_timer_ns(vm_clock, &mips_timer_cb, env);
env->CP0_Compare = 0;
cpu_mips_store_count(env, 1);
}
diff --git a/target-mips/cpu.h b/target-mips/cpu.h
index 89c28f1..27bdc95 100644
--- a/target-mips/cpu.h
+++ b/target-mips/cpu.h
@@ -500,6 +500,16 @@ static inline int cpu_mmu_index (CPUState *env)
return env->hflags & MIPS_HFLAG_KSU;
}
+static inline int is_cpu_user (CPUState *env)
+{
+#ifdef CONFIG_USER_ONLY
+ return 1;
+#else
+ return ((env->CP0_Status &
+ ((3 << CP0St_KSU) | (1 << CP0St_ERL) | (1 << CP0St_EXL))) == (3 << CP0St_KSU));
+#endif // CONFIG_USER_ONLY
+}
+
static inline void cpu_clone_regs(CPUState *env, target_ulong newsp)
{
if (newsp)
diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c
index dda9e82..61a39df 100644
--- a/target-mips/op_helper.c
+++ b/target-mips/op_helper.c
@@ -61,7 +61,7 @@ static void do_restore_state (void *pc_ptr)
tb = tb_find_pc (pc);
if (tb) {
- cpu_restore_state (tb, env, pc, NULL);
+ cpu_restore_state (tb, env, pc);
}
}
#endif
@@ -1846,7 +1846,7 @@ void tlb_fill (target_ulong addr, int is_write, int mmu_idx, void *retaddr)
if (tb) {
/* the PC is inside the translated code. It means that we have
a virtual CPU fault */
- cpu_restore_state(tb, env, pc, NULL);
+ cpu_restore_state(tb, env, pc);
}
}
helper_raise_exception_err(env->exception_index, env->error_code);
@@ -1862,6 +1862,80 @@ void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec,
else
helper_raise_exception(EXCP_DBE);
}
+/*
+ * The following functions are address translation helper functions
+ * for fast memory access in QEMU.
+ */
+static unsigned long v2p_mmu(target_ulong addr, int is_user)
+{
+ int index;
+ target_ulong tlb_addr;
+ target_phys_addr_t physaddr;
+ void *retaddr;
+
+ index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
+redo:
+ tlb_addr = env->tlb_table[is_user][index].addr_read;
+ if ((addr & TARGET_PAGE_MASK) == (tlb_addr & (TARGET_PAGE_MASK | TLB_INVALID_MASK))) {
+ physaddr = addr + env->tlb_table[is_user][index].addend;
+ } else {
+ /* the page is not in the TLB : fill it */
+ retaddr = GETPC();
+ tlb_fill(addr, 0, is_user, retaddr);
+ goto redo;
+ }
+ return physaddr;
+}
+
+/*
+ * translation from virtual address of simulated OS
+ * to the address of simulation host (not the physical
+ * address of simulated OS.
+ */
+target_phys_addr_t v2p(target_ulong ptr, int is_user)
+{
+ CPUState *saved_env;
+ int index;
+ target_ulong addr;
+ target_phys_addr_t physaddr;
+
+ saved_env = env;
+ env = cpu_single_env;
+ addr = ptr;
+ index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
+ if (__builtin_expect(env->tlb_table[is_user][index].addr_read !=
+ (addr & TARGET_PAGE_MASK), 0)) {
+ physaddr = v2p_mmu(addr, is_user);
+ } else {
+ physaddr = (target_phys_addr_t)addr + env->tlb_table[is_user][index].addend;
+ }
+ env = saved_env;
+ return physaddr;
+}
+
+/* copy a string from the simulated virtual space to a buffer in QEMU */
+void vstrcpy(target_ulong ptr, char *buf, int max)
+{
+ char *phys = 0;
+ unsigned long page = 0;
+
+ if (buf == NULL) return;
+
+ while (max) {
+ if ((ptr & TARGET_PAGE_MASK) != page) {
+ phys = (char *)v2p(ptr, 0);
+ page = ptr & TARGET_PAGE_MASK;
+ }
+ *buf = *phys;
+ if (*phys == '\0')
+ return;
+ ptr ++;
+ buf ++;
+ phys ++;
+ max --;
+ }
+}
+
#endif /* !CONFIG_USER_ONLY */
/* Complex FPU operations which may need stack space. */
@@ -2751,10 +2825,10 @@ static int float64_is_unordered(int sig, float64 a, float64 b STATUS_PARAM)
{
if (float64_is_signaling_nan(a) ||
float64_is_signaling_nan(b) ||
- (sig && (float64_is_nan(a) || float64_is_nan(b)))) {
+ (sig && (float64_is_any_nan(a) || float64_is_any_nan(b)))) {
float_raise(float_flag_invalid, status);
return 1;
- } else if (float64_is_nan(a) || float64_is_nan(b)) {
+ } else if (float64_is_any_nan(a) || float64_is_any_nan(b)) {
return 1;
} else {
return 0;
@@ -2809,10 +2883,10 @@ static flag float32_is_unordered(int sig, float32 a, float32 b STATUS_PARAM)
{
if (float32_is_signaling_nan(a) ||
float32_is_signaling_nan(b) ||
- (sig && (float32_is_nan(a) || float32_is_nan(b)))) {
+ (sig && (float32_is_any_nan(a) || float32_is_any_nan(b)))) {
float_raise(float_flag_invalid, status);
return 1;
- } else if (float32_is_nan(a) || float32_is_nan(b)) {
+ } else if (float32_is_any_nan(a) || float32_is_any_nan(b)) {
return 1;
} else {
return 0;
diff --git a/target-mips/translate.c b/target-mips/translate.c
index d1d6f23..853aafd 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -8705,8 +8705,7 @@ void cpu_reset (CPUMIPSState *env)
env->exception_index = EXCP_NONE;
}
-void gen_pc_load(CPUState *env, TranslationBlock *tb,
- unsigned long searched_pc, int pc_pos, void *puc)
+void restore_state_to_opc(CPUState *env, TranslationBlock *tb, int pc_pos)
{
env->active_tc.PC = gen_opc_pc[pc_pos];
env->hflags &= ~MIPS_HFLAG_BMASK;