diff --git a/qemu/include/exec/gen-icount.h b/qemu/include/exec/gen-icount.h index 076dc70e..81396c83 100644 --- a/qemu/include/exec/gen-icount.h +++ b/qemu/include/exec/gen-icount.h @@ -50,7 +50,7 @@ static inline void gen_tb_start(TCGContext *tcg_ctx, TranslationBlock *tb) static inline void gen_tb_end(TCGContext *tcg_ctx, TranslationBlock *tb, int num_insns) { gen_set_label(tcg_ctx, tcg_ctx->exitreq_label); - tcg_gen_exit_tb(tcg_ctx, (uintptr_t)tb + TB_EXIT_REQUESTED); + tcg_gen_exit_tb(tcg_ctx, tb, TB_EXIT_REQUESTED); #if 0 if (tb->cflags & CF_USE_ICOUNT) { diff --git a/qemu/target/arm/translate-a64.c b/qemu/target/arm/translate-a64.c index 45459c7c..3c12d9f9 100644 --- a/qemu/target/arm/translate-a64.c +++ b/qemu/target/arm/translate-a64.c @@ -404,7 +404,7 @@ static inline void gen_goto_tb(DisasContext *s, int n, uint64_t dest) if (use_goto_tb(s, n, dest)) { tcg_gen_goto_tb(tcg_ctx, n); gen_a64_set_pc_im(s, dest); - tcg_gen_exit_tb(tcg_ctx, (intptr_t)tb + n); + tcg_gen_exit_tb(tcg_ctx, tb, n); s->base.is_jmp = DISAS_NORETURN; } else { gen_a64_set_pc_im(s, dest); @@ -14070,7 +14070,7 @@ static void aarch64_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu) gen_a64_set_pc_im(dc, dc->pc); /* fall through */ case DISAS_EXIT: - tcg_gen_exit_tb(tcg_ctx, 0); + tcg_gen_exit_tb(tcg_ctx, NULL, 0); break; case DISAS_JUMP: tcg_gen_lookup_and_goto_ptr(tcg_ctx); @@ -14099,7 +14099,7 @@ static void aarch64_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu) /* The helper doesn't necessarily throw an exception, but we * must go back to the main loop to check for interrupts anyway. */ - tcg_gen_exit_tb(tcg_ctx, 0); + tcg_gen_exit_tb(tcg_ctx, NULL, 0); break; } } diff --git a/qemu/target/arm/translate.c b/qemu/target/arm/translate.c index 90930c99..b3fe03c5 100644 --- a/qemu/target/arm/translate.c +++ b/qemu/target/arm/translate.c @@ -1028,7 +1028,7 @@ static inline void gen_bx_excret_final_code(DisasContext *s) if (is_singlestepping(s)) { gen_singlestep_exception(s); } else { - tcg_gen_exit_tb(tcg_ctx, 0); + tcg_gen_exit_tb(tcg_ctx, NULL, 0); } gen_set_label(tcg_ctx, excret_label); /* Yes: this is an exception return. @@ -4376,7 +4376,7 @@ static void gen_goto_tb(DisasContext *s, int n, target_ulong dest) if (use_goto_tb(s, dest)) { tcg_gen_goto_tb(tcg_ctx, n); gen_set_pc_im(s, dest); - tcg_gen_exit_tb(tcg_ctx, (uintptr_t)s->base.tb + n); + tcg_gen_exit_tb(tcg_ctx, s->base.tb, n); } else { gen_set_pc_im(s, dest); gen_goto_ptr(s); @@ -12907,7 +12907,7 @@ static void arm_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu) /* fall through */ default: /* indicate that the hash table must be used to find the next TB */ - tcg_gen_exit_tb(tcg_ctx, 0); + tcg_gen_exit_tb(tcg_ctx, NULL, 0); break; case DISAS_NORETURN: /* nothing more to generate */ @@ -12922,7 +12922,7 @@ static void arm_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu) /* The helper doesn't necessarily throw an exception, but we * must go back to the main loop to check for interrupts anyway. */ - tcg_gen_exit_tb(tcg_ctx, 0); + tcg_gen_exit_tb(tcg_ctx, NULL, 0); break; } case DISAS_WFE: diff --git a/qemu/target/i386/translate.c b/qemu/target/i386/translate.c index 7b99e63d..ecb98c64 100644 --- a/qemu/target/i386/translate.c +++ b/qemu/target/i386/translate.c @@ -2464,7 +2464,7 @@ static inline void gen_goto_tb(DisasContext *s, int tb_num, target_ulong eip) /* jump to same page: we can use a direct jump */ tcg_gen_goto_tb(tcg_ctx, tb_num); gen_jmp_im(s, eip); - tcg_gen_exit_tb(tcg_ctx, (uintptr_t)s->base.tb + tb_num); + tcg_gen_exit_tb(tcg_ctx, s->base.tb, tb_num); s->base.is_jmp = DISAS_NORETURN; } else { /* jump to another page */ @@ -2904,13 +2904,13 @@ do_gen_eob_worker(DisasContext *s, bool inhibit, bool recheck_tf, bool jr) gen_helper_debug(tcg_ctx, tcg_ctx->cpu_env); } else if (recheck_tf) { gen_helper_rechecking_single_step(tcg_ctx, tcg_ctx->cpu_env); - tcg_gen_exit_tb(tcg_ctx, 0); + tcg_gen_exit_tb(tcg_ctx, NULL, 0); } else if (s->tf) { gen_helper_single_step(tcg_ctx, tcg_ctx->cpu_env); } else if (jr) { tcg_gen_lookup_and_goto_ptr(tcg_ctx); } else { - tcg_gen_exit_tb(tcg_ctx, 0); + tcg_gen_exit_tb(tcg_ctx, NULL, 0); } s->base.is_jmp = DISAS_NORETURN; } @@ -8030,7 +8030,7 @@ case 0x101: gen_helper_vmrun(tcg_ctx, cpu_env, tcg_const_i32(tcg_ctx, s->aflag - 1), tcg_const_i32(tcg_ctx, s->pc - pc_start)); - tcg_gen_exit_tb(tcg_ctx, 0); + tcg_gen_exit_tb(tcg_ctx, NULL, 0); s->base.is_jmp = DISAS_NORETURN; break; diff --git a/qemu/target/m68k/translate.c b/qemu/target/m68k/translate.c index 09f0ee5e..e3d56e85 100644 --- a/qemu/target/m68k/translate.c +++ b/qemu/target/m68k/translate.c @@ -1528,10 +1528,10 @@ static void gen_jmp_tb(DisasContext *s, int n, uint32_t dest) } else if (use_goto_tb(s, dest)) { tcg_gen_goto_tb(tcg_ctx, n); tcg_gen_movi_i32(tcg_ctx, tcg_ctx->QREG_PC, dest); - tcg_gen_exit_tb(tcg_ctx, (uintptr_t)s->tb + n); + tcg_gen_exit_tb(tcg_ctx, s->tb, n); } else { gen_jmp_im(s, dest); - tcg_gen_exit_tb(tcg_ctx, 0); + tcg_gen_exit_tb(tcg_ctx, NULL, 0); } s->is_jmp = DISAS_TB_JUMP; } @@ -6416,7 +6416,7 @@ void gen_intermediate_code(CPUState *cs, TranslationBlock *tb) case DISAS_UPDATE: update_cc_op(dc); /* indicate that the hash table must be used to find the next TB */ - tcg_gen_exit_tb(tcg_ctx, 0); + tcg_gen_exit_tb(tcg_ctx, NULL, 0); break; case DISAS_TB_JUMP: /* nothing more to generate */ diff --git a/qemu/target/mips/translate.c b/qemu/target/mips/translate.c index a7b124bc..8d18e28b 100644 --- a/qemu/target/mips/translate.c +++ b/qemu/target/mips/translate.c @@ -4350,7 +4350,7 @@ static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest) if (use_goto_tb(ctx, dest)) { tcg_gen_goto_tb(tcg_ctx, n); gen_save_pc(ctx, dest); - tcg_gen_exit_tb(tcg_ctx, (uintptr_t)ctx->base.tb + n); + tcg_gen_exit_tb(tcg_ctx, ctx->base.tb, n); } else { gen_save_pc(ctx, dest); if (ctx->base.singlestep_enabled) { @@ -20534,7 +20534,7 @@ static void mips_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs) gen_goto_tb(ctx, 0, ctx->base.pc_next); break; case DISAS_EXIT: - tcg_gen_exit_tb(tcg_ctx, 0); + tcg_gen_exit_tb(tcg_ctx, NULL, 0); break; case DISAS_NORETURN: break; diff --git a/qemu/target/sparc/translate.c b/qemu/target/sparc/translate.c index 58dc1bb3..07820f9f 100644 --- a/qemu/target/sparc/translate.c +++ b/qemu/target/sparc/translate.c @@ -359,12 +359,12 @@ static inline void gen_goto_tb(DisasContext *s, int tb_num, tcg_gen_goto_tb(tcg_ctx, tb_num); tcg_gen_movi_tl(tcg_ctx, tcg_ctx->sparc_cpu_pc, pc); tcg_gen_movi_tl(tcg_ctx, tcg_ctx->cpu_npc, npc); - tcg_gen_exit_tb(tcg_ctx, (uintptr_t)s->base.tb + tb_num); + tcg_gen_exit_tb(tcg_ctx, s->base.tb, tb_num); } else { /* jump to another page: currently not optimized */ tcg_gen_movi_tl(tcg_ctx, tcg_ctx->sparc_cpu_pc, pc); tcg_gen_movi_tl(tcg_ctx, tcg_ctx->cpu_npc, npc); - tcg_gen_exit_tb(tcg_ctx, 0); + tcg_gen_exit_tb(tcg_ctx, NULL, 0); } } @@ -4510,7 +4510,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn, bool hook_ins /* End TB to notice changed ASI. */ save_state(dc); gen_op_next_insn(dc); - tcg_gen_exit_tb(tcg_ctx, 0); + tcg_gen_exit_tb(tcg_ctx, NULL, 0); dc->base.is_jmp = DISAS_NORETURN; break; case 0x6: /* V9 wrfprs */ @@ -4519,7 +4519,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn, bool hook_ins dc->fprs_dirty = 0; save_state(dc); gen_op_next_insn(dc); - tcg_gen_exit_tb(tcg_ctx, 0); + tcg_gen_exit_tb(tcg_ctx, NULL, 0); dc->base.is_jmp = DISAS_NORETURN; break; case 0xf: /* V9 sir, nop if user */ @@ -4647,7 +4647,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn, bool hook_ins dc->cc_op = CC_OP_FLAGS; save_state(dc); gen_op_next_insn(dc); - tcg_gen_exit_tb(tcg_ctx, 0); + tcg_gen_exit_tb(tcg_ctx, NULL, 0); dc->base.is_jmp = DISAS_NORETURN; #endif } @@ -4803,7 +4803,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn, bool hook_ins hpstate)); save_state(dc); gen_op_next_insn(dc); - tcg_gen_exit_tb(tcg_ctx, 0); + tcg_gen_exit_tb(tcg_ctx, NULL, 0); dc->base.is_jmp = DISAS_NORETURN; break; case 1: // htstate @@ -5979,7 +5979,7 @@ static bool sparc_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs, save_state(dc); } gen_helper_debug(tcg_ctx, tcg_ctx->cpu_env); - tcg_gen_exit_tb(tcg_ctx, 0); + tcg_gen_exit_tb(tcg_ctx, NULL, 0); dc->base.is_jmp = DISAS_NORETURN; /* update pc_next so that the current instruction is included in tb->size */ dc->base.pc_next += 4; @@ -6026,7 +6026,7 @@ static void sparc_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs) tcg_gen_movi_tl(tcg_ctx, tcg_ctx->sparc_cpu_pc, dc->pc); } save_npc(dc); - tcg_gen_exit_tb(tcg_ctx, 0); + tcg_gen_exit_tb(tcg_ctx, NULL, 0); } } } diff --git a/qemu/tcg/tcg-op.c b/qemu/tcg/tcg-op.c index 9f4c0f02..e32fe7a6 100644 --- a/qemu/tcg/tcg-op.c +++ b/qemu/tcg/tcg-op.c @@ -2588,10 +2588,30 @@ void tcg_gen_extr32_i64(TCGContext *s, TCGv_i64 lo, TCGv_i64 hi, TCGv_i64 arg) /* QEMU specific operations. */ +void tcg_gen_exit_tb(TCGContext *s, TranslationBlock *tb, unsigned idx) +{ + uintptr_t val = (uintptr_t)tb + idx; + + if (tb == NULL) { + tcg_debug_assert(idx == 0); + } else if (idx <= TB_EXIT_IDXMAX) { +#ifdef CONFIG_DEBUG_TCG + /* This is an exit following a goto_tb. Verify that we have + seen this numbered exit before, via tcg_gen_goto_tb. */ + tcg_debug_assert(tcg_ctx->goto_tb_issue_mask & (1 << idx)); +#endif + } else { + /* This is an exit via the exitreq label. */ + tcg_debug_assert(idx == TB_EXIT_REQUESTED); + } + + tcg_gen_op1i(s, INDEX_op_exit_tb, val); +} + void tcg_gen_goto_tb(TCGContext *s, unsigned idx) { /* We only support two chained exits. */ - tcg_debug_assert(idx <= 1); + tcg_debug_assert(idx <= TB_EXIT_IDXMAX); #ifdef CONFIG_DEBUG_TCG /* Verify that we havn't seen this numbered exit before. */ tcg_debug_assert((s->goto_tb_issue_mask & (1 << idx)) == 0); @@ -2608,7 +2628,7 @@ void tcg_gen_lookup_and_goto_ptr(TCGContext *s) tcg_gen_op1i(s, INDEX_op_goto_ptr, tcgv_ptr_arg(s, ptr)); tcg_temp_free_ptr(s, ptr); } else { - tcg_gen_exit_tb(s, 0); + tcg_gen_exit_tb(s, NULL, 0); } } diff --git a/qemu/tcg/tcg-op.h b/qemu/tcg/tcg-op.h index 327718a6..0fa9f443 100644 --- a/qemu/tcg/tcg-op.h +++ b/qemu/tcg/tcg-op.h @@ -789,10 +789,19 @@ static inline void tcg_gen_insn_start(TCGContext *tcg_ctx, target_ulong pc, targ # error "Unhandled number of operands to insn_start" #endif -static inline void tcg_gen_exit_tb(TCGContext *s, uintptr_t val) -{ - tcg_gen_op1i(s, INDEX_op_exit_tb, val); -} +/** + * tcg_gen_exit_tb() - output exit_tb TCG operation + * @tb: The TranslationBlock from which we are exiting + * @idx: Direct jump slot index, or exit request + * + * See tcg/README for more info about this TCG operation. + * See also tcg.h and the block comment above TB_EXIT_MASK. + * + * For a normal exit from the TB, back to the main loop, @tb should + * be NULL and @idx should be 0. Otherwise, @tb should be valid and + * @idx should be one of the TB_EXIT_ values. + */ +void tcg_gen_exit_tb(TCGContext *s, TranslationBlock *tb, unsigned idx); /** * tcg_gen_goto_tb() - output goto_tb TCG operation diff --git a/qemu/tcg/tcg.h b/qemu/tcg/tcg.h index 21bd9946..8355fd5b 100644 --- a/qemu/tcg/tcg.h +++ b/qemu/tcg/tcg.h @@ -1373,9 +1373,10 @@ static inline unsigned get_mmuidx(TCGMemOpIdx oi) * to this default (which just calls the prologue.code emitted by * tcg_target_qemu_prologue()). */ -#define TB_EXIT_MASK 3 -#define TB_EXIT_IDX0 0 -#define TB_EXIT_IDX1 1 +#define TB_EXIT_MASK 3 +#define TB_EXIT_IDX0 0 +#define TB_EXIT_IDX1 1 +#define TB_EXIT_IDXMAX 1 #define TB_EXIT_ICOUNT_EXPIRED 2 #define TB_EXIT_REQUESTED 3