[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PULL 08/12] target/i386: use TSTEQ/TSTNE to test low bits
From: |
Paolo Bonzini |
Subject: |
[PULL 08/12] target/i386: use TSTEQ/TSTNE to test low bits |
Date: |
Fri, 8 Mar 2024 15:55:50 +0100 |
When testing the sign bit or equality to zero of a partial register, it
is useful to use a single TSTEQ or TSTNE operation. It can also be used
to test the parity flag, using bit 0 of the population count.
Do not do this for target_ulong-sized values however; the optimizer would
produce a comparison against zero anyway, and it avoids shifts by 64
which are undefined behavior.
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
target/i386/tcg/translate.c | 28 ++++++++++++++++++++--------
target/i386/tcg/emit.c.inc | 5 ++---
2 files changed, 22 insertions(+), 11 deletions(-)
diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c
index 07f642dc9e9..fe9021833e3 100644
--- a/target/i386/tcg/translate.c
+++ b/target/i386/tcg/translate.c
@@ -927,11 +927,21 @@ typedef struct CCPrepare {
bool no_setcond;
} CCPrepare;
+static CCPrepare gen_prepare_sign_nz(TCGv src, MemOp size)
+{
+ if (size == MO_TL) {
+ return (CCPrepare) { .cond = TCG_COND_LT, .reg = src, .mask = -1 };
+ } else {
+ return (CCPrepare) { .cond = TCG_COND_TSTNE, .reg = src, .mask = -1,
+ .imm = 1ull << ((8 << size) - 1) };
+ }
+}
+
/* compute eflags.C to reg */
static CCPrepare gen_prepare_eflags_c(DisasContext *s, TCGv reg)
{
TCGv t0, t1;
- int size, shift;
+ MemOp size;
switch (s->cc_op) {
case CC_OP_SUBB ... CC_OP_SUBQ:
@@ -966,9 +976,7 @@ static CCPrepare gen_prepare_eflags_c(DisasContext *s, TCGv
reg)
case CC_OP_SHLB ... CC_OP_SHLQ:
/* (CC_SRC >> (DATA_BITS - 1)) & 1 */
size = s->cc_op - CC_OP_SHLB;
- shift = (8 << size) - 1;
- return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src,
- .mask = (target_ulong)1 << shift };
+ return gen_prepare_sign_nz(cpu_cc_src, size);
case CC_OP_MULB ... CC_OP_MULQ:
return (CCPrepare) { .cond = TCG_COND_NE,
@@ -1028,8 +1036,7 @@ static CCPrepare gen_prepare_eflags_s(DisasContext *s,
TCGv reg)
default:
{
MemOp size = (s->cc_op - CC_OP_ADDB) & 3;
- TCGv t0 = gen_ext_tl(reg, cpu_cc_dst, size, true);
- return (CCPrepare) { .cond = TCG_COND_LT, .reg = t0, .mask = -1 };
+ return gen_prepare_sign_nz(cpu_cc_dst, size);
}
}
}
@@ -1076,8 +1083,13 @@ static CCPrepare gen_prepare_eflags_z(DisasContext *s,
TCGv reg)
default:
{
MemOp size = (s->cc_op - CC_OP_ADDB) & 3;
- TCGv t0 = gen_ext_tl(reg, cpu_cc_dst, size, false);
- return (CCPrepare) { .cond = TCG_COND_EQ, .reg = t0, .mask = -1 };
+ if (size == MO_TL) {
+ return (CCPrepare) { .cond = TCG_COND_EQ, .reg = cpu_cc_dst,
+ .mask = -1 };
+ } else {
+ return (CCPrepare) { .cond = TCG_COND_TSTEQ, .reg = cpu_cc_dst,
+ .mask = -1, .imm = (1ull << (8 << size))
- 1 };
+ }
}
}
}
diff --git a/target/i386/tcg/emit.c.inc b/target/i386/tcg/emit.c.inc
index 6bcf88ecd71..0e00f6635dd 100644
--- a/target/i386/tcg/emit.c.inc
+++ b/target/i386/tcg/emit.c.inc
@@ -1209,7 +1209,7 @@ static void gen_CMPccXADD(DisasContext *s, CPUX86State
*env, X86DecodedInsn *dec
[JCC_Z] = TCG_COND_EQ,
[JCC_BE] = TCG_COND_LEU,
[JCC_S] = TCG_COND_LT, /* test sign bit by comparing against 0 */
- [JCC_P] = TCG_COND_EQ, /* even parity - tests low bit of popcount */
+ [JCC_P] = TCG_COND_TSTEQ, /* even parity - tests low bit of popcount
*/
[JCC_L] = TCG_COND_LT,
[JCC_LE] = TCG_COND_LE,
};
@@ -1260,8 +1260,7 @@ static void gen_CMPccXADD(DisasContext *s, CPUX86State
*env, X86DecodedInsn *dec
case JCC_P:
tcg_gen_ext8u_tl(s->tmp0, s->T0);
tcg_gen_ctpop_tl(s->tmp0, s->tmp0);
- tcg_gen_andi_tl(s->tmp0, s->tmp0, 1);
- cmp_lhs = s->tmp0, cmp_rhs = tcg_constant_tl(0);
+ cmp_lhs = s->tmp0, cmp_rhs = tcg_constant_tl(1);
break;
case JCC_S:
--
2.43.2
- [PULL 00/12] Misc fixes, i386 TSTEQ/TSTNE, coverity CI for 2024-03-08, Paolo Bonzini, 2024/03/08
- [PULL 02/12] system/qdev-monitor: move drain_call_rcu call under if (!dev) in qmp_device_add(), Paolo Bonzini, 2024/03/08
- [PULL 01/12] hw/scsi/lsi53c895a: add timer to scripts processing, Paolo Bonzini, 2024/03/08
- [PULL 03/12] meson: Remove --warn-common ldflag, Paolo Bonzini, 2024/03/08
- [PULL 04/12] hw/scsi/lsi53c895a: stop script on phase mismatch, Paolo Bonzini, 2024/03/08
- [PULL 07/12] mips: do not list individual devices from configs/, Paolo Bonzini, 2024/03/08
- [PULL 05/12] hw/intc/apic: fix memory leak, Paolo Bonzini, 2024/03/08
- [PULL 06/12] oslib-posix: fix memory leak in touch_all_pages, Paolo Bonzini, 2024/03/08
- [PULL 09/12] target/i386: use TSTEQ/TSTNE to check flags, Paolo Bonzini, 2024/03/08
- [PULL 08/12] target/i386: use TSTEQ/TSTNE to test low bits,
Paolo Bonzini <=
- [PULL 11/12] run-coverity-scan: add --check-upload-only option, Paolo Bonzini, 2024/03/08
- [PULL 10/12] target/i386: remove mask from CCPrepare, Paolo Bonzini, 2024/03/08
- [PULL 12/12] gitlab-ci: add manual job to run Coverity, Paolo Bonzini, 2024/03/08
- Re: [PULL 00/12] Misc fixes, i386 TSTEQ/TSTNE, coverity CI for 2024-03-08, Peter Maydell, 2024/03/08