diff options
author | Max Filippov <jcmvbkbc@gmail.com> | 2011-09-06 03:55:48 +0400 |
---|---|---|
committer | Blue Swirl <blauwirbel@gmail.com> | 2011-09-10 16:57:39 +0000 |
commit | b994e91b00cce463bfd306482dfe21630e11bf68 (patch) | |
tree | 097173c01d0e318e0201f30c877927193fce0e57 /target-xtensa/op_helper.c | |
parent | 1ddeaa5d4277af76679d02bc59b08657c357aee6 (diff) |
target-xtensa: implement interrupt option
See ISA, 4.4.6 (interrupt option), 4.4.7 (high priority interrupt
option) and 4.4.8 (timer interrupt option) for details.
Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
Diffstat (limited to 'target-xtensa/op_helper.c')
-rw-r--r-- | target-xtensa/op_helper.c | 46 |
1 files changed, 46 insertions, 0 deletions
diff --git a/target-xtensa/op_helper.c b/target-xtensa/op_helper.c index d37f70dda5..0047fa3c22 100644 --- a/target-xtensa/op_helper.c +++ b/target-xtensa/op_helper.c @@ -338,3 +338,49 @@ void HELPER(dump_state)(void) { cpu_dump_state(env, stderr, fprintf, 0); } + +void HELPER(waiti)(uint32_t pc, uint32_t intlevel) +{ + env->pc = pc; + env->sregs[PS] = (env->sregs[PS] & ~PS_INTLEVEL) | + (intlevel << PS_INTLEVEL_SHIFT); + check_interrupts(env); + if (env->pending_irq_level) { + cpu_loop_exit(env); + return; + } + + if (xtensa_option_enabled(env->config, XTENSA_OPTION_TIMER_INTERRUPT)) { + int i; + uint32_t wake_ccount = env->sregs[CCOUNT] - 1; + + for (i = 0; i < env->config->nccompare; ++i) { + if (env->sregs[CCOMPARE + i] - env->sregs[CCOUNT] < + wake_ccount - env->sregs[CCOUNT]) { + wake_ccount = env->sregs[CCOMPARE + i]; + } + } + env->wake_ccount = wake_ccount; + qemu_mod_timer(env->ccompare_timer, qemu_get_clock_ns(vm_clock) + + muldiv64(wake_ccount - env->sregs[CCOUNT], + 1000000, env->config->clock_freq_khz)); + } + env->halt_clock = qemu_get_clock_ns(vm_clock); + env->halted = 1; + HELPER(exception)(EXCP_HLT); +} + +void HELPER(timer_irq)(uint32_t id, uint32_t active) +{ + xtensa_timer_irq(env, id, active); +} + +void HELPER(advance_ccount)(uint32_t d) +{ + xtensa_advance_ccount(env, d); +} + +void HELPER(check_interrupts)(CPUState *env) +{ + check_interrupts(env); +} |