summaryrefslogtreecommitdiff
path: root/target-xtensa/op_helper.c
diff options
context:
space:
mode:
authorMax Filippov <jcmvbkbc@gmail.com>2011-09-06 03:55:48 +0400
committerBlue Swirl <blauwirbel@gmail.com>2011-09-10 16:57:39 +0000
commitb994e91b00cce463bfd306482dfe21630e11bf68 (patch)
tree097173c01d0e318e0201f30c877927193fce0e57 /target-xtensa/op_helper.c
parent1ddeaa5d4277af76679d02bc59b08657c357aee6 (diff)
downloadqemu-b994e91b00cce463bfd306482dfe21630e11bf68.tar.gz
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.c46
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);
+}