#include "exec.h"
#include "disas.h"
+#if !defined(CONFIG_SOFTMMU)
+#undef EAX
+#undef ECX
+#undef EDX
+#undef EBX
+#undef ESP
+#undef EBP
+#undef ESI
+#undef EDI
+#undef EIP
+#include <signal.h>
+#include <sys/ucontext.h>
+#endif
+
int tb_invalidated_flag;
//#define DEBUG_EXEC
}
#endif
+/* exit the current TB from a signal handler. The host registers are
+ restored in a state compatible with the CPU emulator
+ */
+void cpu_resume_from_signal(CPUState *env1, void *puc)
+{
+#if !defined(CONFIG_SOFTMMU)
+ struct ucontext *uc = puc;
+#endif
+
+ env = env1;
+
+ /* XXX: restore cpu registers saved in host registers */
+
+#if !defined(CONFIG_SOFTMMU)
+ if (puc) {
+ /* XXX: use siglongjmp ? */
+ sigprocmask(SIG_SETMASK, &uc->uc_sigmask, NULL);
+ }
+#endif
+ longjmp(env->jmp_env, 1);
+}
+
/* main execution loop */
int cpu_exec(CPUState *env1)
#if defined(TARGET_I386)
#ifdef reg_EAX
saved_EAX = EAX;
- EAX = env->regs[R_EAX];
#endif
#ifdef reg_ECX
saved_ECX = ECX;
- ECX = env->regs[R_ECX];
#endif
#ifdef reg_EDX
saved_EDX = EDX;
- EDX = env->regs[R_EDX];
#endif
#ifdef reg_EBX
saved_EBX = EBX;
- EBX = env->regs[R_EBX];
#endif
#ifdef reg_ESP
saved_ESP = ESP;
- ESP = env->regs[R_ESP];
#endif
#ifdef reg_EBP
saved_EBP = EBP;
- EBP = env->regs[R_EBP];
#endif
#ifdef reg_ESI
saved_ESI = ESI;
- ESI = env->regs[R_ESI];
#endif
#ifdef reg_EDI
saved_EDI = EDI;
- EDI = env->regs[R_EDI];
#endif
-
+
+ env_to_regs();
/* put eflags in CPU temporary format */
CC_SRC = env->eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
DF = 1 - (2 * ((env->eflags >> 10) & 1));
env->exception_next_eip, 0);
#elif defined(TARGET_PPC)
do_interrupt(env);
+#elif defined(TARGET_SPARC)
+ do_interrupt(env->exception_index,
+ 0,
+ env->error_code,
+ env->exception_next_pc, 0);
#endif
}
env->exception_index = -1;
(env->eflags & IF_MASK) &&
!(env->hflags & HF_INHIBIT_IRQ_MASK)) {
int intno;
- intno = cpu_x86_get_pic_interrupt(env);
- if (loglevel) {
+ env->interrupt_request &= ~CPU_INTERRUPT_HARD;
+ intno = cpu_get_pic_interrupt(env);
+ if (loglevel & CPU_LOG_TB_IN_ASM) {
fprintf(logfile, "Servicing hardware INT=0x%02x\n", intno);
}
do_interrupt(intno, 0, 0, 0, 1);
- env->interrupt_request &= ~CPU_INTERRUPT_HARD;
/* ensure that no TB jump will be modified as
the program flow was changed */
#ifdef __sparc__
#endif
}
#elif defined(TARGET_PPC)
+#if 0
+ if ((interrupt_request & CPU_INTERRUPT_RESET)) {
+ cpu_ppc_reset(env);
+ }
+#endif
+ if (msr_ee != 0) {
if ((interrupt_request & CPU_INTERRUPT_HARD)) {
- do_queue_exception(EXCP_EXTERNAL);
- if (check_exception_state(env))
+ /* Raise it */
+ env->exception_index = EXCP_EXTERNAL;
+ env->error_code = 0;
do_interrupt(env);
env->interrupt_request &= ~CPU_INTERRUPT_HARD;
+ } else if ((interrupt_request & CPU_INTERRUPT_TIMER)) {
+ /* Raise it */
+ env->exception_index = EXCP_DECR;
+ env->error_code = 0;
+ do_interrupt(env);
+ env->interrupt_request &= ~CPU_INTERRUPT_TIMER;
+ }
}
+#elif defined(TARGET_SPARC)
+ if (interrupt_request & CPU_INTERRUPT_HARD) {
+ do_interrupt(0, 0, 0, 0, 0);
+ env->interrupt_request &= ~CPU_INTERRUPT_HARD;
+ } else if (interrupt_request & CPU_INTERRUPT_TIMER) {
+ //do_interrupt(0, 0, 0, 0, 0);
+ env->interrupt_request &= ~CPU_INTERRUPT_TIMER;
+ }
#endif
if (interrupt_request & CPU_INTERRUPT_EXITTB) {
env->interrupt_request &= ~CPU_INTERRUPT_EXITTB;
}
}
#ifdef DEBUG_EXEC
- if (loglevel) {
+ if (loglevel & CPU_LOG_EXEC) {
#if defined(TARGET_I386)
/* restore flags in standard format */
env->regs[R_EAX] = EAX;
env->regs[R_EBP] = EBP;
env->regs[R_ESP] = ESP;
env->eflags = env->eflags | cc_table[CC_OP].compute_all() | (DF & DF_MASK);
- cpu_x86_dump_state(env, logfile, X86_DUMP_CCOP);
+ cpu_dump_state(env, logfile, fprintf, X86_DUMP_CCOP);
env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
#elif defined(TARGET_ARM)
env->cpsr = compute_cpsr();
- cpu_arm_dump_state(env, logfile, 0);
+ cpu_dump_state(env, logfile, fprintf, 0);
env->cpsr &= ~0xf0000000;
#elif defined(TARGET_SPARC)
- cpu_sparc_dump_state (env, logfile, 0);
+ cpu_dump_state (env, logfile, fprintf, 0);
#elif defined(TARGET_PPC)
- cpu_ppc_dump_state(env, logfile, 0);
+ cpu_dump_state(env, logfile, fprintf, 0);
#else
#error unsupported target CPU
#endif
spin_lock(&tb_lock);
tb_invalidated_flag = 0;
+
+ regs_to_env(); /* XXX: do it just before cpu_gen_code() */
/* find translated block using physical mappings */
phys_pc = get_phys_addr_code(env, (unsigned long)pc);
spin_unlock(&tb_lock);
}
#ifdef DEBUG_EXEC
- if (loglevel) {
+ if (loglevel & CPU_LOG_EXEC) {
fprintf(logfile, "Trace 0x%08lx [0x%08lx] %s\n",
(long)tb->tc_ptr, (long)tb->pc,
lookup_symbol((void *)tb->pc));
#endif
}
} else {
+ env_to_regs();
}
} /* for(;;) */
return ret;
}
+/* must only be called from the generated code as an exception can be
+ generated */
+void tb_invalidate_page_range(target_ulong start, target_ulong end)
+{
+ /* XXX: cannot enable it yet because it yields to MMU exception
+ where NIP != read address on PowerPC */
+#if 0
+ target_ulong phys_addr;
+ phys_addr = get_phys_addr_code(env, start);
+ tb_invalidate_phys_page_range(phys_addr, phys_addr + end - start, 0);
+#endif
+}
+
#if defined(TARGET_I386) && defined(CONFIG_USER_ONLY)
void cpu_x86_load_seg(CPUX86State *s, int seg_reg, int selector)
#endif /* TARGET_I386 */
-#undef EAX
-#undef ECX
-#undef EDX
-#undef EBX
-#undef ESP
-#undef EBP
-#undef ESI
-#undef EDI
-#undef EIP
-#include <signal.h>
-#include <sys/ucontext.h>
+#if !defined(CONFIG_SOFTMMU)
#if defined(TARGET_I386)
pc, address, is_write, *(unsigned long *)old_set);
#endif
/* XXX: locking issue */
- if (is_write && page_unprotect(address)) {
+ if (is_write && page_unprotect(address, pc, puc)) {
return 1;
}
+
/* see if it is an MMU fault */
ret = cpu_x86_handle_mmu_fault(env, address, is_write,
((env->hflags & HF_CPL_MASK) == 3), 0);
} else {
/* activate soft MMU for this block */
env->hflags |= HF_SOFTMMU_MASK;
- sigprocmask(SIG_SETMASK, old_set, NULL);
- cpu_loop_exit();
+ cpu_resume_from_signal(env, puc);
}
/* never comes here */
return 1;
void *puc)
{
/* XXX: locking issue */
- if (is_write && page_unprotect(address)) {
+ if (is_write && page_unprotect(address, pc, puc)) {
return 1;
}
return 0;
pc, address, is_write, *(unsigned long *)old_set);
#endif
/* XXX: locking issue */
- if (is_write && page_unprotect(address)) {
+ if (is_write && page_unprotect(address, pc, puc)) {
return 1;
}
/* we restore the process signal mask as the sigreturn should
do it (XXX: use sigsetjmp) */
sigprocmask(SIG_SETMASK, old_set, NULL);
- do_queue_exception_err(env->exception_index, env->error_code);
+ do_raise_exception_err(env->exception_index, env->error_code);
} else {
/* activate soft MMU for this block */
- sigprocmask(SIG_SETMASK, old_set, NULL);
- cpu_loop_exit();
+ cpu_resume_from_signal(env, puc);
}
/* never comes here */
return 1;
&uc->uc_sigmask, puc);
}
-#elif defined(__powerpc)
+#elif defined(__powerpc__)
+
+/***********************************************************************
+ * signal context platform-specific definitions
+ * From Wine
+ */
+#ifdef linux
+/* All Registers access - only for local access */
+# define REG_sig(reg_name, context) ((context)->uc_mcontext.regs->reg_name)
+/* Gpr Registers access */
+# define GPR_sig(reg_num, context) REG_sig(gpr[reg_num], context)
+# define IAR_sig(context) REG_sig(nip, context) /* Program counter */
+# define MSR_sig(context) REG_sig(msr, context) /* Machine State Register (Supervisor) */
+# define CTR_sig(context) REG_sig(ctr, context) /* Count register */
+# define XER_sig(context) REG_sig(xer, context) /* User's integer exception register */
+# define LR_sig(context) REG_sig(link, context) /* Link register */
+# define CR_sig(context) REG_sig(ccr, context) /* Condition register */
+/* Float Registers access */
+# define FLOAT_sig(reg_num, context) (((double*)((char*)((context)->uc_mcontext.regs+48*4)))[reg_num])
+# define FPSCR_sig(context) (*(int*)((char*)((context)->uc_mcontext.regs+(48+32*2)*4)))
+/* Exception Registers access */
+# define DAR_sig(context) REG_sig(dar, context)
+# define DSISR_sig(context) REG_sig(dsisr, context)
+# define TRAP_sig(context) REG_sig(trap, context)
+#endif /* linux */
+
+#ifdef __APPLE__
+# include <sys/ucontext.h>
+typedef struct ucontext SIGCONTEXT;
+/* All Registers access - only for local access */
+# define REG_sig(reg_name, context) ((context)->uc_mcontext->ss.reg_name)
+# define FLOATREG_sig(reg_name, context) ((context)->uc_mcontext->fs.reg_name)
+# define EXCEPREG_sig(reg_name, context) ((context)->uc_mcontext->es.reg_name)
+# define VECREG_sig(reg_name, context) ((context)->uc_mcontext->vs.reg_name)
+/* Gpr Registers access */
+# define GPR_sig(reg_num, context) REG_sig(r##reg_num, context)
+# define IAR_sig(context) REG_sig(srr0, context) /* Program counter */
+# define MSR_sig(context) REG_sig(srr1, context) /* Machine State Register (Supervisor) */
+# define CTR_sig(context) REG_sig(ctr, context)
+# define XER_sig(context) REG_sig(xer, context) /* Link register */
+# define LR_sig(context) REG_sig(lr, context) /* User's integer exception register */
+# define CR_sig(context) REG_sig(cr, context) /* Condition register */
+/* Float Registers access */
+# define FLOAT_sig(reg_num, context) FLOATREG_sig(fpregs[reg_num], context)
+# define FPSCR_sig(context) ((double)FLOATREG_sig(fpscr, context))
+/* Exception Registers access */
+# define DAR_sig(context) EXCEPREG_sig(dar, context) /* Fault registers for coredump */
+# define DSISR_sig(context) EXCEPREG_sig(dsisr, context)
+# define TRAP_sig(context) EXCEPREG_sig(exception, context) /* number of powerpc exception taken */
+#endif /* __APPLE__ */
int cpu_signal_handler(int host_signum, struct siginfo *info,
void *puc)
{
struct ucontext *uc = puc;
- struct pt_regs *regs = uc->uc_mcontext.regs;
unsigned long pc;
int is_write;
- pc = regs->nip;
+ pc = IAR_sig(uc);
is_write = 0;
#if 0
/* ppc 4xx case */
- if (regs->dsisr & 0x00800000)
+ if (DSISR_sig(uc) & 0x00800000)
is_write = 1;
#else
- if (regs->trap != 0x400 && (regs->dsisr & 0x02000000))
+ if (TRAP_sig(uc) != 0x400 && (DSISR_sig(uc) & 0x02000000))
is_write = 1;
#endif
return handle_cpu_signal(pc, (unsigned long)info->si_addr,
#error host CPU specific signal handler needed
#endif
+
+#endif /* !defined(CONFIG_SOFTMMU) */