qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH v2 00/10] target-i386 addressing cleanups
@ 2015-12-17 19:19 Richard Henderson
  2015-12-17 19:19 ` [Qemu-devel] [PATCH v2 01/10] target-i386: Create gen_lea_v_seg Richard Henderson
                   ` (9 more replies)
  0 siblings, 10 replies; 13+ messages in thread
From: Richard Henderson @ 2015-12-17 19:19 UTC (permalink / raw)
  To: qemu-devel; +Cc: pbonzini, aurelien, peter.maydell

This is a rebase of the patch set I posted in July.  There are no
substantive changes since then.

The only comment at the time was re 05/10, where Paolo suggests
optimizing access to CS overrides with the constant that we know
via the TB operands.  I chose to defer that, leaving things as
they are with a simple load from ENV.


r~


Richard Henderson (10):
  target-i386: Create gen_lea_v_seg
  target-i386: Introduce mo_stacksize
  target-i386: Use gen_lea_v_seg in gen_lea_modrm
  target-i386: Use gen_lea_v_seg in stack subroutines
  target-i386: Access segs via TCG registers
  target-i386: Use gen_lea_v_seg in pusha/popa
  target-i386: Rewrite gen_enter inline
  target-i386: Rewrite leave
  target-i386: Tidy gen_add_A0_im
  target-i386: Deconstruct the cpu_T array

 target-i386/helper.h     |    4 -
 target-i386/seg_helper.c |   74 --
 target-i386/translate.c  | 1714 +++++++++++++++++++++-------------------------
 3 files changed, 776 insertions(+), 1016 deletions(-)

-- 
2.5.0

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

* [Qemu-devel] [PATCH v2 01/10] target-i386: Create gen_lea_v_seg
  2015-12-17 19:19 [Qemu-devel] [PATCH v2 00/10] target-i386 addressing cleanups Richard Henderson
@ 2015-12-17 19:19 ` Richard Henderson
  2015-12-17 19:19 ` [Qemu-devel] [PATCH v2 02/10] target-i386: Introduce mo_stacksize Richard Henderson
                   ` (8 subsequent siblings)
  9 siblings, 0 replies; 13+ messages in thread
From: Richard Henderson @ 2015-12-17 19:19 UTC (permalink / raw)
  To: qemu-devel; +Cc: pbonzini, aurelien, peter.maydell

Add forgotten zero-extension in the TARGET_X86_64, !CODE64, ss32 case;
use this new function to implement gen_string_movl_A0_EDI,
gen_string_movl_A0_ESI, gen_add_A0_ds_seg.

Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 target-i386/translate.c | 160 ++++++++++++++++--------------------------------
 1 file changed, 53 insertions(+), 107 deletions(-)

diff --git a/target-i386/translate.c b/target-i386/translate.c
index a3dd167..3cc17f7 100644
--- a/target-i386/translate.c
+++ b/target-i386/translate.c
@@ -416,64 +416,18 @@ static inline void gen_op_add_reg_T0(TCGMemOp size, int reg)
     gen_op_mov_reg_v(size, reg, cpu_tmp0);
 }
 
-static inline void gen_op_addl_A0_reg_sN(int shift, int reg)
-{
-    tcg_gen_mov_tl(cpu_tmp0, cpu_regs[reg]);
-    if (shift != 0)
-        tcg_gen_shli_tl(cpu_tmp0, cpu_tmp0, shift);
-    tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_tmp0);
-    /* For x86_64, this sets the higher half of register to zero.
-       For i386, this is equivalent to a nop. */
-    tcg_gen_ext32u_tl(cpu_A0, cpu_A0);
-}
-
-static inline void gen_op_movl_A0_seg(int reg)
-{
-    tcg_gen_ld32u_tl(cpu_A0, cpu_env, offsetof(CPUX86State, segs[reg].base) + REG_L_OFFSET);
-}
-
 static inline void gen_op_addl_A0_seg(DisasContext *s, int reg)
 {
     tcg_gen_ld_tl(cpu_tmp0, cpu_env, offsetof(CPUX86State, segs[reg].base));
-#ifdef TARGET_X86_64
     if (CODE64(s)) {
-        tcg_gen_andi_tl(cpu_A0, cpu_A0, 0xffffffff);
+        tcg_gen_ext32u_tl(cpu_A0, cpu_A0);
         tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_tmp0);
     } else {
         tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_tmp0);
-        tcg_gen_andi_tl(cpu_A0, cpu_A0, 0xffffffff);
+        tcg_gen_ext32u_tl(cpu_A0, cpu_A0);
     }
-#else
-    tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_tmp0);
-#endif
 }
 
-#ifdef TARGET_X86_64
-static inline void gen_op_movq_A0_seg(int reg)
-{
-    tcg_gen_ld_tl(cpu_A0, cpu_env, offsetof(CPUX86State, segs[reg].base));
-}
-
-static inline void gen_op_addq_A0_seg(int reg)
-{
-    tcg_gen_ld_tl(cpu_tmp0, cpu_env, offsetof(CPUX86State, segs[reg].base));
-    tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_tmp0);
-}
-
-static inline void gen_op_movq_A0_reg(int reg)
-{
-    tcg_gen_mov_tl(cpu_A0, cpu_regs[reg]);
-}
-
-static inline void gen_op_addq_A0_reg_sN(int shift, int reg)
-{
-    tcg_gen_mov_tl(cpu_tmp0, cpu_regs[reg]);
-    if (shift != 0)
-        tcg_gen_shli_tl(cpu_tmp0, cpu_tmp0, shift);
-    tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_tmp0);
-}
-#endif
-
 static inline void gen_op_ld_v(DisasContext *s, int idx, TCGv t0, TCGv a0)
 {
     tcg_gen_qemu_ld_tl(t0, a0, s->mem_index, idx | MO_LE);
@@ -499,70 +453,78 @@ static inline void gen_jmp_im(target_ulong pc)
     gen_op_jmp_v(cpu_tmp0);
 }
 
-static inline void gen_string_movl_A0_ESI(DisasContext *s)
+/* Compute SEG:REG into A0.  SEG is selected from the override segment
+   (OVR_SEG) and the default segment (DEF_SEG).  OVR_SEG may be -1 to
+   indicate no override.  */
+static void gen_lea_v_seg(DisasContext *s, TCGv a0, int def_seg, int ovr_seg)
 {
-    int override;
+    TCGMemOp aflag = s->aflag;
 
-    override = s->override;
-    switch (s->aflag) {
+    switch (aflag) {
 #ifdef TARGET_X86_64
     case MO_64:
-        if (override >= 0) {
-            gen_op_movq_A0_seg(override);
-            gen_op_addq_A0_reg_sN(0, R_ESI);
-        } else {
-            gen_op_movq_A0_reg(R_ESI);
+        if (ovr_seg < 0) {
+            tcg_gen_mov_tl(cpu_A0, a0);
+            return;
         }
         break;
 #endif
     case MO_32:
         /* 32 bit address */
-        if (s->addseg && override < 0)
-            override = R_DS;
-        if (override >= 0) {
-            gen_op_movl_A0_seg(override);
-            gen_op_addl_A0_reg_sN(0, R_ESI);
-        } else {
-            gen_op_movl_A0_reg(R_ESI);
+        if (ovr_seg < 0) {
+            if (s->addseg) {
+                ovr_seg = def_seg;
+            } else {
+                tcg_gen_ext32u_tl(cpu_A0, a0);
+                return;
+            }
         }
         break;
     case MO_16:
-        /* 16 address, always override */
-        if (override < 0)
-            override = R_DS;
-        tcg_gen_ext16u_tl(cpu_A0, cpu_regs[R_ESI]);
-        gen_op_addl_A0_seg(s, override);
+        /* 16 bit address */
+        if (ovr_seg < 0) {
+            ovr_seg = def_seg;
+        }
+        tcg_gen_ext16u_tl(cpu_A0, a0);
+        /* ADDSEG will only be false in 16-bit mode for LEA.  */
+        if (!s->addseg) {
+            return;
+        }
+        a0 = cpu_A0;
         break;
     default:
         tcg_abort();
     }
-}
 
-static inline void gen_string_movl_A0_EDI(DisasContext *s)
-{
-    switch (s->aflag) {
-#ifdef TARGET_X86_64
-    case MO_64:
-        gen_op_movq_A0_reg(R_EDI);
-        break;
-#endif
-    case MO_32:
-        if (s->addseg) {
-            gen_op_movl_A0_seg(R_ES);
-            gen_op_addl_A0_reg_sN(0, R_EDI);
+    if (ovr_seg >= 0) {
+        TCGv seg = tcg_temp_new();
+
+        tcg_gen_ld_tl(seg, cpu_env, offsetof(CPUX86State, segs[ovr_seg].base));
+
+        if (aflag == MO_64) {
+            tcg_gen_add_tl(cpu_A0, a0, seg);
+        } else if (CODE64(s)) {
+            tcg_gen_ext32u_tl(cpu_A0, a0);
+            tcg_gen_add_tl(cpu_A0, cpu_A0, seg);
         } else {
-            gen_op_movl_A0_reg(R_EDI);
+            tcg_gen_add_tl(cpu_A0, a0, seg);
+            tcg_gen_ext32u_tl(cpu_A0, cpu_A0);
         }
-        break;
-    case MO_16:
-        tcg_gen_ext16u_tl(cpu_A0, cpu_regs[R_EDI]);
-        gen_op_addl_A0_seg(s, R_ES);
-        break;
-    default:
-        tcg_abort();
+
+        tcg_temp_free(seg);
     }
 }
 
+static inline void gen_string_movl_A0_ESI(DisasContext *s)
+{
+    gen_lea_v_seg(s, cpu_regs[R_ESI], R_DS, s->override);
+}
+
+static inline void gen_string_movl_A0_EDI(DisasContext *s)
+{
+    gen_lea_v_seg(s, cpu_regs[R_EDI], R_ES, -1);
+}
+
 static inline void gen_op_movl_T0_Dshift(TCGMemOp ot)
 {
     tcg_gen_ld32s_tl(cpu_T[0], cpu_env, offsetof(CPUX86State, df));
@@ -2118,23 +2080,7 @@ static void gen_nop_modrm(CPUX86State *env, DisasContext *s, int modrm)
 /* used for LEA and MOV AX, mem */
 static void gen_add_A0_ds_seg(DisasContext *s)
 {
-    int override, must_add_seg;
-    must_add_seg = s->addseg;
-    override = R_DS;
-    if (s->override >= 0) {
-        override = s->override;
-        must_add_seg = 1;
-    }
-    if (must_add_seg) {
-#ifdef TARGET_X86_64
-        if (CODE64(s)) {
-            gen_op_addq_A0_seg(override);
-        } else
-#endif
-        {
-            gen_op_addl_A0_seg(s, override);
-        }
-    }
+    gen_lea_v_seg(s, cpu_A0, R_DS, s->override);
 }
 
 /* generate modrm memory load or store of 'reg'. TMP0 is used if reg ==
-- 
2.5.0

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

* [Qemu-devel] [PATCH v2 02/10] target-i386: Introduce mo_stacksize
  2015-12-17 19:19 [Qemu-devel] [PATCH v2 00/10] target-i386 addressing cleanups Richard Henderson
  2015-12-17 19:19 ` [Qemu-devel] [PATCH v2 01/10] target-i386: Create gen_lea_v_seg Richard Henderson
