]> git.proxmox.com Git - qemu.git/commitdiff
target-i386: Fix addr32 prefix in gen_lea_modrm
authorRichard Henderson <rth@twiddle.net>
Tue, 12 Nov 2013 01:16:56 +0000 (11:16 +1000)
committerAnthony Liguori <aliguori@amazon.com>
Thu, 21 Nov 2013 16:01:16 +0000 (08:01 -0800)
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>
Message-id: 1384219016-5170-1-git-send-email-rth@twiddle.net
Signed-off-by: Anthony Liguori <aliguori@amazon.com>
target-i386/translate.c

index ecf16b389b755fdd14ca3257a0a2236cd4be6521..7916e5b1f6fd95d0f1a27e51055bd80980f6fa81 100644 (file)
@@ -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;