Index: /trunk/src/VBox/VMM/VMMAll/IEMAllInstructionsOneByte.cpp.h
===================================================================
--- /trunk/src/VBox/VMM/VMMAll/IEMAllInstructionsOneByte.cpp.h	(revision 66112)
+++ /trunk/src/VBox/VMM/VMMAll/IEMAllInstructionsOneByte.cpp.h	(revision 66113)
@@ -52,5 +52,5 @@
  * @opstats     add_Eb_Gb
  * @opgroup     op_gen_arith_bin
- * @optest      op1=1 op2=1 -> op1=2 efl=of,sf,zf,af
+ * @optest      op1=1 op2=1 -> op1=2 efl&|=nv,pl,nz,na,pe
  */
 FNIEMOP_DEF(iemOp_add_Eb_Gb)
@@ -101,5 +101,5 @@
  * @opgroup     op_gen_arith_bin
  * @opflmodify  of,sf,zf,af,pf,cf
- * @optest      op1=1 op2=1 -> op1=2 efl=of,sf,zf,af
+ * @optest      op1=1 op2=1 -> op1=2 efl&|=nv,pl,nz,na,pe
  */
 FNIEMOP_DEF(iemOp_add_Al_Ib)
@@ -114,5 +114,5 @@
  * @opgroup     op_gen_arith_bin
  * @opflmodify  of,sf,zf,af,pf,cf
- * @optest      op1=1 op2=1 -> op1=2 efl=of,sf,zf,af
+ * @optest      op1=1 op2=1 -> op1=2 efl&|=nv,pl,nz,na,pe
  */
 FNIEMOP_DEF(iemOp_add_eAX_Iz)
@@ -297,6 +297,6 @@
  * @opfltest    cf
  * @opflmodify  of,sf,zf,af,pf,cf
- * @optest      op1=1 op2=1 efl&~=cf -> op1=2 efl&|=of,sf,zf,af
- * @optest      op1=1 op2=1 efl|=cf  -> op1=3 efl&|=of,sf,zf,af
+ * @optest      op1=1 op2=1 efl&~=cf -> op1=2 efl&|=nc,nv,pl,nz,na,pe
+ * @optest      op1=1 op2=1 efl|=cf  -> op1=3 efl&|=nc,nv,pl,nz,na,po
  */
 FNIEMOP_DEF(iemOp_adc_Eb_Gb)
Index: /trunk/src/VBox/VMM/VMMAll/IEMAllInstructionsPython.py
===================================================================
--- /trunk/src/VBox/VMM/VMMAll/IEMAllInstructionsPython.py	(revision 66112)
+++ /trunk/src/VBox/VMM/VMMAll/IEMAllInstructionsPython.py	(revision 66113)
@@ -74,4 +74,50 @@
     'X86_EFL_LIVE_MASK':   0x003f7fd5, # UINT32_C(0x003f7fd5)
     'X86_EFL_RA1_MASK':    0x00000002, # RT_BIT_32(1)
