diff options
author | Richard Henderson <richard.henderson@linaro.org> | 2017-12-28 17:50:14 -0800 |
---|---|---|
committer | Richard Henderson <richard.henderson@linaro.org> | 2018-01-30 10:22:26 -0800 |
commit | 49c29d6c2e8ce2d3cddf9a92452d1ccb78051517 (patch) | |
tree | 08f9b4ec746793d61e0b7859f1224746138acfbd /target/hppa/op_helper.c | |
parent | 4f5f254808e1e317b407275724df7794a270c5c1 (diff) | |
download | qemu-49c29d6c2e8ce2d3cddf9a92452d1ccb78051517.zip qemu-49c29d6c2e8ce2d3cddf9a92452d1ccb78051517.tar.gz qemu-49c29d6c2e8ce2d3cddf9a92452d1ccb78051517.tar.bz2 |
target/hppa: Implement the interval timer
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Diffstat (limited to 'target/hppa/op_helper.c')
-rw-r--r-- | target/hppa/op_helper.c | 36 |
1 files changed, 36 insertions, 0 deletions
diff --git a/target/hppa/op_helper.c b/target/hppa/op_helper.c index 917d8de..8c546f4 100644 --- a/target/hppa/op_helper.c +++ b/target/hppa/op_helper.c @@ -22,6 +22,8 @@ #include "exec/exec-all.h" #include "exec/helper-proto.h" #include "exec/cpu_ldst.h" +#include "qemu/timer.h" + void QEMU_NORETURN HELPER(excp)(CPUHPPAState *env, int excp) { @@ -602,7 +604,41 @@ float64 HELPER(fmpynfadd_d)(CPUHPPAState *env, float64 a, float64 b, float64 c) return ret; } +target_ureg HELPER(read_interval_timer)(void) +{ +#ifdef CONFIG_USER_ONLY + /* In user-mode, QEMU_CLOCK_VIRTUAL doesn't exist. + Just pass through the host cpu clock ticks. */ + return cpu_get_host_ticks(); +#else + /* In system mode we have access to a decent high-resolution clock. + In order to make OS-level time accounting work with the cr16, + present it with a well-timed clock fixed at 250MHz. */ + return qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) >> 2; +#endif +} + #ifndef CONFIG_USER_ONLY +void HELPER(write_interval_timer)(CPUHPPAState *env, target_ureg val) +{ + HPPACPU *cpu = hppa_env_get_cpu(env); + uint64_t current = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); + uint64_t timeout; + + /* Even in 64-bit mode, the comparator is always 32-bit. But the + value we expose to the guest is 1/4 of the speed of the clock, + so moosh in 34 bits. */ + timeout = deposit64(current, 0, 34, (uint64_t)val << 2); + + /* If the mooshing puts the clock in the past, advance to next round. */ + if (timeout < current + 1000) { + timeout += 1ULL << 34; + } + + cpu->env.cr[CR_IT] = timeout; + timer_mod(cpu->alarm_timer, timeout); +} + target_ureg HELPER(swap_system_mask)(CPUHPPAState *env, target_ureg nsm) { target_ulong psw = env->psw; |