@ 2015-12-17 19:19 ` Richard Henderson
  2015-12-17 19:19 ` [Qemu-devel] [PATCH v2 03/10] target-i386: Use gen_lea_v_seg in gen_lea_modrm Richard Henderson
                   ` (7 subsequent siblings)
  9 siblings, 0 replies; 13+ messages in thread
From: Richard Henderson @ 2015-12-17 19:19 UTC (permalink / raw)
  To: qemu-devel; +Cc: pbonzini, aurelien, peter.maydell

Centralize computation of a MO_SIZE for the stack pointer.

Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 target-i386/translate.c | 24 ++++++++++--------------
 1 file changed, 10 insertions(+), 14 deletions(-)

diff --git a/target-i386/translate.c b/target-i386/translate.c
index 3cc17f7..e0df5c0 100644
--- a/target-i386/translate.c
+++ b/target-i386/translate.c
@@ -307,6 +307,12 @@ static inline TCGMemOp mo_pushpop(DisasContext *s, TCGMemOp ot)
     }
 }
 
+/* Select the size of the stack pointer.  */
+static inline TCGMemOp mo_stacksize(DisasContext *s)
+{
+    return CODE64(s) ? MO_64 : s->ss32 ? MO_32 : MO_16;
+}
+
 /* Select only size 64 else 32.  Used for SSE operand sizes.  */
 static inline TCGMemOp mo_64_32(TCGMemOp ot)
 {
@@ -2292,31 +2298,22 @@ gen_svm_check_intercept(DisasContext *s, target_ulong pc_start, uint64_t type)
 
 static inline void gen_stack_update(DisasContext *s, int addend)
 {
-#ifdef TARGET_X86_64
-    if (CODE64(s)) {
-        gen_op_add_reg_im(MO_64, R_ESP, addend);
-    } else
-#endif
-    if (s->ss32) {
-        gen_op_add_reg_im(MO_32, R_ESP, addend);
-    } else {
-        gen_op_add_reg_im(MO_16, R_ESP, addend);
-    }
+    gen_op_add_reg_im(mo_stacksize(s), R_ESP, addend);
 }
 
 /* Generate a push. It depends on ss32, addseg and dflag.  */
 static void gen_push_v(DisasContext *s, TCGv val)
 {
-    TCGMemOp a_ot, d_ot = mo_pushpop(s, s->dflag);
+    TCGMemOp d_ot = mo_pushpop(s, s->dflag);
+    TCGMemOp a_ot = mo_stacksize(s);
     int size = 1 << d_ot;
     TCGv new_esp = cpu_A0;
 
     tcg_gen_subi_tl(cpu_A0, cpu_regs[R_ESP], size);
 
     if (CODE64(s)) {
-        a_ot = MO_64;
+        /* No special handling.  */
     } else if (s->ss32) {
-        a_ot = MO_32;
         if (s->addseg) {
             new_esp = cpu_tmp4;
             tcg_gen_mov_tl(new_esp, cpu_A0);
@@ -2325,7 +2322,6 @@ static void gen_push_v(DisasContext *s, TCGv val)
             tcg_gen_ext32u_tl(cpu_A0, cpu_A0);
         }
     } else {
-        a_ot = MO_16;
         new_esp = cpu_tmp4;
         tcg_gen_ext16u_tl(cpu_A0, cpu_A0);
         tcg_gen_mov_tl(new_esp, cpu_A0);
-- 
2.5.0

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

* [Qemu-devel] [PATCH v2 03/10] target-i386: Use gen_lea_v_seg in gen_lea_modrm
  2015-12-17 19:19 [Qemu-devel] [PATCH v2 00/10] target-i386 addressing cleanups Richard Henderson
  2015-12-17 19:19 ` [Qemu-devel] [PATCH v2 01/10] target-i386: Create gen_lea_v_seg Richard Henderson
  2015-12-17 19:19 ` [Qemu-devel] [PATCH v2 02/10] target-i386: Introduce mo_stacksize Richard Henderson
@ 2015-12-17 19:19 ` Richard Henderson
  2015-12-17 19:19 ` [Qemu-devel] [PATCH v2 04/10] target-i386: Use gen_lea_v_seg in stack subroutines Richard Henderson
                   ` (6 subsequent siblings)
  9 siblings, 0 replies; 13+ messages in thread
