+uint64_t idt_table[256];
+
+/* only dpl matters as we do only user space emulation */
+static void set_idt(int n, unsigned int dpl)
+{
+ set_gate(idt_table + n, 0, dpl, 0, 0);
+}
+
+void cpu_loop(CPUX86State *env)
+{
+ int trapnr;
+ uint8_t *pc;
+ target_siginfo_t info;
+
+ for(;;) {
+ trapnr = cpu_x86_exec(env);
+ switch(trapnr) {
+ case 0x80:
+ /* linux syscall */
+ env->regs[R_EAX] = do_syscall(env,
+ env->regs[R_EAX],
+ env->regs[R_EBX],
+ env->regs[R_ECX],
+ env->regs[R_EDX],
+ env->regs[R_ESI],
+ env->regs[R_EDI],
+ env->regs[R_EBP]);
+ break;
+ case EXCP0B_NOSEG:
+ case EXCP0C_STACK:
+ info.si_signo = SIGBUS;
+ info.si_errno = 0;
+ info.si_code = TARGET_SI_KERNEL;
+ info._sifields._sigfault._addr = 0;
+ queue_signal(info.si_signo, &info);
+ break;
+ case EXCP0D_GPF:
+ if (env->eflags & VM_MASK) {
+ handle_vm86_fault(env);
+ } else {
+ info.si_signo = SIGSEGV;
+ info.si_errno = 0;
+ info.si_code = TARGET_SI_KERNEL;
+ info._sifields._sigfault._addr = 0;
+ queue_signal(info.si_signo, &info);
+ }
+ break;
+ case EXCP0E_PAGE:
+ info.si_signo = SIGSEGV;
+ info.si_errno = 0;
+ if (!(env->error_code & 1))
+ info.si_code = TARGET_SEGV_MAPERR;
+ else
+ info.si_code = TARGET_SEGV_ACCERR;
+ info._sifields._sigfault._addr = env->cr[2];
+ queue_signal(info.si_signo, &info);
+ break;
+ case EXCP00_DIVZ:
+ if (env->eflags & VM_MASK) {
+ handle_vm86_trap(env, trapnr);
+ } else {
+ /* division by zero */
+ info.si_signo = SIGFPE;
+ info.si_errno = 0;
+ info.si_code = TARGET_FPE_INTDIV;
+ info._sifields._sigfault._addr = env->eip;
+ queue_signal(info.si_signo, &info);
+ }
+ break;
+ case EXCP01_SSTP:
+ case EXCP03_INT3:
+ if (env->eflags & VM_MASK) {
+ handle_vm86_trap(env, trapnr);
+ } else {
+ info.si_signo = SIGTRAP;
+ info.si_errno = 0;
+ if (trapnr == EXCP01_SSTP) {
+ info.si_code = TARGET_TRAP_BRKPT;
+ info._sifields._sigfault._addr = env->eip;
+ } else {
+ info.si_code = TARGET_SI_KERNEL;
+ info._sifields._sigfault._addr = 0;
+ }
+ queue_signal(info.si_signo, &info);
+ }
+ break;
+ case EXCP04_INTO:
+ case EXCP05_BOUND:
+ if (env->eflags & VM_MASK) {
+ handle_vm86_trap(env, trapnr);
+ } else {
+ info.si_signo = SIGSEGV;
+ info.si_errno = 0;
+ info.si_code = TARGET_SI_KERNEL;
+ info._sifields._sigfault._addr = 0;
+ queue_signal(info.si_signo, &info);
+ }
+ break;
+ case EXCP06_ILLOP:
+ info.si_signo = SIGILL;
+ info.si_errno = 0;
+ info.si_code = TARGET_ILL_ILLOPN;
+ info._sifields._sigfault._addr = env->eip;
+ queue_signal(info.si_signo, &info);
+ break;
+ case EXCP_INTERRUPT:
+ /* just indicate that signals should be handled asap */
+ break;
+ default:
+ pc = env->segs[R_CS].base + env->eip;
+ fprintf(stderr, "qemu: 0x%08lx: unhandled CPU exception 0x%x - aborting\n",
+ (long)pc, trapnr);
+ abort();
+ }
+ process_pending_signals(env);
+ }
+}
+#endif
+
+#ifdef TARGET_ARM
+
+void cpu_loop(CPUARMState *env)
+{
+ int trapnr;
+ unsigned int n, insn;
+ target_siginfo_t info;
+
+ for(;;) {
+ trapnr = cpu_arm_exec(env);
+ switch(trapnr) {
+ case EXCP_UDEF:
+ info.si_signo = SIGILL;
+ info.si_errno = 0;
+ info.si_code = TARGET_ILL_ILLOPN;
+ info._sifields._sigfault._addr = env->regs[15];
+ queue_signal(info.si_signo, &info);
+ break;
+ case EXCP_SWI:
+ {
+ /* system call */
+ insn = ldl((void *)(env->regs[15] - 4));
+ n = insn & 0xffffff;
+ if (n >= ARM_SYSCALL_BASE) {
+ /* linux syscall */
+ n -= ARM_SYSCALL_BASE;
+ env->regs[0] = do_syscall(env,
+ n,
+ env->regs[0],
+ env->regs[1],
+ env->regs[2],
+ env->regs[3],
+ env->regs[4],
+ 0);
+ } else {
+ goto error;
+ }
+ }
+ break;
+ case EXCP_INTERRUPT:
+ /* just indicate that signals should be handled asap */
+ break;
+ default:
+ error:
+ fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n",
+ trapnr);
+ cpu_arm_dump_state(env, stderr, 0);
+ abort();
+ }
+ process_pending_signals(env);
+ }
+}
+
+#endif
+
+#ifdef TARGET_SPARC
+
+void cpu_loop (CPUSPARCState *env)
+{
+ int trapnr;
+
+ while (1) {
+ trapnr = cpu_sparc_exec (env);
+
+ switch (trapnr) {
+ case 0x8: case 0x10:
+ env->regwptr[0] = do_syscall (env, env->gregs[1],
+ env->regwptr[0], env->regwptr[1], env->regwptr[2],
+ env->regwptr[3], env->regwptr[4], env->regwptr[13]);
+ if (env->regwptr[0] >= 0xffffffe0)
+ env->psr |= PSR_CARRY;
+ break;
+ default:
+ printf ("Invalid trap: %d\n", trapnr);
+ exit (1);
+ }
+ process_pending_signals (env);
+ }
+}
+
+#endif