target-mips: minor upstream integration.
Change-Id: Ib356a3cb8aa0bda14f857b951e2c357405acaaee
diff --git a/hw/mips/cputimer.c b/hw/mips/cputimer.c
index 8462c5e..f955461 100644
--- a/hw/mips/cputimer.c
+++ b/hw/mips/cputimer.c
@@ -1,3 +1,25 @@
+/*
+ * QEMU MIPS timer support
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
#include "hw/hw.h"
#include "hw/mips/mips.h"
#include "qemu/timer.h"
@@ -5,7 +27,7 @@
#define TIMER_FREQ 100 * 1000 * 1000
/* XXX: do not use a global */
-uint32_t cpu_mips_get_random (CPUOldState *env)
+uint32_t cpu_mips_get_random (CPUMIPSState *env)
{
static uint32_t lfsr = 1;
static uint32_t prev_idx = 0;
@@ -20,17 +42,7 @@
}
/* MIPS R4K timer */
-uint32_t cpu_mips_get_count (CPUOldState *env)
-{
- if (env->CP0_Cause & (1 << CP0Ca_DC))
- return env->CP0_Count;
- else
- return env->CP0_Count +
- (uint32_t)muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL),
- TIMER_FREQ, get_ticks_per_sec());
-}
-
-static void cpu_mips_timer_update(CPUOldState *env)
+static void cpu_mips_timer_update(CPUMIPSState *env)
{
uint64_t now, next;
uint32_t wait;
@@ -42,7 +54,36 @@
timer_mod(env->timer, next);
}
-void cpu_mips_store_count (CPUOldState *env, uint32_t count)
+/* Expire the timer. */
+static void cpu_mips_timer_expire(CPUMIPSState *env)
+{
+ cpu_mips_timer_update(env);
+ if (env->insn_flags & ISA_MIPS32R2) {
+ env->CP0_Cause |= 1 << CP0Ca_TI;
+ }
+ qemu_irq_raise(env->irq[(env->CP0_IntCtl >> CP0IntCtl_IPTI) & 0x7]);
+}
+
+uint32_t cpu_mips_get_count (CPUMIPSState *env)
+{
+ if (env->CP0_Cause & (1 << CP0Ca_DC)) {
+ return env->CP0_Count;
+ } else {
+ uint64_t now;
+
+ now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
+ if (timer_pending(env->timer)
+ && timer_expired(env->timer, now)) {
+ /* The timer has already expired. */
+ cpu_mips_timer_expire(env);
+ }
+
+ return env->CP0_Count +
+ (uint32_t)muldiv64(now, TIMER_FREQ, get_ticks_per_sec());
+ }
+}
+
+void cpu_mips_store_count (CPUMIPSState *env, uint32_t count)
{
if (env->CP0_Cause & (1 << CP0Ca_DC))
env->CP0_Count = count;
@@ -56,7 +97,7 @@
}
}
-void cpu_mips_store_compare (CPUOldState *env, uint32_t value)
+void cpu_mips_store_compare (CPUMIPSState *env, uint32_t value)
{
env->CP0_Compare = value;
if (!(env->CP0_Cause & (1 << CP0Ca_DC)))
@@ -66,12 +107,12 @@
qemu_irq_lower(env->irq[(env->CP0_IntCtl >> CP0IntCtl_IPTI) & 0x7]);
}
-void cpu_mips_start_count(CPUOldState *env)
+void cpu_mips_start_count(CPUMIPSState *env)
{
cpu_mips_store_count(env, env->CP0_Count);
}
-void cpu_mips_stop_count(CPUOldState *env)
+void cpu_mips_stop_count(CPUMIPSState *env)
{
/* Store the current value */
env->CP0_Count += (uint32_t)muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL),
@@ -80,7 +121,7 @@
static void mips_timer_cb (void *opaque)
{
- CPUOldState *env;
+ CPUMIPSState *env;
env = opaque;
#if 0
@@ -94,16 +135,13 @@
the comparator value. Offset the count by one to avoid immediately
retriggering the callback before any virtual time has passed. */
env->CP0_Count++;
- cpu_mips_timer_update(env);
+ cpu_mips_timer_expire(env);
env->CP0_Count--;
- if (env->insn_flags & ISA_MIPS32R2)
- env->CP0_Cause |= 1 << CP0Ca_TI;
- qemu_irq_raise(env->irq[(env->CP0_IntCtl >> CP0IntCtl_IPTI) & 0x7]);
}
-void cpu_mips_clock_init (CPUOldState *env)
+void cpu_mips_clock_init (CPUMIPSState *env)
{
- env->timer = timer_new(QEMU_CLOCK_VIRTUAL, SCALE_NS, &mips_timer_cb, env);
+ env->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, &mips_timer_cb, env);
env->CP0_Compare = 0;
cpu_mips_store_count(env, 1);
}
diff --git a/target-mips/machine.c b/target-mips/machine.c
index 6ae15e3..0a07db8 100644
--- a/target-mips/machine.c
+++ b/target-mips/machine.c
@@ -58,6 +58,7 @@
/* Save TLB */
qemu_put_be32s(f, &env->tlb->nb_tlb);
+ qemu_put_be32s(f, &env->tlb->tlb_in_use);
for(i = 0; i < MIPS_TLB_MAX; i++) {
uint16_t flags = ((env->tlb->mmu.r4k.tlb[i].G << 10) |
(env->tlb->mmu.r4k.tlb[i].C0 << 7) |
@@ -209,6 +210,7 @@
/* Load TLB */
qemu_get_be32s(f, &env->tlb->nb_tlb);
+ qemu_get_be32s(f, &env->tlb->tlb_in_use);
for(i = 0; i < MIPS_TLB_MAX; i++) {
uint16_t flags;
uint8_t asid;
diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c
index 29c3c6e..ccce17f 100644
--- a/target-mips/op_helper.c
+++ b/target-mips/op_helper.c
@@ -281,18 +281,6 @@
(uint64_t)(uint32_t)arg2);
}
-#ifdef TARGET_MIPS64
-void helper_dmult (CPUMIPSState *env, target_ulong arg1, target_ulong arg2)
-{
- muls64(&(env->active_tc.LO[0]), &(env->active_tc.HI[0]), arg1, arg2);
-}
-
-void helper_dmultu (CPUMIPSState *env, target_ulong arg1, target_ulong arg2)
-{
- mulu64(&(env->active_tc.LO[0]), &(env->active_tc.HI[0]), arg1, arg2);
-}
-#endif
-
#ifndef CONFIG_USER_ONLY
static inline hwaddr do_translate_address(CPUMIPSState *env,
@@ -1774,7 +1762,6 @@
void helper_fork(target_ulong arg1, target_ulong arg2)
{
// arg1 = rt, arg2 = rs
- arg1 = 0;
// TODO: store to TC register
}
@@ -2196,7 +2183,10 @@
void helper_wait(CPUMIPSState *env)
{
- ENV_GET_CPU(env)->halted = 1;
+ CPUState* cs = ENV_GET_CPU(env);
+
+ cs->halted = 1;
+ cpu_reset_interrupt(cs, CPU_INTERRUPT_WAKE);
helper_raise_exception(env, EXCP_HLT);
}
@@ -2247,10 +2237,11 @@
{
CPUMIPSState *env = cpu->env_ptr;
- if (is_exec)
+ if (is_exec) {
helper_raise_exception(env, EXCP_IBE);
- else
+ } else {
helper_raise_exception(env, EXCP_DBE);
+ }
}
/*
* The following functions are address translation helper functions
diff --git a/target-mips/translate.c b/target-mips/translate.c
index 2c2e1fa..9505e2c 100755
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -1026,36 +1026,6 @@
#include "exec/gen-icount.h"
-#define gen_helper_0i(name, arg) do { \
- TCGv_i32 helper_tmp = tcg_const_i32(arg); \
- gen_helper_##name(helper_tmp); \
- tcg_temp_free_i32(helper_tmp); \
- } while(0)
-
-#define gen_helper_1i(name, arg1, arg2) do { \
- TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
- gen_helper_##name(arg1, helper_tmp); \
- tcg_temp_free_i32(helper_tmp); \
- } while(0)
-
-#define gen_helper_2i(name, arg1, arg2, arg3) do { \
- TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
- gen_helper_##name(arg1, arg2, helper_tmp); \
- tcg_temp_free_i32(helper_tmp); \
- } while(0)
-
-#define gen_helper_3i(name, arg1, arg2, arg3, arg4) do { \
- TCGv_i32 helper_tmp = tcg_const_i32(arg4); \
- gen_helper_##name(arg1, arg2, arg3, helper_tmp); \
- tcg_temp_free_i32(helper_tmp); \
- } while(0)
-
-#define gen_helper_4i(name, arg1, arg2, arg3, arg4, arg5) do { \
- TCGv_i32 helper_tmp = tcg_const_i32(arg5); \
- gen_helper_##name(arg1, arg2, arg3, arg4, helper_tmp); \
- tcg_temp_free_i32(helper_tmp); \
- } while(0)
-
#define gen_helper_0e0i(name, arg) do { \
TCGv_i32 helper_tmp = tcg_const_i32(arg); \
gen_helper_##name(cpu_env, helper_tmp); \
@@ -1471,36 +1441,6 @@
generate_exception(ctx, EXCP_RI);
}
-/* load/store instructions. */
-#define OP_LD(insn,fname) \
-static inline void op_ldst_##insn(TCGv ret, TCGv arg1, DisasContext *ctx) \
-{ \
- tcg_gen_qemu_##fname(ret, arg1, ctx->mem_idx); \
-}
-OP_LD(lb,ld8s);
-OP_LD(lbu,ld8u);
-OP_LD(lh,ld16s);
-OP_LD(lhu,ld16u);
-OP_LD(lw,ld32s);
-#if defined(TARGET_MIPS64)
-OP_LD(lwu,ld32u);
-OP_LD(ld,ld64);
-#endif
-#undef OP_LD
-
-#define OP_ST(insn,fname) \
-static inline void op_ldst_##insn(TCGv arg1, TCGv arg2, DisasContext *ctx) \
-{ \
- tcg_gen_qemu_##fname(arg1, arg2, ctx->mem_idx); \
-}
-OP_ST(sb,st8);
-OP_ST(sh,st16);
-OP_ST(sw,st32);
-#if defined(TARGET_MIPS64)
-OP_ST(sd,st64);
-#endif
-#undef OP_ST
-
/* Define small wrappers for gen_load_fpr* so that we have a uniform
calling interface for 32 and 64-bit FPRs. No sense in changing
all callers for gen_load_fpr32 when we need the CTX parameter for
@@ -6186,7 +6126,15 @@
switch (sel) {
case 0:
save_cpu_state(ctx, 1);
+ /* Mark as an IO operation because we may trigger a software
+ interrupt. */
+ if (use_icount) {
+ gen_io_start();
+ }
gen_helper_mtc0_cause(cpu_env, arg);
+ if (use_icount) {
+ gen_io_end();
+ }
/* Stop translation as we may have triggered an intetrupt */
ctx->bstate = BS_STOP;
rn = "Cause";
diff --git a/target-mips/translate_init.c b/target-mips/translate_init.c
index 8ace034..29dc2ef 100644
--- a/target-mips/translate_init.c
+++ b/target-mips/translate_init.c
@@ -51,10 +51,6 @@
#define MIPS_CONFIG5 \
((0 << CP0C5_M))
-/* Define a implementation number of 1.
- Define a major version 1, minor version 0. */
-#define MIPS_FCR0 ((0 << FCR0_S) | (0x1 << FCR0_PRID) | (0x10 << FCR0_REV))
-
/* MMU types, the first four entries have the same layout as the
CP0C0_MT field. */
enum mips_mmu_types {