Index: /trunk/src/VBox/VMM/VMMAll/IEMAllInstPython.py
===================================================================
--- /trunk/src/VBox/VMM/VMMAll/IEMAllInstPython.py	(revision 105852)
+++ /trunk/src/VBox/VMM/VMMAll/IEMAllInstPython.py	(revision 105853)
@@ -1873,4 +1873,14 @@
         self.asParams = asParams;
         self.oUser    = None;
+
+    def __eq__(self, oOther):
+        if self.sName != oOther.sName:
+            return False;
+        if len(self.asParams) != len(oOther.asParams):
+            return False;
+        for iParam, sMyParam in enumerate(self.asParams):
+            if sMyParam != oOther.asParams[iParam]:
+                return False;
+        return True;
 
     def renderCode(self, cchIndent = 0):
Index: /trunk/src/VBox/VMM/VMMAll/IEMAllN8vePython.py
===================================================================
--- /trunk/src/VBox/VMM/VMMAll/IEMAllN8vePython.py	(revision 105852)
+++ /trunk/src/VBox/VMM/VMMAll/IEMAllN8vePython.py	(revision 105853)
@@ -402,9 +402,11 @@
                 aoStmts[iStmt] = oStmt;
 
+                fHadEmptyElseBranch = len(oStmt.aoElseBranch) == 0;
+
                 # Check the two branches for final references. Both branches must
                 # start processing with the same dVars set, fortunately as shallow
                 # copy suffices.
                 dFreedInIfBranch   = self.__analyzeVariableLiveness(oStmt.aoIfBranch, dict(dVars), iDepth + 1);
-                dFreedInElseBranch = self.__analyzeVariableLiveness(oStmt.aoElseBranch, dVars, iDepth + 1);
+                dFreedInElseBranch = self.__analyzeVariableLiveness(oStmt.aoElseBranch, dVars,     iDepth + 1);
 
                 # Add free statements to the start of the IF-branch for variables use
@@ -434,4 +436,33 @@
                         oStmt.aoIfBranch.insert(0, oFreeStmt);
                         oStmt.aoElseBranch.insert(0, oFreeStmt);
+
+                #
+                # HACK ALERT!
+                #
+                # This is a bit backwards, but if the else branch was empty, just zap
+                # it so we don't create a bunch of unnecessary jumps as well as a
+                # potential troublesome dirty guest shadowed register flushing for the
+                # if-branch.  The IEM_MC_ENDIF code is forgiving here and will
+                # automatically free the lost variables when merging the states.
+                #
+                # (In fact this behaviour caused trouble if we moved the IEM_MC_FREE_LOCAL
+                # statements ouf of the branches and put them after the IF/ELSE blocks
+                # to try avoid the unnecessary jump troubles, as the variable would be
+                # assigned a host register and thus differ in an incompatible, cause the
+                # endif code to just free the register and variable both, with the result
+                # that the IEM_MC_FREE_LOCAL following the IF/ELSE blocks would assert
+                # since the variable was already freed.)
+                #
+                # See iemNativeRecompFunc_cmovne_Gv_Ev__greg64_nn_64 and
+                # the other cmovcc functions for examples.
+                #
+                if fHadEmptyElseBranch:
+                    oStmt.aoElseBranch = [];
+                #while (    oStmt.aoIfBranch
+                #       and oStmt.aoElseBranch
+                #       and oStmt.aoIfBranch[-1] == oStmt.aoElseBranch[-1]):
+                #    aoStmts.insert(iStmt + 1, oStmt.aoIfBranch[-1]);
+                #    del oStmt.aoIfBranch[-1];
+                #    del oStmt.aoElseBranch[-1];
 
             elif not oStmt.isCppStmt():
Index: /trunk/src/VBox/VMM/VMMAll/IEMAllN8veRecompFuncs.h
===================================================================
--- /trunk/src/VBox/VMM/VMMAll/IEMAllN8veRecompFuncs.h	(revision 105852)
+++ /trunk/src/VBox/VMM/VMMAll/IEMAllN8veRecompFuncs.h	(revision 105853)
@@ -89,5 +89,83 @@
 
 #ifdef IEMNATIVE_WITH_DELAYED_PC_UPDATING
-# if defined(IEMNATIVE_REG_FIXED_PC_DBG)
+
+# ifdef IEMNATIVE_WITH_DELAYED_PC_UPDATING_DEBUG
+/**
+ * Updates IEMCPU::uPcUpdatingDebug.
+ */
+DECL_INLINE_THROW(uint32_t) iemNativeEmitPcDebugAdd(PIEMRECOMPILERSTATE pReNative, uint32_t off, int64_t offDisp, uint8_t cBits)
+{
+# ifdef RT_ARCH_AMD64
+    if (pReNative->Core.fDebugPcInitialized && cBits >= 32)
+    {
+        PIEMNATIVEINSTR const pCodeBuf = iemNativeInstrBufEnsure(pReNative, off, 32);
+        if ((int32_t)offDisp == offDisp || cBits != 64)
+        {
+            /* add [q]word [pVCpu->iem.s.uPcUpdatingDebug], imm32/imm8 */
+            if (cBits == 64)
+                pCodeBuf[off++] = X86_OP_REX_W;
+            pCodeBuf[off++] = (int8_t)offDisp == offDisp ? 0x83 : 0x81;
+            off = iemNativeEmitGprByVCpuDisp(pCodeBuf, off, 0, RT_UOFFSETOF(VMCPU, iem.s.uPcUpdatingDebug));
+            if ((int8_t)offDisp == offDisp)
+                pCodeBuf[off++] = (int8_t)offDisp;
+            else
+            {
+                *(int32_t *)&pCodeBuf[off] = (int32_t)offDisp;
+                off += sizeof(int32_t);
+            }
+        }
+        else
+        {
+            /* mov tmp0, imm64 */
+            off = iemNativeEmitLoadGprImmEx(pCodeBuf, off, IEMNATIVE_REG_FIXED_TMP0, offDisp);
+
+            /* add [pVCpu->iem.s.uPcUpdatingDebug], tmp0 */
+            if (cBits == 64)
+                pCodeBuf[off++] = X86_OP_REX_W | (IEMNATIVE_REG_FIXED_TMP0 >= 8 ? X86_OP_REX_R : 0);
+            else if (IEMNATIVE_REG_FIXED_TMP0 >= 8)
+                pCodeBuf[off++] = X86_OP_REX_R;
+            pCodeBuf[off++] = 0x01;
+            off = iemNativeEmitGprByVCpuDisp(pCodeBuf, off, IEMNATIVE_REG_FIXED_TMP0 & 7,
+                                             RT_UOFFSETOF(VMCPU, iem.s.uPcUpdatingDebug));
+        }
+        IEMNATIVE_ASSERT_INSTR_BUF_ENSURE(pReNative, off);
+        return off;
+    }
+# endif
+
+    uint8_t const         idxTmpReg = iemNativeRegAllocTmp(pReNative, &off);
+    PIEMNATIVEINSTR const pCodeBuf  = iemNativeInstrBufEnsure(pReNative, off, RT_ARCH_VAL == RT_ARCH_VAL_AMD64 ? 32 : 12);
+
+    if (pReNative->Core.fDebugPcInitialized)
+    {
+        Log4(("uPcUpdatingDebug+=%ld cBits=%d off=%#x\n", offDisp, cBits, off));
+        off = iemNativeEmitLoadGprFromVCpuU64Ex(pCodeBuf, off, idxTmpReg, RT_UOFFSETOF(VMCPU, iem.s.uPcUpdatingDebug));
+    }
+    else
+    {
+        Log4(("uPcUpdatingDebug=rip+%ld cBits=%d off=%#x\n", offDisp, cBits, off));
+        pReNative->Core.fDebugPcInitialized = true;
+        off = iemNativeEmitLoadGprFromVCpuU64Ex(pCodeBuf, off, idxTmpReg, RT_UOFFSETOF(VMCPU, cpum.GstCtx.rip));
+    }
+
+    if (cBits == 64)
+        off = iemNativeEmitAddGprImmEx(pCodeBuf, off, idxTmpReg, offDisp, IEMNATIVE_REG_FIXED_TMP0);
+    else
+    {
+        off = iemNativeEmitAddGpr32ImmEx(pCodeBuf, off, idxTmpReg, (int32_t)offDisp, IEMNATIVE_REG_FIXED_TMP0);
+        if (cBits == 16)
+            off = iemNativeEmitAndGpr32ByImmEx(pCodeBuf, off, idxTmpReg, UINT16_MAX);
+    }
+
+    off = iemNativeEmitStoreGprToVCpuU64Ex(pCodeBuf, off, idxTmpReg, RT_UOFFSETOF(VMCPU, iem.s.uPcUpdatingDebug),
+                                           IEMNATIVE_REG_FIXED_TMP0);
+
+    IEMNATIVE_ASSERT_INSTR_BUF_ENSURE(pReNative, off);
+    iemNativeRegFreeTmp(pReNative, idxTmpReg);
+    return off;
+}
+
+
+# elif defined(IEMNATIVE_REG_FIXED_PC_DBG)
 DECL_INLINE_THROW(uint32_t) iemNativePcAdjustCheck(PIEMRECOMPILERSTATE pReNative, uint32_t off)
 {
@@ -99,4 +177,5 @@
 }
 # endif
+
 #endif /* IEMNATIVE_WITH_DELAYED_PC_UPDATING  */
 
@@ -391,13 +470,5 @@
          * can disregard its state when we hit the IEM_MC_ENDIF.
          */
