aboutsummaryrefslogtreecommitdiff
path: root/tcg
diff options
context:
space:
mode:
authorPaolo Bonzini <pbonzini@redhat.com>2023-12-28 13:05:14 +0100
committerRichard Henderson <richard.henderson@linaro.org>2024-01-11 08:46:35 +1100
commit64708db302edfe57474239a51d4dad4466fac44a (patch)
treef4bf5355163a449b09e123d1b98302ab84c5dc67 /tcg
parent34eac35f893664eb8545b98142e23d9954722766 (diff)
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>
Diffstat (limited to 'tcg')
-rw-r--r--tcg/i386/tcg-target.c.inc49
1 files changed, 34 insertions, 15 deletions
diff --git a/tcg/i386/tcg-target.c.inc b/tcg/i386/tcg-target.c.inc
index a83f8aab30..29e80af78b 100644
--- a/tcg/i386/tcg-target.c.inc
+++ b/tcg/i386/tcg-target.c.inc
@@ -1316,23 +1316,41 @@ static void tgen_arithi(TCGContext *s, int c, int r0,
c &= 7;
}
- /* ??? 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 (!cf && (c == ARITH_ADD || c == ARITH_SUB) && (val == 1 || val == -1)) {
- int is_inc = (c == ARITH_ADD) ^ (val < 0);
- if (TCG_TARGET_REG_BITS == 64) {
- /* The single-byte increment encodings are re-tasked as the
- REX prefixes. Use the MODRM encoding. */
- tcg_out_modrm(s, OPC_GRP5 + rexw,
- (is_inc ? EXT5_INC_Ev : EXT5_DEC_Ev), r0);
- } else {
- tcg_out8(s, (is_inc ? OPC_INC_r32 : OPC_DEC_r32) + r0);
+ switch (c) {
+ case ARITH_ADD:
+ case ARITH_SUB:
+ 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);
+ if (TCG_TARGET_REG_BITS == 64) {
+ /*
+ * The single-byte increment encodings are re-tasked
+ * as the REX prefixes. Use the MODRM encoding.
+ */
+ tcg_out_modrm(s, OPC_GRP5 + rexw,
+ (is_inc ? EXT5_INC_Ev : EXT5_DEC_Ev), r0);
+ } else {
+ tcg_out8(s, (is_inc ? OPC_INC_r32 : OPC_DEC_r32) + r0);
+ }
+ 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;
+ }
}
- return;
- }
+ break;
- if (c == ARITH_AND) {
+ case ARITH_AND:
if (TCG_TARGET_REG_BITS == 64) {
if (val == 0xffffffffu) {
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);
return;
}
+ break;
}
if (val == (int8_t)val) {