qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-devel] Instruction trace for ARM target


From: Stuart Brady
Subject: Re: [Qemu-devel] Instruction trace for ARM target
Date: Mon, 7 Apr 2008 22:58:44 +0100
User-agent: Mutt/1.5.13 (2006-08-11)

On Fri, Apr 04, 2008 at 05:10:51PM +0200, Klaus Goffart wrote:
> Am Donnerstag, den 03.04.2008, 15:13 +0100 schrieb Stuart Brady: 
> > Calling gen_op_dump_pc() adds the code
> > needed to call helper_dump_pc() to the translation block that is
> > currently being generated.
> 
> Just to make sure I picked it up right. The call of gen_op_dump_pc()
> during translation adds the op_dump_pc() to the generated micro
> instruction stream of the translation block.

That's right.

> When the TB is executed, the op_dump_pc() operation is called

Well, op_dump_pc() is never called, as its code is instead copied into
the generated TB, but I think that's what you meant anyway.

> calling helper_dump_pc() with PARAM1. PARAM1 in op_dump_pc() is the
> first parameter passed to gen_op_dump_pc(), i.e. s->pc. So the pc
> values to be traced are included into the micro instruction stream 
> and printed at execution time, right?

That's correct.  It would be better to avoid an immediate load of the
emulated PC for each instruction -- with dyngen, doing so would not be
very practical, as we'd really prefer to hold the emulated PC in an
extra register -- but with TCG, that shouldn't really be a problem.

> > If by 'actual pc value', you mean the PC in the CPUState ('env'), then
> > I'm very surprised that this would appear to produce correct output.
> 
> No, my helper_dump_pc() looks like this:
> 
> void helper_dump_pc(target_ulong pc) 
> {
>     if (logfile)
>     {
>       fputc('#', logfile);
>         fwrite(&pc, sizeof(pc), 1, logfile);
>         insn = ldl_code(pc);
>         fwrite(&insn, sizeof(insn), 1, logfile);
>     } 
> }

Okay, that looks roughly correct -- although if you plan for anyone else
to use that code, it would be preferable to produce the same output on
big-endian and little-endian machines.

> > Well, you'd certainly have to generate extra ops to mark instructions as
> > executed, as instruction fetches occur at translation time. 
> 
> OK, so conditional instructions are skipped by a jump to the next
> instruction if the condition code fails. This is what I found in the
> documentation. In the code it looks like this jump is also a micro
> operation. Therefore, an op should be placed right after the jump_op
> that marks the last dumped instruction as executed. Is this what you
> meant?

Actually, I'd forgotten about ARM's conditional execution, and was
talking about conditional branches.  I expect that translated code can
still be generated after a conditional branch, but never executed, as a
result of that branch always (or perhaps never) being taken.

What I meant was that you cannot mark instructions as executed by adding
extra code to ldl_code(), but thanks to conditional execution, that was
already rather more obvious than I had realised.

Placing the dump_pc op after the jump op sounds correct, but you'll also
need to deal with unconditional instructions, and conditional branches.
Bear in mind that the program counter is incremented after ldl_code() is
called, though.

I wonder, does a branch count as 'executed' if and only if it is taken?
What about branches with static 'taken' or 'not taken' prediction?

Cheers,
-- 
Stuart Brady




reply via email to

[Prev in Thread] Current Thread [Next in Thread]