Index: trunk/src/VBox/VMM/VMMAll/IEMAllInstCommon.cpp.h
===================================================================
--- trunk/src/VBox/VMM/VMMAll/IEMAllInstCommon.cpp.h	(revision 100733)
+++ trunk/src/VBox/VMM/VMMAll/IEMAllInstCommon.cpp.h	(revision 100734)
@@ -730,16 +730,6 @@
 {
     IEMOP_MNEMONIC(InvalidWithRMNeedDecode, "InvalidWithRMNeedDecode");
-    if (pVCpu->iem.s.enmCpuVendor == CPUMCPUVENDOR_INTEL)
-    {
-#ifndef TST_IEM_CHECK_MC
-        if (IEM_IS_MODRM_MEM_MODE(bRm))
-        {
-            RTGCPTR      GCPtrEff;
-            VBOXSTRICTRC rcStrict = iemOpHlpCalcRmEffAddr(pVCpu, bRm, 0, &GCPtrEff);
-            if (rcStrict != VINF_SUCCESS)
-                return rcStrict;
-        }
-#endif
-    }
+    if (pVCpu->iem.s.enmCpuVendor == CPUMCPUVENDOR_INTEL && IEM_IS_MODRM_MEM_MODE(bRm))
+        IEM_OPCODE_SKIP_RM_EFF_ADDR_BYTES(bRm);
     IEMOP_HLP_DONE_DECODING();
     IEMOP_RAISE_INVALID_OPCODE_RET();
@@ -752,13 +742,6 @@
 {
     IEMOP_MNEMONIC(InvalidWithRMAllNeeded, "InvalidWithRMAllNeeded");
-#ifndef TST_IEM_CHECK_MC
     if (IEM_IS_MODRM_MEM_MODE(bRm))
-    {
-        RTGCPTR      GCPtrEff;
-        VBOXSTRICTRC rcStrict = iemOpHlpCalcRmEffAddr(pVCpu, bRm, 0, &GCPtrEff);
-        if (rcStrict != VINF_SUCCESS)
-            return rcStrict;
-    }
-#endif
+        IEM_OPCODE_SKIP_RM_EFF_ADDR_BYTES(bRm);
     IEMOP_HLP_DONE_DECODING();
     IEMOP_RAISE_INVALID_OPCODE_RET();
@@ -773,14 +756,7 @@
     if (pVCpu->iem.s.enmCpuVendor == CPUMCPUVENDOR_INTEL)
     {
-#ifndef TST_IEM_CHECK_MC
         if (IEM_IS_MODRM_MEM_MODE(bRm))
-        {
-            RTGCPTR      GCPtrEff;
-            VBOXSTRICTRC rcStrict = iemOpHlpCalcRmEffAddr(pVCpu, bRm, 0, &GCPtrEff);
-            if (rcStrict != VINF_SUCCESS)
-                return rcStrict;
-        }
-#endif
-        uint8_t bImm8;  IEM_OPCODE_GET_NEXT_U8(&bImm8);  RT_NOREF(bRm);
+            IEM_OPCODE_SKIP_RM_EFF_ADDR_BYTES(bRm);
+        uint8_t bImm8;  IEM_OPCODE_GET_NEXT_U8(&bImm8);  RT_NOREF(bImm8);
     }
     IEMOP_HLP_DONE_DECODING();
@@ -794,14 +770,7 @@
 {
     IEMOP_MNEMONIC(InvalidWithRMAllNeedImm8, "InvalidWithRMAllNeedImm8");
-#ifndef TST_IEM_CHECK_MC
     if (IEM_IS_MODRM_MEM_MODE(bRm))
-    {
-        RTGCPTR      GCPtrEff;
-        VBOXSTRICTRC rcStrict = iemOpHlpCalcRmEffAddr(pVCpu, bRm, 0, &GCPtrEff);
-        if (rcStrict != VINF_SUCCESS)
-            return rcStrict;
-    }
-#endif
-    uint8_t bImm8;  IEM_OPCODE_GET_NEXT_U8(&bImm8);  RT_NOREF(bRm);
+        IEM_OPCODE_SKIP_RM_EFF_ADDR_BYTES(bRm);
+    uint8_t bImm8;  IEM_OPCODE_GET_NEXT_U8(&bImm8);  RT_NOREF(bImm8);
     IEMOP_HLP_DONE_DECODING();
     IEMOP_RAISE_INVALID_OPCODE_RET();
@@ -816,13 +785,6 @@
     {
         uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm); RT_NOREF(bRm);
-#ifndef TST_IEM_CHECK_MC
         if (IEM_IS_MODRM_MEM_MODE(bRm))
-        {
-            RTGCPTR      GCPtrEff;
-            VBOXSTRICTRC rcStrict = iemOpHlpCalcRmEffAddr(pVCpu, bRm, 0, &GCPtrEff);
-            if (rcStrict != VINF_SUCCESS)
-                return rcStrict;
-        }
-#endif
+            IEM_OPCODE_SKIP_RM_EFF_ADDR_BYTES(bRm);
     }
     IEMOP_HLP_DONE_DECODING();
@@ -836,13 +798,6 @@
     IEMOP_MNEMONIC(InvalidAllNeedRM, "InvalidAllNeedRM");
     uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm); RT_NOREF(bRm);
-#ifndef TST_IEM_CHECK_MC
     if (IEM_IS_MODRM_MEM_MODE(bRm))
-    {
-        RTGCPTR      GCPtrEff;
-        VBOXSTRICTRC rcStrict = iemOpHlpCalcRmEffAddr(pVCpu, bRm, 0, &GCPtrEff);
-        if (rcStrict != VINF_SUCCESS)
-            return rcStrict;
-    }
-#endif
+        IEM_OPCODE_SKIP_RM_EFF_ADDR_BYTES(bRm);
     IEMOP_HLP_DONE_DECODING();
     IEMOP_RAISE_INVALID_OPCODE_RET();
@@ -858,13 +813,6 @@
     {
         uint8_t bRm;  IEM_OPCODE_GET_NEXT_U8(&bRm);  RT_NOREF(bRm);
-#ifndef TST_IEM_CHECK_MC
         if (IEM_IS_MODRM_MEM_MODE(bRm))
-        {
-            RTGCPTR      GCPtrEff;
-            VBOXSTRICTRC rcStrict = iemOpHlpCalcRmEffAddr(pVCpu, bRm, 0, &GCPtrEff);
-            if (rcStrict != VINF_SUCCESS)
-                return rcStrict;
-        }
-#endif
+            IEM_OPCODE_SKIP_RM_EFF_ADDR_BYTES(bRm);
         uint8_t bImm; IEM_OPCODE_GET_NEXT_U8(&bImm); RT_NOREF(bImm);
     }
@@ -883,13 +831,6 @@
         uint8_t b3rd; IEM_OPCODE_GET_NEXT_U8(&b3rd); RT_NOREF(b3rd);
         uint8_t bRm;  IEM_OPCODE_GET_NEXT_U8(&bRm);  RT_NOREF(bRm);
-#ifndef TST_IEM_CHECK_MC
         if (IEM_IS_MODRM_MEM_MODE(bRm))
-        {
-            RTGCPTR      GCPtrEff;
-            VBOXSTRICTRC rcStrict = iemOpHlpCalcRmEffAddr(pVCpu, bRm, 0, &GCPtrEff);
-            if (rcStrict != VINF_SUCCESS)
-                return rcStrict;
-        }
-#endif
+            IEM_OPCODE_SKIP_RM_EFF_ADDR_BYTES(bRm);
     }
     IEMOP_HLP_DONE_DECODING();
