TranslationBlock *orig_tb)
{
TranslationBlock *tb;
- target_ulong pc = orig_tb->pc;
- target_ulong cs_base = orig_tb->cs_base;
- uint64_t flags = orig_tb->flags;
/* Should never happen.
We only end up here when an existing TB is too long. */
if (max_cycles > CF_COUNT_MASK)
max_cycles = CF_COUNT_MASK;
- /* tb_gen_code can flush our orig_tb, invalidate it now */
- tb_phys_invalidate(orig_tb, -1);
- tb = tb_gen_code(cpu, pc, cs_base, flags,
+ tb = tb_gen_code(cpu, orig_tb->pc, orig_tb->cs_base, orig_tb->flags,
max_cycles | CF_NOCACHE);
+ tb->orig_tb = tcg_ctx.tb_ctx.tb_invalidated_flag ? NULL : orig_tb;
cpu->current_tb = tb;
/* execute the generated code */
trace_exec_tb_nocache(tb, tb->pc);
void *tc_ptr; /* pointer to the translated code */
/* next matching tb for physical address. */
struct TranslationBlock *phys_hash_next;
+ /* original tb when cflags has CF_NOCACHE */
+ struct TranslationBlock *orig_tb;
/* first and second physical page containing code. The lower bit
of the pointer tells the index in page_next[] */
struct TranslationBlock *page_next[2];
cs_base = tb->cs_base;
flags = tb->flags;
tb_phys_invalidate(tb, -1);
+ if (tb->cflags & CF_NOCACHE) {
+ if (tb->orig_tb) {
+ /* Invalidate original TB if this TB was generated in
+ * cpu_exec_nocache() */
+ tb_phys_invalidate(tb->orig_tb, -1);
+ }
+ tb_free(tb);
+ }
/* FIXME: In theory this could raise an exception. In practice
we have already translated the block once so it's probably ok. */
tb_gen_code(cpu, pc, cs_base, flags, cflags);