-        uint8_t idxCondDepth = pReNative->cCondDepth;
-        if (idxCondDepth)
-        {
-            idxCondDepth--;
-            if (pReNative->aCondStack[idxCondDepth].fInElse)
-                pReNative->aCondStack[idxCondDepth].fElseExitTb = true;
-            else
-                pReNative->aCondStack[idxCondDepth].fIfExitTb   = true;
-        }
+        iemNativeMarkCurCondBranchAsExiting(pReNative);
 
         /*
@@ -510,11 +581,17 @@
 
     pReNative->Core.offPc += cbInstr;
-# if defined(IEMNATIVE_REG_FIXED_PC_DBG)
+    Log4(("offPc=%x cbInstr=%#x off=%#x\n", pReNative->Core.offPc, cbInstr, off));
+# ifdef IEMNATIVE_WITH_DELAYED_PC_UPDATING_DEBUG
+    off = iemNativeEmitPcDebugAdd(pReNative, off, cbInstr, 64);
+    off = iemNativeEmitPcDebugCheck(pReNative, off);
+# elif defined(IEMNATIVE_REG_FIXED_PC_DBG)
     off = iemNativePcAdjustCheck(pReNative, off);
 # endif
+
     if (pReNative->cCondDepth)
         off = iemNativeEmitPcWriteback(pReNative, off);
     else
         pReNative->Core.cInstrPcUpdateSkipped++;
+
 #endif
 
@@ -535,4 +612,56 @@
 DECL_INLINE_THROW(uint32_t)
 iemNativeEmitAddToEip32AndFinishingNoFlags(PIEMRECOMPILERSTATE pReNative, uint32_t off, uint8_t cbInstr)
+{
+#if !defined(IEMNATIVE_WITH_DELAYED_PC_UPDATING) || defined(IEMNATIVE_REG_FIXED_PC_DBG)
+# ifdef IEMNATIVE_REG_FIXED_PC_DBG
+    if (!pReNative->Core.offPc)
+        off = iemNativeEmitLoadGprFromVCpuU64(pReNative, off, IEMNATIVE_REG_FIXED_PC_DBG, RT_UOFFSETOF(VMCPU, cpum.GstCtx.rip));
+# endif
+
+    /* Allocate a temporary PC register. */
+    uint8_t const idxPcReg = iemNativeRegAllocTmpForGuestReg(pReNative, &off, kIemNativeGstReg_Pc, kIemNativeGstRegUse_ForUpdate);
+
+    /* Perform the addition and store the result. */
+    off = iemNativeEmitAddGpr32Imm8(pReNative, off, idxPcReg, cbInstr);
+    off = iemNativeEmitStoreGprToVCpuU64(pReNative, off, idxPcReg, RT_UOFFSETOF(VMCPU, cpum.GstCtx.rip));
+
+    /* Free but don't flush the PC register. */
+    iemNativeRegFreeTmp(pReNative, idxPcReg);
+#endif
+
+#ifdef IEMNATIVE_WITH_DELAYED_PC_UPDATING
+    STAM_COUNTER_INC(&pReNative->pVCpu->iem.s.StatNativePcUpdateTotal);
+
+    pReNative->Core.offPc += cbInstr;
+    Log4(("offPc=%x cbInstr=%#x off=%#x\n", pReNative->Core.offPc, cbInstr, off));
+# ifdef IEMNATIVE_WITH_DELAYED_PC_UPDATING_DEBUG
+    off = iemNativeEmitPcDebugAdd(pReNative, off, cbInstr, 32);
+    off = iemNativeEmitPcDebugCheck(pReNative, off);
+# elif defined(IEMNATIVE_REG_FIXED_PC_DBG)
+    off = iemNativePcAdjustCheck(pReNative, off);
+# endif
+
+    if (pReNative->cCondDepth)
+        off = iemNativeEmitPcWriteback(pReNative, off);
+    else
+        pReNative->Core.cInstrPcUpdateSkipped++;
+#endif
+
+    return off;
+}
+
+
+#define IEM_MC_ADVANCE_RIP_AND_FINISH_THREADED_PC16(a_cbInstr, a_rcNormal) \
+    off = iemNativeEmitAddToIp16AndFinishingNoFlags(pReNative, off, (a_cbInstr)); \
+    off = iemNativeEmitFinishInstructionWithStatus<a_rcNormal, false /*a_fIsJump*/>(pReNative, off, pCallEntry, 0)
+
+#define IEM_MC_ADVANCE_RIP_AND_FINISH_THREADED_PC16_WITH_FLAGS(a_cbInstr, a_rcNormal) \
+    off = iemNativeEmitAddToIp16AndFinishingNoFlags(pReNative, off, (a_cbInstr)); \
+    off = iemNativeEmitFinishInstructionFlagsCheck(pReNative, off); \
+    off = iemNativeEmitFinishInstructionWithStatus<a_rcNormal, false /*a_fIsJump*/>(pReNative, off, pCallEntry, 0)
+
+/** Same as iemRegAddToIp16AndFinishingNoFlags. */
+DECL_INLINE_THROW(uint32_t)
+iemNativeEmitAddToIp16AndFinishingNoFlags(PIEMRECOMPILERSTATE pReNative, uint32_t off, uint8_t cbInstr)
 {
 #if !defined(IEMNATIVE_WITH_DELAYED_PC_UPDATING) || defined(IEMNATIVE_REG_FIXED_PC_DBG)
@@ -547,4 +676,5 @@
     /* Perform the addition and store the result. */
     off = iemNativeEmitAddGpr32Imm8(pReNative, off, idxPcReg, cbInstr);
+    off = iemNativeEmitClear16UpGpr(pReNative, off, idxPcReg);
     off = iemNativeEmitStoreGprToVCpuU64(pReNative, off, idxPcReg, RT_UOFFSETOF(VMCPU, cpum.GstCtx.rip));
 
@@ -557,55 +687,12 @@
 
     pReNative->Core.offPc += cbInstr;
-# if defined(IEMNATIVE_REG_FIXED_PC_DBG)
+    Log4(("offPc=%x cbInstr=%#x off=%#x\n", pReNative->Core.offPc, cbInstr, off));
+# ifdef IEMNATIVE_WITH_DELAYED_PC_UPDATING_DEBUG
+    off = iemNativeEmitPcDebugAdd(pReNative, off, cbInstr, 16);
+    off = iemNativeEmitPcDebugCheck(pReNative, off);
+# elif defined(IEMNATIVE_REG_FIXED_PC_DBG)
     off = iemNativePcAdjustCheck(pReNative, off);
 # endif
-    if (pReNative->cCondDepth)
-        off = iemNativeEmitPcWriteback(pReNative, off);
-    else
-        pReNative->Core.cInstrPcUpdateSkipped++;
-#endif
-
-    return off;
-}
-
-
-#define IEM_MC_ADVANCE_RIP_AND_FINISH_THREADED_PC16(a_cbInstr, a_rcNormal) \
-    off = iemNativeEmitAddToIp16AndFinishingNoFlags(pReNative, off, (a_cbInstr)); \
-    off = iemNativeEmitFinishInstructionWithStatus<a_rcNormal, false /*a_fIsJump*/>(pReNative, off, pCallEntry, 0)
-
-#define IEM_MC_ADVANCE_RIP_AND_FINISH_THREADED_PC16_WITH_FLAGS(a_cbInstr, a_rcNormal) \
-    off = iemNativeEmitAddToIp16AndFinishingNoFlags(pReNative, off, (a_cbInstr)); \
-    off = iemNativeEmitFinishInstructionFlagsCheck(pReNative, off); \
-    off = iemNativeEmitFinishInstructionWithStatus<a_rcNormal, false /*a_fIsJump*/>(pReNative, off, pCallEntry, 0)
-
-/** Same as iemRegAddToIp16AndFinishingNoFlags. */
-DECL_INLINE_THROW(uint32_t)
-iemNativeEmitAddToIp16AndFinishingNoFlags(PIEMRECOMPILERSTATE pReNative, uint32_t off, uint8_t cbInstr)
-{
-#if !defined(IEMNATIVE_WITH_DELAYED_PC_UPDATING) || defined(IEMNATIVE_REG_FIXED_PC_DBG)
-# if defined(IEMNATIVE_REG_FIXED_PC_DBG)
-    if (!pReNative->Core.offPc)
-        off = iemNativeEmitLoadGprFromVCpuU64(pReNative, off, IEMNATIVE_REG_FIXED_PC_DBG, RT_UOFFSETOF(VMCPU, cpum.GstCtx.rip));
-# endif
-
-    /* Allocate a temporary PC register. */
-    uint8_t const idxPcReg = iemNativeRegAllocTmpForGuestReg(pReNative, &off, kIemNativeGstReg_Pc, kIemNativeGstRegUse_ForUpdate);
-
-    /* Perform the addition and store the result. */
-    off = iemNativeEmitAddGpr32Imm8(pReNative, off, idxPcReg, cbInstr);
-    off = iemNativeEmitClear16UpGpr(pReNative, off, idxPcReg);
-    off = iemNativeEmitStoreGprToVCpuU64(pReNative, off, idxPcReg, RT_UOFFSETOF(VMCPU, cpum.GstCtx.rip));
-
-    /* Free but don't flush the PC register. */
-    iemNativeRegFreeTmp(pReNative, idxPcReg);
-#endif
-
-#ifdef IEMNATIVE_WITH_DELAYED_PC_UPDATING
-    STAM_COUNTER_INC(&pReNative->pVCpu->iem.s.StatNativePcUpdateTotal);
-
-    pReNative->Core.offPc += cbInstr;
-# if defined(IEMNATIVE_REG_FIXED_PC_DBG)
-    off = iemNativePcAdjustCheck(pReNative, off);
-# endif
+
     if (pReNative->cCondDepth)
         off = iemNativeEmitPcWriteback(pReNative, off);
@@ -701,9 +788,9 @@
 
     /* We speculatively modify PC and may raise #GP(0), so make sure the right values are in CPUMCTX. */
+/** @todo relax this one, we won't raise \#GP when a_fWithinPage is true. */
     off = iemNativeRegFlushPendingWrites(pReNative, off);
 
 #ifdef IEMNATIVE_WITH_DELAYED_PC_UPDATING
     Assert(pReNative->Core.offPc == 0);
-
     STAM_COUNTER_INC(&pReNative->pVCpu->iem.s.StatNativePcUpdateTotal);
 #endif
@@ -728,4 +815,9 @@
         off = iemNativeEmitClear16UpGpr(pReNative, off, idxPcReg);
     }