@@ -907,17 +848,10 @@
         uint8_t b3rd; IEM_OPCODE_GET_NEXT_U8(&b3rd); RT_NOREF(b3rd);
         uint8_t bRm;  IEM_OPCODE_GET_NEXT_U8(&bRm);  RT_NOREF(bRm);
-#ifndef TST_IEM_CHECK_MC
         if (IEM_IS_MODRM_MEM_MODE(bRm))
-        {
-            RTGCPTR      GCPtrEff;
-            VBOXSTRICTRC rcStrict = iemOpHlpCalcRmEffAddr(pVCpu, bRm, 1, &GCPtrEff);
-            if (rcStrict != VINF_SUCCESS)
-                return rcStrict;
-        }
-#endif
+            IEM_OPCODE_SKIP_RM_EFF_ADDR_BYTES(bRm);
         uint8_t bImm; IEM_OPCODE_GET_NEXT_U8(&bImm); RT_NOREF(bImm);
-        IEMOP_HLP_DONE_DECODING();
     }
-    IEMOP_RAISE_INVALID_OPCODE_RET();
-}
-
+    IEMOP_HLP_DONE_DECODING();
+    IEMOP_RAISE_INVALID_OPCODE_RET();
+}
+
Index: trunk/src/VBox/VMM/VMMAll/IEMAllInstPython.py
===================================================================
--- trunk/src/VBox/VMM/VMMAll/IEMAllInstPython.py	(revision 100733)
+++ trunk/src/VBox/VMM/VMMAll/IEMAllInstPython.py	(revision 100734)
@@ -3033,5 +3033,5 @@
         self.oReHashDefine3 = re.compile('(?s)\A\s*([A-Za-z_][A-Za-z0-9_]*)[^(]\s*(.*)\Z');        ##< Simple, no arguments.
         self.oReHashUndef   = re.compile('^\s*#\s*undef\s+(.*)$');