From: Richard Henderson @ 2015-12-17 19:19 UTC (permalink / raw)
  To: qemu-devel; +Cc: pbonzini, aurelien, peter.maydell

Centralize handling of segment bases.

Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 target-i386/translate.c | 82 ++++++++++++++-----------------------------------
 1 file changed, 23 insertions(+), 59 deletions(-)

diff --git a/target-i386/translate.c b/target-i386/translate.c
index e0df5c0..0a86c63 100644
--- a/target-i386/translate.c
+++ b/target-i386/translate.c
@@ -1844,17 +1844,12 @@ static void gen_shifti(DisasContext *s1, int op, TCGMemOp ot, int d, int c)
 static void gen_lea_modrm(CPUX86State *env, DisasContext *s, int modrm)
 {
     target_long disp;
-    int havesib;
-    int base;
-    int index;
-    int scale;
-    int mod, rm, code, override, must_add_seg;
+    int havesib, base, index, scale;
+    int mod, rm, code, def_seg, ovr_seg;
     TCGv sum;
 
-    override = s->override;
-    must_add_seg = s->addseg;
-    if (override >= 0)
-        must_add_seg = 1;
+    def_seg = R_DS;
+    ovr_seg = s->override;
     mod = (modrm >> 6) & 3;
     rm = modrm & 7;
 
@@ -1924,61 +1919,34 @@ static void gen_lea_modrm(CPUX86State *env, DisasContext *s, int modrm)
         }
         if (TCGV_IS_UNUSED(sum)) {
             tcg_gen_movi_tl(cpu_A0, disp);
-        } else {
+            sum = cpu_A0;
+        } else if (disp != 0) {
             tcg_gen_addi_tl(cpu_A0, sum, disp);
+            sum = cpu_A0;
         }
 
