diff mbox

[v11,10/29] target/i386: [tcg] Refactor translate_insn

Message ID 149865462073.17063.17488435214703164893.stgit@frigg.lan (mailing list archive)
State New, archived
Headers show

Commit Message

Lluís Vilanova June 28, 2017, 12:57 p.m. UTC
Incrementally paves the way towards using the generic instruction translation
loop.

Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
---
 target/i386/translate.c |   72 +++++++++++++++++++++++++++++++----------------
 1 file changed, 48 insertions(+), 24 deletions(-)

Comments

Emilio Cota June 30, 2017, 12:41 a.m. UTC | #1
On Wed, Jun 28, 2017 at 15:57:00 +0300, Lluís Vilanova wrote:
> Incrementally paves the way towards using the generic instruction translation
> loop.
> 
> Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
> ---
>  target/i386/translate.c |   72 +++++++++++++++++++++++++++++++----------------
>  1 file changed, 48 insertions(+), 24 deletions(-)
> 
> diff --git a/target/i386/translate.c b/target/i386/translate.c
> index 3eee348de7..da4b409d97 100644
> --- a/target/i386/translate.c
> +++ b/target/i386/translate.c
> @@ -4420,15 +4420,17 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
>  
>  /* convert one instruction. s->base.is_jmp is set if the translation must
>     be stopped. Return the next pc value */
> -static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
> -                               target_ulong pc_start)
> +static target_ulong disas_insn(DisasContextBase *dcbase, CPUState *cpu)
>  {
> +    DisasContext *s = container_of(dcbase, DisasContext, base);
> +    CPUX86State *env = cpu->env_ptr;

Minor nit: you can pass dc (*s) here directly, no need for container_of

(snip)
> +static target_ulong i386_trblock_translate_insn(DisasContextBase *dcbase,
> +                                                CPUState *cpu)
> +{
> +    DisasContext *dc = container_of(dcbase, DisasContext, base);
> +    target_ulong pc_next = disas_insn(&dc->base, cpu);
> +
> +    if (dc->base.is_jmp) {
> +        return pc_next;
> +    }
> +
> +    if (dc->tf || (dc->base.tb->flags & HF_INHIBIT_IRQ_MASK)) {
> +        /* if single step mode, we generate only one instruction and
> +           generate an exception */
> +        /* if irq were inhibited with HF_INHIBIT_IRQ_MASK, we clear
> +           the flag and abort the translation to give the irqs a
> +           change to be happen */

I know you just moved lines around, but while at it, s/change to be/chance to/

Other than that,

Reviewed-by: Emilio G. Cota <cota@braap.org>

		E.
Richard Henderson July 2, 2017, 12:41 a.m. UTC | #2
On 06/28/2017 05:57 AM, Lluís Vilanova wrote:
> Incrementally paves the way towards using the generic instruction translation
> loop.
> 
> Signed-off-by: Lluís Vilanova<vilanova@ac.upc.edu>
> ---
>   target/i386/translate.c |   72 +++++++++++++++++++++++++++++++----------------
>   1 file changed, 48 insertions(+), 24 deletions(-)

Reviewed-by: Richard Henderson <rth@twiddle.net>


r~
Lluís Vilanova July 7, 2017, 9:25 a.m. UTC | #3
Emilio G Cota writes:

> On Wed, Jun 28, 2017 at 15:57:00 +0300, Lluís Vilanova wrote:
>> Incrementally paves the way towards using the generic instruction translation
>> loop.
>> 
>> Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
>> ---
>> target/i386/translate.c |   72 +++++++++++++++++++++++++++++++----------------
>> 1 file changed, 48 insertions(+), 24 deletions(-)
>> 
>> diff --git a/target/i386/translate.c b/target/i386/translate.c
>> index 3eee348de7..da4b409d97 100644
>> --- a/target/i386/translate.c
>> +++ b/target/i386/translate.c
>> @@ -4420,15 +4420,17 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
>> 
>> /* convert one instruction. s->base.is_jmp is set if the translation must
>> be stopped. Return the next pc value */
>> -static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
>> -                               target_ulong pc_start)
>> +static target_ulong disas_insn(DisasContextBase *dcbase, CPUState *cpu)
>> {
>> +    DisasContext *s = container_of(dcbase, DisasContext, base);
>> +    CPUX86State *env = cpu->env_ptr;

> Minor nit: you can pass dc (*s) here directly, no need for container_of
[...]

I prefer not to so that the code will work in the future (i.e., not assuming the
location of base inside disascontext).


Thanks,
  Lluis
Richard Henderson July 7, 2017, 3:18 p.m. UTC | #4
On 07/06/2017 11:25 PM, Lluís Vilanova wrote:
>>> /* convert one instruction. s->base.is_jmp is set if the translation must
>>> be stopped. Return the next pc value */
>>> -static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
>>> -                               target_ulong pc_start)
>>> +static target_ulong disas_insn(DisasContextBase *dcbase, CPUState *cpu)
>>> {
>>> +    DisasContext *s = container_of(dcbase, DisasContext, base);
>>> +    CPUX86State *env = cpu->env_ptr;
> 
>> Minor nit: you can pass dc (*s) here directly, no need for container_of
> [...]
> 
> I prefer not to so that the code will work in the future (i.e., not assuming the
> location of base inside disascontext).

There's clearly a misunderstanding here.

Emilio is saying that disas_insn is not a hook and private to the front-end. 
Therefore the argument to the function should be "DisasContet *s" and not 
"DisasContextBase *dcbase".

And I agree.  Passing DisasContext should be preferred where possible.


r~
Lluís Vilanova July 7, 2017, 5:05 p.m. UTC | #5
Richard Henderson writes:

> On 07/06/2017 11:25 PM, Lluís Vilanova wrote:
>>>> /* convert one instruction. s->base.is_jmp is set if the translation must
>>>> be stopped. Return the next pc value */
>>>> -static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
>>>> -                               target_ulong pc_start)
>>>> +static target_ulong disas_insn(DisasContextBase *dcbase, CPUState *cpu)
>>>> {
>>>> +    DisasContext *s = container_of(dcbase, DisasContext, base);
>>>> +    CPUX86State *env = cpu->env_ptr;
>> 
>>> Minor nit: you can pass dc (*s) here directly, no need for container_of
>> [...]
>> 
>> I prefer not to so that the code will work in the future (i.e., not assuming the
>> location of base inside disascontext).

> There's clearly a misunderstanding here.

> Emilio is saying that disas_insn is not a hook and private to the
> front-end. Therefore the argument to the function should be "DisasContet *s" and
> not "DisasContextBase *dcbase".

> And I agree.  Passing DisasContext should be preferred where possible.

Woooops, my bad! :)


Thanks,
  Lluis
diff mbox

Patch

diff --git a/target/i386/translate.c b/target/i386/translate.c
index 3eee348de7..da4b409d97 100644
--- a/target/i386/translate.c
+++ b/target/i386/translate.c
@@ -4420,15 +4420,17 @@  static void gen_sse(CPUX86State *env, DisasContext *s, int b,
 
 /* convert one instruction. s->base.is_jmp is set if the translation must
    be stopped. Return the next pc value */
-static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
-                               target_ulong pc_start)
+static target_ulong disas_insn(DisasContextBase *dcbase, CPUState *cpu)
 {
+    DisasContext *s = container_of(dcbase, DisasContext, base);
+    CPUX86State *env = cpu->env_ptr;
     int b, prefixes;
     int shift;
     TCGMemOp ot, aflag, dflag;
     int modrm, reg, rm, mod, op, opreg, val;
     target_ulong next_eip, tval;
     int rex_w, rex_r;
+    target_ulong pc_start = s->base.pc_next;
 
     s->pc_start = s->pc = pc_start;
     prefixes = 0;
@@ -8478,10 +8480,51 @@  static BreakpointCheckType i386_trblock_breakpoint_check(
     }
 }
 
+static target_ulong i386_trblock_translate_insn(DisasContextBase *dcbase,
+                                                CPUState *cpu)
+{
+    DisasContext *dc = container_of(dcbase, DisasContext, base);
+    target_ulong pc_next = disas_insn(&dc->base, cpu);
+
+    if (dc->base.is_jmp) {
+        return pc_next;
+    }
+
+    if (dc->tf || (dc->base.tb->flags & HF_INHIBIT_IRQ_MASK)) {
+        /* if single step mode, we generate only one instruction and
+           generate an exception */
+        /* if irq were inhibited with HF_INHIBIT_IRQ_MASK, we clear
+           the flag and abort the translation to give the irqs a
+           change to be happen */
+        gen_jmp_im(pc_next - dc->cs_base);
+        gen_eob(dc);
+        dc->base.is_jmp = DISAS_TOO_MANY;
+    } else if ((dc->base.tb->cflags & CF_USE_ICOUNT)
+               && ((dc->base.pc_next & TARGET_PAGE_MASK)
+                   != ((dc->base.pc_next + TARGET_MAX_INSN_SIZE - 1)
+                       & TARGET_PAGE_MASK)
+                   || (dc->base.pc_next & ~TARGET_PAGE_MASK) == 0)) {
+        /* Do not cross the boundary of the pages in icount mode,
+           it can cause an exception. Do it only when boundary is
+           crossed by the first instruction in the block.
+           If current instruction already crossed the bound - it's ok,
+           because an exception hasn't stopped this code.
+         */
+        gen_jmp_im(pc_next - dc->cs_base);
+        gen_eob(dc);
+        dc->base.is_jmp = DISAS_TOO_MANY;
+    } else if ((pc_next - dc->base.pc_first) >= (TARGET_PAGE_SIZE - 32)) {
+        gen_jmp_im(pc_next - dc->cs_base);
+        gen_eob(dc);
+        dc->base.is_jmp = DISAS_TOO_MANY;
+    }
+
+    return pc_next;
+}
+
 /* generate intermediate code for basic block 'tb'.  */
 void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb)
 {
-    CPUX86State *env = cpu->env_ptr;
     DisasContext dc1, *dc = &dc1;
     int num_insns;
     int max_insns;
@@ -8543,39 +8586,20 @@  void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb)
             gen_io_start();
         }
 
