diff options
author | Sebastian Macke | 2013-10-22 02:12:41 +0200 |
---|---|---|
committer | Jia Liu | 2013-11-20 14:46:45 +0100 |
commit | d51552176a2ab5e80a211514aa1339fe2575ec2a (patch) | |
tree | f272c169ec8acfdd998b69d7d4eb1ab9af58708d /target-openrisc | |
parent | target-openrisc: Correct wrong epcr register in interrupt handler (diff) | |
download | qemu-d51552176a2ab5e80a211514aa1339fe2575ec2a.tar.gz qemu-d51552176a2ab5e80a211514aa1339fe2575ec2a.tar.xz qemu-d51552176a2ab5e80a211514aa1339fe2575ec2a.zip |
openrisc-timer: Reduce overhead, Separate clock update functions
The clock value is only evaluated when really necessary reducing
the overhead of the timer handling.
This also solves a problem in the way the Linux kernel
handles the timer and the expected accuracy.
The old version could lead to inaccurate timings.
Signed-off-by: Sebastian Macke <sebastian@macke.de>
Reviewed-by: Jia Liu <proljc@gmail.com>
Signed-off-by: Jia Liu <proljc@gmail.com>
Diffstat (limited to 'target-openrisc')
-rw-r--r-- | target-openrisc/cpu.h | 1 | ||||
-rw-r--r-- | target-openrisc/sys_helper.c | 38 |
2 files changed, 19 insertions, 20 deletions
diff --git a/target-openrisc/cpu.h b/target-openrisc/cpu.h index 8fd0bc0bf0..0f9efdf6de 100644 --- a/target-openrisc/cpu.h +++ b/target-openrisc/cpu.h @@ -373,6 +373,7 @@ void cpu_openrisc_pic_init(OpenRISCCPU *cpu); /* hw/openrisc_timer.c */ void cpu_openrisc_clock_init(OpenRISCCPU *cpu); void cpu_openrisc_count_update(OpenRISCCPU *cpu); +void cpu_openrisc_timer_update(OpenRISCCPU *cpu); void cpu_openrisc_count_start(OpenRISCCPU *cpu); void cpu_openrisc_count_stop(OpenRISCCPU *cpu); diff --git a/target-openrisc/sys_helper.c b/target-openrisc/sys_helper.c index cccbc0e939..f1165885d9 100644 --- a/target-openrisc/sys_helper.c +++ b/target-openrisc/sys_helper.c @@ -127,33 +127,31 @@ void HELPER(mtspr)(CPUOpenRISCState *env, break; case TO_SPR(10, 0): /* TTMR */ { + if ((env->ttmr & TTMR_M) ^ (rb & TTMR_M)) { + switch (rb & TTMR_M) { + case TIMER_NONE: + cpu_openrisc_count_stop(cpu); + break; + case TIMER_INTR: + case TIMER_SHOT: + case TIMER_CONT: + cpu_openrisc_count_start(cpu); + break; + default: + break; + } + } + int ip = env->ttmr & TTMR_IP; if (rb & TTMR_IP) { /* Keep IP bit. */ - env->ttmr = (rb & ~TTMR_IP) + ip; + env->ttmr = (rb & ~TTMR_IP) | ip; } else { /* Clear IP bit. */ env->ttmr = rb & ~TTMR_IP; cs->interrupt_request &= ~CPU_INTERRUPT_TIMER; } - cpu_openrisc_count_update(cpu); - - switch (env->ttmr & TTMR_M) { - case TIMER_NONE: - cpu_openrisc_count_stop(cpu); - break; - case TIMER_INTR: - cpu_openrisc_count_start(cpu); - break; - case TIMER_SHOT: - cpu_openrisc_count_start(cpu); - break; - case TIMER_CONT: - cpu_openrisc_count_start(cpu); - break; - default: - break; - } + cpu_openrisc_timer_update(cpu); } break; @@ -162,7 +160,7 @@ void HELPER(mtspr)(CPUOpenRISCState *env, if (env->ttmr & TIMER_NONE) { return; } - cpu_openrisc_count_start(cpu); + cpu_openrisc_timer_update(cpu); break; default: |