On 26 January 2012 19:52, Xin Tong <xerox.time.t...@gmail.com> wrote: > It seems to me that when QEMU emits a TB to TB transition, it does not look > for whether the code has already been generated or not ( at least x86 on x86 > emulation) . it just lay down a 4 byte address, waiting to be patched later. > Am I right ?
Yes, sort of. For an initial translation this address gets patched by tb_set_jmp_target() later [tb_gen_code calls tb_link_page calls tb_reset_jump calls tb_set_jmp_target]. > case INDEX_op_goto_tb: > if (s->tb_jmp_offset) { > /* direct jump method */ > /* need to make sure that the jmp offset does not cross 32 byte > boundary on Intel chip > * and 8 byte boundary on AMD chip. As qemu is not checking for > processor type. Assume > * 8 byte boundary to be safe */ > tcg_out8(s, OPC_JMP_long); /* jmp im */ > s->tb_jmp_offset[args[0]] = s->code_ptr - s->code_buf; > tcg_out32(s, 0); I think technically this is a bug, though only a performance one: if we retranslate this block via cpu_restore_state() we'll write a zero immediate for the jump, which will break the TB link unnecessarily. It should be "s->code_ptr += 4" instead of "tcg_out32(s, 0)", I think. The only reason this doesn't have any visible effect is: (1) x86 doesn't have split icache/dcache so no incoherency issues (2) zero offset in an x86 JMP means "jump to following insn", which happens to be the semantics that op_goto_tb requires for a TB which isn't linked. On tcg/arm we have to be careful in the same situation to use tcg_out_b_noaddr() to skip the branch target rather than writing anything to it. -- PMM