+#ifdef IEMNATIVE_WITH_DELAYED_PC_UPDATING_DEBUG
+    off = iemNativeEmitPcDebugAdd(pReNative, off, (int64_t)offDisp + cbInstr, enmEffOpSize == IEMMODE_64BIT ? 64 : 16);
+    off = iemNativeEmitPcDebugCheckWithReg(pReNative, off, idxPcReg);
+#endif
+
     off = iemNativeEmitStoreGprToVCpuU64(pReNative, off, idxPcReg, RT_UOFFSETOF(VMCPU, cpum.GstCtx.rip));
 
@@ -819,5 +911,4 @@
 #ifdef IEMNATIVE_WITH_DELAYED_PC_UPDATING
     Assert(pReNative->Core.offPc == 0);
-
     STAM_COUNTER_INC(&pReNative->pVCpu->iem.s.StatNativePcUpdateTotal);
 #endif
@@ -836,4 +927,9 @@
     if (!a_fFlat)
         off = iemNativeEmitCheckGpr32AgainstCsSegLimitMaybeRaiseGp0(pReNative, off, idxPcReg, idxInstr);
+
+#ifdef IEMNATIVE_WITH_DELAYED_PC_UPDATING_DEBUG
+    off = iemNativeEmitPcDebugAdd(pReNative, off, offDisp + cbInstr, enmEffOpSize == IEMMODE_32BIT ? 32 : 16);
+    off = iemNativeEmitPcDebugCheckWithReg(pReNative, off, idxPcReg);
+#endif
 
     off = iemNativeEmitStoreGprToVCpuU64(pReNative, off, idxPcReg, RT_UOFFSETOF(VMCPU, cpum.GstCtx.rip));
@@ -883,5 +979,4 @@
 #ifdef IEMNATIVE_WITH_DELAYED_PC_UPDATING
     Assert(pReNative->Core.offPc == 0);
-
     STAM_COUNTER_INC(&pReNative->pVCpu->iem.s.StatNativePcUpdateTotal);
 #endif
@@ -894,4 +989,8 @@
     off = iemNativeEmitClear16UpGpr(pReNative, off, idxPcReg);
     off = iemNativeEmitCheckGpr32AgainstCsSegLimitMaybeRaiseGp0(pReNative, off, idxPcReg, idxInstr);
+#ifdef IEMNATIVE_WITH_DELAYED_PC_UPDATING_DEBUG
+    off = iemNativeEmitPcDebugAdd(pReNative, off, offDisp + cbInstr, 16);
+    off = iemNativeEmitPcDebugCheckWithReg(pReNative, off, idxPcReg);
+#endif
     off = iemNativeEmitStoreGprToVCpuU64(pReNative, off, idxPcReg, RT_UOFFSETOF(VMCPU, cpum.GstCtx.rip));
 
@@ -991,5 +1090,4 @@
 #ifdef IEMNATIVE_WITH_DELAYED_PC_UPDATING
     Assert(pReNative->Core.offPc == 0);
-
     STAM_COUNTER_INC(&pReNative->pVCpu->iem.s.StatNativePcUpdateTotal);
 #endif
@@ -1009,4 +1107,10 @@
     /* Store the result. */
     off = iemNativeEmitStoreGprToVCpuU64(pReNative, off, idxPcReg, RT_UOFFSETOF(VMCPU, cpum.GstCtx.rip));
+
+#ifdef IEMNATIVE_WITH_DELAYED_PC_UPDATING_DEBUG
+    off = iemNativeEmitStoreGprToVCpuU64(pReNative, off, idxPcReg, RT_UOFFSETOF(VMCPU, iem.s.uPcUpdatingDebug));
+    pReNative->Core.fDebugPcInitialized = true;
+    Log4(("uPcUpdatingDebug=rip off=%#x\n", off));
+#endif
 
     iemNativeVarRegisterRelease(pReNative, idxVarPc);
@@ -1401,5 +1505,4 @@
 #ifdef IEMNATIVE_WITH_DELAYED_PC_UPDATING
     Assert(pReNative->Core.offPc == 0);
-
     STAM_COUNTER_INC(&pReNative->pVCpu->iem.s.StatNativePcUpdateTotal);
 #endif
@@ -1458,4 +1561,9 @@
     /* Store the result. */
     off = iemNativeEmitStoreGprToVCpuU64(pReNative, off, idxNewPcReg, RT_UOFFSETOF(VMCPU, cpum.GstCtx.rip));
+#ifdef IEMNATIVE_WITH_DELAYED_PC_UPDATING_DEBUG
+    off = iemNativeEmitStoreGprToVCpuU64(pReNative, off, idxNewPcReg, RT_UOFFSETOF(VMCPU, iem.s.uPcUpdatingDebug));
+    pReNative->Core.fDebugPcInitialized = true;
+    Log4(("uPcUpdatingDebug=rip/indirect-call off=%#x\n", off));
+#endif
 
 #if 1
@@ -1523,5 +1631,4 @@
 #ifdef IEMNATIVE_WITH_DELAYED_PC_UPDATING
     Assert(pReNative->Core.offPc == 0);
-
     STAM_COUNTER_INC(&pReNative->pVCpu->iem.s.StatNativePcUpdateTotal);
 #endif
@@ -1554,4 +1661,9 @@
     /* Store the result. */
     off = iemNativeEmitStoreGprToVCpuU64(pReNative, off, idxPcRegNew, RT_UOFFSETOF(VMCPU, cpum.GstCtx.rip));
+#ifdef IEMNATIVE_WITH_DELAYED_PC_UPDATING_DEBUG
+    off = iemNativeEmitStoreGprToVCpuU64(pReNative, off, idxPcRegNew, RT_UOFFSETOF(VMCPU, iem.s.uPcUpdatingDebug));
+    pReNative->Core.fDebugPcInitialized = true;
+    Log4(("uPcUpdatingDebug=rip/rel-call-16 off=%#x offDisp=%d\n", off, offDisp));
+#endif
 
     /* Need to transfer the shadow information to the new RIP register. */
@@ -1589,5 +1701,4 @@
 #ifdef IEMNATIVE_WITH_DELAYED_PC_UPDATING
     Assert(pReNative->Core.offPc == 0);
-
     STAM_COUNTER_INC(&pReNative->pVCpu->iem.s.StatNativePcUpdateTotal);
 #endif
@@ -1617,4 +1728,9 @@
     /* Store the result. */
     off = iemNativeEmitStoreGprToVCpuU64(pReNative, off, idxPcRegNew, RT_UOFFSETOF(VMCPU, cpum.GstCtx.rip));
+#ifdef IEMNATIVE_WITH_DELAYED_PC_UPDATING_DEBUG
+    off = iemNativeEmitStoreGprToVCpuU64(pReNative, off, idxPcRegNew, RT_UOFFSETOF(VMCPU, iem.s.uPcUpdatingDebug));
+    pReNative->Core.fDebugPcInitialized = true;
+    Log4(("uPcUpdatingDebug=eip/rel-call-32 off=%#x offDisp=%d\n", off, offDisp));
+#endif
 
     /* Need to transfer the shadow information to the new RIP register. */
@@ -1652,5 +1768,4 @@
 #ifdef IEMNATIVE_WITH_DELAYED_PC_UPDATING
     Assert(pReNative->Core.offPc == 0);
-
     STAM_COUNTER_INC(&pReNative->pVCpu->iem.s.StatNativePcUpdateTotal);
 #endif
@@ -1678,4 +1793,9 @@
     /* Store the result. */
     off = iemNativeEmitStoreGprToVCpuU64(pReNative, off, idxPcRegNew, RT_UOFFSETOF(VMCPU, cpum.GstCtx.rip));
+#ifdef IEMNATIVE_WITH_DELAYED_PC_UPDATING_DEBUG
+    off = iemNativeEmitStoreGprToVCpuU64(pReNative, off, idxPcRegNew, RT_UOFFSETOF(VMCPU, iem.s.uPcUpdatingDebug));
+    pReNative->Core.fDebugPcInitialized = true;
+    Log4(("uPcUpdatingDebug=rip/rel-call-64 off=%#x offDisp=%ld\n", off, offDisp));
+#endif
 
     /* Need to transfer the shadow information to the new RIP register. */
@@ -1702,4 +1822,5 @@
     off = iemNativeEmitAddGpr16ImmEx(pCodeBuf, off, idxRegRsp, cbPopAdd); /* ASSUMES this does NOT modify bits [63:16]! */
     RT_NOREF(idxRegTmp);
+
 #elif defined(RT_ARCH_ARM64)
     /* ubfiz regeff, regrsp, #0, #16 - copies bits 15:0 from RSP to EffSp bits 15:0, zeroing bits 63:16. */
@@ -1716,4 +1837,5 @@
     /* bfi regrsp, regeff, #0, #16 - moves bits 15:0 from tmp to RSP bits 15:0, keeping the other RSP bits as is. */
     pCodeBuf[off++] = Armv8A64MkInstrBfi(idxRegRsp, idxRegTmp, 0, 16, false /*f64Bit*/);
+
 #else
 # error "Port me"
@@ -1998,7 +2120,12 @@
 
     /* Commit the result and clear any current guest shadows for RIP. */