-        if (must_add_seg) {
-            if (override < 0) {
-                if (base == R_EBP || base == R_ESP) {
-                    override = R_SS;
-                } else {
-                    override = R_DS;
-                }
-            }
-
-            tcg_gen_ld_tl(cpu_tmp0, cpu_env,
-                          offsetof(CPUX86State, segs[override].base));
-            if (CODE64(s)) {
-                if (s->aflag == MO_32) {
-                    tcg_gen_ext32u_tl(cpu_A0, cpu_A0);
-                }
-                tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_tmp0);
-                return;
-            }
-
-            tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_tmp0);
-        }
-
-        if (s->aflag == MO_32) {
-            tcg_gen_ext32u_tl(cpu_A0, cpu_A0);
+        if (base == R_EBP || base == R_ESP) {
+            def_seg = R_SS;
         }
         break;
 
     case MO_16:
-        switch (mod) {
-        case 0:
+        sum = cpu_A0;
+        if (mod == 0) {
             if (rm == 6) {
                 disp = cpu_lduw_code(env, s->pc);
                 s->pc += 2;
                 tcg_gen_movi_tl(cpu_A0, disp);
-                rm = 0; /* avoid SS override */
-                goto no_rm;
-            } else {
-                disp = 0;
+                break;
             }
-            break;
-        case 1:
+            disp = 0;
+        } else if (mod == 1) {
             disp = (int8_t)cpu_ldub_code(env, s->pc++);
-            break;
-        default:
-        case 2:
+        } else {
             disp = (int16_t)cpu_lduw_code(env, s->pc);
             s->pc += 2;
-            break;
         }
 
-        sum = cpu_A0;
         switch (rm) {
         case 0:
             tcg_gen_add_tl(cpu_A0, cpu_regs[R_EBX], cpu_regs[R_ESI]);
@@ -1988,9 +1956,11 @@ static void gen_lea_modrm(CPUX86State *env, DisasContext *s, int modrm)
             break;
         case 2:
             tcg_gen_add_tl(cpu_A0, cpu_regs[R_EBP], cpu_regs[R_ESI]);
+            def_seg = R_SS;
             break;
         case 3:
             tcg_gen_add_tl(cpu_A0, cpu_regs[R_EBP], cpu_regs[R_EDI]);
+            def_seg = R_SS;
             break;
         case 4:
             sum = cpu_regs[R_ESI];
@@ -2000,30 +1970,24 @@ static void gen_lea_modrm(CPUX86State *env, DisasContext *s, int modrm)
             break;
         case 6:
             sum = cpu_regs[R_EBP];
+            def_seg = R_SS;
             break;
         default:
         case 7:
             sum = cpu_regs[R_EBX];
             break;
         }
-        tcg_gen_addi_tl(cpu_A0, sum, disp);
-        tcg_gen_ext16u_tl(cpu_A0, cpu_A0);
-    no_rm:
-        if (must_add_seg) {
-            if (override < 0) {
-                if (rm == 2 || rm == 3 || rm == 6) {
-                    override = R_SS;
-                } else {
-                    override = R_DS;
-                }
-            }
-            gen_op_addl_A0_seg(s, override);
+        if (disp != 0) {
+            tcg_gen_addi_tl(cpu_A0, sum, disp);
+            sum = cpu_A0;
         }
         break;
 
     default:
         tcg_abort();
     }
+
+    gen_lea_v_seg(s, sum, def_seg, ovr_seg);
 }
 
 static void gen_nop_modrm(CPUX86State *env, DisasContext *s, int modrm)
-- 
2.5.0

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

* [Qemu-devel] [PATCH v2 04/10] target-i386: Use gen_lea_v_seg in stack subroutines
  2015-12-17 19:19 [Qemu-devel] [PATCH v2 00/10] target-i386 addressing cleanups Richard Henderson
                   ` (2 preceding siblings ...)
  2015-12-17 19:19 ` [Qemu-devel] [PATCH v2 03/10] target-i386: Use gen_lea_v_seg in gen_lea_modrm Richard Henderson
@ 2015-12-17 19:19 ` Richard Henderson
  2015-12-17 19:19 ` [Qemu-devel] [PATCH v2 05/10] target-i386: Access segs via TCG registers Richard Henderson
                   ` (5 subsequent siblings)
  9 siblings, 0 replies; 13+ messages in thread
From: Richard Henderson @ 2015-12-17 19:19 UTC (permalink / raw)
  To: qemu-devel; +Cc: pbonzini, aurelien, peter.maydell

I.e. gen_push_v, gen_pop_T0, gen_stack_A0.
More centralization of handling of segment bases.

Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 target-i386/translate.c | 52 +++++++++++++------------------------------------
 1 file changed, 13 insertions(+), 39 deletions(-)

diff --git a/target-i386/translate.c b/target-i386/translate.c
index 0a86c63..1e6dccd 100644
--- a/target-i386/translate.c
+++ b/target-i386/translate.c
@@ -462,10 +462,9 @@ static inline void gen_jmp_im(target_ulong pc)
 /* Compute SEG:REG into A0.  SEG is selected from the override segment
    (OVR_SEG) and the default segment (DEF_SEG).  OVR_SEG may be -1 to
    indicate no override.  */
-static void gen_lea_v_seg(DisasContext *s, TCGv a0, int def_seg, int ovr_seg)
+static void gen_lea_v_seg(DisasContext *s, TCGMemOp aflag, TCGv a0,
+                          int def_seg, int ovr_seg)
 {
-    TCGMemOp aflag = s->aflag;
-
     switch (aflag) {
 #ifdef TARGET_X86_64
     case MO_64:
@@ -523,12 +522,12 @@ static void gen_lea_v_seg(DisasContext *s, TCGv a0, int def_seg, int ovr_seg)
 
 static inline void gen_string_movl_A0_ESI(DisasContext *s)
 {
-    gen_lea_v_seg(s, cpu_regs[R_ESI], R_DS, s->override);
+    gen_lea_v_seg(s, s->aflag, cpu_regs[R_ESI], R_DS, s->override);
 }
 
 static inline void gen_string_movl_A0_EDI(DisasContext *s)
 {
-    gen_lea_v_seg(s, cpu_regs[R_EDI], R_ES, -1);
+    gen_lea_v_seg(s, s->aflag, cpu_regs[R_EDI], R_ES, -1);
 }
 
 static inline void gen_op_movl_T0_Dshift(TCGMemOp ot)
@@ -1987,7 +1986,7 @@ static void gen_lea_modrm(CPUX86State *env, DisasContext *s, int modrm)
         tcg_abort();
     }
 
-    gen_lea_v_seg(s, sum, def_seg, ovr_seg);
+    gen_lea_v_seg(s, s->aflag, sum, def_seg, ovr_seg);
 }
 
 static void gen_nop_modrm(CPUX86State *env, DisasContext *s, int modrm)
@@ -2050,7 +2049,7 @@ static void gen_nop_modrm(CPUX86State *env, DisasContext *s, int modrm)
 /* used for LEA and MOV AX, mem */
 static void gen_add_A0_ds_seg(DisasContext *s)
 {
-    gen_lea_v_seg(s, cpu_A0, R_DS, s->override);
+    gen_lea_v_seg(s, s->aflag, cpu_A0, R_DS, s->override);
 }
 
 /* generate modrm memory load or store of 'reg'. TMP0 is used if reg ==
@@ -2275,21 +2274,12 @@ static void gen_push_v(DisasContext *s, TCGv val)
 
     tcg_gen_subi_tl(cpu_A0, cpu_regs[R_ESP], size);
 
-    if (CODE64(s)) {
-        /* No special handling.  */
-    } else if (s->ss32) {
+    if (!CODE64(s)) {
         if (s->addseg) {
             new_esp = cpu_tmp4;
             tcg_gen_mov_tl(new_esp, cpu_A0);
-            gen_op_addl_A0_seg(s, R_SS);
-        } else {
-            tcg_gen_ext32u_tl(cpu_A0, cpu_A0);
         }
-    } else {
-        new_esp = cpu_tmp4;
-        tcg_gen_ext16u_tl(cpu_A0, cpu_A0);
-        tcg_gen_mov_tl(new_esp, cpu_A0);
-        gen_op_addl_A0_seg(s, R_SS);
+        gen_lea_v_seg(s, a_ot, cpu_A0, R_SS, -1);
     }
 
     gen_op_st_v(s, d_ot, val, cpu_A0);
@@ -2300,37 +2290,21 @@ static void gen_push_v(DisasContext *s, TCGv val)
 static TCGMemOp gen_pop_T0(DisasContext *s)
 {
     TCGMemOp d_ot = mo_pushpop(s, s->dflag);
-    TCGv addr = cpu_A0;
 
-    if (CODE64(s)) {
-        addr = cpu_regs[R_ESP];
-    } else if (!s->ss32) {
-        tcg_gen_ext16u_tl(cpu_A0, cpu_regs[R_ESP]);
-        gen_op_addl_A0_seg(s, R_SS);
-    } else if (s->addseg) {
-        tcg_gen_mov_tl(cpu_A0, cpu_regs[R_ESP]);
-        gen_op_addl_A0_seg(s, R_SS);
-    } else {
-        tcg_gen_ext32u_tl(cpu_A0, cpu_regs[R_ESP]);
-    }
+    gen_lea_v_seg(s, mo_stacksize(s), cpu_regs[R_ESP], R_SS, -1);
+    gen_op_ld_v(s, d_ot, cpu_T[0], cpu_A0);
 
-    gen_op_ld_v(s, d_ot, cpu_T[0], addr);
     return d_ot;
 }
 
-static void gen_pop_update(DisasContext *s, TCGMemOp ot)
+static inline void gen_pop_update(DisasContext *s, TCGMemOp ot)
 {
     gen_stack_update(s, 1 << ot);
 }
 
-static void gen_stack_A0(DisasContext *s)
+static inline void gen_stack_A0(DisasContext *s)
 {
-    gen_op_movl_A0_reg(R_ESP);
-    if (!s->ss32)
-        tcg_gen_ext16u_tl(cpu_A0, cpu_A0);
-    tcg_gen_mov_tl(cpu_T[1], cpu_A0);
-    if (s->addseg)
-        gen_op_addl_A0_seg(s, R_SS);
+    gen_lea_v_seg(s, s->ss32 ? MO_32 : MO_16, cpu_regs[R_ESP], R_SS, -1);
 }
 
 /* NOTE: wrap around in 16 bit not fully handled */
-- 
2.5.0

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

* [Qemu-devel] [PATCH v2 05/10] target-i386: Access segs via TCG registers
  2015-12-17 19:19 [Qemu-devel] [PATCH v2 00/10] target-i386 addressing cleanups Richard Henderson
                   ` (3 preceding siblings ...)
  2015-12-17 19:19 ` [Qemu-devel] [PATCH v2 04/10] target-i386: Use gen_lea_v_seg in stack subroutines Richard Henderson
@ 2015-12-17 19:19 ` Richard Henderson
  2015-12-17 19:19 ` [Qemu-devel] [PATCH v2 06/10] target-i386: Use gen_lea_v_seg in pusha/popa Richard Henderson
                   ` (4 subsequent siblings)
  9 siblings, 0 replies; 13+ messages in thread
From: Richard Henderson @ 2015-12-17 19:19 UTC (permalink / raw)
  To: qemu-devel; +Cc: pbonzini, aurelien, peter.maydell

Having segs[].base as a register significantly improves code
generation for real and protected modes, particularly for TBs
that have multiple memory references where the segment base
can be held in a hard register through the TB.

Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 target-i386/translate.c | 52 ++++++++++++++++++++++++++-----------------------
 1 file changed, 28 insertions(+), 24 deletions(-)

diff --git a/target-i386/translate.c b/target-i386/translate.c
index 1e6dccd..b346ca5 100644
--- a/target-i386/translate.c
+++ b/target-i386/translate.c
@@ -67,6 +67,7 @@ static TCGv cpu_A0;
 static TCGv cpu_cc_dst, cpu_cc_src, cpu_cc_src2, cpu_cc_srcT;
 static TCGv_i32 cpu_cc_op;
 static TCGv cpu_regs[CPU_NB_REGS];
+static TCGv cpu_seg_base[6];
 /* local temps */
 static TCGv cpu_T[2];
 /* local register indexes (only used inside old micro ops) */
@@ -424,12 +425,11 @@ static inline void gen_op_add_reg_T0(TCGMemOp size, int reg)
 
 static inline void gen_op_addl_A0_seg(DisasContext *s, int reg)
 {
-    tcg_gen_ld_tl(cpu_tmp0, cpu_env, offsetof(CPUX86State, segs[reg].base));
     if (CODE64(s)) {
         tcg_gen_ext32u_tl(cpu_A0, cpu_A0);
-        tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_tmp0);
+        tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_seg_base[reg]);
     } else {
-        tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_tmp0);
+        tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_seg_base[reg]);
         tcg_gen_ext32u_tl(cpu_A0, cpu_A0);
     }
 }
@@ -502,9 +502,7 @@ static void gen_lea_v_seg(DisasContext *s, TCGMemOp aflag, TCGv a0,
     }
 
     if (ovr_seg >= 0) {
-        TCGv seg = tcg_temp_new();
-
-        tcg_gen_ld_tl(seg, cpu_env, offsetof(CPUX86State, segs[ovr_seg].base));
+        TCGv seg = cpu_seg_base[ovr_seg];
 
         if (aflag == MO_64) {
             tcg_gen_add_tl(cpu_A0, a0, seg);
@@ -515,8 +513,6 @@ static void gen_lea_v_seg(DisasContext *s, TCGMemOp aflag, TCGv a0,
             tcg_gen_add_tl(cpu_A0, a0, seg);
             tcg_gen_ext32u_tl(cpu_A0, cpu_A0);
         }
-
-        tcg_temp_free(seg);
     }
 }
 