-        self.oReMcBeginEnd  = re.compile(r'\bIEM_MC_(BEGIN|END|DEFER_TO_CIMPL_[0-5]_RET)\s*\(');
+        self.oReMcBeginEnd  = re.compile(r'\bIEM_MC_(BEGIN|END|DEFER_TO_CIMPL_[1-5]_RET)\s*\('); ##> Not DEFER_TO_CIMPL_0_RET!
         self.fDebug         = True;
         self.fDebugMc       = False;
@@ -4768,5 +4768,5 @@
     def workerIemMcDeferToCImplXRet(self, sCode, offBeginStatementInCodeStr, offBeginStatementInLine, cParams):
         """
-        Process a IEM_MC_DEFER_TO_CIMPL_[0-5]_RET macro invocation.
+        Process a IEM_MC_DEFER_TO_CIMPL_[1-5]_RET macro invocation.
         """
         sStmt = 'IEM_MC_DEFER_TO_CIMPL_%d_RET' % (cParams,);
@@ -5033,5 +5033,6 @@
         oMatch = self.oReHashDefine2.match(sRest);
         if oMatch:
-            asArgs = [sParam.strip() for sParam in oMatch.group(2).split(',')];
+            sAllArgs = oMatch.group(2).strip();
+            asArgs = [sParam.strip() for sParam in sAllArgs.split(',')] if sAllArgs else None;
             sBody  = oMatch.group(3);
         else:
@@ -5049,4 +5050,11 @@
         # Is this of any interest to us?  We do NOT support MC blocks wihtin
         # nested macro expansion, just to avoid lots of extra work.
+        #
+        # Note! IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX and other macros someone making
+        #       use of IEMOP_RAISE_INVALID_LOCK_PREFIX_RET() will be ignored here and
+        #       dealt with by overriding IEMOP_RAISE_INVALID_LOCK_PREFIX_RET and its
+        #       siblings in the recompiler.  This is a lot simpler than nested macro
+        #       expansion and lots of heuristics for locating all the relevant macros.
+        #       Also, this way we don't produce lots of unnecessary threaded functions.
         #
         if sBody.find("IEM_MC_BEGIN") < 0:
