qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] qemu branching internal questions
@ 2011-01-04 19:43 Mike Frysinger
  2011-01-05 10:59 ` Edgar E. Iglesias
  0 siblings, 1 reply; 5+ messages in thread
From: Mike Frysinger @ 2011-01-04 19:43 UTC (permalink / raw)
  To: qemu-devel

i've been working on a new architecture port, but i cant quite figure
out some of the intricacies from reading the code.  i have all the
simple stuff working for linux-user (register moves, immediate moves,
loads, stores, syscall emulation) and want to move on to the next big
piece -- code flow changes.

i cant quite figure out the difference between DISAS_TB_JUMP and
DISAS_JUMP.  the exec-all.h header says one is for "only pc was
modified dynamically" while the other is "only pc was modified
statically".  is this referring to conditional vs unconditional jumps
?  or is this referring to direct vs indirect jumps ?
conditional: if cc jump 1f;
unconditional: jump 1f;
direct: jump foo;
indirect: P0 = [SP++]; jump (P0);

along these lines, when should i be using gen_new_label,
gen_set_label, tcg_gen_brcond*, and tcg_gen_setcond* ?  should they
only be used with conditional code ?  or should unconditional jumps be
generating labels too ?

for conditional register assignments, i think i should be using these
too.  so something like:
  if CC R0 = R1;
should turn into:
  l = gen_new_label();
  tcg_gen_brcondi_tl(TCG_COND_NE, cpu_cc, T, l);
  tcg_gen_mov_tl(reg_dst, reg_src);
  gen_set_label(l);
and i dont need to flag this bit of code as a jump (e.g. DISAS_JUMP) ...

also, having gone through the ops already available in tcg-op.h, ive
managed to decode what they do except for these:
tcg_gen_{ld,st}{8,16,32}{u,s}
i thought originally they were for handling load/store insns, but they
didnt work for me, and then i found the tcg_gen_qemu_{ld,st}* ops.  so
what is the point of these ones ?
-mike

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [Qemu-devel] qemu branching internal questions
  2011-01-04 19:43 [Qemu-devel] qemu branching internal questions Mike Frysinger
@ 2011-01-05 10:59 ` Edgar E. Iglesias
  2011-01-06 18:47   ` Mike Frysinger
  0 siblings, 1 reply; 5+ messages in thread
From: Edgar E. Iglesias @ 2011-01-05 10:59 UTC (permalink / raw)
  To: Mike Frysinger; +Cc: qemu-devel

On Tue, Jan 04, 2011 at 02:43:11PM -0500, Mike Frysinger wrote:
> i've been working on a new architecture port, but i cant quite figure
> out some of the intricacies from reading the code.  i have all the
> simple stuff working for linux-user (register moves, immediate moves,
> loads, stores, syscall emulation) and want to move on to the next big
> piece -- code flow changes.
> 
> i cant quite figure out the difference between DISAS_TB_JUMP and
> DISAS_JUMP.  the exec-all.h header says one is for "only pc was
> modified dynamically" while the other is "only pc was modified
> statically".  is this referring to conditional vs unconditional jumps
> ?  or is this referring to direct vs indirect jumps ?
> conditional: if cc jump 1f;
> unconditional: jump 1f;
> direct: jump foo;
> indirect: P0 = [SP++]; jump (P0);

Hi Mike,

I think it's referering to the latter + some other rules but:
is_jmp is a port local var and the DISAS_XXX states are used in slightly
different ways by different ports depending on the needs. Some ports only
use some of the states. When branching, what really matters is how and when
you end the TB. You need to bring the runtime state up-to-date and end the
TB by potentially jumping to another one (tcg_gen_goto_tb) and by
exiting (tcg_gen_exit_tb).

To be able to jump directly between TB's you need to follow some rules:
Not jump across pages. Not jump from a TB that has modified it's TB
dependant CPU state in a dynamic way. Also the destination address must be
derived from data available at translation time, e.g not an indirect
register branch/jump. + I probably forgot something :). These rules
are related to the DISAS_XXX comments you were wondering about.

For some arch's branching is a fairly easy matter, for others it can be
quite complicated. Delayslots, MMU aborts, variable length ISA encoding
and other details can all come together to make things hairy. It's not
all 100% clear to me either so I hope I'm not missleading you here. If
so, someone will probably correct me.


> along these lines, when should i be using gen_new_label,
> gen_set_label, tcg_gen_brcond*, and tcg_gen_setcond* ?  should they
> only be used with conditional code ?

You can use these for translation of any insn, allthough typically they
are used for insns with conditional logic.


> or should unconditional jumps be generating labels too ?

No, that's not necessary.


> for conditional register assignments, i think i should be using these
> too.  so something like:
>   if CC R0 = R1;
> should turn into:
>   l = gen_new_label();
>   tcg_gen_brcondi_tl(TCG_COND_NE, cpu_cc, T, l);
>   tcg_gen_mov_tl(reg_dst, reg_src);
>   gen_set_label(l);
> and i dont need to flag this bit of code as a jump (e.g. DISAS_JUMP) ...

That's right.


> also, having gone through the ops already available in tcg-op.h, ive
> managed to decode what they do except for these:
> tcg_gen_{ld,st}{8,16,32}{u,s}
> i thought originally they were for handling load/store insns, but they
> didnt work for me, and then i found the tcg_gen_qemu_{ld,st}* ops.  so
> what is the point of these ones ?

tcg_gen_ld/st are for making loads/stores that do not operate on the guest
memory hierarchy. They operate on host memory and don't really have a
connection to guest load/stores. They can for example be used to bring
data to/from the CPU state into tcg variables to emulate some reg to reg
insn.

tcg_gen_qemu_ld/st are for emulating guest load/stores. These operate on
the guest memory hierarcy and may for example abort due to MMU related
aborts or the access may go to emulated I/O etc.

Cheers

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [Qemu-devel] qemu branching internal questions
  2011-01-05 10:59 ` Edgar E. Iglesias