@@ -2207,12 +2203,10 @@ static inline void gen_op_movl_T0_seg(int seg_reg)
 
 static inline void gen_op_movl_seg_T0_vm(int seg_reg)
 {
-    tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 0xffff);
+    tcg_gen_ext16u_tl(cpu_T[0], cpu_T[0]);
     tcg_gen_st32_tl(cpu_T[0], cpu_env, 
                     offsetof(CPUX86State,segs[seg_reg].selector));
-    tcg_gen_shli_tl(cpu_T[0], cpu_T[0], 4);
-    tcg_gen_st_tl(cpu_T[0], cpu_env, 
-                  offsetof(CPUX86State,segs[seg_reg].base));
+    tcg_gen_shli_tl(cpu_seg_base[seg_reg], cpu_T[0], 4);
 }
 
 /* move T0 to seg_reg and compute if the CPU state may change. Never
@@ -7277,21 +7271,16 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
                         if (s->cpl != 0) {
                             gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
                         } else {
-                            tcg_gen_ld_tl(cpu_T[0], cpu_env,
-                                offsetof(CPUX86State,segs[R_GS].base));
-                            tcg_gen_ld_tl(cpu_T[1], cpu_env,
-                                offsetof(CPUX86State,kernelgsbase));
-                            tcg_gen_st_tl(cpu_T[1], cpu_env,
-                                offsetof(CPUX86State,segs[R_GS].base));
+                            tcg_gen_mov_tl(cpu_T[0], cpu_seg_base[R_GS]);
+                            tcg_gen_ld_tl(cpu_seg_base[R_GS], cpu_env,
+                                          offsetof(CPUX86State, kernelgsbase));
                             tcg_gen_st_tl(cpu_T[0], cpu_env,
-                                offsetof(CPUX86State,kernelgsbase));
+                                          offsetof(CPUX86State, kernelgsbase));
                         }
-                    } else
-#endif
-                    {
-                        goto illegal_op;
+                        break;
                     }
-                    break;
+#endif
+                    goto illegal_op;
                 case 1: /* rdtscp */
                     if (!(s->cpuid_ext2_features & CPUID_EXT2_RDTSCP))
                         goto illegal_op;
@@ -7740,6 +7729,14 @@ void optimize_flags_init(void)
         [R_ESP] = "esp",
 #endif
     };
+    static const char seg_base_names[6][8] = {
+        [R_CS] = "cs_base",
+        [R_DS] = "ds_base",
+        [R_ES] = "es_base",
+        [R_FS] = "fs_base",
+        [R_GS] = "gs_base",
+        [R_SS] = "ss_base",
+    };
     int i;
 
     cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
@@ -7758,6 +7755,13 @@ void optimize_flags_init(void)
                                          reg_names[i]);
     }
 
+    for (i = 0; i < 6; ++i) {
+        cpu_seg_base[i]
+            = tcg_global_mem_new(TCG_AREG0,
+                                 offsetof(CPUX86State, segs[i].base),
+                                 seg_base_names[i]);
+    }
+
     helper_lock_init();
 }
 
-- 
2.5.0

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

* [Qemu-devel] [PATCH v2 06/10] target-i386: Use gen_lea_v_seg in pusha/popa
  2015-12-17 19:19 [Qemu-devel] [PATCH v2 00/10] target-i386 addressing cleanups Richard Henderson
                   ` (4 preceding siblings ...)
  2015-12-17 19:19 ` [Qemu-devel] [PATCH v2 05/10] target-i386: Access segs via TCG registers Richard Henderson
@ 2015-12-17 19:19 ` Richard Henderson
  2015-12-17 19:19 ` [Qemu-devel] [PATCH v2 07/10] target-i386: Rewrite gen_enter inline Richard Henderson
                   ` (3 subsequent siblings)
  9 siblings, 0 replies; 13+ messages in thread
From: Richard Henderson @ 2015-12-17 19:19 UTC (permalink / raw)
  To: qemu-devel; +Cc: pbonzini, aurelien, peter.maydell

More centralization of handling of segment bases.
Also fixes the note about 16-bit wrap around not fully handled.

Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 target-i386/translate.c | 50 +++++++++++++++++++++++--------------------------
 1 file changed, 23 insertions(+), 27 deletions(-)

diff --git a/target-i386/translate.c b/target-i386/translate.c
index b346ca5..4c967f3 100644
--- a/target-i386/translate.c
+++ b/target-i386/translate.c
@@ -2301,45 +2301,41 @@ static inline void gen_stack_A0(DisasContext *s)
     gen_lea_v_seg(s, s->ss32 ? MO_32 : MO_16, cpu_regs[R_ESP], R_SS, -1);
 }
 
-/* NOTE: wrap around in 16 bit not fully handled */
 static void gen_pusha(DisasContext *s)
 {
+    TCGMemOp s_ot = s->ss32 ? MO_32 : MO_16;
+    TCGMemOp d_ot = s->dflag;
+    int size = 1 << d_ot;
     int i;
-    gen_op_movl_A0_reg(R_ESP);
-    gen_op_addl_A0_im(-(8 << s->dflag));
-    if (!s->ss32)
-        tcg_gen_ext16u_tl(cpu_A0, cpu_A0);
-    tcg_gen_mov_tl(cpu_T[1], cpu_A0);
-    if (s->addseg)
-        gen_op_addl_A0_seg(s, R_SS);
-    for(i = 0;i < 8; i++) {
-        gen_op_mov_v_reg(MO_32, cpu_T[0], 7 - i);
-        gen_op_st_v(s, s->dflag, cpu_T[0], cpu_A0);
-        gen_op_addl_A0_im(1 << s->dflag);
+
+    for (i = 0; i < 8; i++) {
+        tcg_gen_addi_tl(cpu_A0, cpu_regs[R_ESP], (i - 8) * size);
+        gen_lea_v_seg(s, s_ot, cpu_A0, R_SS, -1);
+        gen_op_st_v(s, d_ot, cpu_regs[7 - i], cpu_A0);
     }
-    gen_op_mov_reg_v(MO_16 + s->ss32, R_ESP, cpu_T[1]);
+
+    gen_stack_update(s, -8 * size);
 }
 
-/* NOTE: wrap around in 16 bit not fully handled */
 static void gen_popa(DisasContext *s)
 {
+    TCGMemOp s_ot = s->ss32 ? MO_32 : MO_16;
+    TCGMemOp d_ot = s->dflag;
+    int size = 1 << d_ot;
     int i;
-    gen_op_movl_A0_reg(R_ESP);
-    if (!s->ss32)
-        tcg_gen_ext16u_tl(cpu_A0, cpu_A0);
-    tcg_gen_mov_tl(cpu_T[1], cpu_A0);
-    tcg_gen_addi_tl(cpu_T[1], cpu_T[1], 8 << s->dflag);
-    if (s->addseg)
-        gen_op_addl_A0_seg(s, R_SS);
-    for(i = 0;i < 8; i++) {
+
+    for (i = 0; i < 8; i++) {
         /* ESP is not reloaded */
-        if (i != 3) {
-            gen_op_ld_v(s, s->dflag, cpu_T[0], cpu_A0);
-            gen_op_mov_reg_v(s->dflag, 7 - i, cpu_T[0]);
+        if (7 - i == R_ESP) {
+            continue;
         }
-        gen_op_addl_A0_im(1 << s->dflag);
+        tcg_gen_addi_tl(cpu_A0, cpu_regs[R_ESP], i * size);
+        gen_lea_v_seg(s, s_ot, cpu_A0, R_SS, -1);
+        gen_op_ld_v(s, d_ot, cpu_T[0], cpu_A0);
+        gen_op_mov_reg_v(d_ot, 7 - i, cpu_T[0]);
     }
-    gen_op_mov_reg_v(MO_16 + s->ss32, R_ESP, cpu_T[1]);
+
+    gen_stack_update(s, 8 * size);
 }
 
 static void gen_enter(DisasContext *s, int esp_addend, int level)
-- 
2.5.0

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

* [Qemu-devel] [PATCH v2 07/10] target-i386: Rewrite gen_enter inline
  2015-12-17 19:19 [Qemu-devel] [PATCH v2 00/10] target-i386 addressing cleanups Richard Henderson
                   ` (5 preceding siblings ...)
  2015-12-17 19:19 ` [Qemu-devel] [PATCH v2 06/10] target-i386: Use gen_lea_v_seg in pusha/popa Richard Henderson
@ 2015-12-17 19:19 ` Richard Henderson
  2015-12-17 19:19 ` [Qemu-devel] [PATCH v2 08/10] target-i386: Rewrite leave Richard Henderson
                   ` (2 subsequent siblings)
  9 siblings, 0 replies; 13+ messages in thread
