Commit f4c828b633 for qemu.org

commit f4c828b6330934aa887ad721de8501ac704cefc3
Author: Paolo Bonzini <pbonzini@redhat.com>
Date:   Sat Oct 17 09:53:54 2026 +0200

    target/i386/tcg: remove X and Y operand types

    Since the Intel SDM is moving away from operand types, remove more of
    the implicit types; X and Y are meant for string instructions but the
    DS:SI and ES:DI addressing modes are handled entirely in the generator
    functions; the operands were just placeholders to distinguish byte
    string operations from s->dflag string operations.

    Note that this moves the port for INS and OUTS from s->T1 to s->T0.

    This frees up some operand letters that could be useful in the future,
    for example to allocate K/X/Y to mask registers in the same guise as
    H/V/W for AVX.

    Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>

diff --git a/target/i386/tcg/decode-new.c.inc b/target/i386/tcg/decode-new.c.inc
index 65fd402c17..7e5ece380a 100644
--- a/target/i386/tcg/decode-new.c.inc
+++ b/target/i386/tcg/decode-new.c.inc
@@ -1810,10 +1810,10 @@ static const X86OpEntry opcodes_root[256] = {
     [0xA1] = X86_OP_ENTRY3(MOV, 0,v, O,v, None, None), /* rAX, Ov */
     [0xA2] = X86_OP_ENTRY3(MOV, O,b, 0,b, None, None), /* Ob, AL */
     [0xA3] = X86_OP_ENTRY3(MOV, O,v, 0,v, None, None), /* Ov, rAX */
-    [0xA4] = X86_OP_ENTRYrr(MOVS, Y,b, X,b),
-    [0xA5] = X86_OP_ENTRYrr(MOVS, Y,v, X,v),
-    [0xA6] = X86_OP_ENTRYrr(CMPS, Y,b, X,b),
-    [0xA7] = X86_OP_ENTRYrr(CMPS, Y,v, X,v),
+    [0xA4] = X86_OP_ENTRY0(MOVS),
+    [0xA5] = X86_OP_ENTRY0(MOVS),
+    [0xA6] = X86_OP_ENTRY0(CMPS),
+    [0xA7] = X86_OP_ENTRY0(CMPS),

     [0xB0] = X86_OP_ENTRY3(MOV, LoBits,b, I,b, None, None),
     [0xB1] = X86_OP_ENTRY3(MOV, LoBits,b, I,b, None, None),
@@ -1916,10 +1916,10 @@ static const X86OpEntry opcodes_root[256] = {
     [0x69] = X86_OP_ENTRY3(IMUL3, G,v, E,v, I,z, sextT0),
     [0x6A] = X86_OP_ENTRYr(PUSH, I,b),
     [0x6B] = X86_OP_ENTRY3(IMUL3, G,v, E,v, I,b, sextT0),
-    [0x6C] = X86_OP_ENTRYrr(INS, Y,b, 2,w), /* DX */
-    [0x6D] = X86_OP_ENTRYrr(INS, Y,z, 2,w), /* DX */
-    [0x6E] = X86_OP_ENTRYrr(OUTS, X,b, 2,w), /* DX */
-    [0x6F] = X86_OP_ENTRYrr(OUTS, X,z, 2,w), /* DX */
+    [0x6C] = X86_OP_ENTRYr(INS, 2,w), /* DX */
+    [0x6D] = X86_OP_ENTRYr(INS, 2,w), /* DX */
+    [0x6E] = X86_OP_ENTRYr(OUTS, 2,w), /* DX */
+    [0x6F] = X86_OP_ENTRYr(OUTS, 2,w), /* DX */

     [0x78] = X86_OP_ENTRYr(Jcc, J,b),
     [0x79] = X86_OP_ENTRYr(Jcc, J,b),
@@ -1951,13 +1951,13 @@ static const X86OpEntry opcodes_root[256] = {

     [0xA8] = X86_OP_ENTRYrr(TEST, 0,b, I,b),   /* AL, Ib */
     [0xA9] = X86_OP_ENTRYrr(TEST, 0,v, I,z),   /* rAX, Iz */
-    [0xAA] = X86_OP_ENTRYwr(STOS, Y,b, 0,b),
-    [0xAB] = X86_OP_ENTRYwr(STOS, Y,v, 0,v),
+    [0xAA] = X86_OP_ENTRYr(STOS, 0,b),
+    [0xAB] = X86_OP_ENTRYr(STOS, 0,v),
     /* Manual writeback because REP LODS (!) has to write EAX/RAX after every LODS.  */
-    [0xAC] = X86_OP_ENTRYr(LODS, X,b),
-    [0xAD] = X86_OP_ENTRYr(LODS, X,v),
-    [0xAE] = X86_OP_ENTRYrr(SCAS, 0,b, Y,b),
-    [0xAF] = X86_OP_ENTRYrr(SCAS, 0,v, Y,v),
+    [0xAC] = X86_OP_ENTRY0(LODS),
+    [0xAD] = X86_OP_ENTRY0(LODS),
+    [0xAE] = X86_OP_ENTRYr(SCAS, 0,b),
+    [0xAF] = X86_OP_ENTRYr(SCAS, 0,v),

     [0xB8] = X86_OP_ENTRYwr(MOV, LoBits,v, I,v),
     [0xB9] = X86_OP_ENTRYwr(MOV, LoBits,v, I,v),
@@ -2552,8 +2552,6 @@ static bool decode_op(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode,
     switch (type) {
     case X86_TYPE_None:  /* Implicit or absent */
     case X86_TYPE_F:  /* EFLAGS/RFLAGS */
-    case X86_TYPE_X:  /* string source */
-    case X86_TYPE_Y:  /* string destination */
         break;

     case X86_TYPE_B:  /* VEX.vvvv selects a GPR, else use modrm */
diff --git a/target/i386/tcg/decode-new.h b/target/i386/tcg/decode-new.h
index a823143bbd..2218a4eda3 100644
--- a/target/i386/tcg/decode-new.h
+++ b/target/i386/tcg/decode-new.h
@@ -41,8 +41,6 @@ typedef enum X86OpType {
     X86_TYPE_U, /* R/M in the modrm byte selects an XMM/YMM register */
     X86_TYPE_V, /* reg in the modrm byte selects an XMM/YMM register */
     X86_TYPE_W, /* XMM/YMM modrm operand */
-    X86_TYPE_X, /* string source */
-    X86_TYPE_Y, /* string destination */

     /* Custom */
     X86_TYPE_EM, /* modrm byte selects an ALU memory operand */
diff --git a/target/i386/tcg/emit.c.inc b/target/i386/tcg/emit.c.inc
index a1ae582174..5754f3dcc8 100644
--- a/target/i386/tcg/emit.c.inc
+++ b/target/i386/tcg/emit.c.inc
@@ -1923,7 +1923,7 @@ static void gen_CMPccXADD(DisasContext *s, X86DecodedInsn *decode)

 static void gen_CMPS(DisasContext *s, X86DecodedInsn *decode)
 {
-    MemOp ot = decode->op[2].ot;
+    MemOp ot = decode->b & 1 ? s->dflag : MO_8;
     gen_repz_nz(s, ot, gen_cmps);
 }

@@ -2388,10 +2388,10 @@ static void gen_INC(DisasContext *s, X86DecodedInsn *decode)

 static void gen_INS(DisasContext *s, X86DecodedInsn *decode)
 {
-    MemOp ot = decode->op[1].ot;
+    MemOp ot = decode->b & 1 ? mo_ins_outs(s) : MO_8;
     TCGv_i32 port = tcg_temp_new_i32();

-    tcg_gen_trunc_tl_i32(port, s->T1);
+    tcg_gen_trunc_tl_i32(port, s->T0);
     tcg_gen_ext16u_i32(port, port);
     if (!gen_check_io(s, ot, port,
                       SVM_IOIO_TYPE_MASK | SVM_IOIO_STR_MASK)) {
@@ -2593,7 +2593,7 @@ static void gen_LGS(DisasContext *s, X86DecodedInsn *decode)

 static void gen_LODS(DisasContext *s, X86DecodedInsn *decode)
 {
-    MemOp ot = decode->op[1].ot;
+    MemOp ot = decode->b & 1 ? s->dflag : MO_8;
     gen_repz(s, ot, gen_lods);
 }

@@ -2803,7 +2803,7 @@ static void gen_MOVq_dq(DisasContext *s, X86DecodedInsn *decode)

 static void gen_MOVS(DisasContext *s, X86DecodedInsn *decode)
 {
-    MemOp ot = decode->op[2].ot;
+    MemOp ot = decode->b & 1 ? s->dflag : MO_8;
     gen_repz(s, ot, gen_movs);
 }

@@ -2960,10 +2960,10 @@ static void gen_OUT(DisasContext *s, X86DecodedInsn *decode)

 static void gen_OUTS(DisasContext *s, X86DecodedInsn *decode)
 {
-    MemOp ot = decode->op[1].ot;
+    MemOp ot = decode->b & 1 ? mo_ins_outs(s) : MO_8;
     TCGv_i32 port = tcg_temp_new_i32();

-    tcg_gen_trunc_tl_i32(port, s->T1);
+    tcg_gen_trunc_tl_i32(port, s->T0);
     tcg_gen_ext16u_i32(port, port);
     if (!gen_check_io(s, ot, port, SVM_IOIO_STR_MASK)) {
         return;
@@ -4128,7 +4128,7 @@ static void gen_SBB(DisasContext *s, X86DecodedInsn *decode)

 static void gen_SCAS(DisasContext *s, X86DecodedInsn *decode)
 {
-    MemOp ot = decode->op[2].ot;
+    MemOp ot = decode->b & 1 ? s->dflag : MO_8;
     gen_repz_nz(s, ot, gen_scas);
 }

@@ -4332,7 +4332,7 @@ static void gen_STMXCSR(DisasContext *s, X86DecodedInsn *decode)

 static void gen_STOS(DisasContext *s, X86DecodedInsn *decode)
 {
-    MemOp ot = decode->op[1].ot;
+    MemOp ot = decode->b & 1 ? s->dflag : MO_8;
     gen_repz(s, ot, gen_stos);
 }

diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c
index 3d542acd97..b715921c37 100644
--- a/target/i386/tcg/translate.c
+++ b/target/i386/tcg/translate.c
@@ -403,6 +403,12 @@ static inline bool byte_reg_is_xH(DisasContext *s, int reg)
     return true;
 }

+/* Select the size of an INS/OUTS operation ("z" operand size).  */
+static inline MemOp mo_ins_outs(DisasContext *s)
+{
+    return s->dflag == MO_16 ? MO_16 : MO_32;
+}
+
 /* Select the size of a push/pop operation.  */
 static inline MemOp mo_pushpop(DisasContext *s, MemOp ot)
 {