aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Henderson <richard.henderson@linaro.org>2025-01-17 22:39:14 -0800
committerRichard Henderson <richard.henderson@linaro.org>2025-04-28 13:40:17 -0700
commit0ad6d64b7be6287f8c07c72f8462ef5635b1e2da (patch)
tree2a01f29fb37042c854a89cb20673458e61973659
parente37e98b711975752d592e7b2daf11d320d0a8daf (diff)
downloadqemu-0ad6d64b7be6287f8c07c72f8462ef5635b1e2da.zip
qemu-0ad6d64b7be6287f8c07c72f8462ef5635b1e2da.tar.gz
qemu-0ad6d64b7be6287f8c07c72f8462ef5635b1e2da.tar.bz2
tcg/i386: Special case addci r, 0, 0
Using addci with two zeros as input in order to capture the value of the carry-in bit is common. Special case this with sbb+neg so that we do not have to load 0 into a register first. Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
-rw-r--r--tcg/i386/tcg-target-con-set.h1
-rw-r--r--tcg/i386/tcg-target.c.inc46
2 files changed, 44 insertions, 3 deletions
diff --git a/tcg/i386/tcg-target-con-set.h b/tcg/i386/tcg-target-con-set.h
index 85c9383..458d69c 100644
--- a/tcg/i386/tcg-target-con-set.h
+++ b/tcg/i386/tcg-target-con-set.h
@@ -45,6 +45,7 @@ C_O1_I2(r, L, L)
C_O1_I2(r, r, r)
C_O1_I2(r, r, re)
C_O1_I2(r, r, ri)
+C_O1_I2(r, rO, re)
C_O1_I2(x, x, x)
C_N1_I2(r, r, r)
C_N1_I2(r, r, rW)
diff --git a/tcg/i386/tcg-target.c.inc b/tcg/i386/tcg-target.c.inc
index 44f9afc..da05f13 100644
--- a/tcg/i386/tcg-target.c.inc
+++ b/tcg/i386/tcg-target.c.inc
@@ -2670,10 +2670,50 @@ static const TCGOutOpBinary outop_addcio = {
.out_rri = tgen_addcio_imm,
};
+static void tgen_addci_rrr(TCGContext *s, TCGType type,
+ TCGReg a0, TCGReg a1, TCGReg a2)
+{
+ /* Because "0O" is not a valid constraint, we must match ourselves. */
+ if (a0 == a2) {
+ tgen_addcio(s, type, a0, a0, a1);
+ } else {
+ tcg_out_mov(s, type, a0, a1);
+ tgen_addcio(s, type, a0, a0, a2);
+ }
+}
+
+static void tgen_addci_rri(TCGContext *s, TCGType type,
+ TCGReg a0, TCGReg a1, tcg_target_long a2)
+{
+ tcg_out_mov(s, type, a0, a1);
+ tgen_addcio_imm(s, type, a0, a0, a2);
+}
+
+static void tgen_addci_rir(TCGContext *s, TCGType type,
+ TCGReg a0, tcg_target_long a1, TCGReg a2)
+{
+ tgen_addci_rri(s, type, a0, a2, a1);
+}
+
+static void tgen_addci_rii(TCGContext *s, TCGType type, TCGReg a0,
+ tcg_target_long a1, tcg_target_long a2)
+{
+ if (a2 == 0) {
+ /* Implement 0 + 0 + C with -(x - x - c). */
+ tgen_arithr(s, ARITH_SBB, a0, a0);
+ tcg_out_modrm(s, OPC_GRP3_Ev, EXT3_NEG, a0);
+ } else {
+ tcg_out_movi(s, type, a0, a2);
+ tgen_addcio_imm(s, type, a0, a0, a1);
+ }
+}
+
static const TCGOutOpAddSubCarry outop_addci = {
- .base.static_constraint = C_O1_I2(r, 0, re),
- .out_rrr = tgen_addcio,
- .out_rri = tgen_addcio_imm,
+ .base.static_constraint = C_O1_I2(r, rO, re),
+ .out_rrr = tgen_addci_rrr,
+ .out_rri = tgen_addci_rri,
+ .out_rir = tgen_addci_rir,
+ .out_rii = tgen_addci_rii,
};
static void tcg_out_set_carry(TCGContext *s)