-    off = iemNativeEmitStoreGprToVCpuU64(pReNative, off, idxRegRsp, RT_UOFFSETOF(VMCPU, cpum.GstCtx.rsp));
+    off = iemNativeEmitStoreGprToVCpuU64(pReNative, off, idxRegRsp,       RT_UOFFSETOF(VMCPU, cpum.GstCtx.rsp));
     off = iemNativeEmitStoreGprToVCpuU64(pReNative, off, idxRegMemResult, RT_UOFFSETOF(VMCPU, cpum.GstCtx.rip));
-    iemNativeRegClearAndMarkAsGstRegShadow(pReNative, idxRegMemResult,  kIemNativeGstReg_Pc, off);
+    iemNativeRegClearAndMarkAsGstRegShadow(pReNative, idxRegMemResult, kIemNativeGstReg_Pc, off);
+#ifdef IEMNATIVE_WITH_DELAYED_PC_UPDATING_DEBUG
+    off = iemNativeEmitStoreGprToVCpuU64(pReNative, off, idxRegMemResult, RT_UOFFSETOF(VMCPU, iem.s.uPcUpdatingDebug));
+    pReNative->Core.fDebugPcInitialized = true;
+    Log4(("uPcUpdatingDebug=rip/ret off=%#x\n", off));
+#endif
 
     /* Need to transfer the shadowing information to the host register containing the updated value now. */
@@ -2464,10 +2591,6 @@
  *          (too many nestings)
  */