Index: trunk/src/VBox/VMM/VMMAll/IEMAllInstTwoByte0f.cpp.h
===================================================================
--- trunk/src/VBox/VMM/VMMAll/IEMAllInstTwoByte0f.cpp.h	(revision 100733)
+++ trunk/src/VBox/VMM/VMMAll/IEMAllInstTwoByte0f.cpp.h	(revision 100734)
@@ -13843,15 +13843,8 @@
     {
         uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm); RT_NOREF(bRm);
-#ifndef TST_IEM_CHECK_MC
         if (IEM_IS_MODRM_MEM_MODE(bRm))
-        {
-            RTGCPTR      GCPtrEff;
-            VBOXSTRICTRC rcStrict = iemOpHlpCalcRmEffAddr(pVCpu, bRm, 0, &GCPtrEff);
-            if (rcStrict != VINF_SUCCESS)
-                return rcStrict;
-        }
-#endif
-        IEMOP_HLP_DONE_DECODING();
-    }
+            IEM_OPCODE_SKIP_RM_EFF_ADDR_BYTES(bRm);
+    }
+    IEMOP_HLP_DONE_DECODING();
     IEMOP_RAISE_INVALID_OPCODE_RET();
 }
Index: trunk/src/VBox/VMM/VMMAll/IEMAllInstVexMap1.cpp.h
===================================================================
--- trunk/src/VBox/VMM/VMMAll/IEMAllInstVexMap1.cpp.h	(revision 100733)
+++ trunk/src/VBox/VMM/VMMAll/IEMAllInstVexMap1.cpp.h	(revision 100734)
@@ -5410,16 +5410,13 @@
 FNIEMOP_DEF(iemOp_vud0)
 {
+/** @todo testcase: vud0 */
     IEMOP_MNEMONIC(vud0, "vud0");
     if (pVCpu->iem.s.enmCpuVendor == CPUMCPUVENDOR_INTEL)
     {
         uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm); RT_NOREF(bRm);
-#ifndef TST_IEM_CHECK_MC
-        RTGCPTR      GCPtrEff;
-        VBOXSTRICTRC rcStrict = iemOpHlpCalcRmEffAddr(pVCpu, bRm, 0, &GCPtrEff);
-        if (rcStrict != VINF_SUCCESS)
-            return rcStrict;
-#endif
-        IEMOP_HLP_DONE_DECODING();
-    }
+        if (IEM_IS_MODRM_MEM_MODE(bRm))
+            IEM_OPCODE_SKIP_RM_EFF_ADDR_BYTES(bRm);
+    }
+    IEMOP_HLP_DONE_DECODING();
     IEMOP_RAISE_INVALID_OPCODE_RET();
 }
Index: trunk/src/VBox/VMM/VMMAll/IEMAllThrdFuncsBltIn.cpp
===================================================================
--- trunk/src/VBox/VMM/VMMAll/IEMAllThrdFuncsBltIn.cpp	(revision 100733)
+++ trunk/src/VBox/VMM/VMMAll/IEMAllThrdFuncsBltIn.cpp	(revision 100734)
@@ -77,4 +77,16 @@
 }
 
+
+/**
+ * Built-in function that calls a C-implemention function taking zero arguments.
+ */
+IEM_DECL_IMPL_DEF(VBOXSTRICTRC, iemThreadedFunc_BltIn_DeferToCImpl0,
+                  (PVMCPU pVCpu, uint64_t uParam0, uint64_t uParam1, uint64_t uParam2))
+{
+    PFNIEMCIMPL0 const pfnCImpl = (PFNIEMCIMPL0)(uintptr_t)uParam0;
+    uint8_t const      cbInstr  = (uint8_t)uParam1;
+    RT_NOREF(uParam2);
+    return pfnCImpl(pVCpu, cbInstr);
+}
 
 
Index: trunk/src/VBox/VMM/VMMAll/IEMAllThrdPython.py
===================================================================
--- trunk/src/VBox/VMM/VMMAll/IEMAllThrdPython.py	(revision 100733)
+++ trunk/src/VBox/VMM/VMMAll/IEMAllThrdPython.py	(revision 100734)
@@ -199,4 +199,6 @@
     ## The value indicates whether it terminates the TB or not. The goal is to
     ## improve the recompiler so all but END_TB will be False.
