Index: trunk/src/VBox/VMM/VMMAll/IEMAllN8veRecompBltIn.cpp
===================================================================
--- trunk/src/VBox/VMM/VMMAll/IEMAllN8veRecompBltIn.cpp	(revision 106101)
+++ trunk/src/VBox/VMM/VMMAll/IEMAllN8veRecompBltIn.cpp	(revision 106113)
@@ -209,6 +209,6 @@
 {
     uint8_t const         idxEflReg  = !a_fCheckIrqs ? UINT8_MAX
-                                     : iemNativeRegAllocTmpForGuestReg(pReNative, &off, kIemNativeGstReg_EFlags,
-                                                                       kIemNativeGstRegUse_ReadOnly);
+                                     : iemNativeRegAllocTmpForGuestEFlags(pReNative, &off, kIemNativeGstRegUse_ReadOnly,
+                                                                          RT_BIT_64(IEMLIVENESSBIT_IDX_EFL_OTHER));
     uint8_t const         idxTmpReg1 = iemNativeRegAllocTmp(pReNative, &off);
     uint8_t const         idxTmpReg2 = a_fCheckIrqs ? iemNativeRegAllocTmp(pReNative, &off) : UINT8_MAX;
Index: trunk/src/VBox/VMM/VMMAll/IEMAllN8veRecompFuncs.h
===================================================================
--- trunk/src/VBox/VMM/VMMAll/IEMAllN8veRecompFuncs.h	(revision 106101)
+++ trunk/src/VBox/VMM/VMMAll/IEMAllN8veRecompFuncs.h	(revision 106113)
@@ -439,7 +439,7 @@
     off = iemNativeRegFlushPendingWrites(pReNative, off);
 
-    uint8_t const idxEflReg = iemNativeRegAllocTmpForGuestReg(pReNative, &off, kIemNativeGstReg_EFlags,
-                                                              kIemNativeGstRegUse_ForUpdate, false /*fNoVolatileRegs*/,
-                                                              true /*fSkipLivenessAssert*/);
+    uint8_t const idxEflReg = iemNativeRegAllocTmpForGuestEFlags(pReNative, &off, kIemNativeGstRegUse_ForUpdate,
+                                                                 RT_BIT_64(IEMLIVENESSBIT_IDX_EFL_OTHER),
+                                                                 RT_BIT_64(IEMLIVENESSBIT_IDX_EFL_OTHER));
     off = iemNativeEmitTestAnyBitsInGprAndTbExitIfAnySet(pReNative, off, idxEflReg,
                                                          X86_EFL_TF | CPUMCTX_DBG_HIT_DRX_MASK | CPUMCTX_DBG_DBGF_MASK,
@@ -1795,6 +1795,6 @@
                        PUSH FS in real mode, so we have to try emulate that here.
                        We borrow the now unused idxReg1 from the TLB lookup code here. */
-                    uint8_t idxRegEfl = iemNativeRegAllocTmpForGuestRegIfAlreadyPresent(pReNative, &off,
-                                                                                        kIemNativeGstReg_EFlags);
+                    uint8_t const idxRegEfl = iemNativeRegAllocTmpForGuestRegIfAlreadyPresent(pReNative, &off,
+                                                                                              kIemNativeGstReg_EFlags);
                     if (idxRegEfl != UINT8_MAX)
                     {
@@ -3348,10 +3348,56 @@
 
 
+/**
+ * Helper function to convert X86_EFL_xxx masks to liveness masks.
+ *
+ * The compiler should be able to figure this out at compile time, so sprinkling
+ * constexpr where ever possible here to nudge it along.
+ */
+template<uint32_t const a_fEfl>
+RT_CONSTEXPR uint64_t iemNativeEflagsToLivenessMask(void)
+{
+    return (a_fEfl & ~X86_EFL_STATUS_BITS ? RT_BIT_64(IEMLIVENESSBIT_IDX_EFL_OTHER) : 0)
+         | (a_fEfl & X86_EFL_CF           ? RT_BIT_64(IEMLIVENESSBIT_IDX_EFL_CF)    : 0)
+         | (a_fEfl & X86_EFL_PF           ? RT_BIT_64(IEMLIVENESSBIT_IDX_EFL_PF)    : 0)
+         | (a_fEfl & X86_EFL_AF           ? RT_BIT_64(IEMLIVENESSBIT_IDX_EFL_AF)    : 0)
+         | (a_fEfl & X86_EFL_ZF           ? RT_BIT_64(IEMLIVENESSBIT_IDX_EFL_ZF)    : 0)
+         | (a_fEfl & X86_EFL_SF           ? RT_BIT_64(IEMLIVENESSBIT_IDX_EFL_SF)    : 0)
+         | (a_fEfl & X86_EFL_OF           ? RT_BIT_64(IEMLIVENESSBIT_IDX_EFL_OF)    : 0);
+}
+
+
+/**
+ * Helper function to convert a single X86_EFL_xxxx value to bit number.
+ *
+ * The compiler should be able to figure this out at compile time, so sprinkling
+ * constexpr where ever possible here to nudge it along.
+ */
+template<uint32_t const a_fEfl>
+RT_CONSTEXPR unsigned iemNativeEflagsToSingleBitNo(void)
+{
+    AssertCompile(   a_fEfl == X86_EFL_CF
+                  || a_fEfl == X86_EFL_PF
+                  || a_fEfl == X86_EFL_AF
+                  || a_fEfl == X86_EFL_ZF
+                  || a_fEfl == X86_EFL_SF
+                  || a_fEfl == X86_EFL_OF
+                  || a_fEfl == X86_EFL_DF);
+    return a_fEfl == X86_EFL_CF ? X86_EFL_CF_BIT
+         : a_fEfl == X86_EFL_PF ? X86_EFL_PF_BIT
+         : a_fEfl == X86_EFL_AF ? X86_EFL_AF_BIT
+         : a_fEfl == X86_EFL_ZF ? X86_EFL_ZF_BIT
+         : a_fEfl == X86_EFL_SF ? X86_EFL_SF_BIT
+         : a_fEfl == X86_EFL_OF ? X86_EFL_OF_BIT
+         :                        X86_EFL_DF_BIT;
+}
+
+
 #define IEM_MC_IF_EFL_ANY_BITS_SET(a_fBits) \
-        off = iemNativeEmitIfEflagAnysBitsSet(pReNative, off, (a_fBits)); \
+        off = iemNativeEmitIfEflagAnysBitsSet(pReNative, off, (a_fBits), iemNativeEflagsToLivenessMask<a_fBits>()); \
         do {
 
 /** Emits code for IEM_MC_IF_EFL_ANY_BITS_SET. */
-DECL_INLINE_THROW(uint32_t) iemNativeEmitIfEflagAnysBitsSet(PIEMRECOMPILERSTATE pReNative, uint32_t off, uint32_t fBitsInEfl)
+DECL_INLINE_THROW(uint32_t)
+iemNativeEmitIfEflagAnysBitsSet(PIEMRECOMPILERSTATE pReNative, uint32_t off, uint32_t fBitsInEfl, uint64_t fLivenessEflBits)
 {
     IEMNATIVE_STRICT_EFLAGS_SKIPPING_EMIT_CHECK(pReNative, off, fBitsInEfl);
@@ -3359,6 +3405,5 @@
 
     /* Get the eflags. */
-    uint8_t const idxEflReg = iemNativeRegAllocTmpForGuestReg(pReNative, &off, kIemNativeGstReg_EFlags,
-                                                              kIemNativeGstRegUse_ReadOnly);
+    uint8_t const idxEflReg = iemNativeRegAllocTmpForGuestEFlags(pReNative, &off, kIemNativeGstRegUse_ReadOnly, fLivenessEflBits);
 
     /* Test and jump. */
@@ -3376,9 +3421,10 @@
 
 #define IEM_MC_IF_EFL_NO_BITS_SET(a_fBits) \
-        off = iemNativeEmitIfEflagNoBitsSet(pReNative, off, (a_fBits)); \
+        off = iemNativeEmitIfEflagNoBitsSet(pReNative, off, (a_fBits), iemNativeEflagsToLivenessMask<a_fBits>()); \
         do {
 
 /** Emits code for IEM_MC_IF_EFL_NO_BITS_SET. */
-DECL_INLINE_THROW(uint32_t) iemNativeEmitIfEflagNoBitsSet(PIEMRECOMPILERSTATE pReNative, uint32_t off, uint32_t fBitsInEfl)
+DECL_INLINE_THROW(uint32_t)
+iemNativeEmitIfEflagNoBitsSet(PIEMRECOMPILERSTATE pReNative, uint32_t off, uint32_t fBitsInEfl, uint64_t fLivenessEflBits)
 {
     IEMNATIVE_STRICT_EFLAGS_SKIPPING_EMIT_CHECK(pReNative, off, fBitsInEfl);
@@ -3386,6 +3432,5 @@
 
     /* Get the eflags. */
-    uint8_t const idxEflReg = iemNativeRegAllocTmpForGuestReg(pReNative, &off, kIemNativeGstReg_EFlags,
-                                                              kIemNativeGstRegUse_ReadOnly);
+    uint8_t const idxEflReg = iemNativeRegAllocTmpForGuestEFlags(pReNative, &off, kIemNativeGstRegUse_ReadOnly, fLivenessEflBits);
 
     /* Test and jump. */
@@ -3403,19 +3448,17 @@
 
 #define IEM_MC_IF_EFL_BIT_SET(a_fBit) \
-        off = iemNativeEmitIfEflagsBitSet(pReNative, off, (a_fBit)); \
+        off = iemNativeEmitIfEflagsBitSet(pReNative, off, iemNativeEflagsToSingleBitNo<a_fBit>(), \
+                                          iemNativeEflagsToLivenessMask<a_fBit>()); \
         do {
 
 /** Emits code for IEM_MC_IF_EFL_BIT_SET. */
-DECL_INLINE_THROW(uint32_t) iemNativeEmitIfEflagsBitSet(PIEMRECOMPILERSTATE pReNative, uint32_t off, uint32_t fBitInEfl)
-{
-    IEMNATIVE_STRICT_EFLAGS_SKIPPING_EMIT_CHECK(pReNative, off, fBitInEfl);
+DECL_INLINE_THROW(uint32_t)
+iemNativeEmitIfEflagsBitSet(PIEMRECOMPILERSTATE pReNative, uint32_t off, unsigned iBitNo, uint64_t fLivenessEflBit)
+{
+    IEMNATIVE_STRICT_EFLAGS_SKIPPING_EMIT_CHECK(pReNative, off, RT_BIT_32(iBitNo));
     PIEMNATIVECOND const pEntry = iemNativeCondPushIf(pReNative);
 
     /* Get the eflags. */
-    uint8_t const idxEflReg = iemNativeRegAllocTmpForGuestReg(pReNative, &off, kIemNativeGstReg_EFlags,
-                                                              kIemNativeGstRegUse_ReadOnly);
-
-    unsigned const iBitNo = ASMBitFirstSetU32(fBitInEfl) - 1;
-    Assert(RT_BIT_32(iBitNo) == fBitInEfl);
+    uint8_t const idxEflReg = iemNativeRegAllocTmpForGuestEFlags(pReNative, &off, kIemNativeGstRegUse_ReadOnly, fLivenessEflBit);
 
     /* Test and jump. */
@@ -3433,19 +3476,17 @@
 
 #define IEM_MC_IF_EFL_BIT_NOT_SET(a_fBit) \
-        off = iemNativeEmitIfEflagsBitNotSet(pReNative, off, (a_fBit)); \
+        off = iemNativeEmitIfEflagsBitNotSet(pReNative, off, iemNativeEflagsToSingleBitNo<a_fBit>(), \
+                                             iemNativeEflagsToLivenessMask<a_fBit>()); \
         do {
 
 /** Emits code for IEM_MC_IF_EFL_BIT_NOT_SET. */
-DECL_INLINE_THROW(uint32_t) iemNativeEmitIfEflagsBitNotSet(PIEMRECOMPILERSTATE pReNative, uint32_t off, uint32_t fBitInEfl)
-{
-    IEMNATIVE_STRICT_EFLAGS_SKIPPING_EMIT_CHECK(pReNative, off, fBitInEfl);
+DECL_INLINE_THROW(uint32_t)
+iemNativeEmitIfEflagsBitNotSet(PIEMRECOMPILERSTATE pReNative, uint32_t off, unsigned iBitNo, uint64_t fLivenessEflBit)
+{
+    IEMNATIVE_STRICT_EFLAGS_SKIPPING_EMIT_CHECK(pReNative, off, RT_BIT_32(iBitNo));
     PIEMNATIVECOND const pEntry = iemNativeCondPushIf(pReNative);
 
     /* Get the eflags. */
-    uint8_t const idxEflReg = iemNativeRegAllocTmpForGuestReg(pReNative, &off, kIemNativeGstReg_EFlags,
-                                                              kIemNativeGstRegUse_ReadOnly);
-
-    unsigned const iBitNo = ASMBitFirstSetU32(fBitInEfl) - 1;
-    Assert(RT_BIT_32(iBitNo) == fBitInEfl);
+    uint8_t const idxEflReg = iemNativeRegAllocTmpForGuestEFlags(pReNative, &off, kIemNativeGstRegUse_ReadOnly, fLivenessEflBit);
 
     /* Test and jump. */
@@ -3462,10 +3503,16 @@
 
 
-#define IEM_MC_IF_EFL_BITS_EQ(a_fBit1, a_fBit2)         \
-    off = iemNativeEmitIfEflagsTwoBitsEqual(pReNative, off, a_fBit1, a_fBit2, false /*fInverted*/); \
+#define IEM_MC_IF_EFL_BITS_EQ(a_fBit1, a_fBit2) \
+    off = iemNativeEmitIfEflagsTwoBitsEqual(pReNative, off, false /*fInverted*/, \
+                                            iemNativeEflagsToSingleBitNo<a_fBit1>(), \
+                                            iemNativeEflagsToSingleBitNo<a_fBit2>(), \
+                                            iemNativeEflagsToLivenessMask<a_fBit1 | a_fBit2>()); \
     do {
 
-#define IEM_MC_IF_EFL_BITS_NE(a_fBit1, a_fBit2)         \
-    off = iemNativeEmitIfEflagsTwoBitsEqual(pReNative, off, a_fBit1, a_fBit2, true /*fInverted*/); \
+#define IEM_MC_IF_EFL_BITS_NE(a_fBit1, a_fBit2) \
+    off = iemNativeEmitIfEflagsTwoBitsEqual(pReNative, off, true /*fInverted*/, \
+                                            iemNativeEflagsToSingleBitNo<a_fBit1>(), \
+                                            iemNativeEflagsToSingleBitNo<a_fBit2>(), \
+                                            iemNativeEflagsToLivenessMask<a_fBit1 | a_fBit2>()); \
     do {
 
@@ -3473,22 +3520,15 @@
 DECL_INLINE_THROW(uint32_t)
 iemNativeEmitIfEflagsTwoBitsEqual(PIEMRECOMPILERSTATE pReNative, uint32_t off,
-                                  uint32_t fBit1InEfl, uint32_t fBit2InEfl, bool fInverted)
-{
-    IEMNATIVE_STRICT_EFLAGS_SKIPPING_EMIT_CHECK(pReNative, off, fBit1InEfl | fBit2InEfl);
+                                  bool fInverted, unsigned iBitNo1, unsigned iBitNo2, uint64_t fLivenessEflBits)
+{
+    Assert(iBitNo1 != iBitNo2);
+    IEMNATIVE_STRICT_EFLAGS_SKIPPING_EMIT_CHECK(pReNative, off, RT_BIT_32(iBitNo1) | RT_BIT_32(iBitNo2));
     PIEMNATIVECOND const pEntry = iemNativeCondPushIf(pReNative);
 
     /* Get the eflags. */
-    uint8_t const idxEflReg = iemNativeRegAllocTmpForGuestReg(pReNative, &off, kIemNativeGstReg_EFlags,
-                                                              kIemNativeGstRegUse_ReadOnly);
-
-    unsigned const iBitNo1 = ASMBitFirstSetU32(fBit1InEfl) - 1;
-    Assert(RT_BIT_32(iBitNo1) == fBit1InEfl);
-
-    unsigned const iBitNo2 = ASMBitFirstSetU32(fBit2InEfl) - 1;
-    Assert(RT_BIT_32(iBitNo2) == fBit2InEfl);
-    Assert(iBitNo1 != iBitNo2);
+    uint8_t const idxEflReg = iemNativeRegAllocTmpForGuestEFlags(pReNative, &off, kIemNativeGstRegUse_ReadOnly, fLivenessEflBits);
 
 #ifdef RT_ARCH_AMD64
-    uint8_t const idxTmpReg = iemNativeRegAllocTmpImm(pReNative, &off, fBit1InEfl);
+    uint8_t const idxTmpReg = iemNativeRegAllocTmpImm(pReNative, &off, RT_BIT_64(iBitNo1));
 
     off = iemNativeEmitAndGpr32ByGpr32(pReNative, off, idxTmpReg, idxEflReg);
@@ -3536,9 +3576,17 @@
 
 #define IEM_MC_IF_EFL_BIT_NOT_SET_AND_BITS_EQ(a_fBit, a_fBit1, a_fBit2) \
-    off = iemNativeEmitIfEflagsBitNotSetAndTwoBitsEqual(pReNative, off, a_fBit, a_fBit1, a_fBit2, false /*fInverted*/); \
+    off = iemNativeEmitIfEflagsBitNotSetAndTwoBitsEqual(pReNative, off, false /*fInverted*/, \
+                                                        iemNativeEflagsToSingleBitNo<a_fBit>(), \
+                                                        iemNativeEflagsToSingleBitNo<a_fBit1>(), \
+                                                        iemNativeEflagsToSingleBitNo<a_fBit2>(), \
+                                                        iemNativeEflagsToLivenessMask<a_fBit | a_fBit1 | a_fBit2>()); \
     do {
 
 #define IEM_MC_IF_EFL_BIT_SET_OR_BITS_NE(a_fBit, a_fBit1, a_fBit2) \
-    off = iemNativeEmitIfEflagsBitNotSetAndTwoBitsEqual(pReNative, off, a_fBit, a_fBit1, a_fBit2, true /*fInverted*/); \
+    off = iemNativeEmitIfEflagsBitNotSetAndTwoBitsEqual(pReNative, off, true /*fInverted*/, \
+                                                        iemNativeEflagsToSingleBitNo<a_fBit>(), \
+                                                        iemNativeEflagsToSingleBitNo<a_fBit1>(), \
+                                                        iemNativeEflagsToSingleBitNo<a_fBit2>(), \
+                                                        iemNativeEflagsToLivenessMask<a_fBit | a_fBit1 | a_fBit2>()); \
     do {
 
@@ -3546,8 +3594,11 @@
  *  IEM_MC_IF_EFL_BIT_SET_OR_BITS_NE. */
 DECL_INLINE_THROW(uint32_t)
-iemNativeEmitIfEflagsBitNotSetAndTwoBitsEqual(PIEMRECOMPILERSTATE pReNative, uint32_t off, uint32_t fBitInEfl,
-                                              uint32_t fBit1InEfl, uint32_t fBit2InEfl, bool fInverted)
-{
-    IEMNATIVE_STRICT_EFLAGS_SKIPPING_EMIT_CHECK(pReNative, off, fBitInEfl | fBit1InEfl | fBit2InEfl);
+iemNativeEmitIfEflagsBitNotSetAndTwoBitsEqual(PIEMRECOMPILERSTATE pReNative, uint32_t off, bool fInverted,
+                                              unsigned iBitNo, unsigned iBitNo1, unsigned iBitNo2, uint64_t fLivenessEflBits)
+{
+    Assert(iBitNo1 != iBitNo);
+    Assert(iBitNo2 != iBitNo);
+    Assert(iBitNo2 != iBitNo1);
+    IEMNATIVE_STRICT_EFLAGS_SKIPPING_EMIT_CHECK(pReNative, off, RT_BIT_32(iBitNo) | RT_BIT_32(iBitNo1) | RT_BIT_32(iBitNo2));
     PIEMNATIVECOND const pEntry = iemNativeCondPushIf(pReNative);
 
@@ -3557,22 +3608,8 @@
 
     /* Get the eflags. */
-    uint8_t const idxEflReg = iemNativeRegAllocTmpForGuestReg(pReNative, &off, kIemNativeGstReg_EFlags,
-                                                              kIemNativeGstRegUse_ReadOnly);
-
-    /* Translate the flag masks to bit numbers. */
-    unsigned const iBitNo = ASMBitFirstSetU32(fBitInEfl) - 1;
-    Assert(RT_BIT_32(iBitNo) == fBitInEfl);
-
-    unsigned const iBitNo1 = ASMBitFirstSetU32(fBit1InEfl) - 1;
-    Assert(RT_BIT_32(iBitNo1) == fBit1InEfl);
-    Assert(iBitNo1 != iBitNo);
-
-    unsigned const iBitNo2 = ASMBitFirstSetU32(fBit2InEfl) - 1;
-    Assert(RT_BIT_32(iBitNo2) == fBit2InEfl);
-    Assert(iBitNo2 != iBitNo);
-    Assert(iBitNo2 != iBitNo1);
+    uint8_t const idxEflReg = iemNativeRegAllocTmpForGuestEFlags(pReNative, &off, kIemNativeGstRegUse_ReadOnly, fLivenessEflBits);
 
 #ifdef RT_ARCH_AMD64
-    uint8_t const idxTmpReg = iemNativeRegAllocTmpImm(pReNative, &off, fBit1InEfl); /* This must come before we jump anywhere! */
+    uint8_t const idxTmpReg = iemNativeRegAllocTmpImm(pReNative, &off, RT_BIT_64(iBitNo1)); /* This must come before we jump anywhere! */
 #elif defined(RT_ARCH_ARM64)
     uint8_t const idxTmpReg = iemNativeRegAllocTmp(pReNative, &off);
@@ -3723,9 +3760,13 @@
 
 #define IEM_MC_IF_CX_IS_NOT_ONE_AND_EFL_BIT_SET(a_fBit) \
-    off = iemNativeEmitIfCxIsNotOneAndTestEflagsBit(pReNative, off, a_fBit, true /*fCheckIfSet*/); \
+    off = iemNativeEmitIfCxIsNotOneAndTestEflagsBit(pReNative, off, true /*fCheckIfSet*/, \
+                                                    iemNativeEflagsToSingleBitNo<a_fBit>(), \
+                                                    iemNativeEflagsToLivenessMask<a_fBit>()); \
     do {
 
 #define IEM_MC_IF_CX_IS_NOT_ONE_AND_EFL_BIT_NOT_SET(a_fBit) \
-    off = iemNativeEmitIfCxIsNotOneAndTestEflagsBit(pReNative, off, a_fBit, false /*fCheckIfSet*/); \
+    off = iemNativeEmitIfCxIsNotOneAndTestEflagsBit(pReNative, off, false /*fCheckIfSet*/, \
+                                                    iemNativeEflagsToSingleBitNo<a_fBit>(), \
+                                                    iemNativeEflagsToLivenessMask<a_fBit>()); \
     do {
 
@@ -3733,7 +3774,8 @@
  *  IEM_MC_IF_CX_IS_NOT_ONE_AND_EFL_BIT_NOT_SET. */
 DECL_INLINE_THROW(uint32_t)
-iemNativeEmitIfCxIsNotOneAndTestEflagsBit(PIEMRECOMPILERSTATE pReNative, uint32_t off, uint32_t fBitInEfl, bool fCheckIfSet)
-{
-    IEMNATIVE_STRICT_EFLAGS_SKIPPING_EMIT_CHECK(pReNative, off, fBitInEfl);
+iemNativeEmitIfCxIsNotOneAndTestEflagsBit(PIEMRECOMPILERSTATE pReNative, uint32_t off,
+                                          bool fCheckIfSet, unsigned iBitNo, uint64_t fLivenessEflBit)
+{
+    IEMNATIVE_STRICT_EFLAGS_SKIPPING_EMIT_CHECK(pReNative, off, RT_BIT_32(iBitNo));
     PIEMNATIVECOND const pEntry = iemNativeCondPushIf(pReNative);
 
@@ -3742,6 +3784,5 @@
        register allocator state.
        Doing EFLAGS first as it's more likely to be loaded, right? */
-    uint8_t const idxEflReg    = iemNativeRegAllocTmpForGuestReg(pReNative, &off, kIemNativeGstReg_EFlags,
-                                                                 kIemNativeGstRegUse_ReadOnly);
+    uint8_t const idxEflReg = iemNativeRegAllocTmpForGuestEFlags(pReNative, &off, kIemNativeGstRegUse_ReadOnly, fLivenessEflBit);
     uint8_t const idxGstRcxReg = iemNativeRegAllocTmpForGuestReg(pReNative, &off, IEMNATIVEGSTREG_GPR(X86_GREG_xCX),
                                                                  kIemNativeGstRegUse_ReadOnly);
@@ -3760,6 +3801,4 @@
 
     /* Check the EFlags bit. */
-    unsigned const iBitNo = ASMBitFirstSetU32(fBitInEfl) - 1;
-    Assert(RT_BIT_32(iBitNo) == fBitInEfl);
     off = iemNativeEmitTestBitInGprAndJmpToLabelIfCc(pReNative, off, idxEflReg, iBitNo, pEntry->idxLabelElse,
                                                      !fCheckIfSet /*fJmpIfSet*/);
@@ -3774,17 +3813,25 @@
 
 #define IEM_MC_IF_ECX_IS_NOT_ONE_AND_EFL_BIT_SET(a_fBit) \
-    off = iemNativeEmitIfRcxEcxIsNotOneAndTestEflagsBit(pReNative, off, a_fBit, true /*fCheckIfSet*/, false /*f64Bit*/); \
+    off = iemNativeEmitIfRcxEcxIsNotOneAndTestEflagsBit(pReNative, off, true /*fCheckIfSet*/, false /*f64Bit*/, \
+                                                        iemNativeEflagsToSingleBitNo<a_fBit>(), \
+                                                        iemNativeEflagsToLivenessMask<a_fBit>()); \
     do {
 
 #define IEM_MC_IF_ECX_IS_NOT_ONE_AND_EFL_BIT_NOT_SET(a_fBit) \
-    off = iemNativeEmitIfRcxEcxIsNotOneAndTestEflagsBit(pReNative, off, a_fBit, false /*fCheckIfSet*/, false /*f64Bit*/); \
+    off = iemNativeEmitIfRcxEcxIsNotOneAndTestEflagsBit(pReNative, off, false /*fCheckIfSet*/, false /*f64Bit*/, \
+                                                        iemNativeEflagsToSingleBitNo<a_fBit>(), \
+                                                        iemNativeEflagsToLivenessMask<a_fBit>()); \
     do {
 
 #define IEM_MC_IF_RCX_IS_NOT_ONE_AND_EFL_BIT_SET(a_fBit) \
-    off = iemNativeEmitIfRcxEcxIsNotOneAndTestEflagsBit(pReNative, off, a_fBit, true /*fCheckIfSet*/, true /*f64Bit*/); \
+    off = iemNativeEmitIfRcxEcxIsNotOneAndTestEflagsBit(pReNative, off, true /*fCheckIfSet*/, true /*f64Bit*/, \
+                                                        iemNativeEflagsToSingleBitNo<a_fBit>(), \
+                                                        iemNativeEflagsToLivenessMask<a_fBit>()); \
     do {
 
 #define IEM_MC_IF_RCX_IS_NOT_ONE_AND_EFL_BIT_NOT_SET(a_fBit) \
-    off = iemNativeEmitIfRcxEcxIsNotOneAndTestEflagsBit(pReNative, off, a_fBit, false /*fCheckIfSet*/, true /*f64Bit*/); \
+    off = iemNativeEmitIfRcxEcxIsNotOneAndTestEflagsBit(pReNative, off, false /*fCheckIfSet*/, true /*f64Bit*/, \
+                                                        iemNativeEflagsToSingleBitNo<a_fBit>(), \
+                                                        iemNativeEflagsToLivenessMask<a_fBit>()); \
     do {
 
@@ -3794,8 +3841,9 @@
  *  IEM_MC_IF_RCX_IS_NOT_ONE_AND_EFL_BIT_NOT_SET. */
 DECL_INLINE_THROW(uint32_t)
-iemNativeEmitIfRcxEcxIsNotOneAndTestEflagsBit(PIEMRECOMPILERSTATE pReNative, uint32_t off,
-                                               uint32_t fBitInEfl, bool fCheckIfSet, bool f64Bit)
-{
-    IEMNATIVE_STRICT_EFLAGS_SKIPPING_EMIT_CHECK(pReNative, off, fBitInEfl);
+iemNativeEmitIfRcxEcxIsNotOneAndTestEflagsBit(PIEMRECOMPILERSTATE pReNative, uint32_t off, bool fCheckIfSet, bool f64Bit,
+                                              unsigned iBitNo, uint64_t fLivenessEFlBit)
+
+{
+    IEMNATIVE_STRICT_EFLAGS_SKIPPING_EMIT_CHECK(pReNative, off, RT_BIT_32(iBitNo));
     PIEMNATIVECOND const pEntry = iemNativeCondPushIf(pReNative);
 
@@ -3804,6 +3852,5 @@
        register allocator state.
        Doing EFLAGS first as it's more likely to be loaded, right? */
-    uint8_t const idxEflReg    = iemNativeRegAllocTmpForGuestReg(pReNative, &off, kIemNativeGstReg_EFlags,
-                                                                 kIemNativeGstRegUse_ReadOnly);
+    uint8_t const idxEflReg = iemNativeRegAllocTmpForGuestEFlags(pReNative, &off, kIemNativeGstRegUse_ReadOnly, fLivenessEFlBit);
     uint8_t const idxGstRcxReg = iemNativeRegAllocTmpForGuestReg(pReNative, &off, IEMNATIVEGSTREG_GPR(X86_GREG_xCX),
                                                                  kIemNativeGstRegUse_ReadOnly);
@@ -3819,6 +3866,4 @@
 
     /* Check the EFlags bit. */
-    unsigned const iBitNo = ASMBitFirstSetU32(fBitInEfl) - 1;
-    Assert(RT_BIT_32(iBitNo) == fBitInEfl);
     off = iemNativeEmitTestBitInGprAndJmpToLabelIfCc(pReNative, off, idxEflReg, iBitNo, pEntry->idxLabelElse,
                                                      !fCheckIfSet /*fJmpIfSet*/);
@@ -5845,27 +5890,29 @@
 #undef  IEM_MC_FETCH_EFLAGS /* should not be used */
 #define IEM_MC_FETCH_EFLAGS_EX(a_EFlags, a_fEflInput, a_fEflOutput) \
-    off = iemNativeEmitFetchEFlags(pReNative, off, a_EFlags, a_fEflInput, a_fEflOutput)
+    off = iemNativeEmitFetchEFlags<a_fEflInput,  iemNativeEflagsToLivenessMask<a_fEflInput>(),\
+                                   a_fEflOutput, iemNativeEflagsToLivenessMask<a_fEflOutput>()>(pReNative, off, a_EFlags)
 
 /** Handles IEM_MC_FETCH_EFLAGS_EX. */
-DECL_INLINE_THROW(uint32_t)
-iemNativeEmitFetchEFlags(PIEMRECOMPILERSTATE pReNative, uint32_t off, uint8_t idxVarEFlags,
-                         uint32_t fEflInput, uint32_t fEflOutput)
+template<uint32_t const a_fEflInput,  uint64_t const a_fLivenessEflInput,
+         uint32_t const a_fEflOutput, uint64_t const a_fLivenessEflOutput>
+DECL_INLINE_THROW(uint32_t)
+iemNativeEmitFetchEFlags(PIEMRECOMPILERSTATE pReNative, uint32_t off, uint8_t idxVarEFlags)
 {
     IEMNATIVE_ASSERT_VAR_IDX(pReNative, idxVarEFlags);
     IEMNATIVE_ASSERT_VAR_SIZE(pReNative, idxVarEFlags, sizeof(uint32_t));
-    RT_NOREF(fEflInput, fEflOutput);
+    /** @todo fix NOT AssertCompile(a_fEflInput != 0 || a_fEflOutput != 0); */
 
 #ifdef IEMNATIVE_WITH_LIVENESS_ANALYSIS
 # ifdef VBOX_STRICT
     if (   pReNative->idxCurCall != 0
-        && (fEflInput != 0 || fEflOutput != 0) /* for NOT these are both zero for now. */)
-    {
-        PCIEMLIVENESSENTRY const pLivenessEntry = &pReNative->paLivenessEntries[pReNative->idxCurCall - 1];
-        uint32_t const           fBoth          = fEflInput | fEflOutput;
+        && (a_fEflInput != 0 || a_fEflOutput != 0) /* for NOT these are both zero for now. */)
+    {
+        PCIEMLIVENESSENTRY const    pLivenessEntry = &pReNative->paLivenessEntries[pReNative->idxCurCall - 1];
+        RT_CONSTEXPR uint32_t const fBoth          = a_fEflInput | a_fEflOutput;
 # define ASSERT_ONE_EFL(a_fElfConst, a_idxField) \
             AssertMsg(   !(fBoth & (a_fElfConst)) \
-                      || (!(fEflInput & (a_fElfConst)) \
+                      || (!(a_fEflInput & (a_fElfConst)) \
                           ? IEMLIVENESS_STATE_IS_CLOBBER_EXPECTED(iemNativeLivenessGetStateByGstRegEx(pLivenessEntry, a_idxField)) \
-                          : !(fEflOutput & (a_fElfConst)) \
+                          : !(a_fEflOutput & (a_fElfConst)) \
                           ? IEMLIVENESS_STATE_IS_INPUT_EXPECTED(  iemNativeLivenessGetStateByGstRegEx(pLivenessEntry, a_idxField)) \
                           : IEMLIVENESS_STATE_IS_MODIFY_EXPECTED( iemNativeLivenessGetStateByGstRegEx(pLivenessEntry, a_idxField)) ), \
@@ -5883,5 +5930,5 @@
 #endif
 
-    IEMNATIVE_STRICT_EFLAGS_SKIPPING_EMIT_CHECK(pReNative, off, fEflInput);
+    IEMNATIVE_STRICT_EFLAGS_SKIPPING_EMIT_CHECK(pReNative, off, a_fEflInput);
 
     /** @todo This could be prettier...*/
@@ -5896,7 +5943,6 @@
          *        zero, but since iemNativeVarRegisterSet clears the shadowing,
          *        that's counter productive... */
-        uint8_t const idxGstReg = iemNativeRegAllocTmpForGuestReg(pReNative, &off, kIemNativeGstReg_EFlags,
-                                                                  kIemNativeGstRegUse_ForUpdate, false /*fNoVolatileRegs*/,
-                                                                  true /** @todo EFlags shadowing+liveness weirdness (@bugref{10720}). */);
+        uint8_t const idxGstReg = iemNativeRegAllocTmpForGuestEFlags(pReNative, &off, kIemNativeGstRegUse_ForUpdate,
+                                                                     a_fLivenessEflInput, a_fLivenessEflOutput);
         iemNativeVarRegisterSet(pReNative, idxVarEFlags, idxGstReg, off, true /*fAllocated*/);
     }
@@ -5905,5 +5951,6 @@
         /* Register argument variable: Avoid assertions in generic call code and load it the traditional way. */
         uint8_t const idxVarReg = iemNativeVarRegisterAcquire(pReNative, idxVarEFlags, &off, false /*fInitialized*/);
-        uint8_t const idxGstReg = iemNativeRegAllocTmpForGuestRegIfAlreadyPresent(pReNative, &off, kIemNativeGstReg_EFlags);
+        uint8_t const idxGstReg = iemNativeRegAllocTmpForGuestEFlagsIfAlreadyPresent(pReNative, &off,
+                                                                                     a_fLivenessEflInput, a_fLivenessEflOutput);
         if (idxGstReg != UINT8_MAX)
         {
@@ -5926,19 +5973,48 @@
 #define IEM_MC_COMMIT_EFLAGS_EX(a_EFlags, a_fEflInput, a_fEflOutput) \
     IEMNATIVE_EFLAGS_OPTIMIZATION_STATS(a_fEflInput, a_fEflOutput); \
-    off = iemNativeEmitCommitEFlags(pReNative, off, a_EFlags, a_fEflOutput, true /*fUpdateSkipping*/)
+    off = iemNativeEmitCommitEFlags<true /*fUpdateSkipping*/, a_fEflOutput, \
+                                    iemNativeEflagsToLivenessMask<a_fEflInput>(), \
+                                    iemNativeEflagsToLivenessMask<a_fEflOutput>()>(pReNative, off, a_EFlags)
 
 #undef IEM_MC_COMMIT_EFLAGS_OPT /* should not be used */
 #define IEM_MC_COMMIT_EFLAGS_OPT_EX(a_EFlags, a_fEflInput, a_fEflOutput) \
     IEMNATIVE_EFLAGS_OPTIMIZATION_STATS(a_fEflInput, a_fEflOutput); \
-    off = iemNativeEmitCommitEFlags(pReNative, off, a_EFlags, a_fEflOutput, false /*fUpdateSkipping*/)
+    off = iemNativeEmitCommitEFlags<false /*fUpdateSkipping*/, a_fEflOutput, \
+                                    iemNativeEflagsToLivenessMask<a_fEflInput>(), \
+                                    iemNativeEflagsToLivenessMask<a_fEflOutput>()>(pReNative, off, a_EFlags)
 
 /** Handles IEM_MC_COMMIT_EFLAGS_EX. */
-DECL_INLINE_THROW(uint32_t)
-iemNativeEmitCommitEFlags(PIEMRECOMPILERSTATE pReNative, uint32_t off, uint8_t idxVarEFlags, uint32_t fEflOutput,
-                          bool fUpdateSkipping)
-{
-    RT_NOREF(fEflOutput);
+template<bool const a_fUpdateSkipping, uint32_t const a_fEflOutput,
+         uint64_t const a_fLivenessEflInputBits, uint64_t const a_fLivenessEflOutputBits>
+DECL_INLINE_THROW(uint32_t) iemNativeEmitCommitEFlags(PIEMRECOMPILERSTATE pReNative, uint32_t off, uint8_t idxVarEFlags)
+{
     uint8_t const idxReg = iemNativeVarRegisterAcquire(pReNative, idxVarEFlags, &off, true /*fInitialized*/);
     IEMNATIVE_ASSERT_VAR_SIZE(pReNative, idxVarEFlags, sizeof(uint32_t));
+
+#ifdef IEMNATIVE_WITH_LIVENESS_ANALYSIS
+# ifdef VBOX_STRICT
+    if (   pReNative->idxCurCall != 0
+        && (a_fLivenessEflInputBits != 0 || a_fLivenessEflOutputBits != 0) /* for NOT these are both zero for now. */)
+    {
+        PCIEMLIVENESSENTRY const pLivenessEntry = &pReNative->paLivenessEntries[pReNative->idxCurCall - 1];
+# define ASSERT_ONE_EFL(a_idxField) \
+            if RT_CONSTEXPR_IF(((a_fLivenessEflInputBits | a_fLivenessEflOutputBits) & RT_BIT_64(a_idxField)) != 0) \
+                AssertMsg(!(a_fLivenessEflInputBits & RT_BIT_64(a_idxField)) \
+                          ? IEMLIVENESS_STATE_IS_CLOBBER_EXPECTED(iemNativeLivenessGetStateByGstRegEx(pLivenessEntry, a_idxField)) \
+                          : !(a_fLivenessEflOutputBits & RT_BIT_64(a_idxField)) \
+                          ? IEMLIVENESS_STATE_IS_INPUT_EXPECTED(  iemNativeLivenessGetStateByGstRegEx(pLivenessEntry, a_idxField)) \
+                          : IEMLIVENESS_STATE_IS_MODIFY_EXPECTED( iemNativeLivenessGetStateByGstRegEx(pLivenessEntry, a_idxField)), \
+                          ("%s - %u\n", #a_idxField, iemNativeLivenessGetStateByGstRegEx(pLivenessEntry, a_idxField)))
+        ASSERT_ONE_EFL(IEMLIVENESSBIT_IDX_EFL_OTHER);
+        ASSERT_ONE_EFL(IEMLIVENESSBIT_IDX_EFL_CF);
+        ASSERT_ONE_EFL(IEMLIVENESSBIT_IDX_EFL_PF);
+        ASSERT_ONE_EFL(IEMLIVENESSBIT_IDX_EFL_AF);
+        ASSERT_ONE_EFL(IEMLIVENESSBIT_IDX_EFL_ZF);
+        ASSERT_ONE_EFL(IEMLIVENESSBIT_IDX_EFL_SF);
+        ASSERT_ONE_EFL(IEMLIVENESSBIT_IDX_EFL_OF);
+# undef ASSERT_ONE_EFL
+    }
+# endif
+#endif
 
 #ifdef VBOX_STRICT
@@ -5955,18 +6031,16 @@
     iemNativeFixupFixedJump(pReNative, offFixup, off);
 
-    /** @todo validate that only bits in the fElfOutput mask changed. */
+    /** @todo validate that only bits in the a_fEflOutput mask changed. */
 #endif
 
 #ifdef IEMNATIVE_STRICT_EFLAGS_SKIPPING
-    if (fUpdateSkipping)
-    {
-        if ((fEflOutput & X86_EFL_STATUS_BITS) == X86_EFL_STATUS_BITS)
+    if RT_CONSTEXPR_IF(a_fUpdateSkipping)
+    {
+        if RT_CONSTEXPR_IF((a_fEflOutput & X86_EFL_STATUS_BITS) == X86_EFL_STATUS_BITS)
             off = iemNativeEmitStoreImmToVCpuU32(pReNative, off, 0, RT_UOFFSETOF(VMCPU, iem.s.fSkippingEFlags));
         else
-            off = iemNativeEmitAndImmIntoVCpuU32(pReNative, off, ~(fEflOutput & X86_EFL_STATUS_BITS),
+            off = iemNativeEmitAndImmIntoVCpuU32(pReNative, off, ~(a_fEflOutput & X86_EFL_STATUS_BITS),
                                                  RT_UOFFSETOF(VMCPU, iem.s.fSkippingEFlags));
     }
-#else
-    RT_NOREF_PV(fUpdateSkipping);
 #endif
 
@@ -5986,27 +6060,27 @@
 
 #define IEM_MC_SET_EFL_BIT(a_fBit) \
-    off = iemNativeEmitModifyEFlagsBit<kIemNativeEmitEflOp_Set>(pReNative, off, a_fBit)
+    off = iemNativeEmitModifyEFlagsBit<kIemNativeEmitEflOp_Set,   a_fBit, iemNativeEflagsToLivenessMask<a_fBit>()>(pReNative, off)
 
 #define IEM_MC_CLEAR_EFL_BIT(a_fBit) \
-    off = iemNativeEmitModifyEFlagsBit<kIemNativeEmitEflOp_Clear>(pReNative, off, a_fBit)
+    off = iemNativeEmitModifyEFlagsBit<kIemNativeEmitEflOp_Clear, a_fBit, iemNativeEflagsToLivenessMask<a_fBit>()>(pReNative, off)
 
 #define IEM_MC_FLIP_EFL_BIT(a_fBit) \
-    off = iemNativeEmitModifyEFlagsBit<kIemNativeEmitEflOp_Flip>(pReNative, off, a_fBit)
+    off = iemNativeEmitModifyEFlagsBit<kIemNativeEmitEflOp_Flip,  a_fBit, iemNativeEflagsToLivenessMask<a_fBit>()>(pReNative, off)
 
 /** Handles IEM_MC_SET_EFL_BIT/IEM_MC_CLEAR_EFL_BIT/IEM_MC_FLIP_EFL_BIT. */
-template<IEMNATIVEMITEFLOP const a_enmOp>
-DECL_INLINE_THROW(uint32_t) iemNativeEmitModifyEFlagsBit(PIEMRECOMPILERSTATE pReNative, uint32_t off, uint32_t fEflBit)
-{
-    uint8_t const idxEflReg = iemNativeRegAllocTmpForGuestReg(pReNative, &off, kIemNativeGstReg_EFlags,
-                                                              kIemNativeGstRegUse_ForUpdate, false /*fNoVolatileRegs*/,
-                                                              true /*fSkipLivenessAssert*/); /** @todo proper liveness / eflags fix */
+template<IEMNATIVEMITEFLOP const a_enmOp, uint32_t const a_fEflBit, uint64_t const a_fLivenessEflBit>
+DECL_INLINE_THROW(uint32_t) iemNativeEmitModifyEFlagsBit(PIEMRECOMPILERSTATE pReNative, uint32_t off)
+{
+    uint8_t const idxEflReg = iemNativeRegAllocTmpForGuestEFlags(pReNative, &off, kIemNativeGstRegUse_ForUpdate,
+                                                                 a_enmOp == kIemNativeEmitEflOp_Flip ? a_fLivenessEflBit : 0,
+                                                                 a_fLivenessEflBit);
 
     /* Using 'if constexpr' forces code elimination in debug builds with VC. */
     if RT_CONSTEXPR_IF(a_enmOp == kIemNativeEmitEflOp_Set)
-        off = iemNativeEmitOrGpr32ByImm(pReNative, off, idxEflReg, fEflBit);
+        off = iemNativeEmitOrGpr32ByImm(pReNative, off, idxEflReg, a_fEflBit);
     else if RT_CONSTEXPR_IF(a_enmOp == kIemNativeEmitEflOp_Clear)
-        off = iemNativeEmitAndGpr32ByImm(pReNative, off, idxEflReg, ~fEflBit);
+        off = iemNativeEmitAndGpr32ByImm(pReNative, off, idxEflReg, ~a_fEflBit);
     else if RT_CONSTEXPR_IF(a_enmOp == kIemNativeEmitEflOp_Flip)
-        off = iemNativeEmitXorGpr32ByImm(pReNative, off, idxEflReg, fEflBit);
+        off = iemNativeEmitXorGpr32ByImm(pReNative, off, idxEflReg, a_fEflBit);
     else
         AssertCompile(   a_enmOp == kIemNativeEmitEflOp_Set /* AssertCompile(false) works with VC 2019 but not clang 15. */
Index: trunk/src/VBox/VMM/VMMAll/IEMAllN8veRecompiler.cpp
===================================================================
--- trunk/src/VBox/VMM/VMMAll/IEMAllN8veRecompiler.cpp	(revision 106101)
+++ trunk/src/VBox/VMM/VMMAll/IEMAllN8veRecompiler.cpp	(revision 106113)
@@ -3567,46 +3567,14 @@
 
 /**
- * Allocates a temporary host general purpose register for keeping a guest
- * register value.
- *
- * Since we may already have a register holding the guest register value,
- * code will be emitted to do the loading if that's not the case. Code may also
- * be emitted if we have to free up a register to satify the request.
- *
- * @returns The host register number; throws VBox status code on failure, so no
- *          need to check the return value.
- * @param   pReNative       The native recompile state.
- * @param   poff            Pointer to the variable with the code buffer
- *                          position. This will be update if we need to move a
- *                          variable from register to stack in order to satisfy
- *                          the request.
- * @param   enmGstReg       The guest register that will is to be updated.
- * @param   enmIntendedUse  How the caller will be using the host register.
- * @param   fNoVolatileRegs Set if no volatile register allowed, clear if any
- *                          register is okay (default).  The ASSUMPTION here is
- *                          that the caller has already flushed all volatile
- *                          registers, so this is only applied if we allocate a
- *                          new register.
- * @param   fSkipLivenessAssert     Hack for liveness input validation of EFLAGS.
- * @sa      iemNativeRegAllocTmpForGuestRegIfAlreadyPresent
- */
-DECL_HIDDEN_THROW(uint8_t)
-iemNativeRegAllocTmpForGuestReg(PIEMRECOMPILERSTATE pReNative, uint32_t *poff, IEMNATIVEGSTREG enmGstReg,
-                                IEMNATIVEGSTREGUSE enmIntendedUse /*= kIemNativeGstRegUse_ReadOnly*/,
-                                bool fNoVolatileRegs /*= false*/, bool fSkipLivenessAssert /*= false*/)
+ * Common worker for iemNativeRegAllocTmpForGuestReg() and
+ * iemNativeRegAllocTmpForGuestEFlags().
+ *
+ * See iemNativeRegAllocTmpForGuestReg() for details.
+ */
+static uint8_t
+iemNativeRegAllocTmpForGuestRegCommon(PIEMRECOMPILERSTATE pReNative, uint32_t *poff, IEMNATIVEGSTREG enmGstReg,
+                                      IEMNATIVEGSTREGUSE enmIntendedUse, bool fNoVolatileRegs)
 {
     Assert(enmGstReg < kIemNativeGstReg_End && g_aGstShadowInfo[enmGstReg].cb != 0);
-#ifdef IEMNATIVE_WITH_LIVENESS_ANALYSIS
-    AssertMsg(   fSkipLivenessAssert
-              || pReNative->idxCurCall == 0
-              || enmGstReg == kIemNativeGstReg_Pc
-              || (enmIntendedUse == kIemNativeGstRegUse_ForFullWrite
-                  ? IEMLIVENESS_STATE_IS_CLOBBER_EXPECTED(iemNativeLivenessGetPrevStateByGstReg(pReNative, enmGstReg))
-                  : enmIntendedUse == kIemNativeGstRegUse_ForUpdate
-                  ? IEMLIVENESS_STATE_IS_MODIFY_EXPECTED( iemNativeLivenessGetPrevStateByGstReg(pReNative, enmGstReg))
-                  : IEMLIVENESS_STATE_IS_INPUT_EXPECTED(  iemNativeLivenessGetPrevStateByGstReg(pReNative, enmGstReg)) ),
-              ("%s - %u\n", g_aGstShadowInfo[enmGstReg].pszName, iemNativeLivenessGetPrevStateByGstReg(pReNative, enmGstReg)));
-#endif
-    RT_NOREF(fSkipLivenessAssert);
 #if defined(LOG_ENABLED) || defined(VBOX_STRICT)
     static const char * const s_pszIntendedUse[] = { "fetch", "update", "full write", "destructive calc" };
@@ -3786,35 +3754,106 @@
 
 /**
- * Allocates a temporary host general purpose register that already holds the
- * given guest register value.
- *
- * The use case for this function is places where the shadowing state cannot be
- * modified due to branching and such.  This will fail if the we don't have a
- * current shadow copy handy or if it's incompatible.  The only code that will
- * be emitted here is value checking code in strict builds.
- *
- * The intended use can only be readonly!
- *
- * @returns The host register number, UINT8_MAX if not present.
+ * Allocates a temporary host general purpose register for keeping a guest
+ * register value.
+ *
+ * Since we may already have a register holding the guest register value,
+ * code will be emitted to do the loading if that's not the case. Code may also
+ * be emitted if we have to free up a register to satify the request.
+ *
+ * @returns The host register number; throws VBox status code on failure, so no
+ *          need to check the return value.
  * @param   pReNative       The native recompile state.
- * @param   poff            Pointer to the instruction buffer offset.
- *                          Will be updated in strict builds if a register is
- *                          found.
+ * @param   poff            Pointer to the variable with the code buffer
+ *                          position. This will be update if we need to move a
+ *                          variable from register to stack in order to satisfy
+ *                          the request.
  * @param   enmGstReg       The guest register that will is to be updated.
- * @note    In strict builds, this may throw instruction buffer growth failures.
- *          Non-strict builds will not throw anything.
- * @sa iemNativeRegAllocTmpForGuestReg
+ * @param   enmIntendedUse  How the caller will be using the host register.
+ * @param   fNoVolatileRegs Set if no volatile register allowed, clear if any
+ *                          register is okay (default).  The ASSUMPTION here is
+ *                          that the caller has already flushed all volatile
+ *                          registers, so this is only applied if we allocate a
+ *                          new register.
+ * @param   fSkipLivenessAssert     Hack for liveness input validation of EFLAGS.
+ * @sa      iemNativeRegAllocTmpForGuestRegIfAlreadyPresent
  */
 DECL_HIDDEN_THROW(uint8_t)
-iemNativeRegAllocTmpForGuestRegIfAlreadyPresent(PIEMRECOMPILERSTATE pReNative, uint32_t *poff, IEMNATIVEGSTREG enmGstReg)
+iemNativeRegAllocTmpForGuestReg(PIEMRECOMPILERSTATE pReNative, uint32_t *poff, IEMNATIVEGSTREG enmGstReg,
+                                IEMNATIVEGSTREGUSE enmIntendedUse /*= kIemNativeGstRegUse_ReadOnly*/,
+                                bool fNoVolatileRegs /*= false*/, bool fSkipLivenessAssert /*= false*/)
+{
+#ifdef IEMNATIVE_WITH_LIVENESS_ANALYSIS
+    AssertMsg(   fSkipLivenessAssert
+              || pReNative->idxCurCall == 0
+              || enmGstReg == kIemNativeGstReg_Pc
+              || (enmIntendedUse == kIemNativeGstRegUse_ForFullWrite
+                  ? IEMLIVENESS_STATE_IS_CLOBBER_EXPECTED(iemNativeLivenessGetPrevStateByGstReg(pReNative, enmGstReg))
+                  : enmIntendedUse == kIemNativeGstRegUse_ForUpdate
+                  ? IEMLIVENESS_STATE_IS_MODIFY_EXPECTED( iemNativeLivenessGetPrevStateByGstReg(pReNative, enmGstReg))
+                  : IEMLIVENESS_STATE_IS_INPUT_EXPECTED(  iemNativeLivenessGetPrevStateByGstReg(pReNative, enmGstReg)) ),
+              ("%s - %u\n", g_aGstShadowInfo[enmGstReg].pszName, iemNativeLivenessGetPrevStateByGstReg(pReNative, enmGstReg)));
+#endif
+    RT_NOREF(fSkipLivenessAssert);
+
+    return iemNativeRegAllocTmpForGuestRegCommon(pReNative, poff, enmGstReg, enmIntendedUse, fNoVolatileRegs);
+}
+
+
+#if defined(IEMNATIVE_WITH_LIVENESS_ANALYSIS) && defined(VBOX_STRICT)
+/**
+ * Specialized version of iemNativeRegAllocTmpForGuestReg for EFLAGS.
+ *
+ * This takes additional arguments for covering liveness assertions in strict
+ * builds, it's otherwise the same as iemNativeRegAllocTmpForGuestReg() with
+ * kIemNativeGstReg_EFlags as argument.
+ */
+DECL_HIDDEN_THROW(uint8_t)
+iemNativeRegAllocTmpForGuestEFlags(PIEMRECOMPILERSTATE pReNative, uint32_t *poff, IEMNATIVEGSTREGUSE enmIntendedUse,
+                                   uint64_t fRead, uint64_t fWrite /*= 0*/, uint64_t fPotentialCall /*= 0*/)
+{
+    if (pReNative->idxCurCall != 0 && (fRead || fWrite /*|| fPotentialCall*/))
+    {
+        Assert(!(fRead & ~IEMLIVENESSBIT_ALL_EFL_MASK));
+        Assert(!(fWrite & ~IEMLIVENESSBIT_ALL_EFL_MASK));
+        Assert(!(fPotentialCall & ~IEMLIVENESSBIT_ALL_EFL_MASK));
+        uint64_t const fAll = fRead | fWrite /*| fPotentialCall*/;
+        uint32_t       fState;
+# define MY_ASSERT_ONE_EFL(a_enmGstEfl) \
+        fState = iemNativeLivenessGetPrevStateByGstRegEx(pReNative, (IEMNATIVEGSTREG)(a_enmGstEfl)); \
+        AssertMsg(   !( fAll   & RT_BIT_64(a_enmGstEfl)) \
+                  || (  fRead  & RT_BIT_64(a_enmGstEfl) \
+                      ? fWrite & RT_BIT_64(a_enmGstEfl) \
+                        ? IEMLIVENESS_STATE_IS_MODIFY_EXPECTED(fState) \
+                        : IEMLIVENESS_STATE_IS_INPUT_EXPECTED(fState) \
+                      : IEMLIVENESS_STATE_IS_CLOBBER_EXPECTED(fState) \
+                      ) \
+                  , ("%s - %u\n", #a_enmGstEfl, fState))
+        MY_ASSERT_ONE_EFL(IEMLIVENESSBIT_IDX_EFL_OTHER);
+        MY_ASSERT_ONE_EFL(IEMLIVENESSBIT_IDX_EFL_CF);
+        MY_ASSERT_ONE_EFL(IEMLIVENESSBIT_IDX_EFL_PF);
+        MY_ASSERT_ONE_EFL(IEMLIVENESSBIT_IDX_EFL_AF);
+        MY_ASSERT_ONE_EFL(IEMLIVENESSBIT_IDX_EFL_ZF);
+        MY_ASSERT_ONE_EFL(IEMLIVENESSBIT_IDX_EFL_SF);
+        MY_ASSERT_ONE_EFL(IEMLIVENESSBIT_IDX_EFL_OF);
+# undef MY_ASSERT_ONE_EFL
+    }
+    RT_NOREF(fPotentialCall);
+    return iemNativeRegAllocTmpForGuestRegCommon(pReNative, poff, kIemNativeGstReg_EFlags,
+                                                 enmIntendedUse, false /*fNoVolatileRegs*/);
+}
+#endif
+
+
+
+/**
+ * Common worker for iemNativeRegAllocTmpForGuestRegIfAlreadyPresent and
+ * iemNativeRegAllocTmpForGuestEFlagsIfAlreadyPresent.
+ *
+ * See iemNativeRegAllocTmpForGuestRegIfAlreadyPresent() for details.
+ */
+DECL_FORCE_INLINE(uint8_t)
+iemNativeRegAllocTmpForGuestRegIfAlreadyPresentCommon(PIEMRECOMPILERSTATE pReNative, uint32_t *poff, IEMNATIVEGSTREG enmGstReg)
 {
     Assert(enmGstReg < kIemNativeGstReg_End && g_aGstShadowInfo[enmGstReg].cb != 0);
-#ifdef IEMNATIVE_WITH_LIVENESS_ANALYSIS
-    AssertMsg(   pReNative->idxCurCall == 0
-              || IEMLIVENESS_STATE_IS_INPUT_EXPECTED(iemNativeLivenessGetPrevStateByGstReg(pReNative, enmGstReg))
-              || enmGstReg == kIemNativeGstReg_Pc
-              || enmGstReg == kIemNativeGstReg_EFlags /** @todo EFlags shadowing+liveness is weird and needs fixing (@bugref{10720}) */,
-              ("%s - %u\n", g_aGstShadowInfo[enmGstReg].pszName, iemNativeLivenessGetPrevStateByGstReg(pReNative, enmGstReg)));
-#endif
 
     /*
@@ -3852,4 +3891,88 @@
     return UINT8_MAX;
 }
+
+
+/**
+ * Allocates a temporary host general purpose register that already holds the
+ * given guest register value.
+ *
+ * The use case for this function is places where the shadowing state cannot be
+ * modified due to branching and such.  This will fail if the we don't have a
+ * current shadow copy handy or if it's incompatible.  The only code that will
+ * be emitted here is value checking code in strict builds.
+ *
+ * The intended use can only be readonly!
+ *
+ * @returns The host register number, UINT8_MAX if not present.
+ * @param   pReNative       The native recompile state.
+ * @param   poff            Pointer to the instruction buffer offset.
+ *                          Will be updated in strict builds if a register is
+ *                          found.
+ * @param   enmGstReg       The guest register that will is to be updated.
+ * @note    In strict builds, this may throw instruction buffer growth failures.
+ *          Non-strict builds will not throw anything.
+ * @sa iemNativeRegAllocTmpForGuestReg
+ */
+DECL_HIDDEN_THROW(uint8_t)
+iemNativeRegAllocTmpForGuestRegIfAlreadyPresent(PIEMRECOMPILERSTATE pReNative, uint32_t *poff, IEMNATIVEGSTREG enmGstReg)
+{
+#ifdef IEMNATIVE_WITH_LIVENESS_ANALYSIS
+    AssertMsg(   pReNative->idxCurCall == 0
+              || IEMLIVENESS_STATE_IS_INPUT_EXPECTED(iemNativeLivenessGetPrevStateByGstReg(pReNative, enmGstReg))
+              || enmGstReg == kIemNativeGstReg_Pc
+              , ("%s - %u\n", g_aGstShadowInfo[enmGstReg].pszName, iemNativeLivenessGetPrevStateByGstReg(pReNative, enmGstReg)));
+#endif
+    return iemNativeRegAllocTmpForGuestRegIfAlreadyPresentCommon(pReNative, poff, enmGstReg);
+}
+
+
+#if defined(IEMNATIVE_WITH_LIVENESS_ANALYSIS) && defined(VBOX_STRICT)
+/**
+ * Specialized version of iemNativeRegAllocTmpForGuestRegIfAlreadyPresent for
+ * EFLAGS.
+ *
+ * This takes additional arguments for covering liveness assertions in strict
+ * builds, it's otherwise the same as
+ * iemNativeRegAllocTmpForGuestRegIfAlreadyPresent() with
+ * kIemNativeGstReg_EFlags as argument.
+ *
+ * @note The @a fWrite parameter is necessary to complete the liveness picture,
+ *       as iemNativeEmitFetchEFlags() may fetch flags in prep for a later
+ *       commit.  It the operation clobbers all the flags, @a fRead will be
+ *       zero, so better verify the whole picture while we're here.
+ */
+DECL_HIDDEN_THROW(uint8_t) iemNativeRegAllocTmpForGuestEFlagsIfAlreadyPresent(PIEMRECOMPILERSTATE pReNative, uint32_t *poff,
+                                                                              uint64_t fRead, uint64_t fWrite /*=0*/)
+{
+    if (pReNative->idxCurCall != 0)
+    {
+        Assert(fRead | fWrite);
+        Assert(!(fRead & ~IEMLIVENESSBIT_ALL_EFL_MASK));
+        Assert(!(fWrite & ~IEMLIVENESSBIT_ALL_EFL_MASK));
+        uint64_t const fAll = fRead | fWrite;
+        uint32_t       fState;
+# define MY_ASSERT_ONE_EFL(a_enmGstEfl) \
+        fState = iemNativeLivenessGetPrevStateByGstRegEx(pReNative, (IEMNATIVEGSTREG)(a_enmGstEfl)); \
+        AssertMsg(   !( fAll   & RT_BIT_64(a_enmGstEfl)) \
+                  || (  fRead  & RT_BIT_64(a_enmGstEfl) \
+                      ? fWrite & RT_BIT_64(a_enmGstEfl) \
+                        ? IEMLIVENESS_STATE_IS_MODIFY_EXPECTED(fState) \
+                        : IEMLIVENESS_STATE_IS_INPUT_EXPECTED(fState) \
+                      : IEMLIVENESS_STATE_IS_CLOBBER_EXPECTED(fState) \
+                      ) \
+                  , ("%s - %u\n", #a_enmGstEfl, fState))
+        MY_ASSERT_ONE_EFL(IEMLIVENESSBIT_IDX_EFL_OTHER);
+        MY_ASSERT_ONE_EFL(IEMLIVENESSBIT_IDX_EFL_CF);
+        MY_ASSERT_ONE_EFL(IEMLIVENESSBIT_IDX_EFL_PF);
+        MY_ASSERT_ONE_EFL(IEMLIVENESSBIT_IDX_EFL_AF);
+        MY_ASSERT_ONE_EFL(IEMLIVENESSBIT_IDX_EFL_ZF);
+        MY_ASSERT_ONE_EFL(IEMLIVENESSBIT_IDX_EFL_SF);
+        MY_ASSERT_ONE_EFL(IEMLIVENESSBIT_IDX_EFL_OF);
+# undef MY_ASSERT_ONE_EFL
+    }
+    RT_NOREF(fRead);
+    return iemNativeRegAllocTmpForGuestRegIfAlreadyPresentCommon(pReNative, poff, kIemNativeGstReg_EFlags);
+}
+#endif
 
 
Index: trunk/src/VBox/VMM/include/IEMN8veRecompiler.h
===================================================================
--- trunk/src/VBox/VMM/include/IEMN8veRecompiler.h	(revision 106101)
+++ trunk/src/VBox/VMM/include/IEMN8veRecompiler.h	(revision 106113)
@@ -1822,6 +1822,32 @@
                                                             IEMNATIVEGSTREGUSE enmIntendedUse = kIemNativeGstRegUse_ReadOnly,
                                                             bool fNoVolatileRegs = false, bool fSkipLivenessAssert = false);
+#if defined(IEMNATIVE_WITH_LIVENESS_ANALYSIS) && defined(VBOX_STRICT)
+DECL_HIDDEN_THROW(uint8_t)  iemNativeRegAllocTmpForGuestEFlags(PIEMRECOMPILERSTATE pReNative, uint32_t *poff,
+                                                               IEMNATIVEGSTREGUSE enmIntendedUse, uint64_t fRead,
+                                                               uint64_t fWrite = 0, uint64_t fPotentialCall = 0);
+#else
+DECL_FORCE_INLINE_THROW(uint8_t)
+iemNativeRegAllocTmpForGuestEFlags(PIEMRECOMPILERSTATE pReNative, uint32_t *poff, IEMNATIVEGSTREGUSE enmIntendedUse,
+                                   uint64_t fRead, uint64_t fWrite = 0, uint64_t fPotentialCall = 0)
+{
+    RT_NOREF(fRead, fWrite, fPotentialCall);
+    return iemNativeRegAllocTmpForGuestReg(pReNative, poff, kIemNativeGstReg_EFlags, enmIntendedUse);
+}
+#endif
+
 DECL_HIDDEN_THROW(uint8_t)  iemNativeRegAllocTmpForGuestRegIfAlreadyPresent(PIEMRECOMPILERSTATE pReNative, uint32_t *poff,
                                                                             IEMNATIVEGSTREG enmGstReg);
+#if defined(IEMNATIVE_WITH_LIVENESS_ANALYSIS) && defined(VBOX_STRICT)
+DECL_HIDDEN_THROW(uint8_t)  iemNativeRegAllocTmpForGuestEFlagsIfAlreadyPresent(PIEMRECOMPILERSTATE pReNative, uint32_t *poff,
+                                                                               uint64_t fRead, uint64_t fWrite = 0);
+#else
+DECL_FORCE_INLINE_THROW(uint8_t)
+iemNativeRegAllocTmpForGuestEFlagsIfAlreadyPresent(PIEMRECOMPILERSTATE pReNative, uint32_t *poff,
+                                                   uint64_t fRead, uint64_t fWrite = 0)
+{
+    RT_NOREF(fRead, fWrite);
+    return iemNativeRegAllocTmpForGuestRegIfAlreadyPresent(pReNative, poff, kIemNativeGstReg_EFlags);
+}
+#endif
 
 DECL_HIDDEN_THROW(uint32_t) iemNativeRegAllocArgs(PIEMRECOMPILERSTATE pReNative, uint32_t off, uint8_t cArgs);
@@ -2352,6 +2378,6 @@
 }
 
-
 # ifdef VBOX_STRICT
+
 /** For assertions only - caller checks that idxCurCall isn't zero. */
 DECL_FORCE_INLINE(uint32_t)
@@ -2360,6 +2386,14 @@
     return iemNativeLivenessGetStateByGstReg(&pReNative->paLivenessEntries[pReNative->idxCurCall - 1], enmGstReg);
 }
+
+
+/** For assertions only - caller checks that idxCurCall isn't zero. */
+DECL_FORCE_INLINE(uint32_t)
+iemNativeLivenessGetPrevStateByGstRegEx(PIEMRECOMPILERSTATE pReNative, IEMNATIVEGSTREG enmGstReg)
+{
+    return iemNativeLivenessGetStateByGstRegEx(&pReNative->paLivenessEntries[pReNative->idxCurCall - 1], enmGstReg);
+}
+
 # endif /* VBOX_STRICT */
-
 #endif /* IEMNATIVE_WITH_LIVENESS_ANALYSIS */
 