-DECL_INLINE_THROW(PIEMNATIVECOND) iemNativeCondPushIf(PIEMRECOMPILERSTATE pReNative, uint32_t *poff)
-{
-#ifdef IEMNATIVE_WITH_DELAYED_PC_UPDATING
-    *poff = iemNativeRegFlushPendingWrites(pReNative, *poff);
-#endif
-
+DECL_INLINE_THROW(PIEMNATIVECOND) iemNativeCondPushIf(PIEMRECOMPILERSTATE pReNative)
+{
     uint32_t const idxStack = pReNative->cCondDepth;
     AssertStmt(idxStack < RT_ELEMENTS(pReNative->aCondStack), IEMNATIVE_DO_LONGJMP(pReNative, VERR_IEM_COND_TOO_DEEPLY_NESTED));
@@ -2508,8 +2631,4 @@
 #endif
 
-#ifdef IEMNATIVE_WITH_DELAYED_PC_UPDATING
-    Assert(pReNative->Core.offPc == 0);
-#endif
-
     /* Copy the initial state so we can restore it in the 'else' block. */
     pEntry->InitialState = pReNative->Core;
@@ -2530,22 +2649,27 @@
     Assert(!pEntry->fInElse);
 
-#ifdef IEMNATIVE_WITH_DELAYED_REGISTER_WRITEBACK
-    /* Writeback any dirty shadow registers. */
-    /** @todo r=aeichner Possible optimization is to only writeback guest registers which became dirty
-     *                   in one of the branches and leave guest registers already dirty before the start of the if
-     *                   block alone. */
-    off = iemNativeRegFlushDirtyGuest(pReNative, off);
-#endif
-
-    /* Jump to the endif */
-    off = iemNativeEmitJmpToLabel(pReNative, off, pEntry->idxLabelEndIf);
+    /* We can skip dirty register flushing and the dirty register flushing if
+       the branch already jumped to a TB exit. */
+    if (!pEntry->fIfExitTb)
+    {
+#if defined(IEMNATIVE_WITH_DELAYED_REGISTER_WRITEBACK) && 0
+        /* Writeback any dirty shadow registers. */
+        /** @todo r=aeichner Possible optimization is to only writeback guest registers which became dirty
+         *                   in one of the branches and leave guest registers already dirty before the start of the if
+         *                   block alone. */
+        off = iemNativeRegFlushDirtyGuest(pReNative, off);
+#endif
+
+        /* Jump to the endif. */
+        off = iemNativeEmitJmpToLabel(pReNative, off, pEntry->idxLabelEndIf);
+    }
+# ifdef IEMNATIVE_WITH_DELAYED_PC_UPDATING
+    else
+        Assert(pReNative->Core.offPc == 0);
+# endif
 
     /* Define the else label and enter the else part of the condition. */
     iemNativeLabelDefine(pReNative, pEntry->idxLabelElse, off);
     pEntry->fInElse = true;
-
-#ifdef IEMNATIVE_WITH_DELAYED_PC_UPDATING
-    Assert(pReNative->Core.offPc == 0);
-#endif
 
     /* Snapshot the core state so we can do a merge at the endif and restore
@@ -2568,6 +2692,7 @@
     Assert(pReNative->cCondDepth > 0 && pReNative->cCondDepth <= RT_ELEMENTS(pReNative->aCondStack));
     PIEMNATIVECOND const pEntry = &pReNative->aCondStack[pReNative->cCondDepth - 1];
-#ifdef IEMNATIVE_WITH_DELAYED_PC_UPDATING
-    Assert(pReNative->Core.offPc == 0);
+
+#if defined(IEMNATIVE_WITH_DELAYED_PC_UPDATING) && 0
+    off = iemNativeRegFlushDirtyGuest(pReNative, off);
 #endif
 
@@ -2576,4 +2701,5 @@
      * other branch and skip all the merging headache.
      */
+    bool fDefinedLabels = false;
     if (pEntry->fElseExitTb || pEntry->fIfExitTb)
     {
@@ -2600,12 +2726,4 @@
     else
     {
-#ifdef IEMNATIVE_WITH_DELAYED_REGISTER_WRITEBACK
-        /* Writeback any dirty shadow registers (else branch). */
-        /** @todo r=aeichner Possible optimization is to only writeback guest registers which became dirty
-         *                   in one of the branches and leave guest registers already dirty before the start of the if
-         *                   block alone. */
-        off = iemNativeRegFlushDirtyGuest(pReNative, off);
-#endif
-
         /*
          * Now we have find common group with the core state at the end of the
@@ -2617,12 +2735,43 @@
          *        But we'd need more info about future for that to be worth the effort. */
         PCIEMNATIVECORESTATE const pOther = pEntry->fInElse ? &pEntry->IfFinalState : &pEntry->InitialState;
-#ifdef IEMNATIVE_WITH_DELAYED_REGISTER_WRITEBACK
-        Assert(   pOther->bmGstRegShadowDirty == 0
-               && pReNative->Core.bmGstRegShadowDirty == 0);
+#ifdef IEMNATIVE_WITH_DELAYED_PC_UPDATING
+        AssertMsgStmt(pReNative->Core.offPc == pOther->offPc,
+                      ("Core.offPc=%#x pOther->offPc=%#x\n", pReNative->Core.offPc, pOther->offPc),
+                      IEMNATIVE_DO_LONGJMP(pReNative, VERR_IEM_COND_ENDIF_RECONCILIATION_FAILED));
 #endif
 
         if (memcmp(&pReNative->Core, pOther, sizeof(*pOther)) != 0)
         {
-            /* shadow guest stuff first. */
+#ifdef IEMNATIVE_WITH_DELAYED_REGISTER_WRITEBACK
+            /*
+             * If the branch has differences in dirty shadow registers, we will flush
+             * the register only dirty in the current branch and dirty any that's only
+             * dirty in the other one.
+             */
+            uint64_t const fGstRegDirtyOther = pOther->bmGstRegShadowDirty;
+            uint64_t const fGstRegDirtyThis  = pReNative->Core.bmGstRegShadowDirty;
+            uint64_t const fGstRegDirtyDiff  = fGstRegDirtyOther ^ fGstRegDirtyThis;
+            uint64_t const fGstRegDirtyHead  = fGstRegDirtyThis  & fGstRegDirtyDiff;
+            uint64_t       fGstRegDirtyTail  = fGstRegDirtyOther & fGstRegDirtyDiff;
+            if (!fGstRegDirtyDiff)
+            { /* likely */ }
+            else
+            {
+                //uint64_t const fGstRegDirtyHead = pReNative->Core.bmGstRegShadowDirty & fGstRegDirtyDiff;
+                if (fGstRegDirtyHead)
+                {
+                    Log12(("iemNativeEmitEndIf: flushing dirty guest registers in current branch: %RX64\n", fGstRegDirtyHead));
+                    off = iemNativeRegFlushDirtyGuest(pReNative, off, fGstRegDirtyHead);
+                }
+            }
+#endif
+
+            /*
+             * Shadowed guest registers.
+             *
+             * We drop any shadows where the two states disagree about where
+             * things are kept.  We may end up flushing dirty more registers
+             * here, if the two branches keeps things in different registers.
+             */
             uint64_t fGstRegs = pReNative->Core.bmGstRegShadows;
             if (fGstRegs)
@@ -2634,31 +2783,85 @@
                     fGstRegs &= ~RT_BIT_64(idxGstReg);
 
-                    uint8_t const idxHstReg = pReNative->Core.aidxGstRegShadows[idxGstReg];
-                    if (  !(pOther->bmGstRegShadows & RT_BIT_64(idxGstReg))
-                        || idxHstReg != pOther->aidxGstRegShadows[idxGstReg])
+                    uint8_t const idxCurHstReg   = pReNative->Core.aidxGstRegShadows[idxGstReg];
+                    uint8_t const idxOtherHstReg = pOther->aidxGstRegShadows[idxGstReg];
+                    if (   idxCurHstReg != idxOtherHstReg
+                        || !(pOther->bmGstRegShadows & RT_BIT_64(idxGstReg)))
                     {
-                        Log12(("iemNativeEmitEndIf: dropping gst %s from hst %s\n",
-                               g_aGstShadowInfo[idxGstReg].pszName, g_apszIemNativeHstRegNames[idxHstReg]));
-
-#ifdef IEMNATIVE_WITH_DELAYED_REGISTER_WRITEBACK
-                        /* Writeback any dirty shadow registers we are about to unshadow. */
-                        off = iemNativeRegFlushDirtyGuestByHostRegShadow(pReNative, off, idxHstReg);
-#endif
-                        iemNativeRegClearGstRegShadowing(pReNative, idxHstReg, off);
+#ifndef IEMNATIVE_WITH_DELAYED_REGISTER_WRITEBACK
+                        Log12(("iemNativeEmitEndIf: dropping gst %s (%d) from hst %s (other %d/%#RX64)\n",
+                               g_aGstShadowInfo[idxGstReg].pszName, idxGstReg, g_apszIemNativeHstRegNames[idxCurHstReg],
+                               idxOtherHstReg, pOther->bmGstRegShadows));
+#else
+                        Log12(("iemNativeEmitEndIf: dropping %s gst %s (%d) from hst %s (other %d/%#RX64/%s)\n",
+                               pReNative->Core.bmGstRegShadowDirty & RT_BIT_64(idxGstReg) ? "_dirty_" : "clean",
+                               g_aGstShadowInfo[idxGstReg].pszName, idxGstReg, g_apszIemNativeHstRegNames[idxCurHstReg],
+                               idxOtherHstReg, pOther->bmGstRegShadows,
+                               pOther->bmGstRegShadowDirty & RT_BIT_64(idxGstReg) ? "dirty" : "clean"));
+                        if (pOther->bmGstRegShadowDirty & RT_BIT_64(idxGstReg))
+                            fGstRegDirtyTail |= RT_BIT_64(idxGstReg);
+                        if (pReNative->Core.bmGstRegShadowDirty & RT_BIT_64(idxGstReg))
+                            off = iemNativeRegFlushPendingWrite(pReNative, off, (IEMNATIVEGSTREG)idxGstReg);
+#endif
+                        iemNativeRegClearGstRegShadowingOne(pReNative, idxCurHstReg, (IEMNATIVEGSTREG)idxGstReg, off);
                     }
                 } while (fGstRegs);
             }
             else
+                Assert(pReNative->Core.bmHstRegsWithGstShadow == 0);
+
+#ifdef IEMNATIVE_WITH_DELAYED_REGISTER_WRITEBACK
+            /*
+             * Generate jumpy code for flushing dirty registers from the other
+             * branch that aren't dirty in the current one.
+             */
+            if (!fGstRegDirtyTail)
+            { /* likely */ }
+            else
             {
-                Assert(pReNative->Core.bmHstRegsWithGstShadow == 0);
-#ifdef IEMNATIVE_WITH_DELAYED_REGISTER_WRITEBACK
-                Assert(pReNative->Core.bmGstRegShadowDirty == 0);
-#endif
+                STAM_REL_COUNTER_INC(&pReNative->pVCpu->iem.s.StatNativeEndIfOtherBranchDirty);
+                Log12(("iemNativeEmitEndIf: Dirty register only in the other branch: %#RX64 - BAD!\n", fGstRegDirtyTail));
+
+                /* First the current branch has to jump over the dirty flushing from the other branch. */
+                uint32_t const offFixup1 = off;
+                off = iemNativeEmitJmpToFixed(pReNative, off, off + 10);
+
+                /* Put the endif and maybe else label here so the other branch ends up here. */
+                if (!pEntry->fInElse)
+                    iemNativeLabelDefine(pReNative, pEntry->idxLabelElse, off);
+                else
+                    Assert(pReNative->paLabels[pEntry->idxLabelElse].off <= off);
+                iemNativeLabelDefine(pReNative, pEntry->idxLabelEndIf, off);
+                fDefinedLabels = true;
+
+                /* Flush the dirty guest registers from the other branch. */
+                while (fGstRegDirtyTail)
+                {
+                    unsigned idxGstReg = ASMBitFirstSetU64(fGstRegDirtyTail) - 1;
+                    fGstRegDirtyTail &= ~RT_BIT_64(idxGstReg);
+                    Log12(("iemNativeEmitEndIf: tail flushing %s (%d) from other branch %d (cur %d/%#RX64)\n",
+                           g_aGstShadowInfo[idxGstReg].pszName, idxGstReg, pOther->aidxGstRegShadows[idxGstReg],
+                           pReNative->Core.aidxGstRegShadows[idxGstReg], pReNative->Core.bmGstRegShadows));
+
+                    off = iemNativeRegFlushPendingWriteEx(pReNative, off, (PIEMNATIVECORESTATE)pOther, (IEMNATIVEGSTREG)idxGstReg);
+
+                    /* Mismatching shadowing should've been dropped in the previous step already. */
+                    Assert(   !(pReNative->Core.bmGstRegShadows & RT_BIT_64(idxGstReg))
+                           || pReNative->Core.aidxGstRegShadows[idxGstReg] == pOther->aidxGstRegShadows[idxGstReg]);
+                }
+
+                /* Here is the actual endif label, fixup the above jump to land here. */
+                iemNativeFixupFixedJump(pReNative, offFixup1, off);
             }
-
-            /* Check variables next. For now we must require them to be identical
-               or stuff we can recreate. */
+#endif
+
+            /*
+             * Check variables next. For now we must require them to be identical
+             * or stuff we can recreate. (No code is emitted here.)
+             */
             Assert(pReNative->Core.u64ArgVars == pOther->u64ArgVars);
-            uint32_t fVars = pReNative->Core.bmVars | pOther->bmVars;
+#ifdef VBOX_STRICT
+            uint32_t const offAssert = off;
+#endif
+            uint32_t       fVars     = pReNative->Core.bmVars | pOther->bmVars;
             if (fVars)
             {
@@ -2702,7 +2905,10 @@
                 } while (fVars);
             }
-
-            /* Finally, check that the host register allocations matches. */
-            AssertMsgStmt(pReNative->Core.bmHstRegs == pOther->bmHstRegs,
+            Assert(off == offAssert);
+
+            /*
+             * Finally, check that the host register allocations matches.
+             */
+            AssertMsgStmt((pReNative->Core.bmHstRegs & (pReNative->Core.bmHstRegs ^ pOther->bmHstRegs)) == 0,
                           ("Core.bmHstRegs=%#x pOther->bmHstRegs=%#x - %#x\n",
                            pReNative->Core.bmHstRegs, pOther->bmHstRegs, pReNative->Core.bmHstRegs ^ pOther->bmHstRegs),
@@ -2714,9 +2920,12 @@
      * Define the endif label and maybe the else one if we're still in the 'if' part.
      */
-    if (!pEntry->fInElse)
-        iemNativeLabelDefine(pReNative, pEntry->idxLabelElse, off);
-    else
-        Assert(pReNative->paLabels[pEntry->idxLabelElse].off <= off);
-    iemNativeLabelDefine(pReNative, pEntry->idxLabelEndIf, off);
+    if (!fDefinedLabels)
+    {
+        if (!pEntry->fInElse)
+            iemNativeLabelDefine(pReNative, pEntry->idxLabelElse, off);
+        else
+            Assert(pReNative->paLabels[pEntry->idxLabelElse].off <= off);
+        iemNativeLabelDefine(pReNative, pEntry->idxLabelEndIf, off);
+    }
 
     /* Pop the conditional stack.*/
@@ -2735,5 +2944,5 @@
 {
     IEMNATIVE_STRICT_EFLAGS_SKIPPING_EMIT_CHECK(pReNative, off, fBitsInEfl);
-    PIEMNATIVECOND const pEntry = iemNativeCondPushIf(pReNative, &off);
+    PIEMNATIVECOND const pEntry = iemNativeCondPushIf(pReNative);
 
     /* Get the eflags. */
@@ -2762,5 +2971,5 @@
 {
     IEMNATIVE_STRICT_EFLAGS_SKIPPING_EMIT_CHECK(pReNative, off, fBitsInEfl);
-    PIEMNATIVECOND const pEntry = iemNativeCondPushIf(pReNative, &off);
+    PIEMNATIVECOND const pEntry = iemNativeCondPushIf(pReNative);
 
     /* Get the eflags. */
@@ -2789,5 +2998,5 @@
 {
     IEMNATIVE_STRICT_EFLAGS_SKIPPING_EMIT_CHECK(pReNative, off, fBitInEfl);
-    PIEMNATIVECOND const pEntry = iemNativeCondPushIf(pReNative, &off);
+    PIEMNATIVECOND const pEntry = iemNativeCondPushIf(pReNative);
 
     /* Get the eflags. */
@@ -2819,5 +3028,5 @@
 {
     IEMNATIVE_STRICT_EFLAGS_SKIPPING_EMIT_CHECK(pReNative, off, fBitInEfl);
-    PIEMNATIVECOND const pEntry = iemNativeCondPushIf(pReNative, &off);
+    PIEMNATIVECOND const pEntry = iemNativeCondPushIf(pReNative);
 
     /* Get the eflags. */
@@ -2855,5 +3064,5 @@
 {
     IEMNATIVE_STRICT_EFLAGS_SKIPPING_EMIT_CHECK(pReNative, off, fBit1InEfl | fBit2InEfl);
-    PIEMNATIVECOND const pEntry = iemNativeCondPushIf(pReNative, &off);
+    PIEMNATIVECOND const pEntry = iemNativeCondPushIf(pReNative);
 
     /* Get the eflags. */
@@ -2929,5 +3138,5 @@
 {
     IEMNATIVE_STRICT_EFLAGS_SKIPPING_EMIT_CHECK(pReNative, off, fBitInEfl | fBit1InEfl | fBit2InEfl);
-    PIEMNATIVECOND const pEntry = iemNativeCondPushIf(pReNative, &off);
+    PIEMNATIVECOND const pEntry = iemNativeCondPushIf(pReNative);
 
     /* We need an if-block label for the non-inverted variant. */
@@ -3015,5 +3224,5 @@
 DECL_INLINE_THROW(uint32_t) iemNativeEmitIfCxIsNotZero(PIEMRECOMPILERSTATE pReNative, uint32_t off)
 {
-    PIEMNATIVECOND const pEntry = iemNativeCondPushIf(pReNative, &off);
+    PIEMNATIVECOND const pEntry = iemNativeCondPushIf(pReNative);
 
     uint8_t const idxGstRcxReg = iemNativeRegAllocTmpForGuestReg(pReNative, &off, IEMNATIVEGSTREG_GPR(X86_GREG_xCX),
@@ -3038,5 +3247,5 @@
 DECL_INLINE_THROW(uint32_t) iemNativeEmitIfRcxEcxIsNotZero(PIEMRECOMPILERSTATE pReNative, uint32_t off, bool f64Bit)
 {
-    PIEMNATIVECOND const pEntry = iemNativeCondPushIf(pReNative, &off);
+    PIEMNATIVECOND const pEntry = iemNativeCondPushIf(pReNative);
 
     uint8_t const idxGstRcxReg = iemNativeRegAllocTmpForGuestReg(pReNative, &off, IEMNATIVEGSTREG_GPR(X86_GREG_xCX),
@@ -3057,5 +3266,5 @@
 DECL_INLINE_THROW(uint32_t) iemNativeEmitIfCxIsNotOne(PIEMRECOMPILERSTATE pReNative, uint32_t off)
 {
-    PIEMNATIVECOND const pEntry = iemNativeCondPushIf(pReNative, &off);
+    PIEMNATIVECOND const pEntry = iemNativeCondPushIf(pReNative);
 
     uint8_t const idxGstRcxReg = iemNativeRegAllocTmpForGuestReg(pReNative, &off, IEMNATIVEGSTREG_GPR(X86_GREG_xCX),
@@ -3086,5 +3295,5 @@
 DECL_INLINE_THROW(uint32_t) iemNativeEmitIfRcxEcxIsNotOne(PIEMRECOMPILERSTATE pReNative, uint32_t off, bool f64Bit)
 {
-    PIEMNATIVECOND const pEntry = iemNativeCondPushIf(pReNative, &off);
+    PIEMNATIVECOND const pEntry = iemNativeCondPushIf(pReNative);
 
     uint8_t const idxGstRcxReg = iemNativeRegAllocTmpForGuestReg(pReNative, &off, IEMNATIVEGSTREG_GPR(X86_GREG_xCX),
@@ -3115,5 +3324,5 @@
 {
     IEMNATIVE_STRICT_EFLAGS_SKIPPING_EMIT_CHECK(pReNative, off, fBitInEfl);
-    PIEMNATIVECOND const pEntry = iemNativeCondPushIf(pReNative, &off);
+    PIEMNATIVECOND const pEntry = iemNativeCondPushIf(pReNative);
 
     /* We have to load both RCX and EFLAGS before we can start branching,
@@ -3177,5 +3386,5 @@
 {
     IEMNATIVE_STRICT_EFLAGS_SKIPPING_EMIT_CHECK(pReNative, off, fBitInEfl);
-    PIEMNATIVECOND const pEntry = iemNativeCondPushIf(pReNative, &off);
+    PIEMNATIVECOND const pEntry = iemNativeCondPushIf(pReNative);
 
     /* We have to load both RCX and EFLAGS before we can start branching,
@@ -3219,5 +3428,5 @@
 iemNativeEmitIfLocalIsZ(PIEMRECOMPILERSTATE pReNative, uint32_t off, uint8_t idxVarLocal)
 {
-    PIEMNATIVECOND const pEntry = iemNativeCondPushIf(pReNative, &off);
+    PIEMNATIVECOND const pEntry = iemNativeCondPushIf(pReNative);
 
     IEMNATIVE_ASSERT_VAR_IDX(pReNative, idxVarLocal);
@@ -3245,5 +3454,5 @@
 iemNativeEmitIfGregBitSet(PIEMRECOMPILERSTATE pReNative, uint32_t off, uint8_t iGReg, uint8_t iBitNo)
 {
-    PIEMNATIVECOND const pEntry = iemNativeCondPushIf(pReNative, &off);
+    PIEMNATIVECOND const pEntry = iemNativeCondPushIf(pReNative);
     Assert(iGReg < 16);
 
@@ -3527,4 +3736,9 @@
         fGstShwFlush |= RT_BIT_64(kIemNativeGstReg_EFlags);
     iemNativeRegFlushGuestShadows(pReNative, fGstShwFlush);
+
+#ifdef IEMNATIVE_WITH_DELAYED_PC_UPDATING_DEBUG
+    pReNative->Core.fDebugPcInitialized = false;
+    Log4(("fDebugPcInitialized=false cimpl off=%#x (v1)\n", off));
+#endif
 
     return iemNativeEmitCheckCallRetAndPassUp(pReNative, off, idxInstr);
@@ -6703,9 +6917,14 @@
          */
         /* Allocate a temporary PC register. */
-        uint8_t const idxPcReg = iemNativeRegAllocTmpForGuestReg(pReNative, &off, kIemNativeGstReg_Pc, kIemNativeGstRegUse_ForUpdate);
+/** @todo r=bird: This would technically need to be done up front as it's a register allocation. */
+        uint8_t const idxPcReg = iemNativeRegAllocTmpForGuestReg(pReNative, &off, kIemNativeGstReg_Pc,
+                                                                 kIemNativeGstRegUse_ForUpdate);
 
         /* Perform the addition and store the result. */
         off = iemNativeEmitAddGprImm(pReNative, off, idxPcReg, pReNative->Core.offPc);
         off = iemNativeEmitStoreGprToVCpuU64(pReNative, off, idxPcReg, RT_UOFFSETOF(VMCPU, cpum.GstCtx.rip));
+# ifdef IEMNATIVE_WITH_DELAYED_PC_UPDATING_DEBUG
+        off = iemNativeEmitPcDebugCheckWithReg(pReNative, off, idxPcReg);
+# endif
 
         /* Free and flush the PC register. */
Index: /trunk/src/VBox/VMM/VMMAll/IEMAllN8veRecompiler.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMAll/IEMAllN8veRecompiler.cpp	(revision 105852)
+++ /trunk/src/VBox/VMM/VMMAll/IEMAllN8veRecompiler.cpp	(revision 105853)
@@ -8,5 +8,5 @@
  *      - Level 2  (Log2) : Details calls as they're recompiled.
  *      - Level 3  (Log3) : Disassemble native code after recompiling.
- *      - Level 4  (Log4) : ...
+ *      - Level 4  (Log4) : Delayed PC updating.
  *      - Level 5  (Log5) : ...
  *      - Level 6  (Log6) : ...
@@ -2072,4 +2072,7 @@
     pReNative->Core.offPc                  = 0;
     pReNative->Core.cInstrPcUpdateSkipped  = 0;
+# ifdef IEMNATIVE_WITH_DELAYED_PC_UPDATING_DEBUG
+    pReNative->Core.fDebugPcInitialized    = false;
+# endif
 #endif
 #ifdef IEMNATIVE_WITH_SIMD_REG_ALLOCATOR
@@ -2977,6 +2980,6 @@
 #endif /* unused */
 
-
 #ifdef IEMNATIVE_WITH_DELAYED_REGISTER_WRITEBACK
+
 /**
  * Stores the host reg @a idxHstReg into guest shadow register @a enmGstReg.
@@ -3002,8 +3005,8 @@
         case sizeof(uint16_t):
             return iemNativeEmitStoreGprToVCpuU16(pReNative, off, idxHstReg, g_aGstShadowInfo[enmGstReg].off);
-#if 0 /* not present in the table. */
+# if 0 /* not present in the table. */
         case sizeof(uint8_t):
             return iemNativeEmitStoreGprToVCpuU8(pReNative, off, idxHstReg, g_aGstShadowInfo[enmGstReg].off);
-#endif
+# endif
         default:
             AssertFailedStmt(IEMNATIVE_DO_LONGJMP(pReNative, VERR_IPE_NOT_REACHED_DEFAULT_CASE));
@@ -3013,5 +3016,35 @@
 
 /**
- * Emits code to flush a pending write of the given guest register if any.
+ * Emits code to flush a pending write of the given guest register,
+ * version with alternative core state.
+ *
+ * @returns New code buffer offset.
+ * @param   pReNative       The native recompile state.
+ * @param   off             Current code buffer position.
+ * @param   pCore           Alternative core state.
+ * @param   enmGstReg       The guest register to flush.
+ */
+DECL_HIDDEN_THROW(uint32_t)
+iemNativeRegFlushPendingWriteEx(PIEMRECOMPILERSTATE pReNative, uint32_t off, PIEMNATIVECORESTATE pCore, IEMNATIVEGSTREG enmGstReg)
+{
+    uint8_t const idxHstReg = pCore->aidxGstRegShadows[enmGstReg];
+
+    Assert(   (   enmGstReg >= kIemNativeGstReg_GprFirst
+               && enmGstReg <= kIemNativeGstReg_GprLast)
+           || enmGstReg == kIemNativeGstReg_MxCsr);
+    Assert(   idxHstReg != UINT8_MAX
+           && pCore->bmGstRegShadowDirty & RT_BIT_64(enmGstReg));
+    Log12(("iemNativeRegFlushPendingWriteEx: Clearing guest register %s shadowed by host %s (off=%#x)\n",
+           g_aGstShadowInfo[enmGstReg].pszName, g_apszIemNativeHstRegNames[idxHstReg], off));
+
+    off = iemNativeEmitStoreGprWithGstShadowReg(pReNative, off, enmGstReg, idxHstReg);
+
+    pCore->bmGstRegShadowDirty &= ~RT_BIT_64(enmGstReg);
+    return off;
+}
+
+
+/**
+ * Emits code to flush a pending write of the given guest register.
  *
  * @returns New code buffer offset.
@@ -3091,8 +3124,4 @@
         iemNativeDbgInfoAddGuestRegWriteback(pReNative, false /*fSimdReg*/, pReNative->Core.bmGstRegShadowDirty & fGstRegShadows);
 # endif
-        /** @todo r=bird: This is a crap way of enumerating a bitmask where we're
-         *        likely to only have a single bit set. It'll be in the 0..15 range,
-         *        but still it's 15 unnecessary loops for the last guest register.  */
-
         uint64_t bmGstRegShadowDirty = pReNative->Core.bmGstRegShadowDirty & fGstRegShadows;
         do
@@ -3107,5 +3136,6 @@
     return off;
 }
-#endif
+
+#endif /* IEMNATIVE_WITH_DELAYED_REGISTER_WRITEBACK */
 
 
@@ -5667,6 +5697,64 @@
 }
 
-
 #ifdef IEMNATIVE_WITH_DELAYED_PC_UPDATING
+
+# ifdef IEMNATIVE_WITH_DELAYED_PC_UPDATING_DEBUG
+
+/**
+ * Checks if the value in @a idxPcReg matches IEMCPU::uPcUpdatingDebug.
+ */
+DECL_HIDDEN_THROW(uint32_t) iemNativeEmitPcDebugCheckWithReg(PIEMRECOMPILERSTATE pReNative, uint32_t off, uint8_t idxPcReg)
+{
+    Assert(idxPcReg != IEMNATIVE_REG_FIXED_TMP0);
+    Assert(pReNative->Core.fDebugPcInitialized);
+
+    /* cmp [pVCpu->iem.s.uPcUpdatingDebug], pcreg */
+#  ifdef RT_ARCH_AMD64
+    PIEMNATIVEINSTR const pCodeBuf = iemNativeInstrBufEnsure(pReNative, off, 32);
+    pCodeBuf[off++] = X86_OP_REX_W | (idxPcReg >= 8 ? X86_OP_REX_R : 0);
+    pCodeBuf[off++] = 0x3b;
+    off = iemNativeEmitGprByVCpuDisp(pCodeBuf, off, idxPcReg & 7, RT_UOFFSETOF(VMCPU, iem.s.uPcUpdatingDebug));
+#  else
+    PIEMNATIVEINSTR const pCodeBuf = iemNativeInstrBufEnsure(pReNative, off, 8);
+    off = iemNativeEmitLoadGprFromVCpuU64Ex(pCodeBuf, off, IEMNATIVE_REG_FIXED_TMP0, RT_UOFFSETOF(VMCPU, iem.s.uPcUpdatingDebug));
+    off = iemNativeEmitCmpGprWithGprEx(pCodeBuf, off, IEMNATIVE_REG_FIXED_TMP0, idxPcReg);
+#  endif
+
+    uint32_t offFixup = off;
+    off = iemNativeEmitJccToFixedEx(pCodeBuf, off, off + 1, kIemNativeInstrCond_e);
+    off = iemNativeEmitBrkEx(pCodeBuf, off, UINT32_C(0x2200));
+    iemNativeFixupFixedJump(pReNative, offFixup, off);
+
+    IEMNATIVE_ASSERT_INSTR_BUF_ENSURE(pReNative, off);
+    return off;
+}
+
+
+/**
+ * Checks that the current RIP+offPc matches IEMCPU::uPcUpdatingDebug.
+ */
+DECL_HIDDEN_THROW(uint32_t) iemNativeEmitPcDebugCheck(PIEMRECOMPILERSTATE pReNative, uint32_t off)
+{
+    if (pReNative->Core.fDebugPcInitialized)
+    {
+        uint8_t const idxPcReg  = iemNativeRegAllocTmpForGuestReg(pReNative, &off, kIemNativeGstReg_Pc);
+        if (pReNative->Core.offPc)
+        {
+            uint8_t const         idxTmpReg = iemNativeRegAllocTmp(pReNative, &off);
+            PIEMNATIVEINSTR const pCodeBuf  = iemNativeInstrBufEnsure(pReNative, off, RT_ARCH_VAL == RT_ARCH_VAL_AMD64 ? 32 : 8);
+            off = iemNativeEmitGprEqGprPlusImmEx(pCodeBuf, off, idxTmpReg, idxPcReg, pReNative->Core.offPc);
+            IEMNATIVE_ASSERT_INSTR_BUF_ENSURE(pReNative, off);
+            off = iemNativeEmitPcDebugCheckWithReg(pReNative, off, idxTmpReg);
+            iemNativeRegFreeTmp(pReNative, idxTmpReg);
+        }
+        else
+            off = iemNativeEmitPcDebugCheckWithReg(pReNative, off, idxPcReg);
+        iemNativeRegFreeTmp(pReNative, idxPcReg);
+    }
+    return off;
+}
+
+# endif /* IEMNATIVE_WITH_DELAYED_PC_UPDATING_DEBUG */
+
 /**
  * Emits code to update the guest RIP value by adding the current offset since the start of the last RIP update.
@@ -5675,4 +5763,5 @@
 {
     Assert(pReNative->Core.offPc);
+    Log4(("offPc=%#x -> 0; off=%#x\n", pReNative->Core.offPc, off));
 # ifdef IEMNATIVE_WITH_TB_DEBUG_INFO
     iemNativeDbgInfoAddNativeOffset(pReNative, off);
@@ -5687,4 +5776,7 @@
     off = iemNativeEmitAddGprImm(pReNative, off, idxPcReg, pReNative->Core.offPc);
     off = iemNativeEmitStoreGprToVCpuU64(pReNative, off, idxPcReg, RT_UOFFSETOF(VMCPU, cpum.GstCtx.rip));
+# ifdef IEMNATIVE_WITH_DELAYED_PC_UPDATING_DEBUG
+    off = iemNativeEmitPcDebugCheckWithReg(pReNative, off, idxPcReg);
+# endif
 
     /* Free but don't flush the PC register. */
@@ -5702,4 +5794,5 @@
     return off;
 }
+
 #endif /* IEMNATIVE_WITH_DELAYED_PC_UPDATING */
 
@@ -6431,4 +6524,9 @@
 #endif
 
+#ifdef IEMNATIVE_WITH_DELAYED_PC_UPDATING_DEBUG
+    pReNative->Core.fDebugPcInitialized = false;
+    Log4(("fDebugPcInitialized=false cimpl off=%#x (v2)\n", off));
+#endif
+
     /*
      * Check the status code.
@@ -6516,4 +6614,9 @@
 #else
 # error "port me"
+#endif
+
+#ifdef IEMNATIVE_WITH_DELAYED_PC_UPDATING_DEBUG
+    pReNative->Core.fDebugPcInitialized = false;
+    Log4(("fDebugPcInitialized=false todo off=%#x (v2)\n", off));
 #endif
 
@@ -8746,4 +8849,7 @@
         ENTRY(iem.s.idxTbCurInstr),
         ENTRY(iem.s.fSkippingEFlags),
+#ifdef IEMNATIVE_WITH_DELAYED_PC_UPDATING_DEBUG
+        ENTRY(iem.s.uPcUpdatingDebug),
+#endif
 #ifdef VBOX_WITH_STATISTICS
         ENTRY(iem.s.StatNativeTlbHitsForFetch),
@@ -10090,6 +10196,6 @@
              * Actual work.
              */
-            Log2(("%u[%u]: %s%s\n", idxCurCall, pCallEntry->idxInstr, g_apszIemThreadedFunctions[pCallEntry->enmFunction],
-                  pfnRecom ? "(recompiled)" : "(todo)"));
+            Log2(("%u[%u]: %s%s (off=%#x)\n", idxCurCall, pCallEntry->idxInstr,
+                  g_apszIemThreadedFunctions[pCallEntry->enmFunction], pfnRecom ? "(recompiled)" : "(todo)", off));
             if (pfnRecom) /** @todo stats on this.   */
             {
Index: /trunk/src/VBox/VMM/VMMR3/IEMR3.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMR3/IEMR3.cpp	(revision 105852)
+++ /trunk/src/VBox/VMM/VMMR3/IEMR3.cpp	(revision 105853)
@@ -809,5 +809,11 @@
         STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativePcUpdateTotal,   STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT, "Total RIP updates",   "/IEM/CPU%u/re/NativePcUpdateTotal", idCpu);
         STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativePcUpdateDelayed, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT, "Delayed RIP updates", "/IEM/CPU%u/re/NativePcUpdateDelayed", idCpu);
-
+#  endif /* VBOX_WITH_STATISTICS */
+#  ifdef IEMNATIVE_WITH_DELAYED_REGISTER_WRITEBACK
+        STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativeEndIfOtherBranchDirty, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
+                        "IEM_MC_ENDIF flushing dirty shadow registers for other branch (not good).",
+                        "/IEM/CPU%u/re/NativeEndIfOtherBranchDirty", idCpu);
+#  endif
+#  ifdef VBOX_WITH_STATISTICS
 #   ifdef IEMNATIVE_WITH_SIMD_REG_ALLOCATOR
         STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativeSimdRegFindFree, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
Index: /trunk/src/VBox/VMM/include/IEMInternal.h
===================================================================
--- /trunk/src/VBox/VMM/include/IEMInternal.h	(revision 105852)
+++ /trunk/src/VBox/VMM/include/IEMInternal.h	(revision 105853)
@@ -112,4 +112,10 @@
 #if defined(DOXYGEN_RUNNING) || 1
 # define IEMNATIVE_WITH_DELAYED_PC_UPDATING
+#endif
+/** @def IEMNATIVE_WITH_DELAYED_PC_UPDATING_DEBUG
+ * Enabled delayed PC updating debugging code.
+ * This is an alternative to the ARM64-only IEMNATIVE_REG_FIXED_PC_DBG. */
+#if defined(DOXYGEN_RUNNING) || 0
+# define IEMNATIVE_WITH_DELAYED_PC_UPDATING_DEBUG
 #endif
 
@@ -2270,4 +2276,12 @@
     /** Dummy entry for ppTbLookupEntryR3. */
     R3PTRTYPE(PIEMTB)       pTbLookupEntryDummyR3;
+#ifdef IEMNATIVE_WITH_DELAYED_PC_UPDATING_DEBUG
+    /** The debug code advances this register as if it was CPUMCTX::rip and we
+     * didn't do delayed PC updating.  When CPUMCTX::rip is finally updated,
+     * the result is compared with this value. */
+    uint64_t                uPcUpdatingDebug;
+#else
+    uint64_t                u64Placeholder;
+#endif
     /** @} */
 
@@ -2394,4 +2408,8 @@
     STAMCOUNTER             StatNativePcUpdateDelayed;
 
+    /** Native recompiler: Number of time we had complicated dirty shadow
+     *  register situations with the other branch in IEM_MC_ENDIF. */
+    STAMCOUNTER             StatNativeEndIfOtherBranchDirty;
+
 //#ifdef IEMNATIVE_WITH_SIMD_REG_ALLOCATOR
     /** Native recompiler: Number of calls to iemNativeSimdRegAllocFindFree. */
@@ -2519,7 +2537,7 @@
 
 #ifdef IEM_WITH_TLB_TRACE
+    uint64_t                au64Padding[4];
+#else
     uint64_t                au64Padding[6];
-#else
-    //uint64_t                au64Padding[0];
 #endif
 
Index: /trunk/src/VBox/VMM/include/IEMN8veRecompiler.h
===================================================================
--- /trunk/src/VBox/VMM/include/IEMN8veRecompiler.h	(revision 105852)
+++ /trunk/src/VBox/VMM/include/IEMN8veRecompiler.h	(revision 105853)
@@ -1246,5 +1246,12 @@
     uint32_t                    offPc;
     /** Number of instructions where we could skip the updating. */
-    uint32_t                    cInstrPcUpdateSkipped;
+    uint8_t                     cInstrPcUpdateSkipped;
+# ifdef IEMNATIVE_WITH_DELAYED_PC_UPDATING_DEBUG
+    /** Set after we've loaded PC into uPcUpdatingDebug at the first update. */
+    bool                        fDebugPcInitialized;
+    uint8_t                     abPadding[2];
+# else
+    uint8_t                     abPadding[3];
+# endif
 #endif
     /** Allocation bitmap for aHstRegs. */
@@ -1386,8 +1393,16 @@
     /** Set if we're in the "else" part, clear if we're in the "if" before it. */
     bool                        fInElse;
-    /** Set if the if-block unconditionally exited the TB. */
-    bool                        fIfExitTb;
-    /** Set if the else-block unconditionally exited the TB. */
-    bool                        fElseExitTb;
+    union
+    {
+        struct
+        {
+            /** Set if the if-block unconditionally exited the TB. */
+            bool                fIfExitTb;
+            /** Set if the else-block unconditionally exited the TB. */
+            bool                fElseExitTb;
+        };
+        /** Indexed by fInElse. */
+        bool                    afExitTb[2];
+    };
     bool                        afPadding[5];
     /** The label for the IEM_MC_ELSE. */
@@ -1712,10 +1727,18 @@
                                                                uint64_t fGstSimdShwExcept);
 #ifdef IEMNATIVE_WITH_DELAYED_PC_UPDATING
+# ifdef IEMNATIVE_WITH_DELAYED_PC_UPDATING_DEBUG
+DECL_HIDDEN_THROW(uint32_t) iemNativeEmitPcDebugCheck(PIEMRECOMPILERSTATE pReNative, uint32_t off);
+DECL_HIDDEN_THROW(uint32_t) iemNativeEmitPcDebugCheckWithReg(PIEMRECOMPILERSTATE pReNative, uint32_t off, uint8_t idxPcReg);
+# endif
 DECL_HIDDEN_THROW(uint32_t) iemNativeEmitPcWritebackSlow(PIEMRECOMPILERSTATE pReNative, uint32_t off);
 #endif
 #ifdef IEMNATIVE_WITH_DELAYED_REGISTER_WRITEBACK
 DECL_HIDDEN_THROW(uint32_t) iemNativeRegFlushPendingWrite(PIEMRECOMPILERSTATE pReNative, uint32_t off, IEMNATIVEGSTREG enmGstReg);
-DECL_HIDDEN_THROW(uint32_t) iemNativeRegFlushDirtyGuest(PIEMRECOMPILERSTATE pReNative, uint32_t off, uint64_t fFlushGstReg = UINT64_MAX);
-DECL_HIDDEN_THROW(uint32_t) iemNativeRegFlushDirtyGuestByHostRegShadow(PIEMRECOMPILERSTATE pReNative, uint32_t off, uint8_t idxHstReg);
+DECL_HIDDEN_THROW(uint32_t) iemNativeRegFlushPendingWriteEx(PIEMRECOMPILERSTATE pReNative, uint32_t off,
+                                                            PIEMNATIVECORESTATE pCore, IEMNATIVEGSTREG enmGstReg);
+DECL_HIDDEN_THROW(uint32_t) iemNativeRegFlushDirtyGuest(PIEMRECOMPILERSTATE pReNative, uint32_t off,
+                                                        uint64_t fFlushGstReg = UINT64_MAX);
+DECL_HIDDEN_THROW(uint32_t) iemNativeRegFlushDirtyGuestByHostRegShadow(PIEMRECOMPILERSTATE pReNative,
+                                                                       uint32_t off, uint8_t idxHstReg);
 #endif
 
@@ -2326,5 +2349,5 @@
     Assert(pReNative->Core.bmHstRegsWithGstShadow             & RT_BIT_32(idxHstReg));
 #ifdef IEMNATIVE_WITH_DELAYED_REGISTER_WRITEBACK
-    Assert(!(pReNative->Core.aHstRegs[idxHstReg].fGstRegShadows & pReNative->Core.bmGstRegShadowDirty));
+    Assert(!(pReNative->Core.bmGstRegShadowDirty              & RT_BIT_64(enmGstReg)));
 #endif
 
Index: /trunk/src/VBox/VMM/include/IEMN8veRecompilerEmit.h
===================================================================
--- /trunk/src/VBox/VMM/include/IEMN8veRecompilerEmit.h	(revision 105852)
+++ /trunk/src/VBox/VMM/include/IEMN8veRecompilerEmit.h	(revision 105853)
@@ -4360,5 +4360,5 @@
  */
 DECL_FORCE_INLINE_THROW(uint32_t)
-iemNativeEmitAddGpr32ImmEx(PIEMNATIVEINSTR pCodeBuf, uint32_t off, uint8_t iGprDst, int32_t iAddend)
+iemNativeEmitAddGpr32ImmEx(PIEMNATIVEINSTR pCodeBuf, uint32_t off, uint8_t iGprDst, int32_t iAddend, uint8_t iGprTmp = UINT8_MAX)
 {
 #if defined(RT_ARCH_AMD64)
@@ -4375,4 +4375,5 @@
     pCodeBuf[off++] = RT_BYTE3((uint32_t)iAddend);
     pCodeBuf[off++] = RT_BYTE4((uint32_t)iAddend);
+    RT_NOREF(iGprTmp);
 
 #elif defined(RT_ARCH_ARM64)
@@ -4386,4 +4387,9 @@
         if (uAbsAddend & 0xfffU)
             pCodeBuf[off++] = Armv8A64MkInstrAddSubUImm12(fSub, iGprDst, iGprDst, uAbsAddend & 0xfff, false /*f64Bit*/);
+    }
+    else if (iGprTmp != UINT8_MAX)
+    {
+        off = iemNativeEmitLoadGpr32ImmEx(pCodeBuf, off, iGprTmp, iAddend);
+        pCodeBuf[off++] = Armv8A64MkInstrAddReg(iGprDst, iGprDst, iGprTmp, false /*f64Bit*/);
     }
     else
@@ -8266,4 +8272,20 @@
 
 /**
+ * Helper for marking the current conditional branch as exiting the TB.
+ *
+ * This simplifies the state consolidation later when we reach the IEM_MC_ENDIF.
+ */
+DECL_FORCE_INLINE(void) iemNativeMarkCurCondBranchAsExiting(PIEMRECOMPILERSTATE pReNative)
+{
+    uint8_t idxCondDepth = pReNative->cCondDepth;
+    if (idxCondDepth)
+    {
+        idxCondDepth--;
+        pReNative->aCondStack[idxCondDepth].afExitTb[pReNative->aCondStack[idxCondDepth].fInElse] = true;
+    }
+}
+
+
+/**
  * Emits a Jcc rel32 / B.cc imm19 to the given label (ASSUMED requiring fixup).
  */
@@ -8273,4 +8295,5 @@
 {
     Assert(IEMNATIVELABELTYPE_IS_EXIT_REASON(enmExitReason));
+
 #if defined(IEMNATIVE_WITH_RECOMPILER_PER_CHUNK_TAIL_CODE) && defined(RT_ARCH_AMD64)
     /* jcc rel32 */
@@ -8380,4 +8403,7 @@
 {
     Assert(IEMNATIVELABELTYPE_IS_EXIT_REASON(enmExitReason));
+
+    iemNativeMarkCurCondBranchAsExiting(pReNative);
+
 #ifdef IEMNATIVE_WITH_RECOMPILER_PER_CHUNK_TAIL_CODE
 # ifdef RT_ARCH_AMD64
@@ -8409,4 +8435,7 @@
 {
     Assert(IEMNATIVELABELTYPE_IS_EXIT_REASON(enmExitReason));
+
+    iemNativeMarkCurCondBranchAsExiting(pReNative);
+
 #ifdef IEMNATIVE_WITH_RECOMPILER_PER_CHUNK_TAIL_CODE
 # ifdef RT_ARCH_AMD64
