void HELPER(exception)(CPUXtensaState *env, uint32_t excp) { CPUState *cs = CPU(xtensa_env_get_cpu(env)); cs->exception_index = excp; if (excp == EXCP_DEBUG) { env->exception_taken = 0; } cpu_loop_exit(cs); }
void xtensa_irq_init(CPUXtensaState *env) { XtensaCPU *cpu = xtensa_env_get_cpu(env); env->irq_inputs = (void **)qemu_allocate_irqs( xtensa_set_irq, env, env->config->ninterrupt); if (xtensa_option_enabled(env->config, XTENSA_OPTION_TIMER_INTERRUPT) && env->config->nccompare > 0) { env->ccompare_timer = qemu_new_timer_ns(vm_clock, &xtensa_ccompare_cb, cpu); } }
static void do_unaligned_access(CPUXtensaState *env, target_ulong addr, int is_write, int is_user, uintptr_t retaddr) { XtensaCPU *cpu = xtensa_env_get_cpu(env); if (xtensa_option_enabled(env->config, XTENSA_OPTION_UNALIGNED_EXCEPTION) && !xtensa_option_enabled(env->config, XTENSA_OPTION_HW_ALIGNMENT)) { cpu_restore_state(CPU(cpu), retaddr); HELPER(exception_cause_vaddr)(env, env->pc, LOAD_STORE_ALIGNMENT_CAUSE, addr); } }
void cpu_loop(CPUXtensaState *env) { CPUState *cs = CPU(xtensa_env_get_cpu(env)); target_siginfo_t info; abi_ulong ret; int trapnr; while (1) { cpu_exec_start(cs); trapnr = cpu_exec(cs); cpu_exec_end(cs); process_queued_cpu_work(cs); env->sregs[PS] &= ~PS_EXCM; switch (trapnr) { case EXCP_INTERRUPT: break; case EXC_WINDOW_OVERFLOW4: xtensa_overflow4(env); break; case EXC_WINDOW_UNDERFLOW4: xtensa_underflow4(env); break; case EXC_WINDOW_OVERFLOW8: xtensa_overflow8(env); break; case EXC_WINDOW_UNDERFLOW8: xtensa_underflow8(env); break; case EXC_WINDOW_OVERFLOW12: xtensa_overflow12(env); break; case EXC_WINDOW_UNDERFLOW12: xtensa_underflow12(env); break; case EXC_USER: switch (env->sregs[EXCCAUSE]) { case ILLEGAL_INSTRUCTION_CAUSE: case PRIVILEGED_CAUSE: info.si_signo = TARGET_SIGILL; info.si_errno = 0; info.si_code = env->sregs[EXCCAUSE] == ILLEGAL_INSTRUCTION_CAUSE ? TARGET_ILL_ILLOPC : TARGET_ILL_PRVOPC; info._sifields._sigfault._addr = env->sregs[EPC1]; queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); break; case SYSCALL_CAUSE: env->pc += 3; ret = do_syscall(env, env->regs[2], env->regs[6], env->regs[3], env->regs[4], env->regs[5], env->regs[8], env->regs[9], 0, 0); switch (ret) { default: env->regs[2] = ret; break; case -TARGET_ERESTARTSYS: env->pc -= 3; break; case -TARGET_QEMU_ESIGRETURN: break; } break; case ALLOCA_CAUSE: env->sregs[PS] = deposit32(env->sregs[PS], PS_OWB_SHIFT, PS_OWB_LEN, env->sregs[WINDOW_BASE]); switch (env->regs[0] & 0xc0000000) { case 0x00000000: case 0x40000000: xtensa_rotate_window(env, -1); xtensa_underflow4(env); break; case 0x80000000: xtensa_rotate_window(env, -2); xtensa_underflow8(env); break; case 0xc0000000: xtensa_rotate_window(env, -3); xtensa_underflow12(env); break; } break; case INTEGER_DIVIDE_BY_ZERO_CAUSE: info.si_signo = TARGET_SIGFPE; info.si_errno = 0; info.si_code = TARGET_FPE_INTDIV; info._sifields._sigfault._addr = env->sregs[EPC1]; queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); break; case LOAD_PROHIBITED_CAUSE: case STORE_PROHIBITED_CAUSE: info.si_signo = TARGET_SIGSEGV; info.si_errno = 0; info.si_code = TARGET_SEGV_ACCERR; info._sifields._sigfault._addr = env->sregs[EXCVADDR]; queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); break; default: fprintf(stderr, "exccause = %d\n", env->sregs[EXCCAUSE]); g_assert_not_reached(); } break; case EXCP_DEBUG: info.si_signo = TARGET_SIGTRAP; info.si_errno = 0; info.si_code = TARGET_TRAP_BRKPT; queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); break; case EXC_DEBUG: default: fprintf(stderr, "trapnr = %d\n", trapnr); g_assert_not_reached(); } process_pending_signals(env); } }