@ 2011-01-06 18:47   ` Mike Frysinger
  2011-01-07  2:04     ` Edgar E. Iglesias
  0 siblings, 1 reply; 5+ messages in thread
From: Mike Frysinger @ 2011-01-06 18:47 UTC (permalink / raw)
  To: Edgar E. Iglesias; +Cc: qemu-devel

On Wed, Jan 5, 2011 at 05:59, Edgar E. Iglesias wrote:
> On Tue, Jan 04, 2011 at 02:43:11PM -0500, Mike Frysinger wrote:
>> i've been working on a new architecture port, but i cant quite figure
>> out some of the intricacies from reading the code.  i have all the
>> simple stuff working for linux-user (register moves, immediate moves,
>> loads, stores, syscall emulation) and want to move on to the next big
>> piece -- code flow changes.
>>
>> i cant quite figure out the difference between DISAS_TB_JUMP and
>> DISAS_JUMP.  the exec-all.h header says one is for "only pc was
>> modified dynamically" while the other is "only pc was modified
>> statically".  is this referring to conditional vs unconditional jumps
>> ?  or is this referring to direct vs indirect jumps ?
>> conditional: if cc jump 1f;
>> unconditional: jump 1f;
>> direct: jump foo;
>> indirect: P0 = [SP++]; jump (P0);
>
> I think it's referering to the latter + some other rules but:
> is_jmp is a port local var and the DISAS_XXX states are used in slightly
> different ways by different ports depending on the needs. Some ports only
> use some of the states. When branching, what really matters is how and when
> you end the TB. You need to bring the runtime state up-to-date and end the
> TB by potentially jumping to another one (tcg_gen_goto_tb) and by
> exiting (tcg_gen_exit_tb).
>
> To be able to jump directly between TB's you need to follow some rules:
> Not jump across pages. Not jump from a TB that has modified it's TB
> dependant CPU state in a dynamic way. Also the destination address must be
> derived from data available at translation time, e.g not an indirect
> register branch/jump. + I probably forgot something :). These rules
> are related to the DISAS_XXX comments you were wondering about.
>
> For some arch's branching is a fairly easy matter, for others it can be
> quite complicated. Delayslots, MMU aborts, variable length ISA encoding
> and other details can all come together to make things hairy. It's not
> all 100% clear to me either so I hope I'm not missleading you here. If
> so, someone will probably correct me.

thanks for the info ... my arch doesnt have to deal with crazy stuff
like that.  it has fixed insn length (2 or 4 bytes) and no delayed
branching.  so it should be somewhat like arm/i386 i think.