+};
+
+## EFlags values allowed in \@opfltest, \@opflmodify, \@opflundef, \@opflset, and \@opflclear.
+g_kdEFlagsMnemonics = {
+    # Debugger flag notation:
+    'ov':   'X86_EFL_OF',   ##< OVerflow.
+    'nv':  '!X86_EFL_OF',   ##< No Overflow.
+
+    'ng':   'X86_EFL_SF',   ##< NeGative (sign).
+    'pl':  '!X86_EFL_SF',   ##< PLuss (sign).
+
+    'zr':   'X86_EFL_ZF',   ##< ZeRo.
+    'nz':  '!X86_EFL_ZF',   ##< No Zero.
+
+    'af':   'X86_EFL_AF',   ##< Aux Flag.
+    'na':  '!X86_EFL_AF',   ##< No Aux.
+
+    'po':   'X86_EFL_PF',   ##< Parity Pdd.
+    'pe':  '!X86_EFL_PF',   ##< Parity Even.
+
+    'cf':   'X86_EFL_CF',   ##< Carry Flag.
+    'nc':  '!X86_EFL_CF',   ##< No Carry.
+
+    'ei':   'X86_EFL_IF',   ##< Enabled Interrupts.
+    'di':  '!X86_EFL_IF',   ##< Disabled Interrupts.
+
+    'dn':   'X86_EFL_DF',   ##< DowN (string op direction).
+    'up':  '!X86_EFL_DF',   ##< UP (string op direction).
+
+    'vip':  'X86_EFL_VIP',  ##< Virtual Interrupt Pending.
+    'vif':  'X86_EFL_VIF',  ##< Virtual Interrupt Flag.
+    'ac':   'X86_EFL_AC',   ##< Alignment Check.
+    'vm':   'X86_EFL_VM',   ##< Virtual-8086 Mode.
+    'rf':   'X86_EFL_RF',   ##< Resume Flag.
+    'nt':   'X86_EFL_NT',   ##< Nested Task.
+    'tf':   'X86_EFL_TF',   ##< Trap flag.
+
+    # Reference manual notation:
+    'of':   'X86_EFL_OF',
+    'sf':   'X86_EFL_SF',
+    'zf':   'X86_EFL_ZF',
+    'pf':   'X86_EFL_PF',
+    'if':   'X86_EFL_IF',
+    'df':   'X86_EFL_DF',
+    'iopl': 'X86_EFL_IOPL',
+    'id':   'X86_EFL_ID',
 };
 
@@ -588,5 +634,5 @@
         fSet   = 0;
         for sFlag in sValue.split(','):
-            sConstant = SimpleParser.kdEFlags.get(sFlag, None);
+            sConstant = g_kdEFlagsMnemonics.get(sFlag, None);
             if sConstant is None:
                 raise self.BadValue('Unknown flag "%s" in "%s"' % (sFlag, sValue))
@@ -643,4 +689,5 @@
         # Flags.
         'efl':      ( 'efl',  '', ),
+        'efl_undef': ( 'uint',  '', ),
         # 8-bit GPRs.
         'al':       ( 'uint', '', ),
@@ -823,8 +870,8 @@
 
     def __init__(self, oInstr): # type: (InstructionTest, Instruction)
-        self.oInstr         = oInstr; # type: InstructionTest
-        self.aoInputs       = [];
-        self.aoOutputs      = [];
-        self.aoSelectors    = []; # type: list(TestSelector)
+        self.oInstr         = oInstr;   # type: InstructionTest
+        self.aoInputs       = [];       # type: TestInOut
+        self.aoOutputs      = [];       # type: TestInOut
+        self.aoSelectors    = [];       # type: list(TestSelector)
 
 
@@ -975,4 +1022,36 @@
         raise Exception('unsupported opcode byte spec "%s" for %s' % (sOpcode, self,));
 
+    @staticmethod
+    def _flagsToIntegerMask(asFlags):
+        """
+        Returns the integer mask value for asFlags.
+        """
+        uRet = 0;
+        if asFlags:
+            for sFlag in asFlags:
+                sConstant = g_kdEFlagsMnemonics[sFlag];
+                assert sConstant[0] != '!', sConstant
+                uRet |= g_kdX86EFlagsConstants[sConstant];
+        return uRet;
+
+    def getTestedFlagsMask(self):
+        """ Returns asFlTest into a integer mask value """
+        return self._flagsToIntegerMask(self.asFlTest);
+
+    def getModifiedFlagsMask(self):
+        """ Returns asFlModify into a integer mask value """
+        return self._flagsToIntegerMask(self.asFlModify);
+
+    def getUndefinedFlagsMask(self):
+        """ Returns asFlUndefined into a integer mask value """
+        return self._flagsToIntegerMask(self.asFlUndefined);
+
+    def getSetFlagsMask(self):
+        """ Returns asFlSet into a integer mask value """
+        return self._flagsToIntegerMask(self.asFlSet);
+
+    def getClearedFlagsMask(self):
+        """ Returns asFlClear into a integer mask value """
+        return self._flagsToIntegerMask(self.asFlClear);
 
 
@@ -1607,50 +1686,4 @@
         return True;
 