+    ##
+    ## @note iemThreadedRecompilerMcDeferToCImpl0 duplicates info found here.
     kdCImplFlags = {
         'IEM_CIMPL_F_MODE':                 True,
@@ -914,4 +916,5 @@
         # Emit fEndTb = true or fTbBranched = true if any of the CIMPL flags
         # indicates we should do so.
+        # Note! iemThreadedRecompilerMcDeferToCImpl0 duplicates work done here.
         asEndTbFlags      = [];
         asTbBranchedFlags = [];
@@ -922,14 +925,7 @@
                 asTbBranchedFlags.append(sFlag);
         if asTbBranchedFlags:
-            aoStmts.extend([
-                iai.McCppGeneric('iemThreadedSetBranched(pVCpu, %s);'
-                                 % ((' | '.join(asTbBranchedFlags)).replace('IEM_CIMPL_F_BRANCH', 'IEMBRANCHED_F'),),
-                                 cchIndent = cchIndent), # Using the inline fn saves ~2 seconds for gcc 13/dbg (1m13s vs 1m15s).
-                #iai.McCppGeneric('pVCpu->iem.s.fTbBranched = %s;'
-                #                 % ((' | '.join(asTbBranchedFlags)).replace('IEM_CIMPL_F_BRANCH', 'IEMBRANCHED_F'),),
-                #                 cchIndent = cchIndent),
-                #iai.McCppGeneric('pVCpu->iem.s.GCPhysTbBranchSrcBuf = pVCpu->iem.s.GCPhysInstrBuf;', cchIndent = cchIndent),
-                #iai.McCppGeneric('pVCpu->iem.s.GCVirtTbBranchSrcBuf = pVCpu->iem.s.uInstrBufPc;', cchIndent = cchIndent),
-            ]);
+            aoStmts.append(iai.McCppGeneric('iemThreadedSetBranched(pVCpu, %s);'
+                                            % ((' | '.join(asTbBranchedFlags)).replace('IEM_CIMPL_F_BRANCH', 'IEMBRANCHED_F'),),
+                                            cchIndent = cchIndent)); # Inline fn saves ~2 seconds for gcc 13/dbg (1m13s vs 1m15s).
         if asEndTbFlags:
             aoStmts.append(iai.McCppGeneric('pVCpu->iem.s.fEndTb = true; /* %s */' % (','.join(asEndTbFlags),),
@@ -1289,4 +1285,5 @@
             '     * Predefined',
             '     */',
+            '    kIemThreadedFunc_DeferToCImpl0,',
             '    kIemThreadedFunc_CheckMode,',
             '    kIemThreadedFunc_CheckCsLim,',
@@ -1460,4 +1457,5 @@
                    + '     * Predefined.\n'
                    + '     */'
+                   + '    iemThreadedFunc_BltIn_DeferToCImpl0,\n'
                    + '    iemThreadedFunc_BltIn_CheckMode,\n'
                    + '    iemThreadedFunc_BltIn_CheckCsLim,\n'
@@ -1505,4 +1503,5 @@
                    + '     * Predefined.\n'
                    + '     */'
+                   + '    "BltIn_DeferToCImpl0",\n'
                    + '    "BltIn_CheckMode",\n'
                    + '    "BltIn_CheckCsLim",\n'
Index: trunk/src/VBox/VMM/VMMAll/IEMAllThrdRecompiler.cpp
===================================================================
--- trunk/src/VBox/VMM/VMMAll/IEMAllThrdRecompiler.cpp	(revision 100733)
+++ trunk/src/VBox/VMM/VMMAll/IEMAllThrdRecompiler.cpp	(revision 100734)
@@ -137,4 +137,13 @@
     ((a_GCPtrEff) = iemOpHlpCalcRmEffAddrJmpEx(pVCpu, (a_bRm), (a_cbImmAndRspOffset), &uEffAddrInfo))
 #endif
+
+/*
+ * Likewise override IEM_OPCODE_SKIP_RM_EFF_ADDR_BYTES so we fetch all the opcodes.
+ */
+#undef IEM_OPCODE_SKIP_RM_EFF_ADDR_BYTES
+#define IEM_OPCODE_SKIP_RM_EFF_ADDR_BYTES(a_bRm) do { \
+        uint64_t uEffAddrInfo; \
+        (void)iemOpHlpCalcRmEffAddrJmpEx(pVCpu, bRm, 0, &uEffAddrInfo); \
+    } while (0)
 
 /*
@@ -267,11 +276,29 @@
  */
 #undef IEM_MC_DEFER_TO_CIMPL_0_RET
-#define IEM_MC_DEFER_TO_CIMPL_0_RET(a_fFlags, a_pfnCImpl) return iemThreadedRecompilerMcDeferToCImpl0(pVCpu, a_pfnCImpl)
-
-typedef IEM_CIMPL_DECL_TYPE_0(FNIEMCIMPL0);
-typedef FNIEMCIMPL0 *PFNIEMCIMPL0;
-
-DECLINLINE(VBOXSTRICTRC) iemThreadedRecompilerMcDeferToCImpl0(PVMCPUCC pVCpu, PFNIEMCIMPL0 pfnCImpl)
-{
+#define IEM_MC_DEFER_TO_CIMPL_0_RET(a_fFlags, a_pfnCImpl) \
+    return iemThreadedRecompilerMcDeferToCImpl0(pVCpu, a_fFlags, a_pfnCImpl)
+
+DECLINLINE(VBOXSTRICTRC) iemThreadedRecompilerMcDeferToCImpl0(PVMCPUCC pVCpu, uint32_t fFlags, PFNIEMCIMPL0 pfnCImpl)
+{
+    Log8(("CImpl0: %04x:%08RX64 LB %#x: %#x %p\n",
+          pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip, IEM_GET_INSTR_LEN(pVCpu), fFlags, pfnCImpl));
+
+    IEM_MC2_BEGIN_EMIT_CALLS();
+    IEM_MC2_EMIT_CALL_2(kIemThreadedFunc_DeferToCImpl0, (uintptr_t)pfnCImpl, IEM_GET_INSTR_LEN(pVCpu));
+    IEM_MC2_END_EMIT_CALLS(fFlags);
+
+    /* We have to repeat work normally done by kdCImplFlags and
+       ThreadedFunctionVariation.emitThreadedCallStmts here. */
+    if (fFlags & (IEM_CIMPL_F_END_TB | IEM_CIMPL_F_MODE | IEM_CIMPL_F_VMEXIT | IEM_CIMPL_F_BRANCH_FAR | IEM_CIMPL_F_REP))
+        pVCpu->iem.s.fEndTb = true;
+
+    AssertCompile(IEM_CIMPL_F_BRANCH_DIRECT      == IEMBRANCHED_F_DIRECT);
+    AssertCompile(IEM_CIMPL_F_BRANCH_INDIRECT    == IEMBRANCHED_F_INDIRECT);
+    AssertCompile(IEM_CIMPL_F_BRANCH_RELATIVE    == IEMBRANCHED_F_RELATIVE);
+    AssertCompile(IEM_CIMPL_F_BRANCH_CONDITIONAL == IEMBRANCHED_F_CONDITIONAL);
+    AssertCompile(IEM_CIMPL_F_BRANCH_FAR         == IEMBRANCHED_F_FAR);
+    if (fFlags & IEM_CIMPL_F_BRANCH_ANY)
+        pVCpu->iem.s.fTbBranched = fFlags & (IEM_CIMPL_F_BRANCH_ANY | IEM_CIMPL_F_BRANCH_FAR | IEM_CIMPL_F_BRANCH_CONDITIONAL);
+
     return pfnCImpl(pVCpu, IEM_GET_INSTR_LEN(pVCpu));
 }