could you elaborate on the tcg_gen_goto_tb and tcg_gen_exit_tb stuff ?
 i think i have all the other pieces squared away in my head now
(labels/branches/conditions).  but i cant quite grasp the meaning of
the arguments to the tb goto/exit points.

this x86_64 asm has direct correlations to my own ISA:
.global _start
_start:
        mov $60, %rax
        mov $6, %rcx
        mov $0, %rbx
1:      add $1, %rbx
        cmp %rcx, %rbx
        jl 1b
        int $0x80;
basically i set the syscall number to __NR_exit, set the first
argument to 0, and then increment it until the argument is 6.  then
the program exits with status of 6.

the tcg ops that the branch generates are:
 movi_i32 cc_op,$0x11
 add_i64 tmp8,cc_dst,cc_src
 brcond_i64 tmp8,cc_src,lt,$0x0
 goto_tb $0x0
 movi_i64 tmp4,$0x4000ce
 st_i64 tmp4,env,$0x80
 exit_tb $0x7fd7a475f088
 set_label $0x0
 goto_tb $0x1
 movi_i64 tmp4,$0x4000c5
 st_i64 tmp4,env,$0x80
 exit_tb $0x7fd7a475f089

what meaning do the goto_tb arguments (0 and 1) have ?  the exit_tb
args appear to be the actual tb pointers, but for some reason the
second one is set to the pointer+1.  i guess this is significant ?

