qemu-devel
[Top][All Lists]
Advanced

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

[Qemu-devel] [PATCH for-1.7] target-i386: Fix addr32 prefix in gen_lea_m


From: Richard Henderson
Subject: [Qemu-devel] [PATCH for-1.7] target-i386: Fix addr32 prefix in gen_lea_modrm
Date: Tue, 12 Nov 2013 11:16:56 +1000

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 <address@hidden>
---
 target-i386/translate.c | 92 +++++++++++++++++++++++++------------------------
 1 file changed, 47 insertions(+), 45 deletions(-)

Split out of my 1.8 patch set, as this should affect the x32
code model.  When I get a chance, I'll download gentoo's x32
stage3 and verify it works now.


r~



diff --git a/target-i386/translate.c b/target-i386/translate.c
index eb0ea93..401187a 100644
--- a/target-i386/translate.c
+++ b/target-i386/translate.c
@@ -2090,6 +2090,7 @@ static void gen_lea_modrm(CPUX86State *env, DisasContext 
*s, int modrm,
     int scale;
     int opreg;
     int mod, rm, code, override, must_add_seg;
+    TCGv sum;
 
     override = s->override;
     must_add_seg = s->addseg;
@@ -2099,10 +2100,9 @@ static void gen_lea_modrm(CPUX86State *env, DisasContext 
*s, int modrm,
     rm = modrm & 7;
 
     if (s->aflag) {
-
         havesib = 0;
         base = rm;
-        index = 0;
+        index = -1;
         scale = 0;
 
         if (base == 4) {
@@ -2110,6 +2110,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);
@@ -2137,59 +2140,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 == 2) {
-                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);
+        /* For correct popl handling with esp.  */
+        if (base == R_ESP && s->popl_esp_hack) {
+            disp += s->popl_esp_hack;
+        }
+
+        /* 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;
             }
-        } else {
-#ifdef TARGET_X86_64
-            if (s->aflag == 2) {
-                gen_op_movq_A0_im(disp);
-            } else
-#endif
-            {
-                gen_op_movl_A0_im(disp);
+            if (base >= 0) {
+                tcg_gen_add_tl(cpu_A0, sum, cpu_regs[base]);
+                sum = cpu_A0;
             }
+        } else if (base >= 0) {
+            sum = cpu_regs[base];
         }
-        /* index == 4 means no index */
-        if (havesib && (index != 4)) {
-#ifdef TARGET_X86_64
-            if (s->aflag == 2) {
-                gen_op_addq_A0_reg_sN(scale, index);
-            } else
-#endif
-            {
-                gen_op_addl_A0_reg_sN(scale, index);
-            }
+        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 == 2) {
-                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 != 2) {
+                    tcg_gen_ext32u_tl(cpu_A0, cpu_A0);
+                }
+                tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_tmp0);
+                goto done;
             }
+
+            tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_tmp0);
+        }
+
+        if (s->aflag != 2) {
+            tcg_gen_ext32u_tl(cpu_A0, cpu_A0);
         }
     } else {
         switch (mod) {
@@ -2259,6 +2260,7 @@ static void gen_lea_modrm(CPUX86State *env, DisasContext 
*s, int modrm,
         }
     }
 
+ done:
     opreg = OR_A0;
     disp = 0;
     *reg_ptr = opreg;
-- 
1.8.3.1




reply via email to

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