Commit 7865eec4 authored by Richard Henderson's avatar Richard Henderson Committed by Anthony Liguori
Browse files

target-i386: Fix addr32 prefix in gen_lea_modrm



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: default avatarRichard Henderson <rth@twiddle.net>
Message-id: 1384219016-5170-1-git-send-email-rth@twiddle.net
Signed-off-by: default avatarAnthony Liguori <aliguori@amazon.com>
parent 33effd3a
Loading
Loading
Loading
Loading
+47 −45
Original line number Diff line number Diff line
@@ -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)
        /* For correct popl handling with esp.  */
        if (base == R_ESP && 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);
        }

        /* Compute the address, with a minimum number of TCG ops.  */
        TCGV_UNUSED(sum);
        if (index >= 0) {
            if (scale == 0) {
                sum = cpu_regs[index];
            } else {
#ifdef TARGET_X86_64
            if (s->aflag == 2) {
                gen_op_movq_A0_im(disp);
            } else
#endif
            {
                gen_op_movl_A0_im(disp);
                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;
            }
        /* 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);
        } 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 == 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;