-    ## EFlags values allowed in \@opfltest, \@opflmodify, \@opflundef, \@opflset, and \@opflclear.
-    kdEFlags = {
-        # Debugger flag notation:
-        'ov':   'X86_EFL_OF',   ##< OVerflow.
-        'nv':  '!X86_EFL_OF',   ##< No Overflow.
-
-        'ng':   'X86_EFL_SF',   ##< NeGative (sign).
-        'pl':  '!X86_EFL_SF',   ##< PLuss (sign).
-
-        'zr':   'X86_EFL_ZF',   ##< ZeRo.
-        'nz':  '!X86_EFL_ZF',   ##< No Zero.
-
-        'af':   'X86_EFL_AF',   ##< Aux Flag.
-        'na':  '!X86_EFL_AF',   ##< No Aux.
-
-        'po':   'X86_EFL_PF',   ##< Parity Pdd.
-        'pe':  '!X86_EFL_PF',   ##< Parity Even.
-
-        'cf':   'X86_EFL_CF',   ##< Carry Flag.
-        'nc':  '!X86_EFL_CF',   ##< No Carry.
-
-        'ei':   'X86_EFL_IF',   ##< Enabled Interrupts.
-        'di':  '!X86_EFL_IF',   ##< Disabled Interrupts.
-
-        'dn':   'X86_EFL_DF',   ##< DowN (string op direction).
-        'up':  '!X86_EFL_DF',   ##< UP (string op direction).
-
-        'vip':  'X86_EFL_VIP',  ##< Virtual Interrupt Pending.
-        'vif':  'X86_EFL_VIF',  ##< Virtual Interrupt Flag.
-        'ac':   'X86_EFL_AC',   ##< Alignment Check.
-        'vm':   'X86_EFL_VM',   ##< Virtual-8086 Mode.
-        'rf':   'X86_EFL_RF',   ##< Resume Flag.
-        'nt':   'X86_EFL_NT',   ##< Nested Task.
-        'tf':   'X86_EFL_TF',   ##< Trap flag.
-
-        # Reference manual notation:
-        'of':   'X86_EFL_OF',
-        'sf':   'X86_EFL_SF',
-        'zf':   'X86_EFL_ZF',
-        'pf':   'X86_EFL_PF',
-        'if':   'X86_EFL_IF',
-        'df':   'X86_EFL_DF',
-        'iopl': 'X86_EFL_IOPL',
-        'id':   'X86_EFL_ID',
-    };
-
     ## EFlags tag to Instruction attribute name.
     kdOpFlagToAttr = {
@@ -1677,6 +1710,6 @@
             fRc = True;
             for iFlag, sFlag in enumerate(asFlags):
-                if sFlag not in self.kdEFlags:
-                    if sFlag.strip() in self.kdEFlags:
+                if sFlag not in g_kdEFlagsMnemonics:
+                    if sFlag.strip() in g_kdEFlagsMnemonics:
                         asFlags[iFlag] = sFlag.strip();
                     else:
@@ -1990,9 +2023,9 @@
                                             oItem = TestInOut(sField, sOp, sValue, sType);
                                         else:
-                                            self.errorComment(iTagLine, '%s: and-or %s value "%s" can only be used with the "="'
+                                            self.errorComment(iTagLine, '%s: and-or %s value "%s" can only be used with "&|="'
                                                                         % ( sTag, sDesc, sItem, ));
                                     else:
-                                        self.errorComment(iTagLine, '%s: invalid %s value "%s" in "%s" (type: %s)'
-                                                                    % ( sTag, sDesc, sValue, sItem, sType, ));
+                                        self.errorComment(iTagLine, '%s: invalid %s value "%s" in "%s" (type: %s): %s'
+                                                                    % ( sTag, sDesc, sValue, sItem, sType, oValid, ));
                                 else:
                                     self.errorComment(iTagLine, '%s: invalid %s type "%s" in "%s" (valid types: %s)'
Index: /trunk/src/VBox/ValidationKit/bootsectors/bs3-cpu-generated-1-data.py
===================================================================
--- /trunk/src/VBox/ValidationKit/bootsectors/bs3-cpu-generated-1-data.py	(revision 66112)
+++ /trunk/src/VBox/ValidationKit/bootsectors/bs3-cpu-generated-1-data.py	(revision 66113)
@@ -104,4 +104,37 @@
 
     @staticmethod
+    def _amendOutputs(aoOutputs, oInstr): # type: (list(iai.TestInOut), iai.Instruction) -> list(iai.TestInOut)
+        """
+        Amends aoOutputs for instructions with special flag behaviour (undefined,
+        always set, always clear).
+
+        Undefined flags are copied from the result context as the very first
+        operation so they can be set to CPU vendor specific values later if
+        desired.
+
+        Always set or cleared flags are applied at the very end of the
+        modification operations so that we spot incorrect specifications.
+        """
+        if oInstr.asFlUndefined or oInstr.asFlClear or oInstr.asFlSet:
+            aoOutputs = list(aoOutputs);
+
+            if oInstr.asFlUndefined:
+                fFlags = oInstr.getUndefinedFlagsMask();
+                assert fFlags != 0;
+                aoOutputs.insert(0, iai.TestInOut('efl_undef', '=', fFlags, 'uint'));
+
+            if oInstr.asFlClear:
+                fFlags = oInstr.getClearedFlagsMask();
+                assert fFlags != 0;
+                aoOutputs.append(iai.TestInOut('efl', '&~=', fFlags, 'uint'));
+
+            if oInstr.asFlSet:
+                fFlags = oInstr.getSetFlagsMask();
+                assert fFlags != 0;
+                aoOutputs.append(iai.TestInOut('efl', '|=', fFlags, 'uint'));
+
+        return aoOutputs;
+
+    @staticmethod
     def _compileContextModifers(aoOperations): # (list(iai.TestInOut))
         """
@@ -116,5 +149,5 @@
             sOp = oOperation.sOp;
             if sOp == '&|=':
-                sOp = '|=' if len(aaoValues) == 1 else '&~=';
+                sOp = '|=' if len(aaoValues) == 1 else '&=';
 
             for fSignExtend, abValue in aaoValues:
@@ -184,5 +217,5 @@
         self.asSelectors = self._compileSelectors(oTest.aoSelectors);
         self.asInputs    = self._compileContextModifers(oTest.aoInputs);
-        self.asOutputs   = self._compileContextModifers(oTest.aoOutputs);
+        self.asOutputs   = self._compileContextModifers(self._amendOutputs(oTest.aoOutputs, oTest.oInstr));
         self.asHdr       = self._constructHeader();
 
Index: /trunk/src/VBox/ValidationKit/bootsectors/bs3-cpu-generated-1-template.c
===================================================================
--- /trunk/src/VBox/ValidationKit/bootsectors/bs3-cpu-generated-1-template.c	(revision 66112)
+++ /trunk/src/VBox/ValidationKit/bootsectors/bs3-cpu-generated-1-template.c	(revision 66113)
@@ -81,4 +81,6 @@
 #endif
 
+#define BS3CG1_DEBUG_CTX_MOD
+
 
 /*********************************************************************************************************************************
@@ -170,4 +172,6 @@
      * are marked not-present. */
     uint8_t BS3_FAR        *pbCodePg;
+    /** The flat address corresponding to pbCodePg.  */
+    uintptr_t               uCodePgFlat;
     /** Page for placing data operands in.  When paging is enabled, the page before
      * and after are marked not-present.  */
@@ -226,5 +230,5 @@
 /** Destination field sizes indexed by bBS3CG1DST.
  * Zero means operand size sized.  */
-static const uint8_t g_cbBs3Cg1DstFields[] =
+static const uint8_t g_acbBs3Cg1DstFields[] =
 {
     /* [BS3CG1DST_INVALID] = */ BS3CG1DSTSIZE_OPERAND,
@@ -329,5 +333,5 @@
 /** Destination field offset indexed by bBS3CG1DST.
  * Zero means operand size sized.  */
-static const unsigned g_offBs3Cg1DstFields[] =
+static const unsigned g_aoffBs3Cg1DstFields[] =
 {
     /* [BS3CG1DST_INVALID] = */ ~0U,
@@ -428,4 +432,108 @@
     /* [BS3CG1DST_OZ_R15] = */  RT_OFFSETOF(BS3REGCTX, r15),
 };
+
+#ifdef BS3CG1_DEBUG_CTX_MOD
+/** Destination field names. */
+static const struct { char sz[8]; } g_aszBs3Cg1DstFields[] =
+{
+    { "INVALID" },
+    { "OP1" },
+    { "OP2" },
+    { "OP3" },
+    { "OP4" },
+    { "EFL" },
+    { "EFL_UND" },
+
+    { "AL" },
+    { "CL" },
+    { "DL" },
+    { "BL" },
+    { "AH" },
+    { "CH" },
+    { "DH" },
+    { "BH" },
+    { "SPL" },
+    { "BPL" },
+    { "SIL" },
+    { "DIL" },
+    { "R8L" },
+    { "R9L" },
+    { "R10L" },
+    { "R11L" },
+    { "R12L" },
+    { "R13L" },
+    { "R14L" },
+    { "R15L" },
+
+    { "AX" },
+    { "CX" },
+    { "DX" },
+    { "BX" },
+    { "SP" },
+    { "BP" },
+    { "SI" },
+    { "DI" },
+    { "R8W" },
+    { "R9W" },
+    { "R10W" },
+    { "R11W" },
+    { "R12W" },
+    { "R13W" },
+    { "R14W" },
+    { "R15W" },
+
+    { "EAX" },
+    { "ECX" },
+    { "EDX" },
+    { "EBX" },
+    { "ESP" },
+    { "EBP" },
+    { "ESI" },
+    { "EDI" },
+    { "R8D" },
+    { "R9D" },
+    { "R10D" },
+    { "R11D" },
+    { "R12D" },
+    { "R13D" },
+    { "R14D" },
+    { "R15D" },
+
+    { "RAX" },
+    { "RCX" },
+    { "RDX" },
+    { "RBX" },
+    { "RSP" },
+    { "RBP" },
+    { "RSI" },
+    { "RDI" },
+    { "R8" },
+    { "R9" },
+    { "R10" },
+    { "R11" },
+    { "R12" },
+    { "R13" },
+    { "R14" },
+    { "R15" },
+
+    { "OZ_RAX" },
+    { "OZ_RCX" },
+    { "OZ_RDX" },
+    { "OZ_RBX" },
+    { "OZ_RSP" },
+    { "OZ_RBP" },
+    { "OZ_RSI" },
+    { "OZ_RDI" },
+    { "OZ_R8" },
+    { "OZ_R9" },
+    { "OZ_R10" },
+    { "OZ_R11" },
+    { "OZ_R12" },
+    { "OZ_R13" },
+    { "OZ_R14" },
+    { "OZ_R15" },
+};
+
+#endif
 
 #if 0
@@ -738,5 +846,5 @@
          * Do value processing specific to the target field size.
          */
-        cbDst = g_cbBs3Cg1DstFields[idxField];
+        cbDst = g_acbBs3Cg1DstFields[idxField];
         if (cbDst == BS3CG1DSTSIZE_OPERAND)
             cbDst = pThis->aOperands[idxField - BS3CG1DST_OP1].cbOp;
@@ -745,5 +853,5 @@
         if (cbDst <= 8)
         {
-            unsigned const offField = g_offBs3Cg1DstFields[idxField];
+            unsigned const offField = g_aoffBs3Cg1DstFields[idxField];
             BS3PTRUNION    PtrField;
 
@@ -808,4 +916,36 @@
             }
 
+#ifdef BS3CG1_DEBUG_CTX_MOD
+            {
+                const char BS3_FAR *pszOp;
+                switch (bOpcode & BS3CG1_CTXOP_OPERATOR_MASK)
+                {
+                    case BS3CG1_CTXOP_ASSIGN:   pszOp = "="; break;
+                    case BS3CG1_CTXOP_OR:       pszOp = "|="; break;
+                    case BS3CG1_CTXOP_AND:      pszOp = "&="; break;
+                    case BS3CG1_CTXOP_AND_INV:  pszOp = "&~="; break;
+                }
+                switch (cbDst)
+                {
+                    case 1:
+                        BS3CG1_DPRINTF(("dbg: modify %s: %#04RX8 (LB %u) %s %#RX64 (LB %u)\n",
+                                        g_aszBs3Cg1DstFields[idxField].sz, *PtrField.pu8, cbDst, pszOp, uValue, cbValue));
+                        break;
+                    case 2:
+                        BS3CG1_DPRINTF(("dbg: modify %s: %#06RX16 (LB %u) %s %#RX64 (LB %u)\n",
+                                        g_aszBs3Cg1DstFields[idxField].sz, *PtrField.pu16, cbDst, pszOp, uValue, cbValue));
+                        break;
+                    case 4:
+                        BS3CG1_DPRINTF(("dbg: modify %s: %#010RX32 (LB %u) %s %#RX64 (LB %u)\n",
+                                        g_aszBs3Cg1DstFields[idxField].sz, *PtrField.pu32, cbDst, pszOp, uValue, cbValue));
+                        break;
+                    default:
+                        BS3CG1_DPRINTF(("dbg: modify %s: %#018RX64 (LB %u) %s %#RX64 (LB %u)\n",
+                                        g_aszBs3Cg1DstFields[idxField].sz, *PtrField.pu64, cbDst, pszOp, uValue, cbValue));
+                        break;
+                }
+            }
+#endif
+
             /* Modify the field. */
             switch (cbDst)
@@ -855,4 +995,15 @@
                     return false;
             }
+
+#ifdef BS3CG1_DEBUG_CTX_MOD
+            switch (cbDst)
+            {
+                case 1:  BS3CG1_DPRINTF(("dbg:    --> %s: %#04RX32\n", g_aszBs3Cg1DstFields[idxField].sz, *PtrField.pu8));   break;
+                case 2:  BS3CG1_DPRINTF(("dbg:    --> %s: %#06RX32\n", g_aszBs3Cg1DstFields[idxField].sz, *PtrField.pu16));  break;
+                case 4:  BS3CG1_DPRINTF(("dbg:    --> %s: %#010RX32\n", g_aszBs3Cg1DstFields[idxField].sz, *PtrField.pu32)); break;
+                default: BS3CG1_DPRINTF(("dbg:    --> %s: %#018RX64\n", g_aszBs3Cg1DstFields[idxField].sz, *PtrField.pu64)); break;
+            }
+#endif
+
         }
         /*
@@ -932,4 +1083,5 @@
         }
     }
+    This.uCodePgFlat = Bs3SelPtrToFlat(This.pbCodePg);
 
     /* Create basic context for each target ring.  In protected 16-bit code we need
@@ -1050,5 +1202,5 @@
                         Bs3MemCpy(&This.Ctx, &This.aInitialCtxs[iRing], sizeof(This.Ctx));
                         if (BS3_MODE_IS_PAGED(bMode))
-                            pbCode = &This.pbCodePg[This.cbCurInstr];
+                            pbCode = &This.pbCodePg[X86_PAGE_SIZE - This.cbCurInstr];
                         else
                         {
@@ -1073,4 +1225,8 @@
                             {
                                 /* Apply output modifications and compare the contexts. */
+                                if (BS3_MODE_IS_PAGED(bMode))
+                                    This.Ctx.cr2.u = This.uCodePgFlat + X86_PAGE_SIZE;
+                                This.Ctx.rflags.u32 &= ~X86_EFL_RF;
+                                This.Ctx.rflags.u32 |= X86_EFL_RF & This.TrapFrame.Ctx.rflags.u32;
                                 if (Bs3Cg1RunContextModifier(&This, &This.Ctx, pHdr,
                                                              pHdr->cbSelector + pHdr->cbInput, pHdr->cbOutput,
@@ -1083,5 +1239,5 @@
                             else
                             {
-                                Bs3TestFailedF("bXcpt=%#x expected %#x; rip=%RX64 expected %RX64 encoding: %.*Rhxs",
+                                Bs3TestFailedF("bXcpt=%#x expected %#x; rip=%RX64 expected %RX64; encoding: %.*Rhxs",
                                                This.TrapFrame.bXcpt, BS3_MODE_IS_PAGED(bMode) ? X86_XCPT_PF : X86_XCPT_UD,
                                                This.TrapFrame.Ctx.rip.u, This.Ctx.rip.u + This.cbCurInstr,
@@ -1120,4 +1276,6 @@
     }
 
+    Bs3TestSubDone();
+
     return 0;
 }