when i attempt to generate the same thing, qemu hits a loop on me.  i
guess i'll have to throw both into gdb and find out where it is going
wrong.
-mike

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [Qemu-devel] qemu branching internal questions
  2011-01-06 18:47   ` Mike Frysinger
@ 2011-01-07  2:04     ` Edgar E. Iglesias
  2011-01-07  3:05       ` Mike Frysinger
  0 siblings, 1 reply; 5+ messages in thread
From: Edgar E. Iglesias @ 2011-01-07  2:04 UTC (permalink / raw)
  To: Mike Frysinger; +Cc: qemu-devel

On Thu, Jan 06, 2011 at 01:47:56PM -0500, Mike Frysinger wrote:
> On Wed, Jan 5, 2011 at 05:59, Edgar E. Iglesias wrote:
> > On Tue, Jan 04, 2011 at 02:43:11PM -0500, Mike Frysinger wrote:
> >> i've been working on a new architecture port, but i cant quite figure
> >> out some of the intricacies from reading the code.  i have all the
> >> simple stuff working for linux-user (register moves, immediate moves,
> >> loads, stores, syscall emulation) and want to move on to the next big
> >> piece -- code flow changes.
> >>
> >> i cant quite figure out the difference between DISAS_TB_JUMP and
> >> DISAS_JUMP.  the exec-all.h header says one is for "only pc was
> >> modified dynamically" while the other is "only pc was modified
> >> statically".  is this referring to conditional vs unconditional jumps
> >> ?  or is this referring to direct vs indirect jumps ?
> >> conditional: if cc jump 1f;
> >> unconditional: jump 1f;
> >> direct: jump foo;
> >> indirect: P0 = [SP++]; jump (P0);
> >
> > I think it's referering to the latter + some other rules but:
> > is_jmp is a port local var and the DISAS_XXX states are used in slightly
> > different ways by different ports depending on the needs. Some ports only
> > use some of the states. When branching, what really matters is how and when
> > you end the TB. You need to bring the runtime state up-to-date and end the
> > TB by potentially jumping to another one (tcg_gen_goto_tb) and by
> > exiting (tcg_gen_exit_tb).
> >
> > To be able to jump directly between TB's you need to follow some rules:
> > Not jump across pages. Not jump from a TB that has modified it's TB
> > dependant CPU state in a dynamic way. Also the destination address must be
> > derived from data available at translation time, e.g not an indirect
> > register branch/jump. + I probably forgot something :). These rules
> > are related to the DISAS_XXX comments you were wondering about.
> >
> > For some arch's branching is a fairly easy matter, for others it can be
> > quite complicated. Delayslots, MMU aborts, variable length ISA encoding
> > and other details can all come together to make things hairy. It's not
> > all 100% clear to me either so I hope I'm not missleading you here. If
> > so, someone will probably correct me.
> 
> thanks for the info ... my arch doesnt have to deal with crazy stuff
> like that.  it has fixed insn length (2 or 4 bytes) and no delayed
> branching.  so it should be somewhat like arm/i386 i think.
> 
> could you elaborate on the tcg_gen_goto_tb and tcg_gen_exit_tb stuff ?
>  i think i have all the other pieces squared away in my head now
> (labels/branches/conditions).  but i cant quite grasp the meaning of
> the arguments to the tb goto/exit points.

IIUC: 
Every TB can goto_tb to max two other different destinations. There are
two jump slots. tcg_gen_goto_tb takes a jump slot index as an arg,
0 or 1. These jumps will only take place if the TB's get chained,
you need to tcg_gen_exit_tb with (tb | index) for that to ever happen.
tcg_gen_exit_tb should be called with the ptr of the current tb OR:ed
with the index of the taken jump slot.

Chaining will allow TB's to run back to back after eachother, but note
that it will not happen the first time and also TB's can at any time
get unchained (e.g due to interrrupts).

If you tcg_gen_exit_tb(0), chaining will not happen and a new TB
will be looked up based on the CPU state (can still be a jump). A
bit slower but needed in some cases (for example if you change the
TB dependant CPU state dynamically + the other rules I mentioned in
the previous email).


> this x86_64 asm has direct correlations to my own ISA:
> .global _start
> _start:
>         mov $60, %rax
>         mov $6, %rcx
>         mov $0, %rbx
> 1:      add $1, %rbx
>         cmp %rcx, %rbx
>         jl 1b
>         int $0x80;
> basically i set the syscall number to __NR_exit, set the first
> argument to 0, and then increment it until the argument is 6.  then
> the program exits with status of 6.
> 
> the tcg ops that the branch generates are:
>  movi_i32 cc_op,$0x11
>  add_i64 tmp8,cc_dst,cc_src
>  brcond_i64 tmp8,cc_src,lt,$0x0
>  goto_tb $0x0
>  movi_i64 tmp4,$0x4000ce
>  st_i64 tmp4,env,$0x80
>  exit_tb $0x7fd7a475f088
>  set_label $0x0
>  goto_tb $0x1
>  movi_i64 tmp4,$0x4000c5
>  st_i64 tmp4,env,$0x80
>  exit_tb $0x7fd7a475f089
> 
> what meaning do the goto_tb arguments (0 and 1) have ?  the exit_tb
> args appear to be the actual tb pointers, but for some reason the
> second one is set to the pointer+1.  i guess this is significant ?

Yes, it let's the chaning machinery know which jump index should be
chained to the next tb.

You'll have to check the details in the code but I hope this gets
you going.

Cheers

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [Qemu-devel] qemu branching internal questions
  2011-01-07  2:04     ` Edgar E. Iglesias
@ 2011-01-07  3:05       ` Mike Frysinger
  0 siblings, 0 replies; 5+ messages in thread
From: Mike Frysinger @ 2011-01-07  3:05 UTC (permalink / raw)
  To: Edgar E. Iglesias; +Cc: qemu-devel

On Thu, Jan 6, 2011 at 21:04, Edgar E. Iglesias wrote:
> You'll have to check the details in the code but I hope this gets
> you going.

thanks, that info was perfect.  it allowed me to understand better
what qemu actually was doing and track down the problem.  i thought
the infinite loop/hang was due to my jump code being wrong when it
turned out my tcg_gen_setcondi_tl was accidentally passing the same
two registers (typo in the 2nd arg).

now that i know that i can rely on searching for the pc all the time
via tcg_gen_exit_tb(0), i can focus on making things functional.  then
i can refocus on optimizing things via direct chaining.

your help has saved me a ton of time !  i'll see about turning it into
the wiki and/or tcg/README to help others in the future.
-mike

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2011-01-07  3:06 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-01-04 19:43 [Qemu-devel] qemu branching internal questions Mike Frysinger
2011-01-05 10:59 ` Edgar E. Iglesias
2011-01-06 18:47   ` Mike Frysinger
2011-01-07  2:04     ` Edgar E. Iglesias
2011-01-07  3:05       ` Mike Frysinger

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).