On 1/8/26 00:44, Richard Henderson wrote:
On 1/8/26 02:14, Paolo Bonzini wrote:
Unlike the older code in translate.c, mod=11b *is* filtered out earlier
by decode_modrm.

Signed-off-by: Paolo Bonzini <[email protected]>
---
  target/i386/tcg/decode-new.c.inc | 7 -------
  1 file changed, 7 deletions(-)

diff --git a/target/i386/tcg/decode-new.c.inc b/target/i386/tcg/ decode-new.c.inc
index 243df7e3735..7b595607fa7 100644
--- a/target/i386/tcg/decode-new.c.inc
+++ b/target/i386/tcg/decode-new.c.inc
@@ -2024,12 +2024,6 @@ static AddressParts decode_modrm_address(CPUX86State *env, DisasContext *s,
      rm = modrm & 7;
      base = rm | REX_B(s);
-    if (mod == 3) {
-        /* Normally filtered out earlier, but including this path
-           simplifies multi-byte nop, as well as bndcl, bndcu, bndcn.  */
-        goto done;
-    }
-

I can see that this is true, but one has to dig around to see that it's so.

There's enough prep code duplicated between decode_modrm and decode_modrm_address that I think it would be worthwhile to merge the two functions and simplify.

Is there really so much?  I guess you could write the combined function like so:

    int modrm = get_modrm(s, env);
    int mod = (s->modrm >> 6) & 3;
    int rm = s->modrm & 7;
    if (mod == 3) {
        op->n = (rm | REX_B(s)) & reg_nb_mask(s, op->unit);
        return;
    }

    int def_seg = R_DS;
    int base = rm | REX_B(s);
    int index = -1;
    int scale = 0;
    targe_long disp = 0;
    bool is_vsib = decode->e.vex_class == 12;
    switch(s->aflag) {
        ...
    }

    op->has_ea = true;
    op->n = -1;
    decode->mem = (AddressParts){ def_seg, base, index, scale, disp };

but it does not seem so much better...  I guess I could do the modrm
split just once:

diff --git a/target/i386/tcg/decode-new.c.inc b/target/i386/tcg/decode-new.c.inc
index 41012659104..23cae451eb7 100644
--- a/target/i386/tcg/decode-new.c.inc
+++ b/target/i386/tcg/decode-new.c.inc
@@ -2247,21 +2247,19 @@
/* Decompose an address. */
 static AddressParts decode_modrm_address(CPUX86State *env, DisasContext *s,
-                                         int modrm, bool is_vsib)
+                                         int mod, int rm, bool is_vsib)
 {
-    int def_seg, base, index, scale, mod, rm;
+    int def_seg, base, index, scale;
     target_long disp;
     bool havesib;
+ assert(mod == 3);
     def_seg = R_DS;
+    base = rm | REX_B(s);
     index = -1;
     scale = 0;
     disp = 0;
- mod = (modrm >> 6) & 3;
-    rm = modrm & 7;
-    base = rm | REX_B(s);
-
     switch (s->aflag) {
     case MO_64:
     case MO_32:
@@ -2379,16 +2376,18 @@
 static int decode_modrm(DisasContext *s, CPUX86State *env,
                         X86DecodedInsn *decode, X86DecodedOp *op)
 {
-    int modrm = s->modrm;
-    if ((modrm >> 6) == 3) {
-        op->n = (modrm & 7);
+    int modrm = get_modrm(s, env);
+    int mod = (s->modrm >> 6) & 3;
+    int rm = s->modrm & 7;
+    if (mod == 3) {
+        op->n = rm;
         if (op->unit != X86_OP_MMX) {
             op->n |= REX_B(s);
         }
     } else {
         op->has_ea = true;
         op->n = -1;
-        decode->mem = decode_modrm_address(env, s, get_modrm(s, env),
+        decode->mem = decode_modrm_address(env, s, mod, rm,
                                            decode->e.vex_class == 12);
     }
     return modrm;


Also, not do things like

         switch (mod) {
...
         default:
         case 2:

where the default isn't reachable.

I agree and was curious to when it dated... and it's March 2003 :) (commit 4b74fe1f001, 
"many fixes", which brought in the very first implementation of 16-bit 
addressing modes):

+        default:
+        case 7:
+            gen_op_movl_A0_reg[R_EBX]();
+            break;

Paolo


Reply via email to