qemu-devel
[Top][All Lists]
Advanced

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

Re: [Qemu-devel] [PATCH] target-tilegx: Finish decoding the first TB blo


From: Chen Gang S
Subject: Re: [Qemu-devel] [PATCH] target-tilegx: Finish decoding the first TB block.
Date: Sun, 22 Feb 2015 08:25:06 +0800
User-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:31.0) Gecko/20100101 Thunderbird/31.4.0

On 2/22/15 00:33, Richard Henderson wrote:
> On 02/21/2015 07:31 AM, Chen Gang S wrote:
>>
>>  - We can still use the original pipes order: "y0, y2, y1" and "x0, x1".
> 
> I guess, sure, though I don't think that'll help as much as you imagine.
> 
>>  - y0, y2, and x0 need to use tcg temporary variables, but y1 and x1 can
>>    still use real variables.
> 
> Possibly, but I wouldn't structure it that way.  I'd have all of the pipes
> write to temporaries.
> 
>>  - y1 and x1 need to flush the temporary variables, they also need to
>>    consider about jump cases for tcg code (flush tcg temporary variables
>>    after comparing and before jump).
> 
> I wouldn't do that either.  I'd have y1/x1 record that a branch occurred, and
> the condition, but delay the flushing and branching to common code.
>

OK, thanks. For me, your idea is OK, it is more simpler (although with
more tcg temporary variables).

At present, the performance is not quite important, so I shall implement
the translation with the way which you provide below, thanks.

> For instance:
> 

The demo code below is much valuable to me, but I guess, it can be
improved too (the related reply is below):

> typedef enum ExitStatus {
>     NO_EXIT,         /* Fall through to next bundle */
>     EXIT_JUMP,       /* Normal branch exit */
>     EXIT_NORETURN    /* Exception taken (e.g. syscall) */
> } ExitStatus;
> 
> typedef struct DisasContext {
>     struct TranslationBlock *tb;
>     int mem_idx;
> 
>     uint64_t pc;
>     ExitStatus exit;
> 
>     int result_regs[3];
>     TCGv result_vals[3];
> 
>     TCGCond branch_cond;
>     TCGv branch_dest;
>     TCGv branch_val1;
>     TCGv branch_val2;
> } DisasContext;
> 
> 
> static void translate_one_bundle(DisasContext *dc, uint64_t bundle)
> {
>     int i;
> 
>     /* Initialize the per-bundle state of DC.  */
>     dc->exit = NO_EXIT;
>     for (i = 0; i < 3; ++i) {
>         dc->result_regs[i] = -1;
>         TCGV_UNUSED_I64(dc->result_vals[i]);
>     }
>     dc->branch_cond = TCG_COND_NEVER;
>     dc->branch_desti = -1;

It is branch_dest, not branch_desti.

>     TCGV_UNUSED_I64(dc->branch_dest);
>     TCGV_UNUSED_I64(dc->branch_val1);
>     TCGV_UNUSED_I64(dc->branch_val2);
> 
>     /* Decode all pipes, writing results into DC.  */
> 
>     /* If some pipe raises an exception, nothing left to do.  */
>     if (dc->exit == EXIT_NORETURN) {
>         return;
>     }
> 
>     /* Write back register results from all pipes.  */
>     for (i = 0; i < 3; ++i) {
>         int r = dc->result_regs[i];
>         if (r >= 0)
>             tcg_gen_mov_i64(cpu_regs[r], dc->result_vals[i]);
>             tcg_temp_free_i64(dc->result_vals[i]);
>         }
>     }
> 
>     /* Write back branch results, i.e. take the branch now.  */
>     if (dc->branch_cond != TCG_COND_NEVER) {
>         if (dc->branch_cond == TCG_COND_ALWAYS) {
>             /* Unconditional branch */
>             tcg_gen_mov_i64(cpu_pc, dc->branch_dest);
>         } else {
>             /* Conditional branch */
>             TCGv next_pc = tcg_const_i64(dc->pc + 8);
>             tcg_gen_movcond_i64(dc->branch_cond, cpu_pc,
>                                 dc->branch_val1, dc->branch_val2,
>                                 dc->branch_dest, next_pc);
>             tcg_temp_free_i64(dc->branch_val1);
>             tcg_temp_free_i64(dc->branch_val2);
>             tcg_temp_free_i64(next_pc);
>         }
>         tcg_temp_free_i64(dc->branch_dest);
>         dc->exit = EXIT_JUMP;

Do we need tcg_gen_exit_tb(0)? At present for simplify thinking, I always
use tcg_gen_exit_tb(0) for the end of one TB block.

>     }
> }
> 
> This mostly ignores the use of tcg_gen_goto_tb for now.  It's slightly more
> complicated to use, and it makes debugging execution traces a bit harder.
> Neither of which do you really want while bringing up the decoder.  However,
> the eventual use of goto_tb is why we want to delay performing the branch 
> until
> after writing back the registers, rather than simply writing to cpu_pc right 
> away.
>

Excuse me, I am not quite familiar with tcg_gen_goto/exit_tb(), at
present, I still don't understand their parameters.

I guess, they are for performance (tb chaining), so I simply only use
tcg_gen_exit_tb(0), at present.

Welcome more information about tcg_gen_goto_tb() and tcg_gen_exit_tb().


> I hope this is enough to get started properly.
> 

Yeah, it is really enough.

Thanks.
-- 
Chen Gang

Open, share, and attitude like air, water, and life which God blessed



reply via email to

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