tcg/i386: convert add/sub of 128 to sub/add of -128

Extend the existing conditional that generates INC/DEC, to also swap an
ADD for a SUB and vice versa when the immediate is 128.  This facilitates
using OPC_ARITH_EvIb instead of OPC_ARITH_EvIz.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Message-Id: <20231228120514.70205-1-pbonzini@redhat.com>
[rth: Use a switch on C]
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
Paolo Bonzini 2023-12-28 13:05:14 +01:00 committed by Richard Henderson
parent 34eac35f89
commit 64708db302

View file

@ -1316,14 +1316,22 @@ static void tgen_arithi(TCGContext *s, int c, int r0,
c &= 7; c &= 7;
} }
/* ??? While INC is 2 bytes shorter than ADDL $1, they also induce switch (c) {
partial flags update stalls on Pentium4 and are not recommended case ARITH_ADD:
by current Intel optimization manuals. */ case ARITH_SUB:
if (!cf && (c == ARITH_ADD || c == ARITH_SUB) && (val == 1 || val == -1)) { if (!cf) {
/*
* ??? While INC is 2 bytes shorter than ADDL $1, they also induce
* partial flags update stalls on Pentium4 and are not recommended
* by current Intel optimization manuals.
*/
if (val == 1 || val == -1) {
int is_inc = (c == ARITH_ADD) ^ (val < 0); int is_inc = (c == ARITH_ADD) ^ (val < 0);
if (TCG_TARGET_REG_BITS == 64) { if (TCG_TARGET_REG_BITS == 64) {
/* The single-byte increment encodings are re-tasked as the /*
REX prefixes. Use the MODRM encoding. */ * The single-byte increment encodings are re-tasked
* as the REX prefixes. Use the MODRM encoding.
*/
tcg_out_modrm(s, OPC_GRP5 + rexw, tcg_out_modrm(s, OPC_GRP5 + rexw,
(is_inc ? EXT5_INC_Ev : EXT5_DEC_Ev), r0); (is_inc ? EXT5_INC_Ev : EXT5_DEC_Ev), r0);
} else { } else {
@ -1331,8 +1339,18 @@ static void tgen_arithi(TCGContext *s, int c, int r0,
} }
return; return;
} }
if (val == 128) {
/*
* Facilitate using an 8-bit immediate. Carry is inverted
* by this transformation, so do it only if cf == 0.
*/
c ^= ARITH_ADD ^ ARITH_SUB;
val = -128;
}
}
break;
if (c == ARITH_AND) { case ARITH_AND:
if (TCG_TARGET_REG_BITS == 64) { if (TCG_TARGET_REG_BITS == 64) {
if (val == 0xffffffffu) { if (val == 0xffffffffu) {
tcg_out_ext32u(s, r0, r0); tcg_out_ext32u(s, r0, r0);
@ -1351,6 +1369,7 @@ static void tgen_arithi(TCGContext *s, int c, int r0,
tcg_out_ext16u(s, r0, r0); tcg_out_ext16u(s, r0, r0);
return; return;
} }
break;
} }
if (val == (int8_t)val) { if (val == (int8_t)val) {