mirror of
https://github.com/yuzu-emu/unicorn.git
synced 2025-01-14 15:25:30 +00:00
cpu-exec: Move exception handling out of cpu_exec()
Simplify cpu_exec() by extracting exception handling code out of cpu_exec() into a new static inline function cpu_handle_exception(). Also make cpu_handle_debug_exception() inline as it is used only once. Backports commit ea284766ec6b9f1712369249566b4c372f3cec8b from qemu
This commit is contained in:
parent
fc3d135dac
commit
c1b52a4387
118
qemu/cpu-exec.c
118
qemu/cpu-exec.c
|
@ -189,7 +189,7 @@ static inline bool cpu_handle_halt(CPUState *cpu)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void cpu_handle_debug_exception(CPUState *cpu)
|
static inline void cpu_handle_debug_exception(CPUState *cpu)
|
||||||
{
|
{
|
||||||
CPUClass *cc = CPU_GET_CLASS(cpu->uc, cpu);
|
CPUClass *cc = CPU_GET_CLASS(cpu->uc, cpu);
|
||||||
CPUWatchpoint *wp;
|
CPUWatchpoint *wp;
|
||||||
|
@ -203,6 +203,61 @@ static void cpu_handle_debug_exception(CPUState *cpu)
|
||||||
cc->debug_excp_handler(cpu);
|
cc->debug_excp_handler(cpu);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline bool cpu_handle_exception(struct uc_struct *uc, CPUState *cpu, int *ret)
|
||||||
|
{
|
||||||
|
struct hook *hook;
|
||||||
|
|
||||||
|
if (cpu->exception_index >= 0) {
|
||||||
|
if (uc->stop_interrupt && uc->stop_interrupt(cpu->exception_index)) {
|
||||||
|
cpu->halted = 1;
|
||||||
|
uc->invalid_error = UC_ERR_INSN_INVALID;
|
||||||
|
*ret = EXCP_HLT;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cpu->exception_index >= EXCP_INTERRUPT) {
|
||||||
|
/* exit request from the cpu execution loop */
|
||||||
|
*ret = cpu->exception_index;
|
||||||
|
if (*ret == EXCP_DEBUG) {
|
||||||
|
cpu_handle_debug_exception(cpu);
|
||||||
|
}
|
||||||
|
cpu->exception_index = -1;
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
#if defined(CONFIG_USER_ONLY)
|
||||||
|
/* if user mode only, we simulate a fake exception
|
||||||
|
which will be handled outside the cpu execution
|
||||||
|
loop */
|
||||||
|
#if defined(TARGET_I386)
|
||||||
|
CPUClass *cc = CPU_GET_CLASS(cpu);
|
||||||
|
cc->do_interrupt(cpu);
|
||||||
|
#endif
|
||||||
|
*ret = cpu->exception_index;
|
||||||
|
cpu->exception_index = -1;
|
||||||
|
return true;
|
||||||
|
#else
|
||||||
|
bool catched = false;
|
||||||
|
// Unicorn: call registered interrupt callbacks
|
||||||
|
HOOK_FOREACH_VAR_DECLARE;
|
||||||
|
HOOK_FOREACH(uc, hook, UC_HOOK_INTR) {
|
||||||
|
((uc_cb_hookintr_t)hook->callback)(uc, cpu->exception_index, hook->user_data);
|
||||||
|
catched = true;
|
||||||
|
}
|
||||||
|
// Unicorn: If un-catched interrupt, stop executions.
|
||||||
|
if (!catched) {
|
||||||
|
cpu->halted = 1;
|
||||||
|
uc->invalid_error = UC_ERR_EXCEPTION;
|
||||||
|
*ret = EXCP_HLT;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
cpu->exception_index = -1;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/* main execution loop */
|
/* main execution loop */
|
||||||
|
|
||||||
int cpu_exec(struct uc_struct *uc, CPUState *cpu)
|
int cpu_exec(struct uc_struct *uc, CPUState *cpu)
|
||||||
|
@ -215,7 +270,6 @@ int cpu_exec(struct uc_struct *uc, CPUState *cpu)
|
||||||
int ret, interrupt_request;
|
int ret, interrupt_request;
|
||||||
TranslationBlock *tb, *last_tb;
|
TranslationBlock *tb, *last_tb;
|
||||||
int tb_exit = 0;
|
int tb_exit = 0;
|
||||||
struct hook *hook;
|
|
||||||
|
|
||||||
if (cpu_handle_halt(cpu)) {
|
if (cpu_handle_halt(cpu)) {
|
||||||
return EXCP_HALTED;
|
return EXCP_HALTED;
|
||||||
|
@ -232,66 +286,16 @@ int cpu_exec(struct uc_struct *uc, CPUState *cpu)
|
||||||
cpu->exception_index = -1;
|
cpu->exception_index = -1;
|
||||||
env->invalid_error = UC_ERR_OK;
|
env->invalid_error = UC_ERR_OK;
|
||||||
|
|
||||||
/* prepare setjmp context for exception handling */
|
|
||||||
for(;;) {
|
for(;;) {
|
||||||
|
/* prepare setjmp context for exception handling */
|
||||||
if (sigsetjmp(cpu->jmp_env, 0) == 0) {
|
if (sigsetjmp(cpu->jmp_env, 0) == 0) {
|
||||||
if (uc->stop_request || uc->invalid_error)
|
if (uc->stop_request || uc->invalid_error) {
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
/* if an exception is pending, we execute it here */
|
/* if an exception is pending, we execute it here */
|
||||||
if (cpu->exception_index >= 0) {
|
if (cpu_handle_exception(uc, cpu, &ret)) {
|
||||||
//printf(">>> GOT INTERRUPT. exception idx = %x\n", cpu->exception_index); // qq
|
break;
|
||||||
if (uc->stop_interrupt && uc->stop_interrupt(cpu->exception_index)) {
|
|
||||||
cpu->halted = 1;
|
|
||||||
uc->invalid_error = UC_ERR_INSN_INVALID;
|
|
||||||
ret = EXCP_HLT;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cpu->exception_index >= EXCP_INTERRUPT) {
|
|
||||||
/* exit request from the cpu execution loop */
|
|
||||||
ret = cpu->exception_index;
|
|
||||||
if (ret == EXCP_DEBUG) {
|
|
||||||
cpu_handle_debug_exception(cpu);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
} else {
|
|
||||||
#if defined(CONFIG_USER_ONLY)
|
|
||||||
/* if user mode only, we simulate a fake exception
|
|
||||||
which will be handled outside the cpu execution
|
|
||||||
loop */
|
|
||||||
#if defined(TARGET_I386)
|
|
||||||
cc->do_interrupt(cpu);
|
|
||||||
#endif
|
|
||||||
ret = cpu->exception_index;
|
|
||||||
break;
|
|
||||||
#else
|
|
||||||
bool catched = false;
|
|
||||||
// Unicorn: call registered interrupt callbacks
|
|
||||||
HOOK_FOREACH_VAR_DECLARE;
|
|
||||||
HOOK_FOREACH(uc, hook, UC_HOOK_INTR) {
|
|
||||||
((uc_cb_hookintr_t)hook->callback)(uc, cpu->exception_index, hook->user_data);
|
|
||||||
catched = true;
|
|
||||||
}
|
|
||||||
// Unicorn: If un-catched interrupt, stop executions.
|
|
||||||
if (!catched) {
|
|
||||||
cpu->halted = 1;
|
|
||||||
uc->invalid_error = UC_ERR_EXCEPTION;
|
|
||||||
ret = EXCP_HLT;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
cpu->exception_index = -1;
|
|
||||||
#if defined(TARGET_X86_64)
|
|
||||||
if (env->exception_is_int) {
|
|
||||||
// point EIP to the next instruction after INT
|
|
||||||
env->eip = env->exception_next_eip;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#if defined(TARGET_MIPS) || defined(TARGET_MIPS64)
|
|
||||||
env->active_tc.PC = uc->next_pc;
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
last_tb = NULL; /* forget the last executed TB after exception */
|
last_tb = NULL; /* forget the last executed TB after exception */
|
||||||
|
|
Loading…
Reference in a new issue