mirror of
https://github.com/yuzu-emu/unicorn.git
synced 2025-06-25 05:51:16 +00:00
tcg: Clean up from 'next_tb'
The value returned from tcg_qemu_tb_exec() is the value passed to the corresponding tcg_gen_exit_tb() at translation time of the last TB attempted to execute. It is a little confusing to store it in a variable named 'next_tb'. In fact, it is a combination of 4-byte aligned pointer and additional information in its two least significant bits. Break it down right away into two variables named 'last_tb' and 'tb_exit' which are a pointer to the last TB attempted to execute and the TB exit reason, correspondingly. This simplifies the code and improves its readability. Correct a misleading documentation comment for tcg_qemu_tb_exec() and fix logging in cpu_tb_exec(). Also rename a misleading 'next_tb' in another couple of places. Backports commit 819af24b9c1e95e6576f1cefd32f4d6bf56dfa56 from qemu
This commit is contained in:
parent
66faf3b5df
commit
c9700af2bd
|
@ -44,11 +44,10 @@ int cpu_exec(struct uc_struct *uc, CPUState *cpu)
|
||||||
X86CPU *x86_cpu = X86_CPU(uc, cpu);
|
X86CPU *x86_cpu = X86_CPU(uc, cpu);
|
||||||
#endif
|
#endif
|
||||||
int ret, interrupt_request;
|
int ret, interrupt_request;
|
||||||
TranslationBlock *tb;
|
TranslationBlock *tb, *last_tb;
|
||||||
uintptr_t next_tb;
|
int tb_exit = 0;
|
||||||
struct hook *hook;
|
struct hook *hook;
|
||||||
|
|
||||||
|
|
||||||
if (cpu->halted) {
|
if (cpu->halted) {
|
||||||
if (!cpu_has_work(cpu)) {
|
if (!cpu_has_work(cpu)) {
|
||||||
return EXCP_HALTED;
|
return EXCP_HALTED;
|
||||||
|
@ -130,7 +129,7 @@ int cpu_exec(struct uc_struct *uc, CPUState *cpu)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
next_tb = 0; /* force lookup of first TB */
|
last_tb = NULL; /* forget the last executed TB after exception */
|
||||||
for(;;) {
|
for(;;) {
|
||||||
interrupt_request = cpu->interrupt_request;
|
interrupt_request = cpu->interrupt_request;
|
||||||
|
|
||||||
|
@ -167,7 +166,7 @@ int cpu_exec(struct uc_struct *uc, CPUState *cpu)
|
||||||
True when it is, and we should restart on a new TB,
|
True when it is, and we should restart on a new TB,
|
||||||
and via longjmp via cpu_loop_exit. */
|
and via longjmp via cpu_loop_exit. */
|
||||||
if (cc->cpu_exec_interrupt(cpu, interrupt_request)) {
|
if (cc->cpu_exec_interrupt(cpu, interrupt_request)) {
|
||||||
next_tb = 0;
|
last_tb = NULL;
|
||||||
}
|
}
|
||||||
/* Don't use the cached interrupt_request value,
|
/* Don't use the cached interrupt_request value,
|
||||||
do_interrupt may have updated the EXITTB flag. */
|
do_interrupt may have updated the EXITTB flag. */
|
||||||
|
@ -175,7 +174,7 @@ int cpu_exec(struct uc_struct *uc, CPUState *cpu)
|
||||||
cpu->interrupt_request &= ~CPU_INTERRUPT_EXITTB;
|
cpu->interrupt_request &= ~CPU_INTERRUPT_EXITTB;
|
||||||
/* ensure that no TB jump will be modified as
|
/* ensure that no TB jump will be modified as
|
||||||
the program flow was changed */
|
the program flow was changed */
|
||||||
next_tb = 0;
|
last_tb = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (unlikely(cpu->exit_request)) {
|
if (unlikely(cpu->exit_request)) {
|
||||||
|
@ -195,22 +194,23 @@ int cpu_exec(struct uc_struct *uc, CPUState *cpu)
|
||||||
/* as some TB could have been invalidated because
|
/* as some TB could have been invalidated because
|
||||||
of memory exceptions while generating the code, we
|
of memory exceptions while generating the code, we
|
||||||
must recompute the hash index here */
|
must recompute the hash index here */
|
||||||
next_tb = 0;
|
last_tb = NULL;
|
||||||
tcg_ctx->tb_ctx.tb_invalidated_flag = 0;
|
tcg_ctx->tb_ctx.tb_invalidated_flag = 0;
|
||||||
}
|
}
|
||||||
/* See if we can patch the calling TB. */
|
/* See if we can patch the calling TB. */
|
||||||
if (next_tb != 0 && !qemu_loglevel_mask(CPU_LOG_TB_NOCHAIN)) {
|
if (last_tb && !qemu_loglevel_mask(CPU_LOG_TB_NOCHAIN)) {
|
||||||
tb_add_jump((TranslationBlock *)(next_tb & ~TB_EXIT_MASK),
|
tb_add_jump(last_tb, tb_exit, tb);
|
||||||
next_tb & TB_EXIT_MASK, tb);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (likely(!cpu->exit_request)) {
|
if (likely(!cpu->exit_request)) {
|
||||||
|
uintptr_t ret;
|
||||||
cpu->current_tb = tb;
|
cpu->current_tb = tb;
|
||||||
/* execute the generated code */
|
/* execute the generated code */
|
||||||
next_tb = cpu_tb_exec(cpu, tb);
|
ret = cpu_tb_exec(cpu, tb);
|
||||||
cpu->current_tb = NULL;
|
cpu->current_tb = NULL;
|
||||||
|
last_tb = (TranslationBlock *)(ret & ~TB_EXIT_MASK);
|
||||||
switch (next_tb & TB_EXIT_MASK) {
|
tb_exit = ret & TB_EXIT_MASK;
|
||||||
|
switch (tb_exit) {
|
||||||
case TB_EXIT_REQUESTED:
|
case TB_EXIT_REQUESTED:
|
||||||
/* Something asked us to stop executing
|
/* Something asked us to stop executing
|
||||||
* chained TBs; just continue round the main
|
* chained TBs; just continue round the main
|
||||||
|
@ -223,8 +223,7 @@ int cpu_exec(struct uc_struct *uc, CPUState *cpu)
|
||||||
* or cpu->interrupt_request.
|
* or cpu->interrupt_request.
|
||||||
*/
|
*/
|
||||||
smp_rmb();
|
smp_rmb();
|
||||||
tb = (TranslationBlock *)(next_tb & ~TB_EXIT_MASK);
|
last_tb = NULL;
|
||||||
next_tb = 0;
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
@ -277,46 +276,53 @@ static inline tcg_target_ulong cpu_tb_exec(CPUState *cpu, TranslationBlock *itb)
|
||||||
{
|
{
|
||||||
CPUArchState *env = cpu->env_ptr;
|
CPUArchState *env = cpu->env_ptr;
|
||||||
TCGContext *tcg_ctx = env->uc->tcg_ctx;
|
TCGContext *tcg_ctx = env->uc->tcg_ctx;
|
||||||
uintptr_t next_tb;
|
uintptr_t ret;
|
||||||
|
TranslationBlock *last_tb;
|
||||||
|
int tb_exit;
|
||||||
uint8_t *tb_ptr = itb->tc_ptr;
|
uint8_t *tb_ptr = itb->tc_ptr;
|
||||||
|
|
||||||
// Unicorn: commented out
|
// Unicorn: commented out
|
||||||
//qemu_log_mask_and_addr(CPU_LOG_EXEC, itb->pc,
|
//qemu_log_mask_and_addr(CPU_LOG_EXEC, itb->pc,
|
||||||
// "Trace %p [" TARGET_FMT_lx "] %s\n",
|
// "Trace %p [" TARGET_FMT_lx "] %s\n",
|
||||||
// itb->tc_ptr, itb->pc, lookup_symbol(itb->pc));
|
// itb->tc_ptr, itb->pc, lookup_symbol(itb->pc));
|
||||||
next_tb = tcg_qemu_tb_exec(env, tb_ptr);
|
ret = tcg_qemu_tb_exec(env, tb_ptr);
|
||||||
|
last_tb = (TranslationBlock *)(ret & ~TB_EXIT_MASK);
|
||||||
|
tb_exit = ret & TB_EXIT_MASK;
|
||||||
|
//trace_exec_tb_exit(last_tb, tb_exit);
|
||||||
|
|
||||||
if ((next_tb & TB_EXIT_MASK) > TB_EXIT_IDX1) {
|
if (tb_exit > TB_EXIT_IDX1) {
|
||||||
/* We didn't start executing this TB (eg because the instruction
|
/* We didn't start executing this TB (eg because the instruction
|
||||||
* counter hit zero); we must restore the guest PC to the address
|
* counter hit zero); we must restore the guest PC to the address
|
||||||
* of the start of the TB.
|
* of the start of the TB.
|
||||||
*/
|
*/
|
||||||
CPUClass *cc = CPU_GET_CLASS(env->uc, cpu);
|
CPUClass *cc = CPU_GET_CLASS(env->uc, cpu);
|
||||||
TranslationBlock *tb = (TranslationBlock *)(next_tb & ~TB_EXIT_MASK);
|
|
||||||
// Unicorn: commented out
|
// Unicorn: commented out
|
||||||
//qemu_log_mask_and_addr(CPU_LOG_EXEC, itb->pc,
|
//qemu_log_mask_and_addr(CPU_LOG_EXEC, last_tb->pc,
|
||||||
// "Stopped execution of TB chain before %p ["
|
// "Stopped execution of TB chain before %p ["
|
||||||
// TARGET_FMT_lx "] %s\n",
|
// TARGET_FMT_lx "] %s\n",
|
||||||
// itb->tc_ptr, itb->pc, lookup_symbol(itb->pc));
|
// last_tb->tc_ptr, last_tb->pc,
|
||||||
|
// lookup_symbol(last_tb->pc));
|
||||||
if (cc->synchronize_from_tb) {
|
if (cc->synchronize_from_tb) {
|
||||||
// avoid sync twice when helper_uc_tracecode() already did this.
|
// avoid sync twice when helper_uc_tracecode() already did this.
|
||||||
if (env->uc->emu_counter <= env->uc->emu_count &&
|
if (env->uc->emu_counter <= env->uc->emu_count &&
|
||||||
!env->uc->stop_request && !env->uc->quit_request)
|
!env->uc->stop_request && !env->uc->quit_request) {
|
||||||
cc->synchronize_from_tb(cpu, tb);
|
cc->synchronize_from_tb(cpu, last_tb);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
assert(cc->set_pc);
|
assert(cc->set_pc);
|
||||||
// avoid sync twice when helper_uc_tracecode() already did this.
|
// avoid sync twice when helper_uc_tracecode() already did this.
|
||||||
if (env->uc->emu_counter <= env->uc->emu_count && !env->uc->quit_request)
|
if (env->uc->emu_counter <= env->uc->emu_count && !env->uc->quit_request) {
|
||||||
cc->set_pc(cpu, tb->pc);
|
cc->set_pc(cpu, last_tb->pc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ((next_tb & TB_EXIT_MASK) == TB_EXIT_REQUESTED) {
|
}
|
||||||
|
if (tb_exit == TB_EXIT_REQUESTED) {
|
||||||
/* We were asked to stop executing TBs (probably a pending
|
/* We were asked to stop executing TBs (probably a pending
|
||||||
* interrupt. We've now stopped, so clear the flag.
|
* interrupt. We've now stopped, so clear the flag.
|
||||||
*/
|
*/
|
||||||
cpu->tcg_exit_req = 0;
|
cpu->tcg_exit_req = 0;
|
||||||
}
|
}
|
||||||
return next_tb;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static TranslationBlock *tb_find_slow(CPUState *cpu,
|
static TranslationBlock *tb_find_slow(CPUState *cpu,
|
||||||
|
|
|
@ -1062,7 +1062,7 @@ static inline unsigned get_mmuidx(TCGMemOpIdx oi)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* tcg_qemu_tb_exec:
|
* tcg_qemu_tb_exec:
|
||||||
* @env: CPUArchState * for the CPU
|
* @env: pointer to CPUArchState for the CPU
|
||||||
* @tb_ptr: address of generated code for the TB to execute
|
* @tb_ptr: address of generated code for the TB to execute
|
||||||
*
|
*
|
||||||
* Start executing code from a given translation block.
|
* Start executing code from a given translation block.
|
||||||
|
@ -1073,22 +1073,23 @@ static inline unsigned get_mmuidx(TCGMemOpIdx oi)
|
||||||
* which has not yet been directly linked, or an asynchronous
|
* which has not yet been directly linked, or an asynchronous
|
||||||
* event such as an interrupt needs handling.
|
* event such as an interrupt needs handling.
|
||||||
*
|
*
|
||||||
* The return value is a pointer to the next TB to execute
|
* Return: The return value is the value passed to the corresponding
|
||||||
* (if known; otherwise zero). This pointer is assumed to be
|
* tcg_gen_exit_tb() at translation time of the last TB attempted to execute.
|
||||||
* 4-aligned, and the bottom two bits are used to return further
|
* The value is either zero or a 4-byte aligned pointer to that TB combined
|
||||||
* information:
|
* with additional information in its two least significant bits. The
|
||||||
|
* additional information is encoded as follows:
|
||||||
* 0, 1: the link between this TB and the next is via the specified
|
* 0, 1: the link between this TB and the next is via the specified
|
||||||
* TB index (0 or 1). That is, we left the TB via (the equivalent
|
* TB index (0 or 1). That is, we left the TB via (the equivalent
|
||||||
* of) "goto_tb <index>". The main loop uses this to determine
|
* of) "goto_tb <index>". The main loop uses this to determine
|
||||||
* how to link the TB just executed to the next.
|
* how to link the TB just executed to the next.
|
||||||
* 2: we are using instruction counting code generation, and we
|
* 2: we are using instruction counting code generation, and we
|
||||||
* did not start executing this TB because the instruction counter
|
* did not start executing this TB because the instruction counter
|
||||||
* would hit zero midway through it. In this case the next-TB pointer
|
* would hit zero midway through it. In this case the pointer
|
||||||
* returned is the TB we were about to execute, and the caller must
|
* returned is the TB we were about to execute, and the caller must
|
||||||
* arrange to execute the remaining count of instructions.
|
* arrange to execute the remaining count of instructions.
|
||||||
* 3: we stopped because the CPU's exit_request flag was set
|
* 3: we stopped because the CPU's exit_request flag was set
|
||||||
* (usually meaning that there is an interrupt that needs to be
|
* handled). The pointer returned is the TB we were about to execute
|
||||||
* handled). The next-TB pointer returned is the TB we were
|
* when we noticed the pending exit request.
|
||||||
* about to execute when we noticed the pending exit request.
|
* about to execute when we noticed the pending exit request.
|
||||||
*
|
*
|
||||||
* If the bottom two bits indicate an exit-via-index then the CPU
|
* If the bottom two bits indicate an exit-via-index then the CPU
|
||||||
|
@ -1096,7 +1097,7 @@ static inline unsigned get_mmuidx(TCGMemOpIdx oi)
|
||||||
* TB (and in particular the guest PC is the address to execute next).
|
* TB (and in particular the guest PC is the address to execute next).
|
||||||
* Otherwise, we gave up on execution of this TB before it started, and
|
* Otherwise, we gave up on execution of this TB before it started, and
|
||||||
* the caller must fix up the CPU state by calling the CPU's
|
* the caller must fix up the CPU state by calling the CPU's
|
||||||
* synchronize_from_tb() method with the next-TB pointer we return (falling
|
* synchronize_from_tb() method with the TB pointer we return (falling
|
||||||
* back to calling the CPU's set_pc method with tb->pb if no
|
* back to calling the CPU's set_pc method with tb->pb if no
|
||||||
* synchronize_from_tb() method exists).
|
* synchronize_from_tb() method exists).
|
||||||
*
|
*
|
||||||
|
|
Loading…
Reference in a new issue