Index: /trunk/src/VBox/VMM/VMMAll/IEMAllInstructionsPython.py
===================================================================
--- /trunk/src/VBox/VMM/VMMAll/IEMAllInstructionsPython.py	(revision 65925)
+++ /trunk/src/VBox/VMM/VMMAll/IEMAllInstructionsPython.py	(revision 65926)
@@ -162,5 +162,5 @@
 
 ## IEMFORM_XXX mappings.
-g_kdIemForms = { # sEncoding,    [sWhere,]
+g_kdIemForms = { # sEncoding,   [ sWhere1, ... ]
     'RM':       ( 'ModR/M',     [ 'reg', 'rm' ], ),
     'RM_REG':   ( 'ModR/M',     [ 'reg', 'rm' ], ),
@@ -197,7 +197,7 @@
 ## Valid values for \@openc
 g_kdEncodings = {
-    'ModR/M': [],       ##< ModR/M
-    'fixed':  [],       ##< Fixed encoding (address, registers, etc).
-    'prefix': [],       ##< Prefix
+    'ModR/M':   [ 'BS3CG1ENC_MODRM', ],     ##< ModR/M
+    'fixed':    [ 'BS3CG1ENC_FIXED', ],     ##< Fixed encoding (address, registers, etc).
+    'prefix':   [ None, ],                  ##< Prefix
 };
 
@@ -2758,6 +2758,8 @@
         oDstFile.write('\n');
         break; #for now
-generateDisassemblerTables();
-
-
-
+
+if __name__ == '__main__':
+    generateDisassemblerTables();
+
+
+
Index: /trunk/src/VBox/ValidationKit/bootsectors/Makefile.kmk
===================================================================
--- /trunk/src/VBox/ValidationKit/bootsectors/Makefile.kmk	(revision 65925)
+++ /trunk/src/VBox/ValidationKit/bootsectors/Makefile.kmk	(revision 65926)
@@ -317,12 +317,29 @@
 MISCBINS += bs3-cpu-generated-1
 bs3-cpu-generated-1_TEMPLATE = VBoxBS3KitImg
-bs3-cpu-generated-1_INCS  = .
+bs3-cpu-generated-1_INCS = .
+bs3-cpu-generated-1_DEFS = BS3_CMN_INSTANTIATE_FILE1=bs3-cpu-generated-1-template.c
 bs3-cpu-generated-1_SOURCES = \
 	bs3kit/bs3-first-rm.asm \
 	bs3-cpu-generated-1.c \
-	bs3-cpu-generated-1-asm.asm
+	bs3-cpu-generated-1-asm.asm \
+       bs3kit/bs3-cmn-instantiate.c16 \
+       bs3kit/bs3-cmn-instantiate.c32 \
+       bs3kit/bs3-cmn-instantiate.c64 \
+	$(bs3-cpu-generated-1_0_OUTDIR)/bs3-cpu-generated-1-data.c16
+bs3-cpu-generated-1_CLEAN = $(bs3-cpu-generated-1_0_OUTDIR)/bs3-cpu-generated-1-data.c16
+
 bs3-cpu-generated-1-template.o:: \
+	$$(bs3-cpu-generated-1_0_OUTDIR)/bs3kit/bs3-cmn-instantiate.o16 \
+	$$(bs3-cpu-generated-1_0_OUTDIR)/bs3kit/bs3-cmn-instantiate.o32 \
+	$$(bs3-cpu-generated-1_0_OUTDIR)/bs3kit/bs3-cmn-instantiate.o64 \
 	$$(bs3-cpu-generated-1_0_OUTDIR)/bs3-cpu-generated-1-asm.o16
 
+$$(bs3-cpu-generated-1_0_OUTDIR)/bs3-cpu-generated-1-data.c16: \
+		$(PATH_SUB_CURRENT)/bs3-cpu-generated-1-data.py \
+		$(PATH_SUB_CURRENT)/../../VMM/VMMAll/IEMAllInstructionsPython.py \
+		$(PATH_SUB_CURRENT)/../../VMM/VMMAll/IEMAllInstructions*.cpp.h \
+               | $$(dir $$@)
+	$(VBOX_BLD_PYTHON) $< $@
+
 endif # VBOX_WITH_BS3KIT
 
Index: /trunk/src/VBox/ValidationKit/bootsectors/bs3-cpu-generated-1-data.py
===================================================================
--- /trunk/src/VBox/ValidationKit/bootsectors/bs3-cpu-generated-1-data.py	(revision 65926)
+++ /trunk/src/VBox/ValidationKit/bootsectors/bs3-cpu-generated-1-data.py	(revision 65926)
@@ -0,0 +1,514 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+# $Id$
+
+"""
+Generates testcases from @optest specifications in IEM.
+"""
+
+from __future__ import print_function;
+
+__copyright__ = \
+"""
+Copyright (C) 2017 Oracle Corporation
+
+This file is part of VirtualBox Open Source Edition (OSE), as
+available from http://www.virtualbox.org. This file is free software;
+you can redistribute it and/or modify it under the terms of the GNU
+General Public License (GPL) as published by the Free Software
+Foundation, in version 2 as it comes in the "COPYING" file of the
+VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+
+The contents of this file may alternatively be used under the terms
+of the Common Development and Distribution License Version 1.0
+(CDDL) only, as it comes in the "COPYING.CDDL" file of the
+VirtualBox OSE distribution, in which case the provisions of the
+CDDL are applicable instead of those of the GPL.
+
+You may elect to license modified versions of this file under the
+terms and conditions of either the GPL or the CDDL or both.
+"""
+__version__ = "$Revision$"
+
+# Standard python imports.
+import os;
+import re;
+import sys;
+import time;
+
+# Only the main script needs to modify the path.
+g_ksValidationKitDir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)));
+g_ksVmmAllDir = os.path.join(os.path.dirname(g_ksValidationKitDir), 'VMM', 'VMMAll')
+sys.path.extend([g_ksValidationKitDir, g_ksVmmAllDir]);
+
+from common import utils;
+import IEMAllInstructionsPython as iai;
+
+# Python 3 hacks:
+if sys.version_info[0] >= 3:
+    long = int;     # pylint: disable=redefined-builtin,invalid-name
+
+
+class Bs3Cg1TestEncoder(object):
+    """
+    Does the encoding of a single test.
+    """
+
+    def __init__(self, fLast):
+        self.fLast      = fLast;
+        # Each list member (in all lists) are C expression of a byte.
+        self.asHdr       = [];
+        self.asSelectors = [];
+        self.asInputs    = [];
+        self.asOutputs   = [];
+
+    @staticmethod
+    def _compileSelectors(aoSelectors): # (list(iai.TestSelector)) -> list(str)
+        """
+        Compiles a list of iai.TestSelector predicate checks.
+        Returns C byte expression strings.
+        """
+        asRet = [];
+        for oSelector in aoSelectors:
+            sConstant = oSelector.kdVariables[oSelector.sVariable][oSelector.sValue];
+            sConstant = sConstant.upper().replace('.', '_');
+            if oSelector.sValue.sOp == '==':
+                sByte = '(BS3CG1PRED_%s << BS3CG1SEL_OP_PRED_SHIFT) | BS3CG1SEL_OP_IS_TRUE' % (sConstant,);
+            elif oSelector.sValue.sOp == '!=':
+                sByte = '(BS3CG1PRED_%s << BS3CG1SEL_OP_PRED_SHIFT) | BS3CG1SEL_OP_IS_FALSE' % (sConstant,);
+            else:
+                raise Exception('Unknown selector operator: %s' % (oSelector.sOp,));
+            asRet.append(sByte);
+        return asRet;
+
+    kdSmallFields = {
+        'op1':  'BS3CG1_CTXOP_OP1',
+        'op2':  'BS3CG1_CTXOP_OP2',
+        'efl':  'BS3CG1_CTXOP_EFL',
+    };
+    kdOperators = {
+        '=':    'BS3CG1_CTXOP_ASSIGN',
+        '|=':   'BS3CG1_CTXOP_OR',
+        '&=':   'BS3CG1_CTXOP_AND',
+        '&~=':  'BS3CG1_CTXOP_AND_INV',
+    };
+    kdSmallSizes = {
+        1:      'BS3CG1_CTXOP_1_BYTE',
+        2:      'BS3CG1_CTXOP_2_BYTES',
+        4:      'BS3CG1_CTXOP_4_BYTES',
+        8:      'BS3CG1_CTXOP_8_BYTES',
+        16:     'BS3CG1_CTXOP_16_BYTES',
+        32:     'BS3CG1_CTXOP_32_BYTES',
+        12:     'BS3CG1_CTXOP_12_BYTES',
+    };
+
+    @staticmethod
+    def _compileContextModifers(aoOperations): # (list(iai.TestInOut))
+        """
+        Compile a list of iai.TestInOut context modifiers.
+        """
+        asRet = [];
+        for oOperation in aoOperations:
+            oType = iai.TestInOut.kdTypes[oOperation.sType];
+            aaoValues = oType.get(oOperation.sValue);
+            assert len(aaoValues) == 1 or len(aaoValues) == 2;
+
+            sOp = oOperation.sOp;
+            if sOp == '&|=':
+                sOp = '|=' if len(aaoValues) == 1 else '&~=';
+
+            for fSignExtend, abValue in aaoValues:
+                cbValue = len(abValue);
+
+                # The opcode byte.
+                sOpcode = Bs3Cg1TestEncoder.kdOperators[sOp];
+                sOpcode += ' | ';
+                if oOperation.sField in Bs3Cg1TestEncoder.kdSmallFields:
+                    sOpcode += Bs3Cg1TestEncoder.kdSmallFields[oOperation.sField];
+                else:
+                    sOpcode += 'BS3CG1_CTXOP_DST_ESC';
+                sOpcode += ' | ';
+                if cbValue in Bs3Cg1TestEncoder.kdSmallSizes:
+                    sOpcode += Bs3Cg1TestEncoder.kdSmallSizes[cbValue];
+                else:
+                    sOpcode += 'BS3CG1_CTXOP_SIZE_ESC';
+                if fSignExtend:
+                    sOpcode += '| BS3CG1_CTXOP_SIGN_EXT';
+                asRet.append(sOpcode);
+
+                # Escaped size byte?
+                if cbValue not in Bs3Cg1TestEncoder.kdSmallSizes:
+                    if cbValue >= 256 or cbValue not in [ 1, 2, 4, 6, 8, 12, 16, 32, 64, 128, ]:
+                        raise Exception('Invalid value size: %s' % (cbValue,));
+                    asRet.append('0x%02x' % (cbValue,));
+
+                # Escaped field identifier.
+                if oOperation.sField not in Bs3Cg1TestEncoder.kdSmallFields:
+                    asRet.append('BS3CG1DST_%s' % (oOperation.sField.upper().replace('.', '_'),));
+
+                # The value bytes.
+                for b in abValue:
+                    asRet.append('0x%02x' % (b,));
+
+                sOp = '|=';
+
+        return asRet;
+
+    def _constructHeader(self):
+        """
+        Returns C byte expression strings for BS3CG1TESTHDR.
+        """
+        cbSelectors = len(self.asSelectors);
+        if cbSelectors >=  256:
+            raise Exception('Too many selectors: %s bytes, max 255 bytes' % (cbSelectors,))
+
+        cbInputs = len(self.asInputs);
+        if cbInputs >= 4096:
+            raise Exception('Too many input context modifiers: %s bytes, max 4095 bytes' % (cbInputs,))
+
+        cbOutputs = len(self.asOutputs);
+        if cbOutputs >= 2048:
+            raise Exception('Too many output context modifiers: %s bytes, max 2047 bytes' % (cbOutputs,))
+
+        return [
+            '%#04x' % (cbSelectors,),                                     # 8-bit
+            '%#05x & 0xff' % (cbInputs,),                                 # first 8 bits of cbInputs
+            '(%#05x >> 8) | ((%#05x & 0xf) << 4)' % (cbInputs, cbOutputs,),  # last 4 bits of cbInputs, lower 4 bits of cbOutputs.
+            '(%#05x >> 4) | (%#05x << 7)' % (cbOutputs, self.fLast),         # last 7 bits of cbOutputs and 1 bit fLast.
+        ];
+
+    def encodeTest(self, oTest): # type: (iai.InstructionTest)
+        """
+        Does the encoding.
+        """
+        self.asSelectors = self._compileSelectors(oTest.aoSelectors);
+        self.asInputs    = self._compileContextModifers(oTest.aoInputs);
+        self.asOutputs   = self._compileContextModifers(oTest.aoOutputs);
+        self.asHdr       = self._constructHeader();
+
+
+class Bs3Cg1EncodedTests(object):
+    """
+    Encodes the tests for an instruction.
+    """
+
+    def __init__(self, oInstr):
+        self.offTests = -1;
+        self.cbTests  = 0;
+        self.asLines  = [];
+
+        # Encode the tests.
+        for iTest, oTest in enumerate(oInstr.aoTests):
+            oEncodedTest = Bs3Cg1TestEncoder(iTest + 1 == len(oInstr.aoTests));
+            oEncodedTest.encodeTest(oTest);
+
+            self.cbTests += len(oEncodedTest.asHdr) + len(oEncodedTest.asSelectors) \
+                          + len(oEncodedTest.asInputs) + len(oEncodedTest.asOutputs);
+
+            self.asLines += self.bytesToLines('    /*hdr:*/ ', oEncodedTest.asHdr);
+            if oEncodedTest.asSelectors:
+                self.asLines += self.bytesToLines('    /*sel:*/ ', oEncodedTest.asSelectors);
+            if oEncodedTest.asInputs:
+                self.asLines += self.bytesToLines('    /* in:*/ ', oEncodedTest.asInputs);
+            if oEncodedTest.asOutputs:
+                self.asLines += self.bytesToLines('    /*out:*/ ', oEncodedTest.asOutputs);
+
+    @staticmethod
+    def bytesToLines(sPrefix, asBytes):
+        """
+        Formats a series of bytes into one or more lines.
+        A byte ending with a newline indicates that we should start a new line,
+        and prefix it by len(sPrefix) spaces.
+
+        Returns list of lines.
+        """
+        asRet = [];
+        sLine = sPrefix;
+        for sByte in asBytes:
+            if sByte[-1] == '\n':
+                sLine += sByte[:-1] + ',';
+                asRet.append(sLine);
+                sLine = ' ' * len(sPrefix);
+            else:
+                if len(sLine) + 2 + len(sByte) > 132 and len(sLine) > len(sPrefix):
+                    asRet.append(sLine[:-1]);
+                    sLine = ' ' * len(sPrefix);
+                sLine += sByte + ', ';
+
+
+        if len(sLine) > len(sPrefix):
+            asRet.append(sLine);
+        return asRet;
+
+
+    def isEqual(self, oOther):
+        """ Compares two encoded tests. """
+        if self.cbTests != oOther.cbTests:
+            return False;
+        if len(self.asLines) != len(oOther.asLines):
+            return False;
+        for iLine, sLines in enumerate(self.asLines):
+            if sLines != oOther.asLines[iLine]:
+                return False;
+        return True;
+
+
+
+class Bs3Cg1Instruction(object):
+    """
+    An instruction with tests.
+    """
+
+    def __init__(self, oMap, oInstr, oTests):
+        self.oMap   = oMap;             # type: iai.InstructionMap
+        self.oInstr = oInstr;           # type: iai.Instruction
+        self.oTests = oTests;           # type: Bs3Cg1EncodedTests
+
+        self.asOpcodes          = oMap.asLeadOpcodes + [ '0x%02x' % (oInstr.getOpcodeByte(),) ];
+        self.sEncoding          = iai.g_kdEncodings[oInstr.sEncoding][0];
+        for oOp in oInstr.aoOperands:
+            self.sEncoding     += '_' + oOp.sType;
+        self.asFlags            = [];
+        self.fAdvanceMnemonic   = True; ##< Set by the caller.
+
+    def getOperands(self):
+        """ Returns comma separated string of operand values for g_abBs3Cg1Operands. """
+        return ', '.join(['(uint8_t)BS3CG1OP_%s' % (oOp.sType,) for oOp in self.oInstr.aoOperands]);
+
+    def getInstructionEntry(self):
+        """ Returns an array of BS3CG1INSTR member initializers. """
+        return [
+            '        /* cbOpcode = */         %s,' % (len(self.asOpcodes),),
+            '        /* cOperands = */        %s,' % (len(self.oInstr.aoOperands),),
+            '        /* cchMnemonic = */      %s,' % (len(self.oInstr.sMnemonic),),
+            '        /* fAdvanceMnemonic = */ %s,' % ('true' if self.fAdvanceMnemonic else 'false',),
+            '        /* offTests = */         %s,' % (self.oTests.offTests,),
+            '        /* enmEncoding = */      (unsigned)%s,' % (self.sEncoding,),
+            '        /* uUnused = */          0,',
+            '        /* fFlags = */           %s' % (' | '.join(self.asFlags) if self.asFlags else '0'),
+        ];
+
+
+class Bs3CpuGenerated1Generator(object):
+    """
+    The generator code for bs3-cpu-generated-1.
+    """
+
+    def __init__(self):
+        self.aoInstructions = [];       # type: Bs3Cg1Instruction
+        self.aoTests        = [];       # type: Bs3Cg1EncodedTests
+        self.cbTests        = 0;
+
+    def addTests(self, oTests):
+        """
+        Adds oTests to self.aoTests, setting the oTests.offTests member.
+        Checks for and eliminates duplicates.
+        Returns the tests to use.
+        """
+        # Check for duplicates.
+        for oExisting in self.aoTests:
+            if oTests.isEqual(oExisting):
+                return oExisting;
+
+        # New test, so add it.
+        oTests.offTests = self.cbTests;
+        self.aoTests.append(oTests);
+        self.cbTests   += oTests.cbTests;
+
+        return oTests;
+
+    def processInstruction(self):
+        """
+        Processes the IEM specified instructions.
+        Returns success indicator.
+        """
+
+        #
+        # Group instructions by mnemonic to reduce the number of sub-tests.
+        #
+        for oInstr in sorted(iai.g_aoAllInstructions,
+                             key = lambda(oInstr): oInstr.sMnemonic + ''.join([oOp.sType for oOp in oInstr.aoOperands])
+                                                                    + (oInstr.sOpcode if oInstr.sOpcode else 'zz')):
+            if len(oInstr.aoTests) > 0:
+                oTests = Bs3Cg1EncodedTests(oInstr);
+                oTests = self.addTests(oTests);
+
+                for oMap in oInstr.aoMaps:
+                    self.aoInstructions.append(Bs3Cg1Instruction(oMap, oInstr, oTests));
+
+        # Set fAdvanceMnemonic.
+        for iInstr, oInstr in enumerate(self.aoInstructions):
+            oInstr.fAdvanceMnemonic = iInstr + 1 >= len(self.aoInstructions) \
+                                   or oInstr.oInstr.sMnemonic != self.aoInstructions[iInstr + 1].oInstr.sMnemonic;
+
+        return True;
+
+    def generateCode(self, oOut):
+        """
+        Generates the C code.
+        Returns success indicator.
+        """
+
+        # First, a file header.
+        asLines = [
+            '/*',
+            ' * Autogenerated by  $Id$ ',
+            ' * Do not edit!',
+            ' */',
+            '',
+            '/*',
+            ' * Copyright (C) 2017 Oracle Corporation',
+            ' *',
+            ' * This file is part of VirtualBox Open Source Edition (OSE), as',
+            ' * available from http://www.virtualbox.org. This file is free software;',
+            ' * you can redistribute it and/or modify it under the terms of the GNU',
+            ' * General Public License (GPL) as published by the Free Software',
+            ' * Foundation, in version 2 as it comes in the "COPYING" file of the',
+            ' * VirtualBox OSE distribution. VirtualBox OSE is distributed in the',
+            ' * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.',
+            ' * ',
+            ' * The contents of this file may alternatively be used under the terms',
+            ' * of the Common Development and Distribution License Version 1.0',
+            ' * (CDDL) only, as it comes in the "COPYING.CDDL" file of the',
+            ' * VirtualBox OSE distribution, in which case the provisions of the',
+            ' * CDDL are applicable instead of those of the GPL.',
+            ' * ',
+            ' * You may elect to license modified versions of this file under the',
+            ' * terms and conditions of either the GPL or the CDDL or both.',
+            ' */',
+            '',
+            '',
+            '#include "bs3-cpu-generated-1.h"',
+            '',
+            '',
+        ];
+
+        # Generate the g_achBs3Cg1Mnemonics array.
+        asLines += [
+            'const char BS3_FAR_DATA g_achBs3Cg1Mnemonics[] = ',
+            '{',
+        ];
+        for oInstr in self.aoInstructions:
+            asLines.append('    \"%s\"' % (oInstr.oInstr.sMnemonic,));
+        asLines += [
+            '};',
+            '',
+            '',
+        ];
+
+        # Generate the g_abBs3Cg1Opcodes array.
+        asLines += [
+            'const uint8_t BS3_FAR_DATA g_abBs3Cg1Opcodes[] = ',
+            '{',
+        ];
+        for oInstr in self.aoInstructions:
+            asLines.append('    ' + ', '.join(oInstr.asOpcodes) + ',');
+        asLines += [
+            '};',
+            '',
+            '',
+        ];
+
+        # Generate the g_abBs3Cg1Opcodes array.
+        asLines += [
+            'const uint8_t BS3_FAR_DATA g_abBs3Cg1Operands[] = ',
+            '{',
+        ];
+        for oInstr in self.aoInstructions:
+            asLines.append('    ' + oInstr.getOperands() + ',');
+        asLines += [
+            '};',
+            '',
+            '',
+        ];
+
+        # Generate the g_abBs3Cg1Operands array.
+        asLines += [
+            'const BS3CG1INSTR BS3_FAR_DATA g_aBs3Cg1Instructions[] = ',
+            '{',
+        ];
+        for oInstr in self.aoInstructions:
+            asLines.append('    {');
+            asLines += oInstr.getInstructionEntry();
+            asLines.append('    },');
+        asLines += [
+            '};',
+            'const  uint16_t BS3_FAR_DATA g_cBs3Cg1Instructions = RT_ELEMENTS(g_aBs3Cg1Instructions);',
+            '',
+            '',
+        ];
+
+        # Generate the g_abBs3Cg1Tests array.
+        asLines += [
+            'const uint8_t BS3_FAR_DATA g_abBs3Cg1Tests[] = ',
+            '{',
+        ];
+        for oTests in self.aoTests:
+            asLines.append('    /* offTests=%s */' % (oTests.offTests,));
+            asLines += oTests.asLines;
+        asLines += [
+            '};',
+            '',
+        ];
+
+
+        #/** The test data that BS3CG1INSTR.
+        # * In order to simplify generating these, we use a byte array. */
+        #extern const uint8_t BS3_FAR_DATA   g_abBs3Cg1Tests[];
+
+
+        oOut.write('\n'.join(asLines));
+        return True;
+
+
+    def usage(self):
+        """ Prints usage. """
+        print('usage: bs3-cpu-generated-1-data.py [output file|-]');
+        return 0;
+
+    def main(self, asArgs):
+        """
+        C-like main function.
+        Returns exit code.
+        """
+
+        #
+        # Quick argument parsing.
+        #
+        if len(asArgs) == 1:
+            sOutFile = '-';
+        elif len(asArgs) != 2:
+            print('syntax error! Expected exactly one argument.');
+            return 2;
+        elif asArgs[1] in [ '-h', '-?', '--help' ]:
+            return self.usage();
+        else:
+            sOutFile = asArgs[1];
+
+        #
+        # Process the instructions specified in the IEM sources.
+        #
+        if self.processInstruction():
+
+            #
+            # Open the output file and generate the code.
+            #
+            if sOutFile == '-':
+                oOut = sys.stdout;
+            else:
+                try:
+                    oOut = open(sOutFile, 'wt');
+                except Exception as oXcpt:
+                    print('error! Failed open "%s" for writing: %s' % (sOutFile, oXcpt,));
+                    return 1;
+            if self.generateCode(oOut):
+                return 0;
+
+        return 1;
+
+
+if __name__ == '__main__':
+    sys.exit(Bs3CpuGenerated1Generator().main(sys.argv));
+
+
Index: /trunk/src/VBox/ValidationKit/bootsectors/bs3-cpu-generated-1-template.c
===================================================================
--- /trunk/src/VBox/ValidationKit/bootsectors/bs3-cpu-generated-1-template.c	(revision 65926)
+++ /trunk/src/VBox/ValidationKit/bootsectors/bs3-cpu-generated-1-template.c	(revision 65926)
@@ -0,0 +1,243 @@
+/* $Id$ */
+/** @file
+ * BS3Kit - bs3-cpu-generated-1, C code template.
+ */
+
+/*
+ * Copyright (C) 2007-2017 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+ * VirtualBox OSE distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ */
+
+#ifndef BS3_INSTANTIATING_CMN
+# error "BS3_INSTANTIATING_CMN not defined"
+#endif
+
+
+/*********************************************************************************************************************************
+*   Header Files                                                                                                                 *
+*********************************************************************************************************************************/
+#include <iprt/asm.h>
+#include <iprt/asm-amd64-x86.h>
+
+#include "bs3-cpu-generated-1.h"
+
+
+/*********************************************************************************************************************************
+*   Structures and Typedefs                                                                                                      *
+*********************************************************************************************************************************/
+/**
+ * The state.
+ */
+typedef struct BS3CG1STATE
+{
+    /** @name Instruction details (expanded from BS3CG1INSTR).
+     * @{ */
+    /** Pointer to the mnemonic string (not terminated) (g_achBs3Cg1Mnemonics). */
+    const char BS3_FAR     *pchMnemonic;
+    /** Pointer to the test header. */
+    PCBS3CG1TESTHDR         pTestHdr;
+    /** Pointer to the per operand flags (g_abBs3Cg1Operands). */
+    const uint8_t BS3_FAR  *pabOperands;
+    /** Opcode bytes (g_abBs3Cg1Opcodes). */
+    const uint8_t BS3_FAR  *pabOpcodes;
+
+    /** The instruction flags. */
+    uint32_t                fFlags;
+    /** The encoding. */
+    BS3CG1ENC               enmEncoding;
+#if ARCH_BITS == 16
+    uint16_t                u16Padding0;
+#endif
+    /** Per operand flags. */
+    BS3CG1OP                aenmOperands[4];
+    /** Opcode bytes. */
+    uint8_t                 abOpcodes[4];
+
+    /** The length of the mnemonic. */
+    uint8_t                 cchMnemonic;
+    /** Whether to advance the mnemonic pointer or not. */
+    uint8_t                 fAdvanceMnemonic;
+    /** The number of opcode bytes.   */
+    uint8_t                 cbOpcode;
+    /** Number of operands. */
+    uint8_t                 cOperands;
+    /** @} */
+
+    /** Operand size (16, 32, 64, or 0). */
+    uint8_t                 cBitsOp;
+    /** Target ring (0..3). */
+    uint8_t                 uCpl;
+
+    /** Target mode (g_bBs3CurrentMode).  */
+    uint8_t                 bMode;
+
+    uint8_t                 abPadding1[2];
+
+    /** Page to put code in.  When paging is enabled, the page before and after
+     * are marked not-present. */
+    uint8_t BS3_FAR        *pbCodePg;
+    /** Page for placing data operands in.  When paging is enabled, the page before
+     * and after are marked not-present.  */
+    uint8_t BS3_FAR        *pbDataPg;
+
+    /** The context we're working on. */
+    BS3REGCTX               Ctx;
+    /** The trap context and frame. */
+    BS3TRAPFRAME            TrapFrame;
+    /** Initial contexts, one for each ring. */
+    BS3REGCTX               aInitialCtxs[4];
+
+    /** Memory operand scratch space. */
+    union
+    {
+        uint8_t             ab[128];
+        uint16_t            au16[128 / sizeof(uint16_t)];
+        uint32_t            au32[128 / sizeof(uint32_t)];
+        uint64_t            au64[128 / sizeof(uint64_t)];
+    } MemOp;
+} BS3CG1STATE;
+
+
+
+BS3_DECL_FAR(uint8_t) BS3_CMN_NM(bs3CpuInstr2_mul)(uint8_t bMode)
+{
+    BS3CG1STATE         This;
+    unsigned const      iFirstRing = BS3_MODE_IS_V86(bMode)       ? 3 : 0;
+    unsigned const      cRings     = BS3_MODE_IS_RM_OR_V86(bMode) ? 1 : 4;
+    unsigned            iRing;
+    unsigned            iInstr;
+    BS3MEMKIND const    enmMemKind = BS3_MODE_IS_RM_OR_V86(bMode) ? BS3MEMKIND_REAL
+                                   : BS3_MODE_IS_16BIT_CODE(bMode) ? BS3MEMKIND_TILED : BS3MEMKIND_FLAT32;
+
+    /*
+     * Initalize the state.
+     */
+    Bs3MemSet(&This, 0, sizeof(This));
+
+    This.bMode          = bMode;
+    This.pchMnemonic    = g_achBs3Cg1Mnemonics;
+    This.pabOperands    = g_abBs3Cg1Operands;
+    This.pabOpcodes     = g_abBs3Cg1Opcodes;
+
+    /* Allocate guarded exectuable and data memory. */
+    if (BS3_MODE_IS_PAGED(bMode))
+    {
+        This.pbCodePg = Bs3MemGuardedTestPageAlloc(enmMemKind);
+        if (This.pbCodePg)
+        {
+            Bs3TestFailedF("First Bs3MemGuardedTestPageAlloc(%d) failed", enmMemKind);
+            return 0;
+        }
+        This.pbDataPg = Bs3MemGuardedTestPageAlloc(enmMemKind);
+        if (!This.pbDataPg)
+        {
+            Bs3MemGuardedTestPageFree(This.pbCodePg);
+            Bs3TestFailedF("Second Bs3MemGuardedTestPageAlloc(%d) failed", enmMemKind);
+            return 0;
+        }
+    }
+    else
+    {
+        This.pbCodePg = Bs3MemAlloc(enmMemKind, X86_PAGE_SIZE);
+        if (!This.pbCodePg)
+        {
+            Bs3TestFailedF("First Bs3MemAlloc(%d,Pg) failed", enmMemKind);
+            return 0;
+        }
+        This.pbDataPg = Bs3MemAlloc(enmMemKind, X86_PAGE_SIZE);
+        if (!This.pbDataPg)
+        {
+            Bs3MemFree(This.pbCodePg, X86_PAGE_SIZE);
+            Bs3TestFailedF("Second Bs3MemAlloc(%d,Pg) failed", enmMemKind);
+            return 0;
+        }
+    }
+
+    Bs3RegCtxSaveEx(&This.aInitialCtxs[iFirstRing], bMode, 512);
+    for (iRing = iFirstRing + 1; iRing < cRings; iRing++)
+        Bs3RegCtxConvertToRingX(&This.aInitialCtxs[iFirstRing], iRing);
+
+    /*
+     * Test the instructions.
+     */
+    for (iInstr = 0; iInstr < g_cBs3Cg1Instructions;
+         iInstr++,
+         This.pchMnemonic += This.fAdvanceMnemonic * This.cchMnemonic,
+         This.pabOperands += This.cOperands,
+         This.pabOpcodes  += This.cbOpcode )
+    {
+        unsigned iEncoding;
+
+        /*
+         * Expand the instruction information into the state.
+         * Note! 16-bit will switch to a two level test header lookup once we exceed 64KB.
+         */
+        PCBS3CG1INSTR pInstr = &g_aBs3Cg1Instructions[iInstr];
+        This.pTestHdr        = (PCBS3CG1TESTHDR)&g_abBs3Cg1Tests[pInstr->offTests];
+        This.fFlags          = pInstr->fFlags;
+        This.enmEncoding     = (BS3CG1ENC)pInstr->enmEncoding;
+        This.cchMnemonic     = pInstr->cchMnemonic;
+        This.fAdvanceMnemonic= pInstr->fAdvanceMnemonic;
+        This.cOperands       = pInstr->cOperands;
+        This.cbOpcode        = pInstr->cbOpcode;
+        switch (This.cOperands)
+        {
+            case 3: This.aenmOperands[3] = (BS3CG1OP)This.pabOperands[3];
+            case 2: This.aenmOperands[2] = (BS3CG1OP)This.pabOperands[2];
+            case 1: This.aenmOperands[1] = (BS3CG1OP)This.pabOperands[1];
+            case 0: This.aenmOperands[0] = (BS3CG1OP)This.pabOperands[0];
+        }
+
+        switch (This.cbOpcode)
+        {
+            case 3: This.abOpcodes[3] = This.pabOpcodes[3];
+            case 2: This.abOpcodes[2] = This.pabOpcodes[2];
+            case 1: This.abOpcodes[1] = This.pabOpcodes[1];
+            case 0: This.abOpcodes[0] = This.pabOpcodes[0];
+        }
+
+        if (This.enmEncoding <= BS3CG1ENC_INVALID || This.enmEncoding >= BS3CG1ENC_END)
+        {
+            Bs3TestFailedF("Invalid enmEncoding for instruction #%u (%.*s): %d",
+                           iInstr, This.cchMnemonic, This.pchMnemonic, This.enmEncoding);
+            continue;
+        }
+
+        /*
+         * Encode the instruction in various ways and check out the test values.
+         */
+        for (iEncoding = 0; ; iEncoding++)
+        {
+            //switch (This.enmEncoding)
+            //{
+            //
+            //}
+
+
+            /*
+             * Run the tests.
+             */
+
+        }
+
+    }
+
+    return 0;
+}
+
Index: /trunk/src/VBox/ValidationKit/bootsectors/bs3-cpu-generated-1.h
===================================================================
--- /trunk/src/VBox/ValidationKit/bootsectors/bs3-cpu-generated-1.h	(revision 65925)
+++ /trunk/src/VBox/ValidationKit/bootsectors/bs3-cpu-generated-1.h	(revision 65926)
@@ -33,11 +33,42 @@
 
 
-
-/** Instruction encoding format. */
+/**
+ * Operand details.
+ *
+ * Currently simply using the encoding from the reference manuals.
+ */
+typedef enum BS3CG1OP
+{
+    BS3CG1OP_INVALID = 0,
+
+    BS3CG1OP_Eb,
+    BS3CG1OP_Ev,
+
+    BS3CG1OP_Gb,
+    BS3CG1OP_Gv,
+
+    BS3CG1OP_END
+} BS3CG1OP;
+/** Pointer to a const operand enum. */
+typedef const BS3_FAR *PCBS3CG1OP;
+
+
+/**
+ * Instruction encoding format.
+ *
+ * This duplicates some of the info in the operand array, however it makes it
+ * easier to figure out encoding variations.
+ */
 typedef enum BS3CG1ENC
 {
     BS3CG1ENC_INVALID = 0,
-    BS3CG1ENC_FIXED,
-    BS3CG1ENC_MODRM,
+
+    BS3CG1ENC_FIXED_Iz,
+    BS3CG1ENC_FIXED_FIRST = BS3CG1ENC_FIXED_Iz,
+    BS3CG1ENC_FIXED_Iv,
+
+    BS3CG1ENC_MODRM_Eb_Gb,
+    BS3CG1ENC_MODRM_Ev_Gv,
+
     BS3CG1ENC_END
 } BS3CG1ENC;
