Commit 5e59fb10 authored by Peter Maydell's avatar Peter Maydell
Browse files

Merge remote-tracking branch 'remotes/rth/tags/pull-tcg-20170117' into staging



tcg/i386 fixes

# gpg: Signature made Tue 17 Jan 2017 22:58:04 GMT
# gpg:                using RSA key 0xAD1270CC4DD0279B
# gpg: Good signature from "Richard Henderson <rth7680@gmail.com>"
# gpg:                 aka "Richard Henderson <rth@redhat.com>"
# gpg:                 aka "Richard Henderson <rth@twiddle.net>"
# Primary key fingerprint: 9CB1 8DDA F8E8 49AD 2AFC  16A4 AD12 70CC 4DD0 279B

* remotes/rth/tags/pull-tcg-20170117:
  tcg/i386: Always use TZCNT when available
  Revert "tcg/i386: Rely on undefined/undocumented behaviour of BSF/BSR"

Signed-off-by: default avatarPeter Maydell <peter.maydell@linaro.org>
parents ab4b9276 39f099ec
Loading
Loading
Loading
Loading
+20 −25
Original line number Diff line number Diff line
@@ -1143,17 +1143,18 @@ static void tcg_out_movcond64(TCGContext *s, TCGCond cond, TCGReg dest,
static void tcg_out_ctz(TCGContext *s, int rexw, TCGReg dest, TCGReg arg1,
                        TCGArg arg2, bool const_a2)
{
    if (have_bmi1) {
        tcg_out_modrm(s, OPC_TZCNT + rexw, dest, arg1);
        if (const_a2) {
        tcg_debug_assert(have_bmi1);
            tcg_debug_assert(arg2 == (rexw ? 64 : 32));
        tcg_out_modrm(s, OPC_TZCNT + rexw, dest, arg1);
        } else {
        /* ??? The manual says that the output is undefined when the
           input is zero, but real hardware leaves it unchanged.  As
           noted in target-i386/translate.c, real programs depend on
           this -- now we are one more of those.  */
        tcg_debug_assert(dest == arg2);
            tcg_debug_assert(dest != arg2);
            tcg_out_cmov(s, TCG_COND_LTU, rexw, dest, arg2);
        }
    } else {
        tcg_debug_assert(dest != arg2);
        tcg_out_modrm(s, OPC_BSF + rexw, dest, arg1);
        tcg_out_cmov(s, TCG_COND_EQ, rexw, dest, arg2);
    }
}

@@ -1166,26 +1167,20 @@ static void tcg_out_clz(TCGContext *s, int rexw, TCGReg dest, TCGReg arg1,
            tcg_debug_assert(arg2 == (rexw ? 64 : 32));
        } else {
            tcg_debug_assert(dest != arg2);
            /* LZCNT sets C if the input was zero.  */
            tcg_out_cmov(s, TCG_COND_LTU, rexw, dest, arg2);
        }
    } else {
        TCGType type = rexw ? TCG_TYPE_I64: TCG_TYPE_I32;
        TCGArg rev = rexw ? 63 : 31;

        /* Recall that the output of BSR is the index not the count.
           Therefore we must adjust the result by ^ (SIZE-1).  In some
           cases below, we prefer an extra XOR to a JMP.  */
        /* ??? See the comment in tcg_out_ctz re BSF.  */
        if (const_a2) {
        tcg_debug_assert(!const_a2);
        tcg_debug_assert(dest != arg1);
            tcg_out_movi(s, type, dest, arg2 ^ rev);
        } else {
            tcg_debug_assert(dest == arg2);
            tgen_arithi(s, ARITH_XOR + rexw, dest, rev, 0);
        }
        tcg_debug_assert(dest != arg2);

        /* Recall that the output of BSR is the index not the count.  */
        tcg_out_modrm(s, OPC_BSR + rexw, dest, arg1);
        tgen_arithi(s, ARITH_XOR + rexw, dest, rev, 0);
        tgen_arithi(s, ARITH_XOR + rexw, dest, rexw ? 63 : 31, 0);

        /* Since we have destroyed the flags from BSR, we have to re-test.  */
        tcg_out_cmp(s, arg1, 0, 1, rexw);
        tcg_out_cmov(s, TCG_COND_EQ, rexw, dest, arg2);
    }
}

@@ -2459,7 +2454,7 @@ static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode op)
    case INDEX_op_ctz_i64:
        {
            static const TCGTargetOpDef ctz[2] = {
                { .args_ct_str = { "r", "r", "0" } },
                { .args_ct_str = { "&r", "r", "r" } },
                { .args_ct_str = { "&r", "r", "rW" } },
            };
            return &ctz[have_bmi1];
@@ -2468,7 +2463,7 @@ static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode op)
    case INDEX_op_clz_i64:
        {
            static const TCGTargetOpDef clz[2] = {
                { .args_ct_str = { "&r", "r", "0i" } },
                { .args_ct_str = { "&r", "r", "r" } },
                { .args_ct_str = { "&r", "r", "rW" } },
            };
            return &clz[have_lzcnt];