From: Richard Henderson @ 2015-12-17 19:19 UTC (permalink / raw)
  To: qemu-devel; +Cc: pbonzini, aurelien, peter.maydell

Use gen_lea_v_seg for centralized segment base knowledge.  Unify
code across 32- and 64-bit.  Fix note about "must save state"
before using the out-of-line helpers.

Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 target-i386/helper.h     |  4 ---
 target-i386/seg_helper.c | 74 --------------------------------------
 target-i386/translate.c  | 93 ++++++++++++++++++------------------------------
 3 files changed, 34 insertions(+), 137 deletions(-)

diff --git a/target-i386/helper.h b/target-i386/helper.h
index ecfcfd1..3a25c3b 100644
--- a/target-i386/helper.h
+++ b/target-i386/helper.h
@@ -44,10 +44,6 @@ DEF_HELPER_FLAGS_3(set_dr, TCG_CALL_NO_WG, void, env, int, tl)
 DEF_HELPER_FLAGS_2(get_dr, TCG_CALL_NO_WG, tl, env, int)
 DEF_HELPER_2(invlpg, void, env, tl)
 
-DEF_HELPER_4(enter_level, void, env, int, int, tl)
-#ifdef TARGET_X86_64
-DEF_HELPER_4(enter64_level, void, env, int, int, tl)
-#endif
 DEF_HELPER_1(sysenter, void, env)
 DEF_HELPER_2(sysexit, void, env, int)
 #ifdef TARGET_X86_64
diff --git a/target-i386/seg_helper.c b/target-i386/seg_helper.c
index 20ee892..51da43b 100644
--- a/target-i386/seg_helper.c
+++ b/target-i386/seg_helper.c
@@ -1377,80 +1377,6 @@ bool x86_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
     return ret;
 }
 
-void helper_enter_level(CPUX86State *env, int level, int data32,
-                        target_ulong t1)
-{
-    target_ulong ssp;
-    uint32_t esp_mask, esp, ebp;
-
-    esp_mask = get_sp_mask(env->segs[R_SS].flags);
-    ssp = env->segs[R_SS].base;
-    ebp = env->regs[R_EBP];
-    esp = env->regs[R_ESP];
-    if (data32) {
-        /* 32 bit */
-        esp -= 4;
-        while (--level) {
-            esp -= 4;
-            ebp -= 4;
-            cpu_stl_data_ra(env, ssp + (esp & esp_mask),
-                            cpu_ldl_data_ra(env, ssp + (ebp & esp_mask),
-                                            GETPC()),
-                            GETPC());
-        }
-        esp -= 4;
-        cpu_stl_data_ra(env, ssp + (esp & esp_mask), t1, GETPC());
-    } else {
-        /* 16 bit */
-        esp -= 2;
-        while (--level) {
-            esp -= 2;
-            ebp -= 2;
-            cpu_stw_data_ra(env, ssp + (esp & esp_mask),
-                            cpu_lduw_data_ra(env, ssp + (ebp & esp_mask),
-                                             GETPC()),
-                            GETPC());
-        }
-        esp -= 2;
-        cpu_stw_data_ra(env, ssp + (esp & esp_mask), t1, GETPC());
-    }
-}
-
-#ifdef TARGET_X86_64
-void helper_enter64_level(CPUX86State *env, int level, int data64,
-                          target_ulong t1)
-{
-    target_ulong esp, ebp;
-
-    ebp = env->regs[R_EBP];
-    esp = env->regs[R_ESP];
-
-    if (data64) {
-        /* 64 bit */
-        esp -= 8;
-        while (--level) {
-            esp -= 8;
-            ebp -= 8;
-            cpu_stq_data_ra(env, esp, cpu_ldq_data_ra(env, ebp, GETPC()),
-                            GETPC());
-        }
-        esp -= 8;
-        cpu_stq_data_ra(env, esp, t1, GETPC());
-    } else {
-        /* 16 bit */
-        esp -= 2;
-        while (--level) {
-            esp -= 2;
-            ebp -= 2;
-            cpu_stw_data_ra(env, esp, cpu_lduw_data_ra(env, ebp, GETPC()),
-                            GETPC());
-        }
-        esp -= 2;
-        cpu_stw_data_ra(env, esp, t1, GETPC());
-    }
-}
-#endif
-
 void helper_lldt(CPUX86State *env, int selector)
 {
     SegmentCache *dt;
diff --git a/target-i386/translate.c b/target-i386/translate.c
index 4c967f3..b6749ff 100644
--- a/target-i386/translate.c
+++ b/target-i386/translate.c
@@ -376,11 +376,6 @@ static inline void gen_op_mov_v_reg(TCGMemOp ot, TCGv t0, int reg)
     }
 }
 
-static inline void gen_op_movl_A0_reg(int reg)
-{
-    tcg_gen_mov_tl(cpu_A0, cpu_regs[reg]);
-}
-
 static inline void gen_op_addl_A0_im(int32_t val)
 {
     tcg_gen_addi_tl(cpu_A0, cpu_A0, val);
@@ -423,17 +418,6 @@ static inline void gen_op_add_reg_T0(TCGMemOp size, int reg)
     gen_op_mov_reg_v(size, reg, cpu_tmp0);
 }
 
