target-i386: fix 32-bit addresses in LEA
authorPaolo Bonzini <pbonzini@redhat.com>
Wed, 12 Oct 2016 07:23:39 +0000 (09:23 +0200)
committerPaolo Bonzini <pbonzini@redhat.com>
Mon, 24 Oct 2016 13:27:19 +0000 (15:27 +0200)
This was found with test-i386.  The issue is that instructions
such as

    addr32 lea (%eax), %rax

did not perform a 32-bit extension, because the LEA translation
skipped the gen_lea_v_seg step.  That step does not just add
segments, it also takes care of extending from address size to
pointer size.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
target-i386/translate.c

index 94475579118b3203eceb6be56714046a417c28df..23fde58547ab26d29a577d903fda3568b4045d08 100644 (file)
@@ -457,13 +457,12 @@ static void gen_lea_v_seg(DisasContext *s, TCGMemOp aflag, TCGv a0,
 #endif
     case MO_32:
         /* 32 bit address */
+        if (ovr_seg < 0 && s->addseg) {
+            ovr_seg = def_seg;
+        }
         if (ovr_seg < 0) {
-            if (s->addseg) {
-                ovr_seg = def_seg;
-            } else {
-                tcg_gen_ext32u_tl(cpu_A0, a0);
-                return;
-            }
+            tcg_gen_ext32u_tl(cpu_A0, a0);
+            return;
         }
         break;
     case MO_16:
@@ -5372,7 +5371,8 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
         {
             AddressParts a = gen_lea_modrm_0(env, s, modrm);
             TCGv ea = gen_lea_modrm_1(a);
-            gen_op_mov_reg_v(dflag, reg, ea);
+            gen_lea_v_seg(s, s->aflag, ea, -1, -1);
+            gen_op_mov_reg_v(dflag, reg, cpu_A0);
         }
         break;