@@ -45,45 +76,26 @@
 
 /**
- * Operand details.
- *
- * Currently simply using the encoding from the reference manuals.
- */
-typedef enum BS3CG1OP
-{
-    BS3CG1OP_INVALID = 0,
-
-    BS3CG1OP_Eb,
-    BS3CG1OP_Ev,
-
-    BS3CG1OP_Gb,
-    BS3CG1OP_Gv,
-
-    BS3CG1OP_END
-} BS3CG1OP;
-
-
-/**
  * Generated instruction info.
  */
 typedef struct BS3CG1INSTR
 {
-    /** Opcode bytes. */
-    uint8_t     abOpcode[4];
-    /** BS3CG1OP values for each operand. */
-    uint8_t     aenmOperands[4];
     /** The opcode size.   */
     uint32_t    cbOpcode : 2;
     /** The number of operands.   */
     uint32_t    cOperands : 2;
+    /** The length of the mnemonic. */
+    uint32_t    cchMnemonic : 3;
+    /** Whether to advance the mnemonic array pointer. */
+    uint32_t    fAdvanceMnemonic : 1;
+    /** Offset into g_abBs3Cg1Tests of the first test. */
+    uint32_t    offTests : 23;
     /** BS3CG1ENC values. */
-    uint32_t    enmEncoding : 5;
-    /** The length of the mnemonic. */
-    uint32_t    cchMnemonic : 4;
-    /** Index of the test header into g_aBs3Cg1Tests */
-    uint32_t    idxTestHdr : 19;
+    uint32_t    enmEncoding : 10;
+    /** BS3CG1ENC values. */
+    uint32_t    uUnused : 22;
     /** BS3CG1INSTR_F_XXX. */
     uint32_t    fFlags;
 } BS3CG1INSTR;