-        dc->base.pc_next = disas_insn(env, dc, dc->base.pc_next);
+        dc->base.pc_next = i386_trblock_translate_insn(&dc->base, cpu);
         /* stop translation if indicated */
         if (dc->base.is_jmp) {
             break;
         }
         /* if single step mode, we generate only one instruction and
            generate an exception */
-        /* if irq were inhibited with HF_INHIBIT_IRQ_MASK, we clear
-           the flag and abort the translation to give the irqs a
-           change to be happen */
-        if (dc->tf || dc->base.singlestep_enabled ||
-            (dc->base.tb->flags & HF_INHIBIT_IRQ_MASK)) {
-            gen_jmp_im(dc->base.pc_next - dc->cs_base);
-            gen_eob(dc);
-            break;
-        }
-        /* Do not cross the boundary of the pages in icount mode,
-           it can cause an exception. Do it only when boundary is
-           crossed by the first instruction in the block.
-           If current instruction already crossed the bound - it's ok,
-           because an exception hasn't stopped this code.
-         */
-        if ((tb->cflags & CF_USE_ICOUNT)
-            && ((dc->base.pc_next & TARGET_PAGE_MASK)
-                != ((dc->base.pc_next + TARGET_MAX_INSN_SIZE - 1) & TARGET_PAGE_MASK)
-                || (dc->base.pc_next & ~TARGET_PAGE_MASK) == 0)) {
+        if (dc->base.singlestep_enabled) {
             gen_jmp_im(dc->base.pc_next - dc->cs_base);
             gen_eob(dc);
             break;
         }
         /* if too long translation, stop generation too */
         if (tcg_op_buf_full() ||
-            (dc->base.pc_next - dc->base.pc_first) >= (TARGET_PAGE_SIZE - 32) ||
             num_insns >= max_insns) {
             gen_jmp_im(dc->base.pc_next - dc->cs_base);
             gen_eob(dc);