-static inline void gen_op_addl_A0_seg(DisasContext *s, int reg)
-{
-    if (CODE64(s)) {
-        tcg_gen_ext32u_tl(cpu_A0, cpu_A0);
-        tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_seg_base[reg]);
-    } else {
-        tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_seg_base[reg]);
-        tcg_gen_ext32u_tl(cpu_A0, cpu_A0);
-    }
-}
-
 static inline void gen_op_ld_v(DisasContext *s, int idx, TCGv t0, TCGv a0)
 {
     tcg_gen_qemu_ld_tl(t0, a0, s->mem_index, idx | MO_LE);
@@ -2340,51 +2324,42 @@ static void gen_popa(DisasContext *s)
 
 static void gen_enter(DisasContext *s, int esp_addend, int level)
 {
-    TCGMemOp ot = mo_pushpop(s, s->dflag);
-    int opsize = 1 << ot;
+    TCGMemOp d_ot = mo_pushpop(s, s->dflag);
+    TCGMemOp a_ot = CODE64(s) ? MO_64 : s->ss32 ? MO_32 : MO_16;
+    int size = 1 << d_ot;
 
-    level &= 0x1f;
-#ifdef TARGET_X86_64
-    if (CODE64(s)) {
-        gen_op_movl_A0_reg(R_ESP);
-        gen_op_addq_A0_im(-opsize);
-        tcg_gen_mov_tl(cpu_T[1], cpu_A0);
-
-        /* push bp */
-        gen_op_mov_v_reg(MO_32, cpu_T[0], R_EBP);
-        gen_op_st_v(s, ot, cpu_T[0], cpu_A0);
-        if (level) {
-            /* XXX: must save state */
-            gen_helper_enter64_level(cpu_env, tcg_const_i32(level),
-                                     tcg_const_i32((ot == MO_64)),
-                                     cpu_T[1]);
-        }
-        gen_op_mov_reg_v(ot, R_EBP, cpu_T[1]);
-        tcg_gen_addi_tl(cpu_T[1], cpu_T[1], -esp_addend + (-opsize * level));
-        gen_op_mov_reg_v(MO_64, R_ESP, cpu_T[1]);
-    } else
-#endif
-    {
-        gen_op_movl_A0_reg(R_ESP);
-        gen_op_addl_A0_im(-opsize);
-        if (!s->ss32)
-            tcg_gen_ext16u_tl(cpu_A0, cpu_A0);
-        tcg_gen_mov_tl(cpu_T[1], cpu_A0);
-        if (s->addseg)
-            gen_op_addl_A0_seg(s, R_SS);
-        /* push bp */
-        gen_op_mov_v_reg(MO_32, cpu_T[0], R_EBP);
-        gen_op_st_v(s, ot, cpu_T[0], cpu_A0);
-        if (level) {
-            /* XXX: must save state */
-            gen_helper_enter_level(cpu_env, tcg_const_i32(level),
-                                   tcg_const_i32(s->dflag - 1),
-                                   cpu_T[1]);
-        }
-        gen_op_mov_reg_v(ot, R_EBP, cpu_T[1]);
-        tcg_gen_addi_tl(cpu_T[1], cpu_T[1], -esp_addend + (-opsize * level));
-        gen_op_mov_reg_v(MO_16 + s->ss32, R_ESP, cpu_T[1]);
+    /* Push BP; compute FrameTemp into T1.  */
+    tcg_gen_subi_tl(cpu_T[1], cpu_regs[R_ESP], size);
+    gen_lea_v_seg(s, a_ot, cpu_T[1], R_SS, -1);
+    gen_op_st_v(s, d_ot, cpu_regs[R_EBP], cpu_A0);
+
+    level &= 31;
+    if (level != 0) {
+        int i;
+
+        /* Copy level-1 pointers from the previous frame.  */
+        for (i = 1; i < level; ++i) {
+            tcg_gen_subi_tl(cpu_A0, cpu_regs[R_EBP], size * i);
+            gen_lea_v_seg(s, a_ot, cpu_A0, R_SS, -1);
+            gen_op_ld_v(s, d_ot, cpu_tmp0, cpu_A0);
+
+            tcg_gen_subi_tl(cpu_A0, cpu_T[1], size * i);
+            gen_lea_v_seg(s, a_ot, cpu_A0, R_SS, -1);
+            gen_op_st_v(s, d_ot, cpu_tmp0, cpu_A0);
+        }
+
+        /* Push the current FrameTemp as the last level.  */
+        tcg_gen_subi_tl(cpu_A0, cpu_T[1], size * level);
+        gen_lea_v_seg(s, a_ot, cpu_A0, R_SS, -1);
+        gen_op_st_v(s, d_ot, cpu_T[1], cpu_A0);
     }
+
+    /* Copy the FrameTemp value to EBP.  */
+    gen_op_mov_reg_v(a_ot, R_EBP, cpu_T[1]);
+
+    /* Compute the final value of ESP.  */
+    tcg_gen_subi_tl(cpu_T[1], cpu_T[1], esp_addend + size * level);
+    gen_op_mov_reg_v(a_ot, R_ESP, cpu_T[1]);
 }
 
 static void gen_exception(DisasContext *s, int trapno, target_ulong cur_eip)
-- 
2.5.0

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

* [Qemu-devel] [PATCH v2 08/10] target-i386: Rewrite leave
  2015-12-17 19:19 [Qemu-devel] [PATCH v2 00/10] target-i386 addressing cleanups Richard Henderson
                   ` (6 preceding siblings ...)
  2015-12-17 19:19 ` [Qemu-devel] [PATCH v2 07/10] target-i386: Rewrite gen_enter inline Richard Henderson
@ 2015-12-17 19:19 ` Richard Henderson
  2015-12-17 19:19 ` [Qemu-devel] [PATCH v2 09/10] target-i386: Tidy gen_add_A0_im Richard Henderson
  2016-02-04 23:44 ` [Qemu-devel] [PATCH v2 00/10] target-i386 addressing cleanups Richard Henderson
  9 siblings, 0 replies; 13+ messages in thread
From: Richard Henderson @ 2015-12-17 19:19 UTC (permalink / raw)
  To: qemu-devel; +Cc: pbonzini, aurelien, peter.maydell

Unify the code across stack pointer widths.  Fix the note about
not updating ESP before the potential exception.

Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 target-i386/translate.c | 29 +++++++++++++++--------------
 1 file changed, 15 insertions(+), 14 deletions(-)

diff --git a/target-i386/translate.c b/target-i386/translate.c
index b6749ff..2be4ba8 100644
--- a/target-i386/translate.c
+++ b/target-i386/translate.c
@@ -2362,6 +2362,20 @@ static void gen_enter(DisasContext *s, int esp_addend, int level)
     gen_op_mov_reg_v(a_ot, R_ESP, cpu_T[1]);
 }
 
+static void gen_leave(DisasContext *s)
+{
+    TCGMemOp d_ot = mo_pushpop(s, s->dflag);
+    TCGMemOp a_ot = mo_stacksize(s);
+
+    gen_lea_v_seg(s, a_ot, cpu_regs[R_EBP], R_SS, -1);
+    gen_op_ld_v(s, d_ot, cpu_T[0], cpu_A0);
+
+    tcg_gen_addi_tl(cpu_T[1], cpu_regs[R_EBP], 1 << d_ot);
+
+    gen_op_mov_reg_v(d_ot, R_EBP, cpu_T[0]);
+    gen_op_mov_reg_v(a_ot, R_ESP, cpu_T[1]);
+}
+
 static void gen_exception(DisasContext *s, int trapno, target_ulong cur_eip)
 {
     gen_update_cc_op(s);
@@ -5117,20 +5131,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
         }
         break;
     case 0xc9: /* leave */
-        /* XXX: exception not precise (ESP is updated before potential exception) */
-        if (CODE64(s)) {
-            gen_op_mov_v_reg(MO_64, cpu_T[0], R_EBP);
-            gen_op_mov_reg_v(MO_64, R_ESP, cpu_T[0]);
-        } else if (s->ss32) {
-            gen_op_mov_v_reg(MO_32, cpu_T[0], R_EBP);
-            gen_op_mov_reg_v(MO_32, R_ESP, cpu_T[0]);
-        } else {
-            gen_op_mov_v_reg(MO_16, cpu_T[0], R_EBP);
-            gen_op_mov_reg_v(MO_16, R_ESP, cpu_T[0]);
-        }
-        ot = gen_pop_T0(s);
-        gen_op_mov_reg_v(ot, R_EBP, cpu_T[0]);
-        gen_pop_update(s, ot);
+        gen_leave(s);
         break;
     case 0x06: /* push es */
     case 0x0e: /* push cs */
-- 
2.5.0

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

* [Qemu-devel] [PATCH v2 09/10] target-i386: Tidy gen_add_A0_im
  2015-12-17 19:19 [Qemu-devel] [PATCH v2 00/10] target-i386 addressing cleanups Richard Henderson
                   ` (7 preceding siblings ...)
  2015-12-17 19:19 ` [Qemu-devel] [PATCH v2 08/10] target-i386: Rewrite leave Richard Henderson
@ 2015-12-17 19:19 ` Richard Henderson
  2016-02-04 23:44 ` [Qemu-devel] [PATCH v2 00/10] target-i386 addressing cleanups Richard Henderson
  9 siblings, 0 replies; 13+ messages in thread
From: Richard Henderson @ 2015-12-17 19:19 UTC (permalink / raw)
  To: qemu-devel; +Cc: pbonzini, aurelien, peter.maydell

Merge gen_op_addl_A0_im and gen_op_addq_A0_im into gen_add_A0_im
and clean up the ifdef.

Replace the one remaining user of gen_op_addl_A0_im with gen_add_A0_im.

Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 target-i386/translate.c | 27 +++++----------------------
 1 file changed, 5 insertions(+), 22 deletions(-)

diff --git a/target-i386/translate.c b/target-i386/translate.c
index 2be4ba8..8059bbc 100644
--- a/target-i386/translate.c
+++ b/target-i386/translate.c
@@ -376,29 +376,12 @@ static inline void gen_op_mov_v_reg(TCGMemOp ot, TCGv t0, int reg)
     }
 }
 
-static inline void gen_op_addl_A0_im(int32_t val)
-{
-    tcg_gen_addi_tl(cpu_A0, cpu_A0, val);
-#ifdef TARGET_X86_64
-    tcg_gen_andi_tl(cpu_A0, cpu_A0, 0xffffffff);
-#endif
-}
-
-#ifdef TARGET_X86_64
-static inline void gen_op_addq_A0_im(int64_t val)
-{
-    tcg_gen_addi_tl(cpu_A0, cpu_A0, val);
-}
-#endif
-    
 static void gen_add_A0_im(DisasContext *s, int val)
 {
-#ifdef TARGET_X86_64
-    if (CODE64(s))
-        gen_op_addq_A0_im(val);
-    else
-#endif
-        gen_op_addl_A0_im(val);
+    tcg_gen_addi_tl(cpu_A0, cpu_A0, val);
+    if (!CODE64(s)) {
+        tcg_gen_ext32u_tl(cpu_A0, cpu_A0);
+    }
 }
 
 static inline void gen_op_jmp_v(TCGv dest)
@@ -6232,7 +6215,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
                exception */
             gen_op_jmp_v(cpu_T[0]);
             /* pop selector */
-            gen_op_addl_A0_im(1 << dflag);
+            gen_add_A0_im(s, 1 << dflag);
             gen_op_ld_v(s, dflag, cpu_T[0], cpu_A0);
             gen_op_movl_seg_T0_vm(R_CS);
             /* add stack offset */
-- 
2.5.0

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

* Re: [Qemu-devel] [PATCH v2 00/10] target-i386 addressing cleanups
  2015-12-17 19:19 [Qemu-devel] [PATCH v2 00/10] target-i386 addressing cleanups Richard Henderson
                   ` (8 preceding siblings ...)
  2015-12-17 19:19 ` [Qemu-devel] [PATCH v2 09/10] target-i386: Tidy gen_add_A0_im Richard Henderson
@ 2016-02-04 23:44 ` Richard Henderson
  2016-02-08 17:04   ` Paolo Bonzini
  9 siblings, 1 reply; 13+ messages in thread
From: Richard Henderson @ 2016-02-04 23:44 UTC (permalink / raw)
  To: qemu-devel; +Cc: pbonzini, aurelien, peter.maydell

On 12/18/2015 06:19 AM, Richard Henderson wrote:
> This is a rebase of the patch set I posted in July.  There are no
> substantive changes since then.
>
> The only comment at the time was re 05/10, where Paolo suggests
> optimizing access to CS overrides with the constant that we know
> via the TB operands.  I chose to defer that, leaving things as
> they are with a simple load from ENV.

Ping.

>    target-i386: Deconstruct the cpu_T array

This final patch needs updating to master, but is 100% mechanical.


r~

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

* Re: [Qemu-devel] [PATCH v2 00/10] target-i386 addressing cleanups
  2016-02-04 23:44 ` [Qemu-devel] [PATCH v2 00/10] target-i386 addressing cleanups Richard Henderson
@ 2016-02-08 17:04   ` Paolo Bonzini
  2016-02-08 20:35     ` Richard Henderson
  0 siblings, 1 reply; 13+ messages in thread
From: Paolo Bonzini @ 2016-02-08 17:04 UTC (permalink / raw)
  To: Richard Henderson, qemu-devel; +Cc: peter.maydell, aurelien



On 05/02/2016 00:44, Richard Henderson wrote:
> On 12/18/2015 06:19 AM, Richard Henderson wrote:
>> This is a rebase of the patch set I posted in July.  There are no
>> substantive changes since then.
>>
>> The only comment at the time was re 05/10, where Paolo suggests
>> optimizing access to CS overrides with the constant that we know
>> via the TB operands.  I chose to defer that, leaving things as
>> they are with a simple load from ENV.
> 
> Ping.
> 
>>    target-i386: Deconstruct the cpu_T array
> 
> This final patch needs updating to master, but is 100% mechanical.

v2 wasn't even sent to the list, actually. :)

Applied and sent out as pull request now, thanks!

Paolo

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

* Re: [Qemu-devel] [PATCH v2 00/10] target-i386 addressing cleanups
  2016-02-08 17:04   ` Paolo Bonzini
@ 2016-02-08 20:35     ` Richard Henderson
  0 siblings, 0 replies; 13+ messages in thread
From: Richard Henderson @ 2016-02-08 20:35 UTC (permalink / raw)
  To: Paolo Bonzini, qemu-devel; +Cc: peter.maydell, aurelien

On 02/09/2016 04:04 AM, Paolo Bonzini wrote:
> Applied and sent out as pull request now, thanks!

Thanks!


r~

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

end of thread, other threads:[~2016-02-08 20:35 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-12-17 19:19 [Qemu-devel] [PATCH v2 00/10] target-i386 addressing cleanups Richard Henderson
2015-12-17 19:19 ` [Qemu-devel] [PATCH v2 01/10] target-i386: Create gen_lea_v_seg Richard Henderson
2015-12-17 19:19 ` [Qemu-devel] [PATCH v2 02/10] target-i386: Introduce mo_stacksize Richard Henderson
2015-12-17 19:19 ` [Qemu-devel] [PATCH v2 03/10] target-i386: Use gen_lea_v_seg in gen_lea_modrm Richard Henderson
2015-12-17 19:19 ` [Qemu-devel] [PATCH v2 04/10] target-i386: Use gen_lea_v_seg in stack subroutines Richard Henderson
2015-12-17 19:19 ` [Qemu-devel] [PATCH v2 05/10] target-i386: Access segs via TCG registers Richard Henderson
2015-12-17 19:19 ` [Qemu-devel] [PATCH v2 06/10] target-i386: Use gen_lea_v_seg in pusha/popa Richard Henderson
2015-12-17 19:19 ` [Qemu-devel] [PATCH v2 07/10] target-i386: Rewrite gen_enter inline Richard Henderson
2015-12-17 19:19 ` [Qemu-devel] [PATCH v2 08/10] target-i386: Rewrite leave Richard Henderson
2015-12-17 19:19 ` [Qemu-devel] [PATCH v2 09/10] target-i386: Tidy gen_add_A0_im Richard Henderson
2016-02-04 23:44 ` [Qemu-devel] [PATCH v2 00/10] target-i386 addressing cleanups Richard Henderson
2016-02-08 17:04   ` Paolo Bonzini
2016-02-08 20:35     ` Richard Henderson

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).