-AssertCompileSize(BS3CG1INSTR, 16);
+AssertCompileSize(BS3CG1INSTR, 12);
 /** Pointer to a const instruction. */
 typedef BS3CG1INSTR const BS3_FAR *PCBS3CG1INSTR;
@@ -103,8 +115,8 @@
     /** The size of the selector program in bytes.
      * This is also the offset of the input context modification program.  */
-    uint32_t    cbSelector : 9;
+    uint32_t    cbSelector : 8;
     /** The size of the input context modification program in bytes.
      * This immediately follows the selector program.  */
-    uint32_t    cbInput    : 11;
+    uint32_t    cbInput    : 12;
     /** The size of the output context modification program in bytes.
      * This immediately follows the input context modification program.  The
@@ -128,10 +140,10 @@
 #define BS3CG1_CTXOP_SIZE_MASK      UINT8_C(0x07)
 #define BS3CG1_CTXOP_1_BYTE         UINT8_C(0x00)
-#define BS3CG1_CTXOP_2_BYTE         UINT8_C(0x01)
-#define BS3CG1_CTXOP_4_BYTE         UINT8_C(0x02)
-#define BS3CG1_CTXOP_8_BYTE         UINT8_C(0x03)
-#define BS3CG1_CTXOP_16_BYTE        UINT8_C(0x04)
-#define BS3CG1_CTXOP_32_BYTE        UINT8_C(0x05)
-#define BS3CG1_CTXOP_12_BYTE        UINT8_C(0x06)
+#define BS3CG1_CTXOP_2_BYTES        UINT8_C(0x01)
+#define BS3CG1_CTXOP_4_BYTES        UINT8_C(0x02)
+#define BS3CG1_CTXOP_8_BYTES        UINT8_C(0x03)
+#define BS3CG1_CTXOP_16_BYTES       UINT8_C(0x04)
+#define BS3CG1_CTXOP_32_BYTES       UINT8_C(0x05)
+#define BS3CG1_CTXOP_12_BYTES       UINT8_C(0x06)
 #define BS3CG1_CTXOP_SIZE_ESC       UINT8_C(0x07)   /**< Separate byte encoding the value size follows immediately. */
 
