Patchwork [for-1.8,38/61] target-i386: Fix addr32 prefix in gen_lea_modrm

login
register
mail settings
Submitter Richard Henderson
Date Nov. 7, 2013, 1:05 a.m.
Message ID <1383786324-18415-39-git-send-email-rth@twiddle.net>
Download mbox | patch
Permalink /patch/289091/
State New
Headers show

Comments

Richard Henderson - Nov. 7, 2013, 1:05 a.m.
Fix the following run-test-x86_64 testsuite failures:

-lea (%%eax) = 0000000000000001
-lea (%%ebx) = 0000000000000002
-lea (%%ecx) = 0000000000000004
-lea (%%edx) = 0000000000000008
-lea (%%esi) = 0000000000000010
-lea (%%edi) = 0000000000000020
+lea (%%eax) = 0000abcc00000001
+lea (%%ebx) = 0000abcf00000002
+lea (%%ecx) = 0000abc900000004
+lea (%%edx) = 0000abc500000008
+lea (%%esi) = 0000abdd00000010
+lea (%%edi) = 0000abed00000020

In addition, reduce ifdeffery and minimize the number of TCG ops
produced during address computation.

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

Patch

diff --git a/target-i386/translate.c b/target-i386/translate.c
index fcc787d..7024cfd 100644
--- a/target-i386/translate.c
+++ b/target-i386/translate.c
@@ -1904,6 +1904,7 @@  static void gen_lea_modrm(CPUX86State *env, DisasContext *s, int modrm)
     int index;
     int scale;
     int mod, rm, code, override, must_add_seg;
+    TCGv sum;
 
     override = s->override;
     must_add_seg = s->addseg;
@@ -1913,11 +1914,13 @@  static void gen_lea_modrm(CPUX86State *env, DisasContext *s, int modrm)
     rm = modrm & 7;
 
     switch (s->aflag) {
+#ifdef TARGET_X86_64
     case MO_64:
+#endif
     case MO_32:
         havesib = 0;
         base = rm;
-        index = 0;
+        index = -1;
         scale = 0;
 
         if (base == 4) {
@@ -1925,6 +1928,9 @@  static void gen_lea_modrm(CPUX86State *env, DisasContext *s, int modrm)
             code = cpu_ldub_code(env, s->pc++);
             scale = (code >> 6) & 3;
             index = ((code >> 3) & 7) | REX_X(s);
+            if (index == 4) {
+                index = -1;  /* no index */
+            }
             base = (code & 7);
         }
         base |= REX_B(s);
@@ -1952,52 +1958,57 @@  static void gen_lea_modrm(CPUX86State *env, DisasContext *s, int modrm)
             break;
         }
 
-        if (base >= 0) {
-            /* for correct popl handling with esp */
-            if (base == 4 && s->popl_esp_hack)
-                disp += s->popl_esp_hack;
-#ifdef TARGET_X86_64
-            if (s->aflag == MO_64) {
-                gen_op_movq_A0_reg(base);
-                if (disp != 0) {
-                    gen_op_addq_A0_im(disp);
-                }
-            } else
-#endif
-            {
-                gen_op_movl_A0_reg(base);
-                if (disp != 0)
-                    gen_op_addl_A0_im(disp);
-            }
-        } else {
-            tcg_gen_movi_tl(cpu_A0, disp);
+        /* For correct popl handling with esp.  */
+        if (base == R_ESP && s->popl_esp_hack) {
+            disp += s->popl_esp_hack;
         }
-        /* index == 4 means no index */
-        if (havesib && (index != 4)) {
-#ifdef TARGET_X86_64
-            if (s->aflag == MO_64) {
-                gen_op_addq_A0_reg_sN(scale, index);
-            } else
-#endif
-            {
-                gen_op_addl_A0_reg_sN(scale, index);
+
+        /* Compute the address, with a minimum number of TCG ops.  */
+        TCGV_UNUSED(sum);
+        if (index >= 0) {
+            if (scale == 0) {
+                sum = cpu_regs[index];
+            } else {
+                tcg_gen_shli_tl(cpu_A0, cpu_regs[index], scale);
+                sum = cpu_A0;
+            }
+            if (base >= 0) {
+                tcg_gen_add_tl(cpu_A0, sum, cpu_regs[base]);
+                sum = cpu_A0;
             }
+        } else if (base >= 0) {
+            sum = cpu_regs[base];
         }
+        if (TCGV_IS_UNUSED(sum)) {
+            tcg_gen_movi_tl(cpu_A0, disp);
+        } else {
+            tcg_gen_addi_tl(cpu_A0, sum, disp);
+        }
+
         if (must_add_seg) {
             if (override < 0) {
-                if (base == R_EBP || base == R_ESP)
+                if (base == R_EBP || base == R_ESP) {
                     override = R_SS;
-                else
+                } else {
                     override = R_DS;
+                }
             }
-#ifdef TARGET_X86_64
-            if (s->aflag == MO_64) {
-                gen_op_addq_A0_seg(override);
-            } else
-#endif
-            {
-                gen_op_addl_A0_seg(s, override);
+
+            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);
+                break;
             }
+
+            tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_tmp0);
+        }
+
+        if (s->aflag == MO_32) {
+            tcg_gen_ext32u_tl(cpu_A0, cpu_A0);
         }
         break;