From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1IZnw0-0002ti-B3 for qemu-devel@nongnu.org; Mon, 24 Sep 2007 09:25:12 -0400 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1IZnvz-0002sL-AW for qemu-devel@nongnu.org; Mon, 24 Sep 2007 09:25:12 -0400 Received: from [199.232.76.173] (helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1IZnvz-0002s1-2m for qemu-devel@nongnu.org; Mon, 24 Sep 2007 09:25:11 -0400 Received: from hall.aurel32.net ([88.191.38.19]) by monty-python.gnu.org with esmtps (TLS-1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.60) (envelope-from ) id 1IZnvy-0002lb-55 for qemu-devel@nongnu.org; Mon, 24 Sep 2007 09:25:10 -0400 Received: from aurel32 by hall.aurel32.net with local (Exim 4.63) (envelope-from ) id 1IZnvr-0004uT-G1 for qemu-devel@nongnu.org; Mon, 24 Sep 2007 15:25:03 +0200 Date: Mon, 24 Sep 2007 15:25:03 +0200 From: Aurelien Jarno Message-ID: <20070924132503.GA18826@hall.aurel32.net> MIME-Version: 1.0 Content-Type: text/plain; charset=iso-8859-15 Content-Disposition: inline Sender: "aurel32,,," Subject: [Qemu-devel] [PATCH, MIPS R2] Timer start/stop implementation Reply-To: qemu-devel@nongnu.org List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Hi all, The patch below allows the timer to be stopped using the DC bit in the CP0 Cause register. This feature is required for MIPS R2 implementations. It also removes a few places where the interrupt corresponding to the timer is hardcoded, and leaves it hardcoded at only one place (initialisation). Bye, Aurelien Index: hw/mips_timer.c =================================================================== RCS file: /sources/qemu/qemu/hw/mips_timer.c,v retrieving revision 1.7 diff -u -d -p -r1.7 mips_timer.c --- hw/mips_timer.c 6 Sep 2007 00:18:14 -0000 1.7 +++ hw/mips_timer.c 24 Sep 2007 13:22:50 -0000 @@ -17,9 +17,12 @@ uint32_t cpu_mips_get_random (CPUState * /* MIPS R4K timer */ uint32_t cpu_mips_get_count (CPUState *env) { - return env->CP0_Count + - (uint32_t)muldiv64(qemu_get_clock(vm_clock), - 100 * 1000 * 1000, ticks_per_sec); + if (env->CP0_Cause & (1 << CP0Ca_DC)) + return env->CP0_Count; + else + return env->CP0_Count + + (uint32_t)muldiv64(qemu_get_clock(vm_clock), + 100 * 1000 * 1000, ticks_per_sec); } void cpu_mips_store_count (CPUState *env, uint32_t count) @@ -63,7 +66,19 @@ void cpu_mips_store_compare (CPUState *e cpu_mips_update_count(env, cpu_mips_get_count(env)); if ((env->CP0_Config0 & (0x7 << CP0C0_AR)) == (1 << CP0C0_AR)) env->CP0_Cause &= ~(1 << CP0Ca_TI); - qemu_irq_lower(env->irq[7]); + qemu_irq_lower(env->irq[(env->CP0_IntCtl >> CP0In_IPTI) & 0x7]); +} + +void cpu_mips_start_count(CPUState *env) +{ + cpu_mips_store_count(env, env->CP0_Count); +} + +void cpu_mips_stop_count(CPUState *env) +{ + /* Store the current value */ + env->CP0_Count += (uint32_t)muldiv64(qemu_get_clock(vm_clock), + 100 * 1000 * 1000, ticks_per_sec); } static void mips_timer_cb (void *opaque) @@ -76,10 +91,14 @@ static void mips_timer_cb (void *opaque) fprintf(logfile, "%s\n", __func__); } #endif + + if (env->CP0_Cause & (1 << CP0Ca_DC)) + return; + cpu_mips_update_count(env, cpu_mips_get_count(env)); if ((env->CP0_Config0 & (0x7 << CP0C0_AR)) == (1 << CP0C0_AR)) env->CP0_Cause |= 1 << CP0Ca_TI; - qemu_irq_raise(env->irq[7]); + qemu_irq_raise(env->irq[(env->CP0_IntCtl >> CP0In_IPTI) & 0x7]); } void cpu_mips_clock_init (CPUState *env) Index: target-mips/exec.h =================================================================== RCS file: /sources/qemu/qemu/target-mips/exec.h,v retrieving revision 1.32 diff -u -d -p -r1.32 exec.h --- target-mips/exec.h 16 Sep 2007 21:08:03 -0000 1.32 +++ target-mips/exec.h 24 Sep 2007 13:22:50 -0000 @@ -153,6 +153,8 @@ uint32_t cpu_mips_get_random (CPUState * 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); +void cpu_mips_start_count(CPUState *env); +void cpu_mips_stop_count(CPUState *env); void cpu_mips_update_irq (CPUState *env); void cpu_mips_clock_init (CPUState *env); void cpu_mips_tlb_flush (CPUState *env, int flush_global); Index: target-mips/op.c =================================================================== RCS file: /sources/qemu/qemu/target-mips/op.c,v retrieving revision 1.72 diff -u -d -p -r1.72 op.c --- target-mips/op.c 24 Sep 2007 12:48:00 -0000 1.72 +++ target-mips/op.c 24 Sep 2007 13:22:51 -0000 @@ -1882,9 +1882,8 @@ void op_mttc0_status(void) void op_mtc0_intctl (void) { - /* vectored interrupts not implemented, timer on int 7, - no performance counters. */ - env->CP0_IntCtl |= T0 & 0x000002e0; + /* vectored interrupts not implemented, no performance counters. */ + env->CP0_IntCtl = (env->CP0_IntCtl & ~0x000002e0) | (T0 & 0x000002e0); RETURN(); } @@ -1904,12 +1903,20 @@ void op_mtc0_srsmap (void) void op_mtc0_cause (void) { uint32_t mask = 0x00C00300; + uint32_t old = env->CP0_Cause; if (env->insn_flags & ISA_MIPS32R2) mask |= 1 << CP0Ca_DC; env->CP0_Cause = (env->CP0_Cause & ~mask) | (T0 & mask); + if ((old ^ env->CP0_Cause) & (1 << CP0Ca_DC)) { + if (env->CP0_Cause & (1 << CP0Ca_DC)) + CALL_FROM_TB1(cpu_mips_stop_count, env); + else + CALL_FROM_TB1(cpu_mips_start_count, env); + } + /* Handle the software interrupt as an hardware one, as they are very similar */ if (T0 & CP0Ca_IP_mask) { Index: target-mips/op_helper.c =================================================================== RCS file: /sources/qemu/qemu/target-mips/op_helper.c,v retrieving revision 1.59 diff -u -d -p -r1.59 op_helper.c --- target-mips/op_helper.c 17 Sep 2007 08:09:53 -0000 1.59 +++ target-mips/op_helper.c 24 Sep 2007 13:22:52 -0000 @@ -265,6 +265,16 @@ void cpu_mips_store_compare(CPUState *en cpu_abort(env, "mtc0 compare\n"); } +void cpu_mips_start_count(CPUState *env) +{ + cpu_abort(env, "start count\n"); +} + +void cpu_mips_stop_count(CPUState *env) +{ + cpu_abort(env, "stop count\n"); +} + void cpu_mips_update_irq(CPUState *env) { cpu_abort(env, "mtc0 status / mtc0 cause\n"); -- .''`. Aurelien Jarno | GPG: 1024D/F1BCDB73 : :' : Debian developer | Electrical Engineer `. `' aurel32@debian.org | aurelien@aurel32.net `- people.debian.org/~aurel32 | www.aurel32.net