@@ -309,14 +321,23 @@
 
 
+/** The test instructions (generated). */
+extern const BS3CG1INSTR BS3_FAR_DATA   g_aBs3Cg1Instructions[];
 /** The number of test instructions (generated). */
-extern uint16_t BS3_FAR_DATA        g_cBs3Cg1Instructions;
-/** The test instructions (generated). */
-extern const char BS3_FAR_DATA      g_aBs3Cg1Instructions[];
-/** The test data that BS3CG1INSTR. */
-extern BS3CG1TESTHDR BS3_FAR_DATA   g_aBs3Cg1Tests[];
+extern const uint16_t BS3_FAR_DATA      g_cBs3Cg1Instructions;
 /** The mnemonics (generated).
  * Variable length sequence of mnemonics that runs in parallel to
  * g_aBs3Cg1Instructions. */
-extern const char BS3_FAR_DATA      g_achBs3Cg1Mnemonics[];
+extern const char BS3_FAR_DATA          g_achBs3Cg1Mnemonics[];
+/** The opcodes (generated).
+ * Variable length sequence of opcode bytes that runs in parallel to
+ * g_aBs3Cg1Instructions, advancing by BS3CG1INSTR::cbOpcode each time. */
+extern const uint8_t BS3_FAR_DATA       g_abBs3Cg1Opcodes[];
+/** The operands (generated).
+ * Variable length sequence of opcode values (BS3CG1OP) that runs in
+ * parallel to g_aBs3Cg1Instructions, advancing by BS3CG1INSTR::cOperands. */
+extern const uint8_t BS3_FAR_DATA       g_abBs3Cg1Operands[];
+/** The test data that BS3CG1INSTR.
+ * In order to simplify generating these, we use a byte array. */
+extern const uint8_t BS3_FAR_DATA       g_abBs3Cg1Tests[];
 
 
