[Pkg-virtualbox-commits] [virtualbox] 01/06: New upstream version 5.1.24-dfsg

Gianfranco Costamagna locutusofborg at moszumanska.debian.org
Tue Jul 18 13:34:54 UTC 2017


This is an automated email from the git hooks/post-receive script.

locutusofborg pushed a commit to branch master
in repository virtualbox.

commit 41e192fb22f05f35649d896369576fc2003c1d58
Author: Gianfranco Costamagna <costamagnagianfranco at yahoo.it>
Date:   Tue Jul 18 15:05:48 2017 +0200

    New upstream version 5.1.24-dfsg
---
 Config.kmk                                         |   25 +-
 Makefile.kmk                                       |   44 -
 README.GuestAdditionsPackaging                     |   14 +
 configure                                          |   51 +-
 configure.vbs                                      |  304 +-
 doc/manual/Makefile.kmk                            |    4 +-
 doc/manual/en_US/user_AdvancedTopics.xml           |    4 +-
 doc/manual/en_US/user_GuestAdditions.xml           |   49 +-
 doc/manual/en_US/user_KnownIssues.xml              |    8 +-
 doc/manual/en_US/user_VBoxManage.xml               |    9 +-
 doc/manual/user_ChangeLogImpl.xml                  |  151 +
 include/VBox/disopcode.h                           |   89 +-
 include/VBox/sup.h                                 |   20 +-
 include/VBox/vmm/cpum.h                            |    1 +
 include/VBox/vmm/dbgf.h                            |   38 +-
 include/VBox/vmm/gvm.h                             |    2 +
 include/VBox/vmm/gvmm.h                            |   10 +-
 include/VBox/vmm/hm_vmx.h                          |   18 +-
 include/VBox/vmm/hm_vmx.mac                        |   10 +-
 include/VBox/vmm/iem.h                             |   63 +
 include/VBox/vmm/pdmaudioifs.h                     |  158 +-
 include/VBox/vmm/vmm.h                             |    6 +-
 include/iprt/asm.h                                 |   16 +-
 include/iprt/cdefs.h                               |   21 +-
 include/iprt/formats/pecoff.h                      |  110 +-
 include/iprt/mangling.h                            |    5 +
 include/iprt/net.h                                 |   24 +
 include/iprt/nt/nt.h                               |    6 +
 include/iprt/string.h                              |   42 +-
 include/iprt/types.h                               |  339 +-
 include/iprt/utf16.h                               |   19 +-
 include/iprt/x86.h                                 |    4 +
 src/VBox/Additions/Makefile.kmk                    |    6 +-
 src/VBox/Additions/common/VBoxGuest/linux/Makefile |    3 +-
 .../common/VBoxGuest/linux/files_vboxguest         |    2 +
 .../common/VBoxService/VBoxServiceToolBox.cpp      |    2 +-
 src/VBox/Additions/common/crOpenGL/DD_glc.py       |    0
 src/VBox/Additions/common/crOpenGL/DD_glh.py       |    0
 .../common/crOpenGL/Linux_i386_exports.py          |    0
 .../common/crOpenGL/Linux_i386_exports_dri.py      |    0
 src/VBox/Additions/common/crOpenGL/NULLfuncs.py    |    0
 src/VBox/Additions/common/crOpenGL/cr_gl.py        |    0
 src/VBox/Additions/common/crOpenGL/defs.py         |    0
 src/VBox/Additions/common/crOpenGL/defs64.py       |    0
 src/VBox/Additions/common/crOpenGL/entrypoints.py  |    0
 .../Additions/common/crOpenGL/feedback/feedback.py |    0
 .../common/crOpenGL/feedback/feedback_funcs.py     |    0
 .../common/crOpenGL/feedback/feedback_state.py     |    0
 .../common/crOpenGL/feedback/feedbackspu_proto.py  |    0
 .../Additions/common/crOpenGL/getprocaddress.py    |    0
 src/VBox/Additions/common/crOpenGL/pack/pack.py    |    0
 .../common/crOpenGL/pack/packspu_beginend.py       |    0
 .../common/crOpenGL/pack/packspu_flush.py          |    0
 .../Additions/common/crOpenGL/pack/packspu_get.py  |    0
 .../common/crOpenGL/pack/packspu_proto.py          |    0
 .../common/crOpenGL/passthrough/passthrough.py     |    0
 src/VBox/Additions/common/crOpenGL/stub_common.py  |    0
 src/VBox/Additions/common/crOpenGL/tsfuncs.py      |    0
 .../Additions/common/crOpenGL/windows_exports.py   |    0
 .../common/crOpenGL/windows_getprocaddress.py      |    0
 .../common/crOpenGL/windows_i386_exports.py        |    0
 src/VBox/Additions/linux/drm/Makefile.module.kms   |    5 +-
 src/VBox/Additions/linux/drm/vbox_dummy.c          |    2 +
 src/VBox/Additions/linux/drm/vbox_ttm.c            |    6 +
 src/VBox/Additions/linux/installer/install.sh.in   |   32 +-
 src/VBox/Additions/linux/installer/vboxadd-x11.sh  |   30 +-
 src/VBox/Additions/linux/installer/vboxadd.sh      |   10 +-
 .../Additions/linux/sharedfolders/Makefile.module  |    1 +
 .../Additions/linux/sharedfolders/files_vboxsf     |    2 +
 .../Additions/linux/sharedfolders/mount.vboxsf.c   |    2 +
 src/VBox/Additions/linux/sharedfolders/vfsmod.c    |    1 +
 src/VBox/Additions/x11/VBoxClient/draganddrop.cpp  |    1 +
 src/VBox/Additions/x11/VBoxClient/seamless.cpp     |   29 -
 .../x11/VBoxClient/testcase/tstSeamlessX11.cpp     |   10 -
 src/VBox/Debugger/DBGCEmulateCodeView.cpp          |    1 +
 src/VBox/Debugger/DBGCOps.cpp                      |   12 +-
 src/VBox/Debugger/DBGConsole.cpp                   |    7 +
 src/VBox/Debugger/DBGPlugInLinux.cpp               |  541 ++-
 src/VBox/Devices/Audio/AudioMixBuffer.cpp          | 1423 ++++----
 src/VBox/Devices/Audio/AudioMixBuffer.h            |   28 +-
 src/VBox/Devices/Audio/AudioMixer.cpp              |   17 +-
 src/VBox/Devices/Audio/DevHDA.cpp                  | 3503 +++++++++++++------
 src/VBox/Devices/Audio/DevHDA.h                    |  176 +
 src/VBox/Devices/Audio/DevIchAc97.cpp              |  414 ++-
 src/VBox/Devices/Audio/DevSB16.cpp                 |  144 +-
 src/VBox/Devices/Audio/DrvAudio.cpp                |  244 +-
 src/VBox/Devices/Audio/DrvAudio.h                  |   25 +-
 src/VBox/Devices/Audio/DrvAudioCommon.cpp          |  162 +-
 src/VBox/Devices/Audio/DrvHostALSAAudio.cpp        |  146 +-
 src/VBox/Devices/Audio/DrvHostCoreAudio.cpp        |  119 +-
 src/VBox/Devices/Audio/DrvHostDSound.cpp           |   95 +-
 src/VBox/Devices/Audio/DrvHostNullAudio.cpp        |   56 +-
 src/VBox/Devices/Audio/DrvHostOSSAudio.cpp         |   95 +-
 src/VBox/Devices/Audio/DrvHostPulseAudio.cpp       |  205 +-
 src/VBox/Devices/Audio/HDACodec.cpp                |   15 +-
 .../Devices/Audio/{DevIchHdaCodec.h => HDACodec.h} |   13 +-
 src/VBox/Devices/Audio/HDAStreamPeriod.cpp         |  419 +++
 src/VBox/Devices/Audio/HDAStreamPeriod.h           |  109 +
 src/VBox/Devices/Audio/pulse_mangling.h            |    8 +-
 src/VBox/Devices/Audio/pulse_stubs.c               |   26 +-
 src/VBox/Devices/Audio/testcase/Makefile.kmk       |    2 +-
 .../Devices/Audio/testcase/tstAudioMixBuffer.cpp   |  500 +--
 src/VBox/Devices/Bus/DevPCI.cpp                    |   11 +-
 src/VBox/Devices/Bus/DevPciIch9.cpp                |   93 +-
 src/VBox/Devices/EFI/DevEFI.cpp                    |   19 +
 src/VBox/Devices/EFI/DevEFI.h                      |    2 +
 .../Applications/Python/PyMod-2.7.2/Lib/ntpath.py  |    0
 .../BaseTools/Scripts/ConvertMasmToNasm.py         |    0
 .../BaseTools/Scripts/UpdateBuildVersions.py       |    0
 .../BaseTools/Source/C/PyEfiCompressor/setup.py    |    0
 .../Firmware/BaseTools/Source/C/PyUtility/setup.py |    0
 .../BaseTools/Source/Python/AutoGen/AutoGen.py     |    0
 .../BaseTools/Source/Python/AutoGen/BuildEngine.py |    0
 .../BaseTools/Source/Python/AutoGen/GenC.py        |    0
 .../BaseTools/Source/Python/AutoGen/GenDepex.py    |    0
 .../BaseTools/Source/Python/AutoGen/GenMake.py     |    0
 .../BaseTools/Source/Python/AutoGen/GenPcdDb.py    |    0
 .../Source/Python/AutoGen/InfSectionParser.py      |    0
 .../BaseTools/Source/Python/AutoGen/StrGather.py   |    0
 .../Source/Python/AutoGen/UniClassObject.py        |    0
 .../Firmware/BaseTools/Source/Python/BPDG/BPDG.py  |    0
 .../BaseTools/Source/Python/BPDG/GenVpd.py         |    0
 .../BaseTools/Source/Python/Common/Database.py     |    0
 .../Source/Python/Common/DecClassObject.py         |    0
 .../BaseTools/Source/Python/Common/Dictionary.py   |    0
 .../Source/Python/Common/DscClassObject.py         |    0
 .../Source/Python/Common/EdkIIWorkspace.py         |    0
 .../Source/Python/Common/EdkIIWorkspaceBuild.py    |    0
 .../BaseTools/Source/Python/Common/EdkLogger.py    |    0
 .../BaseTools/Source/Python/Common/Expression.py   |    0
 .../Source/Python/Common/FdfClassObject.py         |    0
 .../Source/Python/Common/FdfParserLite.py          |    0
 .../Source/Python/Common/Identification.py         |    0
 .../Source/Python/Common/InfClassObject.py         |    0
 .../Source/Python/Common/LongFilePathOs.py         |    0
 .../Source/Python/Common/LongFilePathOsPath.py     |    0
 .../Source/Python/Common/LongFilePathSupport.py    |    0
 .../Source/Python/Common/MigrationUtilities.py     |    0
 .../BaseTools/Source/Python/Common/Misc.py         |    0
 .../BaseTools/Source/Python/Common/Parsing.py      |    0
 .../BaseTools/Source/Python/Common/String.py       |    0
 .../Source/Python/Common/TargetTxtClassObject.py   |    0
 .../Source/Python/Common/ToolDefClassObject.py     |    0
 .../BaseTools/Source/Python/Common/VpdInfoFile.py  |    0
 .../Source/Python/CommonDataClass/CommonClass.py   |    0
 .../Source/Python/CommonDataClass/FdfClass.py      |    0
 .../Source/Python/CommonDataClass/ModuleClass.py   |    0
 .../Source/Python/CommonDataClass/PackageClass.py  |    0
 .../Source/Python/CommonDataClass/PlatformClass.py |    0
 .../EFI/Firmware/BaseTools/Source/Python/Ecc/C.g   |    0
 .../Firmware/BaseTools/Source/Python/Ecc/CLexer.py |    0
 .../BaseTools/Source/Python/Ecc/CParser.py         |    0
 .../Firmware/BaseTools/Source/Python/Ecc/Check.py  |    0
 .../BaseTools/Source/Python/Ecc/CodeFragment.py    |    0
 .../Source/Python/Ecc/CodeFragmentCollector.py     |    0
 .../BaseTools/Source/Python/Ecc/Configuration.py   |    0
 .../BaseTools/Source/Python/Ecc/Database.py        |    0
 .../Firmware/BaseTools/Source/Python/Ecc/Ecc.py    |    0
 .../BaseTools/Source/Python/Ecc/Exception.py       |    0
 .../BaseTools/Source/Python/Ecc/FileProfile.py     |    0
 .../BaseTools/Source/Python/Ecc/MetaDataParser.py  |    0
 .../Python/Ecc/MetaFileWorkspace/MetaDataTable.py  |    0
 .../Python/Ecc/MetaFileWorkspace/MetaFileParser.py |    0
 .../Python/Ecc/MetaFileWorkspace/MetaFileTable.py  |    0
 .../BaseTools/Source/Python/Ecc/ParserWarning.py   |    0
 .../BaseTools/Source/Python/Ecc/Xml/XmlRoutines.py |    0
 .../EFI/Firmware/BaseTools/Source/Python/Ecc/c.py  |    0
 .../Firmware/BaseTools/Source/Python/Eot/CLexer.py |    0
 .../BaseTools/Source/Python/Eot/CParser.py         |    0
 .../BaseTools/Source/Python/Eot/CodeFragment.py    |    0
 .../Source/Python/Eot/CodeFragmentCollector.py     |    0
 .../BaseTools/Source/Python/Eot/Database.py        |    0
 .../Firmware/BaseTools/Source/Python/Eot/Eot.py    |    0
 .../BaseTools/Source/Python/Eot/EotGlobalData.py   |    0
 .../BaseTools/Source/Python/Eot/FileProfile.py     |    0
 .../BaseTools/Source/Python/Eot/FvImage.py         |    0
 .../BaseTools/Source/Python/Eot/InfParserLite.py   |    0
 .../Firmware/BaseTools/Source/Python/Eot/Parser.py |    0
 .../BaseTools/Source/Python/Eot/ParserWarning.py   |    0
 .../Firmware/BaseTools/Source/Python/Eot/Report.py |    0
 .../EFI/Firmware/BaseTools/Source/Python/Eot/c.py  |    0
 .../Source/Python/GenFds/AprioriSection.py         |    0
 .../BaseTools/Source/Python/GenFds/Attribute.py    |    0
 .../BaseTools/Source/Python/GenFds/Capsule.py      |    0
 .../BaseTools/Source/Python/GenFds/CapsuleData.py  |    0
 .../Source/Python/GenFds/ComponentStatement.py     |    0
 .../Source/Python/GenFds/CompressSection.py        |    0
 .../BaseTools/Source/Python/GenFds/DataSection.py  |    0
 .../BaseTools/Source/Python/GenFds/DepexSection.py |    0
 .../BaseTools/Source/Python/GenFds/EfiSection.py   |    0
 .../Firmware/BaseTools/Source/Python/GenFds/Fd.py  |    0
 .../BaseTools/Source/Python/GenFds/FdfParser.py    |    0
 .../Firmware/BaseTools/Source/Python/GenFds/Ffs.py |    0
 .../Source/Python/GenFds/FfsFileStatement.py       |    0
 .../Source/Python/GenFds/FfsInfStatement.py        |    0
 .../Firmware/BaseTools/Source/Python/GenFds/Fv.py  |    0
 .../Source/Python/GenFds/FvImageSection.py         |    0
 .../BaseTools/Source/Python/GenFds/GenFds.py       |    0
 .../Source/Python/GenFds/GenFdsGlobalVariable.py   |    0
 .../BaseTools/Source/Python/GenFds/GuidSection.py  |    0
 .../Source/Python/GenFds/OptRomFileStatement.py    |    0
 .../Source/Python/GenFds/OptRomInfStatement.py     |    0
 .../BaseTools/Source/Python/GenFds/OptionRom.py    |    0
 .../BaseTools/Source/Python/GenFds/Region.py       |    0
 .../BaseTools/Source/Python/GenFds/Rule.py         |    0
 .../Source/Python/GenFds/RuleComplexFile.py        |    0
 .../Source/Python/GenFds/RuleSimpleFile.py         |    0
 .../BaseTools/Source/Python/GenFds/Section.py      |    0
 .../BaseTools/Source/Python/GenFds/UiSection.py    |    0
 .../BaseTools/Source/Python/GenFds/VerSection.py   |    0
 .../Firmware/BaseTools/Source/Python/GenFds/Vtf.py |    0
 .../Python/GenPatchPcdTable/GenPatchPcdTable.py    |    0
 .../Source/Python/PatchPcdValue/PatchPcdValue.py   |    0
 .../Rsa2048Sha256Sign/Rsa2048Sha256GenerateKeys.py |    0
 .../Python/Rsa2048Sha256Sign/Rsa2048Sha256Sign.py  |    0
 .../BaseTools/Source/Python/Table/Table.py         |    0
 .../Source/Python/Table/TableDataModel.py          |    0
 .../BaseTools/Source/Python/Table/TableDec.py      |    0
 .../BaseTools/Source/Python/Table/TableDsc.py      |    0
 .../Source/Python/Table/TableEotReport.py          |    0
 .../BaseTools/Source/Python/Table/TableFdf.py      |    0
 .../BaseTools/Source/Python/Table/TableFile.py     |    0
 .../BaseTools/Source/Python/Table/TableFunction.py |    0
 .../Source/Python/Table/TableIdentifier.py         |    0
 .../BaseTools/Source/Python/Table/TableInf.py      |    0
 .../BaseTools/Source/Python/Table/TablePcd.py      |    0
 .../BaseTools/Source/Python/Table/TableQuery.py    |    0
 .../BaseTools/Source/Python/Table/TableReport.py   |    0
 .../Source/Python/TargetTool/TargetTool.py         |    0
 .../Firmware/BaseTools/Source/Python/Trim/Trim.py  |    0
 .../Source/Python/UPT/Core/DependencyRules.py      |    0
 .../Python/UPT/Core/DistributionPackageClass.py    |    0
 .../BaseTools/Source/Python/UPT/Core/FileHook.py   |    0
 .../BaseTools/Source/Python/UPT/Core/IpiDb.py      |    0
 .../Source/Python/UPT/Core/PackageFile.py          |    0
 .../Source/Python/UPT/GenMetaFile/GenDecFile.py    |    0
 .../Source/Python/UPT/GenMetaFile/GenInfFile.py    |    0
 .../Python/UPT/GenMetaFile/GenMetaFileMisc.py      |    0
 .../BaseTools/Source/Python/UPT/InstallPkg.py      |    0
 .../BaseTools/Source/Python/UPT/InventoryWs.py     |    0
 .../Source/Python/UPT/Library/CommentGenerating.py |    0
 .../Source/Python/UPT/Library/CommentParsing.py    |    0
 .../Python/UPT/Library/ExpressionValidate.py       |    0
 .../BaseTools/Source/Python/UPT/Library/Misc.py    |    0
 .../Source/Python/UPT/Library/ParserValidate.py    |    0
 .../BaseTools/Source/Python/UPT/Library/Parsing.py |    0
 .../BaseTools/Source/Python/UPT/Library/String.py  |    0
 .../Source/Python/UPT/Library/UniClassObject.py    |    0
 .../Source/Python/UPT/Library/Xml/XmlRoutines.py   |    0
 .../BaseTools/Source/Python/UPT/Logger/Log.py      |    0
 .../Firmware/BaseTools/Source/Python/UPT/MkPkg.py  |    0
 .../Source/Python/UPT/Object/POM/CommonObject.py   |    0
 .../Source/Python/UPT/Object/POM/ModuleObject.py   |    0
 .../Source/Python/UPT/Object/POM/PackageObject.py  |    0
 .../Source/Python/UPT/Object/Parser/DecObject.py   |    0
 .../Python/UPT/Object/Parser/InfBinaryObject.py    |    0
 .../UPT/Object/Parser/InfBuildOptionObject.py      |    0
 .../Python/UPT/Object/Parser/InfCommonObject.py    |    0
 .../UPT/Object/Parser/InfDefineCommonObject.py     |    0
 .../Python/UPT/Object/Parser/InfDefineObject.py    |    0
 .../Python/UPT/Object/Parser/InfDepexObject.py     |    0
 .../Python/UPT/Object/Parser/InfGuidObject.py      |    0
 .../Python/UPT/Object/Parser/InfHeaderObject.py    |    0
 .../UPT/Object/Parser/InfLibraryClassesObject.py   |    0
 .../Source/Python/UPT/Object/Parser/InfMisc.py     |    0
 .../Python/UPT/Object/Parser/InfPackagesObject.py  |    0
 .../Python/UPT/Object/Parser/InfPcdObject.py       |    0
 .../Python/UPT/Object/Parser/InfPpiObject.py       |    0
 .../Python/UPT/Object/Parser/InfProtocolObject.py  |    0
 .../Python/UPT/Object/Parser/InfSoucesObject.py    |    0
 .../UPT/Object/Parser/InfUserExtensionObject.py    |    0
 .../Source/Python/UPT/Parser/DecParser.py          |    0
 .../Source/Python/UPT/Parser/DecParserMisc.py      |    0
 .../Source/Python/UPT/Parser/InfAsBuiltProcess.py  |    0
 .../Python/UPT/Parser/InfBinarySectionParser.py    |    0
 .../UPT/Parser/InfBuildOptionSectionParser.py      |    0
 .../Python/UPT/Parser/InfDefineSectionParser.py    |    0
 .../Python/UPT/Parser/InfDepexSectionParser.py     |    0
 .../UPT/Parser/InfGuidPpiProtocolSectionParser.py  |    0
 .../Python/UPT/Parser/InfLibrarySectionParser.py   |    0
 .../Python/UPT/Parser/InfPackageSectionParser.py   |    0
 .../Source/Python/UPT/Parser/InfParser.py          |    0
 .../Source/Python/UPT/Parser/InfParserMisc.py      |    0
 .../Python/UPT/Parser/InfPcdSectionParser.py       |    0
 .../Source/Python/UPT/Parser/InfSectionParser.py   |    0
 .../Python/UPT/Parser/InfSourceSectionParser.py    |    0
 .../Python/UPT/PomAdapter/DecPomAlignment.py       |    0
 .../Python/UPT/PomAdapter/InfPomAlignment.py       |    0
 .../Python/UPT/PomAdapter/InfPomAlignmentMisc.py   |    0
 .../BaseTools/Source/Python/UPT/ReplacePkg.py      |    0
 .../Firmware/BaseTools/Source/Python/UPT/RmPkg.py  |    0
 .../Firmware/BaseTools/Source/Python/UPT/UPT.py    |    0
 .../UPT/UnitTest/CommentGeneratingUnitTest.py      |    0
 .../Python/UPT/UnitTest/CommentParsingUnitTest.py  |    0
 .../Source/Python/UPT/UnitTest/DecParserTest.py    |    0
 .../Python/UPT/UnitTest/DecParserUnitTest.py       |    0
 .../Python/UPT/UnitTest/InfBinarySectionTest.py    |    0
 .../BaseTools/Source/Python/UPT/Xml/CommonXml.py   |    0
 .../Source/Python/UPT/Xml/GuidProtocolPpiXml.py    |    0
 .../BaseTools/Source/Python/UPT/Xml/IniToXml.py    |    0
 .../Source/Python/UPT/Xml/ModuleSurfaceAreaXml.py  |    0
 .../Source/Python/UPT/Xml/PackageSurfaceAreaXml.py |    0
 .../BaseTools/Source/Python/UPT/Xml/PcdXml.py      |    0
 .../BaseTools/Source/Python/UPT/Xml/XmlParser.py   |    0
 .../Source/Python/UPT/Xml/XmlParserMisc.py         |    0
 .../Source/Python/Workspace/BuildClassObject.py    |    0
 .../Source/Python/Workspace/MetaDataTable.py       |    0
 .../Python/Workspace/MetaFileCommentParser.py      |    0
 .../Source/Python/Workspace/MetaFileParser.py      |    0
 .../Source/Python/Workspace/MetaFileTable.py       |    0
 .../Source/Python/Workspace/WorkspaceCommon.py     |    0
 .../Source/Python/Workspace/WorkspaceDatabase.py   |    0
 .../BaseTools/Source/Python/build/BuildReport.py   |    0
 .../BaseTools/Source/Python/build/build.py         |    0
 .../Firmware/IntelFspPkg/FspSecCore/Vtf0/Build.py  |    0
 .../FspSecCore/Vtf0/Tools/FixupForRawSection.py    |    0
 .../EFI/Firmware/IntelFspPkg/Tools/GenCfgOpt.py    |    0
 .../EFI/Firmware/IntelFspPkg/Tools/PatchFv.py      |    0
 .../FspWrapperSecCore/Vtf0/Build.py                |    0
 .../Vtf0/Tools/FixupForRawSection.py               |    0
 .../EFI/Firmware/OvmfPkg/PlatformPei/Platform.c    |   36 +
 .../Firmware/OvmfPkg/PlatformPei/PlatformPei.inf   |    1 +
 .../Firmware/UefiCpuPkg/ResetVector/Vtf0/Build.py  |    0
 src/VBox/Devices/EFI/FirmwareBin/VBoxEFI32.fd      |  Bin 2097152 -> 2097152 bytes
 src/VBox/Devices/EFI/FirmwareBin/VBoxEFI64.fd      |  Bin 2097152 -> 2097152 bytes
 src/VBox/Devices/Graphics/DevVGA-SVGA3d-internal.h |    7 +
 src/VBox/Devices/Graphics/DevVGA-SVGA3d-ogl.cpp    |   12 +-
 src/VBox/Devices/Graphics/DevVGA-SVGA3d-shared.cpp |   73 +
 src/VBox/Devices/Graphics/DevVGA-SVGA3d-win.cpp    |  267 +-
 src/VBox/Devices/Graphics/DevVGA-SVGA3d.cpp        |  129 +-
 src/VBox/Devices/Graphics/DevVGA-SVGA3d.h          |    2 +
 src/VBox/Devices/Graphics/DevVGA.cpp               |    2 +-
 src/VBox/Devices/Graphics/DevVGA_VDMA.cpp          |    1 +
 src/VBox/Devices/Input/DevPS2.cpp                  |    1 +
 src/VBox/Devices/Input/PS2K.cpp                    |    1 +
 src/VBox/Devices/Input/PS2M.cpp                    |    1 +
 src/VBox/Devices/Makefile.kmk                      |   10 +-
 src/VBox/Devices/Misc/VirtualKD.cpp                |   14 +-
 src/VBox/Devices/Network/DevE1000.cpp              |   25 +-
 src/VBox/Devices/Network/DevVirtioNet.cpp          |  149 +-
 .../Devices/Network/slirp/libalias/alias_ftp.c     |    1 +
 src/VBox/Devices/PC/DevACPI.cpp                    |    4 +-
 src/VBox/Devices/PC/DevDMA.cpp                     |    1 +
 src/VBox/Devices/PC/DevPcBios.cpp                  |   10 +-
 src/VBox/Devices/PC/ipxe/src/include/curses.h      |    2 +-
 src/VBox/Devices/Storage/DevAHCI.cpp               |   25 +-
 src/VBox/Devices/Storage/DevATA.cpp                |    8 +
 src/VBox/Devices/Storage/DevBusLogic.cpp           |    6 +-
 src/VBox/Devices/Storage/DevLsiLogicSCSI.cpp       |   13 +-
 src/VBox/Devices/Storage/DrvVD.cpp                 |    1 +
 src/VBox/Devices/Storage/UsbMsd.cpp                |    3 +-
 src/VBox/Devices/Storage/VSCSI/VSCSILunMmc.cpp     |    2 +
 src/VBox/Devices/Storage/VSCSI/VSCSILunSbc.cpp     |    1 +
 src/VBox/Devices/USB/USBProxyDevice.cpp            |   51 +
 src/VBox/Devices/build/VBoxDD.cpp                  |    5 +
 src/VBox/Devices/build/VBoxDD.h                    |    3 +
 .../Devices/testcase/tstDeviceStructSizeRC.cpp     |   31 +-
 src/VBox/Disassembler/DisasmCore.cpp               |    6 +-
 src/VBox/Disassembler/DisasmFormatYasm.cpp         |    3 +-
 .../VBoxDTrace/onnv/cmd/dtrace/demo/mkdemo.pl      |    0
 .../dtrace/test/tst/common/ip/tst.ipv4localtcp.ksh |    0
 .../dtrace/test/tst/common/ip/tst.ipv4localudp.ksh |    0
 .../test/tst/common/ip/tst.ipv4remotetcp.ksh       |    0
 .../test/tst/common/ip/tst.ipv4remoteudp.ksh       |    0
 .../test/tst/common/ip/tst.localtcpstate.ksh       |    0
 .../test/tst/common/ip/tst.remotetcpstate.ksh      |    0
 .../scripting/err.D_MACRO_UNDEF.invalidargs.d      |    0
 .../tst/common/scripting/err.D_OP_LVAL.rdonly.d    |    0
 .../common/scripting/err.D_OP_WRITE.usepidmacro.d  |    0
 .../test/tst/common/scripting/err.D_SYNTAX.inval.d |    0
 .../test/tst/common/scripting/err.D_SYNTAX.pid.d   |    0
 .../dtrace/test/tst/common/scripting/tst.arg0.d    |    0
 .../dtrace/test/tst/common/scripting/tst.assign.d  |    0
 .../dtrace/test/tst/common/scripting/tst.basic.d   |    0
 .../dtrace/test/tst/common/scripting/tst.egid.d    |    0
 .../dtrace/test/tst/common/scripting/tst.euid.d    |    0
 .../cmd/dtrace/test/tst/common/scripting/tst.gid.d |    0
 .../dtrace/test/tst/common/scripting/tst.pgid.d    |    0
 .../cmd/dtrace/test/tst/common/scripting/tst.pid.d |    0
 .../dtrace/test/tst/common/scripting/tst.ppid.d    |    0
 .../dtrace/test/tst/common/scripting/tst.projid.d  |    0
 .../dtrace/test/tst/common/scripting/tst.quite.d   |    0
 .../cmd/dtrace/test/tst/common/scripting/tst.sid.d |    0
 .../dtrace/test/tst/common/scripting/tst.taskid.d  |    0
 .../dtrace/test/tst/common/scripting/tst.trace.d   |    0
 .../cmd/dtrace/test/tst/common/scripting/tst.uid.d |    0
 .../err.D_ACT_SPEC.SpeculateWithBreakPoint.d       |    0
 .../err.D_ACT_SPEC.SpeculateWithChill.d            |    0
 .../err.D_ACT_SPEC.SpeculateWithCopyOut.d          |    0
 .../err.D_ACT_SPEC.SpeculateWithCopyOutStr.d       |    0
 .../err.D_ACT_SPEC.SpeculateWithPanic.d            |    0
 .../err.D_ACT_SPEC.SpeculateWithRaise.d            |    0
 .../speculation/err.D_ACT_SPEC.SpeculateWithStop.d |    0
 .../dtrace/test/tst/common/usdt/tst.corruptenv.ksh |    0
 .../onnv/lib/libdtrace/common/mkerrtags.sh         |    0
 .../Frontends/VBoxManage/VBoxManageControlVM.cpp   |    2 +-
 src/VBox/Frontends/VBoxManage/VBoxManageDisk.cpp   |    7 +-
 src/VBox/Frontends/VBoxManage/VBoxManageHelp.cpp   |    2 +-
 .../Frontends/VBoxManage/VBoxManageModifyVM.cpp    |    8 +
 src/VBox/Frontends/VBoxSDL/VBoxSDL.cpp             |    2 +-
 src/VBox/Frontends/VirtualBox/nls/VirtualBox_bg.ts |   12 +-
 src/VBox/Frontends/VirtualBox/nls/VirtualBox_ca.ts |    8 +-
 .../Frontends/VirtualBox/nls/VirtualBox_ca_VA.ts   |   12 +-
 src/VBox/Frontends/VirtualBox/nls/VirtualBox_cs.ts |   12 +-
 src/VBox/Frontends/VirtualBox/nls/VirtualBox_da.ts |   12 +-
 src/VBox/Frontends/VirtualBox/nls/VirtualBox_de.ts |   20 +-
 src/VBox/Frontends/VirtualBox/nls/VirtualBox_el.ts |  146 +-
 src/VBox/Frontends/VirtualBox/nls/VirtualBox_es.ts |   12 +-
 src/VBox/Frontends/VirtualBox/nls/VirtualBox_eu.ts |   12 +-
 .../Frontends/VirtualBox/nls/VirtualBox_fa_IR.ts   |   12 +-
 src/VBox/Frontends/VirtualBox/nls/VirtualBox_fi.ts |   12 +-
 src/VBox/Frontends/VirtualBox/nls/VirtualBox_fr.ts |   12 +-
 .../Frontends/VirtualBox/nls/VirtualBox_gl_ES.ts   |   12 +-
 src/VBox/Frontends/VirtualBox/nls/VirtualBox_he.ts |    8 +-
 src/VBox/Frontends/VirtualBox/nls/VirtualBox_hu.ts |   12 +-
 src/VBox/Frontends/VirtualBox/nls/VirtualBox_id.ts |   12 +-
 src/VBox/Frontends/VirtualBox/nls/VirtualBox_it.ts |   12 +-
 src/VBox/Frontends/VirtualBox/nls/VirtualBox_ja.ts |   12 +-
 .../Frontends/VirtualBox/nls/VirtualBox_km_KH.ts   |   12 +-
 src/VBox/Frontends/VirtualBox/nls/VirtualBox_ko.ts |   12 +-
 src/VBox/Frontends/VirtualBox/nls/VirtualBox_lt.ts |   18 +-
 src/VBox/Frontends/VirtualBox/nls/VirtualBox_nl.ts |   12 +-
 src/VBox/Frontends/VirtualBox/nls/VirtualBox_pl.ts |   36 +-
 src/VBox/Frontends/VirtualBox/nls/VirtualBox_pt.ts |   12 +-
 .../Frontends/VirtualBox/nls/VirtualBox_pt_BR.ts   |   12 +-
 src/VBox/Frontends/VirtualBox/nls/VirtualBox_ro.ts |   12 +-
 src/VBox/Frontends/VirtualBox/nls/VirtualBox_ru.ts |   12 +-
 src/VBox/Frontends/VirtualBox/nls/VirtualBox_sk.ts |   12 +-
 src/VBox/Frontends/VirtualBox/nls/VirtualBox_sl.ts |   10 +-
 src/VBox/Frontends/VirtualBox/nls/VirtualBox_sr.ts |   12 +-
 src/VBox/Frontends/VirtualBox/nls/VirtualBox_sv.ts |   12 +-
 src/VBox/Frontends/VirtualBox/nls/VirtualBox_th.ts |    8 +-
 src/VBox/Frontends/VirtualBox/nls/VirtualBox_tr.ts |   12 +-
 src/VBox/Frontends/VirtualBox/nls/VirtualBox_uk.ts |   12 +-
 .../Frontends/VirtualBox/nls/VirtualBox_xx_YY.ts   |    8 +-
 .../Frontends/VirtualBox/nls/VirtualBox_zh_CN.ts   |   12 +-
 .../Frontends/VirtualBox/nls/VirtualBox_zh_TW.ts   |    8 +-
 src/VBox/Frontends/VirtualBox/nls/qt_el.ts         |  366 +-
 src/VBox/Frontends/VirtualBox/nls/qt_pl.ts         |    6 +-
 src/VBox/Frontends/VirtualBox/nls/qt_sr.ts         |    1 -
 .../Frontends/VirtualBox/src/VBoxFBOverlay.cpp     |    2 +
 .../VirtualBox/src/extradata/UIExtraDataDefs.cpp   |    2 +
 .../VirtualBox/src/extradata/UIExtraDataDefs.h     |    4 +
 .../src/extradata/UIExtraDataManager.cpp           |   30 +-
 .../VirtualBox/src/extradata/UIExtraDataManager.h  |   10 +
 src/VBox/Frontends/VirtualBox/src/precomp.h        |    2 -
 .../VirtualBox/src/runtime/UIMachineView.cpp       |  123 +-
 .../VirtualBox/src/runtime/UIMouseHandler.cpp      |    2 +
 .../VirtualBox/src/runtime/UISlidingToolBar.cpp    |   71 +-
 .../VirtualBox/src/runtime/UISlidingToolBar.h      |   22 +-
 .../fullscreen/UIMachineWindowFullscreen.cpp       |    3 +-
 .../src/runtime/normal/UIMachineWindowNormal.cpp   |    9 +-
 .../runtime/seamless/UIMachineWindowSeamless.cpp   |    3 +-
 .../selector/graphics/chooser/UIGChooserModel.cpp  |    2 +
 .../graphics/details/UIGMachinePreview.cpp         |    1 +
 .../settings/global/UIGlobalSettingsNetwork.cpp    |    6 +-
 .../global/UIGlobalSettingsNetworkDetailsHost.ui   |    4 +-
 .../VirtualBox/src/widgets/UIFilmContainer.cpp     |    0
 .../VirtualBox/src/widgets/UIMiniToolBar.cpp       |  150 +-
 .../VirtualBox/src/widgets/UIMiniToolBar.h         |   17 +-
 src/VBox/GuestHost/OpenGL/error/error.py           |    0
 src/VBox/GuestHost/OpenGL/packer/opcodes.py        |    0
 src/VBox/GuestHost/OpenGL/packer/pack_client.c     |   20 +-
 src/VBox/GuestHost/OpenGL/packer/pack_current.py   |    0
 .../GuestHost/OpenGL/packer/pack_currentheader.py  |    0
 src/VBox/GuestHost/OpenGL/packer/pack_header.py    |    0
 src/VBox/GuestHost/OpenGL/packer/pack_swap.py      |    0
 src/VBox/GuestHost/OpenGL/packer/packer.py         |    0
 src/VBox/GuestHost/OpenGL/packer/packer_bbox.py    |    0
 src/VBox/GuestHost/OpenGL/spu_loader/dispatch.py   |    0
 .../GuestHost/OpenGL/spu_loader/dispatchheader.py  |    0
 src/VBox/GuestHost/OpenGL/spu_loader/glloader.py   |    0
 src/VBox/GuestHost/OpenGL/spu_loader/spuchange.py  |    0
 src/VBox/GuestHost/OpenGL/spu_loader/spucopy.py    |    0
 src/VBox/GuestHost/OpenGL/state_tracker/convert.py |    0
 .../GuestHost/OpenGL/state_tracker/dump_gen.py     |    0
 .../GuestHost/OpenGL/state_tracker/gendiffcode.py  |    0
 .../OpenGL/state_tracker/get_components.py         |    0
 .../GuestHost/OpenGL/state_tracker/state_buffer.c  |    6 +
 .../OpenGL/state_tracker/state_current.py          |    0
 .../GuestHost/OpenGL/state_tracker/state_funcs.py  |    0
 .../GuestHost/OpenGL/state_tracker/state_get.py    |    0
 .../OpenGL/state_tracker/state_isenabled.py        |    0
 .../GuestHost/OpenGL/state_tracker/state_polygon.c |    1 +
 src/VBox/GuestHost/OpenGL/util/debug_opcodes.py    |    0
 src/VBox/HostDrivers/Support/Makefile.kmk          |    1 +
 src/VBox/HostDrivers/Support/SUPDrv.cpp            |  319 +-
 src/VBox/HostDrivers/Support/SUPDrvIOC.h           |   28 +-
 src/VBox/HostDrivers/Support/SUPDrvInternal.h      |   16 +-
 src/VBox/HostDrivers/Support/SUPLib.cpp            |   36 +-
 src/VBox/HostDrivers/Support/SUPR3HardenedMain.cpp |    1 +
 .../HostDrivers/Support/SUPR3HardenedVerify.cpp    |   28 +-
 src/VBox/HostDrivers/Support/linux/Makefile        |    1 +
 src/VBox/HostDrivers/Support/linux/SUPDrv-linux.c  |   18 +-
 src/VBox/HostDrivers/Support/linux/files_vboxdrv   |    2 +
 .../Support/posix/SUPR3HardenedMain-posix.cpp      |   45 +-
 src/VBox/HostDrivers/Support/testcase/tstInt.cpp   |   43 +-
 src/VBox/HostDrivers/Support/win/SUPDrv-win.cpp    |    4 +-
 src/VBox/HostDrivers/Support/win/SUPDrvA-win.asm   |   14 -
 .../Support/win/SUPHardenedVerifyProcess-win.cpp   |    4 +-
 .../Support/win/SUPR3HardenedMain-win.cpp          |  330 +-
 .../Support/win/import-template-ntdll.h            |    1 +
 src/VBox/HostDrivers/VBoxNetAdp/linux/Makefile     |    1 +
 .../HostDrivers/VBoxNetAdp/linux/files_vboxnetadp  |    4 +-
 src/VBox/HostDrivers/VBoxNetFlt/linux/Makefile     |    1 +
 .../HostDrivers/VBoxNetFlt/linux/files_vboxnetflt  |    2 +
 .../HostDrivers/VBoxNetFlt/win/cfg/VBoxNetCfg.cpp  |    2 +-
 src/VBox/HostDrivers/VBoxPci/linux/Makefile        |    1 +
 src/VBox/HostDrivers/VBoxPci/linux/files_vboxpci   |    2 +
 src/VBox/HostDrivers/VBoxUSB/USBFilter.cpp         |    4 +
 src/VBox/HostDrivers/adpctl/VBoxNetAdpCtl.cpp      |  784 +++--
 .../SharedOpenGL/crserverlib/get_sizes.py          |    0
 .../SharedOpenGL/crserverlib/server_dispatch.py    |    0
 .../crserverlib/server_dispatch_header.py          |    0
 .../SharedOpenGL/crserverlib/server_get.py         |    0
 .../SharedOpenGL/crserverlib/server_retval.py      |    0
 .../SharedOpenGL/crserverlib/server_simpleget.py   |    0
 .../HostServices/SharedOpenGL/dlm/dlm_generated.py |    0
 .../HostServices/SharedOpenGL/unpacker/unpack.py   |    0
 .../SharedOpenGL/unpacker/unpack_extend.py         |    0
 .../SharedOpenGL/unpacker/unpack_header.py         |    0
 src/VBox/Installer/Makefile.kmk                    |    1 -
 src/VBox/Installer/linux/Makefile.kmk              |    1 +
 src/VBox/Installer/linux/distributions_rpm         |    1 +
 src/VBox/Installer/linux/install.sh                |   22 +
 src/VBox/Installer/linux/postinst-common.sh        |    9 +-
 src/VBox/Installer/linux/routines.sh               |   10 +-
 src/VBox/Installer/linux/rpm/VirtualBox.tmpl.spec  |    5 +-
 src/VBox/Installer/linux/rpm/rules                 |    7 +-
 src/VBox/Installer/solaris/Makefile.kmk            |    1 +
 src/VBox/Main/Makefile.kmk                         |    4 +-
 src/VBox/Main/glue/constants-python.xsl            |    0
 src/VBox/Main/glue/vboxapi.py                      |    0
 src/VBox/Main/include/GuestCtrlImplPrivate.h       |    4 +-
 src/VBox/Main/include/GuestOSTypeImpl.h            |    1 +
 src/VBox/Main/include/MachineImpl.h                |    1 +
 src/VBox/Main/include/NetworkAdapterImpl.h         |    2 +-
 src/VBox/Main/include/netif.h                      |   58 +-
 src/VBox/Main/src-all/Global.cpp                   |    8 +-
 src/VBox/Main/src-all/QMTranslatorImpl.cpp         |   41 +-
 src/VBox/Main/src-all/SecretKeyStore.cpp           |    5 +-
 src/VBox/Main/src-client/ConsoleImpl.cpp           |    9 +-
 src/VBox/Main/src-client/ConsoleImpl2.cpp          |   48 +-
 src/VBox/Main/src-client/DisplayImpl.cpp           |    2 +-
 src/VBox/Main/src-client/DrvAudioVRDE.cpp          |   35 +-
 src/VBox/Main/src-client/DrvAudioVideoRec.cpp      |    2 +-
 src/VBox/Main/src-client/EmulatedUSBImpl.cpp       |   11 +-
 src/VBox/Main/src-client/GuestCtrlPrivate.cpp      |  140 +-
 src/VBox/Main/src-client/VideoRec.cpp              |   14 +-
 .../Main/src-server/HostNetworkInterfaceImpl.cpp   |   10 +-
 src/VBox/Main/src-server/HostUSBDeviceImpl.cpp     |    3 +-
 src/VBox/Main/src-server/MachineImpl.cpp           |   21 +-
 src/VBox/Main/src-server/MediumImpl.cpp            |  106 +-
 src/VBox/Main/src-server/MediumLock.cpp            |    5 +-
 src/VBox/Main/src-server/NetworkAdapterImpl.cpp    |   40 +-
 src/VBox/Main/src-server/ParallelPortImpl.cpp      |    5 +-
 src/VBox/Main/src-server/SerialPortImpl.cpp        |   12 +-
 .../Main/src-server/USBIdDatabaseGenerator.cpp     |    2 +-
 src/VBox/Main/src-server/linux/NetIf-linux.cpp     |    2 +-
 src/VBox/Main/src-server/win/NetIf-win.cpp         |  175 +-
 src/VBox/Main/testcase/tstCollector.cpp            |    2 +-
 src/VBox/Main/xml/Settings.cpp                     |    4 +-
 src/VBox/Runtime/Makefile.kmk                      |    4 +
 src/VBox/Runtime/VBox/log-vbox.cpp                 |    2 +
 .../Runtime/common/asn1/asn1-ut-integer-decode.cpp |   14 +-
 src/VBox/Runtime/common/asn1/asn1-ut-integer.cpp   |   14 +-
 src/VBox/Runtime/common/crypto/pkix-util.cpp       |    1 +
 src/VBox/Runtime/common/ldr/ldrPE.cpp              |   32 +-
 src/VBox/Runtime/common/ldr/ldrkStuff.cpp          |    1 +
 src/VBox/Runtime/common/math/bignum.cpp            |   30 +-
 src/VBox/Runtime/common/math/gcc/udivmoddi4.c      |   53 +
 src/VBox/Runtime/common/misc/getoptargv.cpp        |   74 +-
 src/VBox/Runtime/common/misc/lockvalidator.cpp     |    1 +
 src/VBox/Runtime/common/net/netaddrstr2.cpp        |  106 +-
 src/VBox/Runtime/common/rand/randadv.cpp           |   20 +-
 .../Runtime/common/string/RTUtf16NICmpAscii.cpp    |   61 +
 src/VBox/Runtime/common/string/strformat.cpp       |    1 +
 src/VBox/Runtime/common/string/strformatnum.cpp    |   79 +-
 src/VBox/Runtime/common/string/strformatrt.cpp     |    6 +-
 src/VBox/Runtime/common/string/strprintf.cpp       |   62 +-
 src/VBox/Runtime/common/string/utf-8.cpp           |   16 +
 src/VBox/Runtime/common/zip/tarvfs.cpp             |   21 +-
 src/VBox/Runtime/nt/RTErrConvertFromNtStatus.cpp   |    8 +
 src/VBox/Runtime/r0drv/linux/memobj-r0drv-linux.c  |   21 +-
 src/VBox/Runtime/r0drv/linux/mp-r0drv-linux.c      |   26 +-
 src/VBox/Runtime/r0drv/linux/the-linux-kernel.h    |    5 +
 .../Runtime/r0drv/linux/waitqueue-r0drv-linux.h    |    4 +
 src/VBox/Runtime/r0drv/nt/alloc-r0drv-nt.cpp       |   34 +-
 src/VBox/Runtime/r0drv/nt/initterm-r0drv-nt.cpp    |   15 +
 src/VBox/Runtime/r0drv/nt/internal-r0drv-nt.h      |    8 +
 src/VBox/Runtime/r0drv/nt/the-nt-kernel.h          |    7 +
 .../r3/linux/RTSystemQueryDmiString-linux.cpp      |    1 +
 src/VBox/Runtime/r3/nt/pathint-nt.cpp              |   21 +-
 src/VBox/Runtime/testcase/Makefile.kmk             |    6 +
 src/VBox/Runtime/testcase/tstRTMath.cpp            |   71 +
 src/VBox/Runtime/testcase/tstRTR0Timer.cpp         |    3 +-
 src/VBox/Runtime/testcase/tstRTR0TimerDriver.cpp   |    2 +-
 src/VBox/Runtime/win/RTErrConvertFromWin32.cpp     |    2 +
 src/VBox/Storage/QCOW.cpp                          |    3 +
 src/VBox/Storage/QED.cpp                           |    4 +-
 src/VBox/Storage/VDI.cpp                           |    2 +
 src/VBox/Storage/testcase/tstVDIo.cpp              |    1 +
 src/VBox/VMM/Makefile.kmk                          |   14 +-
 src/VBox/VMM/VMMAll/EMAll.cpp                      |   12 +-
 src/VBox/VMM/VMMAll/IEMAll.cpp                     | 1018 +++++-
 src/VBox/VMM/VMMAll/IEMAllAImplC.cpp               |   60 +
 src/VBox/VMM/VMMAll/IEMAllCImpl.cpp.h              |   14 +-
 src/VBox/VMM/VMMAll/IEMAllInstructions.cpp.h       |   22 +
 .../VMM/VMMAll/IEMAllInstructionsOneByte.cpp.h     |   87 +-
 src/VBox/VMM/VMMAll/IEMAllInstructionsPython.py    |  239 +-
 .../VMM/VMMAll/IEMAllInstructionsThree0f38.cpp.h   |   52 +-
 .../VMM/VMMAll/IEMAllInstructionsTwoByte0f.cpp.h   | 1542 ++++++--
 .../VMM/VMMAll/IEMAllInstructionsVexMap1.cpp.h     | 3314 +++++++++++-------
 .../VMM/VMMAll/IEMAllInstructionsVexMap2.cpp.h     |   89 +-
 src/VBox/VMM/VMMR0/CPUMR0A.asm                     |   24 +
 src/VBox/VMM/VMMR0/GVMMR0.cpp                      |  216 +-
 src/VBox/VMM/VMMR0/HMR0A.asm                       |   39 +-
 src/VBox/VMM/VMMR0/HMSVMR0.cpp                     |    8 +-
 src/VBox/VMM/VMMR0/HMVMXR0.cpp                     |   52 +-
 src/VBox/VMM/VMMR0/VMMR0.cpp                       |  172 +-
 src/VBox/VMM/VMMR3/CPUMDbg.cpp                     |  126 +-
 src/VBox/VMM/VMMR3/CPUMR3CpuId.cpp                 |   41 +-
 src/VBox/VMM/VMMR3/DBGFReg.cpp                     |  100 +-
 src/VBox/VMM/VMMR3/PDM.cpp                         |   13 +
 src/VBox/VMM/VMMR3/VMM.cpp                         |    4 +-
 src/VBox/VMM/VMMR3/VMMTests.cpp                    |    2 +-
 src/VBox/VMM/VMMRC/PATMRC.cpp                      |    1 +
 src/VBox/VMM/VMMRC/TRPMRCHandlers.cpp              |    4 +-
 src/VBox/VMM/VMMRZ/CPUMRZ.cpp                      |   28 +-
 src/VBox/VMM/VMMRZ/CPUMRZA.asm                     |   88 +-
 src/VBox/VMM/include/CPUMInternal.h                |    1 +
 src/VBox/VMM/include/IEMInternal.h                 |   61 +-
 src/VBox/VMM/testcase/tstIEMCheckMc.cpp            |   57 +-
 src/VBox/ValidationKit/Makefile.kmk                |    4 +-
 src/VBox/ValidationKit/bootsectors/Config.kmk      |    9 +-
 .../bootsectors/bs3-cpu-generated-1-data.py        |   21 +-
 .../bootsectors/bs3-cpu-generated-1-template.c     | 3667 +++++++++++++++++---
 .../bootsectors/bs3-cpu-generated-1.h              |  178 +-
 .../bootsectors/bs3kit/bs3-mode-EnteredMode.asm    |   12 +-
 src/VBox/ValidationKit/common/__init__.py          |    0
 .../ValidationKit/common/constants/__init__.py     |    0
 src/VBox/ValidationKit/common/utils.py             |    0
 src/VBox/ValidationKit/common/webutils.py          |    0
 src/VBox/ValidationKit/testanalysis/diff.py        |    0
 src/VBox/ValidationKit/testanalysis/reader.py      |    0
 src/VBox/ValidationKit/testanalysis/reporting.py   |    0
 .../ValidationKit/testboxscript/testboxcommand.py  |    0
 .../ValidationKit/testboxscript/testboxcommons.py  |    0
 .../testboxscript/testboxconnection.py             |    0
 .../ValidationKit/testboxscript/testboxtasks.py    |    0
 .../ValidationKit/testboxscript/testboxupgrade.py  |    0
 src/VBox/ValidationKit/testdriver/base.py          |    0
 src/VBox/ValidationKit/testdriver/reporter.py      |    0
 src/VBox/ValidationKit/testdriver/tst-txsclient.py |    0
 src/VBox/ValidationKit/testdriver/txsclient.py     |    0
 src/VBox/ValidationKit/testdriver/vbox.py          |    0
 src/VBox/ValidationKit/testdriver/vboxcon.py       |    0
 src/VBox/ValidationKit/testdriver/vboxtestvms.py   |    0
 src/VBox/ValidationKit/testdriver/vboxwrappers.py  |    0
 src/VBox/ValidationKit/testdriver/winbase.py       |    0
 src/VBox/ValidationKit/testmanager/core/base.py    |    0
 src/VBox/ValidationKit/testmanager/core/build.py   |    0
 .../testmanager/core/buildblacklist.py             |    0
 .../ValidationKit/testmanager/core/buildsource.py  |    0
 src/VBox/ValidationKit/testmanager/core/db.py      |    0
 .../ValidationKit/testmanager/core/dbobjcache.py   |    0
 .../testmanager/core/failurecategory.py            |    0
 .../testmanager/core/failurereason.py              |    0
 .../testmanager/core/globalresource.py             |    0
 src/VBox/ValidationKit/testmanager/core/report.py  |    0
 .../ValidationKit/testmanager/core/schedgroup.py   |    0
 .../testmanager/core/schedulerbase.py              |    0
 .../testmanager/core/schedulerbeci.py              |    0
 .../ValidationKit/testmanager/core/systemlog.py    |    0
 src/VBox/ValidationKit/testmanager/core/testbox.py |    0
 .../testmanager/core/testboxcontroller.py          |    0
 .../testmanager/core/testboxstatus.py              |    0
 .../ValidationKit/testmanager/core/testcase.py     |    0
 .../ValidationKit/testmanager/core/testcaseargs.py |    0
 .../ValidationKit/testmanager/core/testgroup.py    |    0
 .../testmanager/core/testresultfailures.py         |    0
 .../ValidationKit/testmanager/core/testresults.py  |    0
 src/VBox/ValidationKit/testmanager/core/testset.py |    0
 .../ValidationKit/testmanager/core/useraccount.py  |    0
 .../ValidationKit/testmanager/core/vcsrevisions.py |    0
 .../testmanager/core/webservergluebase.py          |    0
 .../testmanager/core/webservergluecgi.py           |    0
 .../ValidationKit/testmanager/webui/wuiadmin.py    |    0
 .../testmanager/webui/wuiadminbuild.py             |    0
 .../testmanager/webui/wuiadminbuildblacklist.py    |    0
 .../testmanager/webui/wuiadminbuildcategory.py     |    0
 .../testmanager/webui/wuiadminbuildsource.py       |    0
 .../testmanager/webui/wuiadminfailurecategory.py   |    0
 .../testmanager/webui/wuiadminfailurereason.py     |    0
 .../testmanager/webui/wuiadminglobalrsrc.py        |    0
 .../testmanager/webui/wuiadminschedgroup.py        |    0
 .../testmanager/webui/wuiadminsystemlog.py         |    0
 .../testmanager/webui/wuiadmintestbox.py           |    0
 .../testmanager/webui/wuiadmintestcase.py          |    0
 .../testmanager/webui/wuiadmintestgroup.py         |    0
 .../testmanager/webui/wuiadminuseraccount.py       |    0
 .../ValidationKit/testmanager/webui/wuibase.py     |    0
 .../testmanager/webui/wuicontentbase.py            |    0
 .../ValidationKit/testmanager/webui/wuigraphwiz.py |    0
 .../ValidationKit/testmanager/webui/wuihlpform.py  |    0
 .../ValidationKit/testmanager/webui/wuihlpgraph.py |    0
 .../testmanager/webui/wuihlpgraphbase.py           |    0
 .../testmanager/webui/wuihlpgraphgooglechart.py    |    0
 .../testmanager/webui/wuihlpgraphmatplotlib.py     |    0
 .../testmanager/webui/wuihlpgraphsimple.py         |    0
 .../testmanager/webui/wuilogviewer.py              |    0
 .../ValidationKit/testmanager/webui/wuimain.py     |    0
 .../ValidationKit/testmanager/webui/wuireport.py   |    0
 .../testmanager/webui/wuitestresult.py             |    0
 .../testmanager/webui/wuitestresultfailure.py      |    0
 .../testmanager/webui/wuivcshistory.py             |    0
 .../ValidationKit/tests/storage/remoteexecutor.py  |    0
 src/VBox/ValidationKit/tests/storage/storagecfg.py |    0
 src/VBox/ValidationKit/tests/usb/tst-utsgadget.py  |    0
 src/VBox/ValidationKit/tests/usb/usbgadget.py      |    0
 src/libs/Makefile.kmk                              |    2 +-
 src/libs/xpcom18a4/nsprpub/Makefile.in             |    0
 src/libs/xpcom18a4/nsprpub/config/config.mk        |    0
 src/libs/xpcom18a4/nsprpub/config/rules.mk         |    0
 src/libs/xpcom18a4/python/Makefile.kmk             |   94 +-
 src/libs/xpcom18a4/python/__init__.py              |    0
 src/libs/xpcom18a4/python/client/__init__.py       |    0
 src/libs/xpcom18a4/python/components.py            |    0
 src/libs/xpcom18a4/python/file.py                  |    0
 src/libs/xpcom18a4/python/gen_python_deps.py       |    2 +-
 src/libs/xpcom18a4/python/nsError.py               |    0
 src/libs/xpcom18a4/python/primitives.py            |    0
 src/libs/xpcom18a4/python/server/__init__.py       |    0
 src/libs/xpcom18a4/python/server/enumerator.py     |    0
 src/libs/xpcom18a4/python/server/factory.py        |    0
 src/libs/xpcom18a4/python/server/loader.py         |    0
 src/libs/xpcom18a4/python/server/module.py         |    0
 src/libs/xpcom18a4/python/server/policy.py         |    0
 .../xpcom18a4/python/test/pyxpcom_test_tools.py    |    0
 .../xpcom18a4/python/test/test_com_exceptions.py   |    0
 src/libs/xpcom18a4/python/test/test_comfile.py     |    0
 .../test/test_component/py_test_component.py       |    0
 src/libs/xpcom18a4/python/test/test_components.py  |    0
 .../python/test/test_isupports_primitives.py       |    0
 src/libs/xpcom18a4/python/test/test_misc.py        |    0
 src/libs/xpcom18a4/python/test/test_streams.py     |    0
 .../xpcom18a4/python/test/test_test_component.py   |    0
 .../xpcom18a4/python/test/test_weakreferences.py   |    0
 src/libs/xpcom18a4/python/tools/regxpcom.py        |    0
 src/libs/xpcom18a4/python/tools/tracer_demo.py     |    0
 src/libs/xpcom18a4/python/xpt.py                   |    0
 src/recompiler/Makefile.kmk                        |    3 +-
 752 files changed, 20319 insertions(+), 7359 deletions(-)

diff --git a/Config.kmk b/Config.kmk
index 3ff6865..faecc44 100644
--- a/Config.kmk
+++ b/Config.kmk
@@ -208,7 +208,7 @@ VBOX_VERSION_MINOR = 1
 # This is the current build number. It should be increased every time we publish a
 # new build. The define is available in every source file. Only even build numbers
 # will be published, odd numbers are set during development.
-VBOX_VERSION_BUILD = 22
+VBOX_VERSION_BUILD =  24
 # The raw version string. This *must not* contain any other information/fields than
 # major, minor and build revision (as it is now) -- also will be used for host/guest version
 # comparison.
@@ -1135,6 +1135,10 @@ ifdef VBOX_OSE
  if1of ($(KBUILD_TARGET), solaris)
   VBOX_WITH_32_ON_64_MAIN_API=
  endif
+ if1of ($(KBUILD_TARGET), win)
+  # tar/gzip uncommon on Windows
+  VBOX_WITH_EXTPACK_VBOXDTRACE=
+ endif
  # Enable any translations in OSE, even partial ones.
  ifndef ($(VBOX_NO_DOCS_TRANSLATIONS))
   VBOX_WITH_DOCS_TRANSLATIONS = 1
@@ -1934,8 +1938,15 @@ else
  VBOX_MKISOFS  ?= mkisofs
 endif
 
-ifeq ($(KBUILD_HOST),win)
- VBOX_NM ?= $(PATH_TOOL_MINGW32)/bin/nm.exe -p
+# zip
+VBOX_ZIP ?= zip$(HOSTSUFF_EXE)
+
+ifeq ($(KBUILD_TARGET),win)
+ ifeq ($(KBUILD_TARGET_ARCH),x86) # Normally we should test for KBUILD_HOST_ARCH but we only require MINGWW64 for 64-bit _targets_
+  VBOX_NM ?= $(PATH_TOOL_MINGW32)/bin/nm.exe -p
+ else
+  VBOX_NM ?= $(PATH_TOOL_MINGWW64)/bin/nm.exe -p
+ endif
 else ifeq ($(KBUILD_HOST),darwin) # Xcode 7.3.1 nm doesn't like -t, and -x behaves very differently.  Throwing in -B (bsd) to make sure.
  VBOX_NM ?= $(TOOL_$(VBOX_GCC_TOOL)_ENV_SETUP) $(PATH_TOOL_$(VBOX_GCC_TOOL)_TOOLCHAIN_BIN_SLASH)nm -p $(if-expr \
  	$(VBOX_XCODE_VERSION_MAJOR) > 7 || ($(VBOX_XCODE_VERSION_MAJOR) == 7 && $(VBOX_XCODE_VERSION_MINOR) >= 3),-B,)
@@ -5771,7 +5782,9 @@ ifdef VBOX_WITH_QTGUI
      # legacy libraries required to be installed on EL5
      VBOX_QT_LEGACY_LIBS = \
       $(if $(VBOX_LD_HAS_LIBXCB),,libxcb.so.1 libX11.so.6 libX11-xcb.so.1)
-     VBOX_QT_PLUGINS = plugins/platforms/libqxcb.so
+     VBOX_QT_PLUGINS = \
+       plugins/platforms/libqxcb.so \
+       plugins/xcbglintegrations/libqxcb-glx-integration.so
     else ifeq ($(KBUILD_TARGET), win)
      VBOX_QT_MOD += \
       Qt5WinExtras
@@ -5885,7 +5898,6 @@ ifdef VBOX_WITH_QTGUI
   TEMPLATE_VBOXQTGUIEXE_LDFLAGS.amd64 = -m64
   TEMPLATE_VBOXQTGUIEXE_LIBS = \
 	$(VBOX_LIBS_QT) \
-	$(LIB_SDL) \
 	$(LIB_RUNTIME) \
 	$(if-expr "$(LIB_VMM)" == "$(VBOX_LIB_VMM_LAZY)",$(LIB_REM),) \
 	$(VBOX_LIB_VMM_LAZY)
@@ -6857,7 +6869,7 @@ endif
 SVN                    ?= svn$(HOSTSUFF_EXE)
 VBOX_SVN_REV_KMK        = $(PATH_OUT)/revision.kmk
 ifndef VBOX_SVN_REV
- VBOX_SVN_REV_FALLBACK := $(patsubst %:,,  $Rev: 115126 $  )
+ VBOX_SVN_REV_FALLBACK := $(patsubst %:,,  $Rev: 117012 $  )
  VBOX_SVN_DEP          := $(firstword $(wildcard $(PATH_ROOT)/.svn/wc.db $(abspath $(PATH_ROOT)/../.svn/wc.db) $(abspath $(PATH_ROOT)/../../.svn/wc.db) $(PATH_ROOT)/.svn/entries))
  ifeq ($(which $(SVN)),)
   VBOX_SVN_DEP         :=
@@ -7044,3 +7056,4 @@ st stat status:
 quick:
 	$(MAKE) VBOX_QUICK=1
 
+
diff --git a/Makefile.kmk b/Makefile.kmk
index 8edc962..7d65e3e 100644
--- a/Makefile.kmk
+++ b/Makefile.kmk
@@ -1726,50 +1726,6 @@ efi-packing:
 
 
 #
-# Generate VirtualBox-x.x.x.tar.bz2 (OSE) tarballs for distribution
-# - includes kBuild
-# - must be executed on an OSE checkout
-#
-
-# the path where to store the tarball
-TARBALLPATH ?= $(abspath $(PATH_ROOT)/..)
-# the root directory inside the tarball
-TARBALLROOT ?= VirtualBox-$(subst _OSE,,$(VBOX_VERSION_STRING))
-# the name of the tarball file
-TARBALLNAME ?= VirtualBox-$(subst _OSE,,$(VBOX_VERSION_STRING)).tar.bz2
-snapshot-ose:
-	@$(call MSG_L1,Creating tarball $(TARBALLPATH)/$(TARBALLNAME))
-	@if [ -r "$(PATH_ROOT)/src/VBox/RDP/server/server.cpp" ]; then \
-	    echo; \
-	    echo "Found RDP stuff, refused to build OSE tarball!"; \
-	    echo; \
-	    exit 1; \
-	fi; \
-	if [ -z "$(VBOX_OSE)" ]; then \
-	    echo; \
-	    echo "Please do 'kmk snapshot-ose VBOX_OSE=1'"; \
-	    echo; \
-	    exit 1; \
-	fi
-	$(QUIET)$(MKDIR) -p $(TARBALLPATH)
-	$(QUIET)$(RM) -f $(TARBALLPATH)/$(TARBALLROOT)
-	$(QUIET)$(LN_SYMLINK) $(PATH_ROOT) $(TARBALLPATH)/$(TARBALLROOT)
-	$(QUIET)tar -cjh --dereference --owner 0 --group 0 --totals \
-	    --exclude=.svn \
-	    --exclude=$(TARBALLROOT)/out \
-	    --exclude=$(TARBALLROOT)/env.sh \
-	    --exclude=$(TARBALLROOT)/configure.log \
-	    --exclude=$(TARBALLROOT)/build.log \
-	    --exclude=$(TARBALLROOT)/AutoConfig.kmk \
-	    --exclude=$(TARBALLROOT)/LocalConfig.kmk \
-	    --exclude=$(TARBALLROOT)/prebuild \
-	    -C $(TARBALLPATH) \
-	    -f $(TARBALLPATH)/$(TARBALLNAME) \
-	    $(TARBALLROOT)
-	$(QUIET)$(RM) $(TARBALLPATH)/$(TARBALLROOT)
-
-
-#
 # Generate VirtualBox-x.x.x.tar.bz2 (PUEL) zip archives for internal use only
 # - includes kBuild
 # - must be executed on an PUEL checkout
diff --git a/README.GuestAdditionsPackaging b/README.GuestAdditionsPackaging
new file mode 100644
index 0000000..9bd5aff
--- /dev/null
+++ b/README.GuestAdditionsPackaging
@@ -0,0 +1,14 @@
+Information for people packaging the Guest Additions for Linux distributions
+============================================================================
+We strongly recommend that people packaging the Guest Additions for Linux
+distributions track the latest stable version rather than staying with a given
+major release number for the life-time of the distribution.  The major number
+is more relevant for the host software (the actual VirtualBox application)
+than for the Linux Additions, which are developed more continuously.
+
+We sometimes have two stable versions at one time - one with more features and
+a long-term stable version from the previous major release, which has less
+features but a code base which has had longer to mature.  While this is also
+less relevant for the Additions, you can find the current long-term stable
+release version number at
+  http://download.virtualbox.org/virtualbox/LATEST-STABLE.TXT
diff --git a/configure b/configure
index 116b442..bafa715 100755
--- a/configure
+++ b/configure
@@ -422,13 +422,19 @@ check_gcc()
 {
   test_header gcc
   if check_avail "$CC" CC really; then
-    cc_ver=`$CC -dumpversion` 2>/dev/null
+    cc_ver=`$CC -dumpfullversion` 2>/dev/null
+    if [ $? -ne 0 ]; then
+      cc_ver=`$CC -dumpversion` 2>/dev/null
+    fi
     if [ $? -ne 0 ]; then
       log_failure "cannot execute '$CC -dumpversion'"
       fail really
     fi
     if check_avail "$CXX" CXX really; then
-      cxx_ver=`$CXX -dumpversion` 2>/dev/null
+      cxx_ver=`$CXX -dumpfullversion` 2>/dev/null
+      if [ $? -ne 0 ]; then
+        cxx_ver=`$CXX -dumpversion` 2>/dev/null
+      fi
       if [ $? -ne 0 ]; then
         log_failure "cannot execute '$CXX -dumpversion'"
         fail really
@@ -444,11 +450,8 @@ check_gcc()
       elif [ $cc_maj -lt 4 \
              -o \( $cc_maj -eq 4 -a $cc_min -lt 4 -a "$OS" != "darwin" \) \
              -o \( $cc_maj -eq 4 -a $cc_min -lt 2 -a "$OS"  = "darwin" \) \
-             -o \( $cc_maj -eq 4 -a $cc_min -gt 9 \) \
-             -o \( $cc_maj -eq 5 -a $cc_min -gt 9 \) \
-             -o \( $cc_maj -eq 6 -a $cc_min -gt 9 \) \
-             -o $cc_maj -gt 6 ]; then
-        log_failure "gcc version $cc_maj.$cc_min found, expected gcc 4.x, gcc 5.x or gcc 6.x"
+             -o $cc_maj -gt 7 ]; then
+        log_failure "gcc version $cc_maj.$cc_min found, expected gcc 4.x...7.x"
         fail really
       else
         log_success "found version $cc_ver"
@@ -530,7 +533,11 @@ check_open_watcom()
   if [ -z "$WATCOM" ]; then
     WATCOM=`/bin/ls -rd1 $PWD/tools/common/openwatcom/* 2> /dev/null | head -1`
     if [ -z "$WATCOM" ]; then
-      log_failure "Open Watcom was not found"
+      if [ $OSE -eq 0 -a $OS = "linux" ]; then
+        log_failure "Open Watcom was not found"
+        exit 1
+      fi
+      log_failure "Open Watcom was not found, using alternative BIOS sources"
       cnf_append "VBOX_WITH_OPEN_WATCOM" ""
       return 0;
     fi
@@ -2348,6 +2355,14 @@ check_darwinversion()
   test_header "Darwin version"
   darwin_ver=`uname -r`
   case "$darwin_ver" in
+    16\.*)
+      check_xcode_sdk_path "$WITH_XCODE_DIR"
+      [ $? -eq 1 ] || fail
+      darwin_ver="10.12" # Sierra
+      sdk=$WITH_XCODE_DIR/Developer/SDKs/MacOSX10.6.sdk
+      cnf_append "VBOX_WITH_MACOSX_COMPILERS_FROM_DEVEL" "1"
+      cnf_append "VBOX_PATH_MACOSX_DEVEL_ROOT" "$WITH_XCODE_DIR/Developer"
+      ;;
     15\.*)
       check_xcode_sdk_path "$WITH_XCODE_DIR"
       [ $? -eq 1 ] || fail
@@ -2448,26 +2463,6 @@ check_makeself()
 
 
 #
-# Checks that i386-elf-gcc-3.4.6, i386-elf-gcc-3.4.3, i386-elf-gcc-3.4 or i386-elf-gcc
-# is around to prevent confusion when the build fails in src/recompiler.
-# Note. Keep the which order in sync with the $(which ) in src/recompiler/Makefile.kmk.
-#
-check_i386elfgcc()
-{
-  test_header "i386-elf-gcc"
-  i386_elf_gcc=`which_wrapper i386-elf-gcc-3.4.6`
-  test -z "$i386_elf_gcc" && i386_elf_gcc=`which_wrapper i386-elf-gcc-3.4.3`
-  test -z "$i386_elf_gcc" && i386_elf_gcc=`which_wrapper i386-elf-gcc-3.4`
-  test -z "$i386_elf_gcc" && i386_elf_gcc=`which_wrapper i386-elf-gcc`
-  if test -z "$i386_elf_gcc"; then
-    echo "  failed to find i386-elf-gcc"
-    fail
-  fi
-  log_success "found $i386_elf_gcc"
-}
-
-
-#
 # Show help
 #
 show_help()
diff --git a/configure.vbs b/configure.vbs
index e2ee83d..6449513 100644
--- a/configure.vbs
+++ b/configure.vbs
@@ -43,7 +43,7 @@ g_strPathPSDK = ""
 g_strPathDDK = ""
 
 dim g_strTargetArch
-g_strTargetArch = "x86"
+g_strTargetArch = ""
 
 dim g_blnDisableCOM, g_strDisableCOM
 g_blnDisableCOM = False
@@ -869,14 +869,25 @@ sub CheckForkBuild(strOptkBuild)
       MsgWarning "Found unknown KBUILD_TARGET_ARCH value '" & str &"' in your environment. Setting it to 'x86'."
       str = "x86"
    end if
-   if str <> "" then
-      g_strTargetArch = str
-   elseif (EnvGet("PROCESSOR_ARCHITEW6432") = "AMD64" ) _
-       Or (EnvGet("PROCESSOR_ARCHITECTURE") = "AMD64" ) then
-      g_strTargetArch = "amd64"
+   if g_strTargetArch = "" then '' command line parameter --target-arch=x86|amd64 has priority
+      if str <> "" then
+         g_strTargetArch = str
+      elseif (EnvGet("PROCESSOR_ARCHITEW6432") = "AMD64" ) _
+          Or (EnvGet("PROCESSOR_ARCHITECTURE") = "AMD64" ) then
+         g_strTargetArch = "amd64"
+      else
+         g_strTargetArch = "x86"
+      end if
    else
-      g_strTargetArch = "x86"
+      if InStr(1, "x86|amd64", g_strTargetArch) <= 0 then
+         EnvPrint "set KBUILD_TARGET_ARCH=x86"
+         EnvSet "KBUILD_TARGET_ARCH", "x86"
+         MsgWarning "Unknown --target-arch=" & str &". Setting it to 'x86'."
+      end if
    end if
+   LogPrint " Target architecture: " & g_strTargetArch & "."
+   Wscript.Echo " Target architecture: " & g_strTargetArch & "."
+   EnvPrint "set KBUILD_TARGET_ARCH=" & g_strTargetArch
 
    str = EnvGetFirst("KBUILD_TARGET_CPU", "BUILD_TARGET_CPU")
     ' perhaps a bit pedantic this since this isn't clearly define nor used much...
@@ -896,12 +907,20 @@ sub CheckForkBuild(strOptkBuild)
    end if
 
    str = EnvGetFirst("KBUILD_HOST_ARCH", "BUILD_PLATFORM_ARCH")
-   if   (str <> "") _
-    And (InStr(1, "x86|amd64", str) <= 0) then
-      EnvPrint "set KBUILD_HOST_ARCH=x86"
-      EnvSet "KBUILD_HOST_ARCH", "x86"
-      MsgWarning "Found unknown KBUILD_HOST_ARCH value '" & str &"' in your environment. Setting it to 'x86'."
+   if str <> "" then
+      if InStr(1, "x86|amd64", str) <= 0 then
+         str = "x86"
+         MsgWarning "Found unknown KBUILD_HOST_ARCH value '" & str &"' in your environment. Setting it to 'x86'."
+      end if
+   elseif (EnvGet("PROCESSOR_ARCHITEW6432") = "AMD64" ) _
+       Or (EnvGet("PROCESSOR_ARCHITECTURE") = "AMD64" ) then
+      str = "amd64"
+   else
+      str = "x86"
    end if
+   LogPrint " Host architecture: " & str & "."
+   Wscript.Echo " Host architecture: " & str & "."
+   EnvPrint "set KBUILD_HOST_ARCH=" & str
 
    str = EnvGetFirst("KBUILD_HOST_CPU", "BUILD_PLATFORM_CPU")
     ' perhaps a bit pedantic this since this isn't clearly define nor used much...
@@ -1530,7 +1549,6 @@ end function
 
 ''
 ' Checks for a MinGW-w64 suitable for building the recompiler.
-'
 sub CheckForMinGWw64(strOptMinGWw64)
    dim strPathMingWw64, str
    PrintHdr "MinGW-w64 GCC (unprefixed)"
@@ -1813,94 +1831,16 @@ end function
 
 
 ''
-' Checks for libxslt.
-sub CheckForXslt(strOptXslt)
-   dim strPathXslt, str
-   PrintHdr "libxslt"
-
-   ' Skip if no COM/ATL.
-   if g_blnDisableCOM then
-      PrintResultMsg "libxslt", "Skipped (" & g_strDisableCOM & ")"
-      exit sub
-   end if
-
-   '
-   ' Try find some libxslt dll/lib.
-   '
-   strPathXslt = ""
-   if (strPathXslt = "") And (strOptXslt <> "") then
-      if CheckForXsltSub(strOptXslt) then strPathXslt = strOptXslt
-   end if
-
-   if strPathXslt = "" Then
-      str = Which("libxslt.lib")
-      if str <> "" Then
-         str = PathParent(PathStripFilename(str))
-         if CheckForXsltSub(str) then strPathXslt = str
-      end if
-   end if
-
-   if strPathXslt = "" Then
-      str = Which("libxslt.dll")
-      if str <> "" Then
-         str = PathParent(PathStripFilename(str))
-         if CheckForXsltSub(str) then strPathXslt = str
-      end if
-   end if
-
-   ' Ignore failure if we're in 'internal' mode.
-   if (strPathXslt = "") and g_blnInternalMode then
-      PrintResultMsg "libxslt", "ignored (internal mode)"
-      exit sub
-   end if
-
-   ' Success?
-   if strPathXslt = "" then
-      if strOptXslt = "" then
-         MsgError "Can't locate libxslt. Try specify the path with the --with-libxslt=<path> argument. " _
-                & "If still no luck, consult the configure.log and the build requirements."
-      else
-         MsgError "Can't locate libxslt. Please consult the configure.log and the build requirements."
-      end if
-      exit sub
-   end if
-
-   strPathXslt = UnixSlashes(PathAbs(strPathXslt))
-   CfgPrint "SDK_VBOX_LIBXSLT_INCS   := " & strPathXslt & "/include"
-   CfgPrint "SDK_VBOX_LIBXSLT_LIBS   := " & strPathXslt & "/lib/libxslt.lib"
-
-   PrintResult "libxslt", strPathXslt
-end sub
-
-
-''
-' Checks if the specified path points to an usable libxslt or not.
-function CheckForXsltSub(strPathXslt)
-   dim str
-
-   CheckForXsltSub = False
-   LogPrint "trying: strPathXslt=" & strPathXslt
-
-   if   LogFileExists(strPathXslt, "include/libxslt/namespaces.h") _
-    And LogFileExists(strPathXslt, "include/libxslt/xsltutils.h") _
-      then
-      str = LogFindFile(strPathXslt, "lib/libxslt.dll")
-      if str <> "" then
-         if   LogFileExists(strPathXslt, "lib/libxslt.lib") _
-            then
-            CheckForXsltSub = True
-         end if
-      end if
-   end if
-end function
-
-
-''
 ' Checks for openssl
-sub CheckForSsl(strOptSsl)
+sub CheckForSsl(strOptSsl, bln32Bit)
    dim strPathSsl, str
    PrintHdr "openssl"
 
+   strOpenssl = "openssl"
+   if bln32Bit = True then
+       strOpenssl = "openssl32"
+   end if
+
    '
    ' Try find some openssl dll/lib.
    '
@@ -1910,7 +1850,7 @@ sub CheckForSsl(strOptSsl)
    end if
 
    if strPathSsl = "" Then
-      str = Which("ssleay32.lib")
+      str = Which("libssl.lib")
       if str <> "" Then
          str = PathParent(PathStripFilename(str))
          if CheckForSslSub(str) then strPathSsl = str
@@ -1919,27 +1859,35 @@ sub CheckForSsl(strOptSsl)
 
    ' Ignore failure if we're in 'internal' mode.
    if (strPathSsl = "") and g_blnInternalMode then
-      PrintResultMsg "openssl", "ignored (internal mode)"
+      PrintResultMsg strOpenssl, "ignored (internal mode)"
       exit sub
    end if
 
    ' Success?
    if strPathSsl = "" then
       if strOptSsl = "" then
-         MsgError "Can't locate openssl. Try specify the path with the --with-openssl=<path> argument. " _
+         MsgError "Can't locate " & strOpenssl & ". " _
+                & "Try specify the path with the --with-" & strOpenssl & "=<path> argument. " _
                 & "If still no luck, consult the configure.log and the build requirements."
       else
-         MsgError "Can't locate openssl. Please consult the configure.log and the build requirements."
+         MsgError "Can't locate " & strOpenssl & ". " _
+                & "Please consult the configure.log and the build requirements."
       end if
       exit sub
    end if
 
    strPathSsl = UnixSlashes(PathAbs(strPathSsl))
-   CfgPrint "SDK_VBOX_OPENSSL_INCS := " & strPathSsl & "/include"
-   CfgPrint "SDK_VBOX_OPENSSL_LIBS := " & strPathSsl & "/lib/ssleay32.lib" & " " & strPathSsl & "/lib/libeay32.lib"
-   CfgPrint "SDK_VBOX_BLD_OPENSSL_LIBS := " & strPathSsl & "/lib/ssleay32.lib" & " " & strPathSsl & "/lib/libeay32.lib"
+   if bln32Bit = True then
+      CfgPrint "SDK_VBOX_OPENSSL-x86_INCS := " & strPathSsl & "/include"
+      CfgPrint "SDK_VBOX_OPENSSL-x86_LIBS := " & strPathSsl & "/lib/libcrypto.lib" & " " & strPathSsl & "/lib/libssl.lib"
+      CfgPrint "SDK_VBOX_BLD_OPENSSL-x86_LIBS := " & strPathSsl & "/lib/libcrypto.lib" & " " & strPathSsl & "/lib/libssl.lib"
+   else
+      CfgPrint "SDK_VBOX_OPENSSL_INCS := " & strPathSsl & "/include"
+      CfgPrint "SDK_VBOX_OPENSSL_LIBS := " & strPathSsl & "/lib/libcrypto.lib" & " " & strPathSsl & "/lib/libssl.lib"
+      CfgPrint "SDK_VBOX_BLD_OPENSSL_LIBS := " & strPathSsl & "/lib/libcrypto.lib" & " " & strPathSsl & "/lib/libssl.lib"
+   end if
 
-   PrintResult "openssl", strPathSsl
+   PrintResult strOpenssl, strPathSsl
 end sub
 
 ''
@@ -1949,10 +1897,7 @@ function CheckForSslSub(strPathSsl)
    CheckForSslSub = False
    LogPrint "trying: strPathSsl=" & strPathSsl
    if   LogFileExists(strPathSsl, "include/openssl/md5.h") _
-    And LogFindFile(strPathSsl, "bin/ssleay32.dll") <> "" _
-    And LogFindFile(strPathSsl, "lib/ssleay32.lib") <> "" _
-    And LogFindFile(strPathSsl, "bin/libeay32.dll") <> "" _
-    And LogFindFile(strPathSsl, "lib/libeay32.lib") <> "" _
+    And LogFindFile(strPathSsl, "lib/libssl.lib") <> "" _
       then
          CheckForSslSub = True
       end if
@@ -1961,10 +1906,15 @@ end function
 
 ''
 ' Checks for libcurl
-sub CheckForCurl(strOptCurl)
+sub CheckForCurl(strOptCurl, bln32Bit)
    dim strPathCurl, str
    PrintHdr "libcurl"
 
+   strCurl = "libcurl"
+   if bln32Bit = True then
+       strCurl = "libcurl32"
+   end if
+
    '
    ' Try find some cURL dll/lib.
    '
@@ -1983,26 +1933,33 @@ sub CheckForCurl(strOptCurl)
 
    ' Ignore failure if we're in 'internal' mode.
    if (strPathCurl = "") and g_blnInternalMode then
-      PrintResultMsg "curl", "ignored (internal mode)"
+      PrintResultMsg strCurl, "ignored (internal mode)"
       exit sub
    end if
 
    ' Success?
    if strPathCurl = "" then
       if strOptCurl = "" then
-         MsgError "Can't locate libcurl. Try specify the path with the --with-libcurl=<path> argument. " _
+         MsgError "Can't locate " & strCurl & ". " _
+                & "Try specify the path with the --with-" & strCurl & "=<path> argument. " _
                 & "If still no luck, consult the configure.log and the build requirements."
       else
-         MsgError "Can't locate libcurl. Please consult the configure.log and the build requirements."
+         MsgError "Can't locate " & strCurl & ". " _
+                & "Please consult the configure.log and the build requirements."
       end if
       exit sub
    end if
 
    strPathCurl = UnixSlashes(PathAbs(strPathCurl))
-   CfgPrint "SDK_VBOX_LIBCURL_INCS := " & strPathCurl & "/include"
-   CfgPrint "SDK_VBOX_LIBCURL_LIBS := " & strPathCurl & "/libcurl.lib"
+   if bln32Bit = True then
+      CfgPrint "SDK_VBOX_LIBCURL-x86_INCS := " & strPathCurl & "/include"
+      CfgPrint "SDK_VBOX_LIBCURL-x86_LIBS.x86 := " & strPathCurl & "/libcurl.lib"
+   else
+      CfgPrint "SDK_VBOX_LIBCURL_INCS := " & strPathCurl & "/include"
+      CfgPrint "SDK_VBOX_LIBCURL_LIBS := " & strPathCurl & "/libcurl.lib"
+   end if
 
-   PrintResult "libcurl", strPathCurl
+   PrintResult strCurl, strPathCurl
 end sub
 
 ''
@@ -2022,36 +1979,8 @@ end function
 
 
 ''
-' Checks for any Qt4/5 binaries.
-sub CheckForQt(strOptQt4, strOptQt5)
-   dim strPathQt4
-
-   PrintHdr "Qt4"
-
-   '
-   ' Try to find the Qt4 installation (user specified path with --with-qt4)
-   '
-   strPathQt4 = ""
-
-   LogPrint "Checking for user specified path of Qt4 ... "
-   if (strPathQt4 = "") And (strOptQt4 <> "") then
-      strOptQt4 = UnixSlashes(strOptQt4)
-      if CheckForQt4Sub(strOptQt4) then strPathQt4 = strOptQt4
-   end if
-
-   ' Check the dev tools
-   if (strPathQt4 = "") Then
-      strPathQt4 = g_strPathDev & "/win." & g_strTargetArch & "/qt/v4.7.3-vcc100"
-      if CheckForQt4Sub(strPathQt4) = False then strPathQt4 = ""
-   end if
-
-   ' Display the result.
-   if strPathQt4 = "" then
-      PrintResultMsg "Qt4", "not found"
-   else
-      PrintResult "Qt4", strPathQt4
-   end if
-
+' Checks for any Qt5 binaries.
+sub CheckForQt(strOptQt5)
    PrintHdr "Qt5"
 
    '
@@ -2082,15 +2011,8 @@ sub CheckForQt(strOptQt4, strOptQt5)
       CfgPrint "PATH_SDK_QT5          := " & strPathQt5
       CfgPrint "PATH_TOOL_QT5         := $(PATH_SDK_QT5)"
       CfgPrint "VBOX_PATH_QT          := $(PATH_SDK_QT5)"
-      if strPathQt4 <> "" then
-         MsgWarning "Have working path to both Qt4 ad Qt5, ignoring Qt4."
-      end if
-   elseif strPathQt4 <> "" then
-      CfgPrint "PATH_SDK_QT4          := " & strPathQt4
-      CfgPrint "PATH_TOOL_QT4         := $(PATH_SDK_QT4)"
-      CfgPrint "VBOX_PATH_QT          := $(PATH_SDK_QT4)"
    end if
-   if (strPathQt4 = "") And (strPathQt5 = "") then
+   if strPathQt5 = "" then
       CfgPrint "VBOX_WITH_QTGUI       :="
    end if
    if strPathQt5 = "" then
@@ -2100,31 +2022,6 @@ end sub
 
 
 ''
-' Checks if the specified path points to an usable Qt4 library.
-function CheckForQt4Sub(strPathQt4)
-
-   CheckForQt4Sub = False
-   LogPrint "trying: strPathQt4=" & strPathQt4
-
-   if   LogFileExists(strPathQt4, "bin/moc.exe") _
-    And LogFileExists(strPathQt4, "bin/uic.exe") _
-    And LogFileExists(strPathQt4, "include/Qt/qwidget.h") _
-    And LogFileExists(strPathQt4, "include/QtGui/QApplication") _
-    And LogFileExists(strPathQt4, "include/QtNetwork/QHostAddress") _
-    And (   LogFileExists(strPathQt4, "lib/QtCore4.lib") _
-         Or LogFileExists(strPathQt4, "lib/VBoxQtCore4.lib") _
-         Or LogFileExists(strPathQt4, "lib/QtCoreVBox4.lib")) _
-    And (   LogFileExists(strPathQt4, "lib/QtNetwork4.lib") _
-         Or LogFileExists(strPathQt4, "lib/VBoxQtNetwork4.lib") _
-         Or LogFileExists(strPathQt4, "lib/QtNetworkVBox4.lib")) _
-      then
-         CheckForQt4Sub = True
-   end if
-
-end function
-
-
-''
 ' Checks if the specified path points to an usable Qt5 library.
 function CheckForQt5Sub(strPathQt5)
 
@@ -2195,29 +2092,31 @@ sub usage
    Print "  -h, --help"
    Print "  --internal"
    Print "  --internal-last"
+   Print "  --target-arch=x86|amd64"
    Print ""
    Print "Components:"
    Print "  --disable-COM"
    Print "  --disable-UDPTunnel"
    Print ""
    Print "Locations:"
-   Print "  --with-DDK=PATH       "
    Print "  --with-kBuild=PATH    "
    Print "  --with-libSDL=PATH    "
    Print "  --with-MinGW32=PATH   "
    Print "  --with-MinGW-w64=PATH "
-   Print "  --with-Qt4=PATH       "
    Print "  --with-Qt5=PATH       "
+   Print "  --with-DDK=PATH       "
    Print "  --with-SDK=PATH       "
    Print "  --with-VC=PATH        "
    Print "  --with-VC-Common=PATH "
    Print "  --with-VC-Express-Edition"
    Print "  --with-W32API=PATH    "
    Print "  --with-libxml2=PATH   "
-   Print "  --with-libxslt=PATH   "
    Print "  --with-openssl=PATH   "
+   Print "  --with-openssl32=PATH (only for 64-bit targets)"
    Print "  --with-libcurl=PATH   "
+   Print "  --with-libcurl32=PATH (only for 64-bit targets)"
    Print "  --with-python=PATH    "
+   Print "  --with-mkisofs=PATH   "
 end sub
 
 
@@ -2243,7 +2142,6 @@ Sub Main
    strOptlibSDL = ""
    strOptMinGW32 = ""
    strOptMinGWw64 = ""
-   strOptQt4 = ""
    strOptQt5 = ""
    strOptSDK = ""
    strOptVC = ""
@@ -2251,9 +2149,10 @@ Sub Main
    blnOptVCExpressEdition = False
    strOptW32API = ""
    strOptXml2 = ""
-   strOptXslt = ""
    strOptSsl = ""
+   strOptSsl32 = ""
    strOptCurl = ""
+   strOptCurl32 = ""
    strOptPython = ""
    strOptMkisofs = ""
    blnOptDisableCOM = False
@@ -2286,8 +2185,6 @@ Sub Main
             strOptMinGW32 = strPath
          case "--with-mingw-w64"
             strOptMinGWw64 = strPath
-         case "--with-qt4"
-            strOptQt4 = strPath
          case "--with-qt5"
             strOptQt5 = strPath
          case "--with-sdk"
@@ -2302,12 +2199,14 @@ Sub Main
             strOptW32API = strPath
          case "--with-libxml2"
             strOptXml2 = strPath
-         case "--with-libxslt"
-            strOptXslt = strPath
          case "--with-openssl"
             strOptSsl = strPath
+         case "--with-openssl32"
+            strOptSsl32 = strPath
          case "--with-libcurl"
             strOptCurl = strPath
+         case "--with-libcurl32"
+            strOptCurl32 = strPath
          case "--with-python"
             strOptPython = strPath
          case "--with-mkisofs"
@@ -2322,6 +2221,8 @@ Sub Main
             g_blnInternalMode = True
          case "--internal-last"
             g_blnInternalFirst = False
+         case "--target-arch"
+            g_strTargetArch = strPath
          case "-h", "--help", "-?"
             usage
             Wscript.Quit(0)
@@ -2364,7 +2265,7 @@ Sub Main
    CheckSourcePath
    CheckForkBuild strOptkBuild
    CheckForWinDDK strOptDDK
-   CfgPrint "VBOX_WITH_WDDM_W8     := " '' @todo look for WinDDKv8; Check with Misha if we _really_ need the v8 DDK...
+   CfgPrint "VBOX_WITH_WDDM_W8     := " '' @todo look for WinDDKv8
    CheckForVisualCPP strOptVC, strOptVCCommon, blnOptVCExpressEdition
    CheckForPlatformSDK strOptSDK
    CheckForMidl
@@ -2372,18 +2273,27 @@ Sub Main
    CheckForMinGWw64 strOptMinGWw64
    CfgPrint "VBOX_WITH_OPEN_WATCOM := " '' @todo look for openwatcom 1.9+
    EnvPrint "set PATH=%PATH%;" & g_strPath& "/tools/win." & g_strTargetArch & "/bin;" '' @todo look for yasm
-   CheckForlibSDL strOptlibSDL
-   ' Don't check for these libraries by default as they are part of OSE
-   ' Using external libs can add a dependency to iconv
+   if blnOptDisableSDL = True then
+      DisableSDL "--disable-sdl"
+   else
+      CheckForlibSDL strOptlibSDL
+   end if
+   ' Don't check for this library by default as it's part of the tarball
+   ' Using an external library can add a dependency to iconv
    if (strOptXml2 <> "") then
       CheckForXml2 strOptXml2
    end if
-   if (strOptXslt <> "") then
-      CheckForXslt strOptXslt
+   CheckForSsl strOptSsl, False
+   if g_strTargetArch = "amd64" then
+       ' 32-bit openssl required as well
+       CheckForSsl strOptSsl32, True
+   end if
+   CheckForCurl strOptCurl, False
+   if g_strTargetArch = "amd64" then
+       ' 32-bit Curl required as well
+       CheckForCurl strOptCurl32, True
    end if
-   CheckForSsl strOptSsl
-   CheckForCurl strOptCurl
-   CheckForQt strOptQt4, strOptQt5
+   CheckForQt strOptQt5
    if (strOptPython <> "") then
      CheckForPython strOptPython
    end if
diff --git a/doc/manual/Makefile.kmk b/doc/manual/Makefile.kmk
index f0032fb..c0fda2a 100644
--- a/doc/manual/Makefile.kmk
+++ b/doc/manual/Makefile.kmk
@@ -772,7 +772,7 @@ ifdef VBOX_WITH_DOCS_CHM
  $(PATH_STAGE_BIN)/VBoxDocumentation.zip: $(VBOX_MANUAL_PACK)
 	$(call MSG_L1,Packing documentation $@)
 	$(QUIET)$(RM) -f $@
-	$(QUIET)$(REDIRECT) -C $(PATH_STAGE_BIN) -- zip$(HOSTSUFF_EXE) -9 $@ $(notdir $^)
+	$(QUIET)$(REDIRECT) -C $(PATH_STAGE_BIN) -- $(VBOX_ZIP) -9 $@ $(notdir $^)
 
 endif # VBOX_WITH_DOCS_CHM
 
@@ -823,7 +823,7 @@ $(VBOX_PATH_MANUAL_OUTBASE)/en_US/UserManual.zip: \
 		$(VBOX_PATH_MANUAL_OUTBASE)/en_US/html-chunks/index.html
 	$(call MSG_L1,Packing documentation $@)
 	$(QUIET)$(RM) -f $@
-	$(QUIET)$(REDIRECT) -C $(VBOX_PATH_MANUAL_OUTBASE)/en_US/ -- zip$(HOSTSUFF_EXE) \
+	$(QUIET)$(REDIRECT) -C $(VBOX_PATH_MANUAL_OUTBASE)/en_US/ -- $(VBOX_ZIP) \
 		-9 -r $@ html-single html-chunks $(VBOX_MANUAL_PNG_FILES_en_US)
 
 html:: $(VBOX_PATH_MANUAL_OUTBASE)/en_US/html-single/UserManual.html
diff --git a/doc/manual/en_US/user_AdvancedTopics.xml b/doc/manual/en_US/user_AdvancedTopics.xml
index 0fd9ec0..218b5d3 100644
--- a/doc/manual/en_US/user_AdvancedTopics.xml
+++ b/doc/manual/en_US/user_AdvancedTopics.xml
@@ -3789,7 +3789,7 @@ VBoxManage setextradata "VM name" VBoxInternal/CPUM/SSE4.2 1</screen>
       is, the heartbeat service of the VirtualBox Guest Additions will send a heartbeat
       ping every two seconds. The value in nanoseconds can be configured like this:
     </para>
-    <screen>VBoxManage controlvm "VM name" VBoxInternal/Devices/VMMDev/0/Config/HeartbeatInterval 2000000000</screen>
+    <screen>VBoxManage setextradata "VM name" VBoxInternal/Devices/VMMDev/0/Config/HeartbeatInterval 2000000000</screen>
     <para>
       The <emphasis>heartbeat timeout</emphasis> defines the time the host waits
       starting from the last heartbeat ping before it defines the guest as unresponsive.
@@ -3797,7 +3797,7 @@ VBoxManage setextradata "VM name" VBoxInternal/CPUM/SSE4.2 1</screen>
       as following (in nanoseconds):
     </para>
 
-    <screen>VBoxManage controlvm "VM name" VBoxInternal/Devices/VMMDev/0/Config/HeartbeatTimeout 4000000000</screen>
+    <screen>VBoxManage setextradata "VM name" VBoxInternal/Devices/VMMDev/0/Config/HeartbeatTimeout 4000000000</screen>
 
     <para>
       If the heartbeat timeout expires, there will be a log message like
diff --git a/doc/manual/en_US/user_GuestAdditions.xml b/doc/manual/en_US/user_GuestAdditions.xml
index 5acf4bf..9666ba4 100644
--- a/doc/manual/en_US/user_GuestAdditions.xml
+++ b/doc/manual/en_US/user_GuestAdditions.xml
@@ -243,13 +243,14 @@
         software on CD is disabled) need manual start of the installer.</para>
 
         <note>
-          <para>For the basic Direct3D acceleration to work in a Windows Guest, you
-          have to install the Guest Additions in "Safe Mode".
-          This does <emphasis role="bold">not</emphasis> apply to the experimental
-          WDDM Direct3D video driver available
-          for Vista and Windows 7 guests, see <xref linkend="KnownIssues" /> for
-          details.<footnote><para>The experimental WDDM driver was added with
-          VirtualBox 4.1.</para></footnote></para>
+          <para>For the basic Direct3D acceleration to work in a Windows guest,
+          you have to install the WDDM video driver available for Windows Vista
+          or higher.<footnote><para>An experimental WDDM driver was
+          added with VirtualBox 4.1.</para></footnote> For Windows 8 and higher
+          only the WDDM Direct3D video driver is available. For basic Direct3D
+          acceleration to work in Windows XP guests, you have to install the
+          Guest Additions in "Safe Mode", see <xref linkend="KnownIssues" /> for
+          details.</para>
         </note>
 
         <para>If you prefer to mount the additions manually, you can perform
@@ -489,13 +490,13 @@
         <para>This automatically installs the right files and drivers for the
         corresponding platform (32- or 64-bit).</para>
 
-        <note><para>By default on an unattended installation on a Windows 7 or 8
-        guest, there will be the XPDM graphics driver installed. This graphics
-        driver does not support Windows Aero / Direct3D on the guest - instead the
-        experimental WDDM graphics driver needs to be installed. To select this
-        driver by default, add the command line parameter
+        <note><para>By default on an unattended installation on a Vista or Windows
+        7 guest, there will be the XPDM graphics driver installed. This graphics
+        driver does not support Windows Aero / Direct3D on the guest – instead
+        the WDDM graphics driver needs to be installed. To select this driver by
+        default, add the command line parameter
         <computeroutput>/with_wddm</computeroutput> when invoking the Windows
-        Guest Additions installer.</para></note>
+        Guest Additions installer (only required for Vista and Windows 7).</para></note>
         <note><para>For Windows Aero to run correctly on a guest, the guest's
         VRAM size needs to be configured to at least 128 MB.</para></note>
 
@@ -1211,10 +1212,8 @@ $</screen>
                 program offers Direct3D acceleration as an option that must
                 be explicitly enabled. Also, you must install the Guest
                 Additions in "Safe Mode". This does <emphasis role="bold">not</emphasis>
-                apply to the experimental WDDM Direct3D video
-                driver available for Vista and Windows 7 guests,
-                see <xref linkend="KnownIssues" />
-                for details.</para></note>
+                apply to the WDDM Direct3D video driver available for Vista
+                and higher, see <xref linkend="KnownIssues" /> for details.</para></note>
               </para>
           </listitem>
 
@@ -1239,18 +1238,14 @@ $</screen>
           </listitem>
         </orderedlist></para>
 
-      <para>With VirtualBox 4.1, Windows Aero theme support is added for
-      Windows Vista and Windows 7 guests. To enable Aero theme support,
-      the experimental VirtualBox WDDM video driver must be installed,
+      <para>To enable Aero theme support,
+      the VirtualBox WDDM video driver must be installed,
       which is available with the Guest Additions installation.
-      Since the WDDM video driver is still experimental at this time, it is
-      not installed by default and must be <emphasis role="bold">manually
+      The WDDM driver is not installed by default for Vista and Windows 7
+      guest and must be <emphasis role="bold">manually
       selected</emphasis> in the Guest Additions installer by answering "No"
-      int the "Would you like to install basic Direct3D support" dialog
-      displayed when the Direct3D feature is selected.
-      <note><para>Unlike the current basic Direct3D support, the WDDM video
-      driver installation does <emphasis role="bold">not</emphasis> require
-      the "Safe Mode".</para></note></para>
+      in the "Would you like to install basic Direct3D support" dialog
+      displayed when the Direct3D feature is selected.</para>
 
       <para>The Aero theme is not enabled by default. To enable it
         <itemizedlist>
diff --git a/doc/manual/en_US/user_KnownIssues.xml b/doc/manual/en_US/user_KnownIssues.xml
index d147e30..f90de94 100644
--- a/doc/manual/en_US/user_KnownIssues.xml
+++ b/doc/manual/en_US/user_KnownIssues.xml
@@ -11,9 +11,6 @@
             welcome. A comprehensive list of experimental features follows:</para>
         <itemizedlist>
             <listitem>
-                <para>WDDM Direct3D video driver for Windows guests</para>
-            </listitem>
-            <listitem>
                 <para>Hardware 3D acceleration support for Windows, Linux, and Solaris 
                 guests</para>
             </listitem>
@@ -87,9 +84,8 @@
           installed by VirtualBox and keep restoring the original Windows system
           DLLs. <note>
           <para>This does <emphasis role="bold">not</emphasis> apply to the
-          experimental WDDM Direct3D video
-          driver available for Vista and Windows 7 guests shipped with
-            VirtualBox 4.1.</para>
+          WDDM Direct3D video driver available for Vista and Windows 7 guests
+          shipped with VirtualBox 4.1.</para>
           </note></para>
         </listitem>
     
diff --git a/doc/manual/en_US/user_VBoxManage.xml b/doc/manual/en_US/user_VBoxManage.xml
index 8811fa5..75911aa 100644
--- a/doc/manual/en_US/user_VBoxManage.xml
+++ b/doc/manual/en_US/user_VBoxManage.xml
@@ -3455,7 +3455,7 @@ Virtual system 0:
                          [--property <name=[value]>]
                          [--compact]
                          [--resize <megabytes>|--resizebyte <bytes>]
-                         [--move <full path to a new location></screen><note>
+                         [--move <path></screen><note>
         <para>For compatibility with earlier versions of VirtualBox, the "modifyvdi" and "modifyhd" 
         commands are also supported and mapped internally to the "modifymedium" command.</para>
       </note></para>
@@ -3531,9 +3531,10 @@ Virtual system 0:
         </listitem>
 
         <listitem>
-          <para>The <computeroutput>--move <dest></computeroutput> option
-          can be used to move an image to a different location <dest> on the host file system, 
-          specified by either the relative path to the current directory or absolute path.</para>
+          <para>The <computeroutput>--move <path></computeroutput> option
+          can be used to relocate a medium to a different location <path> on the
+          host file system. The path can be either relative to the current directory or
+          absolute.</para>
         </listitem>
       </itemizedlist></para>
   </sect1>
diff --git a/doc/manual/user_ChangeLogImpl.xml b/doc/manual/user_ChangeLogImpl.xml
index d56b941..892048e 100644
--- a/doc/manual/user_ChangeLogImpl.xml
+++ b/doc/manual/user_ChangeLogImpl.xml
@@ -3,6 +3,157 @@
 <chapter> <!-- HACK ALERT! Seems we must have a single top level element for xi:include to work.
                            So, we use chapter and xpointer="xpointer(/chapter/)" with xi:include. -->
   <sect1>
+    <title>Version 5.1.24 (2017-07-18)</title>
+
+    <para>This is a maintenance release. The following items were fixed and/or
+      added:</para>
+
+    <itemizedlist>
+
+      <listitem>
+        <para>VMM: mask the VME CPUID capability on AMD Ryzen processors
+          for now to make certain guests works, for example Windows XP</para>
+      </listitem>
+
+      <listitem>
+        <para>VMM: emulate more SSE2 instructions</para>
+      </listitem>
+
+      <listitem>
+        <para>VMM: properly clear the <emphasis>TF</emphasis> and
+          <emphasis>AC</emphasis> flags when dispatching real-mode
+          interrupts</para>
+      </listitem>
+
+      <listitem>
+        <para>GUI: fixes to make the mini-toolbar work with recent versions
+          of KDE / Plasma (bug #16325)</para>
+      </listitem>
+
+      <listitem>
+        <para>GUI: fixed a potential crash when a VM with multiple screens is
+          running in full screen / seamless mode and a host screen is removed,
+          for example when connecting to the host via RDP</para>
+      </listitem>
+
+      <listitem>
+        <para>GUI: fixed initial size hints for guests which
+          set intermediate sizes before responding (bug #16593)</para>
+      </listitem>
+
+      <listitem>
+        <para>GUI: prevent stopped screen updates or black screen on reboot
+          in a multi-screen setup under certain conditions</para>
+      </listitem>
+
+      <listitem>
+        <para>Audio: many improvements for Windows 10 guests (bugs #15189,
+          #15925, #16170, #16682, #16794 and others)</para>
+      </listitem>
+
+      <listitem>
+        <para>Storage: fixed possible crash when using Intels SPDK</para>
+      </listitem>
+
+      <listitem>
+        <para>API: use the correct file name of the VM machine state if the
+          VM settings directory is renamed, for example during grouping /
+          ungrouping a VM (bugs #16075 and #16745)</para>
+      </listitem>
+
+      <listitem>
+        <para>API: return the correct error code if powering up a VM fails</para>
+      </listitem>
+
+      <listitem>
+        <para>API: video recording did not automatically start at VM start
+          when enabled in the VM settings (bug #16803)</para>
+      </listitem>
+
+      <listitem>
+        <para>API: when relocating a medium, check that the target path is
+          fully qualified</para>
+      </listitem>
+
+      <listitem>
+        <para>EFI: fix for VMs with more than 3504MB RAM (bug #11103)</para>
+      </listitem>
+
+      <listitem>
+        <para>Host-only adapter: correctly determine IPv4 netmasks on Windows
+          hosts (bug #16826)</para>
+      </listitem>
+
+      <listitem>
+        <para>NAT network: properly do the refcounting for starting / stopping
+          the NAT / DHCP services if the NAT network is changed while the
+          adapter network connection type is anything else but NAT network</para>
+      </listitem>
+
+      <listitem>
+        <para>VBoxManage: fixed <emphasis>controlvm videocapfile</emphasis>
+          (bug #16779)</para>
+      </listitem>
+
+      <listitem>
+        <para>Windows hosts: fixed crashes if driver verifier is enabled
+          (bug #15741)</para>
+      </listitem>
+
+      <listitem>
+        <para>Linux / Mac OS X hosts: more fixes for loading shared libraries
+          (5.1.20 regression; bugs #16778, #16693)</para>
+      </listitem>
+
+      <listitem>
+        <para>Linux hosts / guests: Linux 4.12 fixes (bugs #16725, #16800)</para>
+      </listitem>
+
+      <listitem>
+        <para>Linux hosts / guests: reduce the kernel stack consumption for
+          Linux kernels with <emphasis>CONFIG_CPUMASK_OFFSTACK</emphasis>
+          defined</para>
+      </listitem>
+
+      <listitem>
+        <para>Linux hosts / guests: fixes for kernel modules built with gcc-7
+          (bug #16772)</para>
+      </listitem>
+
+      <listitem>
+        <para>Linux hosts / guests: Linux 4.13 fix (bug #16887)</para>
+      </listitem>
+
+      <listitem>
+        <para>Linux hosts: don't depend on <emphasis>net-tools</emphasis> on newer
+          distributions as this package is deprecated in favour of
+          <emphasis>iproute</emphasis> (bug #16764)</para>
+      </listitem>
+
+      <listitem>
+        <para>Linux hosts: make 2D video acceleration available for older
+          Linux distributions (5.1 regression; bug #16858)</para>
+      </listitem>
+
+      <listitem>
+        <para>Linux Additions: fix for dynamic resizing with Oracle Linux 6
+           with UEK4</para>
+      </listitem>
+
+      <listitem>
+        <para>Linux Additions: make Fedora 25 and 26 Alpha work when 3D
+           pass-through is enabled</para>
+      </listitem>
+
+      <listitem>
+        <para>Linux Additions: no longer recommend removing distribution-
+           installed Additions if they are updated to our guidelines</para>
+      </listitem>
+
+    </itemizedlist>
+  </sect1>
+
+  <sect1>
     <title>Version 5.1.22 (2017-04-28)</title>
 
     <para>This is a maintenance release. The following items were fixed and/or
diff --git a/include/VBox/disopcode.h b/include/VBox/disopcode.h
index 3a8ce66..f171d98 100644
--- a/include/VBox/disopcode.h
+++ b/include/VBox/disopcode.h
@@ -182,6 +182,7 @@ enum OPCODES
     OP_MOVHLPS = OP_MOVLPS, /**< @todo OP_MOVHLPS */
     OP_UNPCKLPS,
     OP_MOVHPS,
+    OP_MOVLHPS = OP_MOVHPS, /**< @todo OP_MOVLHPS */
     OP_UNPCKHPS,
     OP_PREFETCH_GRP16,
     OP_MOV_CR,
@@ -738,11 +739,6 @@ enum OPCODES
     OP_SWAPGS,
     OP_UD1,
     OP_UD2,
-/** @name AVX instructions
- * @{ */
-    OP_VLDMXCSR,
-    OP_VSTMXCSR,
-/** @} */
 /** @name VT-x instructions
  * @{ */
     OP_VMREAD,
@@ -773,8 +769,33 @@ enum OPCODES
 /** @}  */
 /** @name 64 bits instruction
  * @{ */
-    OP_MOVSXD
+    OP_MOVSXD,
+/** @} */
+/** @name AVX instructions
+ * @{ */
+    OP_VLDMXCSR,
+    OP_VSTMXCSR,
+    OP_VMOVUPS,
+    OP_VMOVUPD,
+    OP_VMOVSS,
+    OP_VMOVSD,
+    OP_VMOVHLPS,
+    OP_VMOVLPS,
+    OP_VMOVLPD,
+    OP_VMOVSLDUP,
+    OP_VMOVDDUP,
+    OP_VMOVAPS,
+    OP_VMOVAPD,
+    OP_VMOVNTPS,
+    OP_VMOVNTPD,
+    OP_VMOVD,
+    OP_VMOVQ,
+    OP_VMOVDQA,
+    OP_VMOVDQU,
+    OP_VMOVNTDQ,
+    OP_VMOVNTDQA,
 /** @} */
+    OP_END_OF_OPCODES
 };
 AssertCompile(OP_LOCK == 7);
 /** @} */
@@ -1062,15 +1083,55 @@ enum OP_PARM
 #define OP_PARM_Lx              (OP_PARM_L+OP_PARM_x)
 
 /* For making IEM / bs3-cpu-generated-1 happy: */
+#define OP_PARM_Ed_WO           OP_PARM_Ed              /**< Annotates write only operand. */
+#define OP_PARM_Eq              (OP_PARM_E+OP_PARM_q)
+#define OP_PARM_Eq_WO           OP_PARM_Eq              /**< Annotates write only operand. */
+#define OP_PARM_Gv_RO           OP_PARM_Gv              /**< Annotates read only first operand (default is readwrite). */
+#define OP_PARM_HssHi           OP_PARM_Hx              /**< Register referenced by VEX.vvvv, bits [127:32]. */
+#define OP_PARM_HsdHi           OP_PARM_Hx              /**< Register referenced by VEX.vvvv, bits [127:64]. */
+#define OP_PARM_HqHi            OP_PARM_Hx              /**< Register referenced by VEX.vvvv, bits [127:64]. */
+#define OP_PARM_M_RO            OP_PARM_M               /**< Annotates read only memory of variable operand size (xrstor). */
+#define OP_PARM_M_RW            OP_PARM_M               /**< Annotates read-write memory of variable operand size (xsave). */
+#define OP_PARM_Mb_RO           OP_PARM_Mb              /**< Annotates read only memory byte operand. */
+#define OP_PARM_Md_RO           OP_PARM_Md              /**< Annotates read only memory operand. */
+#define OP_PARM_Md_WO           OP_PARM_Md              /**< Annotates write only memory operand. */
+#define OP_PARM_Mdq_WO          OP_PARM_Mdq             /**< Annotates write only memory operand. */
+#define OP_PARM_Mq_WO           OP_PARM_Mq              /**< Annotates write only memory quad word operand. */
+#define OP_PARM_Mps_WO          OP_PARM_Mps             /**< Annotates write only memory operand. */
+#define OP_PARM_Mpd_WO          OP_PARM_Mpd             /**< Annotates write only memory operand. */
+#define OP_PARM_Mx_WO           OP_PARM_Mx             /**< Annotates write only memory operand. */
+#define OP_PARM_PdZx_WO         OP_PARM_Pd              /**< Annotates write only operand and zero extends to 64-bit. */
+#define OP_PARM_Pq_WO           OP_PARM_Pq              /**< Annotates write only operand. */
+#define OP_PARM_Qq_WO           OP_PARM_Qq              /**< Annotates write only operand. */
+#define OP_PARM_Nq              OP_PARM_Qq              /**< Missing 'N' class (MMX reg selected by modrm.mem) in disasm. */
 #define OP_PARM_Uq              (OP_PARM_U+OP_PARM_q)
-#define OP_PARM_UqHi            OP_PARM_Uq
-#define OP_PARM_WqZxReg         OP_PARM_Wq              /**< Annotates that register targets get their upper bits cleared. */
-#define OP_PARM_VssZxReg        OP_PARM_Vss             /**< Annotates that register targets get their upper bits cleared. */
-#define OP_PARM_MbRO            OP_PARM_Mb              /**< Annotates read only memory byte operand. */
-#define OP_PARM_MdRO            OP_PARM_Md              /**< Annotates read only memory byte operand. */
-#define OP_PARM_MdWO            OP_PARM_Md              /**< Annotates write only memory byte operand. */
-#define OP_PARM_MRO             OP_PARM_M               /**< Annotates read only memory of variable operand size (xrstor). */
-#define OP_PARM_MRW             OP_PARM_M               /**< Annotates read-write memory of variable operand size (xsave). */
+#define OP_PARM_UqHi            (OP_PARM_U+OP_PARM_dq)
+#define OP_PARM_Uss             (OP_PARM_U+OP_PARM_ss)
+#define OP_PARM_Uss_WO          OP_PARM_Uss             /**< Annotates write only operand. */
+#define OP_PARM_Usd             (OP_PARM_U+OP_PARM_sd)
+#define OP_PARM_Usd_WO          OP_PARM_Usd             /**< Annotates write only operand. */
+#define OP_PARM_Vd              (OP_PARM_V+OP_PARM_d)
+#define OP_PARM_Vd_WO           OP_PARM_Vd              /**< Annotates write only operand. */
+#define OP_PARM_VdZx_WO         OP_PARM_Vd              /**< Annotates that the registers get their upper bits cleared */
+#define OP_PARM_Vdq_WO          OP_PARM_Vdq             /**< Annotates that only YMM/XMM[127:64] are accessed. */
+#define OP_PARM_Vpd_WO          OP_PARM_Vpd             /**< Annotates write only operand. */
+#define OP_PARM_Vps_WO          OP_PARM_Vps             /**< Annotates write only operand. */
+#define OP_PARM_Vq_WO           OP_PARM_Vq              /**< Annotates write only operand. */
+#define OP_PARM_VqHi            OP_PARM_Vdq             /**< Annotates that only YMM/XMM[127:64] are accessed. */
+#define OP_PARM_VqHi_WO         OP_PARM_Vdq             /**< Annotates that only YMM/XMM[127:64] are written. */
+#define OP_PARM_VqZx_WO         OP_PARM_Vq              /**< Annotates that the registers get their upper bits cleared */
+#define OP_PARM_VsdZx_WO        OP_PARM_Vsd             /**< Annotates that the registers get their upper bits cleared. */
+#define OP_PARM_VssZx_WO        OP_PARM_Vss             /**< Annotates that the registers get their upper bits cleared. */
+#define OP_PARM_Vss_WO          OP_PARM_Vss             /**< Annotates write only operand. */
+#define OP_PARM_Vsd_WO          OP_PARM_Vsd             /**< Annotates write only operand. */
+#define OP_PARM_Vx_WO           OP_PARM_Vx              /**< Annotates write only operand. */
+#define OP_PARM_Wpd_WO          OP_PARM_Wpd             /**< Annotates write only operand. */
+#define OP_PARM_Wps_WO          OP_PARM_Wps             /**< Annotates write only operand. */
+#define OP_PARM_Wq_WO           OP_PARM_Wq              /**< Annotates write only operand. */
+#define OP_PARM_WqZxReg_WO      OP_PARM_Wq              /**< Annotates that register targets get their upper bits cleared. */
+#define OP_PARM_Wss_WO          OP_PARM_Wss             /**< Annotates write only operand. */
+#define OP_PARM_Wsd_WO          OP_PARM_Wsd             /**< Annotates write only operand. */
+#define OP_PARM_Wx_WO           OP_PARM_Wx              /**< Annotates write only operand. */
 
 /** @} */
 
diff --git a/include/VBox/sup.h b/include/VBox/sup.h
index a3b3eaf..b488de2 100644
--- a/include/VBox/sup.h
+++ b/include/VBox/sup.h
@@ -100,9 +100,11 @@ typedef enum SUPPAGINGMODE
  * @{
  */
 /** GDT is read-only. */
-#define SUPKERNELFEATURES_GDT_READ_ONLY     RT_BIT(0)
+#define SUPKERNELFEATURES_GDT_READ_ONLY       RT_BIT(0)
 /** SMAP is possibly enabled. */
-#define SUPKERNELFEATURES_SMAP              RT_BIT(1)
+#define SUPKERNELFEATURES_SMAP                RT_BIT(1)
+/** GDT is read-only but the writable GDT can be fetched by SUPR0GetCurrentGdtRw(). */
+#define SUPKERNELFEATURES_GDT_NEED_WRITABLE   RT_BIT(2)
 /** @} */
 
 
@@ -1814,6 +1816,14 @@ SUPR3DECL(int) SUPR3ReadTsc(uint64_t *puTsc, uint16_t *pidApic);
  */
 SUPR3DECL(int) SUPR3GipSetFlags(uint32_t fOrMask, uint32_t fAndMask);
 
+/**
+ * Return processor microcode revision, if applicable.
+ *
+ * @returns VINF_SUCCESS if supported, error code indicating why if not.
+ * @param   puMicrocodeRev  Pointer to microcode revision dword (out).
+ */
+SUPR3DECL(int) SUPR3QueryMicrocodeRev(uint32_t *puMicrocodeRev);
+
 /** @} */
 #endif /* IN_RING3 */
 
@@ -1877,6 +1887,10 @@ SUPR0DECL(int) SUPR0ObjAddRefEx(void *pvObj, PSUPDRVSESSION pSession, bool fNoBl
 SUPR0DECL(int) SUPR0ObjRelease(void *pvObj, PSUPDRVSESSION pSession);
 SUPR0DECL(int) SUPR0ObjVerifyAccess(void *pvObj, PSUPDRVSESSION pSession, const char *pszObjName);
 
+SUPR0DECL(PVM) SUPR0GetSessionVM(PSUPDRVSESSION pSession);
+SUPR0DECL(PGVM) SUPR0GetSessionGVM(PSUPDRVSESSION pSession);
+SUPR0DECL(int) SUPR0SetSessionVM(PSUPDRVSESSION pSession, PGVM pGVM, PVM pVM);
+
 SUPR0DECL(int) SUPR0LockMem(PSUPDRVSESSION pSession, RTR3PTR pvR3, uint32_t cPages, PRTHCPHYS paPages);
 SUPR0DECL(int) SUPR0UnlockMem(PSUPDRVSESSION pSession, RTR3PTR pvR3);
 SUPR0DECL(int) SUPR0ContAlloc(PSUPDRVSESSION pSession, uint32_t cPages, PRTR0PTR ppvR0, PRTR3PTR ppvR3, PRTHCPHYS pHCPhys);
@@ -1893,8 +1907,10 @@ SUPR0DECL(int) SUPR0PageFree(PSUPDRVSESSION pSession, RTR3PTR pvR3);
 SUPR0DECL(int) SUPR0GipMap(PSUPDRVSESSION pSession, PRTR3PTR ppGipR3, PRTHCPHYS pHCPhysGip);
 SUPR0DECL(int) SUPR0GetSvmUsability(bool fInitSvm);
 SUPR0DECL(int) SUPR0GetVmxUsability(bool *pfIsSmxModeAmbiguous);
+SUPR0DECL(int) SUPR0GetCurrentGdtRw(RTHCUINTPTR *pGdtRw);
 SUPR0DECL(int) SUPR0QueryVTCaps(PSUPDRVSESSION pSession, uint32_t *pfCaps);
 SUPR0DECL(int) SUPR0GipUnmap(PSUPDRVSESSION pSession);
+SUPR0DECL(int) SUPR0QueryUcodeRev(PSUPDRVSESSION pSession, uint32_t *puMicrocodeRev);
 SUPR0DECL(SUPPAGINGMODE) SUPR0GetPagingMode(void);
 SUPR0DECL(RTCCUINTREG) SUPR0ChangeCR4(RTCCUINTREG fOrMask, RTCCUINTREG fAndMask);
 SUPR0DECL(int) SUPR0EnableVTx(bool fEnable);
diff --git a/include/VBox/vmm/cpum.h b/include/VBox/vmm/cpum.h
index 9e67597..7d00d6e 100644
--- a/include/VBox/vmm/cpum.h
+++ b/include/VBox/vmm/cpum.h
@@ -1675,6 +1675,7 @@ VMMRZ_INT_DECL(void)    CPUMRZFpuStatePrepareHostCpuForUse(PVMCPU pVCpu);
 VMMRZ_INT_DECL(void)    CPUMRZFpuStateActualizeForRead(PVMCPU pVCpu);
 VMMRZ_INT_DECL(void)    CPUMRZFpuStateActualizeForChange(PVMCPU pVCpu);
 VMMRZ_INT_DECL(void)    CPUMRZFpuStateActualizeSseForRead(PVMCPU pVCpu);
+VMMRZ_INT_DECL(void)    CPUMRZFpuStateActualizeAvxForRead(PVMCPU pVCpu);
 /** @} */
 
 
diff --git a/include/VBox/vmm/dbgf.h b/include/VBox/vmm/dbgf.h
index acc35ae..1befbea 100644
--- a/include/VBox/vmm/dbgf.h
+++ b/include/VBox/vmm/dbgf.h
@@ -1677,6 +1677,24 @@ typedef enum DBGFREG
     DBGFREG_XMM15,
     /** @todo add XMM aliases. */
 
+    /* AVX: */
+    DBGFREG_YMM0,
+    DBGFREG_YMM1,
+    DBGFREG_YMM2,
+    DBGFREG_YMM3,
+    DBGFREG_YMM4,
+    DBGFREG_YMM5,
+    DBGFREG_YMM6,
+    DBGFREG_YMM7,
+    DBGFREG_YMM8,
+    DBGFREG_YMM9,
+    DBGFREG_YMM10,
+    DBGFREG_YMM11,
+    DBGFREG_YMM12,
+    DBGFREG_YMM13,
+    DBGFREG_YMM14,
+    DBGFREG_YMM15,
+
     /* System registers: */
     DBGFREG_GDTR_BASE,
     DBGFREG_GDTR_LIMIT,
@@ -1759,6 +1777,10 @@ typedef enum DBGFREGVALTYPE
     DBGFREGVALTYPE_U64,
     /** Unsigned 128-bit register value. */
     DBGFREGVALTYPE_U128,
+    /** Unsigned 256-bit register value. */
+    DBGFREGVALTYPE_U256,
+    /** Unsigned 512-bit register value. */
+    DBGFREGVALTYPE_U512,
     /** Long double register value. */
     DBGFREGVALTYPE_R80,
     /** Descriptor table register value. */
@@ -1776,16 +1798,18 @@ typedef DBGFREGVALTYPE *PDBGFREGVALTYPE;
  */
 typedef union DBGFREGVAL
 {
-    uint64_t    au64[2];        /**< The 64-bit array view. First because of the initializer. */
-    uint32_t    au32[4];        /**< The 32-bit array view. */
-    uint16_t    au16[8];        /**< The 16-bit array view. */
-    uint8_t     au8[16];        /**< The 8-bit array view. */
+    uint64_t    au64[8];        /**< The 64-bit array view. First because of the initializer. */
+    uint32_t    au32[16];       /**< The 32-bit array view. */
+    uint16_t    au16[32];       /**< The 16-bit array view. */
+    uint8_t     au8[64];        /**< The 8-bit array view. */
 
     uint8_t     u8;             /**< The 8-bit view. */
     uint16_t    u16;            /**< The 16-bit view. */
     uint32_t    u32;            /**< The 32-bit view. */
     uint64_t    u64;            /**< The 64-bit view. */
     RTUINT128U  u128;           /**< The 128-bit view. */
+    RTUINT256U  u256;           /**< The 256-bit view. */
+    RTUINT512U  u512;           /**< The 512-bit view. */
     RTFLOAT80U  r80;            /**< The 80-bit floating point view. */
     RTFLOAT80U2 r80Ex;          /**< The 80-bit floating point view v2. */
     /** GDTR or LDTR (DBGFREGVALTYPE_DTR). */
@@ -1796,8 +1820,6 @@ typedef union DBGFREGVAL
         /** The table limit (length minus 1). */
         uint32_t u32Limit;
     }           dtr;
-
-    RTUINT128U  u;
 } DBGFREGVAL;
 /** Pointer to a generic register value type. */
 typedef DBGFREGVAL *PDBGFREGVAL;
@@ -1805,9 +1827,9 @@ typedef DBGFREGVAL *PDBGFREGVAL;
 typedef DBGFREGVAL const *PCDBGFREGVAL;
 
 /** Initialize a DBGFREGVAL variable to all zeros.  */
-#define DBGFREGVAL_INITIALIZE_ZERO { { 0, 0 } }
+#define DBGFREGVAL_INITIALIZE_ZERO { { 0, 0, 0, 0, 0, 0, 0, 0 } }
 /** Initialize a DBGFREGVAL variable to all bits set .  */
-#define DBGFREGVAL_INITIALIZE_FFFF { { UINT64_MAX, UINT64_MAX } }
+#define DBGFREGVAL_INITIALIZE_FFFF { { UINT64_MAX, UINT64_MAX, UINT64_MAX, UINT64_MAX, UINT64_MAX, UINT64_MAX, UINT64_MAX, UINT64_MAX } }
 
 
 VMMDECL(ssize_t) DBGFR3RegFormatValue(char *pszBuf, size_t cbBuf, PCDBGFREGVAL pValue, DBGFREGVALTYPE enmType, bool fSpecial);
diff --git a/include/VBox/vmm/gvm.h b/include/VBox/vmm/gvm.h
index f1a5cdd..d2f1063 100644
--- a/include/VBox/vmm/gvm.h
+++ b/include/VBox/vmm/gvm.h
@@ -81,6 +81,8 @@ typedef struct GVM
     uint32_t        hSelf;
     /** The ring-0 mapping of the VM structure. */
     PVM             pVM;
+    /** The support driver session the VM is associated with. */
+    PSUPDRVSESSION  pSession;
     /** Number of Virtual CPUs, i.e. how many entries there are in aCpus.
      * Same same as VM::cCpus. */
     uint32_t        cCpus;
diff --git a/include/VBox/vmm/gvmm.h b/include/VBox/vmm/gvmm.h
index f36a5d5..aef9e1e 100644
--- a/include/VBox/vmm/gvmm.h
+++ b/include/VBox/vmm/gvmm.h
@@ -162,8 +162,8 @@ GVMMR0DECL(int)     GVMMR0CreateVM(PSUPDRVSESSION pSession, uint32_t cCpus, PVM
 GVMMR0DECL(int)     GVMMR0InitVM(PVM pVM);
 GVMMR0DECL(void)    GVMMR0DoneInitVM(PVM pVM);
 GVMMR0DECL(bool)    GVMMR0DoingTermVM(PVM pVM, PGVM pGVM);
-GVMMR0DECL(int)     GVMMR0DestroyVM(PVM pVM);
-GVMMR0DECL(int)     GVMMR0RegisterVCpu(PVM pVM, VMCPUID idCpu);
+GVMMR0DECL(int)     GVMMR0DestroyVM(PGVM pGVM, PVM pVM);
+GVMMR0DECL(int)     GVMMR0RegisterVCpu(PGVM pGVM, PVM pVM, VMCPUID idCpu);
 GVMMR0DECL(PGVM)    GVMMR0ByHandle(uint32_t hGVM);
 GVMMR0DECL(int)     GVMMR0ByVM(PVM pVM, PGVM *ppGVM);
 GVMMR0DECL(int)     GVMMR0ByVMAndEMT(PVM pVM, VMCPUID idCpu, PGVM *ppGVM);
@@ -200,7 +200,7 @@ typedef struct GVMMCREATEVMREQ
 /** Pointer to a GVMMR0CreateVM request packet. */
 typedef GVMMCREATEVMREQ *PGVMMCREATEVMREQ;
 
-GVMMR0DECL(int)     GVMMR0CreateVMReq(PGVMMCREATEVMREQ pReq);
+GVMMR0DECL(int)     GVMMR0CreateVMReq(PGVMMCREATEVMREQ pReq, PSUPDRVSESSION pSession);
 
 
 /**
@@ -238,7 +238,7 @@ typedef struct GVMMQUERYSTATISTICSSREQ
 /** Pointer to a GVMMR0QueryStatisticsReq / VMMR0_DO_GVMM_QUERY_STATISTICS request buffer. */
 typedef GVMMQUERYSTATISTICSSREQ *PGVMMQUERYSTATISTICSSREQ;
 
-GVMMR0DECL(int)     GVMMR0QueryStatisticsReq(PVM pVM, PGVMMQUERYSTATISTICSSREQ pReq);
+GVMMR0DECL(int)     GVMMR0QueryStatisticsReq(PVM pVM, PGVMMQUERYSTATISTICSSREQ pReq, PSUPDRVSESSION pSession);
 
 
 /**
@@ -258,7 +258,7 @@ typedef struct GVMMRESETSTATISTICSSREQ
 /** Pointer to a GVMMR0ResetStatisticsReq / VMMR0_DO_GVMM_RESET_STATISTICS request buffer. */
 typedef GVMMRESETSTATISTICSSREQ *PGVMMRESETSTATISTICSSREQ;
 
-GVMMR0DECL(int)     GVMMR0ResetStatisticsReq(PVM pVM, PGVMMRESETSTATISTICSSREQ pReq);
+GVMMR0DECL(int)     GVMMR0ResetStatisticsReq(PVM pVM, PGVMMRESETSTATISTICSSREQ pReq, PSUPDRVSESSION pSession);
 
 
 /** @} */
diff --git a/include/VBox/vmm/hm_vmx.h b/include/VBox/vmm/hm_vmx.h
index 0783f82..2e842e6 100644
--- a/include/VBox/vmm/hm_vmx.h
+++ b/include/VBox/vmm/hm_vmx.h
@@ -111,6 +111,7 @@
 #define VMX_RESTORE_HOST_IDTR                 RT_BIT(6)
 #define VMX_RESTORE_HOST_GDT_READ_ONLY        RT_BIT(7)
 #define VMX_RESTORE_HOST_REQUIRED             RT_BIT(8)
+#define VMX_RESTORE_HOST_GDT_NEED_WRITABLE    RT_BIT(9)
 /** @} */
 
 /**
@@ -126,19 +127,22 @@ typedef struct VMXRESTOREHOST
     RTSEL       uHostSelGS;     /* 0x06 */
     RTSEL       uHostSelTR;     /* 0x08 */
     uint8_t     abPadding0[4];
-    X86XDTR64   HostGdtr;       /**< 0x0e - should be aligned by it's 64-bit member.  */
+    X86XDTR64   HostGdtr;       /**< 0x0e - should be aligned by it's 64-bit member. */
     uint8_t     abPadding1[6];
-    X86XDTR64   HostIdtr;       /**< 0x1e - should be aligned by it's 64-bit member. */
-    uint64_t    uHostFSBase;    /* 0x28 */
-    uint64_t    uHostGSBase;    /* 0x30 */
+    X86XDTR64   HostGdtrRw;     /**< 0x1e - should be aligned by it's 64-bit member. */
+    uint8_t     abPadding2[6];
+    X86XDTR64   HostIdtr;       /**< 0x2e - should be aligned by it's 64-bit member. */
+    uint64_t    uHostFSBase;    /* 0x38 */
+    uint64_t    uHostGSBase;    /* 0x40 */
 } VMXRESTOREHOST;
 /** Pointer to VMXRESTOREHOST. */
 typedef VMXRESTOREHOST *PVMXRESTOREHOST;
 AssertCompileSize(X86XDTR64, 10);
 AssertCompileMemberOffset(VMXRESTOREHOST, HostGdtr.uAddr, 16);
-AssertCompileMemberOffset(VMXRESTOREHOST, HostIdtr.uAddr, 32);
-AssertCompileMemberOffset(VMXRESTOREHOST, uHostFSBase,    40);
-AssertCompileSize(VMXRESTOREHOST, 56);
+AssertCompileMemberOffset(VMXRESTOREHOST, HostGdtrRw.uAddr, 32);
+AssertCompileMemberOffset(VMXRESTOREHOST, HostIdtr.uAddr, 48);
+AssertCompileMemberOffset(VMXRESTOREHOST, uHostFSBase,    56);
+AssertCompileSize(VMXRESTOREHOST, 72);
 AssertCompileSizeAlignment(VMXRESTOREHOST, 8);
 
 /** @name Host-state MSR lazy-restoration flags.
diff --git a/include/VBox/vmm/hm_vmx.mac b/include/VBox/vmm/hm_vmx.mac
index 2f3bd30..e20c0da 100644
--- a/include/VBox/vmm/hm_vmx.mac
+++ b/include/VBox/vmm/hm_vmx.mac
@@ -160,6 +160,7 @@
 %define VMX_RESTORE_HOST_IDTR                                   40h   ;RT_BIT(6)
 %define VMX_RESTORE_HOST_GDT_READ_ONLY                          80h   ;RT_BIT(7)
 %define VMX_RESTORE_HOST_REQUIRED                              100h   ;RT_BIT(8)
+%define VMX_RESTORE_HOST_GDT_NEED_WRITABLE                     200h   ;RT_BIT(9)
 
 ;; C version hm_vmx.h.
 struc VMXRESTOREHOST
@@ -171,12 +172,15 @@ struc VMXRESTOREHOST
     .abPadding0         resb    4
     .HostGdtr           resb    10
     .abPadding1         resb    6
+    .HostGdtrRw         resb    10
+    .abPadding2         resb    6
     .HostIdtr           resb    10
     .uHostFSBase        resq    1
     .uHostGSBase        resq    1
 endstruc
 AssertCompileMemberOffset(VMXRESTOREHOST, HostGdtr,     16-2)
-AssertCompileMemberOffset(VMXRESTOREHOST, HostIdtr,     32-2)
-AssertCompileMemberOffset(VMXRESTOREHOST, uHostFSBase,    40)
-AssertCompileSize(VMXRESTOREHOST, 56)
+AssertCompileMemberOffset(VMXRESTOREHOST, HostGdtrRw,   32-2)
+AssertCompileMemberOffset(VMXRESTOREHOST, HostIdtr,     48-2)
+AssertCompileMemberOffset(VMXRESTOREHOST, uHostFSBase,    56)
+AssertCompileSize(VMXRESTOREHOST, 72)
 
diff --git a/include/VBox/vmm/iem.h b/include/VBox/vmm/iem.h
index 72e24c4..e63ce16 100644
--- a/include/VBox/vmm/iem.h
+++ b/include/VBox/vmm/iem.h
@@ -38,6 +38,63 @@ RT_C_DECLS_BEGIN
  * @{
  */
 
+/** @name IEMXCPTRAISEINFO_XXX - Extra info. on a recursive exception situation.
+ *
+ * This is primarily used by HM for working around a PGM limitation (see
+ * @bugref{6607}) and special NMI/IRET handling. In the future, this may be
+ * used for diagnostics.
+ *
+ * @{
+ */
+typedef uint32_t IEMXCPTRAISEINFO;
+/** Pointer to a IEMXCPTINFO type. */
+typedef IEMXCPTRAISEINFO *PIEMXCPTRAISEINFO;
+/** No addition info. available. */
+#define IEMXCPTRAISEINFO_NONE                    RT_BIT_32(0)
+/** Delivery of a \#AC caused another \#AC. */
+#define IEMXCPTRAISEINFO_AC_AC                   RT_BIT_32(1)
+/** Delivery of a \#PF caused another \#PF. */
+#define IEMXCPTRAISEINFO_PF_PF                   RT_BIT_32(2)
+/** Delivery of a \#PF caused some contributory exception. */
+#define IEMXCPTRAISEINFO_PF_CONTRIBUTORY_XCPT    RT_BIT_32(3)
+/** Delivery of an external interrupt caused an exception. */
+#define IEMXCPTRAISEINFO_EXT_INT_XCPT            RT_BIT_32(4)
+/** Delivery of an software interrupt caused an exception. */
+#define IEMXCPTRAISEINFO_EXT_INT_PF              RT_BIT_32(5)
+/** Delivery of an external interrupt caused a \#PF. */
+#define IEMXCPTRAISEINFO_SOFT_INT_XCPT           RT_BIT_32(6)
+/** Delivery of an NMI caused an exception. */
+#define IEMXCPTRAISEINFO_NMI_XCPT                RT_BIT_32(7)
+/** Delivery of an NMI caused a \#PF. */
+#define IEMXCPTRAISEINFO_NMI_PF                  RT_BIT_32(8)
+/** Can re-execute the instruction at CS:RIP. */
+#define IEMXCPTRAISEINFO_CAN_REEXEC_INSTR        RT_BIT_32(9)
+/** @} */
+
+
+/** @name IEMXCPTRAISE_XXX - Ways to handle a recursive exception condition.
+ * @{ */
+typedef enum IEMXCPTRAISE
+{
+    /** Raise the current (second) exception. */
+    IEMXCPTRAISE_CURRENT_XCPT = 0,
+    /** Re-raise the previous (first) event (for HM, unused by IEM). */
+    IEMXCPTRAISE_PREV_EVENT,
+    /** Re-execute instruction at CS:RIP (for HM, unused by IEM). */
+    IEMXCPTRAISE_REEXEC_INSTR,
+    /** Raise a \#DF exception. */
+    IEMXCPTRAISE_DOUBLE_FAULT,
+    /** Raise a triple fault. */
+    IEMXCPTRAISE_TRIPLE_FAULT,
+    /** Cause a CPU hang. */
+    IEMXCPTRAISE_CPU_HANG,
+    /** Invalid sequence of events. */
+    IEMXCPTRAISE_INVALID = 0x7fffffff
+} IEMXCPTRAISE;
+/** Pointer to a IEMXCPTRAISE type. */
+typedef IEMXCPTRAISE *PIEMXCPTRAISE;
+/** @} */
+
 
 /** @name Operand or addressing mode.
  * @{ */
@@ -65,6 +122,10 @@ typedef uint8_t IEMMODE;
 #define IEM_XCPT_FLAGS_BP_INSTR         RT_BIT_32(5)
 /** Generated by a DRx instruction breakpoint and RF should be cleared. */
 #define IEM_XCPT_FLAGS_DRx_INSTR_BP     RT_BIT_32(6)
+/** Generated by the icebp instruction. */
+#define IEM_XCPT_FLAGS_ICEBP_INSTR      RT_BIT_32(7)
+/** Generated by the overflow instruction. */
+#define IEM_XCPT_FLAGS_OF_INSTR         RT_BIT_32(8)
 /** @}  */
 
 
@@ -138,6 +199,8 @@ VMM_INT_DECL(void)          IEMTlbInvalidatePage(PVMCPU pVCpu, RTGCPTR GCPtr);
 VMM_INT_DECL(void)          IEMTlbInvalidateAllPhysical(PVMCPU pVCpu);
 VMM_INT_DECL(bool)          IEMGetCurrentXcpt(PVMCPU pVCpu, uint8_t *puVector, uint32_t *pfFlags, uint32_t *puErr,
                                               uint64_t *puCr2);
+VMM_INT_DECL(IEMXCPTRAISE)  IEMEvaluateRecursiveXcpt(PVMCPU pVCpu, uint32_t fPrevFlags, uint8_t uPrevVector, uint32_t fCurFlags,
+                                                     uint8_t uCurVector, PIEMXCPTRAISEINFO pXcptRaiseInfo);
 
 /** @name Given Instruction Interpreters
  * @{ */
diff --git a/include/VBox/vmm/pdmaudioifs.h b/include/VBox/vmm/pdmaudioifs.h
index 1e5dc98..7d8cd3b 100644
--- a/include/VBox/vmm/pdmaudioifs.h
+++ b/include/VBox/vmm/pdmaudioifs.h
@@ -3,7 +3,7 @@
  */
 
 /*
- * Copyright (C) 2006-2016 Oracle Corporation
+ * Copyright (C) 2006-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;
@@ -74,15 +74,19 @@ typedef struct PDMAUDIOBACKENDCFG
 } PDMAUDIOBACKENDCFG, *PPDMAUDIOBACKENDCFG;
 
 /**
- * An audio sample. At the moment stereo (left + right channels) only.
- * @todo Replace this with a more generic union
- *       which then also could handle 2.1 or 5.1 sound.
+ * A single audio sample, representing left and right channels (stereo).
  */
 typedef struct PDMAUDIOSAMPLE
 {
+    /** Left channel. */
     int64_t i64LSample;
+    /** Right channel. */
     int64_t i64RSample;
-} PDMAUDIOSAMPLE, *PPDMAUDIOSAMPLE;
+} PDMAUDIOSAMPLE;
+/** Pointer to a single (stereo) audio sample.   */
+typedef PDMAUDIOSAMPLE *PPDMAUDIOSAMPLE;
+/** Pointer to a const single (stereo) audio sample.   */
+typedef PDMAUDIOSAMPLE const *PCPDMAUDIOSAMPLE;
 
 typedef enum PDMAUDIOENDIANNESS
 {
@@ -187,7 +191,7 @@ typedef enum PDMAUDIOSTREAMCMD
  * Properties of audio streams for host/guest
  * for in or out directions.
  */
-typedef struct PDMPCMPROPS
+typedef struct PDMAUDIOPCMPROPS
 {
     /** Sample width. Bits per sample. */
     uint8_t     cBits;
@@ -211,7 +215,20 @@ typedef struct PDMPCMPROPS
     uint32_t    cbPerSec;
     /** Whether the endianness is swapped or not. */
     bool        fSwapEndian;
-} PDMPCMPROPS, *PPDMPCMPROPS;
+} PDMAUDIOPCMPROPS, *PPDMAUDIOPCMPROPS;
+
+/** Calculates the cShift value of given samples bits and audio channels.
+ *  Note: Does only support mono/stereo channels for now. */
+#define PDMAUDIOPCMPROPS_MAKE_SHIFT_PARMS(cBits, cChannels)     ((cChannels == 2) + (cBits / 16))
+/** Calculates the cShift value of a PDMAUDIOPCMPROPS structure.
+ *  Note: Does only support mono/stereo channels for now. */
+#define PDMAUDIOPCMPROPS_MAKE_SHIFT(pProps)                     PDMAUDIOPCMPROPS_MAKE_SHIFT_PARMS((pProps)->cChannels == 2) + (pProps)->cBits / 16)
+/** Converts (audio) samples to bytes.
+ *  Needs the cShift value set correctly, using PDMAUDIOPCMPROPS_MAKE_SHIFT. */
+#define PDMAUDIOPCMPROPS_S2B(pProps, samples)                   ((samples) << (pProps)->cShift)
+/** Converts bytes to (audio) samples.
+ *  Needs the cShift value set correctly, using PDMAUDIOPCMPROPS_MAKE_SHIFT. */
+#define PDMAUDIOPCMPROPS_B2S(pProps, cb)                        (cb >> (pProps)->cShift)
 
 /**
  * Structure keeping an audio volume level.
@@ -250,44 +267,120 @@ typedef struct PDMAUDIOSTRMRATE
 } PDMAUDIOSTRMRATE, *PPDMAUDIOSTRMRATE;
 
 /**
+ * Structure for holding mixing buffer volume parameters.
+ * The volume values are in fixed point style and must
+ * be converted to/from before using with e.g. PDMAUDIOVOLUME.
+ */
+typedef struct PDMAUDMIXBUFVOL
+{
+    /** Set to @c true if this stream is muted, @c false if not. */
+    bool    fMuted;
+    /** Left volume to apply during conversion. Pass 0
+     *  to convert the original values. May not apply to
+     *  all conversion functions. */
+    uint32_t uLeft;
+    /** Right volume to apply during conversion. Pass 0
+     *  to convert the original values. May not apply to
+     *  all conversion functions. */
+    uint32_t uRight;
+} PDMAUDMIXBUFVOL, *PPDMAUDMIXBUFVOL;
+
+/**
+ * Structure for holding sample conversion parameters for
+ * the audioMixBufConvFromXXX / audioMixBufConvToXXX macros.
+ */
+typedef struct PDMAUDMIXBUFCONVOPTS
+{
+    /** Number of audio samples to convert. */
+    uint32_t        cSamples;
+    union
+    {
+        struct
+        {
+            /** Volume to use for conversion. */
+            PDMAUDMIXBUFVOL Volume;
+        } From;
+    };
+} PDMAUDMIXBUFCONVOPTS;
+/** Pointer to conversion parameters for the audio mixer.   */
+typedef PDMAUDMIXBUFCONVOPTS *PPDMAUDMIXBUFCONVOPTS;
+/** Pointer to const conversion parameters for the audio mixer.   */
+typedef PDMAUDMIXBUFCONVOPTS const *PCPDMAUDMIXBUFCONVOPTS;
+
+/**
  * Note: All internal handling is done in samples,
  *       not in bytes!
  */
 typedef uint32_t PDMAUDIOMIXBUFFMT;
 typedef PDMAUDIOMIXBUFFMT *PPDMAUDIOMIXBUFFMT;
 
+/**
+ * Convertion-from function used by the PDM audio buffer mixer.
+ *
+ * @returns Number of samples returned.
+ * @param   paDst           Where to return the converted samples.
+ * @param   pvSrc           The source samples bytes.
+ * @param   cbSrc           Number of bytes to convert.
+ * @param   pOpts           Conversion options.
+ */
+typedef DECLCALLBACK(uint32_t) FNPDMAUDIOMIXBUFCONVFROM(PPDMAUDIOSAMPLE paDst, const void *pvSrc, uint32_t cbSrc,
+                                                        PCPDMAUDMIXBUFCONVOPTS pOpts);
+/** Pointer to a convertion-from function used by the PDM audio buffer mixer. */
+typedef FNPDMAUDIOMIXBUFCONVFROM *PFNPDMAUDIOMIXBUFCONVFROM;
+
+/**
+ * Convertion-to function used by the PDM audio buffer mixer.
+ *
+ * @param   pvDst           Output buffer.
+ * @param   paSrc           The input samples.
+ * @param   pOpts           Conversion options.
+ */
+typedef DECLCALLBACK(void) FNPDMAUDIOMIXBUFCONVTO(void *pvDst, PCPDMAUDIOSAMPLE paSrc, PCPDMAUDMIXBUFCONVOPTS pOpts);
+/** Pointer to a convertion-to function used by the PDM audio buffer mixer. */
+typedef FNPDMAUDIOMIXBUFCONVTO *PFNPDMAUDIOMIXBUFCONVTO;
+
 typedef struct PDMAUDIOMIXBUF *PPDMAUDIOMIXBUF;
 typedef struct PDMAUDIOMIXBUF
 {
-    RTLISTNODE             Node;
+    RTLISTNODE                Node;
     /** Name of the buffer. */
-    char                  *pszName;
+    char                     *pszName;
     /** Sample buffer. */
-    PPDMAUDIOSAMPLE        pSamples;
+    PPDMAUDIOSAMPLE           pSamples;
     /** Size of the sample buffer (in samples). */
-    uint32_t               cSamples;
-    /** The current read/write position (in samples)
-     *  in the samples buffer. */
-    uint32_t               offReadWrite;
+    uint32_t                  cSamples;
+    /** The current read position (in samples). */
+    uint32_t                  offRead;
+    /** The current write position (in samples). */
+    uint32_t                  offWrite;
     /**
      * Total samples already mixed down to the parent buffer (if any). Always starting at
-     * the parent's offReadWrite position.
+     * the parent's offRead position.
      *
      * Note: Count always is specified in parent samples, as the sample count can differ between parent
      *       and child.
      */
-    uint32_t               cMixed;
-    uint32_t               cProcessed;
+    uint32_t                  cMixed;
+    /** How much audio samples are currently being used
+     *  in this buffer.
+     *  Note: This also is known as the distance in ring buffer terms. */
+    uint32_t                  cUsed;
     /** Pointer to parent buffer (if any). */
-    PPDMAUDIOMIXBUF        pParent;
+    PPDMAUDIOMIXBUF           pParent;
     /** List of children mix buffers to keep in sync with (if being a parent buffer). */
-    RTLISTANCHOR           lstBuffers;
+    RTLISTANCHOR              lstChildren;
+    /** Number of children mix buffers kept in lstChildren. */
+    uint32_t                  cChildren;
     /** Intermediate structure for buffer conversion tasks. */
-    PPDMAUDIOSTRMRATE      pRate;
-    /** Current volume used for mixing. */
-    PDMAUDIOVOLUME         Volume;
+    PPDMAUDIOSTRMRATE         pRate;
+    /** Internal representation of current volume used for mixing. */
+    PDMAUDMIXBUFVOL           Volume;
     /** This buffer's audio format. */
-    PDMAUDIOMIXBUFFMT      AudioFmt;
+    PDMAUDIOMIXBUFFMT         AudioFmt;
+    /** Standard conversion-to function for set AudioFmt. */
+    PFNPDMAUDIOMIXBUFCONVTO   pfnConvTo;
+    /** Standard conversion-from function for set AudioFmt. */
+    PFNPDMAUDIOMIXBUFCONVFROM pfnConvFrom;
     /**
      * Ratio of the associated parent stream's frequency by this stream's
      * frequency (1<<32), represented as a signed 64 bit integer.
@@ -298,10 +391,9 @@ typedef struct PDMAUDIOMIXBUF
      *
      * Currently this does not get changed once assigned.
      */
-    int64_t                iFreqRatio;
-    /* For quickly converting samples <-> bytes and
-     * vice versa. */
-    uint8_t                cShift;
+    int64_t                   iFreqRatio;
+    /** For quickly converting samples <-> bytes and vice versa. */
+    uint8_t                   cShift;
 } PDMAUDIOMIXBUF;
 
 /** Stream status flag. To be used with PDMAUDIOSTRMSTS_FLAG_ flags. */
@@ -336,7 +428,7 @@ typedef struct PDMAUDIOHSTSTRMIN
     /** List node. */
     RTLISTNODE             Node;
     /** PCM properties. */
-    PDMPCMPROPS            Props;
+    PDMAUDIOPCMPROPS       Props;
     /** Stream status flag. */
     PDMAUDIOSTRMSTS        fStatus;
     /** Critical section for serializing access. */
@@ -359,7 +451,7 @@ typedef struct PDMAUDIOHSTSTRMOUT
     /** List node. */
     RTLISTNODE             Node;
     /** Stream properites. */
-    PDMPCMPROPS            Props;
+    PDMAUDIOPCMPROPS       Props;
     /** Stream status flag. */
     PDMAUDIOSTRMSTS        fStatus;
     /** Critical section for serializing access. */
@@ -368,6 +460,8 @@ typedef struct PDMAUDIOHSTSTRMOUT
     PDMAUDIOMIXBUF         MixBuf;
     /** Associated guest output streams. */
     RTLISTANCHOR           lstGstStrmOut;
+    /** Timestamp (in ns) of last audio data playback. */
+    uint64_t               tsLastPlayedNs;
 } PDMAUDIOHSTSTRMOUT, *PPDMAUDIOHSTSTRMOUT;
 
 /**
@@ -395,7 +489,7 @@ typedef struct PDMAUDIOGSTSTRMSTATE
 typedef struct PDMAUDIOGSTSTRMIN
 {
     /** Guest stream properites. */
-    PDMPCMPROPS            Props;
+    PDMAUDIOPCMPROPS       Props;
     /** Current stream state. */
     PDMAUDIOGSTSTRMSTATE   State;
     /** This stream's mixing buffer. */
@@ -415,13 +509,15 @@ typedef struct PDMAUDIOGSTSTRMOUT
     /** List node. */
     RTLISTNODE             Node;
     /** Guest output stream properites. */
-    PDMPCMPROPS            Props;
+    PDMAUDIOPCMPROPS       Props;
     /** Current stream state. */
     PDMAUDIOGSTSTRMSTATE   State;
     /** This stream's mixing buffer. */
     PDMAUDIOMIXBUF         MixBuf;
     /** Pointer to the associated host output stream. */
     PPDMAUDIOHSTSTRMOUT    pHstStrmOut;
+    /** Timestamp (in ns) of last written audio data. */
+    uint64_t               tsLastWrittenNs;
 } PDMAUDIOGSTSTRMOUT, *PPDMAUDIOGSTSTRMOUT;
 
 /** Pointer to a audio connector interface. */
diff --git a/include/VBox/vmm/vmm.h b/include/VBox/vmm/vmm.h
index df7dfca..24ab647 100644
--- a/include/VBox/vmm/vmm.h
+++ b/include/VBox/vmm/vmm.h
@@ -515,9 +515,9 @@ typedef struct GCFGMVALUEREQ
 typedef GCFGMVALUEREQ *PGCFGMVALUEREQ;
 
 #if defined(IN_RING0) || defined(DOXYGEN_RUNNING)
-VMMR0DECL(int)       VMMR0EntryInt(PVM pVM, VMMR0OPERATION enmOperation, void *pvArg);
-VMMR0DECL(void)      VMMR0EntryFast(PVM pVM, VMCPUID idCpu, VMMR0OPERATION enmOperation);
-VMMR0DECL(int)       VMMR0EntryEx(PVM pVM, VMCPUID idCpu, VMMR0OPERATION enmOperation, PSUPVMMR0REQHDR pReq, uint64_t u64Arg, PSUPDRVSESSION);
+VMMR0DECL(void)      VMMR0EntryFast(PGVM pGVM, PVM pVM, VMCPUID idCpu, VMMR0OPERATION enmOperation);
+VMMR0DECL(int)       VMMR0EntryEx(PGVM pGVM, PVM pVM, VMCPUID idCpu, VMMR0OPERATION enmOperation,
+                                  PSUPVMMR0REQHDR pReq, uint64_t u64Arg, PSUPDRVSESSION);
 VMMR0_INT_DECL(int)  VMMR0TermVM(PVM pVM, PGVM pGVM);
 VMMR0_INT_DECL(bool) VMMR0IsLongJumpArmed(PVMCPU pVCpu);
 VMMR0_INT_DECL(bool) VMMR0IsInRing3LongJump(PVMCPU pVCpu);
diff --git a/include/iprt/asm.h b/include/iprt/asm.h
index c3d9a25..75f24b9 100644
--- a/include/iprt/asm.h
+++ b/include/iprt/asm.h
@@ -140,8 +140,9 @@
  * Used to work around some 4.3.x register allocation issues in this version of
  * the compiler. So far this workaround is still required for 4.4 and 4.5 but
  * definitely not for 5.x */
-#define RT_INLINE_ASM_GCC_4_3_X_X86 (RT_GNUC_PREREQ(4, 3) && !RT_GNUC_PREREQ(5, 0) && defined(__i386__))
-#ifndef RT_INLINE_ASM_GCC_4_3_X_X86
+#if (RT_GNUC_PREREQ(4, 3) && !RT_GNUC_PREREQ(5, 0) && defined(__i386__))
+# define RT_INLINE_ASM_GCC_4_3_X_X86 1
+#else
 # define RT_INLINE_ASM_GCC_4_3_X_X86 0
 #endif
 
@@ -158,12 +159,13 @@
 #  define RT_INLINE_DONT_MIX_CMPXCHG8B_AND_PIC 1
 # elif defined(_MSC_VER) /* Visual C++ has trouble too, but it'll only tell us when C4688 is enabled. */
 #  define RT_INLINE_DONT_MIX_CMPXCHG8B_AND_PIC 0
+# elif (   (defined(PIC) || defined(__PIC__)) \
+        && defined(RT_ARCH_X86) \
+        && (   RT_INLINE_ASM_GCC_4_3_X_X86 \
+            || defined(RT_OS_DARWIN)) )
+#  define RT_INLINE_DONT_MIX_CMPXCHG8B_AND_PIC 1
 # else
-#  define RT_INLINE_DONT_MIX_CMPXCHG8B_AND_PIC \
-    (   (defined(PIC) || defined(__PIC__)) \
-     && defined(RT_ARCH_X86) \
-     && (   RT_INLINE_ASM_GCC_4_3_X_X86 \
-         || defined(RT_OS_DARWIN)) )
+#  define RT_INLINE_DONT_MIX_CMPXCHG8B_AND_PIC 0
 # endif
 #endif
 
diff --git a/include/iprt/cdefs.h b/include/iprt/cdefs.h
index f901144..5fca8bc 100644
--- a/include/iprt/cdefs.h
+++ b/include/iprt/cdefs.h
@@ -1093,14 +1093,12 @@
  *          Do NOT use this for the actual throwing of exceptions!
  */
 #ifdef RT_EXCEPTIONS_ENABLED
-# ifdef _MSC_VER
-#  if _MSC_VER >= 1310
+# if RT_MSC_PREREQ_EX(RT_MSC_VER_VC71, 0)
+#   define RT_THROW(type)
+# elif RT_GNUC_PREREQ(7, 0)
 #   define RT_THROW(type)
-#  else
-#   define RT_THROW(type)       throw(type)
-#  endif
 # else
-#  define RT_THROW(type)        throw(type)
+#   define RT_THROW(type)       throw(type)
 # endif
 #else
 # define RT_THROW(type)
@@ -2248,6 +2246,15 @@
  */
 #define RT_SIZEOFMEMB(type, member)             ( sizeof(((type *)(void *)0)->member) )
 
+/** @def RT_UOFFSET_AFTER
+ * Returns the offset of the first byte following a structure/union member.
+ *
+ * @return byte offset into the struct.
+ * @param   a_Type      Structure type.
+ * @param   a_Member    The member name.
+ */
+#define RT_UOFFSET_AFTER(a_Type, a_Member)      ( RT_UOFFSETOF(a_Type, a_Member) + RT_SIZEOFMEMB(a_Type, a_Member) )
+
 /** @def RT_FROM_MEMBER
  * Convert a pointer to a structure member into a pointer to the structure.
  *
@@ -2302,7 +2309,7 @@
  * @sa      RT_FLEXIBLE_ARRAY_NESTED, RT_FLEXIBLE_ARRAY_IN_UNION
  */
 #if RT_MSC_PREREQ(RT_MSC_VER_VS2005) /** @todo Probably much much earlier. */ \
- || (defined(__cplusplus) && RT_GNUC_PREREQ(6, 1)) \
+ || (defined(__cplusplus) && RT_GNUC_PREREQ(6, 1) && !RT_GNUC_PREREQ(7, 0)) /* gcc-7 warns again */\
  || defined(__WATCOMC__) /* openwatcom 1.9 supports it, we don't care about older atm. */
 # define RT_FLEXIBLE_ARRAY
 # if defined(__cplusplus) && defined(_MSC_VER)
diff --git a/include/iprt/formats/pecoff.h b/include/iprt/formats/pecoff.h
index cb25ac8..2d11da6 100644
--- a/include/iprt/formats/pecoff.h
+++ b/include/iprt/formats/pecoff.h
@@ -921,9 +921,58 @@ AssertCompileSize(IMAGE_LOAD_CONFIG_DIRECTORY32_V8, 0x98);
 typedef IMAGE_LOAD_CONFIG_DIRECTORY32_V8 *PIMAGE_LOAD_CONFIG_DIRECTORY32_V8;
 typedef IMAGE_LOAD_CONFIG_DIRECTORY32_V8 const *PCIMAGE_LOAD_CONFIG_DIRECTORY32_V8;
 
-typedef IMAGE_LOAD_CONFIG_DIRECTORY32_V8   IMAGE_LOAD_CONFIG_DIRECTORY32;
-typedef PIMAGE_LOAD_CONFIG_DIRECTORY32_V8  PIMAGE_LOAD_CONFIG_DIRECTORY32;
-typedef PCIMAGE_LOAD_CONFIG_DIRECTORY32_V8 PCIMAGE_LOAD_CONFIG_DIRECTORY32;
+/** @since  Windows 10 build 16237 (or maybe earlier). */
+typedef struct _IMAGE_LOAD_CONFIG_DIRECTORY32_V9
+{
+    uint32_t  Size;                                 /**< 0x00 */
+    uint32_t  TimeDateStamp;                        /**< 0x04 */
+    uint16_t  MajorVersion;                         /**< 0x08 */
+    uint16_t  MinorVersion;                         /**< 0x0a */
+    uint32_t  GlobalFlagsClear;                     /**< 0x0c */
+    uint32_t  GlobalFlagsSet;                       /**< 0x10 */
+    uint32_t  CriticalSectionDefaultTimeout;        /**< 0x14 */
+    uint32_t  DeCommitFreeBlockThreshold;           /**< 0x18 */
+    uint32_t  DeCommitTotalFreeThreshold;           /**< 0x1c */
+    uint32_t  LockPrefixTable;                      /**< 0x20 */
+    uint32_t  MaximumAllocationSize;                /**< 0x24 */
+    uint32_t  VirtualMemoryThreshold;               /**< 0x28 */
+    uint32_t  ProcessHeapFlags;                     /**< 0x2c */
+    uint32_t  ProcessAffinityMask;                  /**< 0x30 */
+    uint16_t  CSDVersion;                           /**< 0x34 */
+    uint16_t  DependentLoadFlags;                   /**< 0x36 */
+    uint32_t  EditList;                             /**< 0x38 */
+    uint32_t  SecurityCookie;                       /**< 0x3c */
+    uint32_t  SEHandlerTable;                       /**< 0x40 */
+    uint32_t  SEHandlerCount;                       /**< 0x44 */
+    uint32_t  GuardCFCCheckFunctionPointer;         /**< 0x48 */
+    uint32_t  GuardCFDispatchFunctionPointer;       /**< 0x4c */
+    uint32_t  GuardCFFunctionTable;                 /**< 0x50 */
+    uint32_t  GuardCFFunctionCount;                 /**< 0x54 */
+    uint32_t  GuardFlags;                           /**< 0x58 */
+    IMAGE_LOAD_CONFIG_CODE_INTEGRITY CodeIntegrity; /**< 0x5c */
+    uint32_t  GuardAddressTakenIatEntryTable;       /**< 0x68 */
+    uint32_t  GuardAddressTakenIatEntryCount;       /**< 0x6c */
+    uint32_t  GuardLongJumpTargetTable;             /**< 0x70 */
+    uint32_t  GuardLongJumpTargetCount;             /**< 0x74 */
+    uint32_t  DynamicValueRelocTable;               /**< 0x78 */
+    uint32_t  CHPEMetadataPointer;                  /**< 0x7c Not sure when this was renamed from HybridMetadataPointer. */
+    uint32_t  GuardRFFailureRoutine;                /**< 0x80 */
+    uint32_t  GuardRFFailureRoutineFunctionPointer; /**< 0x84 */
+    uint32_t  DynamicValueRelocTableOffset;         /**< 0x88 */
+    uint16_t  DynamicValueRelocTableSection;        /**< 0x8c */
+    uint16_t  Reserved2;                            /**< 0x8e */
+    uint32_t  GuardRFVerifyStackPointerFunctionPointer; /**< 0x90 */
+    uint32_t  HotPatchTableOffset;                  /**< 0x94 */
+    uint32_t  AddressOfSomeUnicodeString;           /**< 0x98 - 64-bit version has this member about here. not sure about location yet. */
+    uint32_t  Reserved3QuestionMark;                /**< 0x9a - Did they 8-byte pad the structure or is AddressOfSomeUnicodeString 64-bit? */
+} IMAGE_LOAD_CONFIG_DIRECTORY32_V9;
+AssertCompileSize(IMAGE_LOAD_CONFIG_DIRECTORY32_V9, 0xa0);
+typedef IMAGE_LOAD_CONFIG_DIRECTORY32_V9 *PIMAGE_LOAD_CONFIG_DIRECTORY32_V9;
+typedef IMAGE_LOAD_CONFIG_DIRECTORY32_V9 const *PCIMAGE_LOAD_CONFIG_DIRECTORY32_V9;
+
+typedef IMAGE_LOAD_CONFIG_DIRECTORY32_V9   IMAGE_LOAD_CONFIG_DIRECTORY32;
+typedef PIMAGE_LOAD_CONFIG_DIRECTORY32_V9  PIMAGE_LOAD_CONFIG_DIRECTORY32;
+typedef PCIMAGE_LOAD_CONFIG_DIRECTORY32_V9 PCIMAGE_LOAD_CONFIG_DIRECTORY32;
 
 
 /* No _IMAGE_LOAD_CONFIG_DIRECTORY64_V1 exists. */
@@ -1195,9 +1244,58 @@ AssertCompileSize(IMAGE_LOAD_CONFIG_DIRECTORY64_V8, 0xf4);
 typedef IMAGE_LOAD_CONFIG_DIRECTORY64_V8 *PIMAGE_LOAD_CONFIG_DIRECTORY64_V8;
 typedef IMAGE_LOAD_CONFIG_DIRECTORY64_V8 const *PCIMAGE_LOAD_CONFIG_DIRECTORY64_V8;
 
-typedef IMAGE_LOAD_CONFIG_DIRECTORY64_V8   IMAGE_LOAD_CONFIG_DIRECTORY64;
-typedef PIMAGE_LOAD_CONFIG_DIRECTORY64_V8  PIMAGE_LOAD_CONFIG_DIRECTORY64;
-typedef PCIMAGE_LOAD_CONFIG_DIRECTORY64_V8 PCIMAGE_LOAD_CONFIG_DIRECTORY64;
+/** @since  Windows 10 build 15002 (or maybe earlier). */
+typedef struct _IMAGE_LOAD_CONFIG_DIRECTORY64_V9
+{
+    uint32_t  Size;                                 /**< 0x00 */
+    uint32_t  TimeDateStamp;                        /**< 0x04 */
+    uint16_t  MajorVersion;                         /**< 0x08 */
+    uint16_t  MinorVersion;                         /**< 0x0a */
+    uint32_t  GlobalFlagsClear;                     /**< 0x0c */
+    uint32_t  GlobalFlagsSet;                       /**< 0x10 */
+    uint32_t  CriticalSectionDefaultTimeout;        /**< 0x14 */
+    uint64_t  DeCommitFreeBlockThreshold;           /**< 0x18 */
+    uint64_t  DeCommitTotalFreeThreshold;           /**< 0x20 */
+    uint64_t  LockPrefixTable;                      /**< 0x28 */
+    uint64_t  MaximumAllocationSize;                /**< 0x30 */
+    uint64_t  VirtualMemoryThreshold;               /**< 0x38 */
+    uint64_t  ProcessAffinityMask;                  /**< 0x40 */
+    uint32_t  ProcessHeapFlags;                     /**< 0x48 */
+    uint16_t  CSDVersion;                           /**< 0x4c */
+    uint16_t  DependentLoadFlags;                   /**< 0x4e */
+    uint64_t  EditList;                             /**< 0x50 */
+    uint64_t  SecurityCookie;                       /**< 0x58 */
+    uint64_t  SEHandlerTable;                       /**< 0x60 */
+    uint64_t  SEHandlerCount;                       /**< 0x68 */
+    uint64_t  GuardCFCCheckFunctionPointer;         /**< 0x70 */
+    uint64_t  GuardCFDispatchFunctionPointer;       /**< 0x78 */
+    uint64_t  GuardCFFunctionTable;                 /**< 0x80 */
+    uint64_t  GuardCFFunctionCount;                 /**< 0x88 */
+    uint32_t  GuardFlags;                           /**< 0x90 */
+    IMAGE_LOAD_CONFIG_CODE_INTEGRITY CodeIntegrity; /**< 0x94 */
+    uint64_t  GuardAddressTakenIatEntryTable;       /**< 0xa0 */
+    uint64_t  GuardAddressTakenIatEntryCount;       /**< 0xa8 */
+    uint64_t  GuardLongJumpTargetTable;             /**< 0xb0 */
+    uint64_t  GuardLongJumpTargetCount;             /**< 0xb8 */
+    uint64_t  DynamicValueRelocTable;               /**< 0xc0 */
+    uint64_t  CHPEMetadataPointer;                  /**< 0xc8 */
+    uint64_t  GuardRFFailureRoutine;                /**< 0xd0 */
+    uint64_t  GuardRFFailureRoutineFunctionPointer; /**< 0xd8 */
+    uint32_t  DynamicValueRelocTableOffset;         /**< 0xe0 */
+    uint16_t  DynamicValueRelocTableSection;        /**< 0xe4 */
+    uint16_t  Reserved2;                            /**< 0xe6 */
+    uint64_t  GuardRFVerifyStackPointerFunctionPointer; /**< 0xe8 */
+    uint32_t  HotPatchTableOffset;                  /**< 0xf0 */
+    uint32_t  Reserved3;                            /**< 0xf4 */
+    uint64_t  AddressOfSomeUnicodeString;           /**< 0xf8 - seen in bcrypt and bcryptprimitives pointing to the string "L". */
+} IMAGE_LOAD_CONFIG_DIRECTORY64_V9;
+AssertCompileSize(IMAGE_LOAD_CONFIG_DIRECTORY64_V9, 0x100);
+typedef IMAGE_LOAD_CONFIG_DIRECTORY64_V9 *PIMAGE_LOAD_CONFIG_DIRECTORY64_V9;
+typedef IMAGE_LOAD_CONFIG_DIRECTORY64_V9 const *PCIMAGE_LOAD_CONFIG_DIRECTORY64_V9;
+
+typedef IMAGE_LOAD_CONFIG_DIRECTORY64_V9   IMAGE_LOAD_CONFIG_DIRECTORY64;
+typedef PIMAGE_LOAD_CONFIG_DIRECTORY64_V9  PIMAGE_LOAD_CONFIG_DIRECTORY64;
+typedef PCIMAGE_LOAD_CONFIG_DIRECTORY64_V9 PCIMAGE_LOAD_CONFIG_DIRECTORY64;
 
 /** @} */
 
diff --git a/include/iprt/mangling.h b/include/iprt/mangling.h
index c1daa8f..40c0c07 100644
--- a/include/iprt/mangling.h
+++ b/include/iprt/mangling.h
@@ -1378,6 +1378,8 @@
 # define RTNetStrIsIPv6AddrAny                          RT_MANGLER(RTNetStrIsIPv6AddrAny)
 # define RTNetStrToIPv6AddrEx                           RT_MANGLER(RTNetStrToIPv6AddrEx)
 # define RTNetStrToIPv6Addr                             RT_MANGLER(RTNetStrToIPv6Addr)
+# define RTNetMaskToPrefixIPv6                          RT_MANGLER(RTNetMaskToPrefixIPv6)
+# define RTNetPrefixToMaskIPv6                          RT_MANGLER(RTNetPrefixToMaskIPv6)
 # define RTOnceSlow                                     RT_MANGLER(RTOnceSlow)
 # define RTOnceReset                                    RT_MANGLER(RTOnceReset)
 # define RTPathAbs                                      RT_MANGLER(RTPathAbs)
@@ -1828,6 +1830,8 @@
 # define RTStrFormatTypeRegister                        RT_MANGLER(RTStrFormatTypeRegister)
 # define RTStrFormatTypeSetUser                         RT_MANGLER(RTStrFormatTypeSetUser)
 # define RTStrFormatU128                                RT_MANGLER(RTStrFormatU128)
+# define RTStrFormatU256                                RT_MANGLER(RTStrFormatU256)
+# define RTStrFormatU512                                RT_MANGLER(RTStrFormatU512)
 # define RTStrFormatU16                                 RT_MANGLER(RTStrFormatU16)
 # define RTStrFormatU32                                 RT_MANGLER(RTStrFormatU32)
 # define RTStrFormatU64                                 RT_MANGLER(RTStrFormatU64)
@@ -3364,6 +3368,7 @@
 # define RTUtf16CatAscii                                RT_MANGLER(RTUtf16CatAscii)
 # define RTUtf16End                                     RT_MANGLER(RTUtf16End)
 # define RTUtf16ICmpAscii                               RT_MANGLER(RTUtf16ICmpAscii)
+# define RTUtf16NICmpAscii                              RT_MANGLER(RTUtf16NICmpAscii)
 # define RTUtf16NLen                                    RT_MANGLER(RTUtf16NLen)
 # define RTUtf16NLenEx                                  RT_MANGLER(RTUtf16NLenEx)
 # define RTUtf16PrintHexBytes                           RT_MANGLER(RTUtf16PrintHexBytes)
diff --git a/include/iprt/net.h b/include/iprt/net.h
index 4b54a63..3f43a9c 100644
--- a/include/iprt/net.h
+++ b/include/iprt/net.h
@@ -181,6 +181,30 @@ RTDECL(int) RTNetStrToIPv6AddrEx(const char *pcszAddr, PRTNETADDRIPV6 pAddr, cha
 RTDECL(int) RTNetStrToIPv6Addr(const char *pcszAddr, PRTNETADDRIPV6 pAddr, char **ppszZone);
 
 /**
+ * Verifies that RTNETADDRIPV6 is a valid contiguous netmask and
+ * computes its prefix length.
+ *
+ * @returns VINF_SUCCESS on success, VERR_INVALID_PARAMETER on
+ *          failure.
+ *
+ * @param   pMask           The netmask to verify and convert.
+ * @param   piPrefix        Where to store the prefix length. (Optional)
+ */
+RTDECL(int) RTNetMaskToPrefixIPv6(PCRTNETADDRIPV6 pMask, int *piPrefix);
+
+/**
+ * Computes netmask corresponding to the prefix length.
+ *
+ * @returns VINF_SUCCESS on success, VERR_INVALID_PARAMETER on
+ *          failure.
+ *
+ * @param   iPrefix         The prefix to convert.
+ * @param   pMask           Where to store the netmask.
+ */
+RTDECL(int) RTNetPrefixToMaskIPv6(int iPrefix, PRTNETADDRIPV6 pMask);
+
+
+/**
  * IPX address.
  */
 #pragma pack(1)
diff --git a/include/iprt/nt/nt.h b/include/iprt/nt/nt.h
index 136b5ed..0b272fa 100644
--- a/include/iprt/nt/nt.h
+++ b/include/iprt/nt/nt.h
@@ -2607,6 +2607,12 @@ NTSYSAPI NTSTATUS NTAPI RtlDosApplyFileIsolationRedirection_Ustr(IN ULONG fFlags
                                                                  IN PULONG pfNewFlags OPTIONAL,
                                                                  IN PSIZE_T pcbFilename OPTIONAL,
                                                                  IN PSIZE_T pcbNeeded OPTIONAL);
+/** @since Windows 8.
+ * @note Status code is always zero in windows 10 build 14393. */
+NTSYSAPI NTSTATUS NTAPI ApiSetQueryApiSetPresence(IN PCUNICODE_STRING pAllegedApiSetDll, OUT PBOOLEAN pfPresent);
+/** @copydoc ApiSetQueryApiSetPresence */
+typedef NTSTATUS (NTAPI *PFNAPISETQUERYAPISETPRESENCE)(IN PCUNICODE_STRING pAllegedApiSetDll, OUT PBOOLEAN pfPresent);
+
 
 # ifdef IPRT_NT_USE_WINTERNL
 typedef NTSTATUS NTAPI RTL_HEAP_COMMIT_ROUTINE(PVOID, PVOID *, PSIZE_T);
diff --git a/include/iprt/string.h b/include/iprt/string.h
index 7f8f969..e14b803 100644
--- a/include/iprt/string.h
+++ b/include/iprt/string.h
@@ -32,11 +32,8 @@
 #include <iprt/stdarg.h>
 #include <iprt/err.h> /* for VINF_SUCCESS */
 #if defined(RT_OS_LINUX) && defined(__KERNEL__)
-  RT_C_DECLS_BEGIN
-# define new newhack /* string.h: strreplace */
+  /* no C++ hacks ('new' etc) here anymore! */
 # include <linux/string.h>
-# undef new
-  RT_C_DECLS_END
 
 #elif defined(IN_XF86_MODULE) && !defined(NO_ANSIC)
   RT_C_DECLS_BEGIN
@@ -1599,11 +1596,48 @@ RTDECL(ssize_t) RTStrFormatU64(char *pszBuf, size_t cbBuf, uint64_t u64Value, un
  * @param   cchWidth        Width.
  * @param   cchPrecision    Precision.
  * @param   fFlags          Flags, RTSTR_F_XXX.
+ * @remarks The current implementation is limited to base 16 and doesn't do
+ *          width or precision and probably ignores few flags too.
  */
 RTDECL(ssize_t) RTStrFormatU128(char *pszBuf, size_t cbBuf, PCRTUINT128U pu128Value, unsigned int uiBase,
                                 signed int cchWidth, signed int cchPrecision, uint32_t fFlags);
 
 /**
+ * Formats an unsigned 256-bit number.
+ *
+ * @returns The length of the formatted number or VERR_BUFFER_OVERFLOW.
+ * @param   pszBuf          The output buffer.
+ * @param   cbBuf           The size of the output buffer.
+ * @param   pu256Value      The value to format.
+ * @param   uiBase          Number representation base.
+ * @param   cchWidth        Width.
+ * @param   cchPrecision    Precision.
+ * @param   fFlags          Flags, RTSTR_F_XXX.
+ * @remarks The current implementation is limited to base 16 and doesn't do
+ *          width or precision and probably ignores few flags too.
+ */
+RTDECL(ssize_t) RTStrFormatU256(char *pszBuf, size_t cbBuf, PCRTUINT256U pu256Value, unsigned int uiBase,
+                                signed int cchWidth, signed int cchPrecision, uint32_t fFlags);
+
+/**
+ * Formats an unsigned 512-bit number.
+ *
+ * @returns The length of the formatted number or VERR_BUFFER_OVERFLOW.
+ * @param   pszBuf          The output buffer.
+ * @param   cbBuf           The size of the output buffer.
+ * @param   pu512Value      The value to format.
+ * @param   uiBase          Number representation base.
+ * @param   cchWidth        Width.
+ * @param   cchPrecision    Precision.
+ * @param   fFlags          Flags, RTSTR_F_XXX.
+ * @remarks The current implementation is limited to base 16 and doesn't do
+ *          width or precision and probably ignores few flags too.
+ */
+RTDECL(ssize_t) RTStrFormatU512(char *pszBuf, size_t cbBuf, PCRTUINT512U pu512Value, unsigned int uiBase,
+                                signed int cchWidth, signed int cchPrecision, uint32_t fFlags);
+
+
+/**
  * Formats an 80-bit extended floating point number.
  *
  * @returns The length of the formatted number or VERR_BUFFER_OVERFLOW.
diff --git a/include/iprt/types.h b/include/iprt/types.h
index 11778ae..fee3303 100644
--- a/include/iprt/types.h
+++ b/include/iprt/types.h
@@ -524,9 +524,9 @@ typedef union RTUINT128U
     uint8_t     au8[16];
 } RTUINT128U;
 #pragma pack()
-/** Pointer to a 64-bit unsigned integer union. */
+/** Pointer to a 128-bit unsigned integer union. */
 typedef RTUINT128U *PRTUINT128U;
-/** Pointer to a const 64-bit unsigned integer union. */
+/** Pointer to a const 128-bit unsigned integer union. */
 typedef const RTUINT128U *PCRTUINT128U;
 
 /** @def RTUINT128_INIT
@@ -547,6 +547,341 @@ typedef const RTUINT128U *PCRTUINT128U;
 
 
 /**
+ * 256-bit unsigned integer union.
+ */
+#pragma pack(1)
+typedef union RTUINT256U
+{
+    /** Quad-Word view (first as it's used by RTUINT256_INIT). */
+    struct
+    {
+#ifdef RT_BIG_ENDIAN
+        uint64_t    qw3;
+        uint64_t    qw2;
+        uint64_t    qw1;
+        uint64_t    qw0;
+#else
+        uint64_t    qw0;
+        uint64_t    qw1;
+        uint64_t    qw2;
+        uint64_t    qw3;
+#endif
+    } QWords;
+    /** Double-Word view. */
+    struct
+    {
+#ifdef RT_BIG_ENDIAN
+        uint32_t    dw7;
+        uint32_t    dw6;
+        uint32_t    dw5;
+        uint32_t    dw4;
+        uint32_t    dw3;
+        uint32_t    dw2;
+        uint32_t    dw1;
+        uint32_t    dw0;
+#else
+        uint32_t    dw0;
+        uint32_t    dw1;
+        uint32_t    dw2;
+        uint32_t    dw3;
+        uint32_t    dw4;
+        uint32_t    dw5;
+        uint32_t    dw6;
+        uint32_t    dw7;
+#endif
+    } DWords;
+    /** Word view. */
+    struct
+    {
+#ifdef RT_BIG_ENDIAN
+        uint16_t    w15;
+        uint16_t    w14;
+        uint16_t    w13;
+        uint16_t    w12;
+        uint16_t    w11;
+        uint16_t    w10;
+        uint16_t    w9;
+        uint16_t    w8;
+        uint16_t    w7;
+        uint16_t    w6;
+        uint16_t    w5;
+        uint16_t    w4;
+        uint16_t    w3;
+        uint16_t    w2;
+        uint16_t    w1;
+        uint16_t    w0;
+#else
+        uint16_t    w0;
+        uint16_t    w1;
+        uint16_t    w2;
+        uint16_t    w3;
+        uint16_t    w4;
+        uint16_t    w5;
+        uint16_t    w6;
+        uint16_t    w7;
+        uint16_t    w8;
+        uint16_t    w9;
+        uint16_t    w10;
+        uint16_t    w11;
+        uint16_t    w12;
+        uint16_t    w13;
+        uint16_t    w14;
+        uint16_t    w15;
+#endif
+    } Words;
+
+    /** Double-Quad-Word view. */
+    struct
+    {
+#ifdef RT_BIG_ENDIAN
+        RTUINT128U  dqw1;
+        RTUINT128U  dqw0;
+#else
+        RTUINT128U  dqw0;
+        RTUINT128U  dqw1;
+#endif
+    } DQWords;
+
+    /** 128-bit view. */
+    RTUINT128U  au128[2];
+    /** 64-bit view. */
+    uint64_t    au64[4];
+    /** 32-bit view. */
+    uint32_t    au32[8];
+    /** 16-bit view. */
+    uint16_t    au16[16];
+    /** 8-bit view. */
+    uint8_t     au8[32];
+} RTUINT256U;
+#pragma pack()
+/** Pointer to a 256-bit unsigned integer union. */
+typedef RTUINT256U *PRTUINT256U;
+/** Pointer to a const 256-bit unsigned integer union. */
+typedef const RTUINT256U *PCRTUINT256U;
+
+/** @def RTUINT256_INIT
+ * Portable RTUINT256U initializer. */
+#ifdef RT_BIG_ENDIAN
+# define RTUINT256_INIT(a_Qw3, a_Qw2, a_Qw1, a_Qw0)   { { a_Qw3, a_Qw2, a_Qw1, a_Qw0 } }
+#else
+# define RTUINT256_INIT(a_Qw3, a_Qw2, a_Qw1, a_Qw0)   { { a_Qw0, a_Qw1, a_Qw2, a_Qw3 } }
+#endif
+
+/** @def RTUINT256_INIT_C
+ * Portable RTUINT256U initializer for 64-bit constants. */
+#define RTUINT256_INIT_C(a_Qw3, a_Qw2, a_Qw1, a_Qw0)  \
+    RTUINT256_INIT(UINT64_C(a_Qw3), UINT64_C(a_Qw2), UINT64_C(a_Qw1), UINT64_C(a_Qw0))
+
+
+/**
+ * 512-bit unsigned integer union.
+ */
+#pragma pack(1)
+typedef union RTUINT512U
+{
+    /** Quad-Word view (first as it's used by RTUINT512_INIT). */
+    struct
+    {
+#ifdef RT_BIG_ENDIAN
+        uint64_t    qw7;
+        uint64_t    qw6;
+        uint64_t    qw5;
+        uint64_t    qw4;
+        uint64_t    qw3;
+        uint64_t    qw2;
+        uint64_t    qw1;
+        uint64_t    qw0;
+#else
+        uint64_t    qw0;
+        uint64_t    qw1;
+        uint64_t    qw2;
+        uint64_t    qw3;
+        uint64_t    qw4;
+        uint64_t    qw5;
+        uint64_t    qw6;
+        uint64_t    qw7;
+#endif
+    } QWords;
+    /** Double-Word view. */
+    struct
+    {
+#ifdef RT_BIG_ENDIAN
+        uint32_t    dw15;
+        uint32_t    dw14;
+        uint32_t    dw13;
+        uint32_t    dw12;
+        uint32_t    dw11;
+        uint32_t    dw10;
+        uint32_t    dw9;
+        uint32_t    dw8;
+        uint32_t    dw7;
+        uint32_t    dw6;
+        uint32_t    dw5;
+        uint32_t    dw4;
+        uint32_t    dw3;
+        uint32_t    dw2;
+        uint32_t    dw1;
+        uint32_t    dw0;
+#else
+        uint32_t    dw0;
+        uint32_t    dw1;
+        uint32_t    dw2;
+        uint32_t    dw3;
+        uint32_t    dw4;
+        uint32_t    dw5;
+        uint32_t    dw6;
+        uint32_t    dw7;
+        uint32_t    dw8;
+        uint32_t    dw9;
+        uint32_t    dw10;
+        uint32_t    dw11;
+        uint32_t    dw12;
+        uint32_t    dw13;
+        uint32_t    dw14;
+        uint32_t    dw15;
+#endif
+    } DWords;
+    /** Word view. */
+    struct
+    {
+#ifdef RT_BIG_ENDIAN
+        uint16_t    w31;
+        uint16_t    w30;
+        uint16_t    w29;
+        uint16_t    w28;
+        uint16_t    w27;
+        uint16_t    w26;
+        uint16_t    w25;
+        uint16_t    w24;
+        uint16_t    w23;
+        uint16_t    w22;
+        uint16_t    w21;
+        uint16_t    w20;
+        uint16_t    w19;
+        uint16_t    w18;
+        uint16_t    w17;
+        uint16_t    w16;
+        uint16_t    w15;
+        uint16_t    w14;
+        uint16_t    w13;
+        uint16_t    w12;
+        uint16_t    w11;
+        uint16_t    w10;
+        uint16_t    w9;
+        uint16_t    w8;
+        uint16_t    w7;
+        uint16_t    w6;
+        uint16_t    w5;
+        uint16_t    w4;
+        uint16_t    w3;
+        uint16_t    w2;
+        uint16_t    w1;
+        uint16_t    w0;
+#else
+        uint16_t    w0;
+        uint16_t    w1;
+        uint16_t    w2;
+        uint16_t    w3;
+        uint16_t    w4;
+        uint16_t    w5;
+        uint16_t    w6;
+        uint16_t    w7;
+        uint16_t    w8;
+        uint16_t    w9;
+        uint16_t    w10;
+        uint16_t    w11;
+        uint16_t    w12;
+        uint16_t    w13;
+        uint16_t    w14;
+        uint16_t    w15;
+        uint16_t    w16;
+        uint16_t    w17;
+        uint16_t    w18;
+        uint16_t    w19;
+        uint16_t    w20;
+        uint16_t    w21;
+        uint16_t    w22;
+        uint16_t    w23;
+        uint16_t    w24;
+        uint16_t    w25;
+        uint16_t    w26;
+        uint16_t    w27;
+        uint16_t    w28;
+        uint16_t    w29;
+        uint16_t    w30;
+        uint16_t    w31;
+#endif
+    } Words;
+
+    /** Double-Quad-Word view. */
+    struct
+    {
+#ifdef RT_BIG_ENDIAN
+        RTUINT128U  dqw3;
+        RTUINT128U  dqw2;
+        RTUINT128U  dqw1;
+        RTUINT128U  dqw0;
+#else
+        RTUINT128U  dqw0;
+        RTUINT128U  dqw1;
+        RTUINT128U  dqw2;
+        RTUINT128U  dqw3;
+#endif
+    } DQWords;
+
+    /** Octo-Word view. */
+    struct
+    {
+#ifdef RT_BIG_ENDIAN
+        RTUINT256U  ow3;
+        RTUINT256U  ow2;
+        RTUINT256U  ow1;
+        RTUINT256U  ow0;
+#else
+        RTUINT256U  ow0;
+        RTUINT256U  ow1;
+        RTUINT256U  ow2;
+        RTUINT256U  ow3;
+#endif
+    } OWords;
+
+    /** 256-bit view. */
+    RTUINT256U  au256[2];
+    /** 128-bit view. */
+    RTUINT128U  au128[4];
+    /** 64-bit view. */
+    uint64_t    au64[8];
+    /** 32-bit view. */
+    uint32_t    au32[16];
+    /** 16-bit view. */
+    uint16_t    au16[32];
+    /** 8-bit view. */
+    uint8_t     au8[64];
+} RTUINT512U;
+#pragma pack()
+/** Pointer to a 512-bit unsigned integer union. */
+typedef RTUINT512U *PRTUINT512U;
+/** Pointer to a const 512-bit unsigned integer union. */
+typedef const RTUINT512U *PCRTUINT512U;
+
+/** @def RTUINT512_INIT
+ * Portable RTUINT512U initializer. */
+#ifdef RT_BIG_ENDIAN
+# define RTUINT512_INIT(a_Qw7, a_Qw6, a_Qw5, a_Qw4, a_Qw3, a_Qw2, a_Qw1, a_Qw0) \
+    { { a_Qw7, a_Qw6, a_Qw5, a_Qw4, a_Qw3, a_Qw2, a_Qw1, a_Qw0 } }
+#else
+# define RTUINT512_INIT(a_Qw7, a_Qw6, a_Qw5, a_Qw4, a_Qw3, a_Qw2, a_Qw1, a_Qw0) \
+    { { a_Qw0, a_Qw1, a_Qw2, a_Qw3, a_Qw4, a_Qw5, a_Qw6, a_Qw7 } }
+#endif
+
+/** @def RTUINT512_INIT_C
+ * Portable RTUINT512U initializer for 64-bit constants. */
+#define RTUINT512_INIT_C(a_Qw7, a_Qw6, a_Qw5, a_Qw4, a_Qw3, a_Qw2, a_Qw1, a_Qw0) \
+    RTUINT512_INIT(UINT64_C(a_Qw7), UINT64_C(a_Qw6), UINT64_C(a_Qw5), UINT64_C(a_Qw4), \
+                   UINT64_C(a_Qw3), UINT64_C(a_Qw2), UINT64_C(a_Qw1), UINT64_C(a_Qw0))
+
+
+/**
  * Double precision floating point format (64-bit).
  */
 typedef union RTFLOAT64U
diff --git a/include/iprt/utf16.h b/include/iprt/utf16.h
index 97fe9bb..f17ae55 100644
--- a/include/iprt/utf16.h
+++ b/include/iprt/utf16.h
@@ -445,7 +445,7 @@ RTDECL(int) RTUtf16ICmp(PCRTUTF16 pwsz1, PCRTUTF16 pwsz2);
 RTDECL(int) RTUtf16ICmpUtf8(PCRTUTF16 pwsz1, const char *psz2);
 
 /**
- * Performs a case insensitive string compare between an UTF-16 string and an
+ * Performs a case insensitive string compare between an UTF-16 string and a
  * pure ASCII string.
  *
  * Since this compare only takes cares about the first 128 codepoints in
@@ -476,6 +476,23 @@ RTDECL(int) RTUtf16ICmpAscii(PCRTUTF16 pwsz1, const char *psz2);
 RTDECL(int) RTUtf16LocaleICmp(PCRTUTF16 pwsz1, PCRTUTF16 pwsz2);
 
 /**
+ * Performs a case insensitive string compare between a UTF-16 string and a pure
+ * ASCII string, stopping after N characters.
+ *
+ * Since this compare only takes cares about the first 128 codepoints in
+ * unicode, no tables are needed and there aren't any real complications.
+ *
+ * @returns < 0 if the first string less than the second string.
+ * @returns 0 if the first string identical to the second string.
+ * @returns > 0 if the first string greater than the second string.
+ * @param   pwsz1       The UTF-16 first string. Null is allowed.
+ * @param   psz2        The pure ASCII second string. Null is allowed.
+ * @param   cwcMax      Maximum number of UTF-16 characters to compare.
+ */
+RTDECL(int) RTUtf16NICmpAscii(PCRTUTF16 pwsz1, const char *psz2, size_t cwcMax);
+
+
+/**
  * Folds a UTF-16 string to lowercase.
  *
  * This is a very simple folding; is uses the simple lowercase
diff --git a/include/iprt/x86.h b/include/iprt/x86.h
index 064be0b..81b03c8 100644
--- a/include/iprt/x86.h
+++ b/include/iprt/x86.h
@@ -3052,6 +3052,10 @@ typedef struct X86XSAVEAREA
        follows immediately. */
     union
     {
+        /** The high 128-bit AVX registers for easy access by IEM.
+         * @note This ASSUMES they will always be here...  */
+        X86XSAVEYMMHI       YmmHi;
+
         /** This is a typical layout on intel CPUs (good for debuggers). */
         struct
         {
diff --git a/src/VBox/Additions/Makefile.kmk b/src/VBox/Additions/Makefile.kmk
index abfc17d..49e8876 100644
--- a/src/VBox/Additions/Makefile.kmk
+++ b/src/VBox/Additions/Makefile.kmk
@@ -131,7 +131,7 @@ ifndef VBOX_ONLY_VALIDATIONKIT
  # The packing target rule, but only if we're on the local build box.
  # (VBOX_WITHOUT_ADDITIONS_ISO is used by the additions build box, see the root makefile.)
  ifndef VBOX_WITHOUT_ADDITIONS_ISO
-  PACKING += $(VBOX_PATH_ADDITIONS_ISO)/VBoxGuestAdditions.zip
+  PACKING += $(VBOX_PATH_ADDITIONS_ISO)/VBoxGuestAdditions.iso
  endif
 endif # !VBOX_ONLY_VALIDATIONKIT
 
@@ -333,11 +333,11 @@ $(VBOX_PATH_ADDITIONS_ISO)/VBoxGuestAdditions.iso: \
 $(VBOX_PATH_ADDITIONS_ISO)/VBoxGuestAdditions.zip: $(VBOX_PATH_ADDITIONS_ISO)/VBoxGuestAdditions.iso
 	$(call MSG_L1,Zipping image $@)
 	$(QUIET)$(RM) -f $@
-	$(QUIET)$(REDIRECT) -C $(VBOX_PATH_ADDITIONS_ISO) -- zip$(HOSTSUFF_EXE) -9 $@ $(notdir $^)
+	$(QUIET)$(REDIRECT) -C $(VBOX_PATH_ADDITIONS_ISO) -- $(VBOX_ZIP) -9 $@ $(notdir $^)
 
 # Alias for creating the iso.
 .PHONY: additions-iso
-additions-iso: $(VBOX_PATH_ADDITIONS_ISO)/VBoxGuestAdditions.zip
+additions-iso: $(VBOX_PATH_ADDITIONS_ISO)/VBoxGuestAdditions.iso
 
 endif
 
diff --git a/src/VBox/Additions/common/VBoxGuest/linux/Makefile b/src/VBox/Additions/common/VBoxGuest/linux/Makefile
index c3f8bb0..534526b 100644
--- a/src/VBox/Additions/common/VBoxGuest/linux/Makefile
+++ b/src/VBox/Additions/common/VBoxGuest/linux/Makefile
@@ -1,4 +1,4 @@
-# $Revision: 114568 $
+# $Revision: 115996 $
 ## @file
 # VirtualBox Guest Additions Module Makefile.
 #
@@ -100,6 +100,7 @@ MOD_OBJS += \
 	common/math/gcc/divdi3.o \
 	common/math/gcc/moddi3.o \
 	common/math/gcc/udivdi3.o \
+	common/math/gcc/udivmoddi4.o \
 	common/math/gcc/umoddi3.o \
 	common/math/gcc/qdivrem.o
 endif
diff --git a/src/VBox/Additions/common/VBoxGuest/linux/files_vboxguest b/src/VBox/Additions/common/VBoxGuest/linux/files_vboxguest
index bf8f502..121ea18 100755
--- a/src/VBox/Additions/common/VBoxGuest/linux/files_vboxguest
+++ b/src/VBox/Additions/common/VBoxGuest/linux/files_vboxguest
@@ -54,6 +54,7 @@ FILES_VBOXGUEST_NOBIN=" \
     ${PATH_ROOT}/include/iprt/time.h=>include/iprt/time.h \
     ${PATH_ROOT}/include/iprt/timer.h=>include/iprt/timer.h \
     ${PATH_ROOT}/include/iprt/types.h=>include/iprt/types.h \
+    ${PATH_ROOT}/include/iprt/uint64.h=>include/iprt/uint64.h \
     ${PATH_ROOT}/include/iprt/uni.h=>include/iprt/uni.h \
     ${PATH_ROOT}/include/iprt/utf16.h=>include/iprt/utf16.h \
     ${PATH_ROOT}/include/iprt/x86.h=>include/iprt/x86.h \
@@ -113,6 +114,7 @@ FILES_VBOXGUEST_NOBIN=" \
     ${PATH_ROOT}/src/VBox/Runtime/common/math/gcc/qdivrem.c=>common/math/gcc/qdivrem.c \
     ${PATH_ROOT}/src/VBox/Runtime/common/math/gcc/quad.h=>common/math/gcc/quad.h \
     ${PATH_ROOT}/src/VBox/Runtime/common/math/gcc/udivdi3.c=>common/math/gcc/udivdi3.c \
+    ${PATH_ROOT}/src/VBox/Runtime/common/math/gcc/udivmoddi4.c=>common/math/gcc/udivmoddi4.c \
     ${PATH_ROOT}/src/VBox/Runtime/common/math/gcc/umoddi3.c=>common/math/gcc/umoddi3.c \
     ${PATH_ROOT}/src/VBox/Runtime/common/misc/RTAssertMsg1Weak.cpp=>common/misc/RTAssertMsg1Weak.c \
     ${PATH_ROOT}/src/VBox/Runtime/common/misc/RTAssertMsg2.cpp=>common/misc/RTAssertMsg2.c \
diff --git a/src/VBox/Additions/common/VBoxService/VBoxServiceToolBox.cpp b/src/VBox/Additions/common/VBoxService/VBoxServiceToolBox.cpp
index 6f16050..5daa827 100644
--- a/src/VBox/Additions/common/VBoxService/VBoxServiceToolBox.cpp
+++ b/src/VBox/Additions/common/VBoxService/VBoxServiceToolBox.cpp
@@ -808,7 +808,7 @@ static int vgsvcToolboxLsHandleDir(const char *pszDir, uint32_t fFlags, uint32_t
                     case RTFS_TYPE_SYMLINK:
                         if (!(fFlags & VBOXSERVICETOOLBOXLSFLAG_SYMLINKS))
                             break;
-                        /* Fall through is intentional. */
+                        /* fall thru */
                     case RTFS_TYPE_DIRECTORY:
                     {
                         const char *pszName = pNodeIt->dirEntry.szName;
diff --git a/src/VBox/Additions/common/crOpenGL/DD_glc.py b/src/VBox/Additions/common/crOpenGL/DD_glc.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Additions/common/crOpenGL/DD_glh.py b/src/VBox/Additions/common/crOpenGL/DD_glh.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Additions/common/crOpenGL/Linux_i386_exports.py b/src/VBox/Additions/common/crOpenGL/Linux_i386_exports.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Additions/common/crOpenGL/Linux_i386_exports_dri.py b/src/VBox/Additions/common/crOpenGL/Linux_i386_exports_dri.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Additions/common/crOpenGL/NULLfuncs.py b/src/VBox/Additions/common/crOpenGL/NULLfuncs.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Additions/common/crOpenGL/cr_gl.py b/src/VBox/Additions/common/crOpenGL/cr_gl.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Additions/common/crOpenGL/defs.py b/src/VBox/Additions/common/crOpenGL/defs.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Additions/common/crOpenGL/defs64.py b/src/VBox/Additions/common/crOpenGL/defs64.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Additions/common/crOpenGL/entrypoints.py b/src/VBox/Additions/common/crOpenGL/entrypoints.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Additions/common/crOpenGL/feedback/feedback.py b/src/VBox/Additions/common/crOpenGL/feedback/feedback.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Additions/common/crOpenGL/feedback/feedback_funcs.py b/src/VBox/Additions/common/crOpenGL/feedback/feedback_funcs.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Additions/common/crOpenGL/feedback/feedback_state.py b/src/VBox/Additions/common/crOpenGL/feedback/feedback_state.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Additions/common/crOpenGL/feedback/feedbackspu_proto.py b/src/VBox/Additions/common/crOpenGL/feedback/feedbackspu_proto.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Additions/common/crOpenGL/getprocaddress.py b/src/VBox/Additions/common/crOpenGL/getprocaddress.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Additions/common/crOpenGL/pack/pack.py b/src/VBox/Additions/common/crOpenGL/pack/pack.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Additions/common/crOpenGL/pack/packspu_beginend.py b/src/VBox/Additions/common/crOpenGL/pack/packspu_beginend.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Additions/common/crOpenGL/pack/packspu_flush.py b/src/VBox/Additions/common/crOpenGL/pack/packspu_flush.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Additions/common/crOpenGL/pack/packspu_get.py b/src/VBox/Additions/common/crOpenGL/pack/packspu_get.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Additions/common/crOpenGL/pack/packspu_proto.py b/src/VBox/Additions/common/crOpenGL/pack/packspu_proto.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Additions/common/crOpenGL/passthrough/passthrough.py b/src/VBox/Additions/common/crOpenGL/passthrough/passthrough.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Additions/common/crOpenGL/stub_common.py b/src/VBox/Additions/common/crOpenGL/stub_common.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Additions/common/crOpenGL/tsfuncs.py b/src/VBox/Additions/common/crOpenGL/tsfuncs.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Additions/common/crOpenGL/windows_exports.py b/src/VBox/Additions/common/crOpenGL/windows_exports.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Additions/common/crOpenGL/windows_getprocaddress.py b/src/VBox/Additions/common/crOpenGL/windows_getprocaddress.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Additions/common/crOpenGL/windows_i386_exports.py b/src/VBox/Additions/common/crOpenGL/windows_i386_exports.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Additions/linux/drm/Makefile.module.kms b/src/VBox/Additions/linux/drm/Makefile.module.kms
index d9eb2ce..8c4a7d9 100644
--- a/src/VBox/Additions/linux/drm/Makefile.module.kms
+++ b/src/VBox/Additions/linux/drm/Makefile.module.kms
@@ -46,7 +46,10 @@ ifneq ($(wildcard $(KBUILD_EXTMOD)/vboxvideo),)
 else
  MANGLING := $(KBUILD_EXTMOD)/include/VBox/VBoxGuestMangling.h
 endif
-MOD_CFLAGS = -Wno-declaration-after-statement -fshort-wchar -include $(MANGLING) -fno-pie
+MOD_CFLAGS = -Wno-declaration-after-statement -fshort-wchar -fno-pie
+ifneq ($(KERN_VERSION),24)
+MOD_CFLAGS += -include $(MANGLING)
+endif
 MOD_INCL   = $(addprefix -I$(KBUILD_EXTMOD),/ /include)
 # What on earth is this?
 MOD_INCL  += $(addprefix -I$(KBUILD_EXTMOD)/vboxvideo,/ /include)
diff --git a/src/VBox/Additions/linux/drm/vbox_dummy.c b/src/VBox/Additions/linux/drm/vbox_dummy.c
index eae5d1d..6d449fc 100644
--- a/src/VBox/Additions/linux/drm/vbox_dummy.c
+++ b/src/VBox/Additions/linux/drm/vbox_dummy.c
@@ -16,6 +16,8 @@
  * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
  */
 
+#include <linux/errno.h>
+#include <linux/init.h>
 #include <linux/module.h>
 
 static int __init vbox_init(void)
diff --git a/src/VBox/Additions/linux/drm/vbox_ttm.c b/src/VBox/Additions/linux/drm/vbox_ttm.c
index 57dd087..83f8122 100644
--- a/src/VBox/Additions/linux/drm/vbox_ttm.c
+++ b/src/VBox/Additions/linux/drm/vbox_ttm.c
@@ -275,11 +275,17 @@ struct ttm_bo_driver vbox_bo_driver = {
     .ttm_tt_populate = vbox_ttm_tt_populate,
     .ttm_tt_unpopulate = vbox_ttm_tt_unpopulate,
     .init_mem_type = vbox_bo_init_mem_type,
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 10, 0)
+    .eviction_valuable = ttm_bo_eviction_valuable,
+#endif
     .evict_flags = vbox_bo_evict_flags,
     .move = vbox_bo_move,
     .verify_access = vbox_bo_verify_access,
     .io_mem_reserve = &vbox_ttm_io_mem_reserve,
     .io_mem_free = &vbox_ttm_io_mem_free,
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)
+    .io_mem_pfn = ttm_bo_default_io_mem_pfn,
+#endif
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0) && LINUX_VERSION_CODE < KERNEL_VERSION(4, 11, 0)
     .lru_tail = &ttm_bo_default_lru_tail,
     .swap_lru_tail = &ttm_bo_default_swap_lru_tail,
diff --git a/src/VBox/Additions/linux/installer/install.sh.in b/src/VBox/Additions/linux/installer/install.sh.in
index 6b19092..404df78 100755
--- a/src/VBox/Additions/linux/installer/install.sh.in
+++ b/src/VBox/Additions/linux/installer/install.sh.in
@@ -130,16 +130,23 @@ def_uninstall()
         done
     test "$found" = 0 && return 0
     if ! test "$1" = "force" ; then
+        # Try to make the promised notification appear on next start.
+        VBoxControl guestproperty delete \
+            /VirtualBox/GuestAdd/HostVerLastChecked 2>&1 > /dev/null
         cat 1>&2 << EOF
-You appear to have a version of the VirtualBox Guest Additions
-on your system which was installed from a different source or using a
-different type of installer.  If you installed it from a package from your
-Linux distribution or if it is a default part of the system then we strongly
-recommend that you cancel this installation and remove it properly before
-installing this version.  If this is simply an older or a damaged
-installation you may safely proceed.
-
-Do you wish to continue anyway? [yes or no]
+This system appears to have a version of the VirtualBox Guest Additions
+already installed.  If it is part of the operating system and kept up-to-date,
+there is most likely no need to replace it.  If it is not up-to-date, you
+should get a notification when you start the system.  If you wish to replace
+it with this version, please do not continue with this installation now, but
+instead remove the current version first, following the instructions for the
+operating system.
+
+If your system simply has the remains of a version of the Additions you could
+not remove you should probably continue now, and these will be removed during
+installation.
+
+Do you wish to continue? [yes or no]
 EOF
         read reply dummy
         if ! expr "$reply" : [yY] > /dev/null &&
@@ -435,9 +442,10 @@ if [ -n "${INSTALLATION_MODULES_LIST}" ]; then
   done
 fi
 
-# Install, set up and start init scripts
-for i in "$INSTALLATION_DIR/init/vboxadd" "$INSTALLATION_DIR/init/vboxadd-service" \
-    "$INSTALLATION_DIR/init/vboxadd-x11"; do
+# Install, set up and start init scripts.
+# Note: vboxadd-x11 must come first because it's called by vboxadd!
+for i in "$INSTALLATION_DIR/init/vboxadd-x11" \
+    "$INSTALLATION_DIR/init/vboxadd" "$INSTALLATION_DIR/init/vboxadd-service"; do
   if test -r "$i"; then
     install_init_script "$i" "`basename "$i"`" 2>> "${LOGFILE}"
     addrunlevel "`basename "$i"`" 2>> "${LOGFILE}"
diff --git a/src/VBox/Additions/linux/installer/vboxadd-x11.sh b/src/VBox/Additions/linux/installer/vboxadd-x11.sh
index 0364c74..09a6ff4 100755
--- a/src/VBox/Additions/linux/installer/vboxadd-x11.sh
+++ b/src/VBox/Additions/linux/installer/vboxadd-x11.sh
@@ -1,6 +1,6 @@
 #! /bin/sh
 #
-# Linux Additions X11 setup init script ($Revision: 111712 $)
+# Linux Additions X11 setup init script ($Revision: 116807 $)
 #
 
 #
@@ -65,6 +65,8 @@ x_version=`echo "$xver" | sed -n 's/^X Window System Version \([0-9.]\+\)/\1/p'`
 x_version_short=`echo "${x_version}" | sed 's/\([0-9]*\.[0-9]*\)\..*/\1/'`
 # Version of Redhat or Fedora installed.  Needed for setting up selinux policy.
 redhat_release=`cat /etc/redhat-release 2> /dev/null`
+# Version of OL installed.  Needed for blacklisting vboxvideo.
+oracle_release=`cat /etc/oracle-release 2> /dev/null`
 # All the different possible locations for XFree86/X.Org configuration files
 # - how many of these have ever been used?
 x11conf_files="/etc/X11/xorg.conf /etc/X11/xorg.conf-4 /etc/X11/.xorg.conf \
@@ -375,18 +377,24 @@ setup()
     esac
     case "${x_version}" in
     4.* | 6.* | 7.* | 1.?.* | 1.1[0-6].* )
-        echo "blacklist vboxvideo" > /etc/modprobe.d/blacklist-vboxvideo.conf
-        ;;
-    *)
-        if test -f /etc/modprobe.d/blacklist-vboxvideo.conf; then
-            rm -f /etc/modprobe.d/blacklist-vboxvideo.conf
-            # We do not want to load the driver if X.Org Server is already
-            # running, as without a driver the server will touch the hardware
-            # directly, causing problems.
-            ps -Af | grep -q '[X]org' || ${MODPROBE} vboxvideo
-        fi
+        blacklist_vboxvideo="yes"
         ;;
     esac
+    case "$oracle_release" in
+        Oracle*release\ 6.* )
+            # relevant for OL6/UEK4 but cannot hurt for other kernels
+            blacklist_vboxvideo="yes"
+    esac
+    if test -n "${blacklist_vboxvideo}"; then
+        echo "blacklist vboxvideo" > /etc/modprobe.d/blacklist-vboxvideo.conf
+    else
+        test -f /etc/modprobe.d/blacklist-vboxvideo.conf &&
+            rm -f /etc/modprobe.d/blacklist-vboxvideo.conf
+        # We do not want to load the driver if X.Org Server is already
+        # running, as without a driver the server will touch the hardware
+        # directly, causing problems.
+        ps -Af | grep -q '[X]org' || ${MODPROBE} vboxvideo
+    fi
     test -n "${dox11config}" &&
         begin "Installing $xserver_version modules"
     case "$vboxvideo_src" in
diff --git a/src/VBox/Additions/linux/installer/vboxadd.sh b/src/VBox/Additions/linux/installer/vboxadd.sh
index a5260cb..6ff1a2c 100755
--- a/src/VBox/Additions/linux/installer/vboxadd.sh
+++ b/src/VBox/Additions/linux/installer/vboxadd.sh
@@ -1,6 +1,6 @@
 #! /bin/sh
 #
-# Linux Additions kernel module init script ($Revision: 114649 $)
+# Linux Additions kernel module init script ($Revision: 116785 $)
 #
 
 #
@@ -15,6 +15,8 @@
 # hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
 #
 
+# X-Start-Before is a Debian Addition which we use when converting to
+# a systemd unit.  X-Service-Type is our own invention, also for systemd.
 
 # chkconfig: 345 10 90
 # description: VirtualBox Linux Additions kernel modules
@@ -25,6 +27,8 @@
 # Required-Stop:
 # Default-Start:  2 3 4 5
 # Default-Stop:   0 1 6
+# X-Start-Before: display-manager
+# X-Service-Type: oneshot
 # Description:    VirtualBox Linux Additions kernel modules
 ### END INIT INFO
 
@@ -238,20 +242,18 @@ start()
     # Install the guest OpenGL drivers.  For now we don't support
     # multi-architecture installations
     rm -f /etc/ld.so.conf.d/00vboxvideo.conf
+    rm -Rf /var/lib/VBoxGuestAdditions/lib
     if /usr/bin/VBoxClient --check3d 2>/dev/null; then
         mkdir -p /var/lib/VBoxGuestAdditions/lib
         ln -sf "${INSTALL_DIR}/lib/VBoxOGL.so" /var/lib/VBoxGuestAdditions/lib/libGL.so.1
-        ln -sf "${INSTALL_DIR}/lib/VBoxEGL.so" /var/lib/VBoxGuestAdditions/lib/libEGL.so.1
         # SELinux for the OpenGL libraries, so that gdm can load them during the
         # acceleration support check.  This prevents an "Oh no, something has gone
         # wrong!" error when starting EL7 guests.
         if test -e /etc/selinux/config; then
             if command -v semanage > /dev/null; then
                 semanage fcontext -a -t lib_t "/var/lib/VBoxGuestAdditions/lib/libGL.so.1"
-                semanage fcontext -a -t lib_t "/var/lib/VBoxGuestAdditions/lib/libEGL.so.1"
             fi
             chcon -h  -t lib_t "/var/lib/VBoxGuestAdditions/lib/libGL.so.1"
-            chcon -h  -t lib_t  "/var/lib/VBoxGuestAdditions/lib/libEGL.so.1"
         fi
         echo "/var/lib/VBoxGuestAdditions/lib" > /etc/ld.so.conf.d/00vboxvideo.conf
     fi
diff --git a/src/VBox/Additions/linux/sharedfolders/Makefile.module b/src/VBox/Additions/linux/sharedfolders/Makefile.module
index 97f2080..fddff28 100644
--- a/src/VBox/Additions/linux/sharedfolders/Makefile.module
+++ b/src/VBox/Additions/linux/sharedfolders/Makefile.module
@@ -38,6 +38,7 @@ MOD_OBJS  += \
 	divdi3.o \
 	moddi3.o \
 	udivdi3.o \
+	udivmoddi4.o \
 	umoddi3.o \
 	qdivrem.o
 endif
diff --git a/src/VBox/Additions/linux/sharedfolders/files_vboxsf b/src/VBox/Additions/linux/sharedfolders/files_vboxsf
index 072855a..2abc650 100755
--- a/src/VBox/Additions/linux/sharedfolders/files_vboxsf
+++ b/src/VBox/Additions/linux/sharedfolders/files_vboxsf
@@ -38,6 +38,7 @@ FILES_VBOXSF_NOBIN=" \
     ${PATH_ROOT}/include/iprt/string.h=>include/iprt/string.h \
     ${PATH_ROOT}/include/iprt/time.h=>include/iprt/time.h \
     ${PATH_ROOT}/include/iprt/types.h=>include/iprt/types.h \
+    ${PATH_ROOT}/include/iprt/uint64.h=>include/iprt/uint64.h \
     ${PATH_ROOT}/include/iprt/uni.h=>include/iprt/uni.h \
     ${PATH_ROOT}/include/iprt/utf16.h=>include/iprt/utf16.h \
     ${PATH_ROOT}/include/VBox/cdefs.h=>include/VBox/cdefs.h \
@@ -73,6 +74,7 @@ FILES_VBOXSF_NOBIN=" \
     ${PATH_ROOT}/src/VBox/Runtime/common/math/gcc/qdivrem.c=>qdivrem.c \
     ${PATH_ROOT}/src/VBox/Runtime/common/math/gcc/quad.h=>quad.h \
     ${PATH_ROOT}/src/VBox/Runtime/common/math/gcc/udivdi3.c=>udivdi3.c \
+    ${PATH_ROOT}/src/VBox/Runtime/common/math/gcc/udivmoddi4.c=>udivmoddi4.c \
     ${PATH_ROOT}/src/VBox/Runtime/common/math/gcc/umoddi3.c=>umoddi3.c \
     ${PATH_ROOT}/src/VBox/Runtime/r0drv/linux/the-linux-kernel.h=>r0drv/linux/the-linux-kernel.h \
     ${PATH_ROOT}/src/VBox/Additions/linux/sharedfolders/Makefile.module=>Makefile \
diff --git a/src/VBox/Additions/linux/sharedfolders/mount.vboxsf.c b/src/VBox/Additions/linux/sharedfolders/mount.vboxsf.c
index 29453cc..4c900df 100644
--- a/src/VBox/Additions/linux/sharedfolders/mount.vboxsf.c
+++ b/src/VBox/Additions/linux/sharedfolders/mount.vboxsf.c
@@ -414,6 +414,7 @@ main(int argc, char **argv)
         {
             default:
                 fprintf(stderr, "unknown option `%c:%#x'\n", c, c);
+                /* fall thru */
             case '?':
             case 'h':
                 return usage(argv[0]);
@@ -424,6 +425,7 @@ main(int argc, char **argv)
 
             case 'w':
                 opts.ronly = 0;
+                break;
 
             case 's':
                 opts.sloppy = 1;
diff --git a/src/VBox/Additions/linux/sharedfolders/vfsmod.c b/src/VBox/Additions/linux/sharedfolders/vfsmod.c
index 9bf9627..d66bf80 100644
--- a/src/VBox/Additions/linux/sharedfolders/vfsmod.c
+++ b/src/VBox/Additions/linux/sharedfolders/vfsmod.c
@@ -129,6 +129,7 @@ static int sf_glob_alloc(struct vbsf_mount_info_new *info, struct sf_glob_info *
             {
                 err = -EINVAL;
                 LogFunc(("failed to load nls %s\n", info->nls_name));
+                kfree(str_name);
                 goto fail1;
             }
         }
diff --git a/src/VBox/Additions/x11/VBoxClient/draganddrop.cpp b/src/VBox/Additions/x11/VBoxClient/draganddrop.cpp
index 3c03ffa..9b4fcd4 100644
--- a/src/VBox/Additions/x11/VBoxClient/draganddrop.cpp
+++ b/src/VBox/Additions/x11/VBoxClient/draganddrop.cpp
@@ -3109,6 +3109,7 @@ int DragAndDropService::run(bool fDaemonised /* = false */)
                         }
                         /* Not breaking unconditionally is intentional. See comment above. */
                     }
+                    /* fall thru */
                     case DragAndDropSvc::HOST_DND_HG_EVT_MOVE:
                     {
                         rc = m_pCurDnD->hgMove(e.hgcm.u.a.uXpos, e.hgcm.u.a.uYpos, e.hgcm.u.a.uDefAction);
diff --git a/src/VBox/Additions/x11/VBoxClient/seamless.cpp b/src/VBox/Additions/x11/VBoxClient/seamless.cpp
index bb6209c..c93504e 100644
--- a/src/VBox/Additions/x11/VBoxClient/seamless.cpp
+++ b/src/VBox/Additions/x11/VBoxClient/seamless.cpp
@@ -252,29 +252,6 @@ int SeamlessMain::stopX11MonitorThread(void)
     return rc;
 }
 
-/** @todo Expand this? */
-int SeamlessMain::selfTest()
-{
-    int rc = VERR_INTERNAL_ERROR;
-    const char *pcszStage;
-
-    LogRelFlowFunc(("\n"));
-    do {
-        pcszStage = "Testing event loop cancellation";
-        VbglR3InterruptEventWaits();
-        if (RT_FAILURE(VbglR3WaitEvent(VMMDEV_EVENT_VALID_EVENT_MASK, 0, NULL)))
-            break;
-        if (   VbglR3WaitEvent(VMMDEV_EVENT_VALID_EVENT_MASK, 0, NULL)
-            != VERR_TIMEOUT)
-            break;
-        rc = VINF_SUCCESS;
-    } while(0);
-    if (RT_FAILURE(rc))
-        LogRel(("VBoxClient (seamless): self test failed.  Stage: \"%s\"\n",
-                pcszStage));
-    return rc;
-}
-
 /** Service magic number, start of a UUID. */
 #define SEAMLESSSERVICE_MAGIC 0xd28ba727
 
@@ -321,12 +298,6 @@ static int init(struct VBCLSERVICE **ppInterface)
     rc = pSelf->mSeamless.init();
     if (RT_FAILURE(rc))
         return rc;
-    rc = pSelf->mSeamless.selfTest();
-    if (RT_FAILURE(rc))
-    {
-        pSelf->mSeamless.stop();
-        return rc;
-    }
     pSelf->mIsInitialised = true;
     return VINF_SUCCESS;
 }
diff --git a/src/VBox/Additions/x11/VBoxClient/testcase/tstSeamlessX11.cpp b/src/VBox/Additions/x11/VBoxClient/testcase/tstSeamlessX11.cpp
index a7a922a..7db4067 100644
--- a/src/VBox/Additions/x11/VBoxClient/testcase/tstSeamlessX11.cpp
+++ b/src/VBox/Additions/x11/VBoxClient/testcase/tstSeamlessX11.cpp
@@ -79,16 +79,6 @@ int VbglR3SeamlessWaitEvent(VMMDevSeamlessMode *pMode)
     return rc;
 }
 
-int VbglR3WaitEvent(uint32_t , uint32_t cMillies, uint32_t *)
-{
-    return RTSemEventWait(eventSem, cMillies);
-}
-
-int VbglR3InterruptEventWaits(void)
-{
-    return RTSemEventSignal(eventSem);
-}
-
 VBGLR3DECL(int)     VbglR3InitUser(void) { return VINF_SUCCESS; }
 VBGLR3DECL(void)    VbglR3Term(void) {}
 
diff --git a/src/VBox/Debugger/DBGCEmulateCodeView.cpp b/src/VBox/Debugger/DBGCEmulateCodeView.cpp
index e3c89f1..cb0d0f8 100644
--- a/src/VBox/Debugger/DBGCEmulateCodeView.cpp
+++ b/src/VBox/Debugger/DBGCEmulateCodeView.cpp
@@ -1258,6 +1258,7 @@ static DECLCALLBACK(int) dbgcCmdUnassemble(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp,
             break;
         case DBGCVAR_TYPE_GC_PHYS:
             hDbgAs = DBGF_AS_PHYS;
+            /* fall thru */
         case DBGCVAR_TYPE_HC_FLAT:
         case DBGCVAR_TYPE_HC_PHYS:
         {
diff --git a/src/VBox/Debugger/DBGCOps.cpp b/src/VBox/Debugger/DBGCOps.cpp
index 83b3b68..3aa18ae 100644
--- a/src/VBox/Debugger/DBGCOps.cpp
+++ b/src/VBox/Debugger/DBGCOps.cpp
@@ -225,8 +225,8 @@ static int dbgcOpHelperGetNumber(PDBGC pDbgc, PCDBGCVAR pArg, uint64_t *pu64Ret)
             int rc = dbgcSymbolGet(pDbgc, Var.u.pszString, DBGCVAR_TYPE_NUMBER, &Var);
             if (RT_FAILURE(rc))
                 return rc;
-            /* fall thru */
         }
+        /* fall thru */
         case DBGCVAR_TYPE_STRING:
         default:
             return VERR_DBGC_PARSE_INCORRECT_ARG_TYPE;
@@ -469,6 +469,14 @@ DECLCALLBACK(int) dbgcOpRegister(PDBGC pDbgc, PCDBGCVAR pArg, DBGCVARCAT enmCat,
                 DBGCVAR_INIT_NUMBER(pResult, Value.u128.s.Lo);
                 return VINF_SUCCESS;
 
+            case DBGFREGVALTYPE_U256:
+                DBGCVAR_INIT_NUMBER(pResult, Value.u256.QWords.qw0);
+                return VINF_SUCCESS;
+
+            case DBGFREGVALTYPE_U512:
+                DBGCVAR_INIT_NUMBER(pResult, Value.u512.QWords.qw0);
+                return VINF_SUCCESS;
+
             case DBGFREGVALTYPE_R80:
 #ifdef RT_COMPILER_WITH_80BIT_LONG_DOUBLE
                 DBGCVAR_INIT_NUMBER(pResult, (uint64_t)Value.r80Ex.lrd);
@@ -806,6 +814,7 @@ static DECLCALLBACK(int) dbgcOpAdd(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2
                     rc = dbgcSymbolGet(pDbgc, pArg2->u.pszString, DBGCVAR_TYPE_NUMBER, &Var);
                     if (RT_FAILURE(rc))
                         return rc;
+                    /* fall thru */
                 case DBGCVAR_TYPE_NUMBER:
                     pResult->u.u64Number += pArg2->u.u64Number;
                     break;
@@ -1025,6 +1034,7 @@ static DECLCALLBACK(int) dbgcOpSub(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2
                     rc = dbgcSymbolGet(pDbgc, pArg2->u.pszString, DBGCVAR_TYPE_NUMBER, &Var);
                     if (RT_FAILURE(rc))
                         return rc;
+                    /* fall thru */
                 case DBGCVAR_TYPE_NUMBER:
                     pResult->u.u64Number -= pArg2->u.u64Number;
                     break;
diff --git a/src/VBox/Debugger/DBGConsole.cpp b/src/VBox/Debugger/DBGConsole.cpp
index 28aad47..a1c7307 100644
--- a/src/VBox/Debugger/DBGConsole.cpp
+++ b/src/VBox/Debugger/DBGConsole.cpp
@@ -704,7 +704,14 @@ static int dbgcProcessEvent(PDBGC pDbgc, PCDBGFEVENT pEvent)
                     break;
             }
             if (RT_SUCCESS(rc) && DBGFR3IsHalted(pDbgc->pUVM))
+            {
                 rc = pDbgc->CmdHlp.pfnExec(&pDbgc->CmdHlp, "r");
+
+                /* Set the resume flag to ignore the breakpoint when resuming execution. */
+                if (   RT_SUCCESS(rc)
+                    && pEvent->enmType == DBGFEVENT_BREAKPOINT)
+                    rc = pDbgc->CmdHlp.pfnExec(&pDbgc->CmdHlp, "r eflags.rf = 1");
+            }
             else
                 pDbgc->fRegCtxGuest = fRegCtxGuest;
             break;
diff --git a/src/VBox/Debugger/DBGPlugInLinux.cpp b/src/VBox/Debugger/DBGPlugInLinux.cpp
index 79a4ecf..db01940 100644
--- a/src/VBox/Debugger/DBGPlugInLinux.cpp
+++ b/src/VBox/Debugger/DBGPlugInLinux.cpp
@@ -95,6 +95,12 @@ typedef struct DBGDIGGERLINUX
     bool fValid;
     /** Set if 64-bit, clear if 32-bit.  */
     bool f64Bit;
+    /** Set if the kallsyms table uses relative addressing, clear
+     * if absolute addresses are used. */
+    bool fRelKrnlAddr;
+    /** The relative base when kernel symbols use offsets rather than
+     * absolute addresses. */
+    RTGCUINTPTR uKernelRelativeBase;
 
     /** The address of the linux banner.
      * This is set during probing. */
@@ -213,6 +219,36 @@ static uint64_t g_au64LnxKernelAddresses[] =
 static const uint8_t g_abLinuxVersion[] = "Linux version ";
 
 /**
+ * Converts a given offset into an absolute address if relative kernel offsets are used for
+ * kallsyms.
+ *
+ * @returns The absolute kernel address.
+ * @param   pThis               The Linux digger data.
+ * @param   uOffset             The offset to convert.
+ */
+DECLINLINE(RTGCUINTPTR) dbgDiggerLinuxConvOffsetToAddr(PDBGDIGGERLINUX pThis, int32_t uOffset)
+{
+    RTGCUINTPTR uAddr;
+
+    /*
+     * How the absolute address is calculated from the offset depends on the
+     * CONFIG_KALLSYMS_ABSOLUTE_PERCPU config which is only set for 64bit
+     * SMP kernels (we assume that all 64bit kernels always have SMP enabled too).
+     */
+    if (pThis->f64Bit)
+    {
+        if (uOffset >= 0)
+            uAddr = uOffset;
+        else
+            uAddr = pThis->uKernelRelativeBase - 1 - uOffset;
+    }
+    else
+        uAddr = pThis->uKernelRelativeBase + (uint32_t)uOffset;
+
+    return uAddr;
+}
+
+/**
  * Disassembles a simple getter returning the value for it.
  *
  * @returns VBox status code.
@@ -1137,7 +1173,19 @@ static int dbgDiggerLinuxFoundStartOfNames(PDBGDIGGERLINUX pThis, PCDBGFADDRESS
     pThis->cKernelSymbols = cKernelSymbols;
     pThis->AddrKernelNames = *pAddrKernelNames;
     pThis->AddrKernelAddresses = *pAddrKernelNames;
-    DBGFR3AddrSub(&pThis->AddrKernelAddresses, (cKernelSymbols + 1) * cbAddress);
+    uint32_t cbSymbolsSkip = (pThis->fRelKrnlAddr ? 2 : 1) * cbAddress; /* Relative addressing introduces kallsyms_relative_base. */
+    uint32_t cbOffsets = pThis->fRelKrnlAddr ? sizeof(int32_t) : cbAddress; /* Offsets are always 32bits wide for relative addressing. */
+    uint32_t cbAlign = 0;
+
+    /*
+     * If the number of symbols is odd there is padding to align the following guest pointer
+     * sized data properly on 64bit systems with relative addressing.
+     */
+    if (   pThis->fRelKrnlAddr
+        && pThis->f64Bit
+        && (pThis->cKernelSymbols & 1))
+        cbAlign = sizeof(int32_t);
+    DBGFR3AddrSub(&pThis->AddrKernelAddresses, cKernelSymbols * cbOffsets + cbSymbolsSkip + cbAlign);
 
     Log(("dbgDiggerLinuxFoundStartOfNames: AddrKernelAddresses=%RGv\n"
          "dbgDiggerLinuxFoundStartOfNames: cKernelSymbols=%#x (at %RGv)\n"
@@ -1186,22 +1234,47 @@ static int dbgDiggerLinuxFindStartOfNamesAndSymbolCount(PUVM pUVM, PDBGDIGGERLIN
             return rc;
 
         /*
-         * We assume that the three symbols are aligned on guest pointer boundrary.
+         * Since Linux 4.6 there are two different methods to store the kallsyms addresses
+         * in the image.
+         *
+         * The first and longer existing method is to store the absolute addresses in an
+         * array starting at kallsyms_addresses followed by a field which stores the number
+         * of kernel symbols called kallsyms_num_syms.
+         * The newer method is to use offsets stored in kallsyms_offsets and have a base pointer
+         * to relate the offsets to called kallsyms_relative_base. One entry in kallsyms_offsets is
+         * always 32bit wide regardless of the guest pointer size (this halves the table on 64bit
+         * systems) but means more work for us for the 64bit case.
+         *
+         * When absolute addresses are used the following assumptions hold:
+         *
+         *     We assume that the three symbols are aligned on guest pointer boundary.
          *
-         * The boundrary between the two tables should be noticable as the number
-         * is unlikely to be more than 16 millions, there will be at least one zero
-         * byte where it is, 64-bit will have 5 zero bytes.  Zero bytes aren't all
-         * that common in the kallsyms_names table.
+         *     The boundary between the two tables should be noticable as the number
+         *     is unlikely to be more than 16 millions, there will be at least one zero
+         *     byte where it is, 64-bit will have 5 zero bytes.  Zero bytes aren't all
+         *     that common in the kallsyms_names table.
          *
-         * Also the kallsyms_names table starts with a length byte, which means
-         * we're likely to see a byte in the range 1..31.
+         *     Also the kallsyms_names table starts with a length byte, which means
+         *     we're likely to see a byte in the range 1..31.
          *
-         * The kallsyms_addresses are mostly sorted (except for the start where the
-         * absolute symbols are), so we'll spot a bunch of kernel addresses
-         * immediately preceeding the kallsyms_num_syms field.
+         *     The kallsyms_addresses are mostly sorted (except for the start where the
+         *     absolute symbols are), so we'll spot a bunch of kernel addresses
+         *     immediately preceeding the kallsyms_num_syms field.
          *
-         * Lazy bird: If kallsyms_num_syms is on a buffer boundrary, we skip
-         *            the check for kernel addresses preceeding it.
+         *     Lazy bird: If kallsyms_num_syms is on a buffer boundrary, we skip
+         *                the check for kernel addresses preceeding it.
+         *
+         * For relative offsets most of the assumptions from above are true too
+         * except that we have to distinguish between the relative base address and the offsets.
+         * Every observed kernel has a valid kernel address fo the relative base and kallsyms_relative_base
+         * always comes before kallsyms_num_syms and is aligned on a guest pointer boundary.
+         * Offsets are stored before kallsyms_relative_base and don't contain valid kernel addresses.
+         *
+         * To distinguish between absolute and relative offsetting we check the data before a candidate
+         * for kallsyms_num_syms. If all entries before the kallsyms_num_syms candidate are valid kernel
+         * addresses absolute addresses are assumed. If this is not the case but the first entry before
+         * kallsyms_num_syms is a valid kernel address we check whether the data before and the possible
+         * relative base form a valid kernel address and assume relative offsets.
          */
         if (pThis->f64Bit)
         {
@@ -1214,6 +1287,34 @@ static int dbgDiggerLinuxFindStartOfNamesAndSymbolCount(PUVM pUVM, PDBGDIGGERLIN
                     if (   pb[0] <= LNX_MAX_KALLSYMS_ENC_LENGTH
                         && pb[0] >= LNX_MIN_KALLSYMS_ENC_LENGTH)
                     {
+                        /*
+                         * Check whether we have a valid kernel address and try to distinguish
+                         * whether the kernel uses relative offsetting or absolute addresses.
+                         */
+                        if (   (i >= 1 && LNX64_VALID_ADDRESS(uBuf.au64[i - 1]))
+                            && (i >= 2 && !LNX64_VALID_ADDRESS(uBuf.au64[i - 2]))
+                            && (i >= 3 && !LNX64_VALID_ADDRESS(uBuf.au64[i - 3])))
+                        {
+                            RTGCUINTPTR uKrnlRelBase = uBuf.au64[i - 1];
+                            DBGFADDRESS RelAddr = CurAddr;
+                            int32_t aiRelOff[3];
+                            rc = DBGFR3MemRead(pUVM, 0 /*idCpu*/, DBGFR3AddrAdd(&RelAddr, (i - 1) * sizeof(uint64_t) - sizeof(aiRelOff)),
+                                               &aiRelOff[0], sizeof(aiRelOff));
+                            if (   RT_SUCCESS(rc)
+                                && LNX64_VALID_ADDRESS(uKrnlRelBase + aiRelOff[0])
+                                && LNX64_VALID_ADDRESS(uKrnlRelBase + aiRelOff[1])
+                                && LNX64_VALID_ADDRESS(uKrnlRelBase + aiRelOff[2]))
+                            {
+                                Log(("dbgDiggerLinuxFindStartOfNamesAndSymbolCount: relative base %RGv (at %RGv)\n",
+                                     uKrnlRelBase, CurAddr.FlatPtr + (i - 1) * sizeof(uint64_t)));
+                                pThis->fRelKrnlAddr = true;
+                                pThis->uKernelRelativeBase = uKrnlRelBase;
+                                return dbgDiggerLinuxFoundStartOfNames(pThis,
+                                                                       DBGFR3AddrAdd(&CurAddr, (i + 1) * sizeof(uint64_t)),
+                                                                       (uint32_t)uBuf.au64[i], sizeof(uint64_t));
+                            }
+                        }
+
                         if (   (i <= 0 || LNX64_VALID_ADDRESS(uBuf.au64[i - 1]))
                             && (i <= 1 || LNX64_VALID_ADDRESS(uBuf.au64[i - 2]))
                             && (i <= 2 || LNX64_VALID_ADDRESS(uBuf.au64[i - 3])))
@@ -1234,6 +1335,23 @@ static int dbgDiggerLinuxFindStartOfNamesAndSymbolCount(PUVM pUVM, PDBGDIGGERLIN
                     if (   pb[0] <= LNX_MAX_KALLSYMS_ENC_LENGTH
                         && pb[0] >= LNX_MIN_KALLSYMS_ENC_LENGTH)
                     {
+                        /* Check for relative base addressing. */
+                        if (i >= 1 && LNX32_VALID_ADDRESS(uBuf.au32[i - 1]))
+                        {
+                            RTGCUINTPTR uKrnlRelBase = uBuf.au32[i - 1];
+                            if (   (i <= 1 || LNX32_VALID_ADDRESS(uKrnlRelBase + uBuf.au32[i - 2]))
+                                && (i <= 2 || LNX32_VALID_ADDRESS(uKrnlRelBase + uBuf.au32[i - 3])))
+                            {
+                                Log(("dbgDiggerLinuxFindStartOfNamesAndSymbolCount: relative base %RGv (at %RGv)\n",
+                                     uKrnlRelBase, CurAddr.FlatPtr + (i - 1) * sizeof(uint32_t)));
+                                pThis->fRelKrnlAddr = true;
+                                pThis->uKernelRelativeBase = uKrnlRelBase;
+                                return dbgDiggerLinuxFoundStartOfNames(pThis,
+                                                                       DBGFR3AddrAdd(&CurAddr, (i + 1) * sizeof(uint32_t)),
+                                                                       uBuf.au32[i], sizeof(uint32_t));
+                            }
+                        }
+
                         if (   (i <= 0 || LNX32_VALID_ADDRESS(uBuf.au32[i - 1]))
                             && (i <= 1 || LNX32_VALID_ADDRESS(uBuf.au32[i - 2]))
                             && (i <= 2 || LNX32_VALID_ADDRESS(uBuf.au32[i - 3])))
@@ -1467,205 +1585,315 @@ static int dbgDiggerLinuxFindTokenIndex(PUVM pUVM, PDBGDIGGERLINUX pThis)
 
 
 /**
- * Loads the kernel symbols from the kallsyms tables.
+ * Loads the kernel symbols from the given kallsyms offset table decoding the symbol names
+ * (worker common for dbgDiggerLinuxLoadKernelSymbolsAbsolute() and dbgDiggerLinuxLoadKernelSymbolsRelative()).
  *
  * @returns VBox status code.
  * @param   pUVM                The user mode VM handle.
  * @param   pThis               The Linux digger data.
+ * @param   uKernelStart        Flat kernel start address.
+ * @param   cbKernel            Size of the kernel in bytes.
+ * @param   pauSymOff           Pointer to the array of symbol offsets in the kallsyms table
+ *                              relative to the start of the kernel.
  */
-static int dbgDiggerLinuxLoadKernelSymbols(PUVM pUVM, PDBGDIGGERLINUX pThis)
+static int dbgDiggerLinuxLoadKernelSymbolsWorker(PUVM pUVM, PDBGDIGGERLINUX pThis, RTGCUINTPTR uKernelStart,
+                                                 RTGCUINTPTR cbKernel, RTGCUINTPTR *pauSymOff)
 {
-    /*
-     * Allocate memory for temporary table copies, reading the tables as we go.
-     */
-    uint32_t const cbGuestAddr = pThis->f64Bit ? sizeof(uint64_t) : sizeof(uint32_t);
-    void *pvAddresses = RTMemAllocZ(pThis->cKernelSymbols * cbGuestAddr);
-    int rc = DBGFR3MemRead(pUVM, 0 /*idCpu*/, &pThis->AddrKernelAddresses, pvAddresses, pThis->cKernelSymbols * cbGuestAddr);
+    uint8_t *pbNames = (uint8_t *)RTMemAllocZ(pThis->cbKernelNames);
+    int rc = DBGFR3MemRead(pUVM, 0 /*idCpu*/, &pThis->AddrKernelNames, pbNames, pThis->cbKernelNames);
     if (RT_SUCCESS(rc))
     {
-        uint8_t *pbNames = (uint8_t *)RTMemAllocZ(pThis->cbKernelNames);
-        rc = DBGFR3MemRead(pUVM, 0 /*idCpu*/, &pThis->AddrKernelNames, pbNames, pThis->cbKernelNames);
+        char *pszzTokens = (char *)RTMemAllocZ(pThis->cbKernelTokenTable);
+        rc = DBGFR3MemRead(pUVM, 0 /*idCpu*/, &pThis->AddrKernelTokenTable, pszzTokens, pThis->cbKernelTokenTable);
         if (RT_SUCCESS(rc))
         {
-            char *pszzTokens = (char *)RTMemAllocZ(pThis->cbKernelTokenTable);
-            rc = DBGFR3MemRead(pUVM, 0 /*idCpu*/, &pThis->AddrKernelTokenTable, pszzTokens, pThis->cbKernelTokenTable);
+            uint16_t *paoffTokens = (uint16_t *)RTMemAllocZ(256 * sizeof(uint16_t));
+            rc = DBGFR3MemRead(pUVM, 0 /*idCpu*/, &pThis->AddrKernelTokenIndex, paoffTokens, 256 * sizeof(uint16_t));
             if (RT_SUCCESS(rc))
             {
-                uint16_t *paoffTokens = (uint16_t *)RTMemAllocZ(256 * sizeof(uint16_t));
-                rc = DBGFR3MemRead(pUVM, 0 /*idCpu*/, &pThis->AddrKernelTokenIndex, paoffTokens, 256 * sizeof(uint16_t));
+                /*
+                 * Create a module for the kernel.
+                 */
+                RTDBGMOD hMod;
+                rc = RTDbgModCreate(&hMod, "vmlinux", cbKernel, 0 /*fFlags*/);
                 if (RT_SUCCESS(rc))
                 {
-                    /*
-                     * Figure out the kernel start and end.
-                     */
-                    RTGCUINTPTR uKernelStart = pThis->AddrKernelAddresses.FlatPtr;
-                    RTGCUINTPTR uKernelEnd   = pThis->AddrKernelTokenIndex.FlatPtr + 256 * sizeof(uint16_t);
-                    uint32_t    i;
-                    if (cbGuestAddr == sizeof(uint64_t))
-                    {
-                        uint64_t *pauAddrs = (uint64_t *)pvAddresses;
-                        for (i = 0; i < pThis->cKernelSymbols; i++)
-                            if (   pauAddrs[i] < uKernelStart
-                                && LNX64_VALID_ADDRESS(pauAddrs[i])
-                                && uKernelStart - pauAddrs[i] < LNX_MAX_KERNEL_SIZE)
-                                uKernelStart = pauAddrs[i];
-
-                        for (i = pThis->cKernelSymbols - 1; i > 0; i--)
-                            if (   pauAddrs[i] > uKernelEnd
-                                && LNX64_VALID_ADDRESS(pauAddrs[i])
-                                && pauAddrs[i] - uKernelEnd < LNX_MAX_KERNEL_SIZE)
-                                uKernelEnd = pauAddrs[i];
-                    }
-                    else
-                    {
-                        uint32_t *pauAddrs = (uint32_t *)pvAddresses;
-                        for (i = 0; i < pThis->cKernelSymbols; i++)
-                            if (   pauAddrs[i] < uKernelStart
-                                && LNX32_VALID_ADDRESS(pauAddrs[i])
-                                && uKernelStart - pauAddrs[i] < LNX_MAX_KERNEL_SIZE)
-                                uKernelStart = pauAddrs[i];
-
-                        for (i = pThis->cKernelSymbols - 1; i > 0; i--)
-                            if (   pauAddrs[i] > uKernelEnd
-                                && LNX32_VALID_ADDRESS(pauAddrs[i])
-                                && pauAddrs[i] - uKernelEnd < LNX_MAX_KERNEL_SIZE)
-                                uKernelEnd = pauAddrs[i];
-                    }
-
-                    RTGCUINTPTR cbKernel = uKernelEnd - uKernelStart;
-                    pThis->cbKernel = (uint32_t)cbKernel;
-                    DBGFR3AddrFromFlat(pUVM, &pThis->AddrKernelBase, uKernelStart);
-                    Log(("dbgDiggerLinuxLoadKernelSymbols: uKernelStart=%RGv cbKernel=%#x\n", uKernelStart, cbKernel));
+                    rc = RTDbgModSetTag(hMod, DIG_LNX_MOD_TAG); AssertRC(rc);
+                    rc = VINF_SUCCESS;
 
                     /*
-                     * Create a module for the kernel.
+                     * Enumerate the symbols.
                      */
-                    RTDBGMOD hMod;
-                    rc = RTDbgModCreate(&hMod, "vmlinux", cbKernel, 0 /*fFlags*/);
-                    if (RT_SUCCESS(rc))
+                    uint32_t        offName   = 0;
+                    uint32_t        cLeft = pThis->cKernelSymbols;
+                    while (cLeft-- > 0 && RT_SUCCESS(rc))
                     {
-                        rc = RTDbgModSetTag(hMod, DIG_LNX_MOD_TAG); AssertRC(rc);
-                        rc = VINF_SUCCESS;
-
-                        /*
-                         * Enumerate the symbols.
-                         */
-                        uint8_t const  *pbCurAddr = (uint8_t const *)pvAddresses;
-                        uint32_t        offName   = 0;
-                        uint32_t        cLeft = pThis->cKernelSymbols;
-                        while (cLeft-- > 0 && RT_SUCCESS(rc))
+                        /* Decode the symbol name first. */
+                        if (RT_LIKELY(offName < pThis->cbKernelNames))
                         {
-                            /* Decode the symbol name first. */
-                            if (RT_LIKELY(offName < pThis->cbKernelNames))
+                            uint8_t cbName = pbNames[offName++];
+                            if (RT_LIKELY(offName + cbName <= pThis->cbKernelNames))
                             {
-                                uint8_t cbName = pbNames[offName++];
-                                if (RT_LIKELY(offName + cbName <= pThis->cbKernelNames))
+                                char     szSymbol[4096];
+                                uint32_t offSymbol = 0;
+                                while (cbName-- > 0)
                                 {
-                                    char     szSymbol[4096];
-                                    uint32_t offSymbol = 0;
-                                    while (cbName-- > 0)
+                                    uint8_t  bEnc     = pbNames[offName++];
+                                    uint16_t offToken = paoffTokens[bEnc];
+                                    if (RT_LIKELY(offToken < pThis->cbKernelTokenTable))
                                     {
-                                        uint8_t  bEnc     = pbNames[offName++];
-                                        uint16_t offToken = paoffTokens[bEnc];
-                                        if (RT_LIKELY(offToken < pThis->cbKernelTokenTable))
-                                        {
-                                            const char *pszToken = &pszzTokens[offToken];
-                                            char ch;
-                                            while ((ch = *pszToken++) != '\0')
-                                                if (offSymbol < sizeof(szSymbol) - 1)
-                                                    szSymbol[offSymbol++] = ch;
-                                        }
-                                        else
-                                        {
-                                            rc = VERR_INVALID_UTF8_ENCODING;
-                                            break;
-                                        }
+                                        const char *pszToken = &pszzTokens[offToken];
+                                        char ch;
+                                        while ((ch = *pszToken++) != '\0')
+                                            if (offSymbol < sizeof(szSymbol) - 1)
+                                                szSymbol[offSymbol++] = ch;
                                     }
-                                    szSymbol[offSymbol < sizeof(szSymbol) ? offSymbol : sizeof(szSymbol) - 1] = '\0';
+                                    else
+                                    {
+                                        rc = VERR_INVALID_UTF8_ENCODING;
+                                        break;
+                                    }
+                                }
+                                szSymbol[offSymbol < sizeof(szSymbol) ? offSymbol : sizeof(szSymbol) - 1] = '\0';
 
-                                    /* The address. */
-                                    RTGCUINTPTR uSymAddr = cbGuestAddr == sizeof(uint64_t)
-                                                         ? *(uint64_t *)pbCurAddr : *(uint32_t *)pbCurAddr;
-                                    pbCurAddr += cbGuestAddr;
+                                /* The offset. */
+                                RTGCUINTPTR uSymOff = *pauSymOff;
+                                pauSymOff++;
 
-                                    /* Add it without the type char. */
-                                    if (uSymAddr - uKernelStart <= cbKernel)
+                                /* Add it without the type char. */
+                                if (uSymOff <= cbKernel)
+                                {
+                                    rc = RTDbgModSymbolAdd(hMod, &szSymbol[1], RTDBGSEGIDX_RVA, uSymOff,
+                                                           0 /*cb*/, 0 /*fFlags*/, NULL);
+                                    if (RT_FAILURE(rc))
                                     {
-                                        rc = RTDbgModSymbolAdd(hMod, &szSymbol[1], RTDBGSEGIDX_RVA, uSymAddr - uKernelStart,
-                                                               0 /*cb*/, 0 /*fFlags*/, NULL);
-                                        if (RT_FAILURE(rc))
+                                        if (   rc == VERR_DBG_SYMBOL_NAME_OUT_OF_RANGE
+                                            || rc == VERR_DBG_INVALID_RVA
+                                            || rc == VERR_DBG_ADDRESS_CONFLICT
+                                            || rc == VERR_DBG_DUPLICATE_SYMBOL)
                                         {
-                                            if (   rc == VERR_DBG_SYMBOL_NAME_OUT_OF_RANGE
-                                                || rc == VERR_DBG_INVALID_RVA
-                                                || rc == VERR_DBG_ADDRESS_CONFLICT
-                                                || rc == VERR_DBG_DUPLICATE_SYMBOL)
-                                            {
-                                                Log2(("dbgDiggerLinuxLoadKernelSymbols: RTDbgModSymbolAdd(,%s,) failed %Rrc (ignored)\n", szSymbol, rc));
-                                                rc = VINF_SUCCESS;
-                                            }
-                                            else
-                                                Log(("dbgDiggerLinuxLoadKernelSymbols: RTDbgModSymbolAdd(,%s,) failed %Rrc\n", szSymbol, rc));
+                                            Log2(("dbgDiggerLinuxLoadKernelSymbols: RTDbgModSymbolAdd(,%s,) failed %Rrc (ignored)\n", szSymbol, rc));
+                                            rc = VINF_SUCCESS;
                                         }
+                                        else
+                                            Log(("dbgDiggerLinuxLoadKernelSymbols: RTDbgModSymbolAdd(,%s,) failed %Rrc\n", szSymbol, rc));
                                     }
                                 }
-                                else
-                                {
-                                    rc = VERR_END_OF_STRING;
-                                    Log(("dbgDiggerLinuxLoadKernelSymbols: offName=%#x cLeft=%#x cbName=%#x cbKernelNames=%#x\n",
-                                         offName, cLeft, cbName, pThis->cbKernelNames));
-                                }
                             }
                             else
                             {
                                 rc = VERR_END_OF_STRING;
-                                Log(("dbgDiggerLinuxLoadKernelSymbols: offName=%#x cLeft=%#x cbKernelNames=%#x\n",
-                                     offName, cLeft, pThis->cbKernelNames));
+                                Log(("dbgDiggerLinuxLoadKernelSymbols: offName=%#x cLeft=%#x cbName=%#x cbKernelNames=%#x\n",
+                                     offName, cLeft, cbName, pThis->cbKernelNames));
                             }
                         }
-
-                        /*
-                         * Link the module into the address space.
-                         */
-                        if (RT_SUCCESS(rc))
+                        else
                         {
-                            RTDBGAS hAs = DBGFR3AsResolveAndRetain(pUVM, DBGF_AS_KERNEL);
-                            if (hAs != NIL_RTDBGAS)
-                                rc = RTDbgAsModuleLink(hAs, hMod, uKernelStart, RTDBGASLINK_FLAGS_REPLACE);
-                            else
-                                rc = VERR_INTERNAL_ERROR;
-                            RTDbgAsRelease(hAs);
+                            rc = VERR_END_OF_STRING;
+                            Log(("dbgDiggerLinuxLoadKernelSymbols: offName=%#x cLeft=%#x cbKernelNames=%#x\n",
+                                 offName, cLeft, pThis->cbKernelNames));
                         }
+                    }
+
+                    /*
+                     * Link the module into the address space.
+                     */
+                    if (RT_SUCCESS(rc))
+                    {
+                        RTDBGAS hAs = DBGFR3AsResolveAndRetain(pUVM, DBGF_AS_KERNEL);
+                        if (hAs != NIL_RTDBGAS)
+                            rc = RTDbgAsModuleLink(hAs, hMod, uKernelStart, RTDBGASLINK_FLAGS_REPLACE);
                         else
-                            Log(("dbgDiggerLinuxLoadKernelSymbols: Failed: %Rrc\n", rc));
-                        RTDbgModRelease(hMod);
+                            rc = VERR_INTERNAL_ERROR;
+                        RTDbgAsRelease(hAs);
                     }
                     else
-                        Log(("dbgDiggerLinuxLoadKernelSymbols: RTDbgModCreate failed: %Rrc\n", rc));
+                        Log(("dbgDiggerLinuxLoadKernelSymbols: Failed: %Rrc\n", rc));
+                    RTDbgModRelease(hMod);
                 }
                 else
-                    Log(("dbgDiggerLinuxLoadKernelSymbols: Reading token index at %RGv failed: %Rrc\n",
-                         pThis->AddrKernelTokenIndex.FlatPtr, rc));
-                RTMemFree(paoffTokens);
+                    Log(("dbgDiggerLinuxLoadKernelSymbols: RTDbgModCreate failed: %Rrc\n", rc));
             }
             else
-                Log(("dbgDiggerLinuxLoadKernelSymbols: Reading token table at %RGv failed: %Rrc\n",
-                     pThis->AddrKernelTokenTable.FlatPtr, rc));
-            RTMemFree(pszzTokens);
+                Log(("dbgDiggerLinuxLoadKernelSymbols: Reading token index at %RGv failed: %Rrc\n",
+                     pThis->AddrKernelTokenIndex.FlatPtr, rc));
+            RTMemFree(paoffTokens);
         }
         else
-            Log(("dbgDiggerLinuxLoadKernelSymbols: Reading encoded names at %RGv failed: %Rrc\n",
-                 pThis->AddrKernelNames.FlatPtr, rc));
-        RTMemFree(pbNames);
+            Log(("dbgDiggerLinuxLoadKernelSymbols: Reading token table at %RGv failed: %Rrc\n",
+                 pThis->AddrKernelTokenTable.FlatPtr, rc));
+        RTMemFree(pszzTokens);
     }
     else
-        Log(("dbgDiggerLinuxLoadKernelSymbols: Reading symbol addresses at %RGv failed: %Rrc\n",
+        Log(("dbgDiggerLinuxLoadKernelSymbols: Reading encoded names at %RGv failed: %Rrc\n",
+             pThis->AddrKernelNames.FlatPtr, rc));
+    RTMemFree(pbNames);
+
+    return rc;
+}
+
+/**
+ * Loads the kernel symbols from the kallsyms table if it contains absolute addresses
+ *
+ * @returns VBox status code.
+ * @param   pUVM                The user mode VM handle.
+ * @param   pThis               The Linux digger data.
+ */
+static int dbgDiggerLinuxLoadKernelSymbolsAbsolute(PUVM pUVM, PDBGDIGGERLINUX pThis)
+{
+    /*
+     * Allocate memory for temporary table copies, reading the tables as we go.
+     */
+    uint32_t const cbGuestAddr = pThis->f64Bit ? sizeof(uint64_t) : sizeof(uint32_t);
+    void *pvAddresses = RTMemAllocZ(pThis->cKernelSymbols * cbGuestAddr);
+    int rc = DBGFR3MemRead(pUVM, 0 /*idCpu*/, &pThis->AddrKernelAddresses, pvAddresses, pThis->cKernelSymbols * cbGuestAddr);
+    if (RT_SUCCESS(rc))
+    {
+        /*
+         * Figure out the kernel start and end and convert the absolute addresses to relative offsets.
+         */
+        RTGCUINTPTR uKernelStart = pThis->AddrKernelAddresses.FlatPtr;
+        RTGCUINTPTR uKernelEnd   = pThis->AddrKernelTokenIndex.FlatPtr + 256 * sizeof(uint16_t);
+        RTGCUINTPTR *pauSymOff   = (RTGCUINTPTR *)RTMemTmpAllocZ(pThis->cKernelSymbols * sizeof(RTGCUINTPTR));
+        uint32_t    i;
+        if (cbGuestAddr == sizeof(uint64_t))
+        {
+            uint64_t *pauAddrs = (uint64_t *)pvAddresses;
+            for (i = 0; i < pThis->cKernelSymbols; i++)
+                if (   pauAddrs[i] < uKernelStart
+                    && LNX64_VALID_ADDRESS(pauAddrs[i])
+                    && uKernelStart - pauAddrs[i] < LNX_MAX_KERNEL_SIZE)
+                    uKernelStart = pauAddrs[i];
+
+            for (i = pThis->cKernelSymbols - 1; i > 0; i--)
+                if (   pauAddrs[i] > uKernelEnd
+                    && LNX64_VALID_ADDRESS(pauAddrs[i])
+                    && pauAddrs[i] - uKernelEnd < LNX_MAX_KERNEL_SIZE)
+                    uKernelEnd = pauAddrs[i];
+
+            for (i = 0; i < pThis->cKernelSymbols; i++)
+                pauSymOff[i] = pauAddrs[i] - uKernelStart;
+        }
+        else
+        {
+            uint32_t *pauAddrs = (uint32_t *)pvAddresses;
+            for (i = 0; i < pThis->cKernelSymbols; i++)
+                if (   pauAddrs[i] < uKernelStart
+                    && LNX32_VALID_ADDRESS(pauAddrs[i])
+                    && uKernelStart - pauAddrs[i] < LNX_MAX_KERNEL_SIZE)
+                    uKernelStart = pauAddrs[i];
+
+            for (i = pThis->cKernelSymbols - 1; i > 0; i--)
+                if (   pauAddrs[i] > uKernelEnd
+                    && LNX32_VALID_ADDRESS(pauAddrs[i])
+                    && pauAddrs[i] - uKernelEnd < LNX_MAX_KERNEL_SIZE)
+                    uKernelEnd = pauAddrs[i];
+
+            for (i = 0; i < pThis->cKernelSymbols; i++)
+                pauSymOff[i] = pauAddrs[i] - uKernelStart;
+        }
+
+        RTGCUINTPTR cbKernel = uKernelEnd - uKernelStart;
+        pThis->cbKernel = (uint32_t)cbKernel;
+        DBGFR3AddrFromFlat(pUVM, &pThis->AddrKernelBase, uKernelStart);
+        Log(("dbgDiggerLinuxLoadKernelSymbolsAbsolute: uKernelStart=%RGv cbKernel=%#x\n", uKernelStart, cbKernel));
+
+        rc = dbgDiggerLinuxLoadKernelSymbolsWorker(pUVM, pThis, uKernelStart, cbKernel, pauSymOff);
+        if (RT_FAILURE(rc))
+            Log(("dbgDiggerLinuxLoadKernelSymbolsAbsolute: Loading symbols from given offset table failed: %Rrc\n", rc));
+        RTMemTmpFree(pauSymOff);
+    }
+    else
+        Log(("dbgDiggerLinuxLoadKernelSymbolsAbsolute: Reading symbol addresses at %RGv failed: %Rrc\n",
              pThis->AddrKernelAddresses.FlatPtr, rc));
     RTMemFree(pvAddresses);
+
     return rc;
 }
 
 
 /**
+ * Loads the kernel symbols from the kallsyms table if it contains absolute addresses
+ *
+ * @returns VBox status code.
+ * @param   pUVM                The user mode VM handle.
+ * @param   pThis               The Linux digger data.
+ */
+static int dbgDiggerLinuxLoadKernelSymbolsRelative(PUVM pUVM, PDBGDIGGERLINUX pThis)
+{
+    /*
+     * Allocate memory for temporary table copies, reading the tables as we go.
+     */
+    int32_t *pai32Offsets = (int32_t *)RTMemAllocZ(pThis->cKernelSymbols * sizeof(int32_t));
+    int rc = DBGFR3MemRead(pUVM, 0 /*idCpu*/, &pThis->AddrKernelAddresses, pai32Offsets, pThis->cKernelSymbols * sizeof(int32_t));
+    if (RT_SUCCESS(rc))
+    {
+        /*
+         * Figure out the kernel start and end and convert the absolute addresses to relative offsets.
+         */
+        RTGCUINTPTR uKernelStart = pThis->AddrKernelAddresses.FlatPtr;
+        RTGCUINTPTR uKernelEnd   = pThis->AddrKernelTokenIndex.FlatPtr + 256 * sizeof(uint16_t);
+        RTGCUINTPTR *pauSymOff   = (RTGCUINTPTR *)RTMemTmpAllocZ(pThis->cKernelSymbols * sizeof(RTGCUINTPTR));
+        uint32_t    i;
+
+        for (i = 0; i < pThis->cKernelSymbols; i++)
+        {
+            RTGCUINTPTR uSymAddr = dbgDiggerLinuxConvOffsetToAddr(pThis, pai32Offsets[i]);
+
+            if (   uSymAddr < uKernelStart
+                && (pThis->f64Bit ? LNX64_VALID_ADDRESS(uSymAddr) : LNX32_VALID_ADDRESS(uSymAddr))
+                && uKernelStart - uSymAddr < LNX_MAX_KERNEL_SIZE)
+                uKernelStart = uSymAddr;
+        }
+
+        for (i = pThis->cKernelSymbols - 1; i > 0; i--)
+        {
+            RTGCUINTPTR uSymAddr = dbgDiggerLinuxConvOffsetToAddr(pThis, pai32Offsets[i]);
+
+            if (   uSymAddr > uKernelEnd
+                && (pThis->f64Bit ? LNX64_VALID_ADDRESS(uSymAddr) : LNX32_VALID_ADDRESS(uSymAddr))
+                && uSymAddr - uKernelEnd < LNX_MAX_KERNEL_SIZE)
+                uKernelEnd = uSymAddr;
+
+            /* Store the offset from the derived kernel start address. */
+            pauSymOff[i] = uSymAddr - uKernelStart;
+        }
+
+        RTGCUINTPTR cbKernel = uKernelEnd - uKernelStart;
+        pThis->cbKernel = (uint32_t)cbKernel;
+        DBGFR3AddrFromFlat(pUVM, &pThis->AddrKernelBase, uKernelStart);
+        Log(("dbgDiggerLinuxLoadKernelSymbolsRelative: uKernelStart=%RGv cbKernel=%#x\n", uKernelStart, cbKernel));
+
+        rc = dbgDiggerLinuxLoadKernelSymbolsWorker(pUVM, pThis, uKernelStart, cbKernel, pauSymOff);
+        if (RT_FAILURE(rc))
+            Log(("dbgDiggerLinuxLoadKernelSymbolsRelative: Loading symbols from given offset table failed: %Rrc\n", rc));
+        RTMemTmpFree(pauSymOff);
+    }
+    else
+        Log(("dbgDiggerLinuxLoadKernelSymbolsRelative: Reading symbol addresses at %RGv failed: %Rrc\n",
+             pThis->AddrKernelAddresses.FlatPtr, rc));
+    RTMemFree(pai32Offsets);
+
+    return rc;
+}
+
+
+/**
+ * Loads the kernel symbols.
+ *
+ * @returns VBox status code.
+ * @param   pUVM                The user mode VM handle.
+ * @param   pThis               The Linux digger data.
+ */
+static int dbgDiggerLinuxLoadKernelSymbols(PUVM pUVM, PDBGDIGGERLINUX pThis)
+{
+    if (pThis->fRelKrnlAddr)
+        return dbgDiggerLinuxLoadKernelSymbolsRelative(pUVM, pThis);
+    else
+        return dbgDiggerLinuxLoadKernelSymbolsAbsolute(pUVM, pThis);
+}
+
+/**
  * Checks if there is a likely kallsyms_names fragment at pHitAddr.
  *
  * @returns true if it's a likely fragment, false if not.
@@ -2196,6 +2424,7 @@ static DECLCALLBACK(int)  dbgDiggerLinuxInit(PUVM pUVM, void *pvData)
      * Assume 64-bit kernels all live way beyond 32-bit address space.
      */
     pThis->f64Bit = pThis->AddrLinuxBanner.FlatPtr > UINT32_MAX;
+    pThis->fRelKrnlAddr = false;
 
     pThis->hCfgDb = NULL;
 
diff --git a/src/VBox/Devices/Audio/AudioMixBuffer.cpp b/src/VBox/Devices/Audio/AudioMixBuffer.cpp
index 0528dc2..6d77f7d 100644
--- a/src/VBox/Devices/Audio/AudioMixBuffer.cpp
+++ b/src/VBox/Devices/Audio/AudioMixBuffer.cpp
@@ -5,7 +5,7 @@
  */
 
 /*
- * Copyright (C) 2014-2016 Oracle Corporation
+ * Copyright (C) 2014-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;
@@ -18,29 +18,31 @@
 #define LOG_GROUP LOG_GROUP_AUDIO_MIXER_BUFFER
 #include <VBox/log.h>
 
+#if 0
 /*
- * DEBUG_DUMP_PCM_DATA enables dumping the raw PCM data
- * to a file on the host. Be sure to adjust DEBUG_DUMP_PCM_DATA_PATH
+ * AUDIOMIXBUF_DEBUG_DUMP_PCM_DATA enables dumping the raw PCM data
+ * to a file on the host. Be sure to adjust AUDIOMIXBUF_DEBUG_DUMP_PCM_DATA_PATH
  * to your needs before using this!
  */
-#if 0
-# define DEBUG_DUMP_PCM_DATA
+# define AUDIOMIXBUF_DEBUG_DUMP_PCM_DATA
 # ifdef RT_OS_WINDOWS
-#  define DEBUG_DUMP_PCM_DATA_PATH "c:\\temp\\"
+#  define AUDIOMIXBUF_DEBUG_DUMP_PCM_DATA_PATH "c:\\temp\\"
 # else
-#  define DEBUG_DUMP_PCM_DATA_PATH "/tmp/"
+#  define AUDIOMIXBUF_DEBUG_DUMP_PCM_DATA_PATH "/tmp/"
 # endif
+/* Warning: Enabling this will generate *huge* logs! */
+//# define AUDIOMIXBUF_DEBUG_MACROS
 #endif
 
 #include <iprt/asm-math.h>
 #include <iprt/assert.h>
-#ifdef DEBUG_DUMP_PCM_DATA
+#ifdef AUDIOMIXBUF_DEBUG_DUMP_PCM_DATA
 # include <iprt/file.h>
 #endif
 #include <iprt/mem.h>
 #include <iprt/string.h> /* For RT_BZERO. */
 
-#ifdef TESTCASE
+#ifdef VBOX_AUDIO_TESTCASE
 # define LOG_ENABLED
 # include <iprt/stream.h>
 #endif
@@ -48,16 +50,20 @@
 
 #include "AudioMixBuffer.h"
 
-#if 0
-# define AUDMIXBUF_LOG(x) LogFlowFunc(x)
-#else
-# if defined(TESTCASE)
-#  define AUDMIXBUF_LOG(x) LogFunc(x)
+#ifndef VBOX_AUDIO_TESTCASE
+# ifdef DEBUG
+#  define AUDMIXBUF_LOG(x) LogFlowFunc(x)
 # else
-#  define AUDMIXBUF_LOG(x) do {} while (0)
+# define AUDMIXBUF_LOG(x) do {} while (0)
 # endif
+#else /* VBOX_AUDIO_TESTCASE */
+# define AUDMIXBUF_LOG(x) RTPrintf x
 #endif
 
+#ifdef DEBUG
+DECLINLINE(void)        audioMixBufDbgPrintInternal(PPDMAUDIOMIXBUF pMixBuf, const char *pszFunc);
+DECL_FORCE_INLINE(bool) audioMixBufDbgValidate(PPDMAUDIOMIXBUF pMixBuf);
+#endif
 
 /*
  *   Soft Volume Control
@@ -66,7 +72,7 @@
  * 0 .. 255 range. This represents 0 to -96dB attenuation where an input
  * value of 0 corresponds to -96dB and 255 corresponds to 0dB (unchanged).
  *
- * Each step thus correspons to 96 / 256 or 0.375dB. Every 6dB (16 steps)
+ * Each step thus corresponds to 96 / 256 or 0.375dB. Every 6dB (16 steps)
  * represents doubling the sample value.
  *
  * For internal use, the volume control needs to be converted to a 16-bit
@@ -128,118 +134,123 @@ static uint32_t s_aVolumeConv[256] = {
 AssertCompile(AUDIOMIXBUF_VOL_0DB <= 0x40000000);   /* Must always hold. */
 AssertCompile(AUDIOMIXBUF_VOL_0DB == 0x40000000);   /* For now -- when only attenuation is used. */
 
+
 /**
- * Structure for holding sample conversion parameters for
- * the audioMixBufConvFromXXX / audioMixBufConvToXXX macros.
+ * Peeks for audio samples without any conversion done.
+ * This will get the raw sample data out of a mixing buffer.
+ *
+ * @return  IPRT status code or VINF_AUDIO_MORE_DATA_AVAILABLE if more data is available to read.
+ *
+ * @param   pMixBuf                 Mixing buffer to acquire audio samples from.
+ * @param   cSamplesToRead          Number of audio samples to read.
+ * @param   paSampleBuf             Buffer where to store the returned audio samples.
+ * @param   cSampleBuf              Size (in samples) of the buffer to store audio samples into.
+ * @param   pcSamplesRead           Returns number of read audio samples. Optional.
+ *
+ * @remark  This function is not thread safe!
  */
-typedef struct AUDMIXBUF_CONVOPTS
+int AudioMixBufPeek(PPDMAUDIOMIXBUF pMixBuf, uint32_t cSamplesToRead,
+                    PPDMAUDIOSAMPLE paSampleBuf, uint32_t cSampleBuf, uint32_t *pcSamplesRead)
 {
-    /** Number of audio samples to convert. */
-    uint32_t       cSamples;
-    /** Volume to apply during conversion. Pass 0
-     *  to convert the original values. May not apply to
-     *  all conversion functions. */
-    PDMAUDIOVOLUME Volume;
-} AUDMIXBUF_CONVOPTS, *PAUDMIXBUF_CONVOPTS;
+    AssertPtrReturn(pMixBuf,     VERR_INVALID_POINTER);
+    AssertPtrReturn(paSampleBuf, VERR_INVALID_POINTER);
+    AssertReturn(cSampleBuf,     VERR_INVALID_PARAMETER);
+    /* pcRead is optional. */
 
-/*
- * When running the audio testcases we want to verfiy
- * the macro-generated routines separately, so unmark them as being
- * inlined + static.
- */
-#ifdef TESTCASE
-# define AUDMIXBUF_MACRO_FN
-#else
-# define AUDMIXBUF_MACRO_FN static inline
-#endif
+    int rc;
 
-#ifdef DEBUG
-static uint64_t s_cSamplesMixedTotal = 0;
-static inline void audioMixBufPrint(PPDMAUDIOMIXBUF pMixBuf);
-#endif
+    if (!cSamplesToRead)
+    {
+        if (pcSamplesRead)
+            *pcSamplesRead = 0;
+        return VINF_SUCCESS;
+    }
+
+    uint32_t cRead;
+    if (pMixBuf->offRead + cSamplesToRead > pMixBuf->cSamples)
+    {
+        cRead = pMixBuf->cSamples - pMixBuf->offRead;
+        rc = VINF_AUDIO_MORE_DATA_AVAILABLE;
+    }
+    else
+    {
+        cRead = cSamplesToRead;
+        rc = VINF_SUCCESS;
+    }
 
-typedef uint32_t (AUDMIXBUF_FN_CONVFROM) (PPDMAUDIOSAMPLE paDst, const void *pvSrc, uint32_t cbSrc, const PAUDMIXBUF_CONVOPTS pOpts);
-typedef AUDMIXBUF_FN_CONVFROM *PAUDMIXBUF_FN_CONVFROM;
+    if (cRead > cSampleBuf)
+    {
+        cRead = cSampleBuf;
+        rc = VINF_AUDIO_MORE_DATA_AVAILABLE;
+    }
+
+    if (cRead)
+    {
+        memcpy(paSampleBuf, &pMixBuf->pSamples[pMixBuf->offRead], sizeof(PDMAUDIOSAMPLE) * cRead);
 
-typedef void (AUDMIXBUF_FN_CONVTO) (void *pvDst, const PPDMAUDIOSAMPLE paSrc, const PAUDMIXBUF_CONVOPTS pOpts);
-typedef AUDMIXBUF_FN_CONVTO *PAUDMIXBUF_FN_CONVTO;
+        pMixBuf->offRead = (pMixBuf->offRead + cRead) % pMixBuf->cSamples;
+        Assert(pMixBuf->offRead <= pMixBuf->cSamples);
+        pMixBuf->cUsed  -= RT_MIN(cRead, pMixBuf->cUsed);
+    }
 
-/* Can return VINF_TRY_AGAIN for getting next pointer at beginning (circular) */
+    if (pcSamplesRead)
+        *pcSamplesRead = cRead;
+
+    return rc;
+}
 
 /**
- * Acquires (reads) a mutable pointer to the mixing buffer's audio samples without
- * any conversion done.
- ** @todo Rename to AudioMixBufPeek(Mutable/Raw)?
- ** @todo Protect the buffer's data?
+ * Returns a mutable pointer to the mixing buffer's audio sample buffer for writing raw
+ * audio samples.
  *
- * @return  IPRT status code.
+ * @return  IPRT status code. VINF_TRY_AGAIN for getting next pointer at beginning (circular).
  * @param   pMixBuf                 Mixing buffer to acquire audio samples from.
- * @param   cSamplesToRead          Number of audio samples to read.
+ * @param   cSamples                Number of requested audio samples to write.
  * @param   ppvSamples              Returns a mutable pointer to the buffer's audio sample data.
- * @param   pcSamplesRead           Number of audio samples read (acquired).
+ * @param   pcSamplesToWrite        Number of available audio samples to write.
  *
  * @remark  This function is not thread safe!
  */
-int AudioMixBufAcquire(PPDMAUDIOMIXBUF pMixBuf, uint32_t cSamplesToRead,
-                       PPDMAUDIOSAMPLE *ppvSamples, uint32_t *pcSamplesRead)
+int AudioMixBufPeekMutable(PPDMAUDIOMIXBUF pMixBuf, uint32_t cSamples,
+                           PPDMAUDIOSAMPLE *ppvSamples, uint32_t *pcSamplesToWrite)
 {
     AssertPtrReturn(pMixBuf, VERR_INVALID_POINTER);
     AssertPtrReturn(ppvSamples, VERR_INVALID_POINTER);
-    AssertPtrReturn(pcSamplesRead, VERR_INVALID_POINTER);
+    AssertPtrReturn(pcSamplesToWrite, VERR_INVALID_POINTER);
 
     int rc;
 
-    if (!cSamplesToRead)
+    if (!cSamples)
     {
-        *pcSamplesRead = 0;
+        *pcSamplesToWrite = 0;
         return VINF_SUCCESS;
     }
 
-    uint32_t cSamplesRead;
-    if (pMixBuf->offReadWrite + cSamplesToRead > pMixBuf->cSamples)
+    uint32_t cSamplesToWrite;
+    if (pMixBuf->offWrite + cSamples > pMixBuf->cSamples)
     {
-        cSamplesRead = pMixBuf->cSamples - pMixBuf->offReadWrite;
+        cSamplesToWrite = pMixBuf->cSamples - pMixBuf->offWrite;
         rc = VINF_TRY_AGAIN;
     }
     else
     {
-        cSamplesRead = cSamplesToRead;
+        cSamplesToWrite = cSamples;
         rc = VINF_SUCCESS;
     }
 
-    *ppvSamples = &pMixBuf->pSamples[pMixBuf->offReadWrite];
+    *ppvSamples = &pMixBuf->pSamples[pMixBuf->offWrite];
     AssertPtr(ppvSamples);
 
-    pMixBuf->offReadWrite = (pMixBuf->offReadWrite + cSamplesRead) % pMixBuf->cSamples;
-    Assert(pMixBuf->offReadWrite <= pMixBuf->cSamples);
-    pMixBuf->cProcessed -= RT_MIN(cSamplesRead, pMixBuf->cProcessed);
+    pMixBuf->offWrite = (pMixBuf->offWrite + cSamplesToWrite) % pMixBuf->cSamples;
+    Assert(pMixBuf->offWrite <= pMixBuf->cSamples);
+    pMixBuf->cUsed += RT_MIN(cSamplesToWrite, pMixBuf->cUsed);
 
-    *pcSamplesRead = cSamplesRead;
+    *pcSamplesToWrite = cSamplesToWrite;
 
     return rc;
 }
 
 /**
- * Returns available number of samples for reading.
- *
- * @return  uint32_t                Number of samples available for reading.
- * @param   pMixBuf                 Mixing buffer to return value for.
- */
-uint32_t AudioMixBufAvail(PPDMAUDIOMIXBUF pMixBuf)
-{
-    AssertPtrReturn(pMixBuf, true);
-
-    uint32_t cAvail;
-    if (pMixBuf->pParent) /* Child */
-        cAvail = pMixBuf->cMixed;
-    else
-        cAvail = pMixBuf->cProcessed;
-
-    Assert(cAvail <= pMixBuf->cSamples);
-    return cAvail;
-}
-
-/**
  * Clears the entire sample buffer.
  *
  * @param   pMixBuf                 Mixing buffer to clear.
@@ -254,7 +265,7 @@ void AudioMixBufClear(PPDMAUDIOMIXBUF pMixBuf)
 }
 
 /**
- * Clears (zeroes) the buffer by a certain amount of (processed) samples and
+ * Clears (zeroes) the buffer by a certain amount of (used) samples and
  * keeps track to eventually assigned children buffers.
  *
  * @param   pMixBuf                 Mixing buffer to clear.
@@ -262,43 +273,53 @@ void AudioMixBufClear(PPDMAUDIOMIXBUF pMixBuf)
  */
 void AudioMixBufFinish(PPDMAUDIOMIXBUF pMixBuf, uint32_t cSamplesToClear)
 {
-    AUDMIXBUF_LOG(("cSamples=%RU32\n", cSamplesToClear));
-    AUDMIXBUF_LOG(("%s: offReadWrite=%RU32, cProcessed=%RU32\n",
-                   pMixBuf->pszName, pMixBuf->offReadWrite, pMixBuf->cProcessed));
+    AUDMIXBUF_LOG(("cSamplesToClear=%RU32\n", cSamplesToClear));
+    AUDMIXBUF_LOG(("%s: offRead=%RU32, cUsed=%RU32\n",
+                   pMixBuf->pszName, pMixBuf->offRead, pMixBuf->cUsed));
 
     PPDMAUDIOMIXBUF pIter;
-    RTListForEach(&pMixBuf->lstBuffers, pIter, PDMAUDIOMIXBUF, Node)
+    RTListForEach(&pMixBuf->lstChildren, pIter, PDMAUDIOMIXBUF, Node)
     {
         AUDMIXBUF_LOG(("\t%s: cMixed=%RU32 -> %RU32\n",
                        pIter->pszName, pIter->cMixed, pIter->cMixed - cSamplesToClear));
 
         pIter->cMixed -= RT_MIN(pIter->cMixed, cSamplesToClear);
-        pIter->offReadWrite = 0;
+        /* Note: Do not increment pIter->cUsed here, as this gets done when reading from that buffer using AudioMixBufReadXXX. */
     }
 
-    uint32_t cLeft = RT_MIN(cSamplesToClear, pMixBuf->cSamples);
-    uint32_t offClear;
+    Assert(cSamplesToClear <= pMixBuf->cSamples);
+
+    uint32_t cClearOff;
+    uint32_t cClearLen;
 
-    if (cLeft > pMixBuf->offReadWrite) /* Zero end of buffer first (wrap-around). */
+    /* Clear end of buffer (wrap around). */
+    if (cSamplesToClear > pMixBuf->offRead)
     {
-        AUDMIXBUF_LOG(("Clearing1: %RU32 - %RU32\n",
-                       (pMixBuf->cSamples - (cLeft - pMixBuf->offReadWrite)),
-                        pMixBuf->cSamples));
+        cClearOff = pMixBuf->cSamples - (cSamplesToClear - pMixBuf->offRead);
+        cClearLen = pMixBuf->cSamples - cClearOff;
 
-        RT_BZERO(pMixBuf->pSamples + (pMixBuf->cSamples - (cLeft - pMixBuf->offReadWrite)),
-                 (cLeft - pMixBuf->offReadWrite) * sizeof(PDMAUDIOSAMPLE));
+        AUDMIXBUF_LOG(("Clearing1: %RU32 - %RU32\n", cClearOff, cClearOff + cClearLen));
 
-        cLeft -= cLeft - pMixBuf->offReadWrite;
-        offClear = 0;
+        RT_BZERO(pMixBuf->pSamples + cClearOff, cClearLen * sizeof(PDMAUDIOSAMPLE));
+
+        Assert(cSamplesToClear >= cClearLen);
+        cSamplesToClear -= cClearLen;
     }
-    else
-        offClear = pMixBuf->offReadWrite - cLeft;
 
-    if (cLeft)
+    /* Clear beginning of buffer. */
+    if (   cSamplesToClear
+        && pMixBuf->offRead)
     {
-        AUDMIXBUF_LOG(("Clearing2: %RU32 - %RU32\n",
-                       offClear, offClear + cLeft));
-        RT_BZERO(pMixBuf->pSamples + offClear, cLeft * sizeof(PDMAUDIOSAMPLE));
+        Assert(pMixBuf->offRead >= cSamplesToClear);
+
+        cClearOff = pMixBuf->offRead - cSamplesToClear;
+        cClearLen = cSamplesToClear;
+
+        Assert(cClearOff + cClearLen <= pMixBuf->cSamples);
+
+        AUDMIXBUF_LOG(("Clearing2: %RU32 - %RU32\n", cClearOff, cClearOff + cClearLen));
+
+        RT_BZERO(pMixBuf->pSamples + cClearOff, cClearLen * sizeof(PDMAUDIOSAMPLE));
     }
 }
 
@@ -349,23 +370,26 @@ uint32_t AudioMixBufFree(PPDMAUDIOMIXBUF pMixBuf)
 {
     AssertPtrReturn(pMixBuf, 0);
 
-    uint32_t cSamplesFree;
+    uint32_t cSamples, cSamplesFree;
     if (pMixBuf->pParent)
     {
         /*
          * As a linked child buffer we want to know how many samples
          * already have been consumed by the parent.
          */
-        Assert(pMixBuf->cMixed <= pMixBuf->pParent->cSamples);
-        cSamplesFree = pMixBuf->pParent->cSamples - pMixBuf->cMixed;
+        cSamples = pMixBuf->pParent->cSamples;
+
+        Assert(pMixBuf->cMixed <= cSamples);
+        cSamplesFree = cSamples - pMixBuf->cMixed;
     }
     else /* As a parent. */
     {
-        Assert(pMixBuf->cSamples >= pMixBuf->cProcessed);
-        cSamplesFree = pMixBuf->cSamples - pMixBuf->cProcessed;
+        cSamples     = pMixBuf->cSamples;
+        Assert(cSamples >= pMixBuf->cUsed);
+        cSamplesFree = pMixBuf->cSamples - pMixBuf->cUsed;
     }
 
-    AUDMIXBUF_LOG(("%s: cSamplesFree=%RU32\n", pMixBuf->pszName, cSamplesFree));
+    AUDMIXBUF_LOG(("%s: %RU32 of %RU32\n", pMixBuf->pszName, cSamplesFree, cSamples));
     return cSamplesFree;
 }
 
@@ -395,24 +419,18 @@ static int audioMixBufAlloc(PPDMAUDIOMIXBUF pMixBuf, uint32_t cSamples)
     AUDMIXBUF_LOG(("%s: cSamples=%RU32\n", pMixBuf->pszName, cSamples));
 
     size_t cbSamples = cSamples * sizeof(PDMAUDIOSAMPLE);
-    if (!cbSamples)
-        return VERR_INVALID_PARAMETER;
-
     pMixBuf->pSamples = (PPDMAUDIOSAMPLE)RTMemAllocZ(cbSamples);
-    if (!pMixBuf->pSamples)
-        return VERR_NO_MEMORY;
-
-    pMixBuf->cSamples = cSamples;
-
-    return VINF_SUCCESS;
+    if (pMixBuf->pSamples)
+    {
+        pMixBuf->cSamples = cSamples;
+        return VINF_SUCCESS;
+    }
+    return VERR_NO_MEMORY;
 }
 
-/** Note: Enabling this will generate huge logs! */
-//#define DEBUG_MACROS
-
-#ifdef DEBUG_MACROS
+#ifdef AUDIOMIXBUF_DEBUG_MACROS
 # define AUDMIXBUF_MACRO_LOG(x) AUDMIXBUF_LOG(x)
-#elif defined(TESTCASE)
+#elif defined(VBOX_AUDIO_TESTCASE_VERBOSE) /* Warning: VBOX_AUDIO_TESTCASE_VERBOSE will generate huge logs! */
 # define AUDMIXBUF_MACRO_LOG(x) RTPrintf x
 #else
 # define AUDMIXBUF_MACRO_LOG(x) do {} while (0)
@@ -427,19 +445,20 @@ static int audioMixBufAlloc(PPDMAUDIOMIXBUF pMixBuf, uint32_t cSamples)
  */
 #define AUDMIXBUF_CONVERT(_aName, _aType, _aMin, _aMax, _aSigned, _aShift) \
     /* Clips a specific output value to a single sample value. */ \
-    AUDMIXBUF_MACRO_FN int64_t audioMixBufClipFrom##_aName(_aType aVal) \
+    DECLCALLBACK(int64_t) audioMixBufClipFrom##_aName(_aType aVal) \
     { \
+        /* left shifting of signed values is not defined, therefore the intermediate uint64_t cast */ \
         if (_aSigned) \
-            return ((int64_t) aVal) << (32 - _aShift); \
-        return ((int64_t) aVal - ((_aMax >> 1) + 1)) << (32 - _aShift); \
+            return (int64_t) (((uint64_t) ((int64_t) aVal                     )) << (32 - _aShift)); \
+        return     (int64_t) (((uint64_t) ((int64_t) aVal - ((_aMax >> 1) + 1))) << (32 - _aShift)); \
     } \
     \
     /* Clips a single sample value to a specific output value. */ \
-    AUDMIXBUF_MACRO_FN _aType audioMixBufClipTo##_aName(int64_t iVal) \
+    DECLCALLBACK(_aType) audioMixBufClipTo##_aName(int64_t iVal) \
     { \
         if (iVal >= 0x7fffffff) \
             return _aMax; \
-        else if (iVal < -INT64_C(0x80000000)) \
+        if (iVal < -INT64_C(0x80000000)) \
             return _aMin; \
         \
         if (_aSigned) \
@@ -447,49 +466,44 @@ static int audioMixBufAlloc(PPDMAUDIOMIXBUF pMixBuf, uint32_t cSamples)
         return ((_aType) ((iVal >> (32 - _aShift)) + ((_aMax >> 1) + 1))); \
     } \
     \
-    AUDMIXBUF_MACRO_FN uint32_t audioMixBufConvFrom##_aName##Stereo(PPDMAUDIOSAMPLE paDst, const void *pvSrc, uint32_t cbSrc, \
-                                                                    const PAUDMIXBUF_CONVOPTS pOpts) \
+    DECLCALLBACK(uint32_t) audioMixBufConvFrom##_aName##Stereo(PPDMAUDIOSAMPLE paDst, const void *pvSrc, uint32_t cbSrc, \
+                                                               PCPDMAUDMIXBUFCONVOPTS pOpts) \
     { \
-        _aType *pSrc = (_aType *)pvSrc; \
-        uint32_t cSamples = (uint32_t)RT_MIN(pOpts->cSamples, cbSrc / sizeof(_aType)); \
-        AUDMIXBUF_MACRO_LOG(("cSamples=%RU32, sizeof(%zu), lVol=%RU32, rVol=%RU32\n", \
-                             pOpts->cSamples, sizeof(_aType), pOpts->Volume.uLeft, pOpts->Volume.uRight)); \
+        _aType const *pSrc = (_aType const *)pvSrc; \
+        uint32_t cSamples = RT_MIN(pOpts->cSamples, cbSrc / sizeof(_aType)); \
+        AUDMIXBUF_MACRO_LOG(("cSamples=%RU32, BpS=%zu, lVol=%RU32, rVol=%RU32\n", \
+                             pOpts->cSamples, sizeof(_aType), pOpts->From.Volume.uLeft, pOpts->From.Volume.uRight)); \
         for (uint32_t i = 0; i < cSamples; i++) \
         { \
-            AUDMIXBUF_MACRO_LOG(("%p: l=%RI16, r=%RI16\n", paDst, *pSrc, *(pSrc + 1))); \
-            paDst->i64LSample = ASMMult2xS32RetS64((int32_t)audioMixBufClipFrom##_aName(*pSrc++), pOpts->Volume.uLeft ) >> AUDIOMIXBUF_VOL_SHIFT; \
-            paDst->i64RSample = ASMMult2xS32RetS64((int32_t)audioMixBufClipFrom##_aName(*pSrc++), pOpts->Volume.uRight) >> AUDIOMIXBUF_VOL_SHIFT; \
-            AUDMIXBUF_MACRO_LOG(("\t-> l=%RI64, r=%RI64\n", paDst->i64LSample, paDst->i64RSample)); \
+            paDst->i64LSample = ASMMult2xS32RetS64((int32_t)audioMixBufClipFrom##_aName(*pSrc++), pOpts->From.Volume.uLeft ) >> AUDIOMIXBUF_VOL_SHIFT; \
+            paDst->i64RSample = ASMMult2xS32RetS64((int32_t)audioMixBufClipFrom##_aName(*pSrc++), pOpts->From.Volume.uRight) >> AUDIOMIXBUF_VOL_SHIFT; \
             paDst++; \
         } \
         \
         return cSamples; \
     } \
     \
-    AUDMIXBUF_MACRO_FN uint32_t audioMixBufConvFrom##_aName##Mono(PPDMAUDIOSAMPLE paDst, const void *pvSrc, uint32_t cbSrc, \
-                                                                  const PAUDMIXBUF_CONVOPTS pOpts) \
+    DECLCALLBACK(uint32_t) audioMixBufConvFrom##_aName##Mono(PPDMAUDIOSAMPLE paDst, const void *pvSrc, uint32_t cbSrc, \
+                                                             PCPDMAUDMIXBUFCONVOPTS pOpts) \
     { \
-        _aType *pSrc = (_aType *)pvSrc; \
-        uint32_t cSamples = (uint32_t)RT_MIN(pOpts->cSamples, cbSrc / sizeof(_aType)); \
-        AUDMIXBUF_MACRO_LOG(("cSamples=%RU32, sizeof(%zu), lVol=%RU32, rVol=%RU32\n", \
-                             cSamples, sizeof(_aType), pOpts->Volume.uLeft, pOpts->Volume.uRight)); \
+        _aType const *pSrc = (_aType const *)pvSrc; \
+        const uint32_t cSamples = RT_MIN(pOpts->cSamples, cbSrc / sizeof(_aType)); \
+        AUDMIXBUF_MACRO_LOG(("cSamples=%RU32, BpS=%zu, lVol=%RU32, rVol=%RU32\n", \
+                             cSamples, sizeof(_aType), pOpts->From.Volume.uLeft, pOpts->From.Volume.uRight)); \
         for (uint32_t i = 0; i < cSamples; i++) \
         { \
-            AUDMIXBUF_MACRO_LOG(("%p: s=%RI16\n", paDst, *pSrc)); \
-            paDst->i64LSample = ASMMult2xS32RetS64((int32_t)audioMixBufClipFrom##_aName(*pSrc), pOpts->Volume.uLeft)  >> AUDIOMIXBUF_VOL_SHIFT; \
-            paDst->i64RSample = ASMMult2xS32RetS64((int32_t)audioMixBufClipFrom##_aName(*pSrc), pOpts->Volume.uRight) >> AUDIOMIXBUF_VOL_SHIFT; \
-            ++pSrc; \
-            AUDMIXBUF_MACRO_LOG(("\t-> l=%RI64, r=%RI64\n", paDst->i64LSample, paDst->i64RSample)); \
+            paDst->i64LSample = ASMMult2xS32RetS64((int32_t)audioMixBufClipFrom##_aName(*pSrc), pOpts->From.Volume.uLeft)  >> AUDIOMIXBUF_VOL_SHIFT; \
+            paDst->i64RSample = ASMMult2xS32RetS64((int32_t)audioMixBufClipFrom##_aName(*pSrc), pOpts->From.Volume.uRight) >> AUDIOMIXBUF_VOL_SHIFT; \
+            pSrc++; \
             paDst++; \
         } \
         \
         return cSamples; \
     } \
     \
-    AUDMIXBUF_MACRO_FN void audioMixBufConvTo##_aName##Stereo(void *pvDst, const PPDMAUDIOSAMPLE paSrc, \
-                                                              const PAUDMIXBUF_CONVOPTS pOpts) \
+    DECLCALLBACK(void) audioMixBufConvTo##_aName##Stereo(void *pvDst, PCPDMAUDIOSAMPLE paSrc, PCPDMAUDMIXBUFCONVOPTS pOpts) \
     { \
-        PPDMAUDIOSAMPLE pSrc = paSrc; \
+        PCPDMAUDIOSAMPLE pSrc = paSrc; \
         _aType *pDst = (_aType *)pvDst; \
         _aType l, r; \
         uint32_t cSamples = pOpts->cSamples; \
@@ -505,10 +519,9 @@ static int audioMixBufAlloc(PPDMAUDIOMIXBUF pMixBuf, uint32_t cSamples)
         } \
     } \
     \
-    AUDMIXBUF_MACRO_FN void audioMixBufConvTo##_aName##Mono(void *pvDst, const PPDMAUDIOSAMPLE paSrc, \
-                                                            const PAUDMIXBUF_CONVOPTS pOpts) \
+    DECLCALLBACK(void) audioMixBufConvTo##_aName##Mono(void *pvDst, PCPDMAUDIOSAMPLE paSrc, PCPDMAUDMIXBUFCONVOPTS pOpts) \
     { \
-        PPDMAUDIOSAMPLE pSrc = paSrc; \
+        PCPDMAUDIOSAMPLE pSrc = paSrc; \
         _aType *pDst = (_aType *)pvDst; \
         uint32_t cSamples = pOpts->cSamples; \
         while (cSamples--) \
@@ -534,16 +547,15 @@ AUDMIXBUF_CONVERT(U32 /* Name */, uint32_t, 0         /* Min */, UINT32_MAX /* M
 #undef AUDMIXBUF_CONVERT
 
 #define AUDMIXBUF_MIXOP(_aName, _aOp) \
-    AUDMIXBUF_MACRO_FN void audioMixBufOp##_aName(PPDMAUDIOSAMPLE paDst, uint32_t cDstSamples, \
-                                                  PPDMAUDIOSAMPLE paSrc, uint32_t cSrcSamples, \
-                                                  PPDMAUDIOSTRMRATE pRate, \
-                                                  uint32_t *pcDstWritten, uint32_t *pcSrcRead) \
+    static void audioMixBufOp##_aName(PPDMAUDIOSAMPLE paDst, uint32_t cDstSamples, \
+                                      PPDMAUDIOSAMPLE paSrc, uint32_t cSrcSamples, \
+                                      PPDMAUDIOSTRMRATE pRate, \
+                                      uint32_t *pcDstWritten, uint32_t *pcSrcRead) \
     { \
         AUDMIXBUF_MACRO_LOG(("cSrcSamples=%RU32, cDstSamples=%RU32\n", cSrcSamples, cDstSamples)); \
-        AUDMIXBUF_MACRO_LOG(("pRate=%p: srcOffset=0x%RX32 (%RU32), dstOffset=0x%RX32 (%RU32), dstInc=0x%RX64 (%RU64)\n", \
-                             pRate, pRate->srcOffset, pRate->srcOffset, \
-                             (uint32_t)(pRate->dstOffset >> 32), (uint32_t)(pRate->dstOffset >> 32), \
-                             pRate->dstInc, pRate->dstInc)); \
+        AUDMIXBUF_MACRO_LOG(("Rate: srcOffset=%RU32, dstOffset=%RU32, dstInc=%RU32\n", \
+                             pRate->srcOffset, \
+                             (uint32_t)(pRate->dstOffset >> 32), (uint32_t)(pRate->dstInc >> 32))); \
         \
         if (pRate->dstInc == (UINT64_C(1) + UINT32_MAX)) /* No conversion needed? */ \
         { \
@@ -566,28 +578,22 @@ AUDMIXBUF_CONVERT(U32 /* Name */, uint32_t, 0         /* Min */, UINT32_MAX /* M
         PPDMAUDIOSAMPLE paSrcEnd   = paSrc + cSrcSamples; \
         PPDMAUDIOSAMPLE paDstStart = paDst; \
         PPDMAUDIOSAMPLE paDstEnd   = paDst + cDstSamples; \
-        PDMAUDIOSAMPLE  samCur = { 0 }; \
+        PDMAUDIOSAMPLE  samCur     = { 0 }; \
         PDMAUDIOSAMPLE  samOut; \
         PDMAUDIOSAMPLE  samLast    = pRate->srcSampleLast; \
-        uint64_t        lDelta = 0; \
-        \
-        AUDMIXBUF_MACRO_LOG(("Start: paDstEnd=%p - paDstStart=%p -> %zu\n", paDstEnd, paDst, paDstEnd - paDstStart)); \
-        AUDMIXBUF_MACRO_LOG(("Start: paSrcEnd=%p - paSrcStart=%p -> %zu\n", paSrcEnd, paSrc, paSrcEnd - paSrcStart)); \
         \
         while (paDst < paDstEnd) \
         { \
             Assert(paSrc <= paSrcEnd); \
             Assert(paDst <= paDstEnd); \
-            if (paSrc == paSrcEnd) \
+            if (paSrc >= paSrcEnd) \
                 break; \
             \
-            lDelta = 0; \
             while (pRate->srcOffset <= (pRate->dstOffset >> 32)) \
             { \
                 Assert(paSrc <= paSrcEnd); \
                 samLast = *paSrc++; \
                 pRate->srcOffset++; \
-                lDelta++; \
                 if (paSrc == paSrcEnd) \
                     break; \
             } \
@@ -607,25 +613,24 @@ AUDMIXBUF_CONVERT(U32 /* Name */, uint32_t, 0         /* Min */, UINT32_MAX /* M
             paDst->i64LSample _aOp samOut.i64LSample; \
             paDst->i64RSample _aOp samOut.i64RSample; \
             \
-            AUDMIXBUF_MACRO_LOG(("\tlDelta=0x%RX64 (%RU64), iDstOffInt=0x%RX64 (%RI64), l=%RI64, r=%RI64 (cur l=%RI64, r=%RI64)\n", \
-                                 lDelta, lDelta, iDstOffInt, iDstOffInt, \
-                                 paDst->i64LSample, paDst->i64RSample, \
-                                 samCur.i64LSample, samCur.i64RSample)); \
+            AUDMIXBUF_MACRO_LOG(("\tiDstOffInt=%RI64, l=%RI64, r=%RI64 (cur l=%RI64, r=%RI64)\n", \
+                                 iDstOffInt, \
+                                 paDst->i64LSample >> 32, paDst->i64RSample >> 32, \
+                                 samCur.i64LSample >> 32, samCur.i64RSample >> 32)); \
             \
             paDst++; \
             pRate->dstOffset += pRate->dstInc; \
             \
-            AUDMIXBUF_MACRO_LOG(("\t\tpRate->dstOffset=0x%RX32 (%RU32)\n", pRate->dstOffset, pRate->dstOffset >> 32)); \
+            AUDMIXBUF_MACRO_LOG(("\t\tpRate->dstOffset=%RU32\n", pRate->dstOffset >> 32)); \
             \
         } \
         \
-        AUDMIXBUF_MACRO_LOG(("End: paDst=%p - paDstStart=%p -> %zu\n", paDst, paDstStart, paDst - paDstStart)); \
-        AUDMIXBUF_MACRO_LOG(("End: paSrc=%p - paSrcStart=%p -> %zu\n", paSrc, paSrcStart, paSrc - paSrcStart)); \
+        AUDMIXBUF_MACRO_LOG(("%zu source samples -> %zu dest samples\n", paSrc - paSrcStart, paDst - paDstStart)); \
         \
         pRate->srcSampleLast = samLast; \
         \
-        AUDMIXBUF_MACRO_LOG(("pRate->srcSampleLast l=%RI64, r=%RI64, lDelta=0x%RX64 (%RU64)\n", \
-                              pRate->srcSampleLast.i64LSample, pRate->srcSampleLast.i64RSample, lDelta, lDelta)); \
+        AUDMIXBUF_MACRO_LOG(("pRate->srcSampleLast l=%RI64, r=%RI64\n", \
+                              pRate->srcSampleLast.i64LSample, pRate->srcSampleLast.i64RSample)); \
         \
         if (pcDstWritten) \
             *pcDstWritten = paDst - paDstStart; \
@@ -633,23 +638,24 @@ AUDMIXBUF_CONVERT(U32 /* Name */, uint32_t, 0         /* Min */, UINT32_MAX /* M
             *pcSrcRead = paSrc - paSrcStart; \
     }
 
-#if 0 // unused
 /* audioMixBufOpAssign: Assigns values from source buffer to destination bufffer, overwriting the destination. */
 AUDMIXBUF_MIXOP(Assign /* Name */,  = /* Operation */)
-#endif
+#if 0 /* unused */
 /* audioMixBufOpBlend: Blends together the values from both, the source and the destination buffer. */
 AUDMIXBUF_MIXOP(Blend  /* Name */, += /* Operation */)
+#endif
 
 #undef AUDMIXBUF_MIXOP
 #undef AUDMIXBUF_MACRO_LOG
 
 /** Dummy conversion used when the source is muted. */
-AUDMIXBUF_MACRO_FN uint32_t audioMixBufConvFromSilence(PPDMAUDIOSAMPLE paDst, const void *pvSrc,
-                                                       uint32_t cbSrc, const PAUDMIXBUF_CONVOPTS pOpts)
+static DECLCALLBACK(uint32_t)
+audioMixBufConvFromSilence(PPDMAUDIOSAMPLE paDst, const void *pvSrc, uint32_t cbSrc, PCPDMAUDMIXBUFCONVOPTS pOpts)
 {
     RT_NOREF(cbSrc, pvSrc);
+
     /* Internally zero always corresponds to silence. */
-    memset(paDst, 0, pOpts->cSamples * sizeof(paDst[0]));
+    RT_BZERO(paDst, pOpts->cSamples * sizeof(paDst[0]));
     return pOpts->cSamples;
 }
 
@@ -661,13 +667,9 @@ AUDMIXBUF_MACRO_FN uint32_t audioMixBufConvFromSilence(PPDMAUDIOSAMPLE paDst, co
  *
  * @return  PAUDMIXBUF_FN_CONVFROM  Function pointer to conversion macro if found, NULL if not supported.
  * @param   enmFmt                  Audio format to lookup conversion macro for.
- * @param   fMuted                  Flag determining whether the source is muted.
  */
-static inline PAUDMIXBUF_FN_CONVFROM audioMixBufConvFromLookup(PDMAUDIOMIXBUFFMT enmFmt, bool fMuted)
+static PFNPDMAUDIOMIXBUFCONVFROM audioMixBufConvFromLookup(PDMAUDIOMIXBUFFMT enmFmt)
 {
-    if (fMuted)
-        return audioMixBufConvFromSilence;
-
     if (AUDMIXBUF_FMT_SIGNED(enmFmt))
     {
         if (AUDMIXBUF_FMT_CHANNELS(enmFmt) == 2)
@@ -680,7 +682,7 @@ static inline PAUDMIXBUF_FN_CONVFROM audioMixBufConvFromLookup(PDMAUDIOMIXBUFFMT
                 default: return NULL;
             }
         }
-        else if (AUDMIXBUF_FMT_CHANNELS(enmFmt) == 1)
+        else
         {
             switch (AUDMIXBUF_FMT_BITS_PER_SAMPLE(enmFmt))
             {
@@ -703,7 +705,7 @@ static inline PAUDMIXBUF_FN_CONVFROM audioMixBufConvFromLookup(PDMAUDIOMIXBUFFMT
                 default: return NULL;
             }
         }
-        else if (AUDMIXBUF_FMT_CHANNELS(enmFmt) == 1)
+        else
         {
             switch (AUDMIXBUF_FMT_BITS_PER_SAMPLE(enmFmt))
             {
@@ -714,8 +716,7 @@ static inline PAUDMIXBUF_FN_CONVFROM audioMixBufConvFromLookup(PDMAUDIOMIXBUFFMT
             }
         }
     }
-
-    return NULL;
+    /* not reached */
 }
 
 /**
@@ -727,7 +728,7 @@ static inline PAUDMIXBUF_FN_CONVFROM audioMixBufConvFromLookup(PDMAUDIOMIXBUFFMT
  * @return  PAUDMIXBUF_FN_CONVTO    Function pointer to conversion macro if found, NULL if not supported.
  * @param   enmFmt                  Audio format to lookup conversion macro for.
  */
-static inline PAUDMIXBUF_FN_CONVTO audioMixBufConvToLookup(PDMAUDIOMIXBUFFMT enmFmt)
+static PFNPDMAUDIOMIXBUFCONVTO audioMixBufConvToLookup(PDMAUDIOMIXBUFFMT enmFmt)
 {
     if (AUDMIXBUF_FMT_SIGNED(enmFmt))
     {
@@ -741,7 +742,7 @@ static inline PAUDMIXBUF_FN_CONVTO audioMixBufConvToLookup(PDMAUDIOMIXBUFFMT enm
                 default: return NULL;
             }
         }
-        else if (AUDMIXBUF_FMT_CHANNELS(enmFmt) == 1)
+        else
         {
             switch (AUDMIXBUF_FMT_BITS_PER_SAMPLE(enmFmt))
             {
@@ -764,7 +765,7 @@ static inline PAUDMIXBUF_FN_CONVTO audioMixBufConvToLookup(PDMAUDIOMIXBUFFMT enm
                 default: return NULL;
             }
         }
-        else if (AUDMIXBUF_FMT_CHANNELS(enmFmt) == 1)
+        else
         {
             switch (AUDMIXBUF_FMT_BITS_PER_SAMPLE(enmFmt))
             {
@@ -775,8 +776,31 @@ static inline PAUDMIXBUF_FN_CONVTO audioMixBufConvToLookup(PDMAUDIOMIXBUFFMT enm
             }
         }
     }
+    /* not reached */
+}
+
+/**
+ * Converts a PDM audio volume to an internal mixing buffer volume.
+ *
+ * @returns IPRT status code.
+ * @param   pVolDst                 Where to store the converted mixing buffer volume.
+ * @param   pVolSrc                 Volume to convert.
+ */
+static int audioMixBufConvVol(PPDMAUDMIXBUFVOL pVolDst, PPDMAUDIOVOLUME pVolSrc)
+{
+    if (!pVolSrc->fMuted) /* Only change/convert the volume value if we're not muted. */
+    {
+        uint8_t uVolL = pVolSrc->uLeft  & 0xFF;
+        uint8_t uVolR = pVolSrc->uRight & 0xFF;
+
+        /** @todo Ensure that the input is in the correct range/initialized! */
+        pVolDst->uLeft  = s_aVolumeConv[uVolL] * (AUDIOMIXBUF_VOL_0DB >> 16);
+        pVolDst->uRight = s_aVolumeConv[uVolR] * (AUDIOMIXBUF_VOL_0DB >> 16);
+    }
+
+    pVolDst->fMuted = pVolSrc->fMuted;
 
-    return NULL;
+    return VINF_SUCCESS;
 }
 
 /**
@@ -788,21 +812,24 @@ static inline PAUDMIXBUF_FN_CONVTO audioMixBufConvToLookup(PDMAUDIOMIXBUFFMT enm
  * @param   pProps                  PCM audio properties to use for the mixing buffer.
  * @param   cSamples                Maximum number of audio samples the mixing buffer can hold.
  */
-int AudioMixBufInit(PPDMAUDIOMIXBUF pMixBuf, const char *pszName, PPDMPCMPROPS pProps, uint32_t cSamples)
+int AudioMixBufInit(PPDMAUDIOMIXBUF pMixBuf, const char *pszName, PPDMAUDIOPCMPROPS pProps, uint32_t cSamples)
 {
     AssertPtrReturn(pMixBuf, VERR_INVALID_POINTER);
     AssertPtrReturn(pszName, VERR_INVALID_POINTER);
     AssertPtrReturn(pProps,  VERR_INVALID_POINTER);
 
     pMixBuf->pParent = NULL;
-    RTListInit(&pMixBuf->lstBuffers);
+
+    RTListInit(&pMixBuf->lstChildren);
+    pMixBuf->cChildren = 0;
 
     pMixBuf->pSamples = NULL;
     pMixBuf->cSamples = 0;
 
-    pMixBuf->offReadWrite = 0;
-    pMixBuf->cMixed       = 0;
-    pMixBuf->cProcessed   = 0;
+    pMixBuf->offRead  = 0;
+    pMixBuf->offWrite = 0;
+    pMixBuf->cMixed   = 0;
+    pMixBuf->cUsed    = 0;
 
     /* Set initial volume to max. */
     pMixBuf->Volume.fMuted = false;
@@ -819,6 +846,10 @@ int AudioMixBufInit(PPDMAUDIOMIXBUF pMixBuf, const char *pszName, PPDMPCMPROPS p
                                                  pProps->cChannels,
                                                  pProps->cBits,
                                                  pProps->fSigned);
+
+    pMixBuf->pfnConvFrom = audioMixBufConvFromLookup(pMixBuf->AudioFmt);
+    pMixBuf->pfnConvTo   = audioMixBufConvToLookup(pMixBuf->AudioFmt);
+
     pMixBuf->cShift = pProps->cShift;
     pMixBuf->pszName = RTStrDup(pszName);
     if (!pMixBuf->pszName)
@@ -835,10 +866,10 @@ int AudioMixBufInit(PPDMAUDIOMIXBUF pMixBuf, const char *pszName, PPDMPCMPROPS p
 }
 
 /**
- * Returns @true if there are any audio samples available for processing,
- * @false if not.
+ * Returns @c true if there are any audio samples available for processing,
+ * @c false if not.
  *
- * @return  bool                    @true if there are any audio samples available for processing, @false if not.
+ * @return  bool                    @c true if there are any audio samples available for processing, @c false if not.
  * @param   pMixBuf                 Mixing buffer to return value for.
  */
 bool AudioMixBufIsEmpty(PPDMAUDIOMIXBUF pMixBuf)
@@ -847,7 +878,25 @@ bool AudioMixBufIsEmpty(PPDMAUDIOMIXBUF pMixBuf)
 
     if (pMixBuf->pParent)
         return (pMixBuf->cMixed == 0);
-    return (pMixBuf->cProcessed == 0);
+    return (pMixBuf->cUsed == 0);
+}
+
+/**
+ * Calculates the frequency (sample rate) ratio of mixing buffer A in relation to mixing buffer B.
+ *
+ * @returns Calculated frequency ratio.
+ * @param   pMixBufA            First mixing buffer.
+ * @param   pMixBufB            Second mixing buffer.
+ */
+static int64_t audioMixBufCalcFreqRatio(PPDMAUDIOMIXBUF pMixBufA, PPDMAUDIOMIXBUF pMixBufB)
+{
+    int64_t iRatio = ((int64_t)AUDMIXBUF_FMT_SAMPLE_FREQ(pMixBufA->AudioFmt) << 32)
+                   /           AUDMIXBUF_FMT_SAMPLE_FREQ(pMixBufB->AudioFmt);
+
+    if (iRatio == 0)      /* Catch division by zero. */
+        iRatio = 1 << 20; /* Do a 1:1 conversion instead. */
+
+    return iRatio;
 }
 
 /**
@@ -862,7 +911,7 @@ bool AudioMixBufIsEmpty(PPDMAUDIOMIXBUF pMixBuf)
  * device emulation owns the child/children.
  *
  * The audio format of each mixing buffer can vary; the internal mixing code
- * then will autiomatically do the (needed) conversion.
+ * then will automatically do the (needed) conversion.
  *
  * @return  IPRT status code.
  * @param   pMixBuf                 Mixing buffer to link parent to.
@@ -884,21 +933,22 @@ int AudioMixBufLinkTo(PPDMAUDIOMIXBUF pMixBuf, PPDMAUDIOMIXBUF pParent)
 
     if (pMixBuf->pParent) /* Already linked? */
     {
-        AUDMIXBUF_LOG(("%s: Already linked to \"%s\"\n",
+        AUDMIXBUF_LOG(("%s: Already linked to parent '%s'\n",
                        pMixBuf->pszName, pMixBuf->pParent->pszName));
         return VERR_ACCESS_DENIED;
     }
 
-    RTListAppend(&pParent->lstBuffers, &pMixBuf->Node);
-    pMixBuf->pParent = pParent;
+    RTListAppend(&pParent->lstChildren, &pMixBuf->Node);
+    pParent->cChildren++;
 
-    /* Calculate the frequency ratio. */
-    pMixBuf->iFreqRatio = ((int64_t)AUDMIXBUF_FMT_SAMPLE_FREQ(pParent->AudioFmt) << 32)
-                        /           AUDMIXBUF_FMT_SAMPLE_FREQ(pMixBuf->AudioFmt);
+    /* Set the parent. */
+    pMixBuf->pParent = pParent;
 
-    if (pMixBuf->iFreqRatio == 0) /* Catch division by zero. */
-        pMixBuf->iFreqRatio = 1 << 20; /* Do a 1:1 conversion instead. */
+    /* Calculate the frequency ratios. */
+    pMixBuf->iFreqRatio = audioMixBufCalcFreqRatio(pParent, pMixBuf);
 
+    int rc = VINF_SUCCESS;
+#if 0
     uint32_t cSamples = (uint32_t)RT_MIN(  ((uint64_t)pParent->cSamples << 32)
                                          / pMixBuf->iFreqRatio, _64K /* 64K samples max. */);
     if (!cSamples)
@@ -926,6 +976,7 @@ int AudioMixBufLinkTo(PPDMAUDIOMIXBUF pMixBuf, PPDMAUDIOMIXBUF pParent)
             RT_BZERO(pMixBuf->pSamples, cbSamples);
         }
     }
+#endif
 
     if (RT_SUCCESS(rc))
     {
@@ -958,222 +1009,414 @@ int AudioMixBufLinkTo(PPDMAUDIOMIXBUF pMixBuf, PPDMAUDIOMIXBUF pParent)
 }
 
 /**
- * Returns the number of audio samples mixed (processed) by
- * the parent mixing buffer.
+ * Returns number of available live samples, that is, samples that
+ * have been written into the mixing buffer but not have been processed yet.
+ *
+ * For a parent buffer, this simply returns the currently used number of samples
+ * in the buffer.
+ *
+ * For a child buffer, this returns the number of samples which have been mixed
+ * to the parent and were not processed by the parent yet.
  *
- * @return  uint32_t                Number of audio samples mixed (processed).
- * @param   pMixBuf                 Mixing buffer to return number from.
+ * @return  uint32_t                Number of live samples available.
+ * @param   pMixBuf                 Mixing buffer to return value for.
  */
-uint32_t AudioMixBufMixed(PPDMAUDIOMIXBUF pMixBuf)
+uint32_t AudioMixBufLive(PPDMAUDIOMIXBUF pMixBuf)
 {
     AssertPtrReturn(pMixBuf, 0);
 
-    AssertMsgReturn(VALID_PTR(pMixBuf->pParent),
-                              ("Buffer is not linked to a parent buffer\n"),
-                              0);
+#ifdef RT_STRICT
+    uint32_t cSamples;
+#endif
+    uint32_t cAvail;
+    if (pMixBuf->pParent) /* Is this a child buffer? */
+    {
+#ifdef RT_STRICT
+        /* Use the sample count from the parent, as
+         * pMixBuf->cMixed specifies the sample count
+         * in parent samples. */
+        cSamples = pMixBuf->pParent->cSamples;
+#endif
+        cAvail   = pMixBuf->cMixed;
+    }
+    else
+    {
+#ifdef RT_STRICT
+        cSamples = pMixBuf->cSamples;
+#endif
+        cAvail   = pMixBuf->cUsed;
+    }
 
-    AUDMIXBUF_LOG(("%s: cMixed=%RU32\n", pMixBuf->pszName, pMixBuf->cMixed));
-    return pMixBuf->cMixed;
+    Assert(cAvail <= cSamples);
+    return cAvail;
 }
 
 /**
  * Mixes audio samples from a source mixing buffer to a destination mixing buffer.
  *
  * @return  IPRT status code.
+ *          VERR_BUFFER_UNDERFLOW if the source did not have enough audio data.
+ *          VERR_BUFFER_OVERFLOW if the destination did not have enough space to store the converted source audio data.
+ *
  * @param   pDst                    Destination mixing buffer.
  * @param   pSrc                    Source mixing buffer.
- * @param   cSamples                Number of source audio samples to mix.
- * @param   pcProcessed             Number of audio samples successfully mixed.
+ * @param   cSrcOff                 Offset of source audio samples to mix.
+ * @param   cSrcSamples             Number of source audio samples to mix.
+ * @param   pcSrcMixed              Number of source audio samples successfully mixed. Optional.
  */
-static int audioMixBufMixTo(PPDMAUDIOMIXBUF pDst, PPDMAUDIOMIXBUF pSrc, uint32_t cSamples, uint32_t *pcProcessed)
+static int audioMixBufMixTo(PPDMAUDIOMIXBUF pDst, PPDMAUDIOMIXBUF pSrc, uint32_t cSrcOff, uint32_t cSrcSamples,
+                            uint32_t *pcSrcMixed)
 {
-    AssertPtrReturn(pDst, VERR_INVALID_POINTER);
-    AssertPtrReturn(pSrc, VERR_INVALID_POINTER);
-    AssertReturn(cSamples, VERR_INVALID_PARAMETER);
-    /* pcProcessed is optional. */
+    AssertPtrReturn(pDst,  VERR_INVALID_POINTER);
+    AssertPtrReturn(pSrc,  VERR_INVALID_POINTER);
+    /* pcSrcMixed is optional. */
+
+    AssertMsgReturn(pDst == pSrc->pParent, ("Source buffer '%s' is not a child of destination '%s'\n",
+                                            pSrc->pszName, pDst->pszName), VERR_INVALID_PARAMETER);
+    uint32_t cReadTotal    = 0;
+    uint32_t cWrittenTotal = 0;
 
-    /* Live samples indicate how many samples there are in the source buffer
-     * which have not been processed yet by the destination buffer. */
-    uint32_t cLive = pSrc->cMixed;
-    if (cLive >= pDst->cSamples)
-        AUDMIXBUF_LOG(("Destination buffer \"%s\" full (%RU32 samples max), live samples = %RU32\n",
-                       pDst->pszName, pDst->cSamples, cLive));
+    Assert(pSrc->cMixed <= pDst->cSamples);
 
-    /* Dead samples are the number of samples in the destination buffer which
-     * will not be needed, that is, are not needed in order to process the live
-     * samples of the source buffer. */
-    uint32_t cDead = pDst->cSamples - cLive;
+    Assert(pSrc->cUsed >= pDst->cMixed);
+    Assert(pDst->cUsed <= pDst->cSamples);
 
-    uint32_t cToReadTotal = (uint32_t)RT_MIN(cSamples, AUDIOMIXBUF_S2S_RATIO(pSrc, cDead));
-    uint32_t offRead = 0;
+    uint32_t offSrcRead  = cSrcOff;
 
-    uint32_t cReadTotal = 0;
-    uint32_t cWrittenTotal = 0;
-    uint32_t offWrite = (pDst->offReadWrite + cLive) % pDst->cSamples;
+    uint32_t offDstWrite = pDst->offWrite;
+    uint32_t cDstMixed   = pSrc->cMixed;
+
+    uint32_t cSrcAvail   = RT_MIN(cSrcSamples, pSrc->cUsed);
+    uint32_t cDstAvail   = pDst->cSamples - pDst->cUsed; /** @todo Use pDst->cMixed later? */
+
+    AUDMIXBUF_LOG(("%s (%RU32 available) -> %s (%RU32 available)\n",
+                   pSrc->pszName, cSrcAvail, pDst->pszName, cDstAvail));
+#ifdef DEBUG
+    audioMixBufDbgPrintInternal(pDst, __FUNCTION__);
+#endif
 
-    AUDMIXBUF_LOG(("pSrc=%s (%RU32 samples), pDst=%s (%RU32 samples), cLive=%RU32, cDead=%RU32, cToReadTotal=%RU32, offWrite=%RU32\n",
-                   pSrc->pszName, pSrc->cSamples, pDst->pszName, pDst->cSamples, cLive, cDead, cToReadTotal, offWrite));
+    if (!cSrcAvail)
+        return VERR_BUFFER_UNDERFLOW;
 
-    uint32_t cToRead, cToWrite;
-    uint32_t cWritten, cRead;
+    if (!cDstAvail)
+        return VERR_BUFFER_OVERFLOW;
+
+    uint32_t cSrcToRead = 0;
+    uint32_t cSrcRead;
+
+    uint32_t cDstToWrite;
+    uint32_t cDstWritten;
 
-    while (cToReadTotal)
+    int rc = VINF_SUCCESS;
+
+    while (cSrcAvail && cDstAvail)
     {
-        cDead = pDst->cSamples - cLive;
+        cSrcToRead  = RT_MIN(cSrcAvail, pSrc->cSamples - offSrcRead);
+        cDstToWrite = RT_MIN(cDstAvail, pDst->cSamples - offDstWrite);
+
+        AUDMIXBUF_LOG(("\tSource: %RU32 @ %RU32 -> reading %RU32\n", cSrcAvail, offSrcRead, cSrcToRead));
+        AUDMIXBUF_LOG(("\tDest  : %RU32 @ %RU32 -> writing %RU32\n", cDstAvail, offDstWrite, cDstToWrite));
 
-        cToRead  = cToReadTotal;
-        cToWrite = RT_MIN(cDead, pDst->cSamples - offWrite);
-        if (!cToWrite)
+        if (   !cDstToWrite
+            || !cSrcToRead)
         {
-            AUDMIXBUF_LOG(("Warning: Destination buffer \"%s\" full\n", pDst->pszName));
             break;
         }
 
-        Assert(offWrite + cToWrite <= pDst->cSamples);
-        Assert(offRead + cToRead <= pSrc->cSamples);
+        cDstWritten = cSrcRead = 0;
+
+        Assert(offSrcRead < pSrc->cSamples);
+        Assert(offSrcRead + cSrcToRead <= pSrc->cSamples);
+
+        Assert(offDstWrite < pDst->cSamples);
+        Assert(offDstWrite + cDstToWrite <= pDst->cSamples);
+
+        audioMixBufOpAssign(pDst->pSamples + offDstWrite, cDstToWrite,
+                            pSrc->pSamples + offSrcRead,  cSrcToRead,
+                            pSrc->pRate, &cDstWritten, &cSrcRead);
+
+        cReadTotal    += cSrcRead;
+        cWrittenTotal += cDstWritten;
+
+        offSrcRead     = (offSrcRead  + cSrcRead)    % pSrc->cSamples;
+        offDstWrite    = (offDstWrite + cDstWritten) % pDst->cSamples;
+
+        cDstMixed     += cDstWritten;
 
-        AUDMIXBUF_LOG(("\t%RU32Hz -> %RU32Hz\n", AUDMIXBUF_FMT_SAMPLE_FREQ(pSrc->AudioFmt), AUDMIXBUF_FMT_SAMPLE_FREQ(pDst->AudioFmt)));
-        AUDMIXBUF_LOG(("\tcDead=%RU32, offWrite=%RU32, cToWrite=%RU32, offRead=%RU32, cToRead=%RU32\n",
-                       cDead, offWrite, cToWrite, offRead, cToRead));
+        Assert(cSrcAvail >= cSrcRead);
+        cSrcAvail        -= cSrcRead;
 
-        audioMixBufOpBlend(pDst->pSamples + offWrite, cToWrite,
-                           pSrc->pSamples + offRead, cToRead,
-                           pSrc->pRate, &cWritten, &cRead);
+        Assert(cDstAvail >= cDstWritten);
+        cDstAvail        -= cDstWritten;
 
-        AUDMIXBUF_LOG(("\t\tcWritten=%RU32, cRead=%RU32\n", cWritten, cRead));
+        AUDMIXBUF_LOG(("\t%RU32 read (%RU32 left @ %RU32), %RU32 written (%RU32 left @ %RU32)\n",
+                       cSrcRead, cSrcAvail, offSrcRead,
+                       cDstWritten, cDstAvail, offDstWrite));
+    }
+
+    pSrc->offRead     = offSrcRead;
+    Assert(pSrc->cUsed >= cReadTotal);
+    pSrc->cUsed      -= RT_MIN(pSrc->cUsed, cReadTotal);
 
-        cReadTotal    += cRead;
-        cWrittenTotal += cWritten;
+    /* Note: Always count in parent samples, as the rate can differ! */
+    pSrc->cMixed      = RT_MIN(cDstMixed, pDst->cSamples);
 
-        offRead += cRead;
-        Assert(cToReadTotal >= cRead);
-        cToReadTotal -= cRead;
+    pDst->offWrite    = offDstWrite;
+    Assert(pDst->offWrite <= pDst->cSamples);
+    Assert((pDst->cUsed + cWrittenTotal) <= pDst->cSamples);
+    pDst->cUsed      += cWrittenTotal;
 
-        offWrite = (offWrite + cWritten) % pDst->cSamples;
+    /* If there are more used samples than fitting in the destination buffer,
+     * adjust the values accordingly.
+     *
+     * This can happen if this routine has been called too often without
+     * actually processing the destination buffer in between. */
+    if (pDst->cUsed > pDst->cSamples)
+    {
+        LogFunc(("%s: Warning: Destination buffer used %RU32 / %RU32 samples\n", pDst->pszName, pDst->cUsed, pDst->cSamples));
+        pDst->offWrite     = 0;
+        pDst->cUsed        = pDst->cSamples;
 
-        cLive += cWritten;
+        rc = VERR_BUFFER_OVERFLOW;
     }
 
-    pSrc->cMixed     += cWrittenTotal;
-    pDst->cProcessed += cWrittenTotal;
 #ifdef DEBUG
-    s_cSamplesMixedTotal += cWrittenTotal;
-    audioMixBufPrint(pDst);
+    audioMixBufDbgValidate(pSrc);
+    audioMixBufDbgValidate(pDst);
+
+    Assert(pSrc->cMixed <= pDst->cSamples);
 #endif
 
-    if (pcProcessed)
-        *pcProcessed = cReadTotal;
+#ifdef AUDIOMIXBUF_DEBUG_DUMP_PCM_DATA
+    uint32_t offRead = pDst->offRead;
 
-    AUDMIXBUF_LOG(("cReadTotal=%RU32 (pcProcessed), cWrittenTotal=%RU32, cSrcMixed=%RU32, cDstProc=%RU32\n",
-                   cReadTotal, cWrittenTotal, pSrc->cMixed, pDst->cProcessed));
-    return VINF_SUCCESS;
+    uint32_t cLeft = cWrittenTotal;
+    while (cLeft)
+    {
+        uint8_t auBuf[256];
+        RT_ZERO(auBuf);
+
+        Assert(sizeof(auBuf) >= 4);
+        Assert(sizeof(auBuf) % 4 == 0);
+
+        uint32_t cToRead = RT_MIN(AUDIOMIXBUF_B2S(pDst, sizeof(auBuf)), RT_MIN(cLeft, pDst->cSamples - offRead));
+        Assert(cToRead <= pDst->cUsed);
+
+        PDMAUDMIXBUFCONVOPTS convOpts;
+        RT_ZERO(convOpts);
+        convOpts.cSamples = cToRead;
+
+        pDst->pfnConvTo(auBuf, pDst->pSamples + offRead, &convOpts);
+
+        RTFILE fh;
+        int rc2 = RTFileOpen(&fh, AUDIOMIXBUF_DEBUG_DUMP_PCM_DATA_PATH "mixbuf_mixto.pcm",
+                             RTFILE_O_OPEN_CREATE | RTFILE_O_APPEND | RTFILE_O_WRITE | RTFILE_O_DENY_NONE);
+        if (RT_SUCCESS(rc2))
+        {
+            RTFileWrite(fh, auBuf, AUDIOMIXBUF_S2B(pDst, cToRead), NULL);
+            RTFileClose(fh);
+        }
+
+        offRead  = (offRead + cToRead) % pDst->cSamples;
+        cLeft   -= cToRead;
+    }
+#endif /* AUDIOMIXBUF_DEBUG_DUMP_PCM_DATA */
+
+#ifdef DEBUG
+    audioMixBufDbgPrintInternal(pDst, __FUNCTION__);
+#endif
+
+    if (pcSrcMixed)
+        *pcSrcMixed = cReadTotal;
+
+    AUDMIXBUF_LOG(("cReadTotal=%RU32, cWrittenTotal=%RU32, cSrcMixed=%RU32, cDstUsed=%RU32, rc=%Rrc\n",
+                   cReadTotal, cWrittenTotal, pSrc->cMixed, pDst->cUsed, rc));
+    return rc;
 }
 
 /**
- * Mixes (multiplexes) audio samples to all connected mixing buffer children.
+ * Mixes audio samples down to the parent mixing buffer, extended version.
+ *
+ * @return  IPRT status code. See audioMixBufMixTo() for a more detailed explanation.
+ * @param   pMixBuf                 Source mixing buffer to mix to its parent.
+ * @param   cSrcOffset              Offset (in samples) of source mixing buffer.
+ * @param   cSrcSamples             Number of source audio samples to mix to its parent.
+ * @param   pcSrcMixed              Number of source audio samples successfully mixed. Optional.
+ */
+int AudioMixBufMixToParentEx(PPDMAUDIOMIXBUF pMixBuf, uint32_t cSrcOffset, uint32_t cSrcSamples, uint32_t *pcSrcMixed)
+{
+    AssertMsgReturn(VALID_PTR(pMixBuf->pParent),
+                    ("Buffer is not linked to a parent buffer\n"),
+                    VERR_INVALID_PARAMETER);
+
+    return audioMixBufMixTo(pMixBuf->pParent, pMixBuf, cSrcOffset, cSrcSamples, pcSrcMixed);
+}
+
+/**
+ * Mixes audio samples down to the parent mixing buffer.
+ *
+ * @return  IPRT status code. See audioMixBufMixTo() for a more detailed explanation.
+ * @param   pMixBuf                 Source mixing buffer to mix to its parent.
+ * @param   cSrcSamples             Number of source audio samples to mix to its parent.
+ * @param   pcSrcMixed              Number of source audio samples successfully mixed. Optional.
+ */
+int AudioMixBufMixToParent(PPDMAUDIOMIXBUF pMixBuf, uint32_t cSrcSamples, uint32_t *pcSrcMixed)
+{
+    return audioMixBufMixTo(pMixBuf->pParent, pMixBuf, pMixBuf->offRead, cSrcSamples, pcSrcMixed);
+}
+
+#ifdef DEBUG
+/**
+ * Prints a single mixing buffer.
+ * Internal helper function for debugging. Do not use directly.
  *
  * @return  IPRT status code.
- * @param   pMixBuf                 Mixing buffer to use.
- * @param   cSamples                Number of audio samples to mix to children.
- * @param   pcProcessed             Maximum number of audio samples successfully mixed
- *                                  to all children. Optional.
+ * @param   pMixBuf                 Mixing buffer to print.
+ * @param   pszFunc                 Function name to log this for.
+ * @param   fIsParent               Whether this is a parent buffer or not.
+ * @param   uIdtLvl                 Indention level to use.
  */
-int AudioMixBufMixToChildren(PPDMAUDIOMIXBUF pMixBuf, uint32_t cSamples,
-                             uint32_t *pcProcessed)
+DECL_FORCE_INLINE(void) audioMixBufDbgPrintSingle(PPDMAUDIOMIXBUF pMixBuf, const char *pszFunc, bool fIsParent, uint16_t uIdtLvl)
 {
-    AssertPtrReturn(pMixBuf, VERR_INVALID_POINTER);
+    Log(("%s: %*s[%s] %s: offRead=%RU32, offWrite=%RU32, cMixed=%RU32 -> %RU32/%RU32\n",
+         pszFunc, uIdtLvl * 4, "", fIsParent ? "PARENT" : "CHILD",
+         pMixBuf->pszName, pMixBuf->offRead, pMixBuf->offWrite, pMixBuf->cMixed, pMixBuf->cUsed, pMixBuf->cSamples));
+}
 
-    if (!cSamples)
-    {
-        if (pcProcessed)
-            *pcProcessed = 0;
-        return VINF_SUCCESS;
-    }
+/**
+ * Validates a single mixing buffer.
+ *
+ * @return  @true if the buffer state is valid or @false if not.
+ * @param   pMixBuf                 Mixing buffer to validate.
+ */
+DECL_FORCE_INLINE(bool) audioMixBufDbgValidate(PPDMAUDIOMIXBUF pMixBuf)
+{
+    //const uint32_t offReadEnd  = (pMixBuf->offRead + pMixBuf->cUsed) % pMixBuf->cSamples;
+    //const uint32_t offWriteEnd = (pMixBuf->offWrite + (pMixBuf->cSamples - pMixBuf->cUsed)) % pMixBuf->cSamples;
 
-    int rc = VINF_SUCCESS;
+    bool fValid = true;
 
-    uint32_t cProcessed;
-    uint32_t cProcessedMax = 0;
+    AssertStmt(pMixBuf->offRead  <= pMixBuf->cSamples, fValid = false);
+    AssertStmt(pMixBuf->offWrite <= pMixBuf->cSamples, fValid = false);
+    AssertStmt(pMixBuf->cUsed    <= pMixBuf->cSamples, fValid = false);
 
-    PPDMAUDIOMIXBUF pIter;
-    RTListForEach(&pMixBuf->lstBuffers, pIter, PDMAUDIOMIXBUF, Node)
+    if (pMixBuf->offWrite > pMixBuf->offRead)
     {
-        rc = audioMixBufMixTo(pIter, pMixBuf, cSamples, &cProcessed);
-        if (RT_FAILURE(rc))
-            break;
-
-        cProcessedMax = RT_MAX(cProcessedMax, cProcessed);
+        if (pMixBuf->offWrite - pMixBuf->offRead != pMixBuf->cUsed)
+            fValid = false;
+    }
+    else if (pMixBuf->offWrite < pMixBuf->offRead)
+    {
+        if (pMixBuf->offWrite + pMixBuf->cSamples - pMixBuf->offRead != pMixBuf->cUsed)
+            fValid = false;
     }
 
-    if (pcProcessed)
-        *pcProcessed = cProcessedMax;
+    if (!fValid)
+    {
+        audioMixBufDbgPrintInternal(pMixBuf, __FUNCTION__);
+        AssertFailed();
+    }
 
-    return rc;
+    return fValid;
 }
 
 /**
- * Mixes audio samples down to the parent mixing buffer.
+ * Internal helper function for audioMixBufPrintChain().
+ * Do not use directly.
  *
  * @return  IPRT status code.
- * @param   pMixBuf                 Mixing buffer to mix samples down to parent.
- * @param   cSamples                Number of audio samples to mix down.
- * @param   pcProcessed             Number of audio samples successfully processed. Optional.
+ * @param   pMixBuf                 Mixing buffer to print.
+ * @param   pszFunc                 Function name to print the chain for.
+ * @param   uIdtLvl                 Indention level to use.
+ * @param   pcChildren              Pointer to children counter.
  */
-int AudioMixBufMixToParent(PPDMAUDIOMIXBUF pMixBuf, uint32_t cSamples,
-                           uint32_t *pcProcessed)
+DECL_FORCE_INLINE(void) audioMixBufDbgPrintChainHelper(PPDMAUDIOMIXBUF pMixBuf, const char *pszFunc, uint16_t uIdtLvl,
+                                                       size_t *pcChildren)
 {
-    AssertMsgReturn(VALID_PTR(pMixBuf->pParent),
-                    ("Buffer is not linked to a parent buffer\n"),
-                    VERR_INVALID_PARAMETER);
+    PPDMAUDIOMIXBUF pIter;
+    RTListForEach(&pMixBuf->lstChildren, pIter, PDMAUDIOMIXBUF, Node)
+    {
+        audioMixBufDbgPrintSingle(pIter, pszFunc, false /* ifIsParent */, uIdtLvl + 1);
+        *pcChildren++;
+    }
+}
+
+DECL_FORCE_INLINE(void) audioMixBufDbgPrintChainInternal(PPDMAUDIOMIXBUF pMixBuf, const char *pszFunc)
+{
+    PPDMAUDIOMIXBUF pParent = pMixBuf->pParent;
+    while (pParent)
+    {
+        if (!pParent->pParent)
+            break;
+
+        pParent = pParent->pParent;
+    }
+
+    if (!pParent)
+        pParent = pMixBuf;
 
-    return audioMixBufMixTo(pMixBuf->pParent, pMixBuf, cSamples, pcProcessed);
+    audioMixBufDbgPrintSingle(pParent, pszFunc, true /* fIsParent */, 0 /* uIdtLvl */);
+
+    /* Recursively iterate children. */
+    size_t cChildren = 0;
+    audioMixBufDbgPrintChainHelper(pParent, pszFunc, 0 /* uIdtLvl */, &cChildren);
+
+    Log(("%s: Children: %zu\n", pszFunc, cChildren));
 }
 
-#ifdef DEBUG
 /**
- * Prints statistics and status of a mixing buffer to the logger.
+ * Prints statistics and status of the full chain of a mixing buffer to the logger,
+ * starting from the top root mixing buffer.
  * For debug versions only.
  *
  * @return  IPRT status code.
  * @param   pMixBuf                 Mixing buffer to print.
  */
-static inline void audioMixBufPrint(PPDMAUDIOMIXBUF pMixBuf)
+void AudioMixBufDbgPrintChain(PPDMAUDIOMIXBUF pMixBuf)
+{
+    audioMixBufDbgPrintChainInternal(pMixBuf, __FUNCTION__);
+}
+
+DECL_FORCE_INLINE(void) audioMixBufDbgPrintInternal(PPDMAUDIOMIXBUF pMixBuf, const char *pszFunc)
 {
     PPDMAUDIOMIXBUF pParent = pMixBuf;
     if (pMixBuf->pParent)
         pParent = pMixBuf->pParent;
 
-    AUDMIXBUF_LOG(("********************************************\n"));
-    AUDMIXBUF_LOG(("%s: offReadWrite=%RU32, cProcessed=%RU32, cMixed=%RU32 (BpS=%RU32)\n",
-                   pParent->pszName,
-                   pParent->offReadWrite, pParent->cProcessed, pParent->cMixed,
-                   AUDIOMIXBUF_S2B(pParent, 1)));
+    audioMixBufDbgPrintSingle(pMixBuf, pszFunc, pParent == pMixBuf /* fIsParent */, 0 /* iIdtLevel */);
 
     PPDMAUDIOMIXBUF pIter;
-    RTListForEach(&pParent->lstBuffers, pIter, PDMAUDIOMIXBUF, Node)
+    RTListForEach(&pMixBuf->lstChildren, pIter, PDMAUDIOMIXBUF, Node)
     {
-        AUDMIXBUF_LOG(("\t%s: offReadWrite=%RU32, cProcessed=%RU32, cMixed=%RU32 (BpS=%RU32)\n",
-                       pIter->pszName,
-                       pIter->offReadWrite, pIter->cProcessed, pIter->cMixed,
-                       AUDIOMIXBUF_S2B(pIter, 1)));
+        if (pIter == pMixBuf)
+            continue;
+        audioMixBufDbgPrintSingle(pIter, pszFunc, false /* fIsParent */, 1 /* iIdtLevel */);
     }
-    AUDMIXBUF_LOG(("Total samples mixed: %RU64\n", s_cSamplesMixedTotal));
-    AUDMIXBUF_LOG(("********************************************\n"));
 }
-#endif
 
 /**
- * Returns the total number of samples processed.
+ * Prints statistics and status of a mixing buffer to the logger.
+ * For debug versions only.
+ *
+ * @return  IPRT status code.
+ * @param   pMixBuf                 Mixing buffer to print.
+ */
+void AudioMixBufDbgPrint(PPDMAUDIOMIXBUF pMixBuf)
+{
+    audioMixBufDbgPrintInternal(pMixBuf, __FUNCTION__);
+}
+#endif /* DEBUG */
+
+/**
+ * Returns the total number of samples used.
  *
  * @return  uint32_t
  * @param   pMixBuf
  */
-uint32_t AudioMixBufProcessed(PPDMAUDIOMIXBUF pMixBuf)
+uint32_t AudioMixBufUsed(PPDMAUDIOMIXBUF pMixBuf)
 {
     AssertPtrReturn(pMixBuf, 0);
-
-    AUDMIXBUF_LOG(("%s: cProcessed=%RU32\n", pMixBuf->pszName, pMixBuf->cProcessed));
-    return pMixBuf->cProcessed;
+    return pMixBuf->cUsed;
 }
 
 /**
@@ -1218,7 +1461,7 @@ int AudioMixBufReadAtEx(PPDMAUDIOMIXBUF pMixBuf, PDMAUDIOMIXBUFFMT enmFmt,
     /* pcbRead is optional. */
 
     uint32_t cDstSamples = pMixBuf->cSamples;
-    uint32_t cLive = pMixBuf->cProcessed;
+    uint32_t cLive = pMixBuf->cUsed;
 
     uint32_t cDead = cDstSamples - cLive;
     uint32_t cToProcess = (uint32_t)AUDIOMIXBUF_S2S_RATIO(pMixBuf, cDead);
@@ -1230,20 +1473,32 @@ int AudioMixBufReadAtEx(PPDMAUDIOMIXBUF pMixBuf, PDMAUDIOMIXBUFFMT enmFmt,
     int rc;
     if (cToProcess)
     {
-        PAUDMIXBUF_FN_CONVTO pConv = audioMixBufConvToLookup(enmFmt);
-        if (pConv)
+        PFNPDMAUDIOMIXBUFCONVTO pfnConvTo = NULL;
+        if (pMixBuf->AudioFmt != enmFmt)
+            pfnConvTo = audioMixBufConvToLookup(enmFmt);
+        else
+            pfnConvTo = pMixBuf->pfnConvTo;
+
+        if (pfnConvTo)
         {
-            AUDMIXBUF_CONVOPTS convOpts = { cToProcess, pMixBuf->Volume };
-            pConv(pvBuf, pMixBuf->pSamples + offSamples, &convOpts);
+            PDMAUDMIXBUFCONVOPTS convOpts;
+            RT_ZERO(convOpts);
+            /* Note: No volume handling/conversion done in the conversion-to macros (yet). */
 
-            rc = VINF_SUCCESS;
-        }
-        else
-            rc = VERR_INVALID_PARAMETER;
+            convOpts.cSamples = cToProcess;
+
+            pfnConvTo(pvBuf, pMixBuf->pSamples + offSamples, &convOpts);
 
 #ifdef DEBUG
-        audioMixBufPrint(pMixBuf);
+            AudioMixBufDbgPrint(pMixBuf);
 #endif
+            rc = VINF_SUCCESS;
+        }
+        else
+        {
+            AssertFailed();
+            rc = VERR_NOT_SUPPORTED;
+        }
     }
     else
         rc = VINF_SUCCESS;
@@ -1267,11 +1522,9 @@ int AudioMixBufReadAtEx(PPDMAUDIOMIXBUF pMixBuf, PDMAUDIOMIXBUFFMT enmFmt,
  * @param   cbBuf                   Size (in bytes) of buffer to write to.
  * @param   pcRead                  Number of audio samples read. Optional.
  */
-int AudioMixBufReadCirc(PPDMAUDIOMIXBUF pMixBuf,
-                        void *pvBuf, uint32_t cbBuf, uint32_t *pcRead)
+int AudioMixBufReadCirc(PPDMAUDIOMIXBUF pMixBuf, void *pvBuf, uint32_t cbBuf, uint32_t *pcRead)
 {
-    return AudioMixBufReadCircEx(pMixBuf, pMixBuf->AudioFmt,
-                                 pvBuf, cbBuf, pcRead);
+    return AudioMixBufReadCircEx(pMixBuf, pMixBuf->AudioFmt, pvBuf, cbBuf, pcRead);
 }
 
 /**
@@ -1286,114 +1539,91 @@ int AudioMixBufReadCirc(PPDMAUDIOMIXBUF pMixBuf,
  * @param   cbBuf                   Size (in bytes) of buffer to write to.
  * @param   pcRead                  Number of audio samples read. Optional.
  */
-int AudioMixBufReadCircEx(PPDMAUDIOMIXBUF pMixBuf, PDMAUDIOMIXBUFFMT enmFmt,
-                          void *pvBuf, uint32_t cbBuf, uint32_t *pcRead)
+int AudioMixBufReadCircEx(PPDMAUDIOMIXBUF pMixBuf, PDMAUDIOMIXBUFFMT enmFmt, void *pvBuf, uint32_t cbBuf, uint32_t *pcRead)
 {
     AssertPtrReturn(pMixBuf, VERR_INVALID_POINTER);
-    AssertPtrReturn(pvBuf, VERR_INVALID_POINTER);
-    /* pcbRead is optional. */
+    AssertReturn(cbBuf,      VERR_INVALID_PARAMETER);
+    AssertPtrReturn(pvBuf,   VERR_INVALID_POINTER);
+    /* pcRead is optional. */
 
-    if (!cbBuf)
-        return VINF_SUCCESS;
+    /* Make sure that we at least have space for a full audio sample. */
+    AssertReturn(AUDIOMIXBUF_B2S(pMixBuf, cbBuf), VERR_INVALID_PARAMETER);
 
-    uint32_t cToRead = RT_MIN(AUDIOMIXBUF_B2S(pMixBuf, cbBuf), pMixBuf->cProcessed);
+    uint32_t cToRead = RT_MIN(pMixBuf->cUsed, AUDIOMIXBUF_B2S(pMixBuf, cbBuf));
 
-    AUDMIXBUF_LOG(("%s: pvBuf=%p, cbBuf=%zu (%RU32 samples), cToRead=%RU32\n",
-                   pMixBuf->pszName, pvBuf, cbBuf, AUDIOMIXBUF_B2S(pMixBuf, cbBuf), cToRead));
+    AUDMIXBUF_LOG(("%s: cbBuf=%RU32 (%RU32 samples), cToRead=%RU32, fmtSrc=0x%x, fmtDst=0x%x\n",
+                   pMixBuf->pszName, cbBuf, AUDIOMIXBUF_B2S(pMixBuf, cbBuf), cToRead, pMixBuf->AudioFmt, enmFmt));
 
     if (!cToRead)
     {
 #ifdef DEBUG
-        audioMixBufPrint(pMixBuf);
+        audioMixBufDbgPrintInternal(pMixBuf, __FUNCTION__);
 #endif
         if (pcRead)
             *pcRead = 0;
         return VINF_SUCCESS;
     }
 
-    PAUDMIXBUF_FN_CONVTO pConv = audioMixBufConvToLookup(enmFmt);
-    if (!pConv) /* Audio format not supported. */
-        return VERR_NOT_SUPPORTED;
-
-    PPDMAUDIOSAMPLE pSamplesSrc1 = pMixBuf->pSamples + pMixBuf->offReadWrite;
-    uint32_t cLenSrc1 = cToRead;
-
-    PPDMAUDIOSAMPLE pSamplesSrc2 = NULL;
-    uint32_t cLenSrc2 = 0;
-
-    uint32_t offRead = pMixBuf->offReadWrite + cToRead;
-
-    /*
-     * Do we need to wrap around to read all requested data, that is,
-     * starting at the beginning of our circular buffer? This then will
-     * be the optional second part to do.
-     */
-    if (offRead >= pMixBuf->cSamples)
-    {
-        Assert(pMixBuf->offReadWrite <= pMixBuf->cSamples);
-        cLenSrc1 = pMixBuf->cSamples - pMixBuf->offReadWrite;
-
-        pSamplesSrc2 = pMixBuf->pSamples;
-        Assert(cToRead >= cLenSrc1);
-        cLenSrc2 = RT_MIN(cToRead - cLenSrc1, pMixBuf->cSamples);
-
-        /* Save new read offset. */
-        offRead = cLenSrc2;
-    }
-
-    AUDMIXBUF_CONVOPTS convOpts;
-    convOpts.Volume = pMixBuf->Volume;
+    PFNPDMAUDIOMIXBUFCONVTO pfnConvTo = NULL;
+    if (pMixBuf->AudioFmt != enmFmt)
+        pfnConvTo = audioMixBufConvToLookup(enmFmt);
+    else
+        pfnConvTo = pMixBuf->pfnConvTo;
 
-    /* Anything to do at all? */
-    int rc = VINF_SUCCESS;
-    if (cLenSrc1)
+    if (!pfnConvTo) /* Audio format not supported. */
     {
-        convOpts.cSamples = cLenSrc1;
-
-        AUDMIXBUF_LOG(("P1: offRead=%RU32, cToRead=%RU32\n", pMixBuf->offReadWrite, cLenSrc1));
-        pConv(pvBuf, pSamplesSrc1, &convOpts);
+        AssertFailed();
+        return VERR_NOT_SUPPORTED;
     }
 
-    /* Second part present? */
-    if (   RT_LIKELY(RT_SUCCESS(rc))
-        && cLenSrc2)
+    cToRead = RT_MIN(cToRead, pMixBuf->cSamples - pMixBuf->offRead);
+    if (cToRead)
     {
-        AssertPtr(pSamplesSrc2);
+        PDMAUDMIXBUFCONVOPTS convOpts;
+        RT_ZERO(convOpts);
+        convOpts.cSamples = cToRead;
 
-        convOpts.cSamples = cLenSrc2;
+        AUDMIXBUF_LOG(("cToRead=%RU32\n", cToRead));
 
-        AUDMIXBUF_LOG(("P2: cToRead=%RU32, offWrite=%RU32 (%zu bytes)\n", cLenSrc2, cLenSrc1,
-                       AUDIOMIXBUF_S2B(pMixBuf, cLenSrc1)));
-        pConv((uint8_t *)pvBuf + AUDIOMIXBUF_S2B(pMixBuf, cLenSrc1), pSamplesSrc2, &convOpts);
-    }
+        pfnConvTo(pvBuf, pMixBuf->pSamples + pMixBuf->offRead, &convOpts);
 
-    if (RT_SUCCESS(rc))
-    {
-#ifdef DEBUG_DUMP_PCM_DATA
+#ifdef AUDIOMIXBUF_DEBUG_DUMP_PCM_DATA
         RTFILE fh;
-        rc = RTFileOpen(&fh, DEBUG_DUMP_PCM_DATA_PATH "mixbuf_readcirc.pcm",
-                        RTFILE_O_OPEN_CREATE | RTFILE_O_APPEND | RTFILE_O_WRITE | RTFILE_O_DENY_NONE);
-        if (RT_SUCCESS(rc))
+        int rc2 = RTFileOpen(&fh, AUDIOMIXBUF_DEBUG_DUMP_PCM_DATA_PATH "mixbuf_readcirc.pcm",
+                             RTFILE_O_OPEN_CREATE | RTFILE_O_APPEND | RTFILE_O_WRITE | RTFILE_O_DENY_NONE);
+        if (RT_SUCCESS(rc2))
         {
-            RTFileWrite(fh, pvBuf, AUDIOMIXBUF_S2B(pMixBuf, cLenSrc1 + cLenSrc2), NULL);
+            RTFileWrite(fh, pvBuf, AUDIOMIXBUF_S2B(pMixBuf, cToRead), NULL);
             RTFileClose(fh);
         }
 #endif
-        pMixBuf->offReadWrite  = offRead % pMixBuf->cSamples;
-        pMixBuf->cProcessed   -= RT_MIN(cLenSrc1 + cLenSrc2, pMixBuf->cProcessed);
-
-        if (pcRead)
-            *pcRead = cLenSrc1 + cLenSrc2;
+        pMixBuf->offRead  = (pMixBuf->offRead + cToRead) % pMixBuf->cSamples;
+        Assert(pMixBuf->cUsed >= cToRead);
+        pMixBuf->cUsed   -= cToRead;
     }
 
+    if (pcRead)
+        *pcRead = cToRead;
+
 #ifdef DEBUG
-    audioMixBufPrint(pMixBuf);
+    audioMixBufDbgValidate(pMixBuf);
 #endif
 
-    AUDMIXBUF_LOG(("cRead=%RU32 (%zu bytes), rc=%Rrc\n",
-                   cLenSrc1 + cLenSrc2,
-                   AUDIOMIXBUF_S2B(pMixBuf, cLenSrc1 + cLenSrc2), rc));
-    return rc;
+    AUDMIXBUF_LOG(("cRead=%RU32 (%RU32 bytes)\n", cToRead, AUDIOMIXBUF_S2B(pMixBuf, cToRead)));
+    return VINF_SUCCESS;
+}
+
+/**
+ * Returns the current read position of a mixing buffer.
+ *
+ * @returns IPRT status code.
+ * @param   pMixBuf                 Mixing buffer to return position for.
+ */
+uint32_t AudioMixBufReadPos(PPDMAUDIOMIXBUF pMixBuf)
+{
+    AssertPtrReturn(pMixBuf, 0);
+
+    return pMixBuf->offRead;
 }
 
 /**
@@ -1407,9 +1637,10 @@ void AudioMixBufReset(PPDMAUDIOMIXBUF pMixBuf)
 
     AUDMIXBUF_LOG(("%s\n", pMixBuf->pszName));
 
-    pMixBuf->offReadWrite = 0;
-    pMixBuf->cMixed       = 0;
-    pMixBuf->cProcessed   = 0;
+    pMixBuf->offRead  = 0;
+    pMixBuf->offWrite = 0;
+    pMixBuf->cMixed   = 0;
+    pMixBuf->cUsed    = 0;
 
     AudioMixBufClear(pMixBuf);
 }
@@ -1425,14 +1656,10 @@ void AudioMixBufSetVolume(PPDMAUDIOMIXBUF pMixBuf, PPDMAUDIOVOLUME pVol)
     AssertPtrReturnVoid(pMixBuf);
     AssertPtrReturnVoid(pVol);
 
-    LogFlowFunc(("%s: lVol=%RU32, rVol=%RU32\n", pMixBuf->pszName, pVol->uLeft, pVol->uRight));
+    LogFlowFunc(("%s: lVol=%RU8, rVol=%RU8, fMuted=%RTbool\n", pMixBuf->pszName, pVol->uLeft, pVol->uRight, pVol->fMuted));
 
-    pMixBuf->Volume.fMuted = pVol->fMuted;
-    /** @todo Ensure that the input is in the correct range/initialized! */
-    pMixBuf->Volume.uLeft  = s_aVolumeConv[pVol->uLeft  & 0xFF] * (AUDIOMIXBUF_VOL_0DB >> 16);
-    pMixBuf->Volume.uRight = s_aVolumeConv[pVol->uRight & 0xFF] * (AUDIOMIXBUF_VOL_0DB >> 16);
-
-    LogFlowFunc(("\t-> lVol=%#RX32, rVol=%#RX32\n", pMixBuf->Volume.uLeft, pMixBuf->Volume.uRight));
+    int rc2 = audioMixBufConvVol(&pMixBuf->Volume /* Dest */, pVol /* Source */);
+    AssertRC(rc2);
 }
 
 /**
@@ -1472,32 +1699,45 @@ void AudioMixBufUnlink(PPDMAUDIOMIXBUF pMixBuf)
 
     AUDMIXBUF_LOG(("%s\n", pMixBuf->pszName));
 
-    if (pMixBuf->pParent)
+    if (pMixBuf->pParent) /* IS this a children buffer? */
     {
         AUDMIXBUF_LOG(("%s: Unlinking from parent \"%s\"\n",
                        pMixBuf->pszName, pMixBuf->pParent->pszName));
 
         RTListNodeRemove(&pMixBuf->Node);
 
+        /* Decrease the paren't children count. */
+        Assert(pMixBuf->pParent->cChildren);
+        pMixBuf->pParent->cChildren--;
+
         /* Make sure to reset the parent mixing buffer each time it gets linked
          * to a new child. */
         AudioMixBufReset(pMixBuf->pParent);
         pMixBuf->pParent = NULL;
     }
 
-    PPDMAUDIOMIXBUF pIter;
-    while (!RTListIsEmpty(&pMixBuf->lstBuffers))
+    PPDMAUDIOMIXBUF pChild, pChildNext;
+    RTListForEachSafe(&pMixBuf->lstChildren, pChild, pChildNext, PDMAUDIOMIXBUF, Node)
     {
-        pIter = RTListGetFirst(&pMixBuf->lstBuffers, PDMAUDIOMIXBUF, Node);
+        AUDMIXBUF_LOG(("\tUnlinking \"%s\"\n", pChild->pszName));
+
+        AudioMixBufReset(pChild);
 
-        AUDMIXBUF_LOG(("\tUnlinking \"%s\"\n", pIter->pszName));
+        Assert(pChild->pParent == pMixBuf);
+        pChild->pParent = NULL;
 
-        AudioMixBufReset(pIter->pParent);
-        pIter->pParent = NULL;
+        RTListNodeRemove(&pChild->Node);
 
-        RTListNodeRemove(&pIter->Node);
+        /* Decrease the children count. */
+        Assert(pMixBuf->cChildren);
+        pMixBuf->cChildren--;
     }
 
+    Assert(RTListIsEmpty(&pMixBuf->lstChildren));
+    Assert(pMixBuf->cChildren == 0);
+
+    AudioMixBufReset(pMixBuf);
+
     if (pMixBuf->pRate)
     {
         pMixBuf->pRate->dstOffset = pMixBuf->pRate->srcOffset = 0;
@@ -1513,25 +1753,24 @@ void AudioMixBufUnlink(PPDMAUDIOMIXBUF pMixBuf)
  *
  * @return  IPRT status code.
  * @param   pMixBuf                 Pointer to mixing buffer to write to.
- * @param   enmFmt                  Audio format supplied in the buffer.
  * @param   offSamples              Offset (in samples) starting to write at.
  * @param   pvBuf                   Pointer to audio buffer to be written.
  * @param   cbBuf                   Size (in bytes) of audio buffer.
  * @param   pcWritten               Returns number of audio samples written. Optional.
  */
-int AudioMixBufWriteAt(PPDMAUDIOMIXBUF pMixBuf,
-                       uint32_t offSamples,
-                       const void *pvBuf, uint32_t cbBuf,
-                       uint32_t *pcWritten)
+int AudioMixBufWriteAt(PPDMAUDIOMIXBUF pMixBuf, uint32_t offSamples, const void *pvBuf, uint32_t cbBuf, uint32_t *pcWritten)
 {
-    return AudioMixBufWriteAtEx(pMixBuf, pMixBuf->AudioFmt,
-                                offSamples, pvBuf, cbBuf, pcWritten);
+    return AudioMixBufWriteAtEx(pMixBuf, pMixBuf->AudioFmt, offSamples, pvBuf, cbBuf, pcWritten);
 }
 
 /**
- * Writes audio samples at a specific offset. The audio sample format
- * to be written can be different from the audio format the mixing buffer
- * operates on.
+ * Writes audio samples at a specific offset.
+ *
+ * Note that this operation also modifies the current read and write position
+ * to \a offSamples + written samples on success.
+ *
+ * The audio sample format to be written can be different from the audio format
+ * the mixing buffer operates on.
  *
  * @return  IPRT status code.
  * @param   pMixBuf                 Pointer to mixing buffer to write to.
@@ -1542,77 +1781,110 @@ int AudioMixBufWriteAt(PPDMAUDIOMIXBUF pMixBuf,
  * @param   pcWritten               Returns number of audio samples written. Optional.
  */
 int AudioMixBufWriteAtEx(PPDMAUDIOMIXBUF pMixBuf, PDMAUDIOMIXBUFFMT enmFmt,
-                         uint32_t offSamples,
-                         const void *pvBuf, uint32_t cbBuf,
+                         uint32_t offSamples, const void *pvBuf, uint32_t cbBuf,
                          uint32_t *pcWritten)
 {
     AssertPtrReturn(pMixBuf, VERR_INVALID_POINTER);
-    AssertPtrReturn(pvBuf, VERR_INVALID_POINTER);
-    /* pcWritten is optional. */
-
-    uint32_t cDstSamples = pMixBuf->pParent
-                         ? pMixBuf->pParent->cSamples : pMixBuf->cSamples;
-    uint32_t cLive = pMixBuf->cProcessed;
-
-    uint32_t cDead = cDstSamples - cLive;
-    uint32_t cToProcess = (uint32_t)AUDIOMIXBUF_S2S_RATIO(pMixBuf, cDead);
-    cToProcess = RT_MIN(cToProcess, AUDIOMIXBUF_B2S(pMixBuf, cbBuf));
-
-    AUDMIXBUF_LOG(("%s: offSamples=%RU32, cLive=%RU32, cDead=%RU32, cToProcess=%RU32\n",
-                   pMixBuf->pszName, offSamples, cLive, cDead, cToProcess));
+    AssertReturn(cbBuf,      VERR_INVALID_PARAMETER);
+    AssertPtrReturn(pvBuf,   VERR_INVALID_POINTER);
+    /* pcbWritten is optional. */
 
-    if (offSamples + cToProcess > pMixBuf->cSamples)
+    if (offSamples >= pMixBuf->cSamples)
+    {
+        if (pcWritten)
+            *pcWritten = 0;
         return VERR_BUFFER_OVERFLOW;
+    }
 
-    PAUDMIXBUF_FN_CONVFROM pConv = audioMixBufConvFromLookup(enmFmt, pMixBuf->Volume.fMuted);
-    if (!pConv)
-        return VERR_NOT_SUPPORTED;
-
-    int rc;
-    uint32_t cWritten;
+    /*
+     * Adjust cToWrite so we don't overflow our buffers.
+     */
+    uint32_t cToWrite = RT_MIN(AUDIOMIXBUF_B2S(pMixBuf, cbBuf), pMixBuf->cSamples - offSamples);
 
-#ifdef DEBUG_DUMP_PCM_DATA
-    RTFILE fh;
-    rc = RTFileOpen(&fh, DEBUG_DUMP_PCM_DATA_PATH "mixbuf_writeat.pcm",
-                    RTFILE_O_OPEN_CREATE | RTFILE_O_APPEND | RTFILE_O_WRITE | RTFILE_O_DENY_NONE);
-    if (RT_SUCCESS(rc))
+#ifdef AUDIOMIXBUF_DEBUG_DUMP_PCM_DATA
+    /*
+     * Now that we know how much we'll be converting we can log it.
+     */
+    RTFILE hFile;
+    int rc2 = RTFileOpen(&hFile, AUDIOMIXBUF_DEBUG_DUMP_PCM_DATA_PATH "mixbuf_writeat.pcm",
+                         RTFILE_O_OPEN_CREATE | RTFILE_O_APPEND | RTFILE_O_WRITE | RTFILE_O_DENY_NONE);
+    if (RT_SUCCESS(rc2))
     {
-        RTFileWrite(fh, pvBuf, cbBuf, NULL);
-        RTFileClose(fh);
+        RTFileWrite(hFile, pvBuf, AUDIOMIXBUF_S2B(pMixBuf, cToWrite), NULL);
+        RTFileClose(hFile);
     }
 #endif
 
-    if (cToProcess)
+    /*
+     * Pick the conversion function and do the conversion.
+     */
+    PFNPDMAUDIOMIXBUFCONVFROM pfnConvFrom = NULL;
+    if (!pMixBuf->Volume.fMuted)
+    {
+        if (pMixBuf->AudioFmt != enmFmt)
+            pfnConvFrom = audioMixBufConvFromLookup(enmFmt);
+        else
+            pfnConvFrom = pMixBuf->pfnConvFrom;
+    }
+    else
+        pfnConvFrom = &audioMixBufConvFromSilence;
+
+    int rc = VINF_SUCCESS;
+
+    uint32_t cWritten;
+    if (   pfnConvFrom
+        && cToWrite)
     {
-        AUDMIXBUF_CONVOPTS convOpts = { cToProcess, pMixBuf->Volume };
+        PDMAUDMIXBUFCONVOPTS convOpts;
 
-        cWritten = pConv(pMixBuf->pSamples + offSamples, pvBuf, cbBuf, &convOpts);
-#ifdef DEBUG
-        audioMixBufPrint(pMixBuf);
-#endif
-        rc = cWritten ? VINF_SUCCESS : VERR_GENERAL_FAILURE; /** @todo Fudge! */
+        convOpts.cSamples           = cToWrite;
+        convOpts.From.Volume.fMuted = pMixBuf->Volume.fMuted;
+        convOpts.From.Volume.uLeft  = pMixBuf->Volume.uLeft;
+        convOpts.From.Volume.uRight = pMixBuf->Volume.uRight;
+
+        cWritten = pfnConvFrom(pMixBuf->pSamples + offSamples, pvBuf, AUDIOMIXBUF_S2B(pMixBuf, cToWrite), &convOpts);
     }
     else
     {
         cWritten = 0;
-        rc = VINF_SUCCESS;
+        if (!pfnConvFrom)
+        {
+            AssertFailed();
+            rc = VERR_NOT_SUPPORTED;
+        }
     }
 
+    AUDMIXBUF_LOG(("%s: offSamples=%RU32, cbBuf=%RU32, cToWrite=%RU32 (%zu bytes), cWritten=%RU32 (%zu bytes), rc=%Rrc\n",
+                   pMixBuf->pszName, offSamples, cbBuf,
+                   cToWrite, AUDIOMIXBUF_S2B(pMixBuf, cToWrite),
+                   cWritten, AUDIOMIXBUF_S2B(pMixBuf, cWritten), rc));
+
     if (RT_SUCCESS(rc))
     {
+        pMixBuf->offRead  = offSamples % pMixBuf->cSamples;
+        pMixBuf->offWrite = (offSamples + cWritten) % pMixBuf->cSamples;
+        pMixBuf->cUsed    = cWritten;
+        pMixBuf->cMixed   = 0;
+
+#ifdef DEBUG
+        audioMixBufDbgValidate(pMixBuf);
+#endif
         if (pcWritten)
             *pcWritten = cWritten;
     }
+    else
+        AUDMIXBUF_LOG(("%s: Failed with %Rrc\n", pMixBuf->pszName, rc));
 
-    AUDMIXBUF_LOG(("cWritten=%RU32, rc=%Rrc\n", cWritten, rc));
     return rc;
 }
 
 /**
- * Writes audio samples. The sample format being written must match the
- * format of the mixing buffer.
+ * Writes audio samples.
  *
- * @return  IPRT status code.
+ * The sample format being written must match the format of the mixing buffer.
+ *
+ * @return  IPRT status code, or VERR_BUFFER_OVERFLOW if samples which not have
+ *          been processed yet have been overwritten (due to cyclic buffer).
  * @param   pMixBuf                 Pointer to mixing buffer to write to.
  * @param   pvBuf                   Pointer to audio buffer to be written.
  * @param   cbBuf                   Size (in bytes) of audio buffer.
@@ -1627,8 +1899,9 @@ int AudioMixBufWriteCirc(PPDMAUDIOMIXBUF pMixBuf,
 
 /**
  * Writes audio samples of a specific format.
+ * This function might write less data at once than requested.
  *
- * @return  IPRT status code.
+ * @return  IPRT status code, or VERR_BUFFER_OVERFLOW no space is available for writing anymore.
  * @param   pMixBuf                 Pointer to mixing buffer to write to.
  * @param   enmFmt                  Audio format supplied in the buffer.
  * @param   pvBuf                   Pointer to audio buffer to be written.
@@ -1636,11 +1909,10 @@ int AudioMixBufWriteCirc(PPDMAUDIOMIXBUF pMixBuf,
  * @param   pcWritten               Returns number of audio samples written. Optional.
  */
 int AudioMixBufWriteCircEx(PPDMAUDIOMIXBUF pMixBuf, PDMAUDIOMIXBUFFMT enmFmt,
-                           const void *pvBuf, uint32_t cbBuf,
-                           uint32_t *pcWritten)
+                           const void *pvBuf, uint32_t cbBuf, uint32_t *pcWritten)
 {
     AssertPtrReturn(pMixBuf, VERR_INVALID_POINTER);
-    AssertPtrReturn(pvBuf, VERR_INVALID_POINTER);
+    AssertPtrReturn(pvBuf,   VERR_INVALID_POINTER);
     /* pcbWritten is optional. */
 
     if (!cbBuf)
@@ -1650,107 +1922,94 @@ int AudioMixBufWriteCircEx(PPDMAUDIOMIXBUF pMixBuf, PDMAUDIOMIXBUFFMT enmFmt,
         return VINF_SUCCESS;
     }
 
-    PPDMAUDIOMIXBUF pParent = pMixBuf->pParent;
+    /* Make sure that we at least write a full audio sample. */
+    AssertReturn(AUDIOMIXBUF_B2S(pMixBuf, cbBuf), VERR_INVALID_PARAMETER);
 
-    AUDMIXBUF_LOG(("%s: enmFmt=%ld, pBuf=%p, cbBuf=%zu, pParent=%p (%RU32)\n",
-                   pMixBuf->pszName, enmFmt, pvBuf, cbBuf, pParent, pParent ? pParent->cSamples : 0));
+    Assert(pMixBuf->cSamples);
+    AssertPtr(pMixBuf->pSamples);
 
-    if (   pParent
-        && pParent->cSamples <= pMixBuf->cMixed)
+    PFNPDMAUDIOMIXBUFCONVFROM pfnConvFrom = NULL;
+    if (!pMixBuf->Volume.fMuted)
     {
-        if (pcWritten)
-            *pcWritten = 0;
-
-        AUDMIXBUF_LOG(("%s: Parent buffer %s is full\n",
-                       pMixBuf->pszName, pMixBuf->pParent->pszName));
-
-        return VINF_SUCCESS;
+        if (pMixBuf->AudioFmt != enmFmt)
+            pfnConvFrom = audioMixBufConvFromLookup(enmFmt);
+        else
+            pfnConvFrom = pMixBuf->pfnConvFrom;
     }
+    else
+        pfnConvFrom = &audioMixBufConvFromSilence;
 
-    PAUDMIXBUF_FN_CONVFROM pConv = audioMixBufConvFromLookup(enmFmt, pMixBuf->Volume.fMuted);
-    if (!pConv)
+    if (!pfnConvFrom)
+    {
+        AssertFailed();
         return VERR_NOT_SUPPORTED;
+    }
 
     int rc = VINF_SUCCESS;
 
-    uint32_t cToWrite = AUDIOMIXBUF_B2S(pMixBuf, cbBuf);
-    AssertMsg(cToWrite, ("cToWrite is 0 (cbBuf=%zu)\n", cbBuf));
-
-    PPDMAUDIOSAMPLE pSamplesDst1 = pMixBuf->pSamples + pMixBuf->offReadWrite;
-    uint32_t cLenDst1 = cToWrite;
-
-    PPDMAUDIOSAMPLE pSamplesDst2 = NULL;
-    uint32_t cLenDst2 = 0;
-
-    uint32_t offWrite = pMixBuf->offReadWrite + cToWrite;
+    uint32_t cWritten = 0;
 
-    /*
-     * Do we need to wrap around to write all requested data, that is,
-     * starting at the beginning of our circular buffer? This then will
-     * be the optional second part to do.
-     */
-    if (offWrite >= pMixBuf->cSamples)
+    uint32_t cFree = pMixBuf->cSamples - pMixBuf->cUsed;
+    if (cFree)
     {
-        Assert(pMixBuf->offReadWrite <= pMixBuf->cSamples);
-        cLenDst1 = pMixBuf->cSamples - pMixBuf->offReadWrite;
-
-        pSamplesDst2 = pMixBuf->pSamples;
-        Assert(cToWrite >= cLenDst1);
-        cLenDst2 = RT_MIN(cToWrite - cLenDst1, pMixBuf->cSamples);
+        if ((pMixBuf->cSamples - pMixBuf->offWrite) == 0)
+            pMixBuf->offWrite = 0;
 
-        /* Save new read offset. */
-        offWrite = cLenDst2;
-    }
-
-    uint32_t cWrittenTotal = 0;
+        uint32_t cToWrite = RT_MIN(AUDIOMIXBUF_B2S(pMixBuf, cbBuf), RT_MIN(pMixBuf->cSamples - pMixBuf->offWrite, cFree));
+        Assert(cToWrite);
 
-    AUDMIXBUF_CONVOPTS convOpts;
-    convOpts.Volume = pMixBuf->Volume;
+        PDMAUDMIXBUFCONVOPTS convOpts;
+        RT_ZERO(convOpts);
 
-    /* Anything to do at all? */
-    if (cLenDst1)
-    {
-        convOpts.cSamples = cLenDst1;
-        cWrittenTotal = pConv(pSamplesDst1, pvBuf, cbBuf, &convOpts);
-    }
+        convOpts.From.Volume.fMuted = pMixBuf->Volume.fMuted;
+        convOpts.From.Volume.uLeft  = pMixBuf->Volume.uLeft;
+        convOpts.From.Volume.uRight = pMixBuf->Volume.uRight;
 
-    /* Second part present? */
-    if (   RT_LIKELY(RT_SUCCESS(rc))
-        && cLenDst2)
-    {
-        AssertPtr(pSamplesDst2);
+        convOpts.cSamples = cToWrite;
 
-        convOpts.cSamples = cLenDst2;
-        cWrittenTotal += pConv(pSamplesDst2, (uint8_t *)pvBuf + AUDIOMIXBUF_S2B(pMixBuf, cLenDst1), cbBuf, &convOpts);
-    }
+        cWritten = pfnConvFrom(pMixBuf->pSamples + pMixBuf->offWrite,
+                               pvBuf, AUDIOMIXBUF_S2B(pMixBuf, cToWrite), &convOpts);
+        Assert(cWritten == cToWrite);
 
-#ifdef DEBUG_DUMP_PCM_DATA
+#ifdef AUDIOMIXBUF_DEBUG_DUMP_PCM_DATA
         RTFILE fh;
-        RTFileOpen(&fh, DEBUG_DUMP_PCM_DATA_PATH "mixbuf_writeex.pcm",
+        RTFileOpen(&fh, AUDIOMIXBUF_DEBUG_DUMP_PCM_DATA_PATH "mixbuf_writecirc_ex.pcm",
                    RTFILE_O_OPEN_CREATE | RTFILE_O_APPEND | RTFILE_O_WRITE | RTFILE_O_DENY_NONE);
-        RTFileWrite(fh, pSamplesDst1, AUDIOMIXBUF_S2B(pMixBuf, cLenDst1), NULL);
+        RTFileWrite(fh, pvBuf, AUDIOMIXBUF_S2B(pMixBuf, cToWrite), NULL);
         RTFileClose(fh);
 #endif
+        pMixBuf->cUsed   += cWritten;
+        Assert(pMixBuf->cUsed <= pMixBuf->cSamples);
 
-    AUDMIXBUF_LOG(("cLenDst1=%RU32, cLenDst2=%RU32, offWrite=%RU32\n",
-                   cLenDst1, cLenDst2, offWrite));
-
-    if (RT_SUCCESS(rc))
-    {
-        pMixBuf->offReadWrite = offWrite % pMixBuf->cSamples;
-        pMixBuf->cProcessed = RT_MIN(pMixBuf->cProcessed + cLenDst1 + cLenDst2,
-                                     pMixBuf->cSamples /* Max */);
-        if (pcWritten)
-            *pcWritten = cLenDst1 + cLenDst2;
+        pMixBuf->offWrite = (pMixBuf->offWrite + cWritten) % pMixBuf->cSamples;
+        Assert(pMixBuf->offWrite <= pMixBuf->cSamples);
     }
+    else
+        rc = VERR_BUFFER_OVERFLOW;
 
 #ifdef DEBUG
-    audioMixBufPrint(pMixBuf);
+    audioMixBufDbgPrintInternal(pMixBuf, __FUNCTION__);
+    audioMixBufDbgValidate(pMixBuf);
 #endif
 
-    AUDMIXBUF_LOG(("cWritten=%RU32 (%zu bytes), rc=%Rrc\n",
-                   cLenDst1 + cLenDst2,
-                   AUDIOMIXBUF_S2B(pMixBuf, cLenDst1 + cLenDst2), rc));
+    if (pcWritten)
+        *pcWritten = cWritten;
+
+    AUDMIXBUF_LOG(("%s: enmFmt=0x%x, cbBuf=%RU32 (%RU32 samples), cWritten=%RU32, rc=%Rrc\n",
+                   pMixBuf->pszName, enmFmt, cbBuf, AUDIOMIXBUF_B2S(pMixBuf, cbBuf), cWritten, rc));
     return rc;
 }
 
+/**
+ * Returns the current write position of a mixing buffer.
+ *
+ * @returns IPRT status code.
+ * @param   pMixBuf                 Mixing buffer to return position for.
+ */
+uint32_t AudioMixBufWritePos(PPDMAUDIOMIXBUF pMixBuf)
+{
+    AssertPtrReturn(pMixBuf, 0);
+
+    return pMixBuf->offWrite;
+}
+
diff --git a/src/VBox/Devices/Audio/AudioMixBuffer.h b/src/VBox/Devices/Audio/AudioMixBuffer.h
index 11c5912..40b3728 100644
--- a/src/VBox/Devices/Audio/AudioMixBuffer.h
+++ b/src/VBox/Devices/Audio/AudioMixBuffer.h
@@ -1,11 +1,10 @@
 /* $Id: AudioMixBuffer.h $ */
 /** @file
- * VBox audio: Mixing buffer to convert audio samples to/from different
- *             rates / formats.
+ * VBox audio - Mixing buffer to convert audio samples to/from different rates / formats.
  */
 
 /*
- * Copyright (C) 2014-2015 Oracle Corporation
+ * Copyright (C) 2014-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;
@@ -49,25 +48,26 @@
 #define AUDIOMIXBUF_S2S_RATIO(pBuf, samples)  (((int64_t) samples << 32) / (pBuf)->iFreqRatio)
 
 
-int AudioMixBufAcquire(PPDMAUDIOMIXBUF pMixBuf, uint32_t cSamplesToRead, PPDMAUDIOSAMPLE *ppvSamples, uint32_t *pcSamplesRead);
-uint32_t AudioMixBufAvail(PPDMAUDIOMIXBUF pMixBuf);
 inline uint32_t AudioMixBufBytesToSamples(PPDMAUDIOMIXBUF pMixBuf);
 void AudioMixBufClear(PPDMAUDIOMIXBUF pMixBuf);
 void AudioMixBufDestroy(PPDMAUDIOMIXBUF pMixBuf);
 void AudioMixBufFinish(PPDMAUDIOMIXBUF pMixBuf, uint32_t cSamplesToClear);
 uint32_t AudioMixBufFree(PPDMAUDIOMIXBUF pMixBuf);
 uint32_t AudioMixBufFreeBytes(PPDMAUDIOMIXBUF pMixBuf);
-int AudioMixBufInit(PPDMAUDIOMIXBUF pMixBuf, const char *pszName, PPDMPCMPROPS pProps, uint32_t cSamples);
+int AudioMixBufInit(PPDMAUDIOMIXBUF pMixBuf, const char *pszName, PPDMAUDIOPCMPROPS pProps, uint32_t cSamples);
 bool AudioMixBufIsEmpty(PPDMAUDIOMIXBUF pMixBuf);
 int AudioMixBufLinkTo(PPDMAUDIOMIXBUF pMixBuf, PPDMAUDIOMIXBUF pParent);
-uint32_t AudioMixBufMixed(PPDMAUDIOMIXBUF pMixBuf);
-int AudioMixBufMixToChildren(PPDMAUDIOMIXBUF pMixBuf, uint32_t cSamples, uint32_t *pcProcessed);
-int AudioMixBufMixToParent(PPDMAUDIOMIXBUF pMixBuf, uint32_t cSamples, uint32_t *pcProcessed);
-uint32_t AudioMixBufProcessed(PPDMAUDIOMIXBUF pMixBuf);
+uint32_t AudioMixBufLive(PPDMAUDIOMIXBUF pMixBuf);
+int AudioMixBufMixToParent(PPDMAUDIOMIXBUF pMixBuf, uint32_t cSrcSamples, uint32_t *pcSrcMixed);
+int AudioMixBufMixToParentEx(PPDMAUDIOMIXBUF pMixBuf, uint32_t cSrcOffset, uint32_t cSrcSamples, uint32_t *pcSrcMixed);
+int AudioMixBufPeek(PPDMAUDIOMIXBUF pMixBuf, uint32_t cSamplesToRead, PPDMAUDIOSAMPLE paSampleBuf, uint32_t cSampleBuf, uint32_t *pcSamplesRead);
+int AudioMixBufPeekMutable(PPDMAUDIOMIXBUF pMixBuf, uint32_t cSamplesToRead, PPDMAUDIOSAMPLE *ppvSamples, uint32_t *pcSamplesRead);
+uint32_t AudioMixBufUsed(PPDMAUDIOMIXBUF pMixBuf);
 int AudioMixBufReadAt(PPDMAUDIOMIXBUF pMixBuf, uint32_t offSamples, void *pvBuf, uint32_t cbBuf, uint32_t *pcbRead);
 int AudioMixBufReadAtEx(PPDMAUDIOMIXBUF pMixBuf, PDMAUDIOMIXBUFFMT enmFmt, uint32_t offSamples, void *pvBuf, uint32_t cbBuf, uint32_t *pcbRead);
 int AudioMixBufReadCirc(PPDMAUDIOMIXBUF pMixBuf, void *pvBuf, uint32_t cbBuf, uint32_t *pcRead);
 int AudioMixBufReadCircEx(PPDMAUDIOMIXBUF pMixBuf, PDMAUDIOMIXBUFFMT enmFmt, void *pvBuf, uint32_t cbBuf, uint32_t *pcRead);
+uint32_t AudioMixBufReadPos(PPDMAUDIOMIXBUF pMixBuf);
 void AudioMixBufReset(PPDMAUDIOMIXBUF pMixBuf);
 void AudioMixBufSetVolume(PPDMAUDIOMIXBUF pMixBuf, PPDMAUDIOVOLUME pVol);
 uint32_t AudioMixBufSize(PPDMAUDIOMIXBUF pMixBuf);
@@ -77,6 +77,12 @@ int AudioMixBufWriteAt(PPDMAUDIOMIXBUF pMixBuf, uint32_t offSamples, const void
 int AudioMixBufWriteAtEx(PPDMAUDIOMIXBUF pMixBuf, PDMAUDIOMIXBUFFMT enmFmt, uint32_t offSamples, const void *pvBuf, uint32_t cbBuf, uint32_t *pcWritten);
 int AudioMixBufWriteCirc(PPDMAUDIOMIXBUF pMixBuf, const void *pvBuf, uint32_t cbBuf, uint32_t *pcWritten);
 int AudioMixBufWriteCircEx(PPDMAUDIOMIXBUF pMixBuf, PDMAUDIOMIXBUFFMT enmFmt, const void *pvBuf, uint32_t cbBuf, uint32_t *pcWritten);
+uint32_t AudioMixBufWritePos(PPDMAUDIOMIXBUF pMixBuf);
 
-#endif /* !AUDIO_MIXBUF_H */
+#ifdef DEBUG
+void AudioMixBufDbgPrint(PPDMAUDIOMIXBUF pMixBuf);
+void AudioMixBufDbgPrintChain(PPDMAUDIOMIXBUF pMixBuf);
+#endif
+
+#endif
 
diff --git a/src/VBox/Devices/Audio/AudioMixer.cpp b/src/VBox/Devices/Audio/AudioMixer.cpp
index 83a082f..5527a48 100644
--- a/src/VBox/Devices/Audio/AudioMixer.cpp
+++ b/src/VBox/Devices/Audio/AudioMixer.cpp
@@ -301,11 +301,7 @@ int AudioMixerProcessSinkIn(PAUDMIXSINK pSink, AUDMIXOP enmOp, void *pvBuf, uint
 
     /** @todo Handle mixing operation enmOp! */
 
-    uint8_t *pvMixBuf = (uint8_t *)RTMemAlloc(cbBuf);
-    if (!pvMixBuf)
-        return VERR_NO_MEMORY;
-
-    int rc = VERR_NOT_FOUND;
+    int rc = VINF_SUCCESS;
     uint32_t cbProcessed = 0;
 
     LogFlowFunc(("%s: pvBuf=%p, cbBuf=%zu\n", pSink->pszName, pvBuf, cbBuf));
@@ -313,7 +309,6 @@ int AudioMixerProcessSinkIn(PAUDMIXSINK pSink, AUDMIXOP enmOp, void *pvBuf, uint
     PAUDMIXSTREAM pStream;
     RTListForEach(&pSink->lstStreams, pStream, AUDMIXSTREAM, Node)
     {
-        /** @todo Support output sinks as well! */
         if (!pStream->pConn->pfnIsActiveIn(pStream->pConn, pStream->pIn))
             continue;
 
@@ -325,7 +320,7 @@ int AudioMixerProcessSinkIn(PAUDMIXSINK pSink, AUDMIXOP enmOp, void *pvBuf, uint
             uint32_t cbRead;
             AssertPtr(pStream->pConn);
             rc = pStream->pConn->pfnRead(pStream->pConn, pStream->pIn,
-                                         (uint8_t *)pvMixBuf + cbTotalRead, cbToRead, &cbRead);
+                                         (uint8_t *)pvBuf + cbTotalRead, cbToRead, &cbRead);
             if (   RT_FAILURE(rc)
                 || !cbRead)
                 break;
@@ -333,24 +328,26 @@ int AudioMixerProcessSinkIn(PAUDMIXSINK pSink, AUDMIXOP enmOp, void *pvBuf, uint
             AssertBreakStmt(cbRead <= cbToRead, rc = VERR_BUFFER_OVERFLOW);
             cbToRead -= cbRead;
             cbTotalRead += cbRead;
+            AssertBreakStmt(cbTotalRead <= cbBuf, rc = VERR_BUFFER_OVERFLOW);
         }
 
         if (RT_FAILURE(rc))
             continue;
 
         cbProcessed = RT_MAX(cbProcessed, cbTotalRead);
+
+        /** @todo This needs a mixing buffer / routine here -- otherwise input data gets lost
+         *        if multiple nodes are sending input. */
     }
 
     if (RT_SUCCESS(rc))
     {
-        memcpy(pvBuf, pvMixBuf, cbProcessed); /* @todo Use an intermediate mixing buffer per sink! */
+        Assert(cbProcessed <= cbBuf);
 
         if (pcbProcessed)
             *pcbProcessed = cbProcessed;
     }
 
-    RTMemFree(pvMixBuf);
-
     LogFlowFunc(("cbProcessed=%RU32, rc=%Rrc\n", cbProcessed, rc));
     return rc;
 }
diff --git a/src/VBox/Devices/Audio/DevHDA.cpp b/src/VBox/Devices/Audio/DevHDA.cpp
index 2c619d6..290c384 100644
--- a/src/VBox/Devices/Audio/DevHDA.cpp
+++ b/src/VBox/Devices/Audio/DevHDA.cpp
@@ -1,6 +1,6 @@
 /* $Id: DevHDA.cpp $ */
 /** @file
- * DevIchHda - VBox ICH Intel HD Audio Controller.
+ * DevHDA.cpp - VBox ICH Intel HD Audio Controller.
  *
  * Implemented against the specifications found in "High Definition Audio
  * Specification", Revision 1.0a June 17, 2010, and  "Intel I/O Controller
@@ -8,7 +8,7 @@
  */
 
 /*
- * Copyright (C) 2006-2016 Oracle Corporation
+ * Copyright (C) 2006-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;
@@ -25,6 +25,7 @@
 *********************************************************************************************************************************/
 #define LOG_GROUP LOG_GROUP_DEV_HDA
 #include <VBox/log.h>
+
 #include <VBox/vmm/pdmdev.h>
 #include <VBox/vmm/pdmaudioifs.h>
 #include <VBox/version.h>
@@ -32,8 +33,12 @@
 #include <iprt/assert.h>
 #include <iprt/asm.h>
 #include <iprt/asm-math.h>
+#include <iprt/circbuf.h>
+#include <iprt/critsect.h>
+#include <iprt/file.h>
 #include <iprt/list.h>
 #ifdef IN_RING3
+# include <math.h>
 # include <iprt/mem.h>
 # include <iprt/semaphore.h>
 # include <iprt/string.h>
@@ -44,7 +49,9 @@
 
 #include "AudioMixBuffer.h"
 #include "AudioMixer.h"
-#include "DevIchHdaCodec.h"
+#include "HDACodec.h"
+#include "HDAStreamPeriod.h"
+#include "DevHDA.h"
 #include "DrvAudio.h"
 
 
@@ -54,12 +61,29 @@
 //#define HDA_AS_PCI_EXPRESS
 #define VBOX_WITH_INTEL_HDA
 
-#ifdef DEBUG_andy
-/* Enables experimental support for separate mic-in handling.
-   Do not enable this yet for regular builds, as this needs more testing first! */
-//# define VBOX_WITH_HDA_MIC_IN
+/* Installs a DMA access handler (via PGM callback) to monitor
+ * HDA's DMA operations, that is, writing / reading audio stream data.
+ *
+ * !!! Note: Certain guests are *that* timing sensitive that when enabling  !!!
+ * !!!       such a handler will mess up audio completely (e.g. Windows 7). !!! */
+//# define HDA_USE_DMA_ACCESS_HANDLER
+#ifdef HDA_USE_DMA_ACCESS_HANDLER
+# include <VBox/vmm/pgm.h>
 #endif
 
+/* Uses the DMA access handler to read the written DMA audio (output) data.
+ * Only valid if HDA_USE_DMA_ACCESS_HANDLER is set.
+ *
+ * Also see the note / warning for HDA_USE_DMA_ACCESS_HANDLER. */
+//# define HDA_USE_DMA_ACCESS_HANDLER_WRITING
+
+/* Useful to debug the device' timing. */
+//#define HDA_DEBUG_TIMING
+
+/* To debug silence coming from the guest in form of audio gaps.
+ * Very crude implementation for now. */
+//#define HDA_DEBUG_SILENCE
+
 #if defined(VBOX_WITH_HP_HDA)
 /* HP Pavilion dv4t-1300 */
 # define HDA_PCI_VENDOR_ID 0x103c
@@ -76,13 +100,19 @@
 # error "Please specify your HDA device vendor/device IDs"
 #endif
 
-/** @todo r=bird: Looking at what the linux driver (accidentally?) does when
- * updating CORBWP, I belive that the ICH6 datahsheet is wrong and that CORBRP
- * is read only except for bit 15 like the HDA spec states.
+/** Default timer frequency (in Hz).
  *
- * Btw. the CORBRPRST implementation is incomplete according to both docs (sw
- * writes 1, hw sets it to 1 (after completion), sw reads 1, sw writes 0). */
-#define BIRD_THINKS_CORBRP_IS_MOSTLY_RO
+ *  Note: Keep in mind that the Hz rate has nothing to do with samples rates
+ *        or DMA / interrupt timing -- it's purely needed in order to drive
+ *        the data flow at a constant (and sufficient) rate.
+ *
+ *        Lowering this value can ask for trouble, as backends then can run
+ *        into data underruns. */
+#define HDA_TIMER_HZ        200
+
+/** HDA's (fixed) audio frame size in bytes.
+ *  We only support 16-bit stereo frames at the moment. */
+#define HDA_FRAME_SIZE      4
 
 #define HDA_NREGS           114
 #define HDA_NREGS_SAVED     112
@@ -146,7 +176,7 @@
 
 #define HDA_REG_STATESTS            7 /* 0x0E */
 #define HDA_RMX_STATESTS            7
-#define HDA_STATES_SCSF             0x7
+#define HDA_STATESTS_SCSF_MASK      0x7 /* State Change Status Flags (6.2.8). */
 
 #define HDA_REG_GSTS                8 /* 0x10-0x11*/
 #define HDA_RMX_GSTS                8
@@ -174,17 +204,9 @@
 
 #define HDA_REG_INTSTS              12 /* 0x24 */
 #define HDA_RMX_INTSTS              10
-#define HDA_INTSTS_GIS_SHIFT        31
-#define HDA_INTSTS_CIS_SHIFT        30
-#define HDA_INTSTS_S0_SHIFT         0
-#define HDA_INTSTS_S1_SHIFT         1
-#define HDA_INTSTS_S2_SHIFT         2
-#define HDA_INTSTS_S3_SHIFT         3
-#define HDA_INTSTS_S4_SHIFT         4
-#define HDA_INTSTS_S5_SHIFT         5
-#define HDA_INTSTS_S6_SHIFT         6
-#define HDA_INTSTS_S7_SHIFT         7
-#define HDA_INTSTS_S_MASK(num)      RT_BIT(HDA_REG_FIELD_SHIFT(S##num))
+#define HDA_INTSTS_FLAG_CIS         RT_BIT(30) /* Controller Interrupt Status (CIS). */
+#define HDA_INTSTS_FLAG_GIS         RT_BIT(31) /* Global Interrupt Status (GIS). */
+#define HDA_INTSTS_MASK_SIS         0xFF       /* Stream Interrupt Status (SIS). */
 
 #define HDA_REG_WALCLK              13 /* 0x24 */
 #define HDA_RMX_WALCLK              /* Not defined! */
@@ -208,6 +230,7 @@
 #define HDA_REG_CORBRP              18 /* 0x4A */
 #define HDA_RMX_CORBRP              16
 #define HDA_CORBRP_RST_SHIFT        15
+#define HDA_CORBRP_RST              RT_BIT(15)
 #define HDA_CORBRP_WP_SHIFT         0
 #define HDA_CORBRP_WP_MASK          0xFF
 
@@ -442,6 +465,9 @@
  * formula: size - 1
  * Other values not listed are not supported.
  */
+/** Maximum FIFO size (in bytes). */
+#define HDA_FIFO_MAX                256
+
 #define HDA_SDINFIFO_120B           0x77 /* 8-, 16-, 20-, 24-, 32-bit Input Streams */
 #define HDA_SDINFIFO_160B           0x9F /* 20-, 24-bit Input Streams Streams */
 
@@ -472,6 +498,7 @@
 
 #define SDFMT(pThis, num)           (HDA_REG((pThis), SD(FMT, num)))
 #define HDA_SDFMT_BASE_RATE_SHIFT   14
+#define HDA_SDFMT_BASE_RATE_MASK    RT_BIT(14)
 #define HDA_SDFMT_MULT_SHIFT        11
 #define HDA_SDFMT_MULT_MASK         0x7
 #define HDA_SDFMT_DIV_SHIFT         8
@@ -516,6 +543,8 @@
 #define HDA_RMX_SD6BDPU             (HDA_STREAM_RMX_DEF(BDPU, 0) + 60)
 #define HDA_RMX_SD7BDPU             (HDA_STREAM_RMX_DEF(BDPU, 0) + 70)
 
+#define HDA_BDLE_FLAG_IOC           RT_BIT(0) /* Interrupt on completion (IOC). */
+
 #define HDA_CODEC_CAD_SHIFT         28
 /* Encodes the (required) LUN into a codec command. */
 #define HDA_CODEC_CMD(cmd, lun)     ((cmd) | (lun << HDA_CODEC_CAD_SHIFT))
@@ -526,100 +555,28 @@
 *   Structures and Typedefs                                                                                                      *
 *********************************************************************************************************************************/
 
-/**
- * Internal state of a Buffer Descriptor List Entry (BDLE),
- * needed to keep track of the data needed for the actual device
- * emulation.
- */
-typedef struct HDABDLESTATE
-{
-    /** Own index within the BDL (Buffer Descriptor List). */
-    uint32_t     u32BDLIndex;
-    /** Number of bytes below the stream's FIFO watermark (SDFIFOW).
-     *  Used to check if we need fill up the FIFO again. */
-    uint32_t     cbBelowFIFOW;
-    /** The buffer descriptor's internal DMA buffer. */
-    uint8_t      au8FIFO[HDA_SDONFIFO_256B + 1];
-    /** Current offset in DMA buffer (in bytes).*/
-    uint32_t     u32BufOff;
-    uint32_t     Padding;
-} HDABDLESTATE, *PHDABDLESTATE;
-
-/**
- * Buffer Descriptor List Entry (BDLE) (3.6.3).
- *
- * Contains only register values which do *not* change until a
- * stream reset occurs.
- */
-typedef struct HDABDLE
-{
-    /** Starting address of the actual buffer. Must be 128-bit aligned. */
-    uint64_t     u64BufAdr;
-    /** Size of the actual buffer (in bytes). */
-    uint32_t     u32BufSize;
-    /** Interrupt on completion; the controller will generate
-     *  an interrupt when the last byte of the buffer has been
-     *  fetched by the DMA engine. */
-    bool         fIntOnCompletion;
-    /** Internal state of this BDLE.
-     *  Not part of the actual BDLE registers. */
-    HDABDLESTATE State;
-} HDABDLE, *PHDABDLE;
-
-/**
- * Internal state of a HDA stream.
- */
-typedef struct HDASTREAMSTATE
-{
-    /** Current BDLE to use. Wraps around to 0 if
-     *  maximum (cBDLE) is reached. */
-    uint16_t            uCurBDLE;
-    /** Stop indicator. */
-    volatile bool       fDoStop;
-    /** Flag indicating whether this stream is in an
-     *  active (operative) state or not. */
-    volatile bool       fActive;
-    /** Flag indicating whether this stream currently is
-     *  in reset mode and therefore not acccessible by the guest. */
-    volatile bool       fInReset;
-    /** Unused, padding. */
-    bool                fPadding;
-    /** Event signalling that the stream's state has been changed. */
-    RTSEMEVENT          hStateChangedEvent;
-    /** Current BDLE (Buffer Descriptor List Entry). */
-    HDABDLE             BDLE;
-} HDASTREAMSTATE, *PHDASTREAMSTATE;
-
-/**
- * Structure for keeping a HDA stream state.
- *
- * Contains only register values which do *not* change until a
- * stream reset occurs.
- */
-typedef struct HDASTREAM
-{
-    /** Stream number (SDn). */
-    uint8_t        u8Strm;
-    uint8_t        Padding0[7];
-    /** DMA base address (SDnBDPU - SDnBDPL). */
-    uint64_t       u64BDLBase;
-    /** Cyclic Buffer Length (SDnCBL).
-     *  Represents the size of the ring buffer. */
-    uint32_t       u32CBL;
-    /** Format (SDnFMT). */
-    uint16_t       u16FMT;
-    /** FIFO Size (FIFOS).
-     *  Maximum number of bytes that may have been DMA'd into
-     *  memory but not yet transmitted on the link.
-     *
-     *  Must be a power of two. */
-    uint16_t       u16FIFOS;
-    /** Last Valid Index (SDnLVI). */
-    uint16_t       u16LVI;
-    uint16_t       Padding1[3];
-    /** Internal state of this stream. */
-    HDASTREAMSTATE State;
-} HDASTREAM, *PHDASTREAM;
+#ifdef HDA_USE_DMA_ACCESS_HANDLER
+typedef struct HDADMAACCESSHANDLER
+{
+    /** Node for storing this handler in our list in HDASTREAMSTATE. */
+    RTLISTNODER3            Node;
+    /** Pointer to stream to which this access handler is assigned to. */
+    R3PTRTYPE(PHDASTREAM)   pStream;
+    /** Access handler type handle. */
+    PGMPHYSHANDLERTYPE      hAccessHandlerType;
+    /** First address this handler uses. */
+    RTGCPHYS                GCPhysFirst;
+    /** Last address this handler uses. */
+    RTGCPHYS                GCPhysLast;
+    /** Actual BDLE address to handle. */
+    RTGCPHYS                BDLEAddr;
+    /** Actual BDLE buffer size to handle. */
+    RTGCPHYS                BDLESize;
+    /** Whether the access handler has been registered or not. */
+    bool                    fRegistered;
+    uint8_t                 Padding[3];
+} HDADMAACCESSHANDLER, *PHDADMAACCESSHANDLER;
+#endif
 
 typedef struct HDAINPUTSTREAM
 {
@@ -653,7 +610,7 @@ typedef struct HDADRIVER
     /** Pointer to HDA controller (state). */
     R3PTRTYPE(PHDASTATE)               pHDAState;
     /** Driver flags. */
-    PDMAUDIODRVFLAGS                   Flags;
+    PDMAUDIODRVFLAGS                   fFlags;
     uint8_t                            u32Padding0[2];
     /** LUN to which this driver has been assigned. */
     uint8_t                            uLUN;
@@ -671,6 +628,34 @@ typedef struct HDADRIVER
     HDAOUTPUTSTREAM                    Out;
 } HDADRIVER;
 
+#ifdef DEBUG
+/** @todo Make STAM values out of this? */
+typedef struct HDASTATEDBGINFO
+{
+    /** Timestamp (in ns) of the last timer callback (hdaTimer).
+     * Used to calculate the time actually elapsed between two timer callbacks. */
+    uint64_t                           tsTimerLastCalledNs;
+    /** IRQ debugging information. */
+    struct
+    {
+        /** Timestamp (in ns) of last processed (asserted / deasserted) IRQ. */
+        uint64_t                       tsProcessedLastNs;
+        /** Timestamp (in ns) of last asserted IRQ. */
+        uint64_t                       tsAssertedNs;
+        /** How many IRQs have been asserted already. */
+        uint64_t                       cAsserted;
+        /** Accumulated elapsed time (in ns) of all IRQ being asserted. */
+        uint64_t                       tsAssertedTotalNs;
+        /** Timestamp (in ns) of last deasserted IRQ. */
+        uint64_t                       tsDeassertedNs;
+        /** How many IRQs have been deasserted already. */
+        uint64_t                       cDeasserted;
+        /** Accumulated elapsed time (in ns) of all IRQ being deasserted. */
+        uint64_t                       tsDeassertedTotalNs;
+    } IRQ;
+} HDASTATEDBGINFO, *PHDASTATEDBGINFO;
+#endif
+
 /**
  * ICH Intel HD Audio Controller state.
  */
@@ -692,11 +677,11 @@ typedef struct HDASTATE
     /** The HDA's register set. */
     uint32_t                           au32Regs[HDA_NREGS];
     /** Stream state for line-in. */
-    HDASTREAM                          StrmStLineIn;
+    HDASTREAM                          LineIn;
     /** Stream state for microphone-in. */
-    HDASTREAM                          StrmStMicIn;
+    HDASTREAM                          MicIn;
     /** Stream state for output. */
-    HDASTREAM                          StrmStOut;
+    HDASTREAM                          Out;
     /** CORB buffer base address. */
     uint64_t                           u64CORBBase;
     /** RIRB buffer base address. */
@@ -725,13 +710,12 @@ typedef struct HDASTATE
     /** Flag whether the RC part is enabled. */
     bool                               fRCEnabled;
 #ifndef VBOX_WITH_AUDIO_CALLBACKS
-    /** The timer for pumping data thru the attached LUN drivers. */
+    /** The timer instance. */
     PTMTIMERR3                         pTimer;
-    /** The timer interval for pumping data thru the LUN drivers in timer ticks. */
+    /** The current timer expire time (in timer ticks). */
+    uint64_t                           tsTimerExpire;
+    /** The (fixed) timer interval (in timer ticks). */
     uint64_t                           cTimerTicks;
-    /** Timestamp of the last timer callback (hdaTimer).
-     * Used to calculate the time actually elapsed between two timer callbacks. */
-    uint64_t                           uTimerTS;
 #endif
 #ifdef VBOX_WITH_STATISTICS
 # ifndef VBOX_WITH_AUDIO_CALLBACKS
@@ -752,11 +736,21 @@ typedef struct HDASTATE
     R3PTRTYPE(PAUDMIXSINK)             pSinkLineIn;
     /** Audio mixer sink for microphone input. */
     R3PTRTYPE(PAUDMIXSINK)             pSinkMicIn;
+    /** The controller's base time stamp which the WALCLK register
+     *  derives its current value from. */
     uint64_t                           u64BaseTS;
-    /** Response Interrupt Count (RINTCNT). */
+    /** Last updated WALCLK counter. */
+    uint64_t                           u64WalClk;
+    /** Response Interrupt Count (RINTCNT).
+     *  Needed if Response Interrupt Control (RIC) is being used .*/
     uint8_t                            u8RespIntCnt;
+    /** Current IRQ level. */
+    uint8_t                            u8IRQL;
     /** Padding for alignment. */
-    uint8_t                            au8Padding2[7];
+    uint8_t                            au8Padding2[5];
+#ifdef DEBUG
+    HDASTATEDBGINFO                    Dbg;
+#endif
 } HDASTATE;
 /** Pointer to the ICH Intel HD Audio Controller state. */
 typedef HDASTATE *PHDASTATE;
@@ -827,22 +821,33 @@ static int hdaRegWriteU16(PHDASTATE pThis, uint32_t iReg, uint32_t pu32Value);
 static int hdaRegReadU8(PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value);
 static int hdaRegWriteU8(PHDASTATE pThis, uint32_t iReg, uint32_t pu32Value);
 
-#ifdef IN_RING3
-static void hdaStreamDestroy(PHDASTREAM pStrmSt);
-//static int hdaStreamStart(PHDASTREAM pStrmSt);
-static int hdaStreamStop(PHDASTREAM pStrmSt);
-//static int hdaStreamWaitForStateChange(PHDASTREAM pStrmSt, RTMSINTERVAL msTimeout);
-static int hdaTransfer(PHDASTATE pThis, ENMSOUNDSOURCE enmSrc, uint32_t cbToProcess, uint32_t *pcbProcessed);
-#endif
 
 #ifdef IN_RING3
+static int       hdaSDFMTToStrmCfg(uint32_t u32SDFMT, PPDMAUDIOSTREAMCFG pCfg);
+
+static void      hdaStreamDestroy(PHDASTREAM pStream);
+static uint32_t  hdaStreamTransferGetElapsed(PHDASTATE pThis, PHDASTREAM pStream);
+static void      hdaStreamTransfer(PHDASTATE pThis, PHDASTREAM pStream, uint32_t cbToProcessMax);
+DECLINLINE(void) hdaStreamUpdateLPIB(PHDASTATE pThis, PHDASTREAM pStream, uint32_t u32LPIB);
+
 static int       hdaBDLEFetch(PHDASTATE pThis, PHDABDLE pBDLE, uint64_t u64BaseDMA, uint16_t u16Entry);
-DECLINLINE(void) hdaStreamUpdateLPIB(PHDASTATE pThis, PHDASTREAM pStrmSt, uint32_t u32LPIB);
-# ifdef LOG_ENABLED
-static void             hdaBDLEDumpAll(PHDASTATE pThis, uint64_t u64BaseDMA, uint16_t cBDLE);
-# endif
-#endif
+static bool      hdaBDLEIsComplete(PHDABDLE pBDLE);
+static bool      hdaBDLENeedsInterrupt(PHDABDLE pBDLE);
+# ifdef DEBUG
+static void      hdaBDLEDumpAll(PHDASTATE pThis, uint64_t u64BaseDMA, uint16_t cBDLE);
+# endif /* DEBUG */
+
+# ifdef HDA_USE_DMA_ACCESS_HANDLER
+ static DECLCALLBACK(VBOXSTRICTRC) hdaDMAAccessHandler(PVM pVM, PVMCPU pVCpu, RTGCPHYS GCPhys, void *pvPhys, void *pvBuf, size_t cbBuf, PGMACCESSTYPE enmAccessType, PGMACCESSORIGIN enmOrigin, void *pvUser);
+ static bool                       hdaStreamRegisterDMAHandlers(PHDASTATE pThis, PHDASTREAM pStream);
+ static void                       hdaStreamUnregisterDMAHandlers(PHDASTATE pThis, PHDASTREAM pStream);
+# endif /* HDA_USE_DMA_ACCESS_HANDLER */
+#endif /* IN_RING3 */
 
+uint64_t          hdaWalClkGetCurrent(PHDASTATE pThis);
+#ifdef IN_RING3
+bool              hdaWalClkSet(PHDASTATE pThis, uint64_t u64WalClk, bool fForce);
+#endif
 
 /*********************************************************************************************************************************
 *   Global Variables                                                                                                             *
@@ -869,7 +874,7 @@ static void             hdaBDLEDumpAll(PHDASTATE pThis, uint64_t u64BaseDMA, uin
     /* Offset 0x83 (SD0) */ \
     { offset + 0x3,  0x00001, 0x0000001C, 0x0000003C, hdaRegReadU8  , hdaRegWriteSDSTS , HDA_REG_IDX_STRM(name, STS)  , #name " Status" }, \
     /* Offset 0x84 (SD0) */ \
-    { offset + 0x4,  0x00004, 0xFFFFFFFF, 0x00000000, hdaRegReadLPIB, hdaRegWriteU32   , HDA_REG_IDX_STRM(name, LPIB) , #name " Link Position In Buffer" }, \
+    { offset + 0x4,  0x00004, 0xFFFFFFFF, 0x00000000, hdaRegReadLPIB, hdaRegWriteUnimpl, HDA_REG_IDX_STRM(name, LPIB) , #name " Link Position In Buffer" }, \
     /* Offset 0x88 (SD0) */ \
     { offset + 0x8,  0x00004, 0xFFFFFFFF, 0xFFFFFFFF, hdaRegReadU32, hdaRegWriteSDCBL  , HDA_REG_IDX_STRM(name, CBL)  , #name " Cyclic Buffer Length" }, \
     /* Offset 0x8C (SD0) */ \
@@ -985,33 +990,61 @@ static const struct
 };
 
 #ifdef IN_RING3
-/** HDABDLE field descriptors for the v6+ saved state. */
-static SSMFIELD const g_aSSMBDLEFields6[] =
+/** HDABDLEDESC field descriptors for the v7 saved state. */
+static SSMFIELD const g_aSSMBDLEDescFields7[] =
 {
-    SSMFIELD_ENTRY(HDABDLE, u64BufAdr),
-    SSMFIELD_ENTRY(HDABDLE, u32BufSize),
-    SSMFIELD_ENTRY(HDABDLE, fIntOnCompletion),
+    SSMFIELD_ENTRY(HDABDLEDESC, u64BufAdr),
+    SSMFIELD_ENTRY(HDABDLEDESC, u32BufSize),
+    SSMFIELD_ENTRY(HDABDLEDESC, fFlags),
     SSMFIELD_ENTRY_TERM()
 };
 
-/** HDABDLESTATE field descriptors for the v6+ saved state. */
+/** HDABDLESTATE field descriptors for the v6 saved state. */
 static SSMFIELD const g_aSSMBDLEStateFields6[] =
 {
     SSMFIELD_ENTRY(HDABDLESTATE, u32BDLIndex),
     SSMFIELD_ENTRY(HDABDLESTATE, cbBelowFIFOW),
-    SSMFIELD_ENTRY(HDABDLESTATE, au8FIFO),
+    SSMFIELD_ENTRY_OLD(FIFO,     HDA_FIFO_MAX), /* Deprecated; now is handled in the stream's circular buffer. */
+    SSMFIELD_ENTRY(HDABDLESTATE, u32BufOff),
+    SSMFIELD_ENTRY_TERM()
+};
+
+/** HDABDLESTATE field descriptors for the v7 saved state. */
+static SSMFIELD const g_aSSMBDLEStateFields7[] =
+{
+    SSMFIELD_ENTRY(HDABDLESTATE, u32BDLIndex),
+    SSMFIELD_ENTRY(HDABDLESTATE, cbBelowFIFOW),
     SSMFIELD_ENTRY(HDABDLESTATE, u32BufOff),
     SSMFIELD_ENTRY_TERM()
 };
 
-/** HDASTREAMSTATE field descriptors for the v6+ saved state. */
+/** HDASTREAMSTATE field descriptors for the v6 saved state. */
 static SSMFIELD const g_aSSMStreamStateFields6[] =
 {
-    SSMFIELD_ENTRY_OLD(cBDLE, 2),
+    SSMFIELD_ENTRY_OLD(cBDLE,      sizeof(uint16_t)), /* Deprecated. */
+    SSMFIELD_ENTRY(HDASTREAMSTATE, uCurBDLE),
+    SSMFIELD_ENTRY_OLD(fStop,      1),                /* Deprecated; see SSMR3PutBool(). */
+    SSMFIELD_ENTRY(HDASTREAMSTATE, fRunning),
+    SSMFIELD_ENTRY(HDASTREAMSTATE, fInReset),
+    SSMFIELD_ENTRY_TERM()
+};
+
+/** HDASTREAMSTATE field descriptors for the v7 saved state. */
+static SSMFIELD const g_aSSMStreamStateFields7[] =
+{
     SSMFIELD_ENTRY(HDASTREAMSTATE, uCurBDLE),
-    SSMFIELD_ENTRY(HDASTREAMSTATE, fDoStop),
-    SSMFIELD_ENTRY(HDASTREAMSTATE, fActive),
     SSMFIELD_ENTRY(HDASTREAMSTATE, fInReset),
+    SSMFIELD_ENTRY(HDASTREAMSTATE, uTimerTS),
+    SSMFIELD_ENTRY_TERM()
+};
+
+/** HDASTREAMPERIOD field descriptors for the v7 saved state. */
+static SSMFIELD const g_aSSMStreamPeriodFields7[] =
+{
+    SSMFIELD_ENTRY(HDASTREAMPERIOD, u64StartWalClk),
+    SSMFIELD_ENTRY(HDASTREAMPERIOD, u64ElapsedWalClk),
+    SSMFIELD_ENTRY(HDASTREAMPERIOD, framesTransferred),
+    SSMFIELD_ENTRY(HDASTREAMPERIOD, cIntPending),
     SSMFIELD_ENTRY_TERM()
 };
 #endif
@@ -1025,29 +1058,34 @@ static uint32_t const g_afMasks[5] =
 };
 
 #ifdef IN_RING3
-DECLINLINE(void) hdaStreamUpdateLPIB(PHDASTATE pThis, PHDASTREAM pStrmSt, uint32_t u32LPIB)
+/**
+ * Updates an HDA stream's current read or write buffer position (depending on the stream type) by
+ * updating its associated LPIB register and DMA position buffer (if enabled).
+ *
+ * @param   pThis               HDA state.
+ * @param   pStream             HDA stream to update read / write position for.
+ * @param   u32LPIB             Absolute position (in bytes) to set current read / write position to.
+ */
+DECLINLINE(void) hdaStreamUpdateLPIB(PHDASTATE pThis, PHDASTREAM pStream, uint32_t u32LPIB)
 {
     AssertPtrReturnVoid(pThis);
-    AssertPtrReturnVoid(pStrmSt);
+    AssertPtrReturnVoid(pStream);
 
-    Assert(u32LPIB <= pStrmSt->u32CBL);
+    Assert(u32LPIB <= pStream->u32CBL);
 
-    LogFlowFunc(("[SD%RU8]: LPIB=%RU32 (DMA Position Buffer Enabled: %RTbool)\n",
-                 pStrmSt->u8Strm, u32LPIB, pThis->fDMAPosition));
+    Log3Func(("[SD%RU8] LPIB=%RU32 (DMA Position Buffer Enabled: %RTbool)\n",
+              pStream->u8SD, u32LPIB, pThis->fDMAPosition));
 
     /* Update LPIB in any case. */
-    HDA_STREAM_REG(pThis, LPIB, pStrmSt->u8Strm) = u32LPIB;
+    HDA_STREAM_REG(pThis, LPIB, pStream->u8SD) = u32LPIB;
 
     /* Do we need to tell the current DMA position? */
     if (pThis->fDMAPosition)
     {
         int rc2 = PDMDevHlpPCIPhysWrite(pThis->CTX_SUFF(pDevIns),
-                                        (pThis->u64DPBase & DPBASE_ADDR_MASK) + (pStrmSt->u8Strm * 2 * sizeof(uint32_t)),
+                                        pThis->u64DPBase + (pStream->u8SD * 2 * sizeof(uint32_t)),
                                         (void *)&u32LPIB, sizeof(uint32_t));
         AssertRC(rc2);
-#ifdef DEBUG
-        hdaBDLEDumpAll(pThis, pStrmSt->u64BDLBase, pStrmSt->State.uCurBDLE);
-#endif
     }
 }
 #endif
@@ -1085,7 +1123,7 @@ DECLINLINE(uint16_t) hdaSDFIFOSToBytes(uint32_t u32RegFIFOS)
 }
 #endif
 
-#if defined(IN_RING3) && (defined(VBOX_HDA_WITH_FIFO) || defined(DEBUG))
+#if defined(IN_RING3)
 /**
  * Retrieves the number of bytes of a FIFOW register.
  *
@@ -1109,141 +1147,224 @@ DECLINLINE(uint8_t) hdaSDFIFOWToBytes(uint32_t u32RegFIFOW)
 }
 #endif
 
-#ifdef IN_RING3
-/**
- * Fetches the next BDLE to use for a stream.
- *
- * @return  IPRT status code.
- */
-DECLINLINE(int) hdaStreamGetNextBDLE(PHDASTATE pThis, PHDASTREAM pStrmSt)
-{
-    AssertPtrReturn(pThis,   VERR_INVALID_POINTER);
-    AssertPtrReturn(pStrmSt, VERR_INVALID_POINTER);
-
-    NOREF(pThis);
-
-    Assert(pStrmSt->State.uCurBDLE < pStrmSt->u16LVI + 1);
-
-#ifdef DEBUG
-    uint32_t uOldBDLE = pStrmSt->State.uCurBDLE;
-#endif
-
-    /*
-     * Switch to the next BDLE entry and do a wrap around
-     * if we reached the end of the Buffer Descriptor List (BDL).
-     */
-    pStrmSt->State.uCurBDLE++;
-    if (pStrmSt->State.uCurBDLE == pStrmSt->u16LVI + 1)
-    {
-        pStrmSt->State.uCurBDLE = 0;
-
-        hdaStreamUpdateLPIB(pThis, pStrmSt, 0);
-    }
-
-    Assert(pStrmSt->State.uCurBDLE < pStrmSt->u16LVI + 1);
-
-    int rc = hdaBDLEFetch(pThis, &pStrmSt->State.BDLE, pStrmSt->u64BDLBase, pStrmSt->State.uCurBDLE);
-
-#ifdef DEBUG
-    LogFlowFunc(("[SD%RU8]: uOldBDLE=%RU16, uCurBDLE=%RU16, LVI=%RU32, %R[bdle]\n",
-                 pStrmSt->u8Strm, uOldBDLE, pStrmSt->State.uCurBDLE, pStrmSt->u16LVI, &pStrmSt->State.BDLE));
-#endif
-    return rc;
-}
-#endif
-
-DECLINLINE(PHDASTREAM) hdaStreamFromID(PHDASTATE pThis, uint8_t uStreamID)
+DECLINLINE(PHDASTREAM) hdaStreamFromID(PHDASTATE pThis, uint8_t uSD)
 {
-    PHDASTREAM pStrmSt;
+    PHDASTREAM pStream;
 
-    switch (uStreamID)
+    switch (uSD)
     {
         case 0: /** @todo Use dynamic indices, based on stream assignment. */
         {
-            pStrmSt = &pThis->StrmStLineIn;
+            pStream = &pThis->LineIn;
             break;
         }
 # ifdef VBOX_WITH_HDA_MIC_IN
         case 2: /** @todo Use dynamic indices, based on stream assignment. */
         {
-            pStrmSt = &pThis->StrmStMicIn;
+            pStream = &pThis->MicIn;
             break;
         }
 # endif
         case 4: /** @todo Use dynamic indices, based on stream assignment. */
         {
-            pStrmSt = &pThis->StrmStOut;
+            pStream = &pThis->Out;
             break;
         }
 
         default:
         {
-            pStrmSt = NULL;
-            LogFunc(("Warning: Stream with ID=%RU8 not handled\n", uStreamID));
+            pStream = NULL;
+            LogFunc(("Stream with ID=%RU8 not handled\n", uSD));
             break;
         }
     }
 
-    return pStrmSt;
+    return pStream;
 }
 
-#ifdef IN_RING3
-/**
- * Retrieves the minimum number of bytes accumulated/free in the
- * FIFO before the controller will start a fetch/eviction of data.
- *
- * Uses SDFIFOW (FIFO Watermark Register).
- *
- * @return Number of bytes accumulated/free in the FIFO.
- */
-DECLINLINE(uint8_t) hdaStreamGetFIFOW(PHDASTATE pThis, PHDASTREAM pStrmSt)
+static uint32_t hdaGetINTSTS(PHDASTATE pThis)
 {
-    AssertPtrReturn(pThis, 0);
-    AssertPtrReturn(pStrmSt, 0);
+    uint32_t intSts = 0;
 
-# ifdef VBOX_HDA_WITH_FIFO
-    return hdaSDFIFOWToBytes(HDA_STREAM_REG(pThis, FIFOW, pStrmSt->u8Strm));
-# else
-    return 0;
-# endif
+    if (   HDA_REG_FLAG_VALUE(pThis, RIRBSTS, RIRBOIS)
+        || HDA_REG_FLAG_VALUE(pThis, RIRBSTS, RINTFL)
+        || HDA_REG_FLAG_VALUE(pThis, CORBSTS, CMEI))
+    {
+        intSts |= HDA_INTSTS_FLAG_CIS; /* Touch Controller Interrupt Status (CIS). */
+    }
+
+    if (HDA_REG(pThis, STATESTS) & HDA_REG(pThis, WAKEEN))
+    {
+        intSts |= HDA_INTSTS_FLAG_CIS; /* Touch Controller Interrupt Status (CIS). */
+    }
+
+    Log3Func(("RIRBOIS=0x%x, RIRBSTS=0x%x, STATESTS=0x%x\n",
+              HDA_REG_FLAG_VALUE(pThis, RIRBSTS, RIRBOIS), HDA_REG_FLAG_VALUE(pThis, RIRBSTS, RINTFL),
+              (HDA_REG(pThis, STATESTS) & HDA_STATESTS_SCSF_MASK)));
+
+#define HDA_MARK_SIS(x) /* Stream Interrupt Status (SIS). */                \
+        if (   (INTCTL_SX(pThis, x))                                        \
+            && (   (SDSTS(pThis, x) & HDA_REG_FIELD_FLAG_MASK(SDSTS, DE))   \
+                || (SDSTS(pThis, x) & HDA_REG_FIELD_FLAG_MASK(SDSTS, FE))   \
+                || (SDSTS(pThis, x) & HDA_REG_FIELD_FLAG_MASK(SDSTS, BCIS)) \
+               )                                                            \
+           )                                                                \
+    {                                                                       \
+        Log3Func(("[SD%RU8] Marked %R[sdsts]\n", x, SDSTS(pThis, x)));      \
+        intSts |= RT_BIT(x);                                                \
+    }
+
+    HDA_MARK_SIS(0);
+    HDA_MARK_SIS(1);
+    HDA_MARK_SIS(2);
+    HDA_MARK_SIS(3);
+    HDA_MARK_SIS(4);
+    HDA_MARK_SIS(5);
+    HDA_MARK_SIS(6);
+    HDA_MARK_SIS(7);
+
+#undef HDA_MARK_SIS
+
+    if (   (intSts & HDA_INTSTS_FLAG_CIS)
+        || (intSts & HDA_INTSTS_MASK_SIS))
+    {
+        intSts |= HDA_INTSTS_FLAG_GIS; /* Touch Global Interrupt Status (GIS). */
+    }
+
+    Log3Func(("-> 0x%x\n", intSts));
+
+    return intSts;
 }
-#endif
 
+#ifndef DEBUG
 static int hdaProcessInterrupt(PHDASTATE pThis)
+#else
+static int hdaProcessInterrupt(PHDASTATE pThis, const char *pszSource)
+#endif
 {
-#define IS_INTERRUPT_OCCURED_AND_ENABLED(pThis, num) \
-        (   INTCTL_SX((pThis), num) \
-         && (SDSTS(pThis, num) & HDA_REG_FIELD_FLAG_MASK(SDSTS, BCIS)))
+    HDA_REG(pThis, INTSTS) = hdaGetINTSTS(pThis);
+
+    Log3Func(("IRQL=%RU8\n", pThis->u8IRQL));
+
+    /* Global Interrupt Enable (GIE) set? */
+    if (   HDA_REG_FLAG_VALUE(pThis, INTCTL, GIE)
+        && ((HDA_REG(pThis, INTSTS) & ~HDA_INTSTS_FLAG_GIS) & HDA_REG(pThis, INTCTL)))
+    {
+        if (!pThis->u8IRQL)
+        {
+#ifdef DEBUG
+            if (!pThis->Dbg.IRQ.tsProcessedLastNs)
+                pThis->Dbg.IRQ.tsProcessedLastNs = RTTimeNanoTS();
+
+            const uint64_t tsLastElapsedNs = RTTimeNanoTS() - pThis->Dbg.IRQ.tsProcessedLastNs;
 
-    bool fIrq = false;
+            if (!pThis->Dbg.IRQ.tsAssertedNs)
+                pThis->Dbg.IRQ.tsAssertedNs = RTTimeNanoTS();
 
-    if (/* Controller Interrupt Enable (CIE). */
-          HDA_REG_FLAG_VALUE(pThis, INTCTL, CIE)
-       && (   HDA_REG_FLAG_VALUE(pThis, RIRBSTS, RINTFL)
-           || HDA_REG_FLAG_VALUE(pThis, RIRBSTS, RIRBOIS)
-           || (HDA_REG(pThis, STATESTS) & HDA_REG(pThis, WAKEEN))))
-        fIrq = true;
+            const uint64_t tsAssertedElapsedNs = RTTimeNanoTS() - pThis->Dbg.IRQ.tsAssertedNs;
 
-    /** @todo Don't hardcode stream numbers here. */
-    if (   IS_INTERRUPT_OCCURED_AND_ENABLED(pThis, 0)
-        || IS_INTERRUPT_OCCURED_AND_ENABLED(pThis, 4))
+            pThis->Dbg.IRQ.cAsserted++;
+            pThis->Dbg.IRQ.tsAssertedTotalNs += tsAssertedElapsedNs;
+
+            const uint64_t avgAssertedUs = (pThis->Dbg.IRQ.tsAssertedTotalNs / pThis->Dbg.IRQ.cAsserted) / 1000;
+
+            if (avgAssertedUs > (1000 / HDA_TIMER_HZ) /* ms */ * 1000) /* Exceeds time slot? */
+                Log3Func(("Asserted (%s): %zuus elapsed (%zuus on average) -- %zuus alternation delay\n",
+                          pszSource, tsAssertedElapsedNs / 1000,
+                          avgAssertedUs,
+                          (pThis->Dbg.IRQ.tsDeassertedNs - pThis->Dbg.IRQ.tsAssertedNs) / 1000));
+#endif
+            Log3Func(("Asserted (%s): %RU64us between alternation (WALCLK=%RU64)\n",
+                      pszSource, tsLastElapsedNs / 1000, pThis->u64WalClk));
+
+            PDMDevHlpPCISetIrq(pThis->CTX_SUFF(pDevIns), 0, 1 /* Assert */);
+            pThis->u8IRQL = 1;
+
+#ifdef DEBUG
+            pThis->Dbg.IRQ.tsAssertedNs = RTTimeNanoTS();
+            pThis->Dbg.IRQ.tsProcessedLastNs = pThis->Dbg.IRQ.tsAssertedNs;
+#endif
+        }
+    }
+    else
     {
-#ifdef IN_RING3
-        LogFunc(("BCIS\n"));
+        if (pThis->u8IRQL)
+        {
+#ifdef DEBUG
+            if (!pThis->Dbg.IRQ.tsProcessedLastNs)
+                pThis->Dbg.IRQ.tsProcessedLastNs = RTTimeNanoTS();
+
+            const uint64_t tsLastElapsedNs = RTTimeNanoTS() - pThis->Dbg.IRQ.tsProcessedLastNs;
+
+            if (!pThis->Dbg.IRQ.tsDeassertedNs)
+                pThis->Dbg.IRQ.tsDeassertedNs = RTTimeNanoTS();
+
+            const uint64_t tsDeassertedElapsedNs = RTTimeNanoTS() - pThis->Dbg.IRQ.tsDeassertedNs;
+
+            pThis->Dbg.IRQ.cDeasserted++;
+            pThis->Dbg.IRQ.tsDeassertedTotalNs += tsDeassertedElapsedNs;
+
+            const uint64_t avgDeassertedUs = (pThis->Dbg.IRQ.tsDeassertedTotalNs / pThis->Dbg.IRQ.cDeasserted) / 1000;
+
+            if (avgDeassertedUs > (1000 / HDA_TIMER_HZ) /* ms */ * 1000) /* Exceeds time slot? */
+                Log3Func(("Deasserted (%s): %zuus elapsed (%zuus on average)\n",
+                          pszSource, tsDeassertedElapsedNs / 1000, avgDeassertedUs));
+
+            Log3Func(("Deasserted (%s): %RU64us between alternation (WALCLK=%RU64)\n",
+                      pszSource, tsLastElapsedNs / 1000, pThis->u64WalClk));
 #endif
-        fIrq = true;
+            PDMDevHlpPCISetIrq(pThis->CTX_SUFF(pDevIns), 0, 0 /* Deassert */);
+            pThis->u8IRQL = 0;
+
+#ifdef DEBUG
+            pThis->Dbg.IRQ.tsDeassertedNs    = RTTimeNanoTS();
+            pThis->Dbg.IRQ.tsProcessedLastNs = pThis->Dbg.IRQ.tsDeassertedNs;
+#endif
+        }
     }
 
-    if (HDA_REG_FLAG_VALUE(pThis, INTCTL, GIE))
-    {
-        LogFunc(("%s\n", fIrq ? "Asserted" : "Deasserted"));
-        PDMDevHlpPCISetIrq(pThis->CTX_SUFF(pDevIns), 0 , fIrq);
+    return VINF_SUCCESS;
+}
+
+#ifdef IN_RING3
+/**
+ * Reschedules pending interrupts for all audio streams which have complete
+ * audio periods but did not have the chance to issue their (pending) interrupts yet.
+ *
+ * @param   pThis               The HDA device state.
+ */
+static void hdaReschedulePendingInterrupts(PHDASTATE pThis)
+{
+    bool fInterrupt = false;
+
+#define HDA_STREAM_MARK_INT(_aStream) \
+    if (   hdaStreamPeriodIsComplete(&_aStream.State.Period) \
+        && hdaStreamPeriodNeedsInterrupt(&_aStream.State.Period) \
+        && hdaWalClkSet(pThis, hdaStreamPeriodGetAbsElapsedWalClk(&_aStream.State.Period), false /* fForce */)) \
+    { \
+        fInterrupt = true; \
     }
 
-#undef IS_INTERRUPT_OCCURED_AND_ENABLED
+    HDA_STREAM_MARK_INT(pThis->Out);
+    HDA_STREAM_MARK_INT(pThis->LineIn);
+#ifdef VBOX_WITH_HDA_MIC_IN
+    HDA_STREAM_MARK_INT(pThis->MicIn);
+#endif
+
+#undef HDA_STREAM_MARK_INT
 
-    return VINF_SUCCESS;
+    LogFunc(("fInterrupt=%RTbool\n", fInterrupt));
+
+    if (fInterrupt)
+    {
+#ifndef DEBUG
+        hdaProcessInterrupt(pThis);
+#else
+        hdaProcessInterrupt(pThis, __FUNCTION__);
+#endif
+    }
 }
+#endif
 
 /**
  * Looks up a register at the exact offset given by @a offReg.
@@ -1357,12 +1478,17 @@ static int hdaRegLookupWithin(PHDASTATE pThis, uint32_t offReg)
 }
 
 #ifdef IN_RING3
+
 static int hdaCmdSync(PHDASTATE pThis, bool fLocal)
 {
     int rc = VINF_SUCCESS;
     if (fLocal)
     {
         Assert((HDA_REG_FLAG_VALUE(pThis, CORBCTL, DMA)));
+        Assert(pThis->u64CORBBase);
+        AssertPtr(pThis->pu32CorbBuf);
+        Assert(pThis->cbCorbBuf);
+
         rc = PDMDevHlpPhysRead(pThis->CTX_SUFF(pDevIns), pThis->u64CORBBase, pThis->pu32CorbBuf, pThis->cbCorbBuf);
         if (RT_FAILURE(rc))
             AssertRCReturn(rc, rc);
@@ -1429,7 +1555,9 @@ static int hdaCORBCmdProcess(PHDASTATE pThis)
     uint8_t rirbWp = HDA_REG(pThis, RIRBWP);
 
     Assert((corbWp != corbRp));
-    LogFlowFunc(("CORB(RP:%x, WP:%x) RIRBWP:%x\n", HDA_REG(pThis, CORBRP), HDA_REG(pThis, CORBWP), HDA_REG(pThis, RIRBWP)));
+
+    Log3Func(("CORB(RP:%x, WP:%x) RIRBWP:%x\n",
+              HDA_REG(pThis, CORBRP), HDA_REG(pThis, CORBWP), HDA_REG(pThis, RIRBWP)));
 
     while (corbRp != corbWp)
     {
@@ -1465,202 +1593,193 @@ static int hdaCORBCmdProcess(PHDASTATE pThis)
         if (pThis->u8RespIntCnt == RINTCNT_N(pThis))
             break;
     }
+
     HDA_REG(pThis, CORBRP) = corbRp;
     HDA_REG(pThis, RIRBWP) = rirbWp;
+
     rc = hdaCmdSync(pThis, false);
-    LogFunc(("CORB(RP:%x, WP:%x) RIRBWP:%x\n", HDA_REG(pThis, CORBRP),
-         HDA_REG(pThis, CORBWP), HDA_REG(pThis, RIRBWP)));
-    if (HDA_REG_FLAG_VALUE(pThis, RIRBCTL, RIC))
+
+    Log3Func(("CORB(RP:%x, WP:%x) RIRBWP:%x\n",
+              HDA_REG(pThis, CORBRP), HDA_REG(pThis, CORBWP), HDA_REG(pThis, RIRBWP)));
+
+    if (HDA_REG_FLAG_VALUE(pThis, RIRBCTL, RIC)) /* Response Interrupt Control (RIC) enabled? */
     {
-        HDA_REG(pThis, RIRBSTS) |= HDA_REG_FIELD_FLAG_MASK(RIRBSTS,RINTFL);
+        if (pThis->u8RespIntCnt)
+        {
+            pThis->u8RespIntCnt = 0;
 
-        pThis->u8RespIntCnt = 0;
-        rc = hdaProcessInterrupt(pThis);
+            HDA_REG(pThis, RIRBSTS) |= HDA_REG_FIELD_FLAG_MASK(RIRBSTS, RINTFL);
+
+#ifndef DEBUG
+            rc = hdaProcessInterrupt(pThis);
+#else
+            rc = hdaProcessInterrupt(pThis, __FUNCTION__);
+#endif
+        }
     }
+
     if (RT_FAILURE(rc))
         AssertRCReturn(rc, rc);
+
     return rc;
 }
 
-static int hdaStreamCreate(PHDASTREAM pStrmSt)
+static int hdaStreamCreate(PHDASTREAM pStream)
 {
-    AssertPtrReturn(pStrmSt, VERR_INVALID_POINTER);
+    AssertPtrReturn(pStream, VERR_INVALID_POINTER);
 
-    int rc = RTSemEventCreate(&pStrmSt->State.hStateChangedEvent);
-    AssertRC(rc);
+    pStream->u8SD           = UINT8_MAX;
+
+    pStream->State.fRunning = false;
+    pStream->State.fInReset = false;
 
-    pStrmSt->u8Strm         = UINT8_MAX;
+    int rc = RTCircBufCreate(&pStream->State.pCircBuf, _64K); /** @todo Make this configurable. */
+
+#ifdef HDA_USE_DMA_ACCESS_HANDLER
+    RTListInit(&pStream->State.lstDMAHandlers);
+#endif
+
+    if (RT_SUCCESS(rc))
+        rc = hdaStreamPeriodCreate(&pStream->State.Period);
 
-    pStrmSt->State.fActive  = false;
-    pStrmSt->State.fInReset = false;
-    pStrmSt->State.fDoStop  = false;
+#ifdef DEBUG
+    int rc2 = RTCritSectInit(&pStream->Dbg.CritSect);
+    AssertRC(rc2);
+#endif
 
     LogFlowFuncLeaveRC(rc);
     return rc;
 }
 
-static void hdaStreamDestroy(PHDASTREAM pStrmSt)
+static void hdaStreamDestroy(PHDASTREAM pStream)
 {
-    AssertPtrReturnVoid(pStrmSt);
-
-    LogFlowFunc(("[SD%RU8]: Destroy\n", pStrmSt->u8Strm));
+    AssertPtrReturnVoid(pStream);
 
-    int rc2 = hdaStreamStop(pStrmSt);
-    AssertRC(rc2);
+    LogFlowFunc(("[SD%RU8] Destroy\n", pStream->u8SD));
 
-    if (pStrmSt->State.hStateChangedEvent != NIL_RTSEMEVENT)
+    if (pStream->State.pCircBuf)
     {
-        rc2 = RTSemEventDestroy(pStrmSt->State.hStateChangedEvent);
-        AssertRC(rc2);
+        RTCircBufDestroy(pStream->State.pCircBuf);
+        pStream->State.pCircBuf = NULL;
     }
 
+    hdaStreamPeriodDestroy(&pStream->State.Period);
+
+#ifdef DEBUG
+    int rc2 = RTCritSectDelete(&pStream->Dbg.CritSect);
+    AssertRC(rc2);
+#endif
+
     LogFlowFuncLeave();
 }
 
-static int hdaStreamInit(PHDASTATE pThis, PHDASTREAM pStrmSt, uint8_t u8Strm)
+static int hdaStreamInit(PHDASTATE pThis, PHDASTREAM pStream, uint8_t uSD)
 {
     AssertPtrReturn(pThis,   VERR_INVALID_POINTER);
-    AssertPtrReturn(pStrmSt, VERR_INVALID_POINTER);
-
-    pStrmSt->u8Strm     = u8Strm;
-    pStrmSt->u64BDLBase = RT_MAKE_U64(HDA_STREAM_REG(pThis, BDPL, pStrmSt->u8Strm),
-                                      HDA_STREAM_REG(pThis, BDPU, pStrmSt->u8Strm));
-    pStrmSt->u16LVI     = HDA_STREAM_REG(pThis, LVI, pStrmSt->u8Strm);
-    pStrmSt->u32CBL     = HDA_STREAM_REG(pThis, CBL, pStrmSt->u8Strm);
-    pStrmSt->u16FIFOS   = hdaSDFIFOSToBytes(HDA_STREAM_REG(pThis, FIFOS, pStrmSt->u8Strm));
+    AssertPtrReturn(pStream, VERR_INVALID_POINTER);
 
-    RT_ZERO(pStrmSt->State.BDLE);
-    pStrmSt->State.uCurBDLE = 0;
+    pStream->u8SD       = uSD;
+    pStream->u64BDLBase = RT_MAKE_U64(HDA_STREAM_REG(pThis, BDPL, pStream->u8SD),
+                                      HDA_STREAM_REG(pThis, BDPU, pStream->u8SD));
+    pStream->u16LVI     = HDA_STREAM_REG(pThis, LVI, pStream->u8SD);
+    pStream->u32CBL     = HDA_STREAM_REG(pThis, CBL, pStream->u8SD);
+    pStream->u16FIFOS   = hdaSDFIFOSToBytes(HDA_STREAM_REG(pThis, FIFOS, pStream->u8SD));
 
-    LogFlowFunc(("[SD%RU8]: DMA @ 0x%x (%RU32 bytes), LVI=%RU16, FIFOS=%RU16\n",
-                 pStrmSt->u8Strm, pStrmSt->u64BDLBase, pStrmSt->u32CBL, pStrmSt->u16LVI, pStrmSt->u16FIFOS));
+    /* Make sure to also update the stream's DMA counter (base on its current LPIB value). */
+    hdaStreamUpdateLPIB(pThis, pStream, HDA_STREAM_REG(pThis, LPIB, pStream->u8SD));
 
-#ifdef DEBUG
-    uint64_t u64BaseDMA = RT_MAKE_U64(HDA_STREAM_REG(pThis, BDPL, u8Strm),
-                                      HDA_STREAM_REG(pThis, BDPU, u8Strm));
-    uint16_t u16LVI     = HDA_STREAM_REG(pThis, LVI, u8Strm);
-    uint32_t u32CBL     = HDA_STREAM_REG(pThis, CBL, u8Strm);
-
-    LogFlowFunc(("\t-> DMA @ 0x%x, LVI=%RU16, CBL=%RU32\n", u64BaseDMA, u16LVI, u32CBL));
+    int rc = hdaSDFMTToStrmCfg(HDA_STREAM_REG(pThis, FMT, uSD), &pStream->State.strmCfg);
+    if (RT_FAILURE(rc))
+        LogRel(("HDA: Warning: Format 0x%x for stream #%RU8 not supported\n", HDA_STREAM_REG(pThis, FMT, uSD), uSD));
 
-    hdaBDLEDumpAll(pThis, u64BaseDMA, u16LVI + 1);
-#endif
+    LogFunc(("[SD%RU8] DMA @ 0x%x (%RU32 bytes), LVI=%RU16, FIFOS=%RU16, rc=%Rrc\n",
+             pStream->u8SD, pStream->u64BDLBase, pStream->u32CBL, pStream->u16LVI, pStream->u16FIFOS, rc));
 
-    return VINF_SUCCESS;
+    return rc;
 }
 
-static void hdaStreamReset(PHDASTATE pThis, PHDASTREAM pStrmSt, uint8_t u8Strm)
+/**
+ * Resets an HDA stream.
+ *
+ * @param   pThis               HDA state.
+ * @param   pStream             HDA stream to reset.
+ * @param   uSD                 Stream descriptor (SD) number to use for this stream.
+ */
+static void hdaStreamReset(PHDASTATE pThis, PHDASTREAM pStream, uint8_t uSD)
 {
     AssertPtrReturnVoid(pThis);
-    AssertPtrReturnVoid(pStrmSt);
-    AssertReturnVoid(u8Strm <= 7); /** @todo Use a define for MAX_STREAMS! */
+    AssertPtrReturnVoid(pStream);
+    AssertReturnVoid(uSD <= 7); /** @todo Use a define for MAX_STREAMS! */
 
 #ifdef VBOX_STRICT
-    AssertReleaseMsg(!RT_BOOL(HDA_STREAM_REG(pThis, CTL, u8Strm) & HDA_REG_FIELD_FLAG_MASK(SDCTL, RUN)),
-                     ("Cannot reset stream %RU8 while in running state\n", u8Strm));
+    AssertReleaseMsg(!RT_BOOL(HDA_STREAM_REG(pThis, CTL, uSD) & HDA_REG_FIELD_FLAG_MASK(SDCTL, RUN)),
+                     ("Cannot reset stream %RU8 while in running state\n", uSD));
 #endif
 
+    LogFunc(("[SD%RU8]: Reset\n", uSD));
+
     /*
      * Set reset state.
      */
-    Assert(ASMAtomicReadBool(&pStrmSt->State.fInReset) == false); /* No nested calls. */
-    ASMAtomicXchgBool(&pStrmSt->State.fInReset, true);
+    Assert(ASMAtomicReadBool(&pStream->State.fInReset) == false); /* No nested calls. */
+    ASMAtomicXchgBool(&pStream->State.fInReset, true);
+    ASMAtomicXchgBool(&pStream->State.fRunning, false);
 
     /*
-     * First, reset the internal stream state.
+     * Initialize the registers.
      */
-    RT_BZERO(pStrmSt, sizeof(HDASTREAM));
 
-    /*
-     * Second, initialize the registers.
-     */
-    HDA_STREAM_REG(pThis, STS,   u8Strm) = 0;
+    HDA_STREAM_REG(pThis, STS,   uSD) = HDA_REG_FIELD_FLAG_MASK(SDSTS, FIFORDY);
     /* According to the ICH6 datasheet, 0x40000 is the default value for stream descriptor register 23:20
      * bits are reserved for stream number 18.2.33, resets SDnCTL except SRST bit. */
-    HDA_STREAM_REG(pThis, CTL,   u8Strm) = 0x40000 | (HDA_STREAM_REG(pThis, CTL, u8Strm) & HDA_REG_FIELD_FLAG_MASK(SDCTL, SRST));
-    /* ICH6 defines default values (0x77 for input and 0xBF for output descriptors) of FIFO size. 18.2.39. */
-    HDA_STREAM_REG(pThis, FIFOS, u8Strm) = u8Strm < 4 ? HDA_SDINFIFO_120B : HDA_SDONFIFO_192B;
+    HDA_STREAM_REG(pThis, CTL,   uSD) = 0x40000 | (HDA_STREAM_REG(pThis, CTL, uSD) & HDA_REG_FIELD_FLAG_MASK(SDCTL, SRST));
+    /* ICH6 defines default values (120 bytes for input and 192 bytes for output descriptors) of FIFO size. 18.2.39. */
+    HDA_STREAM_REG(pThis, FIFOS, uSD) = uSD < 4 ? HDA_SDINFIFO_120B : HDA_SDONFIFO_192B;
     /* See 18.2.38: Always defaults to 0x4 (32 bytes). */
-    HDA_STREAM_REG(pThis, FIFOW, u8Strm) = HDA_SDFIFOW_32B;
-    HDA_STREAM_REG(pThis, LPIB,  u8Strm) = 0;
-    HDA_STREAM_REG(pThis, CBL,   u8Strm) = 0;
-    HDA_STREAM_REG(pThis, LVI,   u8Strm) = 0;
-    HDA_STREAM_REG(pThis, FMT,   u8Strm) = 0;
-    HDA_STREAM_REG(pThis, BDPU,  u8Strm) = 0;
-    HDA_STREAM_REG(pThis, BDPL,  u8Strm) = 0;
-
-    /*
-     * Third, set the internal state according to the just set registers.
-     */
-    pStrmSt->u8Strm   = u8Strm;
-    pStrmSt->u16FIFOS = HDA_STREAM_REG(pThis, FIFOS, u8Strm);
-
-
-    /* Report that we're done resetting this stream. */
-    HDA_STREAM_REG(pThis, CTL,   u8Strm) = 0;
-
-    LogFunc(("[SD%RU8]: Reset\n", u8Strm));
-
-    /* Exit reset mode. */
-    ASMAtomicXchgBool(&pStrmSt->State.fInReset, false);
-}
-
-#if 0 // unused
-static int hdaStreamStart(PHDASTREAM pStrmSt)
-{
-    AssertPtrReturn(pStrmSt, VERR_INVALID_POINTER);
-
-    ASMAtomicXchgBool(&pStrmSt->State.fDoStop, false);
-    ASMAtomicXchgBool(&pStrmSt->State.fActive, true);
-
-    LogFlowFuncLeave();
-    return VINF_SUCCESS;
-}
+    HDA_STREAM_REG(pThis, FIFOW, uSD) = HDA_SDFIFOW_32B;
+    HDA_STREAM_REG(pThis, LPIB,  uSD) = 0;
+    HDA_STREAM_REG(pThis, CBL,   uSD) = 0;
+    HDA_STREAM_REG(pThis, LVI,   uSD) = 0;
+    HDA_STREAM_REG(pThis, FMT,   uSD) = 0;
+    HDA_STREAM_REG(pThis, BDPU,  uSD) = 0;
+    HDA_STREAM_REG(pThis, BDPL,  uSD) = 0;
+
+#ifdef HDA_USE_DMA_ACCESS_HANDLER
+    hdaStreamUnregisterDMAHandlers(pThis, pStream);
 #endif
 
-static int hdaStreamStop(PHDASTREAM pStrmSt)
-{
-    AssertPtrReturn(pStrmSt, VERR_INVALID_POINTER);
+    RT_ZERO(pStream->State.BDLE);
+    pStream->State.uCurBDLE = 0;
 
-    /* Already in stopped state? */
-    bool fActive = ASMAtomicReadBool(&pStrmSt->State.fActive);
-    if (!fActive)
-        return VINF_SUCCESS;
+    if (pStream->State.pCircBuf)
+        RTCircBufReset(pStream->State.pCircBuf);
 
-#if 0 /** @todo Does not work (yet), as EMT deadlocks then. */
-    /*
-     * Wait for the stream to stop.
-     */
-    ASMAtomicXchgBool(&pStrmSt->State.fDoStop, true);
+    /* (Re-)initialize the stream with current values. */
+    int rc2 = hdaStreamInit(pThis, pStream, uSD);
+    AssertRC(rc2);
 
-    int rc = hdaStreamWaitForStateChange(pStrmSt, 60 * 1000 /* ms timeout */);
-    fActive = ASMAtomicReadBool(&pStrmSt->State.fActive);
-    if (   /* Waiting failed? */
-           RT_FAILURE(rc)
-           /* Stream is still active? */
-        || fActive)
-    {
-        AssertRC(rc);
-        LogRel(("HDA: Warning: Unable to stop stream %RU8 (state: %s), rc=%Rrc\n",
-                pStrmSt->u8Strm, fActive ? "active" : "stopped", rc));
-    }
-#else
-    int rc = VINF_SUCCESS;
+    /* Reset the stream's period. */
+    hdaStreamPeriodReset(&pStream->State.Period);
+
+#ifdef DEBUG
+    pStream->Dbg.cReadsTotal      = 0;
+    pStream->Dbg.cbReadTotal      = 0;
+    pStream->Dbg.tsLastReadNs     = 0;
+    pStream->Dbg.cWritesTotal     = 0;
+    pStream->Dbg.cbWrittenTotal   = 0;
+    pStream->Dbg.cWritesHz        = 0;
+    pStream->Dbg.cbWrittenHz      = 0;
+    pStream->Dbg.tsWriteSlotBegin = 0;
 #endif
 
-    LogFlowFuncLeaveRC(rc);
-    return rc;
-}
+    /* Report that we're done resetting this stream. */
+    HDA_STREAM_REG(pThis, CTL,   uSD) = 0;
 
-#if 0 // unused
-static int hdaStreamWaitForStateChange(PHDASTREAM pStrmSt, RTMSINTERVAL msTimeout)
-{
-    AssertPtrReturn(pStrmSt, VERR_INVALID_POINTER);
+    LogFunc(("[SD%RU8] Reset\n", uSD));
 
-    LogFlowFunc(("[SD%RU8]: msTimeout=%RU32\n", pStrmSt->u8Strm, msTimeout));
-    return RTSemEventWait(pStrmSt->State.hStateChangedEvent, msTimeout);
+    /* Exit reset mode. */
+    ASMAtomicXchgBool(&pStream->State.fInReset, false);
 }
-#endif
 #endif /* IN_RING3 */
 
 /* Register access handlers. */
@@ -1785,84 +1904,173 @@ static int hdaRegWriteSTATESTS(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value
     uint32_t iRegMem = g_aHdaRegMap[iReg].mem_idx;
 
     uint32_t v = pThis->au32Regs[iRegMem];
-    uint32_t nv = u32Value & HDA_STATES_SCSF;
+    uint32_t nv = u32Value & HDA_STATESTS_SCSF_MASK;
     pThis->au32Regs[iRegMem] &= ~(v & nv); /* write of 1 clears corresponding bit */
     return VINF_SUCCESS;
 }
 
 static int hdaRegReadINTSTS(PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value)
 {
+#ifdef IN_RING3
     RT_NOREF(iReg);
-    uint32_t v = 0;
-    if (   HDA_REG_FLAG_VALUE(pThis, RIRBSTS, RIRBOIS)
-        || HDA_REG_FLAG_VALUE(pThis, RIRBSTS, RINTFL)
-        || HDA_REG_FLAG_VALUE(pThis, CORBSTS, CMEI)
-        || HDA_REG(pThis, STATESTS))
-    {
-        v |= RT_BIT(30); /* Touch CIS. */
-    }
-
-#define HDA_IS_STREAM_EVENT(pThis, num)                                  \
-       (   (SDSTS((pThis), num) & HDA_REG_FIELD_FLAG_MASK(SDSTS, DE))    \
-        || (SDSTS((pThis), num) & HDA_REG_FIELD_FLAG_MASK(SDSTS, FE))    \
-        || (SDSTS((pThis), num) & HDA_REG_FIELD_FLAG_MASK(SDSTS, BCIS)))
-
-#define HDA_MARK_STREAM(pThis, num, v) \
-        do { (v) |= HDA_IS_STREAM_EVENT((pThis), num) ? RT_BIT((num)) : 0; } while(0)
-
-    HDA_MARK_STREAM(pThis, 0, v);
-    HDA_MARK_STREAM(pThis, 1, v);
-    HDA_MARK_STREAM(pThis, 2, v);
-    HDA_MARK_STREAM(pThis, 3, v);
-    HDA_MARK_STREAM(pThis, 4, v);
-    HDA_MARK_STREAM(pThis, 5, v);
-    HDA_MARK_STREAM(pThis, 6, v);
-    HDA_MARK_STREAM(pThis, 7, v);
 
-#undef HDA_IS_STREAM_EVENT
-#undef HDA_MARK_STREAM
+    *pu32Value = HDA_REG(pThis, INTSTS);
 
-    v |= v ? RT_BIT(31) : 0;
-
-    *pu32Value = v;
     return VINF_SUCCESS;
+#else
+    RT_NOREF(pThis, iReg, pu32Value);
+    return VINF_IOM_R3_MMIO_WRITE;
+#endif
 }
 
 static int hdaRegReadLPIB(PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value)
 {
-    const uint8_t  u8Strm  = HDA_SD_NUM_FROM_REG(pThis, LPIB, iReg);
-          uint32_t u32LPIB = HDA_STREAM_REG(pThis, LPIB, u8Strm);
+    const uint8_t  uSD     = HDA_SD_NUM_FROM_REG(pThis, LPIB, iReg);
+          uint32_t u32LPIB = HDA_STREAM_REG(pThis, LPIB, uSD);
 
 #if defined(LOG_ENABLED)
-    const uint32_t u32CBL  = HDA_STREAM_REG(pThis, CBL,  u8Strm);
-    LogFlowFunc(("[SD%RU8]: LPIB=%RU32, CBL=%RU32\n", u8Strm, u32LPIB, u32CBL));
+    const uint32_t u32CBL  = HDA_STREAM_REG(pThis, CBL, uSD);
+    LogFlowFunc(("[SD%RU8] LPIB=%RU32, CBL=%RU32\n", uSD, u32LPIB, u32CBL));
 #endif
 
     *pu32Value = u32LPIB;
     return VINF_SUCCESS;
 }
 
+/**
+ * Retrieves the currently set value for the wall clock.
+ *
+ * @return  IPRT status code.
+ * @return  Currently set wall clock value.
+ * @param   pThis               HDA state.
+ *
+ * @remark  Operation is atomic.
+ */
+uint64_t hdaWalClkGetCurrent(PHDASTATE pThis)
+{
+    return ASMAtomicReadU64(&pThis->u64WalClk);
+}
+
+#ifdef IN_RING3
+/**
+ * Returns the current maximum value the wall clock counter can be set to.
+ * This maximum value depends on all currently handled HDA streams and their own current timing.
+ *
+ * @return  Current maximum value the wall clock counter can be set to.
+ * @param   pThis               HDA state.
+ *
+ * @remark  Does not actually set the wall clock counter.
+ */
+uint64_t hdaWalClkGetMax(PHDASTATE pThis)
+{
+    const uint64_t u64WalClkCur       = ASMAtomicReadU64(&pThis->u64WalClk);
+    const uint64_t u64OutAbsWalClk    = hdaStreamPeriodGetAbsElapsedWalClk(&pThis->Out.State.Period);
+    const uint64_t u64LineInAbsWalClk = hdaStreamPeriodGetAbsElapsedWalClk(&pThis->LineIn.State.Period);
+#ifdef VBOX_WITH_HDA_MIC_IN
+    const uint64_t u64MicInAbsWalClk  = hdaStreamPeriodGetAbsElapsedWalClk(&pThis->MicIn.State.Period));
+#endif
+
+    uint64_t u64WalClkNew = RT_MAX(u64WalClkCur, u64OutAbsWalClk);
+             u64WalClkNew = RT_MAX(u64WalClkNew, u64LineInAbsWalClk);
+#ifdef VBOX_WITH_HDA_MIC_IN
+             u64WalClkNew = RT_MAX(u64WalClkNew, u64MicInAbsWalClk);
+#endif
+
+    Log3Func(("%RU64 -> Out=%RU64, LineIn=%RU64 -> %RU64\n",
+              u64WalClkCur, u64OutAbsWalClk, u64LineInAbsWalClk, u64WalClkNew));
+
+    return u64WalClkNew;
+}
+
+/**
+ * Sets the actual WALCLK register to the specified wall clock value.
+ * The specified wall clock value only will be set (unless fForce is set to @true) if all
+ * handled HDA streams have passed (in time) that value. This guarantees that the WALCLK
+ * register stays in sync with all handled HDA streams.
+ *
+ * @return  @true if the WALCLK register has been updated, @false if not.
+ * @param   pThis               HDA state.
+ * @param   u64WalClk           Wall clock value to set WALCLK register to.
+ * @param   fForce              Whether to force setting the wall clock value or not.
+ */
+bool hdaWalClkSet(PHDASTATE pThis, uint64_t u64WalClk, bool fForce)
+{
+    const bool     fOutPassed         = hdaStreamPeriodHasPassedAbsWalClk (&pThis->Out.State.Period,    u64WalClk);
+    const uint64_t u64OutAbsWalClk    = hdaStreamPeriodGetAbsElapsedWalClk(&pThis->Out.State.Period);
+    const bool     fLineInPassed      = hdaStreamPeriodHasPassedAbsWalClk (&pThis->LineIn.State.Period, u64WalClk);
+    const uint64_t u64LineInAbsWalClk = hdaStreamPeriodGetAbsElapsedWalClk(&pThis->LineIn.State.Period);
+#ifdef VBOX_WITH_HDA_MIC_IN
+    const bool     fMicInPassed       = hdaStreamPeriodHasPassedAbsWalClk (&pThis->MicIn.State.Period,  u64WalClk);
+    const uint64_t u64MicInAbsWalClk  = hdaStreamPeriodGetAbsElapsedWalClk(&pThis->MicIn.State.Period));
+#endif
+
+#ifdef VBOX_STRICT
+    const uint64_t u64WalClkCur = ASMAtomicReadU64(&pThis->u64WalClk);
+#endif
+          uint64_t u64WalClkSet = u64WalClk;
+
+    /* Only drive the WALCLK register forward if all (active) stream periods have passed
+     * the specified point in time given by u64WalClk. */
+    if (  (   fOutPassed
+           && fLineInPassed
+#ifdef VBOX_WITH_HDA_MIC_IN
+           && fMicInPassed
+#endif
+          )
+       || fForce)
+    {
+        if (!fForce)
+        {
+            /* Get the maximum value of all periods we need to handle.
+             * Not the most elegant solution, but works for now ... */
+            u64WalClk = RT_MAX(u64WalClkSet, u64OutAbsWalClk);
+            u64WalClk = RT_MAX(u64WalClkSet, u64LineInAbsWalClk);
+#ifdef VBOX_WITH_HDA_MIC_IN
+            u64WalClk = RT_MAX(u64WalClkSet, u64MicInAbsWalClk);
+#endif
+            AssertMsg(u64WalClkSet > u64WalClkCur,
+                      ("Setting WALCLK to a stale or backward value (%RU64 -> %RU64) isn't a good idea really. "
+                       "Good luck with stuck audio stuff.\n", u64WalClkCur, u64WalClkSet));
+        }
+
+        /* Set the new WALCLK value. */
+        ASMAtomicWriteU64(&pThis->u64WalClk, u64WalClkSet);
+    }
+
+    const uint64_t u64WalClkNew = hdaWalClkGetCurrent(pThis);
+
+    Log3Func(("Cur: %RU64, New: %RU64 (force %RTbool) -> %RU64 %s\n",
+              u64WalClkCur, u64WalClk, fForce,
+              u64WalClkNew, u64WalClkNew == u64WalClk ? "[OK]" : "[DELAYED]"));
+
+    return (u64WalClkNew == u64WalClk);
+}
+#endif /* IN_RING3 */
+
 static int hdaRegReadWALCLK(PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value)
 {
+#ifdef IN_RING3
     RT_NOREF(iReg);
-    /* HDA spec (1a): 3.3.16 WALCLK counter ticks with 24Mhz bitclock rate. */
-    *pu32Value = (uint32_t)ASMMultU64ByU32DivByU32(PDMDevHlpTMTimeVirtGetNano(pThis->CTX_SUFF(pDevIns))
-                                                   - pThis->u64BaseTS, 24, 1000);
-    LogFlowFunc(("%RU32\n", *pu32Value));
+
+    *pu32Value = RT_LO_U32(ASMAtomicReadU64(&pThis->u64WalClk));
+
+    Log3Func(("%RU32 (max @ %RU64)\n",*pu32Value, hdaWalClkGetMax(pThis)));
+
     return VINF_SUCCESS;
+#else
+    RT_NOREF(pThis, iReg, pu32Value);
+    return VINF_IOM_R3_MMIO_WRITE;
+#endif
 }
 
 static int hdaRegWriteCORBRP(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
 {
     RT_NOREF(iReg);
     if (u32Value & HDA_REG_FIELD_FLAG_MASK(CORBRP, RST))
-    {
-        HDA_REG(pThis, CORBRP) = 0;
-    }
-#ifndef BIRD_THINKS_CORBRP_IS_MOSTLY_RO
+        HDA_REG(pThis, CORBRP) = HDA_CORBRP_RST;    /* Clears the pointer. */
     else
-        return hdaRegWriteU8(pThis, iReg, u32Value);
-#endif
+        HDA_REG(pThis, CORBRP) &= ~HDA_CORBRP_RST;  /* Only CORBRP_RST bit is writable. */
+
     return VINF_SUCCESS;
 }
 
@@ -1912,22 +2120,19 @@ static int hdaRegWriteCORBWP(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
 
 static int hdaRegWriteSDCBL(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
 {
+    if (!hdaRegWriteSDIsAllowed(pThis, iReg, u32Value))
+        return VINF_SUCCESS;
+
     int rc = hdaRegWriteU32(pThis, iReg, u32Value);
     if (RT_SUCCESS(rc))
     {
-        uint8_t u8Strm  = HDA_SD_NUM_FROM_REG(pThis, CBL, iReg);
-
-        PHDASTREAM pStrmSt = hdaStreamFromID(pThis, u8Strm);
-        if (pStrmSt)
-        {
-            pStrmSt->u32CBL = u32Value;
+        uint8_t uSD = HDA_SD_NUM_FROM_REG(pThis, CBL, iReg);
 
-            /* Reset BDLE state. */
-            RT_ZERO(pStrmSt->State.BDLE);
-            pStrmSt->State.uCurBDLE = 0;
-        }
+        PHDASTREAM pStream = hdaStreamFromID(pThis, uSD);
+        if (pStream)
+            pStream->u32CBL = u32Value;
 
-        LogFlowFunc(("[SD%RU8]: CBL=%RU32\n", u8Strm, u32Value));
+        LogFlowFunc(("[SD%RU8] CBL=%RU32\n", uSD, u32Value));
     }
     else
         AssertRCReturn(rc, VINF_SUCCESS);
@@ -1944,17 +2149,17 @@ static int hdaRegWriteSDCTL(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
     bool const fReset    = RT_BOOL(u32Value & HDA_REG_FIELD_FLAG_MASK(SDCTL, SRST));
     bool const fInReset  = RT_BOOL(HDA_REG_IND(pThis, iReg) & HDA_REG_FIELD_FLAG_MASK(SDCTL, SRST));
 
-    uint8_t u8Strm = HDA_SD_NUM_FROM_REG(pThis, CTL, iReg);
+    uint8_t uSD = HDA_SD_NUM_FROM_REG(pThis, CTL, iReg);
 
-    PHDASTREAM pStrmSt = hdaStreamFromID(pThis, u8Strm);
-    if (!pStrmSt)
+    PHDASTREAM pStream = hdaStreamFromID(pThis, uSD);
+    if (!pStream)
     {
-        LogFunc(("Warning: Changing SDCTL on non-attached stream with ID=%RU8 (iReg=0x%x)\n", u8Strm, iReg));
+        LogFunc(("Warning: Changing SDCTL on non-attached stream with ID=%RU8 (iReg=0x%x)\n", uSD, iReg));
         return hdaRegWriteU24(pThis, iReg, u32Value); /* Write 3 bytes. */
     }
 
-    LogFunc(("[SD%RU8]: fRun=%RTbool, fInRun=%RTbool, fReset=%RTbool, fInReset=%RTbool, %R[sdctl]\n",
-             u8Strm, fRun, fInRun, fReset, fInReset, u32Value));
+    LogFunc(("[SD%RU8] fRun=%RTbool, fInRun=%RTbool, fReset=%RTbool, fInReset=%RTbool, %R[sdctl]\n",
+             uSD, fRun, fInRun, fReset, fInReset, u32Value));
 
     if (fInReset)
     {
@@ -1969,7 +2174,7 @@ static int hdaRegWriteSDCTL(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
         Assert(!fInRun && !fRun);
 
         LogFunc(("Guest initiated enter to stream reset\n"));
-        hdaStreamReset(pThis, pStrmSt, u8Strm);
+        hdaStreamReset(pThis, pStream, uSD);
 #else
         return VINF_IOM_R3_MMIO_WRITE;
 #endif
@@ -1983,10 +2188,10 @@ static int hdaRegWriteSDCTL(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
         if (fInRun != fRun)
         {
             Assert(!fReset && !fInReset);
-            LogFunc(("[SD%RU8]: fRun=%RTbool\n", u8Strm, fRun));
+            LogFunc(("[SD%RU8] fRun=%RTbool\n", uSD, fRun));
 
             PHDADRIVER pDrv;
-            switch (u8Strm)
+            switch (uSD)
             {
                 case 0: /** @todo Use a variable here. Later. */
                 {
@@ -2011,15 +2216,54 @@ static int hdaRegWriteSDCTL(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
                                                        pDrv->Out.pStrmOut, fRun);
                     break;
                 }
+
                 default:
                     AssertMsgFailed(("Changing RUN bit on non-attached stream, register %RU32\n", iReg));
                     break;
             }
-        }
 
-        if (!fInRun && !fRun)
-            hdaStreamInit(pThis, pStrmSt, u8Strm);
+            /* First, set the running flag. */
+            ASMAtomicXchgBool(&pStream->State.fRunning, fRun);
+
+            if (fRun)
+            {
+                /* Re-init the stream. */
+                int rc2 = hdaStreamInit(pThis, pStream, uSD);
+                AssertRC(rc2);
+
+                /* (Re-)init the stream's period. */
+                hdaStreamPeriodInit(&pStream->State.Period,
+                                    pStream->u8SD, pStream->u16LVI, pStream->u32CBL, &pStream->State.strmCfg);
+
+                /* Begin a new period for this stream. */
+                rc2 = hdaStreamPeriodBegin(&pStream->State.Period, hdaWalClkGetCurrent(pThis)/* Use current wall clock time */);
+                AssertRC(rc2);
+
+                /* Update the stream's time stamp before starting the timer. */
+                pStream->State.uTimerTS = TMTimerGet(pThis->pTimer);
+
+#ifndef VBOX_WITH_AUDIO_CALLBACKS
+                if (!TMTimerIsActive(pThis->pTimer))
+                {
+                    pThis->tsTimerExpire = TMTimerGet(pThis->pTimer) + pThis->cTimerTicks;
+# ifdef HDA_DEBUG_TIMING
+                    pThis->Dbg.tsTimerLastCalledNs = pThis->tsTimerExpire;
+# endif
+                    /* Fire off timer. */
+                    rc2 = TMTimerSet(pThis->pTimer, pThis->tsTimerExpire);
+                    AssertRC(rc2);
+                }
+#endif
+            }
+            else
+            {
+                /* Make sure to (re-)schedule outstanding (delayed) interrupts. */
+                hdaReschedulePendingInterrupts(pThis);
 
+                /* Reset the period. */
+                hdaStreamPeriodReset(&pStream->State.Period);
+            }
+        }
 #else /* IN_RING3 */
         return VINF_IOM_R3_MMIO_WRITE;
 #endif /* !IN_RING3 */
@@ -2030,11 +2274,54 @@ static int hdaRegWriteSDCTL(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
 
 static int hdaRegWriteSDSTS(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
 {
+#ifdef IN_RING3
     uint32_t v = HDA_REG_IND(pThis, iReg);
+
+    /* Clear the corresponding bits written by the guest. */
     v &= ~(u32Value & v);
+
     HDA_REG_IND(pThis, iReg) = v;
-    hdaProcessInterrupt(pThis);
+
+    PHDASTREAM pStream = hdaStreamFromID(pThis, HDA_SD_NUM_FROM_REG(pThis, STS, iReg));
+    if (pStream)
+    {
+        /* Some guests tend to write SDnSTS even if the stream is not running.
+         * So make sure to check if the RUN bit is set first. */
+        const bool fInRun = RT_BOOL(HDA_STREAM_REG(pThis, CTL, pStream->u8SD) & HDA_REG_FIELD_FLAG_MASK(SDCTL, RUN));
+
+        Log3Func(("[SD%RU8] fRun=%RTbool %R[sdsts]\n", pStream->u8SD, fInRun, v));
+
+        PHDASTREAMPERIOD pPeriod = &pStream->State.Period;
+
+        if (hdaStreamPeriodLock(pPeriod))
+        {
+            const bool fNeedsInterrupt = hdaStreamPeriodNeedsInterrupt(pPeriod);
+            if (fNeedsInterrupt)
+                hdaStreamPeriodReleaseInterrupt(pPeriod);
+
+            if (hdaStreamPeriodIsComplete(pPeriod))
+            {
+                hdaStreamPeriodEnd(pPeriod);
+
+                if (fInRun)
+                    hdaStreamPeriodBegin(pPeriod, hdaWalClkGetCurrent(pThis) /* Use current wall clock time */);
+            }
+
+            hdaStreamPeriodUnlock(pPeriod); /* Unlock before processing interrupt. */
+
+#ifndef DEBUG
+            hdaProcessInterrupt(pThis);
+#else
+            hdaProcessInterrupt(pThis, __FUNCTION__);
+#endif
+        }
+    }
+
     return VINF_SUCCESS;
+#else /* IN_RING3 */
+    RT_NOREF(pThis, iReg, u32Value);
+    return VINF_IOM_R3_MMIO_WRITE;
+#endif /* !IN_RING3 */
 }
 
 static int hdaRegWriteSDLVI(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
@@ -2042,27 +2329,36 @@ static int hdaRegWriteSDLVI(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
     if (!hdaRegWriteSDIsAllowed(pThis, iReg, u32Value))
         return VINF_SUCCESS;
 
+#ifdef IN_RING3
     int rc = hdaRegWriteU16(pThis, iReg, u32Value);
     if (RT_SUCCESS(rc))
     {
-        uint8_t u8Strm = HDA_SD_NUM_FROM_REG(pThis, LVI, iReg);
+        uint8_t uSD = HDA_SD_NUM_FROM_REG(pThis, LVI, iReg);
 
-        PHDASTREAM pStrmSt = hdaStreamFromID(pThis, u8Strm);
-        if (pStrmSt)
+        PHDASTREAM pStream = hdaStreamFromID(pThis, uSD);
+        if (pStream)
         {
-            pStrmSt->u16LVI = u32Value;
-
-            /* Reset BDLE state. */
-            RT_ZERO(pStrmSt->State.BDLE);
-            pStrmSt->State.uCurBDLE = 0;
+            pStream->u16LVI = u32Value;
+# ifdef HDA_USE_DMA_ACCESS_HANDLER
+            if (pStream->u8SD >= 4) /* Only register for output streams. */ /** @todo Use a define. */
+            {
+                /* Try registering the DMA handlers.
+                 * As we can't be sure in which order LVI + BDL base are set, try registering in both routines. */
+                if (hdaStreamRegisterDMAHandlers(pThis, pStream))
+                    LogFunc(("[SD%RU8] DMA logging enabled\n", pStream->u8SD));
+            }
+# endif
         }
 
-        LogFlowFunc(("[SD%RU8]: CBL=%RU32\n", u8Strm, u32Value));
+        Log2Func(("[SD%RU8] LVI=%RU32\n", uSD, u32Value));
     }
     else
         AssertRCReturn(rc, VINF_SUCCESS);
 
     return rc;
+#else /* IN_RING3 */
+    return VINF_IOM_R3_MMIO_WRITE;
+#endif /* !IN_RING3 */
 }
 
 static int hdaRegWriteSDFIFOW(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
@@ -2074,9 +2370,13 @@ static int hdaRegWriteSDFIFOW(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
         case HDA_SDFIFOW_32B:
             return hdaRegWriteU16(pThis, iReg, u32Value);
         default:
-            LogFunc(("Attempt to store unsupported value(%x) in SDFIFOW\n", u32Value));
-            return hdaRegWriteU16(pThis, iReg, HDA_SDFIFOW_32B);
+            break;
     }
+
+    AssertFailed();
+
+    LogRel(("HDA: Attempt to write unsupported value (%x) for SDFIFOW\n", u32Value));
+    return hdaRegWriteU16(pThis, iReg, HDA_SDFIFOW_32B);
 }
 
 /**
@@ -2085,7 +2385,6 @@ static int hdaRegWriteSDFIFOW(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
  */
 static int hdaRegWriteSDFIFOS(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
 {
-    /** @todo Only allow updating FIFOS if RUN bit is 0? */
     uint32_t u32FIFOS = 0;
 
     switch (iReg)
@@ -2096,7 +2395,7 @@ static int hdaRegWriteSDFIFOS(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
         case HDA_REG_SD2FIFOS:
         case HDA_REG_SD3FIFOS:
         {
-            LogFunc(("Guest tries to change R/O value of FIFO size of input stream, ignoring\n"));
+            LogRel(("HDA: Guest tries to change read-only value of FIFO size of input stream, ignoring\n"));
             break;
         }
         case HDA_REG_SD4FIFOS:
@@ -2115,8 +2414,8 @@ static int hdaRegWriteSDFIFOS(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
                     break;
 
                 case HDA_SDONFIFO_256B: /** @todo r=andy Investigate this. */
-                    LogFunc(("256-bit is unsupported, HDA is switched into 192-bit mode\n"));
-                    /* Fall through is intentional. */
+                    LogRel(("HDA: 256-bit FIFO output size is unsupported, defaulting to 192-bit\n"));
+                    /* fall thru */
                 default:
                     u32FIFOS = HDA_SDONFIFO_192B;
                     break;
@@ -2133,8 +2432,13 @@ static int hdaRegWriteSDFIFOS(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
 
     if (u32FIFOS)
     {
-        LogFunc(("[SD%RU8]: Updating FIFOS to %RU32 bytes\n", 0, hdaSDFIFOSToBytes(u32FIFOS)));
-        /** @todo Update internal stream state with new FIFOS. */
+        uint8_t uSD = HDA_SD_NUM_FROM_REG(pThis, LVI, iReg);
+
+        PHDASTREAM pStream = hdaStreamFromID(pThis, uSD);
+        if (pStream)
+            pStream->u16FIFOS = RT_LO_U16(u32FIFOS) + 1;
+
+        LogFunc(("[SD%RU8] Updating FIFOS to %RU32 bytes\n", uSD, hdaSDFIFOSToBytes(u32FIFOS)));
 
         return hdaRegWriteU16(pThis, iReg, u32FIFOS);
     }
@@ -2142,7 +2446,7 @@ static int hdaRegWriteSDFIFOS(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
     return VINF_SUCCESS;
 }
 
-#if defined(IN_RING3) && defined(VBOX_WITH_HDA_CODEC_EMU)
+#ifdef IN_RING3
 static int hdaSDFMTToStrmCfg(uint32_t u32SDFMT, PPDMAUDIOSTREAMCFG pCfg)
 {
     AssertPtrReturn(pCfg, VERR_INVALID_POINTER);
@@ -2151,7 +2455,7 @@ static int hdaSDFMTToStrmCfg(uint32_t u32SDFMT, PPDMAUDIOSTREAMCFG pCfg)
 
     int rc = VINF_SUCCESS;
 
-    uint32_t u32Hz     = (u32SDFMT & HDA_SDFMT_BASE_RATE_SHIFT) ? 44100 : 48000;
+    uint32_t u32Hz     = (u32SDFMT & HDA_SDFMT_BASE_RATE_MASK) ? 44100 : 48000;
     uint32_t u32HzMult = 1;
     uint32_t u32HzDiv  = 1;
 
@@ -2218,6 +2522,8 @@ static int hdaSDFMTToStrmCfg(uint32_t u32SDFMT, PPDMAUDIOSTREAMCFG pCfg)
         pCfg->cChannels     = (u32SDFMT & 0xf) + 1;
         pCfg->enmFormat     = enmFmt;
         pCfg->enmEndianness = PDMAUDIOHOSTENDIANNESS;
+
+        LogFunc(("uHz=%RU32, cChannels=%RU8, enmFmt=%ld\n", pCfg->uHz, pCfg->cChannels, pCfg->enmFormat));
     }
 
 # undef EXTRACT_VALUE
@@ -2225,50 +2531,79 @@ static int hdaSDFMTToStrmCfg(uint32_t u32SDFMT, PPDMAUDIOSTREAMCFG pCfg)
     LogFlowFuncLeaveRC(rc);
     return rc;
 }
-#endif
+#endif /* IN_RING3 */
 
 static int hdaRegWriteSDFMT(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
 {
-#ifdef IN_RING3
-# ifdef VBOX_WITH_HDA_CODEC_EMU
-    /* No reason to re-open stream with same settings. */
-    if (u32Value == HDA_REG_IND(pThis, iReg))
+    if (!hdaRegWriteSDIsAllowed(pThis, iReg, u32Value))
         return VINF_SUCCESS;
 
+#ifdef IN_RING3
+    uint8_t uSD = HDA_SD_NUM_FROM_REG(pThis, FMT, iReg);
+
+    LogFlowFuncEnter();
+
     PDMAUDIOSTREAMCFG strmCfg;
     int rc = hdaSDFMTToStrmCfg(u32Value, &strmCfg);
     if (RT_FAILURE(rc))
+    {
+        LogRel(("HDA: Guest requested unsupported format (0x%x) for stream #%RU8, ignoring\n", u32Value, uSD));
         return VINF_SUCCESS; /* Always return success to the MMIO handler. */
+    }
 
-    uint8_t u8Strm = HDA_SD_NUM_FROM_REG(pThis, FMT, iReg);
+    /* Write the wanted stream format into the register in any case.
+     *
+     * This is important for e.g. MacOS guests, as those try to initialize streams which are not reported
+     * by the device emulation (wants 4 channels, only have 2 channels at the moment).
+     *
+     * When ignoring those (invalid) formats, this leads to MacOS thinking that the device is malfunctioning
+     * and therefore disabling the device completely. */
+    rc = hdaRegWriteU16(pThis, iReg, u32Value);
+    AssertRC(rc);
+
+    PHDASTREAM pStream = hdaStreamFromID(pThis, uSD);
+    if (!pStream)
+    {
+        LogRel(("HDA: Guest requested format (0x%x) for unhandled stream #%RU8, ignoring\n", u32Value, uSD));
+        return rc;
+    }
 
+    /** @todo Validate config? */
+    memcpy(&pStream->State.strmCfg, &strmCfg, sizeof(PDMAUDIOSTREAMCFG));
+
+# ifdef VBOX_WITH_HDA_CODEC_EMU
     PHDADRIVER pDrv;
     switch (iReg)
     {
         case HDA_REG_SD0FMT:
             RTListForEach(&pThis->lstDrv, pDrv, HDADRIVER, Node)
-                rc = hdaCodecOpenStream(pThis->pCodec, PI_INDEX, &strmCfg);
+            {
+                int rc2 = hdaCodecOpenStream(pThis->pCodec, PI_INDEX, &strmCfg);
+                AssertRC(rc2);
+            }
             break;
 #  ifdef VBOX_WITH_HDA_MIC_IN
         case HDA_REG_SD2FMT:
             RTListForEach(&pThis->lstDrv, pDrv, HDADRIVER, Node)
-                rc = hdaCodecOpenStream(pThis->pCodec, MC_INDEX, &strmCfg);
+            {
+                int rc2 = hdaCodecOpenStream(pThis->pCodec, MC_INDEX, &strmCfg);
+                AssertRC(rc2);
+            }
             break;
 #  endif
         case HDA_REG_SD4FMT:
             RTListForEach(&pThis->lstDrv, pDrv, HDADRIVER, Node)
-                rc = hdaCodecOpenStream(pThis->pCodec, PO_INDEX, &strmCfg);
+            {
+                int rc2 = hdaCodecOpenStream(pThis->pCodec, PO_INDEX, &strmCfg);
+                AssertRC(rc2);
+            }
             break;
         default:
-            LogFunc(("Warning: Changing SDFMT on non-attached stream with ID=%RU8 (iReg=0x%x)\n", u8Strm, iReg));
+            LogFunc(("Warning: Changing SDFMT on non-attached stream with ID=%RU8 (iReg=0x%x)\n", uSD, iReg));
             break;
     }
-
-    /** @todo r=andy rc gets lost; needs fixing. */
-    return hdaRegWriteU16(pThis, iReg, u32Value);
-# else /* !VBOX_WITH_HDA_CODEC_EMU */
-    return hdaRegWriteU16(pThis, iReg, u32Value);
-# endif
+# endif /* VBOX_WITH_HDA_CODEC_EMU */
+    return rc;
 #else /* !IN_RING3 */
     RT_NOREF(pThis, iReg, u32Value);
     return VINF_IOM_R3_MMIO_WRITE;
@@ -2276,28 +2611,39 @@ static int hdaRegWriteSDFMT(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
 }
 
 /* Note: Will be called for both, BDPL and BDPU, registers. */
-DECLINLINE(int) hdaRegWriteSDBDPX(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value, uint8_t u8Strm)
+DECLINLINE(int) hdaRegWriteSDBDPX(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value, uint8_t uSD)
 {
     if (!hdaRegWriteSDIsAllowed(pThis, iReg, u32Value))
         return VINF_SUCCESS;
 
+#ifdef IN_RING3
     int rc = hdaRegWriteU32(pThis, iReg, u32Value);
     if (RT_SUCCESS(rc))
     {
-        PHDASTREAM pStrmSt = hdaStreamFromID(pThis, u8Strm);
-        if (pStrmSt)
+        PHDASTREAM pStream = hdaStreamFromID(pThis, uSD);
+        if (pStream)
         {
-            pStrmSt->u64BDLBase = RT_MAKE_U64(HDA_STREAM_REG(pThis, BDPL, u8Strm),
-                                              HDA_STREAM_REG(pThis, BDPU, u8Strm));
-            /* Reset BDLE state. */
-            RT_ZERO(pStrmSt->State.BDLE);
-            pStrmSt->State.uCurBDLE = 0;
+            pStream->u64BDLBase = RT_MAKE_U64(HDA_STREAM_REG(pThis, BDPL, uSD),
+                                              HDA_STREAM_REG(pThis, BDPU, uSD));
+# ifdef HDA_USE_DMA_ACCESS_HANDLER
+            if (pStream->u8SD >= 4) /* Only register for output streams. */ /** @todo Use a define. */
+            {
+                /* Try registering the DMA handlers.
+                 * As we can't be sure in which order LVI + BDL base are set, try registering in both routines. */
+                if (hdaStreamRegisterDMAHandlers(pThis, pStream))
+                    LogFunc(("[SD%RU8] DMA logging enabled\n", pStream->u8SD));
+            }
+# endif
         }
     }
     else
         AssertRCReturn(rc, VINF_SUCCESS);
 
     return rc;
+#else /* IN_RING3 */
+    RT_NOREF(uSD);
+    return VINF_IOM_R3_MMIO_WRITE;
+#endif /* !IN_RING3 */
 }
 
 static int hdaRegWriteSDBDPL(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
@@ -2327,7 +2673,7 @@ inline bool hdaRegWriteSDIsAllowed(PHDASTATE pThis, uint32_t iReg, uint32_t u32V
     if (fIsRunning)
     {
 #ifdef VBOX_STRICT
-        AssertMsgFailed(("[SD%RU8]: Cannot write to register 0x%x (0x%x) when RUN bit is set\n",
+        AssertMsgFailed(("[SD%RU8] Cannot write to register 0x%x (0x%x) when RUN bit is set\n",
                          HDA_SD_NUM_FROM_REG(pThis, CTL, iReg), iReg, u32Value));
 #endif
         return false;
@@ -2407,9 +2753,8 @@ static int hdaRegWriteRIRBWP(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
 {
     RT_NOREF(iReg);
     if (u32Value & HDA_REG_FIELD_FLAG_MASK(RIRBWP, RST))
-    {
         HDA_REG(pThis, RIRBWP) = 0;
-    }
+
     /* The remaining bits are O, see 6.2.22 */
     return VINF_SUCCESS;
 }
@@ -2441,8 +2786,8 @@ static int hdaRegWriteBase(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
             break;
         case HDA_REG_DPLBASE:
         {
-            pThis->u64DPBase &= UINT64_C(0xFFFFFFFF00000000);
-            pThis->u64DPBase |= pThis->au32Regs[iRegMem];
+            pThis->u64DPBase = pThis->au32Regs[iRegMem] & DPBASE_ADDR_MASK;
+            Assert(pThis->u64DPBase % 128 == 0); /* Must be 128-byte aligned. */
 
             /* Also make sure to handle the DMA position enable bit. */
             pThis->fDMAPosition = pThis->au32Regs[iRegMem] & RT_BIT_32(0);
@@ -2450,8 +2795,7 @@ static int hdaRegWriteBase(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
             break;
         }
         case HDA_REG_DPUBASE:
-            pThis->u64DPBase &= UINT64_C(0x00000000FFFFFFFF);
-            pThis->u64DPBase |= ((uint64_t)pThis->au32Regs[iRegMem] << 32);
+            pThis->u64DPBase = RT_MAKE_U64(RT_LO_U32(pThis->u64DPBase) & DPBASE_ADDR_MASK, pThis->au32Regs[iRegMem]);
             break;
         default:
             AssertMsgFailed(("Invalid index\n"));
@@ -2465,14 +2809,192 @@ static int hdaRegWriteBase(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
 
 static int hdaRegWriteRIRBSTS(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
 {
-    RT_NOREF(iReg);
-    uint8_t v = HDA_REG(pThis, RIRBSTS);
+    uint32_t v = HDA_REG_IND(pThis, iReg);
+
+    /* Clear the corresponding bits written by the guest. */
     HDA_REG(pThis, RIRBSTS) &= ~(v & u32Value);
 
+#ifndef DEBUG
     return hdaProcessInterrupt(pThis);
+#else
+    return hdaProcessInterrupt(pThis, __FUNCTION__);
+#endif
 }
 
 #ifdef IN_RING3
+# ifdef HDA_USE_DMA_ACCESS_HANDLER
+/**
+ * Registers access handlers for a stream's BDLE DMA accesses.
+ *
+ * @returns true if registration was successful, false if not.
+ * @param   pThis               HDA state.
+ * @param   pStream             HDA stream to register BDLE access handlers for.
+ */
+static bool hdaStreamRegisterDMAHandlers(PHDASTATE pThis, PHDASTREAM pStream)
+{
+    /* At least LVI and the BDL base must be set. */
+    if (   !pStream->u16LVI
+        || !pStream->u64BDLBase)
+    {
+        return false;
+    }
+
+    hdaStreamUnregisterDMAHandlers(pThis, pStream);
+
+    LogFunc(("Registering ...\n"));
+
+    int rc = VINF_SUCCESS;
+
+    /*
+     * Create BDLE ranges.
+     */
+
+    struct BDLERANGE
+    {
+        RTGCPHYS uAddr;
+        uint32_t uSize;
+    } arrRanges[16]; /** @todo Use a define. */
+
+    size_t cRanges = 0;
+
+    for (uint16_t i = 0; i < pStream->u16LVI + 1; i++)
+    {
+        HDABDLE BDLE;
+        rc = hdaBDLEFetch(pThis, &BDLE, pStream->u64BDLBase, i /* Index */);
+        if (RT_FAILURE(rc))
+            break;
+
+        bool fAddRange = true;
+        BDLERANGE *pRange;
+
+        if (cRanges)
+        {
+            pRange = &arrRanges[cRanges - 1];
+
+            /* Is the current range a direct neighbor of the current BLDE? */
+            if ((pRange->uAddr + pRange->uSize) == BDLE.Desc.u64BufAdr)
+            {
+                /* Expand the current range by the current BDLE's size. */
+                pRange->uSize += BDLE.Desc.u32BufSize;
+
+                /* Adding a new range in this case is not needed anymore. */
+                fAddRange = false;
+
+                LogFunc(("Expanding range %zu by %RU32 (%RU32 total now)\n", cRanges - 1, BDLE.Desc.u32BufSize, pRange->uSize));
+            }
+        }
+
+        /* Do we need to add a new range? */
+        if (   fAddRange
+            && cRanges < RT_ELEMENTS(arrRanges))
+        {
+            pRange = &arrRanges[cRanges];
+
+            pRange->uAddr = BDLE.Desc.u64BufAdr;
+            pRange->uSize = BDLE.Desc.u32BufSize;
+
+            LogFunc(("Adding range %zu - 0x%x (%RU32)\n", cRanges, pRange->uAddr, pRange->uSize));
+
+            cRanges++;
+        }
+    }
+
+    LogFunc(("%zu ranges total\n", cRanges));
+
+    /*
+     * Register all ranges as DMA access handlers.
+     */
+
+    for (size_t i = 0; i < cRanges; i++)
+    {
+        BDLERANGE *pRange = &arrRanges[i];
+
+        PHDADMAACCESSHANDLER pHandler = (PHDADMAACCESSHANDLER)RTMemAllocZ(sizeof(HDADMAACCESSHANDLER));
+        if (!pHandler)
+        {
+            rc = VERR_NO_MEMORY;
+            break;
+        }
+
+        RTListAppend(&pStream->State.lstDMAHandlers, &pHandler->Node);
+
+        pHandler->pStream = pStream; /* Save a back reference to the owner. */
+
+        char szDesc[32];
+        RTStrPrintf(szDesc, sizeof(szDesc), "HDA[SD%RU8 - RANGE%02zu]", pStream->u8SD, i);
+
+        int rc2 = PGMR3HandlerPhysicalTypeRegister(PDMDevHlpGetVM(pThis->pDevInsR3), PGMPHYSHANDLERKIND_WRITE,
+                                                   hdaDMAAccessHandler,
+                                                   NULL, NULL, NULL,
+                                                   NULL, NULL, NULL,
+                                                   szDesc, &pHandler->hAccessHandlerType);
+        AssertRCBreak(rc2);
+
+        pHandler->BDLEAddr  = pRange->uAddr;
+        pHandler->BDLESize  = pRange->uSize;
+
+        /* Get first and last pages of the BDLE range. */
+        RTGCPHYS pgFirst = pRange->uAddr & ~PAGE_OFFSET_MASK;
+        RTGCPHYS pgLast  = RT_ALIGN(pgFirst + pRange->uSize, PAGE_SIZE);
+
+        /* Calculate the region size (in pages). */
+        RTGCPHYS regionSize = RT_ALIGN(pgLast - pgFirst, PAGE_SIZE);
+
+        pHandler->GCPhysFirst = pgFirst;
+        pHandler->GCPhysLast  = pHandler->GCPhysFirst + (regionSize - 1);
+
+        LogFunc(("\tRegistering region '%s': 0x%x - 0x%x (region size: %zu)\n",
+                 szDesc, pHandler->GCPhysFirst, pHandler->GCPhysLast, regionSize));
+        LogFunc(("\tBDLE @ 0x%x - 0x%x (%RU32)\n",
+                 pHandler->BDLEAddr, pHandler->BDLEAddr + pHandler->BDLESize, pHandler->BDLESize));
+
+        rc2 = PGMHandlerPhysicalRegister(PDMDevHlpGetVM(pThis->pDevInsR3),
+                                         pHandler->GCPhysFirst, pHandler->GCPhysLast,
+                                         pHandler->hAccessHandlerType, pHandler, NIL_RTR0PTR, NIL_RTRCPTR,
+                                         szDesc);
+        AssertRCBreak(rc2);
+
+        pHandler->fRegistered = true;
+    }
+
+    LogFunc(("Registration ended with rc=%Rrc\n", rc));
+
+    return RT_SUCCESS(rc);
+}
+
+/**
+ * Unregisters access handlers of a stream's BDLEs.
+ *
+ * @param   pThis               HDA state.
+ * @param   pStream             HDA stream to unregister BDLE access handlers for.
+ */
+static void hdaStreamUnregisterDMAHandlers(PHDASTATE pThis, PHDASTREAM pStream)
+{
+    LogFunc(("\n"));
+
+    PHDADMAACCESSHANDLER pHandler, pHandlerNext;
+    RTListForEachSafe(&pStream->State.lstDMAHandlers, pHandler, pHandlerNext, HDADMAACCESSHANDLER, Node)
+    {
+        if (!pHandler->fRegistered) /* Handler not registered? Skip. */
+            continue;
+
+        LogFunc(("Unregistering 0x%x - 0x%x (%zu)\n",
+                 pHandler->GCPhysFirst, pHandler->GCPhysLast, pHandler->GCPhysLast - pHandler->GCPhysFirst));
+
+        int rc2 = PGMHandlerPhysicalDeregister(PDMDevHlpGetVM(pThis->pDevInsR3),
+                                               pHandler->GCPhysFirst);
+        AssertRC(rc2);
+
+        RTListNodeRemove(&pHandler->Node);
+
+        RTMemFree(pHandler);
+        pHandler = NULL;
+    }
+
+    Assert(RTListIsEmpty(&pStream->State.lstDMAHandlers));
+}
+# endif /* HDA_USE_DMA_ACCESS_HANDLER */
+
 # ifdef LOG_ENABLED
 static void hdaBDLEDumpAll(PHDASTATE pThis, uint64_t u64BDLBase, uint16_t cBDLE)
 {
@@ -2483,17 +3005,13 @@ static void hdaBDLEDumpAll(PHDASTATE pThis, uint64_t u64BDLBase, uint16_t cBDLE)
     uint32_t cbBDLE = 0;
     for (uint16_t i = 0; i < cBDLE; i++)
     {
-        uint8_t bdle[16]; /** @todo Use a define. */
-        PDMDevHlpPhysRead(pThis->CTX_SUFF(pDevIns), u64BDLBase + i * 16, bdle, 16); /** @todo Use a define. */
-
-        uint64_t addr = *(uint64_t *)bdle;
-        uint32_t len  = *(uint32_t *)&bdle[8];
-        uint32_t ioc  = *(uint32_t *)&bdle[12];
+        HDABDLEDESC bd;
+        PDMDevHlpPhysRead(pThis->CTX_SUFF(pDevIns), u64BDLBase + i * sizeof(HDABDLEDESC), &bd, sizeof(bd));
 
-        LogFlowFunc(("\t#%03d BDLE(adr:0x%llx, size:%RU32, ioc:%RTbool)\n",
-                     i, addr, len, RT_BOOL(ioc & 0x1)));
+        LogFunc(("\t#%03d BDLE(adr:0x%llx, size:%RU32, ioc:%RTbool)\n",
+                 i, bd.u64BufAdr, bd.u32BufSize, bd.fFlags & HDA_BDLE_FLAG_IOC));
 
-        cbBDLE += len;
+        cbBDLE += bd.u32BufSize;
     }
 
     LogFlowFunc(("Total: %RU32 bytes\n", cbBDLE));
@@ -2512,7 +3030,7 @@ static void hdaBDLEDumpAll(PHDASTATE pThis, uint64_t u64BDLBase, uint16_t cBDLE)
         LogFlowFunc(("\t#%03d DMA @ 0x%x\n", i , uDMACnt));
     }
 }
-# endif
+# endif /* LOG_ENABLED */
 
 /**
  * Fetches a Bundle Descriptor List Entry (BDLE) from the DMA engine.
@@ -2527,25 +3045,27 @@ static int hdaBDLEFetch(PHDASTATE pThis, PHDABDLE pBDLE, uint64_t u64BaseDMA, ui
     AssertPtrReturn(pThis,   VERR_INVALID_POINTER);
     AssertPtrReturn(pBDLE,   VERR_INVALID_POINTER);
     AssertReturn(u64BaseDMA, VERR_INVALID_PARAMETER);
-    /** @todo Compare u16Entry with LVI. */
 
-    uint8_t uBundleEntry[16]; /** @todo Define a BDLE length. */
-    int rc = PDMDevHlpPhysRead(pThis->CTX_SUFF(pDevIns), u64BaseDMA + u16Entry * 16, /** @todo Define a BDLE length. */
-                               uBundleEntry, RT_ELEMENTS(uBundleEntry));
-    if (RT_FAILURE(rc))
-        return rc;
+    if (!u64BaseDMA)
+    {
+        LogRel2(("HDA: Unable to fetch BDLE #%RU16 - no base DMA address set (yet)\n", u16Entry));
+        return VERR_NOT_FOUND;
+    }
+    /** @todo Compare u16Entry with LVI. */
 
-    RT_BZERO(pBDLE, sizeof(HDABDLE));
+    int rc = PDMDevHlpPhysRead(pThis->CTX_SUFF(pDevIns), u64BaseDMA + (u16Entry * sizeof(HDABDLEDESC)),
+                               &pBDLE->Desc, sizeof(pBDLE->Desc));
 
-    pBDLE->State.u32BDLIndex = u16Entry;
-    pBDLE->u64BufAdr         = *(uint64_t *) uBundleEntry;
-    pBDLE->u32BufSize        = *(uint32_t *)&uBundleEntry[8];
-    if (pBDLE->u32BufSize < sizeof(uint16_t)) /* Must be at least one word. */
-        return VERR_INVALID_STATE;
+    if (RT_SUCCESS(rc))
+    {
+        /* Reset internal state. */
+        RT_ZERO(pBDLE->State);
+        pBDLE->State.u32BDLIndex = u16Entry;
+    }
 
-    pBDLE->fIntOnCompletion  = (*(uint32_t *)&uBundleEntry[12]) & 0x1;
+    Log3Func(("Entry #%d @ 0x%x: %R[bdle], rc=%Rrc\n", u16Entry, u64BaseDMA + (u16Entry * sizeof(HDABDLEDESC)), pBDLE, rc));
 
-    return VINF_SUCCESS;
+    return rc;
 }
 
 /**
@@ -2554,368 +3074,614 @@ static int hdaBDLEFetch(PHDASTATE pThis, PHDABDLE pBDLE, uint64_t u64BaseDMA, ui
  *
  * @return Number of bytes for the DMA engine to process.
  */
-DECLINLINE(uint32_t) hdaStreamGetTransferSize(PHDASTATE pThis, PHDASTREAM pStrmSt, uint32_t cbMax)
+DECLINLINE(uint32_t) hdaStreamGetTransferSize(PHDASTATE pThis, PHDASTREAM pStream)
 {
     AssertPtrReturn(pThis, 0);
-    AssertPtrReturn(pStrmSt, 0);
+    AssertPtrReturn(pStream, 0);
 
-    if (!cbMax)
+    if (!(HDA_STREAM_REG(pThis, CTL, pStream->u8SD) & HDA_REG_FIELD_FLAG_MASK(SDCTL, RUN)))
+    {
+        AssertFailed(); /* Should never happen. */
         return 0;
+    }
 
-    PHDABDLE pBDLE = &pStrmSt->State.BDLE;
-
-    uint32_t cbFree = pStrmSt->u32CBL - HDA_STREAM_REG(pThis, LPIB, pStrmSt->u8Strm);
-    if (cbFree)
-    {
-        /* Limit to the available free space of the current BDLE. */
-        cbFree = RT_MIN(cbFree, pBDLE->u32BufSize - pBDLE->State.u32BufOff);
+    /* Determine how much for the current BDL entry we have left to transfer. */
+    PHDABDLE pBDLE  = &pStream->State.BDLE;
+    const uint32_t cbBDLE = RT_MIN(pBDLE->Desc.u32BufSize, pBDLE->Desc.u32BufSize - pBDLE->State.u32BufOff);
 
-        /* Make sure we only copy as much as the stream's FIFO can hold (SDFIFOS, 18.2.39). */
-        cbFree = RT_MIN(cbFree, pStrmSt->u16FIFOS);
+    /* Determine how much we (still) can stuff in the stream's internal FIFO.  */
+    const uint32_t cbCircBuf   = (uint32_t)RTCircBufFree(pStream->State.pCircBuf);
 
-        /* Make sure we only transfer as many bytes as requested. */
-        cbFree = RT_MIN(cbFree, cbMax);
+    uint32_t cbToTransfer = cbBDLE;
 
-        if (pBDLE->State.cbBelowFIFOW)
-        {
-            /* Are we not going to reach (or exceed) the FIFO watermark yet with the data to copy?
-             * No need to read data from DMA then. */
-            if (cbFree > pBDLE->State.cbBelowFIFOW)
-            {
-                /* Subtract the amount of bytes that still would fit in the stream's FIFO
-                 * and therefore do not need to be processed by DMA. */
-                cbFree -= pBDLE->State.cbBelowFIFOW;
-            }
-        }
-    }
+    /* Make sure that we don't transfer more than our FIFO can hold at the moment.
+     * As the host sets the overall pace it needs to process some of the FIFO data first before
+     * we can issue a new DMA data transfer. */
+    if (cbToTransfer > cbCircBuf)
+        cbToTransfer = cbCircBuf;
 
-    LogFlowFunc(("[SD%RU8]: CBL=%RU32, LPIB=%RU32, cbFree=%RU32, %R[bdle]\n", pStrmSt->u8Strm,
-                 pStrmSt->u32CBL, HDA_STREAM_REG(pThis, LPIB, pStrmSt->u8Strm), cbFree, pBDLE));
-    return cbFree;
+    Log3Func(("[SD%RU8] LPIB=%RU32 CBL=%RU32 cbCircBuf=%RU32, -> cbToTransfer=%RU32 %R[bdle]\n", pStream->u8SD,
+              HDA_STREAM_REG(pThis, LPIB, pStream->u8SD), pStream->u32CBL, cbCircBuf, cbToTransfer, pBDLE));
+    return cbToTransfer;
 }
 
-DECLINLINE(void) hdaBDLEUpdate(PHDABDLE pBDLE, uint32_t cbData, uint32_t cbProcessed)
+
+DECLINLINE(void) hdaStreamTransferInc(PHDASTATE pThis, PHDASTREAM pStream, uint32_t cbInc)
 {
-    AssertPtrReturnVoid(pBDLE);
+    AssertPtrReturnVoid(pThis);
+    AssertPtrReturnVoid(pStream);
 
-    if (!cbData || !cbProcessed)
+    if (!cbInc)
         return;
 
-    /* Fewer than cbBelowFIFOW bytes were copied.
-     * Probably we need to move the buffer, but it is rather hard to imagine a situation
-     * where it might happen. */
-    AssertMsg((cbProcessed == pBDLE->State.cbBelowFIFOW + cbData), /* we assume that we write the entire buffer including unreported bytes */
-              ("cbProcessed=%RU32 != pBDLE->State.cbBelowFIFOW=%RU32 + cbData=%RU32\n",
-              cbProcessed, pBDLE->State.cbBelowFIFOW, cbData));
+    const uint32_t u32LPIB = HDA_STREAM_REG(pThis, LPIB, pStream->u8SD);
 
-#if 0
-    if (   pBDLE->State.cbBelowFIFOW
-        && pBDLE->State.cbBelowFIFOW <= cbWritten)
+    Log3Func(("[SD%RU8] %RU32 + %RU32 -> %RU32, CBL=%RU32\n",
+              pStream->u8SD, u32LPIB, cbInc, u32LPIB + cbInc, pStream->u32CBL));
+
+    hdaStreamUpdateLPIB(pThis, pStream, u32LPIB + cbInc);
+}
+
+/**
+ * Tells whether a given BDLE is complete or not.
+ *
+ * @return  @true if BDLE is complete, @false if not.
+ * @param   pBDLE               BDLE to retrieve status for.
+ */
+static bool hdaBDLEIsComplete(PHDABDLE pBDLE)
+{
+    bool fIsComplete = false;
+
+    if (   !pBDLE->Desc.u32BufSize /* There can be BDLEs with 0 size. */
+        || (pBDLE->State.u32BufOff >= pBDLE->Desc.u32BufSize))
     {
-        LogFlowFunc(("BDLE(cbUnderFifoW:%RU32, off:%RU32, size:%RU32)\n",
-                     pBDLE->State.cbBelowFIFOW, pBDLE->State.u32BufOff, pBDLE->u32BufSize));
+        Assert(pBDLE->State.u32BufOff == pBDLE->Desc.u32BufSize);
+        fIsComplete = true;
     }
-#endif
 
-    pBDLE->State.cbBelowFIFOW -= RT_MIN(pBDLE->State.cbBelowFIFOW, cbProcessed);
-    Assert(pBDLE->State.cbBelowFIFOW == 0);
+    Log3Func(("%R[bdle] => %s\n", pBDLE, fIsComplete ? "COMPLETE" : "INCOMPLETE"));
 
-    /* We always increment the position of DMA buffer counter because we're always reading
-     * into an intermediate buffer. */
-    pBDLE->State.u32BufOff += cbData;
-    Assert(pBDLE->State.u32BufOff <= pBDLE->u32BufSize);
+    return fIsComplete;
+}
 
-    LogFlowFunc(("cbData=%RU32, cbProcessed=%RU32, %R[bdle]\n", cbData, cbProcessed, pBDLE));
+/**
+ * Tells whether a given BDLE needs an interrupt or not.
+ *
+ * @return  @true if BDLE needs an interrupt, @false if not.
+ * @param   pBDLE               BDLE to retrieve status for.
+ */
+static bool hdaBDLENeedsInterrupt(PHDABDLE pBDLE)
+{
+    return (pBDLE->Desc.fFlags & HDA_BDLE_FLAG_IOC);
 }
 
-DECLINLINE(bool) hdaStreamNeedsNextBDLE(PHDASTATE pThis, PHDASTREAM pStrmSt)
+/**
+ * Writes audio data from an HDA input stream's FIFO to its associated DMA area.
+ *
+ * @return  IPRT status code.
+ * @param   pThis               HDA state.
+ * @param   pStream             HDA input stream to write audio data to.
+ * @param   cbToWrite           How much (in bytes) to write.
+ * @param   pcbWritten          Returns written bytes on success. Optional.
+ */
+static int hdaDMAWrite(PHDASTATE pThis, PHDASTREAM pStream, uint32_t cbToWrite, uint32_t *pcbWritten)
 {
-    AssertPtrReturn(pThis,   false);
-    AssertPtrReturn(pStrmSt, false);
+    AssertPtrReturn(pThis,   VERR_INVALID_POINTER);
+    AssertPtrReturn(pStream, VERR_INVALID_POINTER);
+    /* pcbWritten is optional. */
+
+    PHDABDLE   pBDLE    = &pStream->State.BDLE;
+    PRTCIRCBUF pCircBuf = pStream->State.pCircBuf;
+    AssertPtr(pCircBuf);
+
+    int rc = VINF_SUCCESS;
+
+    uint32_t cbWrittenTotal = 0;
+
+    void *pvBuf  = NULL;
+    size_t cbBuf = 0;
+
+    uint8_t abSilence[HDA_FIFO_MAX + 1] = { 0 };
+
+    while (cbToWrite)
+    {
+        size_t cbChunk = RT_MIN(cbToWrite, pStream->u16FIFOS);
 
-    PHDABDLE pBDLE   = &pStrmSt->State.BDLE;
-    uint32_t u32LPIB = HDA_STREAM_REG(pThis, LPIB, pStrmSt->u8Strm);
+        size_t cbBlock = 0;
+        RTCircBufAcquireReadBlock(pCircBuf, cbChunk, &pvBuf, &cbBlock);
 
-    /* Did we reach the CBL (Cyclic Buffer List) limit? */
-    bool fCBLLimitReached = u32LPIB >= pStrmSt->u32CBL;
+        if (cbBlock)
+        {
+            cbBuf = cbBlock;
+        }
+        else /* No audio data available? Send silence. */
+        {
+            pvBuf = &abSilence;
+            cbBuf = cbChunk;
+        }
+
+        /* Sanity checks. */
+        Assert(cbBuf <= pBDLE->Desc.u32BufSize - pBDLE->State.u32BufOff);
+        Assert(cbBuf % HDA_FRAME_SIZE == 0);
+        Assert((cbBuf >> 1) >= 1);
+
+#ifdef VBOX_AUDIO_DEBUG_DUMP_PCM_DATA
+        RTFILE fh;
+        RTFileOpen(&fh, VBOX_AUDIO_DEBUG_DUMP_PCM_DATA_PATH "hdaDMAWrite.pcm",
+                   RTFILE_O_OPEN_CREATE | RTFILE_O_APPEND | RTFILE_O_WRITE | RTFILE_O_DENY_NONE);
+        RTFileWrite(fh, pvBuf, cbBuf, NULL);
+        RTFileClose(fh);
+#endif
+        int rc2 = PDMDevHlpPCIPhysWrite(pThis->CTX_SUFF(pDevIns),
+                                        pBDLE->Desc.u64BufAdr + pBDLE->State.u32BufOff + cbWrittenTotal,
+                                        pvBuf, cbBuf);
+        AssertRC(rc2);
 
-    /* Do we need to use the next BDLE entry? Either because we reached
-     * the CBL limit or our internal DMA buffer is full. */
-    bool fNeedsNextBDLE   = (   fCBLLimitReached
-                             || (pBDLE->State.u32BufOff >= pBDLE->u32BufSize));
+#ifdef VBOX_WITH_STATISTICS
+        STAM_COUNTER_ADD(&pThis->StatBytesWritten, cbBuf);
+#endif
+        if (cbBlock)
+            RTCircBufReleaseReadBlock(pCircBuf, cbBlock);
 
-    Assert(u32LPIB                <= pStrmSt->u32CBL);
-    Assert(pBDLE->State.u32BufOff <= pBDLE->u32BufSize);
+        Assert(cbToWrite >= cbBuf);
+        cbToWrite -= (uint32_t)cbBuf;
 
-    LogFlowFunc(("[SD%RU8]: LPIB=%RU32, CBL=%RU32, fCBLLimitReached=%RTbool, fNeedsNextBDLE=%RTbool, %R[bdle]\n",
-                 pStrmSt->u8Strm, u32LPIB, pStrmSt->u32CBL, fCBLLimitReached, fNeedsNextBDLE, pBDLE));
+        cbWrittenTotal += (uint32_t)cbBuf;
+    }
 
-    if (fCBLLimitReached)
+    if (RT_SUCCESS(rc))
     {
-        /* Reset LPIB register. */
-        u32LPIB -= RT_MIN(u32LPIB, pStrmSt->u32CBL);
-        hdaStreamUpdateLPIB(pThis, pStrmSt, u32LPIB);
+        if (pcbWritten)
+            *pcbWritten = cbWrittenTotal;
     }
+    else
+        LogFunc(("Failed with %Rrc\n", rc));
 
-    return fNeedsNextBDLE;
+    return rc;
 }
 
-DECLINLINE(void) hdaStreamTransferUpdate(PHDASTATE pThis, PHDASTREAM pStrmSt, uint32_t cbInc)
+/**
+ * Reads (transfers) available audio data from a given input mixer sink into an HDA stream's FIFO buffer.
+ *
+ * @returns IPRT status code.
+ * @param   pThis               HDA state.
+ * @param   pStream             HDA stream to read audio data to.
+ * @param   pSink               Mixer sink to read from.
+ * @param   pcbRead             How much (in bytes) of audio input has been read.
+ */
+static int hdaReadAudio(PHDASTATE pThis, PHDASTREAM pStream, PAUDMIXSINK pSink, uint32_t *pcbRead)
 {
-    AssertPtrReturnVoid(pThis);
-    AssertPtrReturnVoid(pStrmSt);
+    AssertPtrReturn(pThis,   VERR_INVALID_POINTER);
+    AssertPtrReturn(pStream, VERR_INVALID_POINTER);
+    AssertPtrReturn(pSink,   VERR_INVALID_POINTER);
+    /* pcbRead is optional. */
 
-    LogFlowFunc(("[SD%RU8]: cbInc=%RU32\n", pStrmSt->u8Strm, cbInc));
+    /* Stream not active? */
+    if (!ASMAtomicReadBool(&pStream->State.fRunning))
+    {
+        Log3Func(("[SD%RU8] Not running\n", pStream->u8SD));
 
-    Assert(cbInc <= pStrmSt->u16FIFOS);
+        if (pcbRead)
+            *pcbRead = 0;
+        return VINF_SUCCESS;
+    }
 
-    PHDABDLE pBDLE = &pStrmSt->State.BDLE;
+    PRTCIRCBUF pCircBuf = pStream->State.pCircBuf;
+    AssertPtr(pCircBuf);
 
-    /*
-     * If we're below the FIFO watermark (SDFIFOW), it's expected that HDA
-     * doesn't fetch anything via DMA, so just update LPIB.
-     * (ICH6 datasheet 18.2.38).
-     */
-    if (pBDLE->State.cbBelowFIFOW == 0) /* Did we hit (or exceed) the watermark? */
+    int rc = VINF_SUCCESS;
+
+    size_t cbToRead = RTCircBufFree(pCircBuf);
+    while (cbToRead)
     {
-        const uint32_t u32LPIB = RT_MIN(HDA_STREAM_REG(pThis, LPIB, pStrmSt->u8Strm) + cbInc,
-                                        pStrmSt->u32CBL);
+        void *pvBuf;
+        size_t cbBuf;
+
+        RTCircBufAcquireWriteBlock(pCircBuf, cbToRead, &pvBuf, &cbBuf);
+
+        uint32_t cbRead = 0;
 
-        LogFlowFunc(("[SD%RU8]: LPIB: %RU32 -> %RU32, CBL=%RU32\n",
-                     pStrmSt->u8Strm,
-                     HDA_STREAM_REG(pThis, LPIB, pStrmSt->u8Strm), HDA_STREAM_REG(pThis, LPIB, pStrmSt->u8Strm) + cbInc,
-                     pStrmSt->u32CBL));
+        if (cbBuf)
+        {
+            rc = AudioMixerProcessSinkIn(pSink, AUDMIXOP_BLEND, pvBuf, (uint32_t)cbBuf, &cbRead);
+
+#ifdef VBOX_AUDIO_DEBUG_DUMP_PCM_DATA
+            if (cbRead)
+            {
+                RTFILE fh;
+                RTFileOpen(&fh, VBOX_AUDIO_DEBUG_DUMP_PCM_DATA_PATH "hdaReadAudio.pcm",
+                           RTFILE_O_OPEN_CREATE | RTFILE_O_APPEND | RTFILE_O_WRITE | RTFILE_O_DENY_NONE);
+                RTFileWrite(fh, pvBuf, cbRead, NULL);
+                RTFileClose(fh);
+            }
+#endif
+        }
+
+        RTCircBufReleaseWriteBlock(pCircBuf, cbRead);
+
+        if (   RT_FAILURE(rc)
+            || !cbRead)
+        {
+            break;
+        }
 
-        hdaStreamUpdateLPIB(pThis, pStrmSt, u32LPIB);
+        Assert(cbToRead >= cbRead);
+        cbToRead -= cbRead;
     }
+
+    /* Always return the available data which now is in the stream's FIFO buffer. */
+    uint32_t cbReadTotal = (uint32_t)RTCircBufUsed(pCircBuf);
+
+    if (pcbRead)
+        *pcbRead = cbReadTotal;
+
+    Log3Func(("[SD%RU8] cbReadTotal=%RU32, rc=%Rrc\n", pStream->u8SD, cbReadTotal, rc));
+    return rc;
 }
 
-static bool hdaStreamTransferIsComplete(PHDASTATE pThis, PHDASTREAM pStrmSt)
+#ifdef HDA_USE_DMA_ACCESS_HANDLER
+/**
+ * HC access handler for the FIFO.
+ *
+ * @returns VINF_SUCCESS if the handler have carried out the operation.
+ * @returns VINF_PGM_HANDLER_DO_DEFAULT if the caller should carry out the access operation.
+ * @param   pVM             VM Handle.
+ * @param   pVCpu           The cross context CPU structure for the calling EMT.
+ * @param   GCPhys          The physical address the guest is writing to.
+ * @param   pvPhys          The HC mapping of that address.
+ * @param   pvBuf           What the guest is reading/writing.
+ * @param   cbBuf           How much it's reading/writing.
+ * @param   enmAccessType   The access type.
+ * @param   enmOrigin       Who is making the access.
+ * @param   pvUser          User argument.
+ */
+static DECLCALLBACK(VBOXSTRICTRC) hdaDMAAccessHandler(PVM pVM, PVMCPU pVCpu, RTGCPHYS GCPhys, void *pvPhys,
+                                                      void *pvBuf, size_t cbBuf,
+                                                      PGMACCESSTYPE enmAccessType, PGMACCESSORIGIN enmOrigin, void *pvUser)
 {
-    AssertPtrReturn(pThis,   true);
-    AssertPtrReturn(pStrmSt, true);
+    RT_NOREF(pVM, pVCpu, pvPhys, pvBuf, enmOrigin);
 
-    bool fIsComplete = false;
+    PHDADMAACCESSHANDLER pHandler = (PHDADMAACCESSHANDLER)pvUser;
+    AssertPtr(pHandler);
+
+    PHDASTREAM pStream = pHandler->pStream;
+    AssertPtr(pStream);
 
-    PHDABDLE       pBDLE   = &pStrmSt->State.BDLE;
-    const uint32_t u32LPIB = HDA_STREAM_REG(pThis, LPIB, pStrmSt->u8Strm);
+    Assert(GCPhys >= pHandler->GCPhysFirst);
+    Assert(GCPhys <= pHandler->GCPhysLast);
+    Assert(enmAccessType == PGMACCESSTYPE_WRITE);
 
-    if (   pBDLE->State.u32BufOff >= pBDLE->u32BufSize
-        || u32LPIB                >= pStrmSt->u32CBL)
+    /* Not within BDLE range? Bail out. */
+    if (   (GCPhys         < pHandler->BDLEAddr)
+        || (GCPhys + cbBuf > pHandler->BDLEAddr + pHandler->BDLESize))
     {
-        Assert(pBDLE->State.u32BufOff <= pBDLE->u32BufSize);
-        Assert(u32LPIB                <= pStrmSt->u32CBL);
+        return VINF_PGM_HANDLER_DO_DEFAULT;
+    }
 
-        if (/* IOC (Interrupt On Completion) bit set? */
-               pBDLE->fIntOnCompletion
-            /* All data put into the DMA FIFO? */
-            && pBDLE->State.cbBelowFIFOW == 0
-           )
+    switch(enmAccessType)
+    {
+        case PGMACCESSTYPE_WRITE:
         {
-            /**
-             * Set the BCIS (Buffer Completion Interrupt Status) flag as the
-             * last byte of data for the current descriptor has been fetched
-             * from memory and put into the DMA FIFO.
-             *
-             ** @todo More carefully investigate BCIS flag.
-             *
-             * Speech synthesis works fine on Mac Guest if this bit isn't set
-             * but in general sound quality gets worse.
-             */
-            HDA_STREAM_REG(pThis, STS, pStrmSt->u8Strm) |= HDA_REG_FIELD_FLAG_MASK(SDSTS, BCIS);
+# ifdef DEBUG
+            PHDASTREAMDBGINFO pStreamDbg = &pStream->Dbg;
 
-            /*
-             * If the ICE (IOCE, "Interrupt On Completion Enable") bit of the SDCTL register is set
-             * we need to generate an interrupt.
-             */
-            if (HDA_STREAM_REG(pThis, CTL, pStrmSt->u8Strm) & HDA_REG_FIELD_FLAG_MASK(SDCTL, ICE))
-                hdaProcessInterrupt(pThis);
+            const uint64_t tsNowNs     = RTTimeNanoTS();
+            const uint32_t tsElapsedMs = (tsNowNs - pStreamDbg->tsWriteSlotBegin) / 1000 / 1000;
+
+            uint64_t cWritesHz   = ASMAtomicReadU64(&pStreamDbg->cWritesHz);
+            uint64_t cbWrittenHz = ASMAtomicReadU64(&pStreamDbg->cbWrittenHz);
+
+            if (tsElapsedMs >= (1000 / HDA_TIMER_HZ))
+            {
+                LogFunc(("[SD%RU8] %RU32ms elapsed, cbWritten=%RU64, cWritten=%RU64 -- %RU32 bytes on average per time slot (%zums)\n",
+                         pStream->u8SD, tsElapsedMs, cbWrittenHz, cWritesHz,
+                         ASMDivU64ByU32RetU32(cbWrittenHz, cWritesHz ? cWritesHz : 1), 1000 / HDA_TIMER_HZ));
+
+                pStreamDbg->tsWriteSlotBegin = tsNowNs;
+
+                cWritesHz   = 0;
+                cbWrittenHz = 0;
+            }
+
+            cWritesHz   += 1;
+            cbWrittenHz += cbBuf;
+
+            ASMAtomicIncU64(&pStreamDbg->cWritesTotal);
+            ASMAtomicAddU64(&pStreamDbg->cbWrittenTotal, cbBuf);
+
+            ASMAtomicWriteU64(&pStreamDbg->cWritesHz,   cWritesHz);
+            ASMAtomicWriteU64(&pStreamDbg->cbWrittenHz, cbWrittenHz);
+
+            LogFunc(("[SD%RU8] Writing %3zu @ 0x%x (off %zu)\n",
+                     pStream->u8SD, cbBuf, GCPhys, GCPhys - pHandler->BDLEAddr));
+
+            LogFunc(("[SD%RU8] cWrites=%RU64, cbWritten=%RU64 -> %RU32 bytes on average\n",
+                     pStream->u8SD, pStreamDbg->cWritesTotal, pStreamDbg->cbWrittenTotal,
+                     ASMDivU64ByU32RetU32(pStreamDbg->cbWrittenTotal, pStreamDbg->cWritesTotal)));
+# endif
+
+# ifdef VBOX_AUDIO_DEBUG_DUMP_PCM_DATA
+            RTFILE fh;
+            RTFileOpen(&fh, VBOX_AUDIO_DEBUG_DUMP_PCM_DATA_PATH "hdaDMAAccessWrite.pcm",
+                       RTFILE_O_OPEN_CREATE | RTFILE_O_APPEND | RTFILE_O_WRITE | RTFILE_O_DENY_NONE);
+            RTFileWrite(fh, pvBuf, cbBuf, NULL);
+            RTFileClose(fh);
+# endif
+
+# ifdef HDA_USE_DMA_ACCESS_HANDLER_WRITING
+            PRTCIRCBUF pCircBuf = pStream->State.pCircBuf;
+            AssertPtr(pCircBuf);
+
+            uint8_t *pbBuf = (uint8_t *)pvBuf;
+            while (cbBuf)
+            {
+                /* Make sure we only copy as much as the stream's FIFO can hold (SDFIFOS, 18.2.39). */
+                void *pvChunk;
+                size_t cbChunk;
+                RTCircBufAcquireWriteBlock(pCircBuf, cbBuf, &pvChunk, &cbChunk);
+
+                if (cbChunk)
+                {
+                    memcpy(pvChunk, pbBuf, cbChunk);
+
+                    pbBuf  += cbChunk;
+                    Assert(cbBuf >= cbChunk);
+                    cbBuf  -= cbChunk;
+                }
+                else
+                {
+                    //AssertMsg(RTCircBufFree(pCircBuf), ("No more space but still %zu bytes to write\n", cbBuf));
+                    break;
+                }
+
+                LogFunc(("[SD%RU8] cbChunk=%zu\n", pStream->u8SD, cbChunk));
+
+                RTCircBufReleaseWriteBlock(pCircBuf, cbChunk);
+            }
+# endif /* HDA_USE_DMA_ACCESS_HANDLER_WRITING */
+            break;
         }
 
-        fIsComplete = true;
+        default:
+            AssertMsgFailed(("Access type not implemented\n"));
+            break;
     }
 
-    LogFlowFunc(("[SD%RU8]: u32LPIB=%RU32, CBL=%RU32, %R[bdle] => %s\n",
-                 pStrmSt->u8Strm, u32LPIB, pStrmSt->u32CBL, pBDLE, fIsComplete ? "COMPLETE" : "INCOMPLETE"));
-
-    return fIsComplete;
+    return VINF_PGM_HANDLER_DO_DEFAULT;
 }
+#endif /* HDA_USE_DMA_ACCESS_HANDLER */
 
 /**
- * hdaReadAudio - copies samples from audio backend to DMA.
- * Note: This function writes to the DMA buffer immediately,
- *       but "reports bytes" when all conditions are met (FIFOW).
+ * Reads DMA data from a given HDA output stream into its associated FIFO buffer.
+ *
+ * @return  IPRT status code.
+ * @param   pThis               HDA state.
+ * @param   pStream             HDA output stream to read DMA data from.
+ * @param   cbToRead            How much (in bytes) to read from DMA.
+ * @param   pcbRead             Returns read bytes from DMA. Optional.
  */
-static int hdaReadAudio(PHDASTATE pThis, PHDASTREAM pStrmSt, PAUDMIXSINK pSink, uint32_t cbMax, uint32_t *pcbRead)
+static int hdaDMARead(PHDASTATE pThis, PHDASTREAM pStream, uint32_t cbToRead, uint32_t *pcbRead)
 {
     AssertPtrReturn(pThis,   VERR_INVALID_POINTER);
-    AssertPtrReturn(pStrmSt, VERR_INVALID_POINTER);
-    AssertPtrReturn(pSink,   VERR_INVALID_POINTER);
+    AssertPtrReturn(pStream, VERR_INVALID_POINTER);
     /* pcbRead is optional. */
 
-    PHDABDLE pBDLE = &pStrmSt->State.BDLE;
+    int rc = VINF_SUCCESS;
 
-    int rc;
-    uint32_t cbRead = 0;
-    uint32_t cbBuf  = hdaStreamGetTransferSize(pThis, pStrmSt, cbMax);
+    uint32_t cbReadTotal = 0;
 
-    LogFlowFunc(("cbBuf=%RU32, %R[bdle]\n", cbBuf, pBDLE));
+    PHDABDLE   pBDLE     = &pStream->State.BDLE;
+    PRTCIRCBUF pCircBuf  = pStream->State.pCircBuf;
+    AssertPtr(pCircBuf);
 
-    if (!cbBuf)
-    {
-        /* Nothing to write, bail out. */
-        rc = VINF_EOF;
-    }
-    else
+#ifdef HDA_DEBUG_SILENCE
+    uint64_t   csSilence = 0;
+
+    pStream->Dbg.cSilenceThreshold = 100;
+    pStream->Dbg.cbSilenceReadMin  = _1M;
+#endif
+
+    while (cbToRead)
     {
-        rc = AudioMixerProcessSinkIn(pSink, AUDMIXOP_BLEND, pBDLE->State.au8FIFO, cbBuf, &cbRead);
-        if (RT_SUCCESS(rc))
+        /* Make sure we only copy as much as the stream's FIFO can hold (SDFIFOS, 18.2.39). */
+        void *pvBuf;
+        size_t cbBuf;
+        RTCircBufAcquireWriteBlock(pCircBuf, RT_MIN(cbToRead, pStream->u16FIFOS), &pvBuf, &cbBuf);
+
+        if (cbBuf)
         {
-            if (!cbRead)
+            /*
+             * Read from the current BDLE's DMA buffer.
+             */
+            int rc2 = PDMDevHlpPhysRead(pThis->CTX_SUFF(pDevIns),
+                                        pBDLE->Desc.u64BufAdr + pBDLE->State.u32BufOff + cbReadTotal, pvBuf, cbBuf);
+            AssertRC(rc2);
+
+#ifdef HDA_DEBUG_SILENCE
+            uint16_t *pu16Buf = (uint16_t *)pvBuf;
+            for (size_t i = 0; i < cbBuf / sizeof(uint16_t); i++)
             {
-                rc = VINF_EOF;
+                if (*pu16Buf == 0)
+                {
+                    csSilence++;
+                }
+                else
+                    break;
+                pu16Buf++;
             }
-            else
-            {
-                /* Sanity checks. */
-                Assert(cbRead <= pStrmSt->u16FIFOS);
-                Assert(cbRead <= pBDLE->u32BufSize - pBDLE->State.u32BufOff);
-
-                /*
-                 * Write to the BDLE's DMA buffer.
-                 */
-                rc = PDMDevHlpPCIPhysWrite(pThis->CTX_SUFF(pDevIns),
-                                           pBDLE->u64BufAdr + pBDLE->State.u32BufOff,
-                                           pBDLE->State.au8FIFO, cbRead);
-                AssertRC(rc);
+#endif
 
-                if (pBDLE->State.cbBelowFIFOW + cbRead > hdaStreamGetFIFOW(pThis, pStrmSt))
+#ifdef VBOX_AUDIO_DEBUG_DUMP_PCM_DATA
+            if (cbBuf)
+            {
+                RTFILE fh;
+                rc2 = RTFileOpen(&fh, VBOX_AUDIO_DEBUG_DUMP_PCM_DATA_PATH "hdaDMARead.pcm",
+                                 RTFILE_O_OPEN_CREATE | RTFILE_O_APPEND | RTFILE_O_WRITE | RTFILE_O_DENY_NONE);
+                if (RT_SUCCESS(rc2))
                 {
-                    pBDLE->State.u32BufOff    += cbRead;
-                    pBDLE->State.cbBelowFIFOW  = 0;
-                    //hdaBackendReadTransferReported(pBDLE, cbDMAData, cbRead, &cbRead, pcbAvail);
+                    RTFileWrite(fh, pvBuf, cbBuf, NULL);
+                    RTFileClose(fh);
                 }
                 else
-                {
-                    pBDLE->State.u32BufOff    += cbRead;
-                    pBDLE->State.cbBelowFIFOW += cbRead;
-                    Assert(pBDLE->State.cbBelowFIFOW <= hdaStreamGetFIFOW(pThis, pStrmSt));
-                    //hdaBackendTransferUnreported(pThis, pBDLE, pStreamDesc, cbRead, pcbAvail);
+                    AssertRC(rc2);
+            }
+#endif
+
+#if 0
+            pStream->Dbg.cbReadTotal += cbBuf;
+            const uint64_t cbWritten = ASMAtomicReadU64(&pStream->Dbg.cbWrittenTotal);
+            Log3Func(("cbRead=%RU64, cbWritten=%RU64 -> %RU64 bytes %s\n",
+                      pStream->Dbg.cbReadTotal, cbWritten,
+                      pStream->Dbg.cbReadTotal >= cbWritten ? pStream->Dbg.cbReadTotal - cbWritten : cbWritten - pStream->Dbg.cbReadTotal,
+                      pStream->Dbg.cbReadTotal > cbWritten ? "too much" : "too little"));
+#endif
+
+#ifdef VBOX_WITH_STATISTICS
+            STAM_COUNTER_ADD(&pThis->StatBytesRead, cbBuf);
+#endif
+        }
+
+        RTCircBufReleaseWriteBlock(pCircBuf, cbBuf);
+
+        if (!cbBuf)
+        {
+            rc = VERR_BUFFER_OVERFLOW;
+            break;
+        }
+
+        cbReadTotal += (uint32_t)cbBuf;
+        Assert(pBDLE->State.u32BufOff + cbReadTotal <= pBDLE->Desc.u32BufSize);
+
+        Assert(cbToRead >= cbBuf);
+        cbToRead    -= (uint32_t)cbBuf;
+    }
+
+#ifdef HDA_DEBUG_SILENCE
 
-                    rc = VERR_NO_DATA;
-                }
-            }
-        }
+    if (csSilence)
+        pStream->Dbg.csSilence += csSilence;
+
+    if (   csSilence == 0
+        && pStream->Dbg.csSilence   >  pStream->Dbg.cSilenceThreshold
+        && pStream->Dbg.cbReadTotal >= pStream->Dbg.cbSilenceReadMin)
+    {
+        LogFunc(("Silent block detected: %RU64 audio samples\n", pStream->Dbg.csSilence));
+        pStream->Dbg.csSilence = 0;
     }
+#endif
 
     if (RT_SUCCESS(rc))
     {
         if (pcbRead)
-            *pcbRead = cbRead;
+            *pcbRead = cbReadTotal;
     }
-    else
-        LogFlowFunc(("Failed with %Rrc\n", rc));
 
     return rc;
 }
 
-static int hdaWriteAudio(PHDASTATE pThis, PHDASTREAM pStrmSt, uint32_t cbMax, uint32_t *pcbWritten)
+/**
+ * Writes (transfers) audio data from an HDA output stream to its associated FIFO buffer.
+ *
+ * @returns IPRT status code.
+ * @param   pThis               HDA state.
+ * @param   pStream             HDA output stream to write data for.
+ * @param   cbMax               How much (in bytes) to transfer from the given HDA output stream
+ *                              to its associated FIFO buffer.
+ */
+static int hdaWriteAudio(PHDASTATE pThis, PHDASTREAM pStream, uint32_t cbMax)
 {
-    AssertPtrReturn(pThis,      VERR_INVALID_POINTER);
-    AssertPtrReturn(pStrmSt,    VERR_INVALID_POINTER);
-    AssertPtrReturn(pcbWritten, VERR_INVALID_POINTER);
-    /* pcbWritten is optional. */
+    AssertPtrReturn(pThis,   VERR_INVALID_POINTER);
+    AssertPtrReturn(pStream, VERR_INVALID_POINTER);
+
+    /* Stream not active? */
+    if (!ASMAtomicReadBool(&pStream->State.fRunning))
+    {
+        Log3Func(("[SD%RU8] Not running\n", pStream->u8SD));
+        return VINF_SUCCESS;
+    }
 
-    PHDABDLE pBDLE = &pStrmSt->State.BDLE;
+    int rc = VINF_SUCCESS;
 
-    uint32_t cbWritten = 0;
-    uint32_t cbData    = hdaStreamGetTransferSize(pThis, pStrmSt, cbMax);
+    PRTCIRCBUF pCircBuf = pStream->State.pCircBuf;
+    AssertPtr(pCircBuf);
 
-    LogFlowFunc(("cbData=%RU32, %R[bdle]\n", cbData, pBDLE));
+    uint32_t cbWrittenTotal = 0;
+    uint32_t cbToWrite      = RT_MIN(cbMax, (uint32_t)RTCircBufUsed(pCircBuf));
 
-    /*
-     * Copy from DMA to the corresponding stream buffer (if there are any bytes from the
-     * previous unreported transfer we write at offset 'pBDLE->State.cbUnderFifoW').
-     */
-    int rc;
-    if (!cbData)
-    {
-        rc = VINF_EOF;
-    }
-    else
+    Log3Func(("cbToWrite=%RU32\n", cbToWrite));
+
+    while (cbToWrite >= HDA_FRAME_SIZE)
     {
-        /*
-         * Read from the current BDLE's DMA buffer.
-         */
-        rc = PDMDevHlpPhysRead(pThis->CTX_SUFF(pDevIns),
-                               pBDLE->u64BufAdr + pBDLE->State.u32BufOff,
-                               pBDLE->State.au8FIFO + pBDLE->State.cbBelowFIFOW, cbData);
-        AssertRC(rc);
+        void *pvBuf;
+        size_t cbBuf;
 
-#ifdef VBOX_WITH_STATISTICS
-        STAM_COUNTER_ADD(&pThis->StatBytesRead, cbData);
-#endif
-        /*
-         * Write to audio backend. We should ensure that we have enough bytes to copy to the backend.
-         */
-        uint32_t cbToWrite = cbData + pBDLE->State.cbBelowFIFOW;
-        if (cbToWrite >= hdaStreamGetFIFOW(pThis, pStrmSt))
-        {
-            uint32_t cbWrittenToStream;
-            int rc2;
+        uint32_t cbWritten = 0;
 
+        RTCircBufAcquireReadBlock(pCircBuf, cbToWrite, &pvBuf, &cbBuf);
+
+        if (cbBuf)
+        {
             PHDADRIVER pDrv;
             RTListForEach(&pThis->lstDrv, pDrv, HDADRIVER, Node)
             {
                 if (pDrv->pConnector->pfnIsActiveOut(pDrv->pConnector, pDrv->Out.pStrmOut))
                 {
-                    rc2 = pDrv->pConnector->pfnWrite(pDrv->pConnector, pDrv->Out.pStrmOut,
-                                                     pBDLE->State.au8FIFO, cbToWrite, &cbWrittenToStream);
-                    if (RT_SUCCESS(rc2))
+                    uint32_t cbWrittenToStream = 0;
+                    int rc2 = pDrv->pConnector->pfnWrite(pDrv->pConnector, pDrv->Out.pStrmOut,
+                                                         pvBuf, (uint32_t)cbBuf, &cbWrittenToStream);
+                    if (rc2 == VERR_NOT_AVAILABLE)
+                        continue;
+
+                    /* Lagging behind? */
+                    if (cbWrittenToStream < (uint32_t)cbBuf)
+                        LogFunc(("\tLUN#%RU8: Warning: Only written %RU32 / %RU32 bytes, rc=%Rrc\n",
+                                 pDrv->uLUN, cbWrittenToStream, cbToWrite, rc2));
+
+                    /* The primary driver sets the overall pace. */
+                    if (pDrv->fFlags & PDMAUDIODRVFLAG_PRIMARY)
                     {
-                        if (cbWrittenToStream < cbToWrite) /* Lagging behind? */
-                            LogFlowFunc(("\tLUN#%RU8: Warning: Only written %RU32 / %RU32 bytes, expect lags\n",
-                                         pDrv->uLUN, cbWrittenToStream, cbToWrite));
+                        cbWritten = cbWrittenToStream;
+
+                        if (RT_FAILURE(rc2))
+                        {
+                            if (RT_SUCCESS(rc))
+                                rc = rc2;
+                            break;
+                        }
                     }
                 }
                 else /* Stream disabled, not fatal. */
                 {
-                    cbWrittenToStream = 0;
-                    rc2 = VERR_NOT_AVAILABLE;
                     /* Keep going. */
                 }
-
-                LogFlowFunc(("\tLUN#%RU8: cbToWrite=%RU32, cbWrittenToStream=%RU32, rc=%Rrc\n",
-                             pDrv->uLUN, cbToWrite, cbWrittenToStream, rc2));
             }
-
-            /* Always report all data as being written;
-             * backends who were not able to catch up have to deal with it themselves. */
-            cbWritten = cbToWrite;
-
-            hdaBDLEUpdate(pBDLE, cbData, cbWritten);
         }
-        else
-        {
-            pBDLE->State.u32BufOff += cbWritten;
-            pBDLE->State.cbBelowFIFOW += cbWritten;
-            Assert(pBDLE->State.cbBelowFIFOW <= hdaStreamGetFIFOW(pThis, pStrmSt));
 
-            /* Not enough bytes to be processed and reported, we'll try our luck next time around. */
-            //hdaBackendTransferUnreported(pThis, pBDLE, pStreamDesc, cbAvail, NULL);
-            rc = VINF_EOF;
+#ifdef VBOX_AUDIO_DEBUG_DUMP_PCM_DATA
+        if (cbWritten)
+        {
+            RTFILE fh;
+            RTFileOpen(&fh, VBOX_AUDIO_DEBUG_DUMP_PCM_DATA_PATH "hdaWriteAudio.pcm",
+                       RTFILE_O_OPEN_CREATE | RTFILE_O_APPEND | RTFILE_O_WRITE | RTFILE_O_DENY_NONE);
+            RTFileWrite(fh, pvBuf, cbWritten, NULL);
+            RTFileClose(fh);
         }
-    }
+#endif
+        RTCircBufReleaseReadBlock(pCircBuf, cbWritten);
 
-    Assert(cbWritten <= pStrmSt->u16FIFOS);
+        Assert(cbToWrite >= cbWritten);
+        cbToWrite      -= (uint32_t)cbWritten;
 
-    if (RT_SUCCESS(rc))
-    {
-        if (pcbWritten)
-            *pcbWritten = cbWritten;
+        cbWrittenTotal += (uint32_t)cbWritten;
+
+        if (!cbWritten) /* Nothing written? Bail out. */
+            break;
+
+        if (RT_FAILURE(rc))
+            break;
     }
 
-    LogFunc(("Returning cbWritten=%RU32, rc=%Rrc\n", cbWritten, rc));
+    Log3Func(("Returning cbWrittenTotal=%RU32 (%zu bytes left), rc=%Rrc\n", cbWrittenTotal, RTCircBufUsed(pCircBuf), rc));
     return rc;
 }
 
@@ -2932,15 +3698,36 @@ static DECLCALLBACK(int) hdaCodecReset(PHDACODEC pCodec)
 
 static DECLCALLBACK(void) hdaCloseIn(PHDASTATE pThis, PDMAUDIORECSOURCE enmRecSource)
 {
-    NOREF(pThis);
     NOREF(enmRecSource);
+
     LogFlowFuncEnter();
+
+    PHDADRIVER pDrv;
+    RTListForEach(&pThis->lstDrv, pDrv, HDADRIVER, Node)
+    {
+        if (pDrv->LineIn.pStrmIn)
+        {
+            pDrv->pConnector->pfnDestroyIn(pDrv->pConnector, pDrv->LineIn.pStrmIn);
+            LogFlowFunc(("LUN#%RU8: Destroyed input\n", pDrv->uLUN));
+            pDrv->LineIn.pStrmIn = NULL;
+        }
+    }
 }
 
 static DECLCALLBACK(void) hdaCloseOut(PHDASTATE pThis)
 {
-    NOREF(pThis);
     LogFlowFuncEnter();
+
+    PHDADRIVER pDrv;
+    RTListForEach(&pThis->lstDrv, pDrv, HDADRIVER, Node)
+    {
+        if (pDrv->Out.pStrmOut)
+        {
+            pDrv->pConnector->pfnDestroyOut(pDrv->pConnector, pDrv->Out.pStrmOut);
+            LogFlowFunc(("LUN#%RU8: Destroyed output\n", pDrv->uLUN));
+            pDrv->Out.pStrmOut = NULL;
+        }
+    }
 }
 
 static DECLCALLBACK(int) hdaOpenIn(PHDASTATE pThis,
@@ -2970,6 +3757,13 @@ static DECLCALLBACK(int) hdaOpenIn(PHDASTATE pThis,
     PHDADRIVER pDrv;
     RTListForEach(&pThis->lstDrv, pDrv, HDADRIVER, Node)
     {
+        if (pDrv->LineIn.pStrmIn)
+        {
+            pDrv->pConnector->pfnDestroyIn(pDrv->pConnector, pDrv->LineIn.pStrmIn);
+            LogFlowFunc(("LUN#%RU8: Destroyed input with rc=%Rrc\n", pDrv->uLUN, rc));
+            pDrv->LineIn.pStrmIn = NULL;
+        }
+
         if (RTStrAPrintf(&pszDesc, "[LUN#%RU8] %s", pDrv->uLUN, pszName) <= 0)
         {
             rc = VERR_NO_MEMORY;
@@ -3002,6 +3796,13 @@ static DECLCALLBACK(int) hdaOpenOut(PHDASTATE pThis,
     PHDADRIVER pDrv;
     RTListForEach(&pThis->lstDrv, pDrv, HDADRIVER, Node)
     {
+        if (pDrv->Out.pStrmOut)
+        {
+            pDrv->pConnector->pfnDestroyOut(pDrv->pConnector, pDrv->Out.pStrmOut);
+            LogFlowFunc(("LUN#%RU8: Destroyed output with rc=%Rrc\n", pDrv->uLUN, rc));
+            pDrv->Out.pStrmOut = NULL;
+        }
+
         if (RTStrAPrintf(&pszDesc, "[LUN#%RU8] %s (%RU32Hz, %RU8 %s)",
                          pDrv->uLUN, pszName, pCfg->uHz, pCfg->cChannels, pCfg->cChannels > 1 ? "Channels" : "Channel") <= 0)
         {
@@ -3058,7 +3859,6 @@ static DECLCALLBACK(int) hdaSetVolume(PHDASTATE pThis, ENMSOUNDSOURCE enmSource,
 }
 
 #ifndef VBOX_WITH_AUDIO_CALLBACKS
-
 static DECLCALLBACK(void) hdaTimer(PPDMDEVINS pDevIns, PTMTIMER pTimer, void *pvUser)
 {
     RT_NOREF(pDevIns);
@@ -3068,42 +3868,33 @@ static DECLCALLBACK(void) hdaTimer(PPDMDEVINS pDevIns, PTMTIMER pTimer, void *pv
 
     STAM_PROFILE_START(&pThis->StatTimer, a);
 
-    uint32_t cbInMax  = 0;
-    uint32_t cbOutMin = UINT32_MAX;
-
-    PHDADRIVER pDrv;
-
-    uint64_t cTicksNow     = TMTimerGet(pTimer);
-    uint64_t cTicksElapsed = cTicksNow  - pThis->uTimerTS;
-    uint64_t cTicksPerSec  = TMTimerGetFreq(pTimer);
-
-    pThis->uTimerTS = cTicksNow;
-
-    /*
-     * Calculate the codec's (fixed) sampling rate.
-     */
-    AssertPtr(pThis->pCodec);
-    PDMPCMPROPS codecStrmProps;
+#ifdef HDA_DEBUG_TIMING
+    const uint64_t cTicksNow       = TMTimerGet(pTimer);
+    const uint64_t cTicksPerSec    = TMTimerGetFreq(pTimer);
 
-    int rc = DrvAudioStreamCfgToProps(&pThis->pCodec->strmCfg, &codecStrmProps);
-    AssertRC(rc);
+    const uint64_t cTicksElapsed   = cTicksNow - pThis->Out.State.uTimerTS;
+    const uint64_t cTicksElapsedMs = cTicksElapsed / (cTicksPerSec / 1000);
 
-    uint32_t cCodecSamplesMin  = (int)((2 * cTicksElapsed * pThis->pCodec->strmCfg.uHz + cTicksPerSec) / cTicksPerSec / 2);
-    uint32_t cbCodecSamplesMin = cCodecSamplesMin << codecStrmProps.cShift;
+    Log3Func(("%RU64 ticks elapsed -> %RU64ms\n", cTicksElapsed, cTicksElapsedMs));
+#endif
 
     /*
      * Process all driver nodes.
      */
+    uint32_t cbInMax  = 0;
+    uint32_t cbOutMin = UINT32_MAX;
+
+    PHDADRIVER pDrv;
     RTListForEach(&pThis->lstDrv, pDrv, HDADRIVER, Node)
     {
         uint32_t cbIn = 0;
         uint32_t cbOut = 0;
 
-        rc = pDrv->pConnector->pfnQueryStatus(pDrv->pConnector, &cbIn, &cbOut, NULL /* pcSamplesLive */);
-        if (RT_SUCCESS(rc))
-            rc = pDrv->pConnector->pfnPlayOut(pDrv->pConnector, NULL /* pcSamplesPlayed */);
+        int rc2 = pDrv->pConnector->pfnQueryStatus(pDrv->pConnector, &cbIn, &cbOut, NULL /* pcSamplesLive */);
+        if (RT_SUCCESS(rc2))
+            rc2 = pDrv->pConnector->pfnPlayOut(pDrv->pConnector, NULL /* pcSamplesPlayed */);
 
-        Log3Func(("LUN#%RU8: rc=%Rrc, cbIn=%RU32, cbOut=%RU32\n", pDrv->uLUN, rc, cbIn, cbOut));
+        Log3Func(("LUN#%RU8: rc=%Rrc, cbIn=%RU32, cbOut=%RU32\n", pDrv->uLUN, rc2, cbIn, cbOut));
 
         /* If we there was an error handling (available) output or there simply is no output available,
          * then calculate the minimum data rate which must be processed by the device emulation in order
@@ -3114,21 +3905,7 @@ static DECLCALLBACK(void) hdaTimer(PPDMDEVINS pDevIns, PTMTIMER pTimer, void *pv
         if (!pDrv->pConnector->pfnIsValidOut(pDrv->pConnector, pDrv->Out.pStrmOut))
         {
             /* Use the codec's (fixed) sampling rate. */
-            cbOut = RT_MAX(cbOut, cbCodecSamplesMin);
-        }
-        else
-        {
-            const bool fIsActiveOut = pDrv->pConnector->pfnIsActiveOut(pDrv->pConnector, pDrv->Out.pStrmOut);
-            if (   RT_FAILURE(rc)
-                || !fIsActiveOut)
-            {
-                uint32_t cSamplesMin  = (int)((2 * cTicksElapsed * pDrv->Out.pStrmOut->Props.uHz + cTicksPerSec) / cTicksPerSec / 2);
-                uint32_t cbSamplesMin = AUDIOMIXBUF_S2B(&pDrv->Out.pStrmOut->MixBuf, cSamplesMin);
-
-                Log3Func(("\trc=%Rrc, cSamplesMin=%RU32, cbSamplesMin=%RU32\n", rc, cSamplesMin, cbSamplesMin));
-
-                cbOut = RT_MAX(cbOut, cbSamplesMin);
-            }
+            cbOut = RT_MAX(cbOut, hdaStreamTransferGetElapsed(pThis, &pThis->Out));
         }
 
         cbOutMin = RT_MIN(cbOutMin, cbOut);
@@ -3146,19 +3923,30 @@ static DECLCALLBACK(void) hdaTimer(PPDMDEVINS pDevIns, PTMTIMER pTimer, void *pv
     if (cbOutMin)
     {
         Assert(cbOutMin != UINT32_MAX);
-        hdaTransfer(pThis, PO_INDEX, cbOutMin /* cbToProcess */, NULL /* pcbProcessed */);
+        hdaStreamTransfer(pThis, &pThis->Out, cbOutMin /* cbToProcessMax */);
+
+        int rc2 = hdaWriteAudio(pThis, &pThis->Out, cbOutMin);
+        AssertRC(rc2);
     }
 
     /*
-     * Recording.
+     * Recording (Line-In).
      */
-    if (cbInMax)
-        hdaTransfer(pThis, PI_INDEX, cbInMax  /* cbToProcess */, NULL /* pcbProcessed */);
+    uint32_t cbRead;
+    int rc2 = hdaReadAudio(pThis, &pThis->LineIn, pThis->pSinkLineIn, &cbRead);
+    if (   RT_SUCCESS(rc2)
+        && cbRead)
+    {
+        hdaStreamTransfer(pThis, &pThis->LineIn, cbRead);
+    }
+
+#ifdef HDA_DEBUG_TIMING
+    pThis->Dbg.tsTimerLastCalledNs = cTicksNow;
+#endif
 
     /* Kick the timer again. */
-    uint64_t cTicks = pThis->cTimerTicks;
-    /** @todo adjust cTicks down by now much cbOutMin represents. */
-    TMTimerSet(pThis->pTimer, cTicksNow + cTicks);
+    pThis->tsTimerExpire += pThis->cTimerTicks;
+    TMTimerSet(pTimer, pThis->tsTimerExpire);
 
     STAM_PROFILE_STOP(&pThis->StatTimer, a);
 }
@@ -3179,7 +3967,7 @@ static DECLCALLBACK(int) hdaCallbackInput(PDMAUDIOCALLBACKTYPE enmType, void *pv
     PPDMAUDIOCALLBACKDATAIN pData = (PPDMAUDIOCALLBACKDATAIN)pvUser;
     AssertReturn(cbUser == sizeof(PDMAUDIOCALLBACKDATAIN), VERR_INVALID_PARAMETER);
 
-    return hdaTransfer(pCtx->pThis, PI_INDEX, UINT32_MAX, &pData->cbOutRead);
+    return hdaStreamTransfer(pCtx->pThis, PI_INDEX, UINT32_MAX, &pData->cbOutRead);
 }
 
 static DECLCALLBACK(int) hdaCallbackOutput(PDMAUDIOCALLBACKTYPE enmType, void *pvCtx, size_t cbCtx, void *pvUser, size_t cbUser)
@@ -3198,7 +3986,7 @@ static DECLCALLBACK(int) hdaCallbackOutput(PDMAUDIOCALLBACKTYPE enmType, void *p
 
     PHDASTATE pThis = pCtx->pThis;
 
-    int rc = hdaTransfer(pCtx->pThis, PO_INDEX, UINT32_MAX, &pData->cbOutWritten);
+    int rc = hdaStreamTransfer(pCtx->pThis, PO_INDEX, UINT32_MAX, &pData->cbOutWritten);
     if (   RT_SUCCESS(rc)
         && pData->cbOutWritten)
     {
@@ -3213,150 +4001,264 @@ static DECLCALLBACK(int) hdaCallbackOutput(PDMAUDIOCALLBACKTYPE enmType, void *p
 }
 #endif /* VBOX_WITH_AUDIO_CALLBACKS */
 
-static int hdaTransfer(PHDASTATE pThis, ENMSOUNDSOURCE enmSrc, uint32_t cbToProcess, uint32_t *pcbProcessed)
+static uint32_t hdaStreamTransferGetElapsed(PHDASTATE pThis, PHDASTREAM pStream)
 {
-    AssertPtrReturn(pThis, VERR_INVALID_POINTER);
-    /* pcbProcessed is optional. */
+    const uint64_t cTicksNow     = TMTimerGet(pThis->pTimer);
+    const uint64_t cTicksPerSec  = TMTimerGetFreq(pThis->pTimer);
 
-    if (ASMAtomicReadBool(&pThis->fInReset)) /* HDA controller in reset mode? Bail out. */
-    {
-        LogFlowFunc(("In reset mode, skipping\n"));
+    const uint64_t cTicksElapsed = cTicksNow - pStream->State.uTimerTS;
+#ifdef DEBUG
+    const uint64_t cMsElapsed    = cTicksElapsed / (cTicksPerSec / 1000);
+#endif
 
-        if (pcbProcessed)
-            *pcbProcessed = 0;
-        return VINF_SUCCESS;
-    }
+    AssertPtr(pThis->pCodec);
 
-    PHDASTREAM pStrmSt;
-    switch (enmSrc)
-    {
-        case PI_INDEX:
-        {
-            pStrmSt = &pThis->StrmStLineIn;
-            break;
-        }
+    PDMAUDIOPCMPROPS strmProps;
+    int rc = DrvAudioStreamCfgToProps(&pStream->State.strmCfg, &strmProps);
+    AssertRC(rc);
 
-#ifdef VBOX_WITH_HDA_MIC_IN
-        case MC_INDEX:
-        {
-            pStrmSt = &pThis->StrmStMicIn;
-            break;
-        }
-#endif
-        case PO_INDEX:
-        {
-            pStrmSt = &pThis->StrmStOut;
-            break;
-        }
+    /* A stream *always* runs with 48 kHz device-wise, regardless of the actual stream input/output format (Hz) being set. */
+    uint32_t csPerPeriod = (int)((strmProps.cChannels * cTicksElapsed * 48000 /* Hz */ + cTicksPerSec) / cTicksPerSec / 2);
+    uint32_t cbPerPeriod = csPerPeriod << strmProps.cShift;
 
-        default:
-        {
-            AssertMsgFailed(("Unknown source index %ld\n", enmSrc));
-            return VERR_NOT_SUPPORTED;
-        }
+    Log3Func(("[SD%RU8] %RU64ms (%zu samples, %zu bytes) elapsed\n", pStream->u8SD, cMsElapsed, csPerPeriod, cbPerPeriod));
+
+    return cbPerPeriod;
+}
+
+/**
+ * Transfers data of an HDA stream according to its usage (input / output).
+ *
+ * For an SDO (output) stream this means reading DMA data from the device to
+ * the HDA stream's internal FIFO buffer.
+ *
+ * For an SDI (input) stream this is reading audio data from the HDA stream's
+ * internal FIFO buffer and writing it as DMA data to the device.
+ *
+ * @returns IPRT status code.
+ * @param   pThis               HDA state.
+ * @param   pStream             HDA stream to update.
+ * @param   cbToProcessMax      Maximum of data (in bytes) to process.
+ */
+static void hdaStreamTransfer(PHDASTATE pThis, PHDASTREAM pStream, uint32_t cbToProcessMax)
+{
+    AssertPtrReturnVoid(pThis);
+    AssertPtrReturnVoid(pStream);
+    AssertReturnVoid(cbToProcessMax);
+
+    Log3Func(("[SD%RU8] Enter ==========================================\n", pStream->u8SD));
+
+    if (ASMAtomicReadBool(&pThis->fInReset)) /* HDA controller in reset mode? Bail out. */
+    {
+        LogFunc(("[SD%RU8] In reset mode, skipping\n", pStream->u8SD));
+        return;
     }
 
     int  rc       = VINF_SUCCESS;
     bool fProceed = true;
 
-    /* Stop request received? */
-    if (ASMAtomicReadBool(&pStrmSt->State.fDoStop))
-    {
-        pStrmSt->State.fActive = false;
+    PHDASTREAMPERIOD pPeriod = &pStream->State.Period;
 
-        rc = RTSemEventSignal(pStrmSt->State.hStateChangedEvent);
-        AssertRC(rc);
+    rc = hdaStreamPeriodLock(pPeriod);
+    AssertRCReturnVoid(rc);
 
+    /* Stream not active? */
+    if (!ASMAtomicReadBool(&pStream->State.fRunning))
+    {
+        Log3Func(("[SD%RU8] Not running\n", pStream->u8SD));
         fProceed = false;
     }
-    /* Is the stream not in a running state currently? */
-    else if (!(HDA_STREAM_REG(pThis, CTL, pStrmSt->u8Strm) & HDA_REG_FIELD_FLAG_MASK(SDCTL, RUN)))
+    /* Stream not running? */
+    else if (!(HDA_STREAM_REG(pThis, CTL, pStream->u8SD) & HDA_REG_FIELD_FLAG_MASK(SDCTL, RUN)))
+    {
+        Log3Func(("[SD%RU8] RUN bit not set\n", pStream->u8SD));
         fProceed = false;
-    /* Nothing to process? */
-    else if (!cbToProcess)
+    }
+    /* Period complete? */
+    else if (hdaStreamPeriodIsComplete(pPeriod))
+    {
+        Log3Func(("[SD%RU8] Period is complete, nothing to do\n", pStream->u8SD));
         fProceed = false;
+    }
 
     if (!fProceed)
     {
-        if (pcbProcessed)
-            *pcbProcessed = 0;
-        return VINF_SUCCESS;
+        hdaStreamPeriodUnlock(pPeriod);
+        return;
     }
 
-    LogFlowFunc(("enmSrc=%RU32, cbToProcess=%RU32\n", enmSrc, cbToProcess));
-
     /* Sanity checks. */
-    Assert(pStrmSt->u8Strm <= 7); /** @todo Use a define for MAX_STREAMS! */
-    Assert(pStrmSt->u64BDLBase);
-    Assert(pStrmSt->u32CBL);
+    Assert(pStream->u8SD <= 7); /** @todo Use a define for MAX_STREAMS! */
+    Assert(pStream->u64BDLBase);
+    Assert(pStream->u32CBL);
 
     /* State sanity checks. */
-    Assert(ASMAtomicReadBool(&pStrmSt->State.fInReset) == false);
+    Assert(ASMAtomicReadBool(&pStream->State.fInReset) == false);
+
+    /* Fetch first / next BDL entry. */
+    PHDABDLE pBDLE = &pStream->State.BDLE;
+    if (hdaBDLEIsComplete(pBDLE))
+    {
+        rc = hdaBDLEFetch(pThis, pBDLE, pStream->u64BDLBase, pStream->State.uCurBDLE);
+        AssertRC(rc);
+    }
+
+    const uint32_t cbPeriodRemaining = hdaStreamPeriodGetRemainingFrames(pPeriod) * HDA_FRAME_SIZE;
+    Assert(cbPeriodRemaining); /* Paranoia. */
 
-    uint32_t cbProcessedTotal = 0;
-    bool     fIsComplete      = false;
+    const uint32_t cbElapsed         = hdaStreamTransferGetElapsed(pThis, pStream);
+    Assert(cbElapsed);         /* Paranoia. */
 
-    while (cbToProcess)
+    /* Limit the data to read, as this routine could be delayed and therefore
+     * report wrong (e.g. too much) cbElapsed bytes. */
+    uint32_t cbLeft                  = RT_MIN(RT_MIN(cbPeriodRemaining, cbElapsed), cbToProcessMax);
+
+    Log3Func(("[SD%RU8] cbPeriodRemaining=%RU32, cbElapsed=%RU32, cbToProcessMax=%RU32 -> cbLeft=%RU32\n",
+              pStream->u8SD, cbPeriodRemaining, cbElapsed, cbToProcessMax, cbLeft));
+
+    Assert(cbLeft % HDA_FRAME_SIZE == 0);
+
+    while (cbLeft)
     {
-        /* Do we need to fetch the next Buffer Descriptor Entry (BDLE)? */
-        if (hdaStreamNeedsNextBDLE(pThis, pStrmSt))
-            hdaStreamGetNextBDLE(pThis, pStrmSt);
+        uint32_t cbChunk = RT_MIN(hdaStreamGetTransferSize(pThis, pStream), cbLeft);
+        if (!cbChunk)
+            break;
 
-        /* Set the FIFORDY bit on the stream while doing the transfer. */
-        HDA_STREAM_REG(pThis, STS, pStrmSt->u8Strm) |= HDA_REG_FIELD_FLAG_MASK(SDSTS, FIFORDY);
+        uint32_t cbDMA   = 0;
 
-        uint32_t cbProcessed = 0;
-        switch (enmSrc)
+        switch (pStream->u8SD)
         {
-            case PI_INDEX:
-                rc = hdaReadAudio(pThis, pStrmSt, pThis->pSinkLineIn, cbToProcess, &cbProcessed);
-                break;
-            case PO_INDEX:
-                rc = hdaWriteAudio(pThis, pStrmSt, cbToProcess, &cbProcessed);
-                break;
+            case 0: /* Line-In */
 #ifdef VBOX_WITH_HDA_MIC_IN
-            case MC_INDEX:
-                rc = hdaReadAudio(pThis, pStrmSt, pThis->pSinkMicIn, cbToProcess, &cbProcessed);
-                break;
+            case 2: /* Microphone-In */
 #endif
+            {
+                rc = hdaDMAWrite(pThis, pStream, cbChunk, &cbDMA /* pcbWritten */);
+                if (RT_FAILURE(rc))
+                    LogRel(("HDA: Writing to stream #%RU8 DMA failed with %Rrc\n", pStream->u8SD, rc));
+                break;
+            }
+
+            case 4: /* Output */
+            {
+                rc = hdaDMARead(pThis, pStream, cbChunk, &cbDMA /* pcbRead */);
+                if (RT_FAILURE(rc))
+                    LogRel(("HDA: Reading from stream #%RU8 DMA failed with %Rrc\n", pStream->u8SD, rc));
+                break;
+            }
+
             default:
-                AssertMsgFailed(("Unsupported source index %ld\n", enmSrc));
+                AssertMsgFailed(("Unsupported stream #%RU8\n", pStream->u8SD));
                 rc = VERR_NOT_SUPPORTED;
                 break;
         }
 
-        /* Remove the FIFORDY bit again. */
-        HDA_STREAM_REG(pThis, STS, pStrmSt->u8Strm) &= ~HDA_REG_FIELD_FLAG_MASK(SDSTS, FIFORDY);
+        if (cbDMA)
+        {
+            Assert(cbDMA % HDA_FRAME_SIZE == 0);
 
-        if (RT_FAILURE(rc))
-            break;
+            /* We always increment the position of DMA buffer counter because we're always reading
+             * into an intermediate buffer. */
+            pBDLE->State.u32BufOff += (uint32_t)cbDMA;
+            Assert(pBDLE->State.u32BufOff <= pBDLE->Desc.u32BufSize);
+
+            hdaStreamTransferInc(pThis, pStream, cbDMA);
+
+            uint32_t framesDMA = cbDMA / HDA_FRAME_SIZE;
+
+            /* Add the transferred frames to the period. */
+            hdaStreamPeriodInc(pPeriod, framesDMA);
+
+            /* Save the timestamp of when the last successful DMA transfer has been for this stream. */
+            pStream->State.uTimerTS = TMTimerGet(pThis->pTimer);
+
+            Assert(cbLeft >= cbDMA);
+            cbLeft        -= cbDMA;
+        }
+
+        if (hdaBDLEIsComplete(pBDLE))
+        {
+            Log3Func(("[SD%RU8] Complete: %R[bdle]\n", pStream->u8SD, pBDLE));
 
-        hdaStreamTransferUpdate(pThis, pStrmSt, cbProcessed);
+            if (hdaBDLENeedsInterrupt(pBDLE))
+            {
+                /* If the IOCE ("Interrupt On Completion Enable") bit of the SDCTL register is set
+                 * we need to generate an interrupt.
+                 */
+                if (HDA_STREAM_REG(pThis, CTL, pStream->u8SD) & HDA_REG_FIELD_FLAG_MASK(SDCTL, ICE))
+                    hdaStreamPeriodAcquireInterrupt(pPeriod);
+            }
 
-        cbToProcess      -= RT_MIN(cbToProcess, cbProcessed);
-        cbProcessedTotal += cbProcessed;
+            if (pStream->State.uCurBDLE == pStream->u16LVI)
+            {
+                Assert(pStream->u32CBL == HDA_STREAM_REG(pThis, LPIB, pStream->u8SD));
 
-        LogFlowFunc(("cbProcessed=%RU32, cbToProcess=%RU32, cbProcessedTotal=%RU32, rc=%Rrc\n",
-                     cbProcessed, cbToProcess, cbProcessedTotal, rc));
+                pStream->State.uCurBDLE = 0;
+                hdaStreamUpdateLPIB(pThis, pStream, 0 /* LPIB */);
+            }
+            else
+                pStream->State.uCurBDLE++;
 
-        if (rc == VINF_EOF)
-            fIsComplete = true;
+            hdaBDLEFetch(pThis, pBDLE, pStream->u64BDLBase, pStream->State.uCurBDLE);
 
-        if (!fIsComplete)
-            fIsComplete = hdaStreamTransferIsComplete(pThis, pStrmSt);
+            Log3Func(("[SD%RU8] Fetching: %R[bdle]\n", pStream->u8SD, pBDLE));
+        }
 
-        if (fIsComplete)
+        if (RT_FAILURE(rc))
             break;
     }
 
-    if (RT_SUCCESS(rc))
+    if (hdaStreamPeriodIsComplete(pPeriod))
     {
-        if (pcbProcessed)
-            *pcbProcessed = cbProcessedTotal;
+        Log3Func(("[SD%RU8] Period complete -- Current: %R[bdle]\n", pStream->u8SD, &pStream->State.BDLE));
+
+        /* Set the stream's BCIS bit.
+         *
+         * Note: This only must be done if the whole period is complete, and not if only
+         * one specific BDL entry is complete (if it has the IOC bit set).
+         *
+         * This will otherwise confuses the guest when it 1) deasserts the interrupt,
+         * 2) reads SDSTS (with BCIS set) and then 3) too early reads a (wrong) WALCLK value.
+         *
+         * snd_hda_intel on Linux will tell. */
+        HDA_STREAM_REG(pThis, STS, pStream->u8SD) |= HDA_REG_FIELD_FLAG_MASK(SDSTS, BCIS);
+
+        /* Try updating the wall clock. */
+        const uint64_t u64WalClk  = hdaStreamPeriodGetAbsElapsedWalClk(pPeriod);
+        const bool     fWalClkSet = hdaWalClkSet(pThis, u64WalClk, false /* fForce */);
+
+        /* Does the period have any interrupts outstanding? */
+        if (hdaStreamPeriodNeedsInterrupt(pPeriod))
+        {
+            if (fWalClkSet)
+            {
+                Log3Func(("[SD%RU8] Set WALCLK to %RU64, triggering interrupt\n", pStream->u8SD, u64WalClk));
+
+                /* Trigger an interrupt first and let hdaRegWriteSDSTS() deal with
+                 * ending / beginning a period. */
+#ifndef DEBUG
+                hdaProcessInterrupt(pThis);
+#else
+                hdaProcessInterrupt(pThis, __FUNCTION__);
+#endif
+            }
+        }
+        else
+        {
+            /* End the period first ... */
+            hdaStreamPeriodEnd(pPeriod);
+
+            /* ... and immediately begin the next one. */
+            hdaStreamPeriodBegin(pPeriod, hdaWalClkGetCurrent(pThis));
+        }
     }
 
-    LogFlowFuncLeaveRC(rc);
-    return rc;
+    hdaStreamPeriodUnlock(pPeriod);
+
+    Log3Func(("[SD%RU8] Returning %Rrc ==========================================\n", pStream->u8SD, rc));
+
+    if (RT_FAILURE(rc))
+        LogFunc(("[SD%RU8] Failed with rc=%Rrcc\n", pStream->u8SD, rc));
 }
 #endif /* IN_RING3 */
 
@@ -3385,14 +4287,14 @@ PDMBOTHCBDECL(int) hdaMMIORead(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhys
     uint32_t        offRegLog = offReg;
 #endif
 
-    LogFunc(("offReg=%#x cb=%#x\n", offReg, cb));
+    Log3Func(("offReg=%#x cb=%#x\n", offReg, cb));
     Assert(cb == 4); Assert((offReg & 3) == 0);
 
     if (pThis->fInReset && idxRegDsc != HDA_REG_GCTL)
-        LogFunc(("\tAccess to registers except GCTL is blocked while reset\n"));
+        LogFunc(("Access to registers except GCTL is blocked while reset\n"));
 
     if (idxRegDsc == -1)
-        LogRel(("HDA: Invalid read access @0x%x (bytes=%d)\n", offReg, cb));
+        LogRel(("HDA: Invalid read access @0x%x (bytes=%u)\n", offReg, cb));
 
     if (idxRegDsc != -1)
     {
@@ -3403,7 +4305,7 @@ PDMBOTHCBDECL(int) hdaMMIORead(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhys
              * Straight forward DWORD access.
              */
             rc = g_aHdaRegMap[idxRegDsc].pfnRead(pThis, idxRegDsc, (uint32_t *)pv);
-            LogFunc(("\tRead %s => %x (%Rrc)\n", g_aHdaRegMap[idxRegDsc].abbrev, *(uint32_t *)pv, rc));
+            Log3Func(("\tRead %s => %x (%Rrc)\n", g_aHdaRegMap[idxRegDsc].abbrev, *(uint32_t *)pv, rc));
         }
         else
         {
@@ -3419,7 +4321,7 @@ PDMBOTHCBDECL(int) hdaMMIORead(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhys
                 uint32_t        u32Tmp       = 0;
 
                 rc = g_aHdaRegMap[idxRegDsc].pfnRead(pThis, idxRegDsc, &u32Tmp);
-                LogFunc(("\tRead %s[%db] => %x (%Rrc)*\n", g_aHdaRegMap[idxRegDsc].abbrev, cbReg, u32Tmp, rc));
+                Log3Func(("\tRead %s[%db] => %x (%Rrc)*\n", g_aHdaRegMap[idxRegDsc].abbrev, cbReg, u32Tmp, rc));
                 if (rc != VINF_SUCCESS)
                     break;
                 u32Value |= (u32Tmp & g_afMasks[cbReg]) << ((4 - cbLeft) * 8);
@@ -3438,7 +4340,7 @@ PDMBOTHCBDECL(int) hdaMMIORead(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhys
     else
     {
         rc = VINF_IOM_MMIO_UNUSED_FF;
-        LogFunc(("\tHole at %x is accessed for read\n", offReg));
+        Log3Func(("\tHole at %x is accessed for read\n", offReg));
     }
 
     /*
@@ -3446,11 +4348,11 @@ PDMBOTHCBDECL(int) hdaMMIORead(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhys
      */
 #ifdef LOG_ENABLED
     if (cbLog == 4)
-        LogFunc(("\tReturning @%#05x -> %#010x %Rrc\n", offRegLog, *(uint32_t *)pv, rc));
+        Log3Func(("\tReturning @%#05x -> %#010x %Rrc\n", offRegLog, *(uint32_t *)pv, rc));
     else if (cbLog == 2)
-        LogFunc(("\tReturning @%#05x -> %#06x %Rrc\n", offRegLog, *(uint16_t *)pv, rc));
+        Log3Func(("\tReturning @%#05x -> %#06x %Rrc\n", offRegLog, *(uint16_t *)pv, rc));
     else if (cbLog == 1)
-        LogFunc(("\tReturning @%#05x -> %#04x %Rrc\n", offRegLog, *(uint8_t *)pv, rc));
+        Log3Func(("\tReturning @%#05x -> %#04x %Rrc\n", offRegLog, *(uint8_t *)pv, rc));
 #endif
     return rc;
 }
@@ -3668,57 +4570,125 @@ static int hdaSaveStream(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, PHDASTREAM pStrm)
     PHDASTATE pThis = PDMINS_2_DATA(pDevIns, PHDASTATE);
 #endif
 
-    LogFlowFunc(("[SD%RU8]\n", pStrm->u8Strm));
+    Log2Func(("[SD%RU8]\n", pStrm->u8SD));
 
     /* Save stream ID. */
-    int rc = SSMR3PutU8(pSSM, pStrm->u8Strm);
+    int rc = SSMR3PutU8(pSSM, pStrm->u8SD);
     AssertRCReturn(rc, rc);
-    Assert(pStrm->u8Strm <= 7); /** @todo Use a define. */
+    Assert(pStrm->u8SD <= 7); /** @todo Use a define. */
 
-    rc = SSMR3PutStructEx(pSSM, &pStrm->State, sizeof(HDASTREAMSTATE), 0 /*fFlags*/, g_aSSMStreamStateFields6, NULL);
+    rc = SSMR3PutStructEx(pSSM, &pStrm->State, sizeof(HDASTREAMSTATE), 0 /*fFlags*/, g_aSSMStreamStateFields7, NULL);
     AssertRCReturn(rc, rc);
 
 #ifdef VBOX_STRICT /* Sanity checks. */
-    uint64_t u64BaseDMA = RT_MAKE_U64(HDA_STREAM_REG(pThis, BDPL, pStrm->u8Strm),
-                                      HDA_STREAM_REG(pThis, BDPU, pStrm->u8Strm));
-    uint16_t u16LVI     = HDA_STREAM_REG(pThis, LVI, pStrm->u8Strm);
-    uint32_t u32CBL     = HDA_STREAM_REG(pThis, CBL, pStrm->u8Strm);
-
-    hdaBDLEDumpAll(pThis, u64BaseDMA, u16LVI + 1);
+    uint64_t u64BaseDMA = RT_MAKE_U64(HDA_STREAM_REG(pThis, BDPL, pStrm->u8SD),
+                                      HDA_STREAM_REG(pThis, BDPU, pStrm->u8SD));
+    uint16_t u16LVI     = HDA_STREAM_REG(pThis, LVI, pStrm->u8SD);
+    uint32_t u32CBL     = HDA_STREAM_REG(pThis, CBL, pStrm->u8SD);
 
     Assert(u64BaseDMA == pStrm->u64BDLBase);
     Assert(u16LVI     == pStrm->u16LVI);
     Assert(u32CBL     == pStrm->u32CBL);
 #endif
 
-    rc = SSMR3PutStructEx(pSSM, &pStrm->State.BDLE, sizeof(HDABDLE),
-                          0 /*fFlags*/, g_aSSMBDLEFields6, NULL);
+    rc = SSMR3PutStructEx(pSSM, &pStrm->State.BDLE.Desc, sizeof(HDABDLEDESC),
+                          0 /*fFlags*/, g_aSSMBDLEDescFields7, NULL);
     AssertRCReturn(rc, rc);
 
     rc = SSMR3PutStructEx(pSSM, &pStrm->State.BDLE.State, sizeof(HDABDLESTATE),
-                          0 /*fFlags*/, g_aSSMBDLEStateFields6, NULL);
+                          0 /*fFlags*/, g_aSSMBDLEStateFields7, NULL);
+    AssertRCReturn(rc, rc);
+
+    rc = SSMR3PutStructEx(pSSM, &pStrm->State.Period, sizeof(HDASTREAMPERIOD),
+                          0 /* fFlags */, g_aSSMStreamPeriodFields7, NULL);
     AssertRCReturn(rc, rc);
 
 #ifdef VBOX_STRICT /* Sanity checks. */
     PHDABDLE pBDLE = &pStrm->State.BDLE;
     if (u64BaseDMA)
     {
-        Assert(pStrm->State.uCurBDLE <= u16LVI + 1);
+        Assert(pStrm->State.uCurBDLE <= u16LVI);
 
         HDABDLE curBDLE;
         rc = hdaBDLEFetch(pThis, &curBDLE, u64BaseDMA, pStrm->State.uCurBDLE);
         AssertRC(rc);
 
-        Assert(curBDLE.u32BufSize       == pBDLE->u32BufSize);
-        Assert(curBDLE.u64BufAdr        == pBDLE->u64BufAdr);
-        Assert(curBDLE.fIntOnCompletion == pBDLE->fIntOnCompletion);
-    }
-    else
-    {
-        Assert(pBDLE->u64BufAdr  == 0);
-        Assert(pBDLE->u32BufSize == 0);
+        Assert(curBDLE.Desc.u32BufSize == pBDLE->Desc.u32BufSize);
+        Assert(curBDLE.Desc.u64BufAdr  == pBDLE->Desc.u64BufAdr);
+        Assert(curBDLE.Desc.fFlags     == pBDLE->Desc.fFlags);
+    }
+    else
+    {
+        Assert(pBDLE->Desc.u64BufAdr  == 0);
+        Assert(pBDLE->Desc.u32BufSize == 0);
+    }
+#endif
+
+    uint32_t cbCircBufSize = 0;
+    uint32_t cbCircBufUsed = 0;
+
+    if (pStrm->State.pCircBuf)
+    {
+        cbCircBufSize = (uint32_t)RTCircBufSize(pStrm->State.pCircBuf);
+        cbCircBufUsed = (uint32_t)RTCircBufUsed(pStrm->State.pCircBuf);
+    }
+
+    rc = SSMR3PutU32(pSSM, cbCircBufSize);
+    AssertRCReturn(rc, rc);
+
+    rc = SSMR3PutU32(pSSM, cbCircBufUsed);
+    AssertRCReturn(rc, rc);
+
+    if (cbCircBufUsed)
+    {
+        /*
+         * We now need to get the circular buffer's data without actually modifying
+         * the internal read / used offsets -- otherwise we would end up with broken audio
+         * data after saving the state.
+         *
+         * So get the current read offset and serialize the buffer data manually based on that.
+         */
+        size_t cbCircBufOffRead = RTCircBufOffsetRead(pStrm->State.pCircBuf);
+
+        void  *pvBuf;
+        size_t cbBuf;
+        RTCircBufAcquireReadBlock(pStrm->State.pCircBuf, cbCircBufUsed, &pvBuf, &cbBuf);
+
+        if (cbBuf)
+        {
+            size_t cbToRead = cbCircBufUsed;
+            size_t cbEnd    = 0;
+
+            if (cbCircBufUsed > cbCircBufOffRead)
+                cbEnd = cbCircBufUsed - cbCircBufOffRead;
+
+            if (cbEnd) /* Save end of buffer first. */
+            {
+                rc = SSMR3PutMem(pSSM, (uint8_t *)pvBuf + cbCircBufSize - cbEnd /* End of buffer */, cbEnd);
+                AssertRCReturn(rc, rc);
+
+                Assert(cbToRead >= cbEnd);
+                cbToRead -= cbEnd;
+            }
+
+            if (cbToRead) /* Save remaining stuff at start of buffer (if any). */
+            {
+                rc = SSMR3PutMem(pSSM, (uint8_t *)pvBuf - cbCircBufUsed /* Start of buffer */, cbToRead);
+                AssertRCReturn(rc, rc);
+            }
+        }
+
+        RTCircBufReleaseReadBlock(pStrm->State.pCircBuf, 0 /* Don't advance read pointer -- see comment above */);
     }
+
+    Log2Func(("[SD%RU8] LPIB=%RU32, CBL=%RU32, LVI=%RU32\n",
+              pStrm->u8SD,
+              HDA_STREAM_REG(pThis, LPIB, pStrm->u8SD), HDA_STREAM_REG(pThis, CBL, pStrm->u8SD), HDA_STREAM_REG(pThis, LVI, pStrm->u8SD)));
+
+#ifdef LOG_ENABLED
+    hdaBDLEDumpAll(pThis, pStrm->u64BDLBase, pStrm->u16LVI + 1);
 #endif
+
     return rc;
 }
 
@@ -3737,6 +4707,10 @@ static DECLCALLBACK(int) hdaSaveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM)
     SSMR3PutU32(pSSM, RT_ELEMENTS(pThis->au32Regs));
     SSMR3PutMem(pSSM, pThis->au32Regs, sizeof(pThis->au32Regs));
 
+    /* Save controller-specifc internals. */
+    SSMR3PutU64(pSSM, pThis->u64WalClk);
+    SSMR3PutU8(pSSM, pThis->u8IRQL);
+
     /* Save number of streams. */
 #ifdef VBOX_WITH_HDA_MIC_IN
     SSMR3PutU32(pSSM, 3);
@@ -3745,39 +4719,140 @@ static DECLCALLBACK(int) hdaSaveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM)
 #endif
 
     /* Save stream states. */
-    int rc = hdaSaveStream(pDevIns, pSSM, &pThis->StrmStOut);
+    int rc = hdaSaveStream(pDevIns, pSSM, &pThis->Out);
     AssertRCReturn(rc, rc);
 #ifdef VBOX_WITH_HDA_MIC_IN
-    rc = hdaSaveStream(pDevIns, pSSM, &pThis->StrmStMicIn);
+    rc = hdaSaveStream(pDevIns, pSSM, &pThis->MicIn);
     AssertRCReturn(rc, rc);
 #endif
-    rc = hdaSaveStream(pDevIns, pSSM, &pThis->StrmStLineIn);
+    rc = hdaSaveStream(pDevIns, pSSM, &pThis->LineIn);
     AssertRCReturn(rc, rc);
 
+    Log2Func(("DPLBASE=%RU64, DPUBASE=%RU64, DMAPos=%RTbool\n",
+              HDA_REG(pThis, DPLBASE), HDA_REG(pThis, DPUBASE), RT_BOOL(HDA_REG(pThis, DPLBASE) & RT_BIT_32(0))));
+
     return rc;
 }
 
 
 /**
- * @callback_method_impl{FNSSMDEVLOADEXEC}
+ * Does required post processing when loading a saved state.
+ *
+ * @param   pThis               Pointer to HDA state.
  */
-static DECLCALLBACK(int) hdaLoadExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass)
+static int hdaLoadExecPost(PHDASTATE pThis)
 {
-    PHDASTATE pThis = PDMINS_2_DATA(pDevIns, PHDASTATE);
-
-    Assert(uPass == SSM_PASS_FINAL); NOREF(uPass);
+    int rc = VINF_SUCCESS;
 
-    LogRel2(("hdaLoadExec: uVersion=%RU32, uPass=0x%x\n", uVersion, uPass));
+    bool fStartTimer = false; /* Whether to resume the device timer. */
 
     /*
-     * Load Codec nodes states.
+     * Update stuff after the state changes.
      */
-    int rc = hdaCodecLoadState(pThis->pCodec, pSSM, uVersion);
-    if (RT_FAILURE(rc))
+    bool fEnableIn = RT_BOOL(HDA_SDCTL(pThis, 0 /** @todo Use a define. */) & HDA_REG_FIELD_FLAG_MASK(SDCTL, RUN));
+    if (fEnableIn)
     {
-        LogRel(("HDA: Failed loading codec state (version %RU32, pass 0x%x), rc=%Rrc\n", uVersion, uPass, rc));
-        return rc;
+        /* (Re-)initialize the stream with current values. */
+        int rc2 = hdaStreamInit(pThis, &pThis->LineIn, 0 /** @todo Use a define. */);
+        AssertRC(rc2);
+
+        /* Set the running flag. */
+        ASMAtomicXchgBool(&pThis->LineIn.State.fRunning, true);
+
+        /* Resume the stream's period. */
+        hdaStreamPeriodResume(&pThis->LineIn.State.Period);
+    }
+#ifdef VBOX_WITH_HDA_MIC_IN
+    bool fEnableMicIn = RT_BOOL(HDA_SDCTL(pThis, 2 /** @todo Use a define. */) & HDA_REG_FIELD_FLAG_MASK(SDCTL, RUN));
+    if (fEnableMicIn)
+    {
+        /* (Re-)initialize the stream with current values. */
+        int rc2 = hdaStreamInit(pThis, &pThis->MicIn, 2 /** @todo Use a define. */);
+        AssertRC(rc2);
+
+        /* Set the running flag. */
+        ASMAtomicXchgBool(&pThis->MicIn.State.fRunning, true);
+
+        /* Resume the stream's period. */
+        hdaStreamPeriodResume(&pThis->MicIn.State.Period);
+    }
+#endif
+    bool fEnableOut = RT_BOOL(HDA_SDCTL(pThis, 4 /** @todo Use a define. */) & HDA_REG_FIELD_FLAG_MASK(SDCTL, RUN));
+    if (fEnableOut)
+    {
+        /* (Re-)initialize the stream with current values. */
+        int rc2 = hdaStreamInit(pThis, &pThis->Out, 4 /** @todo Use a define. */);
+        AssertRC(rc2);
+
+        /* Set the running flag. */
+        ASMAtomicXchgBool(&pThis->Out.State.fRunning, true);
+
+        /* Resume the stream's period. */
+        hdaStreamPeriodResume(&pThis->Out.State.Period);
+    }
+
+    PHDADRIVER pDrv;
+    RTListForEach(&pThis->lstDrv, pDrv, HDADRIVER, Node)
+    {
+        int rc2 = pDrv->pConnector->pfnEnableIn(pDrv->pConnector, pDrv->LineIn.pStrmIn, fEnableIn);
+        if (RT_FAILURE(rc2))
+            LogRel2(("Audio: Unable to resume line-in, rc=%Rrc\n", rc2));
+#ifdef VBOX_WITH_HDA_MIC_IN
+        rc2 = pDrv->pConnector->pfnEnableIn(pDrv->pConnector, pDrv->MicIn.pStrmIn, fEnableMicIn);
+        if (RT_FAILURE(rc2))
+            LogRel2(("Audio: Unable to resume microphone-in, rc=%Rrc\n", rc2));
+#endif
+        rc2 = pDrv->pConnector->pfnEnableOut(pDrv->pConnector, pDrv->Out.pStrmOut, fEnableOut);
+        if (RT_FAILURE(rc2))
+            LogRel2(("Audio: Unable to resume output, rc=%Rrc\n", rc2));
+    }
+
+#ifndef VBOX_WITH_AUDIO_CALLBACKS
+    if (   fEnableIn
+# ifdef VBOX_WITH_HDA_MIC_IN
+        || fEnableMicIn
+# endif
+        || fEnableOut)
+    {
+        fStartTimer = true;
+    }
+#endif
+
+#ifdef HDA_USE_DMA_ACCESS_HANDLER
+    hdaStreamRegisterDMAHandlers(pThis, &pThis->Out);
+#endif
+
+#ifndef VBOX_WITH_AUDIO_CALLBACKS
+    if (   fStartTimer
+        && pThis->pTimer
+        && !TMTimerIsActive(pThis->pTimer))
+    {
+        pThis->tsTimerExpire = TMTimerGet(pThis->pTimer) + pThis->cTimerTicks;
+
+        /* Resume timer. */
+        int rc2 = TMTimerSet(pThis->pTimer, pThis->tsTimerExpire);
+        AssertRC(rc2);
     }
+#endif
+
+    LogFlowFuncLeaveRC(rc);
+    return rc;
+}
+
+
+/**
+ * Handles loading of all saved state versions older than the current one.
+ *
+ * @param   pThis               Pointer to HDA state.
+ * @param   pSSM                Pointer to SSM handle.
+ * @param   uVersion            Saved state version to load.
+ * @param   uPass               Loading stage to handle.
+ */
+static int hdaLoadExecLegacy(PHDASTATE pThis, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass)
+{
+    RT_NOREF(uPass);
+
+    int rc = VINF_SUCCESS;
 
     /*
      * Load MMIO registers.
@@ -3809,7 +4884,7 @@ static DECLCALLBACK(int) hdaLoadExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32
         /* Since version 4 we store the register count to stay flexible. */
         case HDA_SSM_VERSION_4:
         case HDA_SSM_VERSION_5:
-        case HDA_SSM_VERSION:
+        case HDA_SSM_VERSION_6:
             rc = SSMR3GetU32(pSSM, &cRegs); AssertRCReturn(rc, rc);
             if (cRegs != RT_ELEMENTS(pThis->au32Regs))
                 LogRel(("HDA: SSM version cRegs is %RU32, expected %RU32\n", cRegs, RT_ELEMENTS(pThis->au32Regs)));
@@ -3828,6 +4903,14 @@ static DECLCALLBACK(int) hdaLoadExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32
     else
         SSMR3GetMem(pSSM, pThis->au32Regs, sizeof(uint32_t) * cRegs);
 
+    /* Make sure to update the base addresses first before initializing any streams down below. */
+    pThis->u64CORBBase  = RT_MAKE_U64(HDA_REG(pThis, CORBLBASE), HDA_REG(pThis, CORBUBASE));
+    pThis->u64RIRBBase  = RT_MAKE_U64(HDA_REG(pThis, RIRBLBASE), HDA_REG(pThis, RIRBUBASE));
+    pThis->u64DPBase    = RT_MAKE_U64(HDA_REG(pThis, DPLBASE) & DPBASE_ADDR_MASK, HDA_REG(pThis, DPUBASE));
+
+    /* Also make sure to update the DMA position bit if this was enabled when saving the state. */
+    pThis->fDMAPosition = RT_BOOL(HDA_REG(pThis, DPLBASE) & RT_BIT_32(0));
+
     /*
      * Note: Saved states < v5 store LVI (u32BdleMaxCvi) for
      *       *every* BDLE state, whereas it only needs to be stored
@@ -3839,26 +4922,30 @@ static DECLCALLBACK(int) hdaLoadExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32
      *       according to the spec).
      */
 #define HDA_SSM_LOAD_BDLE_STATE_PRE_V5(v, x)                            \
-    rc = SSMR3Skip(pSSM, sizeof(uint32_t));        /* Begin marker */   \
-    AssertRCReturn(rc, rc);                                             \
-    rc = SSMR3GetU64(pSSM, &x.u64BufAdr);          /* u64BdleCviAddr */ \
-    AssertRCReturn(rc, rc);                                             \
-    rc = SSMR3Skip(pSSM, sizeof(uint32_t));        /* u32BdleMaxCvi */  \
-    AssertRCReturn(rc, rc);                                             \
-    rc = SSMR3GetU32(pSSM, &x.State.u32BDLIndex);  /* u32BdleCvi */     \
-    AssertRCReturn(rc, rc);                                             \
-    rc = SSMR3GetU32(pSSM, &x.u32BufSize);         /* u32BdleCviLen */  \
-    AssertRCReturn(rc, rc);                                             \
-    rc = SSMR3GetU32(pSSM, &x.State.u32BufOff);    /* u32BdleCviPos */  \
-    AssertRCReturn(rc, rc);                                             \
-    rc = SSMR3GetBool(pSSM, &x.fIntOnCompletion);  /* fBdleCviIoc */    \
-    AssertRCReturn(rc, rc);                                             \
-    rc = SSMR3GetU32(pSSM, &x.State.cbBelowFIFOW); /* cbUnderFifoW */   \
-    AssertRCReturn(rc, rc);                                             \
-    rc = SSMR3GetMem(pSSM, &x.State.au8FIFO, sizeof(x.State.au8FIFO));  \
-    AssertRCReturn(rc, rc);                                             \
-    rc = SSMR3Skip(pSSM, sizeof(uint32_t));        /* End marker */     \
-    AssertRCReturn(rc, rc);                                             \
+    {                                                                       \
+        rc = SSMR3Skip(pSSM, sizeof(uint32_t));        /* Begin marker */   \
+        AssertRCReturn(rc, rc);                                             \
+        rc = SSMR3GetU64(pSSM, &x.Desc.u64BufAdr);     /* u64BdleCviAddr */ \
+        AssertRCReturn(rc, rc);                                             \
+        rc = SSMR3Skip(pSSM, sizeof(uint32_t));        /* u32BdleMaxCvi */  \
+        AssertRCReturn(rc, rc);                                             \
+        rc = SSMR3GetU32(pSSM, &x.State.u32BDLIndex);  /* u32BdleCvi */     \
+        AssertRCReturn(rc, rc);                                             \
+        rc = SSMR3GetU32(pSSM, &x.Desc.u32BufSize);    /* u32BdleCviLen */  \
+        AssertRCReturn(rc, rc);                                             \
+        rc = SSMR3GetU32(pSSM, &x.State.u32BufOff);    /* u32BdleCviPos */  \
+        AssertRCReturn(rc, rc);                                             \
+        bool fIOC;                                                          \
+        rc = SSMR3GetBool(pSSM, &fIOC);                /* fBdleCviIoc */    \
+        AssertRCReturn(rc, rc);                                             \
+        x.Desc.fFlags = fIOC ? HDA_BDLE_FLAG_IOC : 0;                       \
+        rc = SSMR3GetU32(pSSM, &x.State.cbBelowFIFOW); /* cbUnderFifoW */   \
+        AssertRCReturn(rc, rc);                                             \
+        rc = SSMR3Skip(pSSM, sizeof(uint8_t) * 256);   /* FIFO */           \
+        AssertRCReturn(rc, rc);                                             \
+        rc = SSMR3Skip(pSSM, sizeof(uint32_t));        /* End marker */     \
+        AssertRCReturn(rc, rc);                                             \
+    }
 
     /*
      * Load BDLEs (Buffer Descriptor List Entries) and DMA counters.
@@ -3877,38 +4964,39 @@ static DECLCALLBACK(int) hdaLoadExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32
             /* Note 2: The stream's saving order is/was fixed, so don't touch! */
 
             /* Output */
-            rc = hdaStreamInit(pThis, &pThis->StrmStOut,    4 /* Stream number, hardcoded */);
+            rc = hdaStreamInit(pThis, &pThis->Out,    4 /* Stream number, hardcoded */);
             if (RT_FAILURE(rc))
                 break;
-            HDA_SSM_LOAD_BDLE_STATE_PRE_V5(uVersion, pThis->StrmStOut.State.BDLE);
-            pThis->StrmStOut.State.uCurBDLE = pThis->StrmStOut.State.BDLE.State.u32BDLIndex;
+            HDA_SSM_LOAD_BDLE_STATE_PRE_V5(uVersion, pThis->Out.State.BDLE);
+            pThis->Out.State.uCurBDLE = pThis->Out.State.BDLE.State.u32BDLIndex;
 
             /* Microphone-In */
-            rc = hdaStreamInit(pThis, &pThis->StrmStMicIn,  2 /* Stream number, hardcoded */);
+            rc = hdaStreamInit(pThis, &pThis->MicIn,  2 /* Stream number, hardcoded */);
             if (RT_FAILURE(rc))
                 break;
-            HDA_SSM_LOAD_BDLE_STATE_PRE_V5(uVersion, pThis->StrmStMicIn.State.BDLE);
-            pThis->StrmStMicIn.State.uCurBDLE = pThis->StrmStMicIn.State.BDLE.State.u32BDLIndex;
+            HDA_SSM_LOAD_BDLE_STATE_PRE_V5(uVersion, pThis->MicIn.State.BDLE);
+            pThis->MicIn.State.uCurBDLE = pThis->MicIn.State.BDLE.State.u32BDLIndex;
 
             /* Line-In */
-            rc = hdaStreamInit(pThis, &pThis->StrmStLineIn, 0 /* Stream number, hardcoded */);
+            rc = hdaStreamInit(pThis, &pThis->LineIn, 0 /* Stream number, hardcoded */);
             if (RT_FAILURE(rc))
                 break;
-            HDA_SSM_LOAD_BDLE_STATE_PRE_V5(uVersion, pThis->StrmStLineIn.State.BDLE);
-            pThis->StrmStLineIn.State.uCurBDLE = pThis->StrmStLineIn.State.BDLE.State.u32BDLIndex;
+            HDA_SSM_LOAD_BDLE_STATE_PRE_V5(uVersion, pThis->LineIn.State.BDLE);
+            pThis->LineIn.State.uCurBDLE = pThis->LineIn.State.BDLE.State.u32BDLIndex;
             break;
         }
 
-        /* Since v5 we support flexible stream and BDLE counts. */
-        case HDA_SSM_VERSION_5:
-        case HDA_SSM_VERSION:
+#undef HDA_SSM_LOAD_BDLE_STATE_PRE_V5
+
+        default: /* Since v5 we support flexible stream and BDLE counts. */
         {
             uint32_t cStreams;
             rc = SSMR3GetU32(pSSM, &cStreams);
             if (RT_FAILURE(rc))
                 break;
 
-            LogRel2(("hdaLoadExec: cStreams=%RU32\n", cStreams));
+            if (cStreams > 8)
+                cStreams = 8; /* Sanity. */
 
             /* Load stream states. */
             for (uint32_t i = 0; i < cStreams; i++)
@@ -3927,8 +5015,6 @@ static DECLCALLBACK(int) hdaLoadExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32
                     LogRel2(("HDA: Warning: Stream ID=%RU32 not supported, skipping to load ...\n", uStreamID));
                 }
 
-                RT_BZERO(pStrm, sizeof(HDASTREAM));
-
                 rc = hdaStreamInit(pThis, pStrm, uStreamID);
                 if (RT_FAILURE(rc))
                 {
@@ -3936,12 +5022,16 @@ static DECLCALLBACK(int) hdaLoadExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32
                     break;
                 }
 
+                /*
+                 * Load BDLEs (Buffer Descriptor List Entries) and DMA counters.
+                 */
+
                 if (uVersion == HDA_SSM_VERSION_5)
                 {
                     /* Get the current BDLE entry and skip the rest. */
                     uint16_t cBDLE;
 
-                    rc = SSMR3Skip(pSSM, sizeof(uint32_t)); /* Begin marker */
+                    rc = SSMR3Skip(pSSM, sizeof(uint32_t));         /* Begin marker */
                     AssertRC(rc);
                     rc = SSMR3GetU16(pSSM, &cBDLE);                 /* cBDLE */
                     AssertRC(rc);
@@ -3953,9 +5043,9 @@ static DECLCALLBACK(int) hdaLoadExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32
                     uint32_t u32BDLEIndex;
                     for (uint16_t a = 0; a < cBDLE; a++)
                     {
-                        rc = SSMR3Skip(pSSM, sizeof(uint32_t)); /* Begin marker */
+                        rc = SSMR3Skip(pSSM, sizeof(uint32_t));     /* Begin marker */
                         AssertRC(rc);
-                        rc = SSMR3GetU32(pSSM, &u32BDLEIndex);  /* u32BDLIndex */
+                        rc = SSMR3GetU32(pSSM, &u32BDLEIndex);      /* u32BDLIndex */
                         AssertRC(rc);
 
                         /* Does the current BDLE index match the current BDLE to process? */
@@ -3963,9 +5053,7 @@ static DECLCALLBACK(int) hdaLoadExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32
                         {
                             rc = SSMR3GetU32(pSSM, &pStrm->State.BDLE.State.cbBelowFIFOW); /* cbBelowFIFOW */
                             AssertRC(rc);
-                            rc = SSMR3GetMem(pSSM,
-                                             &pStrm->State.BDLE.State.au8FIFO,
-                                             sizeof(pStrm->State.BDLE.State.au8FIFO));     /* au8FIFO */
+                            rc = SSMR3Skip(pSSM, sizeof(uint8_t) * 256);                   /* FIFO, deprecated */
                             AssertRC(rc);
                             rc = SSMR3GetU32(pSSM, &pStrm->State.BDLE.State.u32BufOff);    /* u32BufOff */
                             AssertRC(rc);
@@ -3989,72 +5077,251 @@ static DECLCALLBACK(int) hdaLoadExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32
                     if (RT_FAILURE(rc))
                         break;
 
-                    rc = SSMR3GetStructEx(pSSM, &pStrm->State.BDLE, sizeof(HDABDLE),
-                                          0 /* fFlags */, g_aSSMBDLEFields6, NULL);
-                    if (RT_FAILURE(rc))
-                        break;
+                    /* Get HDABDLEDESC. */
+                    uint32_t uMarker;
+                    rc = SSMR3GetU32(pSSM, &uMarker);      /* Begin marker. */
+                    AssertRC(rc);
+                    Assert(uMarker == UINT32_C(0x19200102) /* SSMR3STRUCT_BEGIN */);
+                    rc = SSMR3GetU64(pSSM, &pStrm->State.BDLE.Desc.u64BufAdr);
+                    AssertRC(rc);
+                    rc = SSMR3GetU32(pSSM, &pStrm->State.BDLE.Desc.u32BufSize);
+                    AssertRC(rc);
+                    bool fFlags = false;
+                    rc = SSMR3GetBool(pSSM, &fFlags);      /* Saved states < v7 only stored the IOC as boolean flag. */
+                    AssertRC(rc);
+                    pStrm->State.BDLE.Desc.fFlags = fFlags ? HDA_BDLE_FLAG_IOC : 0;
+                    rc = SSMR3GetU32(pSSM, &uMarker);      /* End marker. */
+                    AssertRC(rc);
+                    Assert(uMarker == UINT32_C(0x19920406) /* SSMR3STRUCT_END */);
 
                     rc = SSMR3GetStructEx(pSSM, &pStrm->State.BDLE.State, sizeof(HDABDLESTATE),
                                           0 /* fFlags */, g_aSSMBDLEStateFields6, NULL);
                     if (RT_FAILURE(rc))
                         break;
+
+                    Log2Func(("[SD%RU8] LPIB=%RU32, CBL=%RU32, LVI=%RU32\n",
+                              uStreamID,
+                              HDA_STREAM_REG(pThis, LPIB, uStreamID), HDA_STREAM_REG(pThis, CBL, uStreamID), HDA_STREAM_REG(pThis, LVI, uStreamID)));
+#ifdef LOG_ENABLED
+                    hdaBDLEDumpAll(pThis, pStrm->u64BDLBase, pStrm->u16LVI + 1);
+#endif
                 }
-            }
+
+                rc = hdaSDFMTToStrmCfg(HDA_STREAM_REG(pThis, FMT, uStreamID), &pStrm->State.strmCfg);
+                if (RT_FAILURE(rc))
+                {
+                    LogRel(("HDA: Stream #%RU8: Loading format failed, rc=%Rrc\n", uStreamID, rc));
+                    /* Continue. */
+                }
+
+            } /* for cStreams */
             break;
-        }
+        } /* default */
+    }
 
-        default:
-            AssertReleaseFailed(); /* Never reached. */
-            return VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION;
+    return rc;
+}
+
+/**
+ * @callback_method_impl{FNSSMDEVLOADEXEC}
+ */
+static DECLCALLBACK(int) hdaLoadExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass)
+{
+    PHDASTATE pThis = PDMINS_2_DATA(pDevIns, PHDASTATE);
+
+    Assert(uPass == SSM_PASS_FINAL); NOREF(uPass);
+
+    LogRel2(("hdaLoadExec: uVersion=%RU32, uPass=0x%x\n", uVersion, uPass));
+
+    /*
+     * Load Codec nodes states.
+     */
+    int rc = hdaCodecLoadState(pThis->pCodec, pSSM, uVersion);
+    if (RT_FAILURE(rc))
+    {
+        LogRel(("HDA: Failed loading codec state (version %RU32, pass 0x%x), rc=%Rrc\n", uVersion, uPass, rc));
+        return rc;
     }
 
-#undef HDA_SSM_LOAD_BDLE_STATE_PRE_V5
+    if (uVersion < HDA_SSM_VERSION) /* Handle older saved states? */
+    {
+        rc = hdaLoadExecLegacy(pThis, pSSM, uVersion, uPass);
+        if (RT_SUCCESS(rc))
+            rc = hdaLoadExecPost(pThis);
 
-    if (RT_SUCCESS(rc))
+        return rc;
+    }
+
+    /*
+     * Load MMIO registers.
+     */
+    uint32_t cRegs;
+    rc = SSMR3GetU32(pSSM, &cRegs); AssertRCReturn(rc, rc);
+    if (cRegs != RT_ELEMENTS(pThis->au32Regs))
+        LogRel(("HDA: SSM version cRegs is %RU32, expected %RU32\n", cRegs, RT_ELEMENTS(pThis->au32Regs)));
+
+    if (cRegs >= RT_ELEMENTS(pThis->au32Regs))
+    {
+        SSMR3GetMem(pSSM, pThis->au32Regs, sizeof(pThis->au32Regs));
+        SSMR3Skip(pSSM, sizeof(uint32_t) * (cRegs - RT_ELEMENTS(pThis->au32Regs)));
+    }
+    else
+        SSMR3GetMem(pSSM, pThis->au32Regs, sizeof(uint32_t) * cRegs);
+
+    /* Make sure to update the base addresses first before initializing any streams down below. */
+    pThis->u64CORBBase  = RT_MAKE_U64(HDA_REG(pThis, CORBLBASE), HDA_REG(pThis, CORBUBASE));
+    pThis->u64RIRBBase  = RT_MAKE_U64(HDA_REG(pThis, RIRBLBASE), HDA_REG(pThis, RIRBUBASE));
+    pThis->u64DPBase    = RT_MAKE_U64(HDA_REG(pThis, DPLBASE) & DPBASE_ADDR_MASK, HDA_REG(pThis, DPUBASE));
+
+    /* Also make sure to update the DMA position bit if this was enabled when saving the state. */
+    pThis->fDMAPosition = RT_BOOL(HDA_REG(pThis, DPLBASE) & RT_BIT_32(0));
+
+    /*
+     * Load controller-specifc internals.
+     */
+    if (SSMR3HandleRevision(pSSM) >= 116273) /* Don't annoy other team mates (forgot this for state v7). */
+    {
+        rc = SSMR3GetU64(pSSM, &pThis->u64WalClk);
+        AssertRC(rc);
+
+        rc = SSMR3GetU8(pSSM, &pThis->u8IRQL);
+        AssertRC(rc);
+    }
+
+    /*
+     * Load streams.
+     */
+    uint32_t cStreams;
+    rc = SSMR3GetU32(pSSM, &cStreams);
+    AssertRC(rc);
+
+    if (cStreams > 8)
+        cStreams = 8; /* Sanity. */
+
+    Log2Func(("cStreams=%RU32\n", cStreams));
+
+    /* Load stream states. */
+    for (uint32_t i = 0; i < cStreams; i++)
     {
+        uint8_t uStreamID;
+        rc = SSMR3GetU8(pSSM, &uStreamID);
+        AssertRC(rc);
+
+        PHDASTREAM pStrm = hdaStreamFromID(pThis, uStreamID);
+        HDASTREAM  StreamDummy;
+
+        if (!pStrm)
+        {
+            pStrm = &StreamDummy;
+            LogRel2(("HDA: Warning: Loading of stream #%RU8 not supported, skipping to load ...\n", uStreamID));
+        }
+
+        rc = hdaStreamInit(pThis, pStrm, uStreamID);
+        if (RT_FAILURE(rc))
+        {
+            LogRel(("HDA: Stream #%RU8: Loading initialization failed, rc=%Rrc\n", uStreamID, rc));
+            /* Continue. */
+        }
+
         /*
-         * Update stuff after the state changes.
+         * Load BDLEs (Buffer Descriptor List Entries) and DMA counters.
          */
-        bool fEnableIn    = RT_BOOL(HDA_SDCTL(pThis, 0 /** @todo Use a define. */) & HDA_REG_FIELD_FLAG_MASK(SDCTL, RUN));
-#ifdef VBOX_WITH_HDA_MIC_IN
-        bool fEnableMicIn = RT_BOOL(HDA_SDCTL(pThis, 2 /** @todo Use a define. */) & HDA_REG_FIELD_FLAG_MASK(SDCTL, RUN));
-#endif
-        bool fEnableOut   = RT_BOOL(HDA_SDCTL(pThis, 4 /** @todo Use a define. */) & HDA_REG_FIELD_FLAG_MASK(SDCTL, RUN));
+        rc = SSMR3GetStructEx(pSSM, &pStrm->State, sizeof(HDASTREAMSTATE),
+                              0 /* fFlags */, g_aSSMStreamStateFields7,
+                              NULL);
+        AssertRC(rc);
 
-        PHDADRIVER pDrv;
-        RTListForEach(&pThis->lstDrv, pDrv, HDADRIVER, Node)
+        rc = SSMR3GetStructEx(pSSM, &pStrm->State.BDLE.Desc, sizeof(HDABDLEDESC),
+                              0 /* fFlags */, g_aSSMBDLEDescFields7, NULL);
+        AssertRC(rc);
+
+        rc = SSMR3GetStructEx(pSSM, &pStrm->State.BDLE.State, sizeof(HDABDLESTATE),
+                              0 /* fFlags */, g_aSSMBDLEStateFields7, NULL);
+        AssertRC(rc);
+
+        /*
+         * Load period state.
+         */
+        hdaStreamPeriodInit(&pStrm->State.Period,
+                            pStrm->u8SD, pStrm->u16LVI, pStrm->u32CBL, &pStrm->State.strmCfg);
+
+        if (SSMR3HandleRevision(pSSM) >= 116273) /* Don't annoy other team mates (forgot this for state v7). */
         {
-            rc = pDrv->pConnector->pfnEnableIn(pDrv->pConnector, pDrv->LineIn.pStrmIn, fEnableIn);
-            if (RT_FAILURE(rc))
-                break;
-#ifdef VBOX_WITH_HDA_MIC_IN
-            rc = pDrv->pConnector->pfnEnableIn(pDrv->pConnector, pDrv->MicIn.pStrmIn, fEnableMicIn);
-            if (RT_FAILURE(rc))
-                break;
-#endif
-            rc = pDrv->pConnector->pfnEnableOut(pDrv->pConnector, pDrv->Out.pStrmOut, fEnableOut);
-            if (RT_FAILURE(rc))
-                break;
+            rc = SSMR3GetStructEx(pSSM, &pStrm->State.Period, sizeof(HDASTREAMPERIOD),
+                                  0 /* fFlags */, g_aSSMStreamPeriodFields7, NULL);
+            AssertRC(rc);
         }
-    }
 
-    if (RT_SUCCESS(rc))
-    {
-        pThis->u64CORBBase  = RT_MAKE_U64(HDA_REG(pThis, CORBLBASE), HDA_REG(pThis, CORBUBASE));
-        pThis->u64RIRBBase  = RT_MAKE_U64(HDA_REG(pThis, RIRBLBASE), HDA_REG(pThis, RIRBUBASE));
-        pThis->u64DPBase    = RT_MAKE_U64(HDA_REG(pThis, DPLBASE),   HDA_REG(pThis, DPUBASE));
+        /*
+         * Load internal (FIFO) buffer.
+         */
 
-        /* Also make sure to update the DMA position bit if this was enabled when saving the state. */
-        pThis->fDMAPosition = RT_BOOL(HDA_REG(pThis, DPLBASE) & RT_BIT_32(0));
-    }
-    else
-        LogRel(("HDA: Failed loading device state (version %RU32, pass 0x%x), rc=%Rrc\n", uVersion, uPass, rc));
+        uint32_t cbCircBufSize = 0;
+        rc = SSMR3GetU32(pSSM, &cbCircBufSize); /* cbCircBuf */
+        AssertRC(rc);
+
+        uint32_t cbCircBufUsed = 0;
+        rc = SSMR3GetU32(pSSM, &cbCircBufUsed); /* cbCircBuf */
+        AssertRC(rc);
+
+        if (cbCircBufSize) /* If 0, skip the buffer. */
+        {
+            /* Paranoia. */
+            AssertReleaseMsg(cbCircBufSize <= _1M,
+                             ("HDA: Saved state contains bogus DMA buffer size (%RU32) for stream #%RU8",
+                              cbCircBufSize, uStreamID));
+            AssertReleaseMsg(cbCircBufUsed <= cbCircBufSize,
+                             ("HDA: Saved state contains invalid DMA buffer usage (%RU32/%RU32) for stream #%RU8",
+                              cbCircBufUsed, cbCircBufSize, uStreamID));
+            AssertPtr(pStrm->State.pCircBuf);
+
+            /* Do we need to cre-create the circular buffer do fit the data size? */
+            if (cbCircBufSize != (uint32_t)RTCircBufSize(pStrm->State.pCircBuf))
+            {
+                RTCircBufDestroy(pStrm->State.pCircBuf);
+                pStrm->State.pCircBuf = NULL;
+
+                rc = RTCircBufCreate(&pStrm->State.pCircBuf, cbCircBufSize);
+                AssertRC(rc);
+            }
+
+            if (   RT_SUCCESS(rc)
+                && cbCircBufUsed)
+            {
+                void  *pvBuf;
+                size_t cbBuf;
+
+                RTCircBufAcquireWriteBlock(pStrm->State.pCircBuf, cbCircBufUsed, &pvBuf, &cbBuf);
+
+                if (cbBuf)
+                {
+                    rc = SSMR3GetMem(pSSM, pvBuf, cbBuf);
+                    AssertRC(rc);
+                }
+
+                RTCircBufReleaseWriteBlock(pStrm->State.pCircBuf, cbBuf);
+
+                Assert(cbBuf == cbCircBufUsed);
+            }
+        }
+
+        Log2Func(("[SD%RU8] LPIB=%RU32, CBL=%RU32, LVI=%RU32\n",
+                  uStreamID,
+                  HDA_STREAM_REG(pThis, LPIB, uStreamID), HDA_STREAM_REG(pThis, CBL, uStreamID), HDA_STREAM_REG(pThis, LVI, uStreamID)));
+#ifdef LOG_ENABLED
+        hdaBDLEDumpAll(pThis, pStrm->u64BDLBase, pStrm->u16LVI + 1);
+#endif
+        /** @todo (Re-)initialize active periods? */
+
+    } /* for cStreams */
+
+    rc = hdaLoadExecPost(pThis);
+    AssertRC(rc);
 
     LogFlowFuncLeaveRC(rc);
     return rc;
 }
 
-#ifdef DEBUG
 /* Debug and log type formatters. */
 
 /**
@@ -4068,8 +5335,9 @@ static DECLCALLBACK(size_t) hdaDbgFmtBDLE(PFNRTSTROUTPUT pfnOutput, void *pvArgO
     RT_NOREF(pszType, cchWidth, cchPrecision, fFlags, pvUser);
     PHDABDLE pBDLE = (PHDABDLE)pvValue;
     return RTStrFormat(pfnOutput,  pvArgOutput, NULL, 0,
-                       "BDLE(idx:%RU32, off:%RU32, fifow:%RU32, DMA[%RU32 bytes @ 0x%x])",
-                       pBDLE->State.u32BDLIndex, pBDLE->State.u32BufOff, pBDLE->State.cbBelowFIFOW, pBDLE->u32BufSize, pBDLE->u64BufAdr);
+                       "BDLE(idx:%RU32, off:%RU32, fifow:%RU32, DMA[%RU32 bytes @ 0x%x], fFlags=0x%x)",
+                       pBDLE->State.u32BDLIndex, pBDLE->State.u32BufOff, pBDLE->State.cbBelowFIFOW,
+                       pBDLE->Desc.u32BufSize, pBDLE->Desc.u64BufAdr, pBDLE->Desc.fFlags);
 }
 
 /**
@@ -4177,9 +5445,9 @@ static void hdaDbgPrintStream(PHDASTATE pThis, PCDBGFINFOHLP pHlp, int iHdaStrmI
     Assert(   pThis
            && iHdaStrmIndex >= 0
            && iHdaStrmIndex < 7);
-    pHlp->pfnPrintf(pHlp, "Dump of %d HDA Stream:\n", iHdaStrmIndex);
-    pHlp->pfnPrintf(pHlp, "SD%dCTL: %R[sdctl]\n", iHdaStrmIndex, HDA_STREAM_REG(pThis, CTL, iHdaStrmIndex));
-    pHlp->pfnPrintf(pHlp, "SD%dCTS: %R[sdsts]\n", iHdaStrmIndex, HDA_STREAM_REG(pThis, STS, iHdaStrmIndex));
+    pHlp->pfnPrintf(pHlp, "Dump of stream #%02d:\n", iHdaStrmIndex);
+    pHlp->pfnPrintf(pHlp, "SD%dCTL: %R[sdctl]\n",     iHdaStrmIndex, HDA_STREAM_REG(pThis, CTL, iHdaStrmIndex));
+    pHlp->pfnPrintf(pHlp, "SD%dCTS: %R[sdsts]\n",     iHdaStrmIndex, HDA_STREAM_REG(pThis, STS, iHdaStrmIndex));
     pHlp->pfnPrintf(pHlp, "SD%dFIFOS: %R[sdfifos]\n", iHdaStrmIndex, HDA_STREAM_REG(pThis, FIFOS, iHdaStrmIndex));
     pHlp->pfnPrintf(pHlp, "SD%dFIFOW: %R[sdfifow]\n", iHdaStrmIndex, HDA_STREAM_REG(pThis, FIFOW, iHdaStrmIndex));
 }
@@ -4201,7 +5469,7 @@ static DECLCALLBACK(void) hdaInfoStream(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp,
     if (iHdaStrmIndex != -1)
         hdaDbgPrintStream(pThis, pHlp, iHdaStrmIndex);
     else
-        for(iHdaStrmIndex = 0; iHdaStrmIndex < 7; ++iHdaStrmIndex)
+        for(iHdaStrmIndex = 0; iHdaStrmIndex < 8; ++iHdaStrmIndex)
             hdaDbgPrintStream(pThis, pHlp, iHdaStrmIndex);
 }
 
@@ -4243,7 +5511,7 @@ static DECLCALLBACK(void) hdaInfoMixer(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, c
     else
         pHlp->pfnPrintf(pHlp, "Mixer not available\n");
 }
-#endif /* DEBUG */
+
 
 /* PDMIBASE */
 
@@ -4292,7 +5560,8 @@ static DECLCALLBACK(void) hdaReset(PPDMDEVINS pDevIns)
      * Stop the timer, if any.
      */
     int rc2;
-    if (pThis->pTimer)
+    if (   pThis->pTimer
+        && TMTimerIsActive(pThis->pTimer))
     {
         rc2 = TMTimerStop(pThis->pTimer);
         AssertRC(rc2);
@@ -4328,44 +5597,32 @@ static DECLCALLBACK(void) hdaReset(PPDMDEVINS pDevIns)
     else
         pThis->pu64RirbBuf = (uint64_t *)RTMemAllocZ(pThis->cbRirbBuf);
 
-    pThis->u64BaseTS = PDMDevHlpTMTimeVirtGetNano(pDevIns);
+    hdaWalClkSet(pThis, 0 /* Always start at 0 */, true /* fForce */);
 
-    for (uint8_t u8Strm = 0; u8Strm < 8; u8Strm++) /** @todo Use a define here. */
+    for (uint8_t uSD = 0; uSD < 8; uSD++) /** @todo Use a define here. */
     {
-        PHDASTREAM pStrmSt = NULL;
-        if (u8Strm == 0)      /** @todo Implement dynamic stream IDs. */
-            pStrmSt = &pThis->StrmStLineIn;
+        PHDASTREAM pStream = NULL;
+        if (uSD == 0)      /** @todo Implement dynamic stream IDs. */
+            pStream = &pThis->LineIn;
 # ifdef VBOX_WITH_HDA_MIC_IN
-        else if (u8Strm == 2) /** @todo Implement dynamic stream IDs. */
-            pStrmSt = &pThis->StrmStMicIn;
+        else if (uSD == 2) /** @todo Implement dynamic stream IDs. */
+            pStream = &pThis->MicIn;
 # endif
-        else if (u8Strm == 4) /** @todo Implement dynamic stream IDs. */
-            pStrmSt = &pThis->StrmStOut;
+        else if (uSD == 4) /** @todo Implement dynamic stream IDs. */
+            pStream = &pThis->Out;
 
-        if (pStrmSt)
+        if (pStream)
         {
             /* Remove the RUN bit from SDnCTL in case the stream was in a running state before. */
-            HDA_STREAM_REG(pThis, CTL, u8Strm) &= ~HDA_REG_FIELD_FLAG_MASK(SDCTL, RUN);
+            HDA_STREAM_REG(pThis, CTL, uSD) &= ~HDA_REG_FIELD_FLAG_MASK(SDCTL, RUN);
 
-            hdaStreamReset(pThis, pStrmSt, u8Strm);
+            hdaStreamReset(pThis, pStream, uSD);
         }
     }
 
     /* Emulation of codec "wake up" (HDA spec 5.5.1 and 6.5). */
     HDA_REG(pThis, STATESTS) = 0x1;
 
-# ifndef VBOX_WITH_AUDIO_CALLBACKS
-    /*
-     * Start timer again, if any.
-     */
-    if (pThis->pTimer)
-    {
-        LogFunc(("Restarting timer\n"));
-        rc2 = TMTimerSet(pThis->pTimer, TMTimerGet(pThis->pTimer) + pThis->cTimerTicks);
-        AssertRC(rc2);
-    }
-# endif
-
     LogRel(("HDA: Reset\n"));
 }
 
@@ -4407,15 +5664,29 @@ static DECLCALLBACK(int) hdaDestruct(PPDMDEVINS pDevIns)
     RTMemFree(pThis->pu64RirbBuf);
     pThis->pu64RirbBuf = NULL;
 
-    hdaStreamDestroy(&pThis->StrmStLineIn);
-    hdaStreamDestroy(&pThis->StrmStMicIn);
-    hdaStreamDestroy(&pThis->StrmStOut);
+    hdaStreamDestroy(&pThis->LineIn);
+#ifdef VBOX_WITH_HDA_MIC_IN
+    hdaStreamDestroy(&pThis->MicIn);
+#endif
+    hdaStreamDestroy(&pThis->Out);
 
     return VINF_SUCCESS;
 }
 
 
 /**
+ * @interface_method_impl{PDMDEVREG,pfnPowerOff}
+ */
+static DECLCALLBACK(void) hdaPowerOff(PPDMDEVINS pDevIns)
+{
+    PHDASTATE pThis = PDMINS_2_DATA(pDevIns, PHDASTATE);
+
+    hdaCloseIn (pThis, PDMAUDIORECSOURCE_LINE_IN);
+    hdaCloseOut(pThis);
+}
+
+
+/**
  * Attach command, internal version.
  *
  * This is called to let the device attach to a driver for a specified LUN
@@ -4438,11 +5709,9 @@ static int hdaAttachInternal(PPDMDEVINS pDevIns, PHDADRIVER pDrv, unsigned uLUN,
     /*
      * Attach driver.
      */
-    char *pszDesc = NULL;
+    char *pszDesc;
     if (RTStrAPrintf(&pszDesc, "Audio driver port (HDA) for LUN#%u", uLUN) <= 0)
-        AssertReleaseMsgReturn(pszDesc,
-                               ("Not enough memory for HDA driver port description of LUN #%u\n", uLUN),
-                               VERR_NO_MEMORY);
+        AssertLogRelFailedReturn(VERR_NO_MEMORY);
 
     PPDMIBASE pDrvBase;
     int rc = PDMDevHlpDriverAttach(pDevIns, uLUN,
@@ -4464,9 +5733,9 @@ static int hdaAttachInternal(PPDMDEVINS pDevIns, PHDADRIVER pDrv, unsigned uLUN,
              * host backend. This might change in the future.
              */
             if (pDrv->uLUN == 0)
-                pDrv->Flags |= PDMAUDIODRVFLAG_PRIMARY;
+                pDrv->fFlags |= PDMAUDIODRVFLAG_PRIMARY;
 
-            LogFunc(("LUN#%u: pCon=%p, drvFlags=0x%x\n", uLUN, pDrv->pConnector, pDrv->Flags));
+            LogFunc(("LUN#%u: pCon=%p, drvFlags=0x%x\n", uLUN, pDrv->pConnector, pDrv->fFlags));
 
             /* Attach to driver list if not attached yet. */
             if (!pDrv->fAttached)
@@ -4516,10 +5785,10 @@ static DECLCALLBACK(void) hdaDetach(PPDMDEVINS pDevIns, unsigned uLUN, uint32_t
 }
 
 /**
- * Re-attach.
+ * Re-attaches a new driver to the device's driver chain.
  *
  * @returns VBox status code.
- * @param   pThis       Device instance.
+ * @param   pThis       Device instance to re-attach driver to.
  * @param   pDrv        Driver instance used for attaching to.
  *                      If NULL is specified, a new driver will be created and appended
  *                      to the driver list.
@@ -4604,7 +5873,7 @@ static DECLCALLBACK(int) hdaConstruct(PPDMDEVINS pDevIns, int iInstance, PCFGMNO
                                 N_("HDA configuration error: failed to read R0Enabled as boolean"));
 #ifndef VBOX_WITH_AUDIO_CALLBACKS
     uint16_t uTimerHz;
-    rc = CFGMR3QueryU16Def(pCfg, "TimerHz", &uTimerHz, 200 /* Hz */);
+    rc = CFGMR3QueryU16Def(pCfg, "TimerHz", &uTimerHz, HDA_TIMER_HZ);
     if (RT_FAILURE(rc))
         return PDMDEV_SET_ERROR(pDevIns, rc,
                                 N_("HDA configuration error: failed to read Hertz (Hz) rate as unsigned integer"));
@@ -4818,13 +6087,13 @@ static DECLCALLBACK(int) hdaConstruct(PPDMDEVINS pDevIns, int iInstance, PCFGMNO
 
     if (RT_SUCCESS(rc))
     {
-        rc = hdaStreamCreate(&pThis->StrmStLineIn);
+        rc = hdaStreamCreate(&pThis->LineIn);
         AssertRC(rc);
 #ifdef VBOX_WITH_HDA_MIC_IN
-        rc = hdaStreamCreate(&pThis->StrmStMicIn);
+        rc = hdaStreamCreate(&pThis->MicIn);
         AssertRC(rc);
 #endif
-        rc = hdaStreamCreate(&pThis->StrmStOut);
+        rc = hdaStreamCreate(&pThis->Out);
         AssertRC(rc);
 
         PHDADRIVER pDrv;
@@ -4834,7 +6103,7 @@ static DECLCALLBACK(int) hdaConstruct(PPDMDEVINS pDevIns, int iInstance, PCFGMNO
              * Only primary drivers are critical for the VM to run. Everything else
              * might not worth showing an own error message box in the GUI.
              */
-            if (!(pDrv->Flags & PDMAUDIODRVFLAG_PRIMARY))
+            if (!(pDrv->fFlags & PDMAUDIODRVFLAG_PRIMARY))
                 continue;
 
             PPDMIAUDIOCONNECTOR pCon = pDrv->pConnector;
@@ -4943,12 +6212,11 @@ static DECLCALLBACK(int) hdaConstruct(PPDMDEVINS pDevIns, int iInstance, PCFGMNO
         HDA_REG(pThis, WAKEEN)   = 0x0;
         HDA_REG(pThis, STATESTS) = 0x0;
 
-#ifdef DEBUG
         /*
          * Debug and string formatter types.
          */
         PDMDevHlpDBGFInfoRegister(pDevIns, "hda",         "HDA info. (hda [register case-insensitive])",    hdaInfo);
-        PDMDevHlpDBGFInfoRegister(pDevIns, "hdastrm",     "HDA stream info. (hdastrm [stream number])",     hdaInfoStream);
+        PDMDevHlpDBGFInfoRegister(pDevIns, "hdastream",   "HDA stream info. (hdastream [stream number])",   hdaInfoStream);
         PDMDevHlpDBGFInfoRegister(pDevIns, "hdcnodes",    "HDA codec nodes.",                               hdaInfoCodecNodes);
         PDMDevHlpDBGFInfoRegister(pDevIns, "hdcselector", "HDA codec's selector states [node number].",     hdaInfoCodecSelector);
         PDMDevHlpDBGFInfoRegister(pDevIns, "hdamixer",    "HDA mixer state.",                               hdaInfoMixer);
@@ -4963,7 +6231,6 @@ static DECLCALLBACK(int) hdaConstruct(PPDMDEVINS pDevIns, int iInstance, PCFGMNO
         AssertRC(rc);
         rc = RTStrFormatTypeRegister("sdfifow", hdaDbgFmtSDFIFOW, NULL);
         AssertRC(rc);
-#endif /* DEBUG */
 
         /*
          * Some debug assertions.
@@ -5015,19 +6282,20 @@ static DECLCALLBACK(int) hdaConstruct(PPDMDEVINS pDevIns, int iInstance, PCFGMNO
 # ifndef VBOX_WITH_AUDIO_CALLBACKS
     if (RT_SUCCESS(rc))
     {
-        /* Start the emulation timer. */
-        rc = PDMDevHlpTMTimerCreate(pDevIns, TMCLOCK_VIRTUAL, hdaTimer, pThis,
+        /* Create the emulation timer.
+         *
+         * Note:  Use TMCLOCK_VIRTUAL_SYNC here, as the guest's HDA driver
+         *        relies on exact (virtual) DMA timing and uses DMA Position Buffers
+         *        instead of the LPIB registers.
+         */
+        rc = PDMDevHlpTMTimerCreate(pDevIns, TMCLOCK_VIRTUAL_SYNC, hdaTimer, pThis,
                                     TMTIMER_FLAGS_NO_CRIT_SECT, "DevIchHda", &pThis->pTimer);
         AssertRCReturn(rc, rc);
 
         if (RT_SUCCESS(rc))
         {
             pThis->cTimerTicks = TMTimerGetFreq(pThis->pTimer) / uTimerHz;
-            pThis->uTimerTS    = TMTimerGet(pThis->pTimer);
             LogFunc(("Timer ticks=%RU64 (%RU16 Hz)\n", pThis->cTimerTicks, uTimerHz));
-
-            /* Fire off timer. */
-            TMTimerSet(pThis->pTimer, TMTimerGet(pThis->pTimer) + pThis->cTimerTicks);
         }
     }
 # else
@@ -5038,7 +6306,7 @@ static DECLCALLBACK(int) hdaConstruct(PPDMDEVINS pDevIns, int iInstance, PCFGMNO
         {
             /* Only register primary driver.
              * The device emulation does the output multiplexing then. */
-            if (pDrv->Flags != PDMAUDIODRVFLAG_PRIMARY)
+            if (pDrv->fFlags != PDMAUDIODRVFLAG_PRIMARY)
                 continue;
 
             PDMAUDIOCALLBACK AudioCallbacks[2];
@@ -5076,6 +6344,15 @@ static DECLCALLBACK(int) hdaConstruct(PPDMDEVINS pDevIns, int iInstance, PCFGMNO
     }
 # endif
 
+#ifdef VBOX_AUDIO_DEBUG_DUMP_PCM_DATA
+    RTFileDelete(VBOX_AUDIO_DEBUG_DUMP_PCM_DATA_PATH "hdaDMAAccessRead.pcm");
+    RTFileDelete(VBOX_AUDIO_DEBUG_DUMP_PCM_DATA_PATH "hdaDMAAccessWrite.pcm");
+    RTFileDelete(VBOX_AUDIO_DEBUG_DUMP_PCM_DATA_PATH "hdaDMARead.pcm");
+    RTFileDelete(VBOX_AUDIO_DEBUG_DUMP_PCM_DATA_PATH "hdaDMAWrite.pcm");
+    RTFileDelete(VBOX_AUDIO_DEBUG_DUMP_PCM_DATA_PATH "hdaReadAudio.pcm");
+    RTFileDelete(VBOX_AUDIO_DEBUG_DUMP_PCM_DATA_PATH "hdaWriteAudio.pcm");
+#endif
+
     LogFlowFuncLeaveRC(rc);
     return rc;
 }
@@ -5128,7 +6405,7 @@ const PDMDEVREG g_DeviceICH6_HDA =
     /* pfnInitComplete */
     NULL,
     /* pfnPowerOff */
-    NULL,
+    hdaPowerOff,
     /* pfnSoftReset */
     NULL,
     /* u32VersionEnd */
diff --git a/src/VBox/Devices/Audio/DevHDA.h b/src/VBox/Devices/Audio/DevHDA.h
new file mode 100644
index 0000000..ff98461
--- /dev/null
+++ b/src/VBox/Devices/Audio/DevHDA.h
@@ -0,0 +1,176 @@
+/* $Id$ */
+/** @file
+ * DevHDA.h - Header file for VBox Intel HD Audio Controller.
+ */
+
+/*
+ * 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.
+ */
+
+#ifndef DEV_HDA_H
+#define DEV_HDA_H
+
+#include <iprt/circbuf.h>
+
+/**
+ * Internal state of a Buffer Descriptor List Entry (BDLE),
+ * needed to keep track of the data needed for the actual device
+ * emulation.
+ */
+typedef struct HDABDLESTATE
+{
+    /** Own index within the BDL (Buffer Descriptor List). */
+    uint32_t     u32BDLIndex;
+    /** Number of bytes below the stream's FIFO watermark (SDFIFOW).
+     *  Used to check if we need fill up the FIFO again. */
+    uint32_t     cbBelowFIFOW;
+    /** Current offset in BDLE buffer (in samples). */
+    uint32_t     u32BufOff;
+    uint32_t     Padding;
+} HDABDLESTATE, *PHDABDLESTATE;
+
+/**
+ * BDL description structure.
+ * Do not touch this, as this must match to the HDA specs.
+ */
+typedef struct HDABDLEDESC
+{
+    /** Starting address of the actual buffer. Must be 128-bit aligned. */
+    uint64_t     u64BufAdr;
+    /** Size of the actual buffer (in bytes). */
+    uint32_t     u32BufSize;
+    /** Bit 0: Interrupt on completion; the controller will generate
+     *  an interrupt when the last byte of the buffer has been
+     *  fetched by the DMA engine.
+     *
+     *  Rest is reserved for further use and must be 0. */
+    uint32_t     fFlags;
+} HDABDLEDESC, *PHDABDLEDESC;
+AssertCompileSize(HDABDLEDESC, 16); /* Always 16 byte. Also must be aligned on 128-byte boundary. */
+
+/**
+ * Buffer Descriptor List Entry (BDLE) (3.6.3).
+ *
+ * Contains only register values which do *not* change until a
+ * stream reset occurs.
+ */
+typedef struct HDABDLE
+{
+    /** The actual BDL description. */
+    HDABDLEDESC    Desc;
+    /** Internal state of this BDLE.
+     *  Not part of the actual BDLE registers. */
+    HDABDLESTATE   State;
+} HDABDLE, *PHDABDLE;
+
+struct HDASTREAMPERIOD;
+
+/**
+ * Internal state of a HDA stream.
+ */
+typedef struct HDASTREAMSTATE
+{
+    /** Current BDLE to use. Wraps around to 0 if
+     *  maximum (cBDLE) is reached. Zero-based. */
+    uint16_t                uCurBDLE;
+    /** Flag indicating whether this stream is in an
+     *  active (operative) state or not. */
+    volatile bool           fRunning;
+    /** Flag indicating whether this stream currently is
+     *  in reset mode and therefore not acccessible by the guest. */
+    volatile bool           fInReset;
+    /** Unused, padding. */
+    bool                    fPadding;
+    /** Current BDLE (Buffer Descriptor List Entry). */
+    HDABDLE                 BDLE;
+    /** The stream's internal FIFO buffer. */
+    R3PTRTYPE(PRTCIRCBUF)   pCircBuf;
+    /** Timestamp of the last success DMA data transfer.
+     *  Used to calculate the time actually elapsed between two transfers. */
+    uint64_t                uTimerTS;
+    /** The stream's period. Need for timing.  */
+    HDASTREAMPERIOD         Period;
+    /** The stream's current configuration.
+     *  Should match SDFMT. */
+    PDMAUDIOSTREAMCFG       strmCfg;
+# ifdef HDA_USE_DMA_ACCESS_HANDLER
+    /** List of DMA handlers. */
+    RTLISTANCHORR3          lstDMAHandlers;
+#endif
+} HDASTREAMSTATE, *PHDASTREAMSTATE;
+
+#if defined (DEBUG) || defined(HDA_USE_DMA_ACCESS_HANDLER)
+typedef struct HDASTREAMDBGINFO
+{
+    /** Critical section to serialize access if needed. */
+    RTCRITSECT              CritSect;
+    uint32_t                Padding1[2];
+    /** Number of total read accesses. */
+    uint64_t                cReadsTotal;
+    /** Number of total DMA bytes read. */
+    uint64_t                cbReadTotal;
+    /** Timestamp (in ns) of last read access. */
+    uint64_t                tsLastReadNs;
+    /** Number of total write accesses. */
+    uint64_t                cWritesTotal;
+    /** Number of total DMA bytes written. */
+    uint64_t                cbWrittenTotal;
+    /** Number of total write accesses since last iteration (Hz). */
+    uint64_t                cWritesHz;
+    /** Number of total DMA bytes written since last iteration (Hz). */
+    uint64_t                cbWrittenHz;
+    /** Timestamp (in ns) of beginning a new write slot. */
+    uint64_t                tsWriteSlotBegin;
+    /** Number of current silence samples in a (consecutive) row. */
+    uint64_t                csSilence;
+    /** Number of silent samples in a row to consider an audio block as audio gap (silence). */
+    uint64_t                cSilenceThreshold;
+    /** How many bytes to skip in an audio stream before detecting silence.
+     *  (useful for intros and silence at the beginning of a song). */
+    uint64_t                cbSilenceReadMin;
+} HDASTREAMDBGINFO ,*PHDASTREAMDBGINFO;
+#endif /* defined (DEBUG) || defined(HDA_USE_DMA_ACCESS_HANDLER) */
+
+/**
+ * Structure for keeping a HDA stream state.
+ *
+ * Contains only register values which do *not* change until a
+ * stream reset occurs.
+ */
+typedef struct HDASTREAM
+{
+    /** Stream descriptor number (SDn). */
+    uint8_t          u8SD;
+    uint8_t          Padding0[7];
+    /** DMA base address (SDnBDPU - SDnBDPL). */
+    uint64_t         u64BDLBase;
+    /** Cyclic Buffer Length (SDnCBL).
+     *  Represents the size of the complete cyclic buffer (in bytes). */
+    uint32_t         u32CBL;
+    /** FIFO Size (FIFOS).
+     *  Maximum number of bytes that may have been DMA'd into
+     *  memory but not yet transmitted on the link.
+     *
+     *  Must be a power of two. */
+    uint16_t         u16FIFOS;
+    /** Last Valid Index (SDnLVI). Zero-based. */
+    uint16_t         u16LVI;
+    uint16_t         Padding1[3];
+    /** Internal state of this stream. */
+    HDASTREAMSTATE   State;
+#ifdef DEBUG
+    /** Debug information. */
+    HDASTREAMDBGINFO Dbg;
+#endif
+} HDASTREAM, *PHDASTREAM;
+
+#endif /* !DEV_HDA_H */
+
diff --git a/src/VBox/Devices/Audio/DevIchAc97.cpp b/src/VBox/Devices/Audio/DevIchAc97.cpp
index 8b61a9d..3d73bbe 100644
--- a/src/VBox/Devices/Audio/DevIchAc97.cpp
+++ b/src/VBox/Devices/Audio/DevIchAc97.cpp
@@ -4,7 +4,7 @@
  */
 
 /*
- * Copyright (C) 2006-2016 Oracle Corporation
+ * Copyright (C) 2006-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;
@@ -42,27 +42,6 @@
 *   Defined Constants And Macros                                                                                                 *
 *********************************************************************************************************************************/
 
-#ifdef DEBUG
-//#define DEBUG_LUN
-# ifdef DEBUG_LUN
-#  define DEBUG_LUN_NUM 1
-# endif
-#endif /* DEBUG */
-
-/*
- * AC97_DEBUG_DUMP_PCM_DATA enables dumping the raw PCM data
- * to a file on the host. Be sure to adjust AC97_DEBUG_DUMP_PCM_DATA_PATH
- * to your needs before using this!
- */
-//#define AC97_DEBUG_DUMP_PCM_DATA
-#ifdef AC97_DEBUG_DUMP_PCM_DATA
-# ifdef RT_OS_WINDOWS
-#  define AC97_DEBUG_DUMP_PCM_DATA_PATH "c:\\temp\\"
-# else
-#  define AC97_DEBUG_DUMP_PCM_DATA_PATH "/tmp/"
-# endif
-#endif
-
 #define AC97_SSM_VERSION 1
 
 #ifdef VBOX
@@ -289,7 +268,7 @@ typedef struct AC97STREAMSTATE
 typedef struct AC97STREAM
 {
     /** Stream number (SDn). */
-    uint8_t         u8Strm;
+    uint8_t         u8SD;
     /** Bus master registers of this stream. */
     AC97BMREGS      Regs;
     /** Internal state of this stream. */
@@ -323,7 +302,7 @@ typedef struct AC97DRIVER
     /** Pointer to AC97 controller (state). */
     R3PTRTYPE(PAC97STATE)              pAC97State;
     /** Driver flags. */
-    PDMAUDIODRVFLAGS                   Flags;
+    PDMAUDIODRVFLAGS                   fFlags;
     uint32_t                           PaddingFlags;
     /** LUN # to which this driver has been assigned. */
     uint8_t                            uLUN;
@@ -357,11 +336,11 @@ typedef struct AC97STATE
     uint32_t                last_samp;
     uint8_t                 mixer_data[256];
     /** Stream state for line-in. */
-    AC97STREAM              StrmStLineIn;
+    AC97STREAM              LineIn;
     /** Stream state for microphone-in. */
-    AC97STREAM              StrmStMicIn;
+    AC97STREAM              MicIn;
     /** Stream state for output. */
-    AC97STREAM              StrmStOut;
+    AC97STREAM              Out;
 #ifndef VBOX_WITH_AUDIO_CALLBACKS
     /** The timer for pumping data thru the attached LUN drivers. */
     PTMTIMERR3              pTimer;
@@ -424,13 +403,19 @@ static void ichac97ColdReset(PAC97STATE pThis)
 }
 
 /** Fetches the buffer descriptor at _CIV. */
-static void ichac97StreamFetchBDLE(PAC97STATE pThis, PAC97STREAM pStrmSt)
+static void ichac97StreamFetchBDLE(PAC97STATE pThis, PAC97STREAM pStream)
 {
     PPDMDEVINS  pDevIns = ICHAC97STATE_2_DEVINS(pThis);
-    PAC97BMREGS pRegs   = &pStrmSt->Regs;
+    PAC97BMREGS pRegs   = &pStream->Regs;
 
-    uint32_t u32[2];
+    if (!pRegs->bdbar) /* Should never happen! */
+    {
+        AssertMsgFailed(("BDBAR address for stream #%RU8 not set (yet)!\n", pStream->u8SD));
+        return;
+    }
 
+    /** @todo Use a struct here. */
+    uint32_t u32[2];
     PDMDevHlpPhysRead(pDevIns, pRegs->bdbar + pRegs->civ * 8, &u32[0], sizeof(u32));
     pRegs->bd_valid   = 1;
 #if !defined(RT_ARCH_X86) && !defined(RT_ARCH_AMD64)
@@ -443,15 +428,17 @@ static void ichac97StreamFetchBDLE(PAC97STATE pThis, PAC97STREAM pStrmSt)
     LogFlowFunc(("bd %2d addr=%#x ctl=%#06x len=%#x(%d bytes)\n",
                   pRegs->civ, pRegs->bd.addr, pRegs->bd.ctl_len >> 16,
                   pRegs->bd.ctl_len & 0xffff, (pRegs->bd.ctl_len & 0xffff) << 1));
+
+    /** @todo Return rc or something? */
 }
 
 /**
  * Update the BM status register
  */
-static void ichac97StreamUpdateStatus(PAC97STATE pThis, PAC97STREAM pStrmSt, uint32_t new_sr)
+static void ichac97StreamUpdateStatus(PAC97STATE pThis, PAC97STREAM pStream, uint32_t new_sr)
 {
     PPDMDEVINS  pDevIns = ICHAC97STATE_2_DEVINS(pThis);
-    PAC97BMREGS pRegs   = &pStrmSt->Regs;
+    PAC97BMREGS pRegs   = &pStream->Regs;
 
     bool fSignal   = false;
     bool iIrqLevel = 0;
@@ -489,26 +476,26 @@ static void ichac97StreamUpdateStatus(PAC97STATE pThis, PAC97STREAM pStrmSt, uin
     if (fSignal)
     {
         if (iIrqLevel)
-            pThis->glob_sta |=  masks[pStrmSt->u8Strm];
+            pThis->glob_sta |=  masks[pStream->u8SD];
         else
-            pThis->glob_sta &= ~masks[pStrmSt->u8Strm];
+            pThis->glob_sta &= ~masks[pStream->u8SD];
 
         LogFlowFunc(("set irq level=%d\n", !!iIrqLevel));
         PDMDevHlpPCISetIrq(pDevIns, 0, !!iIrqLevel);
     }
 }
 
-static int ichac97StreamSetActive(PAC97STATE pThis, PAC97STREAM pStrmSt, bool fActive)
+static int ichac97StreamSetActive(PAC97STATE pThis, PAC97STREAM pStream, bool fActive)
 {
     AssertPtrReturn(pThis,   VERR_INVALID_POINTER);
-    AssertPtrReturn(pStrmSt, VERR_INVALID_POINTER);
+    AssertPtrReturn(pStream, VERR_INVALID_POINTER);
 
-    LogFlowFunc(("u8Strm=%RU8, fActive=%RTbool\n", pStrmSt->u8Strm, fActive));
+    LogFlowFunc(("u8SD=%RU8, fActive=%RTbool\n", pStream->u8SD, fActive));
 
     int rc = VINF_SUCCESS;
 
     PAC97DRIVER pDrv;
-    switch (pStrmSt->u8Strm)
+    switch (pStream->u8SD)
     {
         case PI_INDEX:
             RTListForEach(&pThis->lstDrv, pDrv, AC97DRIVER, Node)
@@ -541,7 +528,7 @@ static int ichac97StreamSetActive(PAC97STATE pThis, PAC97STREAM pStrmSt, bool fA
             break;
 
         default:
-            AssertMsgFailed(("Wrong index %RU32\n", pStrmSt->u8Strm));
+            AssertMsgFailed(("Wrong index %RU32\n", pStream->u8SD));
             rc = VERR_NOT_SUPPORTED;
             break;
     }
@@ -549,27 +536,27 @@ static int ichac97StreamSetActive(PAC97STATE pThis, PAC97STREAM pStrmSt, bool fA
     return rc;
 }
 
-static void ichac97StreamResetBMRegs(PAC97STATE pThis, PAC97STREAM pStrmSt)
+static void ichac97StreamResetBMRegs(PAC97STATE pThis, PAC97STREAM pStream)
 {
     AssertPtrReturnVoid(pThis);
-    AssertPtrReturnVoid(pStrmSt);
+    AssertPtrReturnVoid(pStream);
 
     LogFlowFuncEnter();
 
-    PAC97BMREGS pRegs = &pStrmSt->Regs;
+    PAC97BMREGS pRegs = &pStream->Regs;
 
     pRegs->bdbar    = 0;
     pRegs->civ      = 0;
     pRegs->lvi      = 0;
 
-    ichac97StreamUpdateStatus(pThis, pStrmSt, SR_DCH); /** @todo Do we need to do that? */
+    ichac97StreamUpdateStatus(pThis, pStream, SR_DCH); /** @todo Do we need to do that? */
 
     pRegs->picb     = 0;
     pRegs->piv      = 0;
     pRegs->cr       = pRegs->cr & CR_DONT_CLEAR_MASK;
     pRegs->bd_valid = 0;
 
-    int rc = ichac97StreamSetActive(pThis, pStrmSt, false /* fActive */);
+    int rc = ichac97StreamSetActive(pThis, pStream, false /* fActive */);
     AssertRC(rc);
 
     RT_ZERO(pThis->silence);
@@ -602,20 +589,42 @@ static uint16_t ichac97MixerGet(PAC97STATE pThis, uint32_t u8Idx)
     return uVal;
 }
 
-#if 0 // unused
 static DECLCALLBACK(void) ichac97CloseIn(PAC97STATE pThis, PDMAUDIORECSOURCE enmRecSource)
 {
-    NOREF(pThis);
     NOREF(enmRecSource);
+
     LogFlowFuncEnter();
+
+    PAC97DRIVER pDrv;
+    RTListForEach(&pThis->lstDrv, pDrv, AC97DRIVER, Node)
+    {
+        PAC97INPUTSTREAM pStrmIn;
+        if (enmRecSource == PDMAUDIORECSOURCE_MIC) /** @todo Refine this once we have more streams. */
+            pStrmIn = &pDrv->MicIn;
+        else
+            pStrmIn = &pDrv->LineIn;
+
+        pDrv->pConnector->pfnDestroyIn(pDrv->pConnector, pStrmIn->pStrmIn);
+        LogFlowFunc(("LUN#%RU8: Destroyed input\n", pDrv->uLUN));
+        pStrmIn = NULL;
+    }
 }
 
 static DECLCALLBACK(void) ichac97CloseOut(PAC97STATE pThis)
 {
-    NOREF(pThis);
     LogFlowFuncEnter();
+
+    PAC97DRIVER pDrv;
+    RTListForEach(&pThis->lstDrv, pDrv, AC97DRIVER, Node)
+    {
+        if (pDrv->Out.pStrmOut)
+        {
+            pDrv->pConnector->pfnDestroyOut(pDrv->pConnector, pDrv->Out.pStrmOut);
+            LogFlowFunc(("LUN#%RU8: Destroyed output\n", pDrv->uLUN));
+            pDrv->Out.pStrmOut = NULL;
+        }
+    }
 }
-#endif
 
 static int ichac97OpenIn(PAC97STATE pThis,
                          const char *pszName, PDMAUDIORECSOURCE enmRecSource,
@@ -657,6 +666,12 @@ static int ichac97OpenIn(PAC97STATE pThis,
         else
             pStrmIn = &pDrv->LineIn;
 
+        if (pStrmIn->pStrmIn)
+        {
+            pDrv->pConnector->pfnDestroyIn(pDrv->pConnector, pStrmIn->pStrmIn);
+            pStrmIn->pStrmIn = NULL;
+        }
+
         rc = pDrv->pConnector->pfnCreateIn(pDrv->pConnector, pszDesc, enmRecSource, pCfg, &pStrmIn->pStrmIn);
 
         LogFlowFunc(("LUN#%RU8: Created input \"%s\", with rc=%Rrc\n", pDrv->uLUN, pszDesc, rc));
@@ -694,6 +709,12 @@ static int ichac97OpenOut(PAC97STATE pThis, const char *pszName, PPDMAUDIOSTREAM
             break;
         }
 
+        if (pDrv->Out.pStrmOut)
+        {
+            pDrv->pConnector->pfnDestroyOut(pDrv->pConnector, pDrv->Out.pStrmOut);
+            pDrv->Out.pStrmOut = NULL;
+        }
+
         rc = pDrv->pConnector->pfnCreateOut(pDrv->pConnector, pszDesc, pCfg, &pDrv->Out.pStrmOut);
         LogFlowFunc(("LUN#%RU8: Created output \"%s\", with rc=%Rrc\n", pDrv->uLUN, pszDesc, rc));
         if (rc == VINF_SUCCESS) /* Note: Could return VWRN_ALREADY_EXISTS. */
@@ -711,20 +732,20 @@ static int ichac97OpenOut(PAC97STATE pThis, const char *pszName, PPDMAUDIOSTREAM
     return rc;
 }
 
-static int ichac97StreamInitEx(PAC97STATE pThis, PAC97STREAM pStrmSt, uint8_t u8Strm, PPDMAUDIOSTREAMCFG pCfg)
+static int ichac97StreamInitEx(PAC97STATE pThis, PAC97STREAM pStream, uint8_t u8SD, PPDMAUDIOSTREAMCFG pCfg)
 {
     AssertPtrReturn(pThis,             VERR_INVALID_POINTER);
-    AssertPtrReturn(pStrmSt,           VERR_INVALID_POINTER);
-    AssertReturn(u8Strm <= LAST_INDEX, VERR_INVALID_PARAMETER);
+    AssertPtrReturn(pStream,           VERR_INVALID_POINTER);
+    AssertReturn(u8SD <= LAST_INDEX,   VERR_INVALID_PARAMETER);
     AssertPtrReturn(pCfg,              VERR_INVALID_POINTER);
 
-    pStrmSt->u8Strm = u8Strm;
+    pStream->u8SD = u8SD;
 
-    LogFlowFunc(("u8Strm=%RU8, %RU32Hz, %RU8 %s\n",
-                 pStrmSt->u8Strm, pCfg->uHz, pCfg->cChannels, pCfg->cChannels > 1 ? "Channels" : "Channel"));
+    LogFlowFunc(("u8SD=%RU8, %RU32Hz, %RU8 %s\n",
+                 pStream->u8SD, pCfg->uHz, pCfg->cChannels, pCfg->cChannels > 1 ? "Channels" : "Channel"));
 
     int rc;
-    switch (pStrmSt->u8Strm)
+    switch (pStream->u8SD)
     {
         case PI_INDEX:
             rc = ichac97OpenIn(pThis, "ac97.pi", PDMAUDIORECSOURCE_LINE_IN, pCfg);
@@ -747,14 +768,14 @@ static int ichac97StreamInitEx(PAC97STATE pThis, PAC97STREAM pStrmSt, uint8_t u8
     return rc;
 }
 
-static int ichac97StreamInit(PAC97STATE pThis, PAC97STREAM pStrmSt, uint8_t u8Strm)
+static int ichac97StreamInit(PAC97STATE pThis, PAC97STREAM pStream, uint8_t u8SD)
 {
     int rc = VINF_SUCCESS;
 
     PDMAUDIOSTREAMCFG streamCfg;
     RT_ZERO(streamCfg);
 
-    switch (u8Strm)
+    switch (u8SD)
     {
         case PI_INDEX:
             streamCfg.uHz = ichac97MixerGet(pThis, AC97_PCM_LR_ADC_Rate);
@@ -782,24 +803,24 @@ static int ichac97StreamInit(PAC97STATE pThis, PAC97STREAM pStrmSt, uint8_t u8St
         streamCfg.enmFormat     = AUD_FMT_S16;
         streamCfg.enmEndianness = PDMAUDIOHOSTENDIANNESS;
 
-        return ichac97StreamInitEx(pThis, pStrmSt, u8Strm, &streamCfg);
+        return ichac97StreamInitEx(pThis, pStream, u8SD, &streamCfg);
     }
 
     /* If no frequency is given, disable the stream. */
-    return ichac97StreamSetActive(pThis, pStrmSt, false /* fActive */);
+    return ichac97StreamSetActive(pThis, pStream, false /* fActive */);
 }
 
-static int ichac97StreamReInit(PAC97STATE pThis, PAC97STREAM pStrmSt)
+static int ichac97StreamReInit(PAC97STATE pThis, PAC97STREAM pStream)
 {
-    return ichac97StreamInit(pThis, pStrmSt, pStrmSt->u8Strm);
+    return ichac97StreamInit(pThis, pStream, pStream->u8SD);
 }
 
-static void ichac97StreamReset(PAC97STATE pThis, PAC97STREAM pStrmSt)
+static void ichac97StreamReset(PAC97STATE pThis, PAC97STREAM pStream)
 {
     AssertPtrReturnVoid(pThis);
-    AssertPtrReturnVoid(pStrmSt);
+    AssertPtrReturnVoid(pStream);
 
-    LogFlowFunc(("uStrm=%RU8\n", pStrmSt->u8Strm));
+    LogFlowFunc(("uStrm=%RU8\n", pStream->u8SD));
 }
 
 static int ichac97MixerSetVolume(PAC97STATE pThis, int index, PDMAUDIOMIXERCTL mt, uint32_t val)
@@ -995,19 +1016,19 @@ static int ichac97MixerReset(PAC97STATE pThis)
  *
  * @return  IPRT status code.
  * @param   pThis
- * @param   pStrmSt
+ * @param   pStream
  * @param   cbMax
  * @param   pcbWritten
  */
-static int ichac97WriteAudio(PAC97STATE pThis, PAC97STREAM pStrmSt, uint32_t cbMax, uint32_t *pcbWritten)
+static int ichac97WriteAudio(PAC97STATE pThis, PAC97STREAM pStream, uint32_t cbMax, uint32_t *pcbWritten)
 {
     AssertPtrReturn(pThis,      VERR_INVALID_POINTER);
-    AssertPtrReturn(pStrmSt,    VERR_INVALID_POINTER);
+    AssertPtrReturn(pStream,    VERR_INVALID_POINTER);
     AssertReturn(cbMax,         VERR_INVALID_PARAMETER);
     /* pcbWritten is optional. */
 
     PPDMDEVINS  pDevIns = ICHAC97STATE_2_DEVINS(pThis);
-    PAC97BMREGS pRegs   = &pStrmSt->Regs;
+    PAC97BMREGS pRegs   = &pStream->Regs;
 
     uint32_t    addr           = pRegs->bd.addr;
     uint32_t    cbWrittenTotal = 0;
@@ -1018,45 +1039,72 @@ static int ichac97WriteAudio(PAC97STATE pThis, PAC97STREAM pStrmSt, uint32_t cbM
     {
         if (pcbWritten)
             *pcbWritten = 0;
-        return VINF_EOF;
+        return VINF_SUCCESS;
     }
 
     int rc = VINF_SUCCESS;
 
-    LogFlowFunc(("pReg=%p, cbMax=%RU32, cbToWrite=%RU32\n", pRegs, cbMax, cbToWrite));
+    LogFlowFunc(("cbMax=%RU32, cbToWrite=%RU32\n", cbMax, cbToWrite));
 
     while (cbToWrite)
     {
         cbToRead = RT_MIN(cbToWrite, pThis->cbReadWriteBuf);
         PDMDevHlpPhysRead(pDevIns, addr, pThis->pvReadWriteBuf, cbToRead); /** @todo Check rc? */
 
-        uint32_t cbWritten;
+        uint32_t cbWritten = 0;
 
-#ifdef AC97_DEBUG_DUMP_PCM_DATA
-        RTFILE fh;
-        RTFileOpen(&fh, AC97_DEBUG_DUMP_PCM_DATA_PATH "ac97DMARead.pcm",
-                   RTFILE_O_OPEN_CREATE | RTFILE_O_APPEND | RTFILE_O_WRITE | RTFILE_O_DENY_NONE);
-        RTFileWrite(fh, pThis->pvReadWriteBuf, cbToRead, NULL);
-        RTFileClose(fh);
-#endif
         /* Just multiplex the output to the connected backends.
          * No need to utilize the virtual mixer here (yet). */
         PAC97DRIVER pDrv;
         RTListForEach(&pThis->lstDrv, pDrv, AC97DRIVER, Node)
         {
-            int rc2 = pDrv->pConnector->pfnWrite(pDrv->pConnector, pDrv->Out.pStrmOut,
-                                                 pThis->pvReadWriteBuf, cbToRead, &cbWritten);
-            RT_NOREF(rc2);
-            LogFlowFunc(("\tLUN#%RU8: rc=%Rrc, cbWritten=%RU32\n", pDrv->uLUN, rc2, cbWritten));
+            if (pDrv->pConnector->pfnIsActiveOut(pDrv->pConnector, pDrv->Out.pStrmOut))
+            {
+                uint32_t cbWrittenToStream = 0;
+                int rc2 = pDrv->pConnector->pfnWrite(pDrv->pConnector, pDrv->Out.pStrmOut,
+                                                     pThis->pvReadWriteBuf, cbToRead, &cbWrittenToStream);
+                if (rc2 == VERR_NOT_AVAILABLE)
+                    continue;
+
+                /* The primary driver sets the overall pace. */
+                if (pDrv->fFlags & PDMAUDIODRVFLAG_PRIMARY)
+                {
+                    cbWritten = cbWrittenToStream;
+
+                    if (RT_FAILURE(rc2))
+                    {
+                        if (RT_SUCCESS(rc))
+                            rc = rc2;
+                        break;
+                    }
+                }
+            }
+            else /* Stream disabled, not fatal. */
+            {
+                /* Keep going. */
+            }
         }
 
-        LogFlowFunc(("\tcbToRead=%RU32, cbToWrite=%RU32, cbLeft=%RU32\n",
-                     cbToRead, cbToWrite, cbToWrite - cbWrittenTotal));
+#ifdef VBOX_AUDIO_DEBUG_DUMP_PCM_DATA
+        if (cbWritten)
+        {
+            RTFILE fh;
+            RTFileOpen(&fh, VBOX_AUDIO_DEBUG_DUMP_PCM_DATA_PATH "ac97DMARead.pcm",
+                       RTFILE_O_OPEN_CREATE | RTFILE_O_APPEND | RTFILE_O_WRITE | RTFILE_O_DENY_NONE);
+            RTFileWrite(fh, pThis->pvReadWriteBuf, cbToRead, NULL);
+            RTFileClose(fh);
+        }
+#endif
+        Assert(cbToWrite >= cbWritten);
+        cbToWrite      -= cbWritten;
+        addr           += cbWritten;
+        cbWrittenTotal += cbWritten;
 
-        Assert(cbToWrite >= cbToRead);
-        cbToWrite      -= cbToRead;
-        addr           += cbToRead;
-        cbWrittenTotal += cbToRead;
+        if (!cbWritten) /* Nothing written? Bail out. */
+            break;
+
+        if (RT_FAILURE(rc))
+            break;
     }
 
     pRegs->bd.addr = addr;
@@ -1078,7 +1126,7 @@ static int ichac97WriteAudio(PAC97STATE pThis, PAC97STREAM pStrmSt, uint32_t cbM
             *pcbWritten = cbWrittenTotal;
     }
 
-    LogFlowFunc(("cbWrittenTotal=%RU32, rc=%Rrc\n", cbWrittenTotal, rc));
+    Log3Func(("Returning cbWrittenTotal=%RU32, rc=%Rrc\n", cbWrittenTotal, rc));
     return rc;
 }
 
@@ -1090,7 +1138,7 @@ static void ichac97WriteBUP(PAC97STATE pThis, uint32_t cbElapsed)
         {
             unsigned int i;
             uint32_t *p = (uint32_t*)pThis->silence;
-            for (i = 0; i < sizeof(pThis->silence) / 4; i++)
+            for (i = 0; i < sizeof(pThis->silence) / 4 /** @todo Define frame size */; i++)
                 *p++ = pThis->last_samp;
         }
         else
@@ -1102,16 +1150,15 @@ static void ichac97WriteBUP(PAC97STATE pThis, uint32_t cbElapsed)
     while (cbElapsed)
     {
         uint32_t cbToWrite = RT_MIN(cbElapsed, (uint32_t)sizeof(pThis->silence));
-        uint32_t cbWrittenToStream;
-        int rc2;
 
         PAC97DRIVER pDrv;
         RTListForEach(&pThis->lstDrv, pDrv, AC97DRIVER, Node)
         {
+            uint32_t cbWrittenToStream;
             if (pDrv->pConnector->pfnIsActiveOut(pDrv->pConnector, pDrv->Out.pStrmOut))
             {
-                rc2 = pDrv->pConnector->pfnWrite(pDrv->pConnector, pDrv->Out.pStrmOut,
-                                                 pThis->silence, cbToWrite, &cbWrittenToStream);
+                int rc2 = pDrv->pConnector->pfnWrite(pDrv->pConnector, pDrv->Out.pStrmOut,
+                                                     pThis->silence, cbToWrite, &cbWrittenToStream);
                 if (RT_SUCCESS(rc2))
                 {
                     if (cbWrittenToStream < cbToWrite) /* Lagging behind? */
@@ -1121,8 +1168,6 @@ static void ichac97WriteBUP(PAC97STATE pThis, uint32_t cbElapsed)
             }
             else /* Stream disabled, not fatal. */
             {
-                cbWrittenToStream = 0;
-                rc2 = VERR_NOT_AVAILABLE;
                 /* Keep going. */
             }
         }
@@ -1134,19 +1179,19 @@ static void ichac97WriteBUP(PAC97STATE pThis, uint32_t cbElapsed)
     }
 }
 
-static int ichac97ReadAudio(PAC97STATE pThis, PAC97STREAM pStrmSt, uint32_t cbMax, uint32_t *pcbRead)
+static int ichac97ReadAudio(PAC97STATE pThis, PAC97STREAM pStream, uint32_t cbMax, uint32_t *pcbRead)
 {
     AssertPtrReturn(pThis,   VERR_INVALID_POINTER);
-    AssertPtrReturn(pStrmSt, VERR_INVALID_POINTER);
+    AssertPtrReturn(pStream, VERR_INVALID_POINTER);
     AssertReturn(cbMax,      VERR_INVALID_PARAMETER);
     /* pcbRead is optional. */
 
     PPDMDEVINS pDevIns = ICHAC97STATE_2_DEVINS(pThis);
-    PAC97BMREGS pRegs  = &pStrmSt->Regs;
+    PAC97BMREGS pRegs  = &pStream->Regs;
 
     /* Select audio sink to process. */
-    AssertMsg(pStrmSt->u8Strm != PO_INDEX, ("Can't read from output\n"));
-    PAUDMIXSINK pSink = pStrmSt->u8Strm == MC_INDEX ? pThis->pSinkMicIn : pThis->pSinkLineIn;
+    AssertMsg(pStream->u8SD != PO_INDEX, ("Can't read from output\n"));
+    PAUDMIXSINK pSink = pStream->u8SD == MC_INDEX ? pThis->pSinkMicIn : pThis->pSinkLineIn;
     AssertPtr(pSink);
 
     uint32_t cbRead   = 0;
@@ -1158,7 +1203,7 @@ static int ichac97ReadAudio(PAC97STATE pThis, PAC97STREAM pStrmSt, uint32_t cbMa
     {
         if (pcbRead)
             *pcbRead = 0;
-        return VINF_EOF;
+        return VINF_SUCCESS;
     }
 
     int rc;
@@ -1170,6 +1215,13 @@ static int ichac97ReadAudio(PAC97STATE pThis, PAC97STREAM pStrmSt, uint32_t cbMa
         if (   RT_SUCCESS(rc)
             && cbRead)
         {
+#ifdef VBOX_AUDIO_DEBUG_DUMP_PCM_DATA
+            RTFILE fh;
+            RTFileOpen(&fh, VBOX_AUDIO_DEBUG_DUMP_PCM_DATA_PATH "ac97DMAWrite.pcm",
+                       RTFILE_O_OPEN_CREATE | RTFILE_O_APPEND | RTFILE_O_WRITE | RTFILE_O_DENY_NONE);
+            RTFileWrite(fh, pvMixBuf, cbRead, NULL);
+            RTFileClose(fh);
+#endif
             PDMDevHlpPCIPhysWrite(pDevIns, pRegs->bd.addr, pvMixBuf, cbRead);
             pRegs->bd.addr += cbRead;
         }
@@ -1219,7 +1271,7 @@ static DECLCALLBACK(void) ichac97Timer(PPDMDEVINS pDevIns, PTMTIMER pTimer, void
     int rc = AudioMixerGetDeviceFormat(pThis->pMixer, &mixerStrmCfg);
     AssertRC(rc);
 
-    PDMPCMPROPS mixerStrmProps;
+    PDMAUDIOPCMPROPS mixerStrmProps;
     rc = DrvAudioStreamCfgToProps(&mixerStrmCfg, &mixerStrmProps);
     AssertRC(rc);
 
@@ -1302,12 +1354,12 @@ static int ichac97TransferAudio(PAC97STATE pThis, AC97SOUNDSOURCE enmSrc, uint32
 {
     LogFlowFunc(("pThis=%p, enmSrc=%RU32, cbElapsed=%RU32\n", pThis, enmSrc, cbElapsed));
 
-    PAC97STREAM pStrmSt;
+    PAC97STREAM pStream;
     switch (enmSrc)
     {
-        case PI_INDEX: pStrmSt = &pThis->StrmStLineIn; break;
-        case MC_INDEX: pStrmSt = &pThis->StrmStMicIn;  break;
-        case PO_INDEX: pStrmSt = &pThis->StrmStOut;    break;
+        case PI_INDEX: pStream = &pThis->LineIn; break;
+        case MC_INDEX: pStream = &pThis->MicIn;  break;
+        case PO_INDEX: pStream = &pThis->Out;    break;
         default:
         {
             AssertMsgFailed(("Unknown source index %ld\n", enmSrc));
@@ -1315,7 +1367,7 @@ static int ichac97TransferAudio(PAC97STATE pThis, AC97SOUNDSOURCE enmSrc, uint32
         }
     }
 
-    PAC97BMREGS pRegs = &pStrmSt->Regs;
+    PAC97BMREGS pRegs = &pStream->Regs;
 
     if (pRegs->sr & SR_DCH) /* Controller halted? */
     {
@@ -1343,7 +1395,7 @@ static int ichac97TransferAudio(PAC97STATE pThis, AC97SOUNDSOURCE enmSrc, uint32
         if (!pRegs->bd_valid)
         {
             LogFlowFunc(("Invalid buffer descriptor, fetching next one ...\n"));
-            ichac97StreamFetchBDLE(pThis, pStrmSt);
+            ichac97StreamFetchBDLE(pThis, pStream);
         }
 
         if (!pRegs->picb) /* Got a new buffer descriptor, that is, the position is 0? */
@@ -1363,16 +1415,17 @@ static int ichac97TransferAudio(PAC97STATE pThis, AC97SOUNDSOURCE enmSrc, uint32
             pRegs->civ = pRegs->piv;
             pRegs->piv = (pRegs->piv + 1) % 32;
 
-            ichac97StreamFetchBDLE(pThis, pStrmSt);
+            ichac97StreamFetchBDLE(pThis, pStream);
             continue;
         }
 
-        uint32_t cbTransferred;
+        uint32_t cbTransferred = 0;
+
         switch (enmSrc)
         {
             case PO_INDEX:
             {
-                rc = ichac97WriteAudio(pThis, pStrmSt, cbElapsed, &cbTransferred);
+                rc = ichac97WriteAudio(pThis, pStream, cbElapsed, &cbTransferred);
                 if (   RT_SUCCESS(rc)
                     && cbTransferred)
                 {
@@ -1388,7 +1441,7 @@ static int ichac97TransferAudio(PAC97STATE pThis, AC97SOUNDSOURCE enmSrc, uint32
             case PI_INDEX:
             case MC_INDEX:
             {
-                rc = ichac97ReadAudio(pThis, pStrmSt, cbElapsed, &cbTransferred);
+                rc = ichac97ReadAudio(pThis, pStream, cbElapsed, &cbTransferred);
                 if (   RT_SUCCESS(rc)
                     && cbTransferred)
                 {
@@ -1429,14 +1482,17 @@ static int ichac97TransferAudio(PAC97STATE pThis, AC97SOUNDSOURCE enmSrc, uint32
             {
                 pRegs->civ = pRegs->piv;
                 pRegs->piv = (pRegs->piv + 1) % 32;
-                ichac97StreamFetchBDLE(pThis, pStrmSt);
+                ichac97StreamFetchBDLE(pThis, pStream);
             }
 
-            ichac97StreamUpdateStatus(pThis, pStrmSt, new_sr);
+            ichac97StreamUpdateStatus(pThis, pStream, new_sr);
         }
 
+        if (!cbTransferred)    /* No more data to process? */
+            rc = VINF_EOF;
+
         if (   RT_FAILURE(rc)
-            || rc == VINF_EOF) /* All data processed? */
+            || rc == VINF_EOF) /* Abort loop? */
         {
             break;
         }
@@ -1458,8 +1514,8 @@ static DECLCALLBACK(int) ichac97IOPortNABMRead(PPDMDEVINS pDevIns, void *pvUser,
     /* Get the index of the NABMBAR port. */
     const uint32_t uPortIdx = Port - pThis->IOPortBase[1];
 
-    PAC97STREAM pStrmSt     = ichac97GetStreamFromID(pThis, AC97_PORT2IDX(uPortIdx));
-    PAC97BMREGS pRegs       = pStrmSt ? &pStrmSt->Regs : NULL;
+    PAC97STREAM pStream     = ichac97GetStreamFromID(pThis, AC97_PORT2IDX(uPortIdx));
+    PAC97BMREGS pRegs       = pStream ? &pStream->Regs : NULL;
 
     switch (cbVal)
     {
@@ -1609,8 +1665,8 @@ static DECLCALLBACK(int) ichac97IOPortNABMWrite(PPDMDEVINS pDevIns, void *pvUser
     /* Get the index of the NABMBAR register. */
     const uint32_t uPortIdx = Port - pThis->IOPortBase[1];
 
-    PAC97STREAM pStrmSt     = ichac97GetStreamFromID(pThis, AC97_PORT2IDX(uPortIdx));
-    PAC97BMREGS pRegs       = pStrmSt ? &pStrmSt->Regs : NULL;
+    PAC97STREAM pStream     = ichac97GetStreamFromID(pThis, AC97_PORT2IDX(uPortIdx));
+    PAC97BMREGS pRegs       = pStream ? &pStream->Regs : NULL;
 
     switch (cbVal)
     {
@@ -1628,7 +1684,7 @@ static DECLCALLBACK(int) ichac97IOPortNABMWrite(PPDMDEVINS pDevIns, void *pvUser
                         pRegs->civ = pRegs->piv;
                         pRegs->piv = (pRegs->piv + 1) % 32;
 
-                        ichac97StreamFetchBDLE(pThis, pStrmSt);
+                        ichac97StreamFetchBDLE(pThis, pStream);
                     }
                     pRegs->lvi = u32Val % 32;
                     LogFlowFunc(("LVI[%d] <- %#x\n", AC97_PORT2IDX(uPortIdx), u32Val));
@@ -1640,14 +1696,14 @@ static DECLCALLBACK(int) ichac97IOPortNABMWrite(PPDMDEVINS pDevIns, void *pvUser
                     /* Control Register */
                     if (u32Val & CR_RR) /* Busmaster reset */
                     {
-                        ichac97StreamResetBMRegs(pThis, pStrmSt);
+                        ichac97StreamResetBMRegs(pThis, pStream);
                     }
                     else
                     {
                         pRegs->cr = u32Val & CR_VALID_MASK;
                         if (!(pRegs->cr & CR_RPBM))
                         {
-                            ichac97StreamSetActive(pThis, pStrmSt, false /* fActive */);
+                            ichac97StreamSetActive(pThis, pStream, false /* fActive */);
                             pRegs->sr |= SR_DCH;
                         }
                         else
@@ -1655,10 +1711,10 @@ static DECLCALLBACK(int) ichac97IOPortNABMWrite(PPDMDEVINS pDevIns, void *pvUser
                             pRegs->civ = pRegs->piv;
                             pRegs->piv = (pRegs->piv + 1) % 32;
 
-                            ichac97StreamFetchBDLE(pThis, pStrmSt);
+                            ichac97StreamFetchBDLE(pThis, pStream);
 
                             pRegs->sr &= ~SR_DCH;
-                            ichac97StreamSetActive(pThis, pStrmSt, true /* fActive */);
+                            ichac97StreamSetActive(pThis, pStream, true /* fActive */);
                         }
                     }
                     LogFlowFunc(("CR[%d] <- %#x (cr %#x)\n", AC97_PORT2IDX(uPortIdx), u32Val, pRegs->cr));
@@ -1669,7 +1725,7 @@ static DECLCALLBACK(int) ichac97IOPortNABMWrite(PPDMDEVINS pDevIns, void *pvUser
                 case MC_SR:
                     /* Status Register */
                     pRegs->sr |= u32Val & ~(SR_RO_MASK | SR_WCLEAR_MASK);
-                    ichac97StreamUpdateStatus(pThis, pStrmSt, pRegs->sr & ~(u32Val & SR_WCLEAR_MASK));
+                    ichac97StreamUpdateStatus(pThis, pStream, pRegs->sr & ~(u32Val & SR_WCLEAR_MASK));
                     LogFlowFunc(("SR[%d] <- %#x (sr %#x)\n", AC97_PORT2IDX(uPortIdx), u32Val, pRegs->sr));
                     break;
                 default:
@@ -1688,7 +1744,7 @@ static DECLCALLBACK(int) ichac97IOPortNABMWrite(PPDMDEVINS pDevIns, void *pvUser
                 case MC_SR:
                     /* Status Register */
                     pRegs->sr |= u32Val & ~(SR_RO_MASK | SR_WCLEAR_MASK);
-                    ichac97StreamUpdateStatus(pThis, pStrmSt, pRegs->sr & ~(u32Val & SR_WCLEAR_MASK));
+                    ichac97StreamUpdateStatus(pThis, pStream, pRegs->sr & ~(u32Val & SR_WCLEAR_MASK));
                     LogFlowFunc(("SR[%d] <- %#x (sr %#x)\n", AC97_PORT2IDX(uPortIdx), u32Val, pRegs->sr));
                     break;
                 default:
@@ -1850,15 +1906,15 @@ static DECLCALLBACK(int) ichac97IOPortNAMWrite(PPDMDEVINS pDevIns,
                     if (!(u32Val & EACS_VRA))
                     {
                         ichac97MixerSet(pThis, AC97_PCM_Front_DAC_Rate, 48000);
-                        ichac97StreamReInit(pThis, &pThis->StrmStOut);
+                        ichac97StreamReInit(pThis, &pThis->Out);
 
                         ichac97MixerSet(pThis, AC97_PCM_LR_ADC_Rate,    48000);
-                        ichac97StreamReInit(pThis, &pThis->StrmStLineIn);
+                        ichac97StreamReInit(pThis, &pThis->LineIn);
                     }
                     if (!(u32Val & EACS_VRM))
                     {
                         ichac97MixerSet(pThis, AC97_MIC_ADC_Rate,       48000);
-                        ichac97StreamReInit(pThis, &pThis->StrmStMicIn);
+                        ichac97StreamReInit(pThis, &pThis->MicIn);
                     }
                     LogFlowFunc(("Setting extended audio control to %#x\n", u32Val));
                     ichac97MixerSet(pThis, AC97_Extended_Audio_Ctrl_Stat, u32Val);
@@ -1868,7 +1924,7 @@ static DECLCALLBACK(int) ichac97IOPortNAMWrite(PPDMDEVINS pDevIns,
                     {
                         ichac97MixerSet(pThis, index, u32Val);
                         LogFlowFunc(("Set front DAC rate to %RU32\n", u32Val));
-                        ichac97StreamReInit(pThis, &pThis->StrmStOut);
+                        ichac97StreamReInit(pThis, &pThis->Out);
                     }
                     else
                         LogFlowFunc(("Attempt to set front DAC rate to %RU32, but VRA is not set\n", u32Val));
@@ -1878,7 +1934,7 @@ static DECLCALLBACK(int) ichac97IOPortNAMWrite(PPDMDEVINS pDevIns,
                     {
                         ichac97MixerSet(pThis, index, u32Val);
                         LogFlowFunc(("Set MIC ADC rate to %RU32\n", u32Val));
-                        ichac97StreamReInit(pThis, &pThis->StrmStMicIn);
+                        ichac97StreamReInit(pThis, &pThis->MicIn);
                     }
                     else
                         LogFlowFunc(("Attempt to set MIC ADC rate to %RU32, but VRM is not set\n", u32Val));
@@ -1888,7 +1944,7 @@ static DECLCALLBACK(int) ichac97IOPortNAMWrite(PPDMDEVINS pDevIns,
                     {
                         ichac97MixerSet(pThis, index, u32Val);
                         LogFlowFunc(("Set front LR ADC rate to %RU32\n", u32Val));
-                        ichac97StreamReInit(pThis, &pThis->StrmStLineIn);
+                        ichac97StreamReInit(pThis, &pThis->LineIn);
                     }
                     else
                         LogFlowFunc(("Attempt to set LR ADC rate to %RU32, but VRA is not set\n", u32Val));
@@ -1953,9 +2009,9 @@ DECLINLINE(PAC97STREAM) ichac97GetStreamFromID(PAC97STATE pThis, uint32_t uID)
 {
     switch (uID)
     {
-        case PI_INDEX: return &pThis->StrmStLineIn;
-        case MC_INDEX: return &pThis->StrmStMicIn;
-        case PO_INDEX: return &pThis->StrmStOut;
+        case PI_INDEX: return &pThis->LineIn;
+        case MC_INDEX: return &pThis->MicIn;
+        case PO_INDEX: return &pThis->Out;
         default:       break;
     }
 
@@ -1963,10 +2019,10 @@ DECLINLINE(PAC97STREAM) ichac97GetStreamFromID(PAC97STATE pThis, uint32_t uID)
 }
 
 #ifdef IN_RING3
-static int ichac97SaveStream(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, PAC97STREAM pStrmSt)
+static int ichac97SaveStream(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, PAC97STREAM pStream)
 {
     RT_NOREF(pDevIns);
-    PAC97BMREGS pRegs = &pStrmSt->Regs;
+    PAC97BMREGS pRegs = &pStream->Regs;
 
     SSMR3PutU32(pSSM, pRegs->bdbar);
     SSMR3PutU8( pSSM, pRegs->civ);
@@ -1995,11 +2051,11 @@ static DECLCALLBACK(int) ichac97SaveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM)
 
     /** @todo r=andy For the next saved state version, add unique stream identifiers and a stream count. */
     /* Note: The order the streams are saved here is critical, so don't touch. */
-    int rc2 = ichac97SaveStream(pDevIns, pSSM, &pThis->StrmStLineIn);
+    int rc2 = ichac97SaveStream(pDevIns, pSSM, &pThis->LineIn);
     AssertRC(rc2);
-    rc2 = ichac97SaveStream(pDevIns, pSSM, &pThis->StrmStOut);
+    rc2 = ichac97SaveStream(pDevIns, pSSM, &pThis->Out);
     AssertRC(rc2);
-    rc2 = ichac97SaveStream(pDevIns, pSSM, &pThis->StrmStMicIn);
+    rc2 = ichac97SaveStream(pDevIns, pSSM, &pThis->MicIn);
     AssertRC(rc2);
 
     SSMR3PutMem(pSSM, pThis->mixer_data, sizeof(pThis->mixer_data));
@@ -2021,10 +2077,10 @@ static DECLCALLBACK(int) ichac97SaveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM)
     return VINF_SUCCESS;
 }
 
-static int ichac97LoadStream(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, PAC97STREAM pStrmSt)
+static int ichac97LoadStream(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, PAC97STREAM pStream)
 {
     RT_NOREF(pDevIns);
-    PAC97BMREGS pRegs = &pStrmSt->Regs;
+    PAC97BMREGS pRegs = &pStream->Regs;
 
     SSMR3GetU32(pSSM, &pRegs->bdbar);
     SSMR3GetU8( pSSM, &pRegs->civ);
@@ -2056,11 +2112,11 @@ static DECLCALLBACK(int) ichac97LoadExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, ui
 
     /** @todo r=andy For the next saved state version, add unique stream identifiers and a stream count. */
     /* Note: The order the streams are loaded here is critical, so don't touch. */
-    int rc2 = ichac97LoadStream(pDevIns, pSSM, &pThis->StrmStLineIn);
+    int rc2 = ichac97LoadStream(pDevIns, pSSM, &pThis->LineIn);
     AssertRC(rc2);
-    rc2 = ichac97LoadStream(pDevIns, pSSM, &pThis->StrmStOut);
+    rc2 = ichac97LoadStream(pDevIns, pSSM, &pThis->Out);
     AssertRC(rc2);
-    rc2 = ichac97LoadStream(pDevIns, pSSM, &pThis->StrmStMicIn);
+    rc2 = ichac97LoadStream(pDevIns, pSSM, &pThis->MicIn);
     AssertRC(rc2);
 
     SSMR3GetMem(pSSM, pThis->mixer_data, sizeof(pThis->mixer_data));
@@ -2081,19 +2137,19 @@ static DECLCALLBACK(int) ichac97LoadExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, ui
                              ichac97MixerGet(pThis, AC97_Headphone_Volume_Mute));
 
     int rc;
-    rc = ichac97StreamInit(pThis, &pThis->StrmStLineIn, PI_INDEX);
+    rc = ichac97StreamInit(pThis, &pThis->LineIn, PI_INDEX);
     AssertRC(rc);
-    rc = ichac97StreamInit(pThis, &pThis->StrmStMicIn,  MC_INDEX);
+    rc = ichac97StreamInit(pThis, &pThis->MicIn,  MC_INDEX);
     AssertRC(rc);
-    rc = ichac97StreamInit(pThis, &pThis->StrmStOut,    PO_INDEX);
+    rc = ichac97StreamInit(pThis, &pThis->Out,    PO_INDEX);
     AssertRC(rc);
 
     /** @todo r=andy Stream IDs are hardcoded to certain streams. */
-    rc = ichac97StreamSetActive(pThis, &pThis->StrmStLineIn, RT_BOOL(uaStrmsActive[PI_INDEX]));
+    rc = ichac97StreamSetActive(pThis, &pThis->LineIn, RT_BOOL(uaStrmsActive[PI_INDEX]));
     AssertRC(rc);
-    rc = ichac97StreamSetActive(pThis, &pThis->StrmStMicIn,  RT_BOOL(uaStrmsActive[MC_INDEX]));
+    rc = ichac97StreamSetActive(pThis, &pThis->MicIn,  RT_BOOL(uaStrmsActive[MC_INDEX]));
     AssertRC(rc);
-    rc = ichac97StreamSetActive(pThis, &pThis->StrmStOut,    RT_BOOL(uaStrmsActive[PO_INDEX]));
+    rc = ichac97StreamSetActive(pThis, &pThis->Out,    RT_BOOL(uaStrmsActive[PO_INDEX]));
     AssertRC(rc);
 
     pThis->bup_flag = 0;
@@ -2131,9 +2187,9 @@ static DECLCALLBACK(void) ichac97Reset(PPDMDEVINS pDevIns)
     /*
      * Reset the device state (will need pDrv later).
      */
-    ichac97StreamResetBMRegs(pThis, &pThis->StrmStLineIn);
-    ichac97StreamResetBMRegs(pThis, &pThis->StrmStMicIn);
-    ichac97StreamResetBMRegs(pThis, &pThis->StrmStOut);
+    ichac97StreamResetBMRegs(pThis, &pThis->LineIn);
+    ichac97StreamResetBMRegs(pThis, &pThis->MicIn);
+    ichac97StreamResetBMRegs(pThis, &pThis->Out);
 
     /*
      * Reset the mixer too. The Windows XP driver seems to rely on
@@ -2159,9 +2215,9 @@ static DECLCALLBACK(void) ichac97Reset(PPDMDEVINS pDevIns)
     /*
      * Reset all streams.
      */
-    ichac97StreamReset(pThis, &pThis->StrmStLineIn);
-    ichac97StreamReset(pThis, &pThis->StrmStMicIn);
-    ichac97StreamReset(pThis, &pThis->StrmStOut);
+    ichac97StreamReset(pThis, &pThis->LineIn);
+    ichac97StreamReset(pThis, &pThis->MicIn);
+    ichac97StreamReset(pThis, &pThis->Out);
 
     LogRel(("AC97: Reset\n"));
 }
@@ -2205,6 +2261,19 @@ static DECLCALLBACK(int) ichac97Destruct(PPDMDEVINS pDevIns)
 
 
 /**
+ * @interface_method_impl{PDMDEVREG,pfnPowerOff}
+ */
+static DECLCALLBACK(void) ichac97PowerOff(PPDMDEVINS pDevIns)
+{
+    PAC97STATE pThis = PDMINS_2_DATA(pDevIns, PAC97STATE);
+
+    ichac97CloseIn(pThis, PDMAUDIORECSOURCE_MIC);
+    ichac97CloseIn(pThis, PDMAUDIORECSOURCE_LINE_IN);
+    ichac97CloseOut(pThis);
+}
+
+
+/**
  * Attach command, internal version.
  *
  * This is called to let the device attach to a driver for a specified LUN
@@ -2227,11 +2296,9 @@ static DECLCALLBACK(int) ichac97AttachInternal(PPDMDEVINS pDevIns, PAC97DRIVER p
     /*
      * Attach driver.
      */
-    char *pszDesc = NULL;
+    char *pszDesc;
     if (RTStrAPrintf(&pszDesc, "Audio driver port (AC'97) for LUN #%u", uLUN) <= 0)
-        AssertReleaseMsgReturn(pszDesc,
-                               ("Not enough memory for AC'97 driver port description of LUN #%u\n", uLUN),
-                               VERR_NO_MEMORY);
+        AssertLogRelFailedReturn(VERR_NO_MEMORY);
 
     PPDMIBASE pDrvBase;
     int rc = PDMDevHlpDriverAttach(pDevIns, uLUN,
@@ -2253,9 +2320,9 @@ static DECLCALLBACK(int) ichac97AttachInternal(PPDMDEVINS pDevIns, PAC97DRIVER p
              * host backend. This might change in the future.
              */
             if (pDrv->uLUN == 0)
-                pDrv->Flags |= PDMAUDIODRVFLAG_PRIMARY;
+                pDrv->fFlags |= PDMAUDIODRVFLAG_PRIMARY;
 
-            LogFunc(("LUN#%RU8: pCon=%p, drvFlags=0x%x\n", uLUN, pDrv->pConnector, pDrv->Flags));
+            LogFunc(("LUN#%RU8: pCon=%p, drvFlags=0x%x\n", uLUN, pDrv->pConnector, pDrv->fFlags));
 
             /* Attach to driver list if not attached yet. */
             if (!pDrv->fAttached)
@@ -2542,13 +2609,13 @@ static DECLCALLBACK(int) ichac97Construct(PPDMDEVINS pDevIns, int iInstance, PCF
 
     if (RT_SUCCESS(rc))
     {
-        rc = ichac97StreamInit(pThis, &pThis->StrmStLineIn, PI_INDEX);
+        rc = ichac97StreamInit(pThis, &pThis->LineIn, PI_INDEX);
         if (RT_FAILURE(rc))
             return rc;
-        rc = ichac97StreamInit(pThis, &pThis->StrmStMicIn,  MC_INDEX);
+        rc = ichac97StreamInit(pThis, &pThis->MicIn,  MC_INDEX);
         if (RT_FAILURE(rc))
             return rc;
-        rc = ichac97StreamInit(pThis, &pThis->StrmStOut,    PO_INDEX);
+        rc = ichac97StreamInit(pThis, &pThis->Out,    PO_INDEX);
         if (RT_FAILURE(rc))
             return rc;
 
@@ -2559,7 +2626,7 @@ static DECLCALLBACK(int) ichac97Construct(PPDMDEVINS pDevIns, int iInstance, PCF
              * Only primary drivers are critical for the VM to run. Everything else
              * might not worth showing an own error message box in the GUI.
              */
-            if (!(pDrv->Flags & PDMAUDIODRVFLAG_PRIMARY))
+            if (!(pDrv->fFlags & PDMAUDIODRVFLAG_PRIMARY))
                 continue;
 
             PPDMIAUDIOCONNECTOR pCon = pDrv->pConnector;
@@ -2680,7 +2747,7 @@ static DECLCALLBACK(int) ichac97Construct(PPDMDEVINS pDevIns, int iInstance, PCF
         {
             /* Only register primary driver.
              * The device emulation does the output multiplexing then. */
-            if (!(pDrv->Flags & PDMAUDIODRVFLAG_PRIMARY))
+            if (!(pDrv->fFlags & PDMAUDIODRVFLAG_PRIMARY))
                 continue;
 
             PDMAUDIOCALLBACK AudioCallbacks[2];
@@ -2716,6 +2783,13 @@ static DECLCALLBACK(int) ichac97Construct(PPDMDEVINS pDevIns, int iInstance, PCF
     }
 # endif
 
+#ifdef VBOX_AUDIO_DEBUG_DUMP_PCM_DATA
+    RTFileDelete(VBOX_AUDIO_DEBUG_DUMP_PCM_DATA_PATH "ac97DMARead.pcm");
+    RTFileDelete(VBOX_AUDIO_DEBUG_DUMP_PCM_DATA_PATH "ac97DMAWrite.pcm");
+    RTFileDelete(VBOX_AUDIO_DEBUG_DUMP_PCM_DATA_PATH "ac97ReadAudio.pcm");
+    RTFileDelete(VBOX_AUDIO_DEBUG_DUMP_PCM_DATA_PATH "ac97WriteAudio.pcm");
+#endif
+
     LogFlowFuncLeaveRC(rc);
     return rc;
 }
@@ -2768,7 +2842,7 @@ const PDMDEVREG g_DeviceICHAC97 =
     /* pfnInitComplete */
     NULL,
     /* pfnPowerOff */
-    NULL,
+    ichac97PowerOff,
     /* pfnSoftReset */
     NULL,
     /* u32VersionEnd */
diff --git a/src/VBox/Devices/Audio/DevSB16.cpp b/src/VBox/Devices/Audio/DevSB16.cpp
index 81d0026..b21f03b 100644
--- a/src/VBox/Devices/Audio/DevSB16.cpp
+++ b/src/VBox/Devices/Audio/DevSB16.cpp
@@ -6,7 +6,7 @@
  */
 
 /*
- * Copyright (C) 2015-2016 Oracle Corporation
+ * Copyright (C) 2015-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;
@@ -92,7 +92,7 @@ typedef struct SB16DRIVER
     /** Pointer to SB16 controller (state). */
     R3PTRTYPE(PSB16STATE)              pSB16State;
     /** Driver flags. */
-    PDMAUDIODRVFLAGS                   Flags;
+    PDMAUDIODRVFLAGS                   fFlags;
     uint32_t                           PaddingFlags;
     /** LUN # to which this driver has been assigned. */
     uint8_t                            uLUN;
@@ -215,11 +215,9 @@ static DECLCALLBACK(int) sb16AttachInternal(PPDMDEVINS pDevIns, PSB16DRIVER pDrv
     /*
      * Attach driver.
      */
-    char *pszDesc = NULL;
+    char *pszDesc;
     if (RTStrAPrintf(&pszDesc, "Audio driver port (SB16) for LUN #%u", uLUN) <= 0)
-        AssertReleaseMsgReturn(pszDesc,
-                               ("Not enough memory for SB16 driver port description of LUN #%u\n", uLUN),
-                               VERR_NO_MEMORY);
+        AssertLogRelFailedReturn(VERR_NO_MEMORY);
 
     PPDMIBASE pDrvBase;
     int rc = PDMDevHlpDriverAttach(pDevIns, uLUN,
@@ -241,9 +239,9 @@ static DECLCALLBACK(int) sb16AttachInternal(PPDMDEVINS pDevIns, PSB16DRIVER pDrv
              * host backend. This might change in the future.
              */
             if (pDrv->uLUN == 0)
-                pDrv->Flags |= PDMAUDIODRVFLAG_PRIMARY;
+                pDrv->fFlags |= PDMAUDIODRVFLAG_PRIMARY;
 
-            LogFunc(("LUN#%RU8: pCon=%p, drvFlags=0x%x\n", uLUN, pDrv->pConnector, pDrv->Flags));
+            LogFunc(("LUN#%RU8: pCon=%p, drvFlags=0x%x\n", uLUN, pDrv->pConnector, pDrv->fFlags));
 
             /* Attach to driver list if not attached yet. */
             if (!pDrv->fAttached)
@@ -1620,35 +1618,58 @@ static int sb16WriteAudio(PSB16STATE pThis, int nchan, uint32_t dma_pos,
 
     while (cbToWrite)
     {
-        uint32_t cbToRead;
-        uint32_t cbRead;
-
-        cbToRead = RT_MIN(dma_len - dma_pos, cbToWrite);
+        uint32_t cbToRead = RT_MIN(dma_len - dma_pos, cbToWrite);
         if (cbToRead > sizeof(tmpbuf))
             cbToRead = sizeof(tmpbuf);
 
-        int rc = PDMDevHlpDMAReadMemory(pThis->pDevInsR3, nchan, tmpbuf, dma_pos, cbToRead, &cbRead);
-        AssertMsgRC(rc, ("DMAReadMemory -> %Rrc\n", rc));
+        uint32_t cbRead;
+        int rc2 = PDMDevHlpDMAReadMemory(pThis->pDevInsR3, nchan, tmpbuf, dma_pos, cbToRead, &cbRead);
+        AssertMsgRC(rc2, (" from DMA failed: %Rrc\n", rc2));
 
-        uint32_t cbWritten;
+#ifdef VBOX_AUDIO_DEBUG_DUMP_PCM_DATA
+        if (cbRead)
+        {
+            RTFILE fh;
+            RTFileOpen(&fh, VBOX_AUDIO_DEBUG_DUMP_PCM_DATA_PATH "sb16WriteAudio.pcm",
+                       RTFILE_O_OPEN_CREATE | RTFILE_O_APPEND | RTFILE_O_WRITE | RTFILE_O_DENY_NONE);
+            RTFileWrite(fh, tmpbuf, cbRead, NULL);
+            RTFileClose(fh);
+        }
+#endif
+        uint32_t cbWritten = 0;
 
         /* Just multiplex the output to the connected backends.
          * No need to utilize the virtual mixer here (yet). */
         PSB16DRIVER pDrv;
         RTListForEach(&pThis->lstDrv, pDrv, SB16DRIVER, Node)
         {
-            int rc2 = pDrv->pConnector->pfnWrite(pDrv->pConnector, pDrv->Out.pStrmOut,
-                                                 tmpbuf, cbToRead, &cbWritten);
-            RT_NOREF(rc2);
-            LogFlowFunc(("\tLUN#%RU8: rc=%Rrc, cbWritten=%RU32\n", pDrv->uLUN, rc2, cbWritten));
+            if (pDrv->pConnector->pfnIsActiveOut(pDrv->pConnector, pDrv->Out.pStrmOut))
+            {
+                uint32_t cbWrittenToStream = 0;
+                rc2 = pDrv->pConnector->pfnWrite(pDrv->pConnector, pDrv->Out.pStrmOut,
+                                                 tmpbuf, cbRead, &cbWrittenToStream);
+                if (rc2 == VERR_NOT_AVAILABLE)
+                    continue;
+
+                LogFlowFunc(("\tLUN#%RU8: rc=%Rrc, cbWrittenToStream=%RU32\n", pDrv->uLUN, rc2, cbWrittenToStream));
+
+                /* The primary driver sets the overall pace. */
+                if (pDrv->fFlags & PDMAUDIODRVFLAG_PRIMARY)
+                {
+                    cbWritten = cbWrittenToStream;
+
+                    if (RT_FAILURE(rc2))
+                        break;
+                }
+            }
         }
 
-        Assert(cbToWrite >= cbToRead);
-        cbToWrite      -= cbToRead;
-        dma_pos         = (dma_pos + cbToRead) % dma_len;
-        cbWrittenTotal += cbToRead;
+        Assert(cbToWrite >= cbWritten);
+        cbToWrite      -= cbWritten;
+        dma_pos         = (dma_pos + cbWritten) % dma_len;
+        cbWrittenTotal += cbWritten;
 
-        if (!cbRead)
+        if (!cbWritten)
             break;
     }
 
@@ -1769,7 +1790,7 @@ static DECLCALLBACK(void) sb16TimerIO(PPDMDEVINS pDevIns, PTMTIMER pTimer, void
     int rc = AudioMixerGetDeviceFormat(pThis->pMixer, &mixerStrmCfg);
     AssertRC(rc);
 
-    PDMPCMPROPS mixerStrmProps;
+    PDMAUDIOPCMPROPS mixerStrmProps;
     rc = DrvAudioStreamCfgToProps(&mixerStrmCfg, &mixerStrmProps);
     AssertRC(rc);
 
@@ -1786,9 +1807,8 @@ static DECLCALLBACK(void) sb16TimerIO(PPDMDEVINS pDevIns, PTMTIMER pTimer, void
         if (RT_SUCCESS(rc))
             rc = pDrv->pConnector->pfnPlayOut(pDrv->pConnector, NULL /* cSamplesPlayed */);
 
-#ifdef DEBUG_TIMER
-        LogFlowFunc(("LUN#%RU8: rc=%Rrc, cbIn=%RU32, cbOut=%RU32\n", pDrv->uLUN, rc, cbIn, cbOut));
-#endif
+        Log3Func(("LUN#%RU8: rc=%Rrc, cbIn=%RU32, cbOut=%RU32\n", pDrv->uLUN, rc, cbIn, cbOut));
+
         /* If we there was an error handling (available) output or there simply is no output available,
          * then calculate the minimum data rate which must be processed by the device emulation in order
          * to function correctly.
@@ -1802,23 +1822,11 @@ static DECLCALLBACK(void) sb16TimerIO(PPDMDEVINS pDevIns, PTMTIMER pTimer, void
             continue;
         }
 
-        const bool fIsActiveOut = pDrv->pConnector->pfnIsActiveOut(pDrv->pConnector, pDrv->Out.pStrmOut);
-        if (   RT_FAILURE(rc)
-            || !fIsActiveOut)
-        {
-            uint32_t cSamplesMin  = (int)((2 * cTicksElapsed * pDrv->Out.pStrmOut->Props.uHz + cTicksPerSec) / cTicksPerSec / 2);
-            uint32_t cbSamplesMin = AUDIOMIXBUF_S2B(&pDrv->Out.pStrmOut->MixBuf, cSamplesMin);
-
-            Log2Func(("\trc=%Rrc, cSamplesMin=%RU32, cbSamplesMin=%RU32\n", rc, cSamplesMin, cbSamplesMin));
-
-            cbOut = RT_MAX(cbOut, cbSamplesMin);
-        }
-
         cbOutMin = RT_MIN(cbOutMin, cbOut);
         cbInMax  = RT_MAX(cbInMax, cbIn);
     }
 
-    Log2Func(("cbInMax=%RU32, cbOutMin=%RU32\n", cbInMax, cbOutMin));
+    Log3Func(("cbInMax=%RU32, cbOutMin=%RU32\n", cbInMax, cbOutMin));
 
     if (cbOutMin == UINT32_MAX)
         cbOutMin = 0;
@@ -1952,18 +1960,6 @@ static int sb16Load(PSSMHANDLE pSSM, PSB16STATE pThis, int version_id)
     SSMR3GetS32(pSSM, &pThis->mixer_nreg);
     SSMR3GetMem(pSSM, pThis->mixer_regs, 256);
 
-#if 0
-    PSB16DRIVER pDrv;
-    RTListForEach(&pThis->lstDrv, pDrv, SB16DRIVER, Node)
-    {
-        if (pDrv->Out.pStrmOut)
-        {
-            pDrv->pConnector->pfnCloseOut(pThis->pDrv, pDrv->Out.pStrmOut);
-            pDrv->Out.pStrmOut = NULL;
-        }
-    }
-#endif
-
     if (pThis->dma_running)
     {
         if (pThis->freq)
@@ -2075,6 +2071,13 @@ static int sb16OpenOut(PSB16STATE pThis, PPDMAUDIOSTREAMCFG pCfg)
             break;
         }
 
+        if (pDrv->Out.pStrmOut)
+        {
+            pDrv->pConnector->pfnDestroyOut(pDrv->pConnector, pDrv->Out.pStrmOut);
+            LogFlowFunc(("LUN#%RU8: Destroyed output\n", pDrv->uLUN));
+            pDrv->Out.pStrmOut = NULL;
+        }
+
         int rc2 = pDrv->pConnector->pfnCreateOut(pDrv->pConnector, pszDesc, pCfg, &pDrv->Out.pStrmOut);
         LogFlowFunc(("LUN#%RU8: Created output with rc=%Rrc\n", uLUN, rc));
         if (rc2 == VINF_SUCCESS) /* Note: Could return VWRN_ALREADY_EXISTS. */
@@ -2157,11 +2160,6 @@ static DECLCALLBACK(int) sb16Destruct(PPDMDEVINS pDevIns)
     PDMDEV_CHECK_VERSIONS_RETURN_QUIET(pDevIns);
     PSB16STATE pThis = PDMINS_2_DATA(pDevIns, PSB16STATE);
 
-    PSB16DRIVER pDrv;
-
-    RTListForEach(&pThis->lstDrv, pDrv, SB16DRIVER, Node)
-        pDrv->Out.phStrmOut = NULL;
-
     pThis->pSinkOutput = NULL;
 
     if (pThis->pMixer)
@@ -2173,6 +2171,30 @@ static DECLCALLBACK(int) sb16Destruct(PPDMDEVINS pDevIns)
     return VINF_SUCCESS;
 }
 
+/**
+ * @interface_method_impl{PDMDEVREG,pfnPowerOff}
+ */
+static DECLCALLBACK(void) sb16PowerOff(PPDMDEVINS pDevIns)
+{
+    PSB16STATE pThis = PDMINS_2_DATA(pDevIns, PSB16STATE);
+
+    PSB16DRIVER pDrv;
+    while (!RTListIsEmpty(&pThis->lstDrv))
+    {
+        pDrv = RTListGetFirst(&pThis->lstDrv, SB16DRIVER, Node);
+
+        if (pDrv->Out.pStrmOut)
+        {
+            pDrv->pConnector->pfnDestroyOut(pDrv->pConnector, pDrv->Out.pStrmOut);
+            LogFlowFunc(("LUN#%RU8: Destroyed output\n", pDrv->uLUN));
+            pDrv->Out.pStrmOut = NULL;
+        }
+
+        RTListNodeRemove(&pDrv->Node);
+        RTMemFree(pDrv);
+    }
+}
+
 static DECLCALLBACK(int) sb16Construct(PPDMDEVINS pDevIns, int iInstance, PCFGMNODE pCfg)
 {
     RT_NOREF(iInstance);
@@ -2323,7 +2345,7 @@ static DECLCALLBACK(int) sb16Construct(PPDMDEVINS pDevIns, int iInstance, PCFGMN
          * Only primary drivers are critical for the VM to run. Everything else
          * might not worth showing an own error message box in the GUI.
          */
-        if (!(pDrv->Flags & PDMAUDIODRVFLAG_PRIMARY))
+        if (!(pDrv->fFlags & PDMAUDIODRVFLAG_PRIMARY))
             continue;
 
         PPDMIAUDIOCONNECTOR pCon = pDrv->pConnector;
@@ -2371,7 +2393,7 @@ static DECLCALLBACK(int) sb16Construct(PPDMDEVINS pDevIns, int iInstance, PCFGMN
         {
             /* Only register primary driver.
              * The device emulation does the output multiplexing then. */
-            if (pDrv->Flags != PDMAUDIODRVFLAG_PRIMARY)
+            if (pDrv->fFlags != PDMAUDIODRVFLAG_PRIMARY)
                 continue;
 
             PDMAUDIOCALLBACK AudioCallbacks[2];
@@ -2443,7 +2465,7 @@ const PDMDEVREG g_DeviceSB16 =
     /* pfnInitComplete */
     NULL,
     /* pfnPowerOff */
-    NULL,
+    sb16PowerOff,
     /* pfnSoftReset */
     NULL,
     /* u32VersionEnd */
diff --git a/src/VBox/Devices/Audio/DrvAudio.cpp b/src/VBox/Devices/Audio/DrvAudio.cpp
index a7b8992..6d28a6e 100644
--- a/src/VBox/Devices/Audio/DrvAudio.cpp
+++ b/src/VBox/Devices/Audio/DrvAudio.cpp
@@ -7,7 +7,7 @@
  */
 
 /*
- * Copyright (C) 2006-2016 Oracle Corporation
+ * Copyright (C) 2006-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;
@@ -53,6 +53,7 @@
 #include <iprt/asm-math.h>
 #include <iprt/assert.h>
 #include <iprt/circbuf.h>
+#include <iprt/file.h>
 #include <iprt/string.h>
 #include <iprt/uuid.h>
 
@@ -366,7 +367,7 @@ static bool drvAudioStreamCfgIsValid(PPDMAUDIOSTREAMCFG pCfg)
  * @param   cbBuf                   Size (in bytes) of the buffer.
  * @param   cSamples                Number of audio samples to clear in the buffer.
  */
-void DrvAudioClearBuf(PPDMPCMPROPS pPCMProps, void *pvBuf, size_t cbBuf, uint32_t cSamples)
+void DrvAudioClearBuf(PPDMAUDIOPCMPROPS pPCMProps, void *pvBuf, size_t cbBuf, uint32_t cSamples)
 {
     AssertPtrReturnVoid(pPCMProps);
     AssertPtrReturnVoid(pvBuf);
@@ -571,7 +572,12 @@ static int drvAudioControlHstOut(PDRVAUDIO pThis, PPDMAUDIOHSTSTRMOUT pHstStrmOu
                 if (RT_SUCCESS(rc))
                 {
                     pHstStrmOut->fStatus = PDMAUDIOSTRMSTS_FLAG_NONE; /* Clear all. */
-                    AudioMixBufClear(&pHstStrmOut->MixBuf);
+
+                    AudioMixBufReset(&pHstStrmOut->MixBuf);
+
+                    PPDMAUDIOGSTSTRMOUT pGstStrmOut;
+                    RTListForEach(&pHstStrmOut->lstGstStrmOut, pGstStrmOut, PDMAUDIOGSTSTRMOUT, Node)
+                        AudioMixBufReset(&pGstStrmOut->MixBuf);
 
                     LogFunc(("[%s] Disabled stream\n", pHstStrmOut->MixBuf.pszName));
                 }
@@ -766,7 +772,13 @@ int drvAudioGstOutInit(PPDMAUDIOGSTSTRMOUT pGstStrmOut, PPDMAUDIOHSTSTRMOUT pHos
         if (RTStrAPrintf(&pszTemp, "%s (Guest)", pszName) <= 0)
             return VERR_NO_MEMORY;
 
-        rc = AudioMixBufInit(&pGstStrmOut->MixBuf, pszTemp, &pGstStrmOut->Props, AudioMixBufSize(&pHostStrmOut->MixBuf));
+        const unsigned cGuestBufferFactor = 2; /** @ŧodo Make this configurable. */
+
+        uint32_t cSamples = AudioMixBufSize(&pHostStrmOut->MixBuf) * cGuestBufferFactor;
+
+        LogRel2(("Audio: Output buffer size for '%s' is %RU16ms\n", pszTemp, cSamples / (pGstStrmOut->Props.uHz / 1000 /* ms */)));
+
+        rc = AudioMixBufInit(&pGstStrmOut->MixBuf, pszTemp, &pGstStrmOut->Props, cSamples);
         if (RT_SUCCESS(rc))
             rc = AudioMixBufLinkTo(&pGstStrmOut->MixBuf, &pHostStrmOut->MixBuf);
 
@@ -848,10 +860,11 @@ int drvAudioAllocHstOut(PDRVAUDIO pThis, const char *pszName, PPDMAUDIOSTREAMCFG
         }
 
 #ifdef DEBUG
-        LogFunc(("%s: Requested format:\n", pszTemp));
+        LogFunc(("[%s] Requested format:\n", pszTemp));
         drvAudioStreamCfgPrint(pCfg);
-        LogFunc(("%s: Acquired format:\n",  pszTemp));
+        LogFunc(("[%s] Acquired format:\n",  pszTemp));
         drvAudioStreamCfgPrint(&CfgAcq);
+        LogFunc(("[%s] Audio samples: %RU32\n", pszTemp, cSamples));
 #else
         LogRel2(("Audio: Acquired output format for '%s': %RU32Hz, %s, %RU8 %s\n",
                  pszTemp, CfgAcq.uHz, drvAudioHlpFormatToString(CfgAcq.enmFormat),
@@ -860,7 +873,9 @@ int drvAudioAllocHstOut(PDRVAUDIO pThis, const char *pszName, PPDMAUDIOSTREAMCFG
         rc = DrvAudioStreamCfgToProps(&CfgAcq, &pHstStrmOut->Props);
         if (RT_SUCCESS(rc))
         {
-            rc = AudioMixBufInit(&pHstStrmOut->MixBuf, pszTemp, &pHstStrmOut->Props, cSamples);
+            LogRel2(("Audio: Output buffer size for '%s' is  %RU16ms\n", pszTemp, cSamples / (CfgAcq.uHz / 1000 /* ms */)));
+
+            rc = AudioMixBufInit(&pHstStrmOut->MixBuf, pszTemp, &pHstStrmOut->Props, cSamples * 2);
             if (RT_SUCCESS(rc))
                 rc = RTCritSectInit(&pHstStrmOut->CritSect);
 
@@ -1128,9 +1143,9 @@ static int drvAudioAllocHstIn(PDRVAUDIO pThis, const char *pszName, PPDMAUDIOSTR
         }
 
 #ifdef DEBUG
-        LogFunc(("%s: Requested format:\n", pszTemp));
+        LogFunc(("[%s] Requested format:\n", pszTemp));
         drvAudioStreamCfgPrint(pCfg);
-        LogFunc(("%s: Acquired format:\n",  pszTemp));
+        LogFunc(("[%s] Acquired format:\n",  pszTemp));
         drvAudioStreamCfgPrint(&CfgAcq);
 #else
         LogRel2(("Audio: Acquired input format for '%s': %RU32Hz, %s, %RU8 %s\n",
@@ -1217,33 +1232,58 @@ static DECLCALLBACK(int) drvAudioWrite(PPDMIAUDIOCONNECTOR pInterface, PPDMAUDIO
               ("Writing to disabled host output stream \"%s\" not possible\n",
               pHstStrmOut->MixBuf.pszName));
 
-    if (!AudioMixBufFreeBytes(&pGstStrmOut->MixBuf))
-    {
-        if (pcbWritten)
-            *pcbWritten = 0;
-
-        return RTCritSectLeave(&pThis->CritSect);
-    }
-
+    AssertMsgReturn(cbBuf % ((pGstStrmOut->Props.cBits / 8) * pGstStrmOut->Props.cChannels) == 0, /** @todo Make frame size a member or calculate it. */
+                    ("Buffer size must be an integer value of audio samples\n"),
+                    VERR_INVALID_PARAMETER);
     /*
      * First, write data from the device emulation into our
      * guest mixing buffer.
      */
-    uint32_t cWritten;
-    rc = AudioMixBufWriteAt(&pGstStrmOut->MixBuf, 0 /* Offset in samples */, pvBuf, cbBuf, &cWritten);
+    uint32_t cSrcWritten = 0;
+    rc = AudioMixBufWriteAt(&pGstStrmOut->MixBuf, 0 /* Offset */, pvBuf, cbBuf, &cSrcWritten);
+    if (RT_FAILURE(rc))
+    {
+        LogRel2(("Audio: Warning: Writing guest audio data of '%s' failed with %Rrc\n", pGstStrmOut->MixBuf.pszName, rc));
+
+#ifdef DEBUG_andy
+        AssertFailed();
+#endif
+        rc = RTCritSectLeave(&pThis->CritSect);
+        AssertRC(rc);
+
+        return rc;
+    }
+
+    uint32_t cSrcToMix = cSrcWritten;
+    uint32_t cSrcMixed = 0;
+
+    /* As the host side sets the overall pace, don't attempt to mix anything if the
+     * host-side buffer is full already. */
+    if (AudioMixBufFree(&pHstStrmOut->MixBuf) == 0)
+        cSrcToMix = 0;
+
+    Log3Func(("[%s] cbBuf=%RU32, cSrcWritten=%RU32, cSrcToMix=%RU32\n",
+              pGstStrmOut->MixBuf.pszName, cbBuf, cSrcWritten, cSrcToMix));
 
     /*
      * Second, mix the guest mixing buffer with the host mixing
      * buffer so that the host backend can play the data lateron.
      */
-    uint32_t cMixed;
-    if (   RT_SUCCESS(rc)
-        && cWritten)
+    if (cSrcToMix)
     {
-        rc = AudioMixBufMixToParent(&pGstStrmOut->MixBuf, cWritten, &cMixed);
+        rc = AudioMixBufMixToParentEx(&pGstStrmOut->MixBuf, 0 /* Offset */, cSrcToMix, &cSrcMixed);
+        if (RT_FAILURE(rc))
+        {
+            LogRel2(("Audio: Warning: Mixing guest audio data of '%s' to parent failed with %Rrc\n", pGstStrmOut->MixBuf.pszName, rc));
+#ifdef DEBUG_andy
+            AssertFailed();
+#endif
+        }
     }
-    else
-        cMixed = 0;
+
+    Log3Func(("[%s] cSrcMixed=%RU32\n", pGstStrmOut->MixBuf.pszName, cSrcMixed));
+
+    pGstStrmOut->tsLastWrittenNs = RTTimeNanoTS();
 
     if (RT_SUCCESS(rc))
     {
@@ -1253,13 +1293,9 @@ static DECLCALLBACK(int) drvAudioWrite(PPDMIAUDIOCONNECTOR pInterface, PPDMAUDIO
          * into the children buffer.
          */
         if (pcbWritten)
-            *pcbWritten = AUDIOMIXBUF_S2B(&pGstStrmOut->MixBuf, cMixed);
+            *pcbWritten = AUDIOMIXBUF_S2B(&pGstStrmOut->MixBuf, cSrcMixed);
     }
 
-    LogFlowFunc(("%s -> %s: Written pvBuf=%p, cbBuf=%RU32, cWritten=%RU32 (%RU32 bytes), cMixed=%RU32, rc=%Rrc\n",
-                 pGstStrmOut->MixBuf.pszName, pHstStrmOut->MixBuf.pszName, pvBuf, cbBuf, cWritten,
-                 AUDIOMIXBUF_S2B(&pGstStrmOut->MixBuf, cWritten), cMixed, rc));
-
     int rc2 = RTCritSectLeave(&pThis->CritSect);
     if (RT_SUCCESS(rc))
         rc = rc2;
@@ -1394,7 +1430,7 @@ static DECLCALLBACK(int) drvAudioQueryStatus(PPDMIAUDIOCONNECTOR pInterface,
     PPDMAUDIOHSTSTRMOUT pHstStrmOut = NULL;
     while ((pHstStrmOut = drvAudioHstFindAnyEnabledOut(pThis, pHstStrmOut)))
     {
-        cSamplesLive = AudioMixBufAvail(&pHstStrmOut->MixBuf);
+        cSamplesLive = AudioMixBufLive(&pHstStrmOut->MixBuf);
 
         /* Has this stream marked as disabled but there still were guest streams relying
          * on it? Check if this stream now can be closed and do so, if possible. */
@@ -1434,9 +1470,7 @@ static DECLCALLBACK(int) drvAudioQueryStatus(PPDMIAUDIOCONNECTOR pInterface,
                  * so that it can start writing PCM data to us. */
                 cbFree2 = RT_MIN(cbFree2, AUDIOMIXBUF_S2B_RATIO(&pGstStrmOut->MixBuf,
                                                                 AudioMixBufFree(&pGstStrmOut->MixBuf)));
-#ifdef DEBUG_andy
                 LogFlowFunc(("\t[%s] cbFreeOut=%RU32\n", pGstStrmOut->MixBuf.pszName, cbFree2));
-#endif
             }
         }
 
@@ -1451,24 +1485,33 @@ static DECLCALLBACK(int) drvAudioQueryStatus(PPDMIAUDIOCONNECTOR pInterface,
     PPDMAUDIOHSTSTRMIN pHstStrmIn = NULL;
     while ((pHstStrmIn = drvAudioFindNextEnabledHstIn(pThis, pHstStrmIn)))
     {
-        /* Call the host backend to capture the audio input data. */
-        uint32_t cSamplesCaptured;
-        int rc2 = pThis->pHostDrvAudio->pfnCaptureIn(pThis->pHostDrvAudio, pHstStrmIn,
-                                                     &cSamplesCaptured);
-        if (RT_FAILURE(rc2))
-            continue;
-
         PPDMAUDIOGSTSTRMIN pGstStrmIn = pHstStrmIn->pGstStrmIn;
         AssertPtrBreak(pGstStrmIn);
 
-        if (pGstStrmIn->State.fActive)
+        if (!pGstStrmIn->State.fActive) /* Only handle active guest streams. */
+            continue;
+
+        const uint32_t csFree     = AudioMixBufFree(&pGstStrmIn->MixBuf);
+              uint32_t csCaptured = 0;
+
+        /* Is some space left for recording in our parent buffer (guest side for recording)? */
+        if (csFree)
         {
-            cbAvailIn = RT_MAX(cbAvailIn, AUDIOMIXBUF_S2B(&pHstStrmIn->MixBuf,
-                                                          AudioMixBufMixed(&pHstStrmIn->MixBuf)));
+            /* Call the host backend to capture the audio input data. */
+            int rc2 = pThis->pHostDrvAudio->pfnCaptureIn(pThis->pHostDrvAudio, pHstStrmIn, &csCaptured);
+            if (RT_FAILURE(rc2))
+                LogRel(("Audio: Capturing from '%s' failed: %Rrc\n", pHstStrmIn->MixBuf.pszName, rc2));
+
 #ifdef DEBUG_andy
-            LogFlowFunc(("\t[%s] cbAvailIn=%RU32\n", pHstStrmIn->MixBuf.pszName, cbAvailIn));
+            AssertRC(rc2);
 #endif
         }
+
+        cbAvailIn = RT_MAX(cbAvailIn, AUDIOMIXBUF_S2B(&pGstStrmIn->MixBuf,
+                                                      AudioMixBufUsed(&pGstStrmIn->MixBuf)));
+
+        LogFlowFunc(("\t[%s] fActive=%RTbool, csFree=%RU32, csCaptured=%RU32 -> cbAvailIn=%RU32\n",
+                     pHstStrmIn->MixBuf.pszName, pGstStrmIn->State.fActive, csFree, csCaptured, cbAvailIn));
     }
 
     if (RT_SUCCESS(rc))
@@ -1507,6 +1550,8 @@ static DECLCALLBACK(int) drvAudioPlayOut(PPDMIAUDIOCONNECTOR pInterface, uint32_
     if (RT_FAILURE(rc))
         return rc;
 
+    Log2Func(("Enter\n"));
+
     /* Backend output (temporarily) disabled / unavailable? */
     if (!pThis->pHostDrvAudio->pfnIsEnabled(pThis->pHostDrvAudio, PDMAUDIODIR_OUT))
     {
@@ -1527,49 +1572,44 @@ static DECLCALLBACK(int) drvAudioPlayOut(PPDMIAUDIOCONNECTOR pInterface, uint32_
      */
     uint32_t            cSamplesPlayedMax = 0;
     PPDMAUDIOHSTSTRMOUT pHstStrmOut       = NULL;
+
     while ((pHstStrmOut = drvAudioHstFindAnyEnabledOut(pThis, pHstStrmOut)))
     {
-#if 0
-        uint32_t cStreamsLive;
-        uint32_t cSamplesLive = drvAudioHstOutSamplesLive(pHstStrmOut, &cStreamsLive);
-        if (!cStreamsLive)
-            cSamplesLive = 0;
+        if (!pHstStrmOut->tsLastPlayedNs)
+            pHstStrmOut->tsLastPlayedNs = RTTimeNanoTS();
 
-        /* Has this stream marked as disabled but there still were guest streams relying
-         * on it? Check if this stream now can be closed and do so, if possible. */
-        if (   pHstStrmOut->fPendingDisable
-            && !cStreamsLive)
-        {
-            /* Stop playing the current (pending) stream. */
-            int rc2 = pThis->pHostDrvAudio->pfnControlOut(pThis->pHostDrvAudio, pHstStrmOut,
-                                                          PDMAUDIOSTREAMCMD_DISABLE);
-            if (RT_SUCCESS(rc2))
-            {
-                pHstStrmOut->fEnabled        = false;
-                pHstStrmOut->fPendingDisable = false;
+#ifdef DEBUG
+        uint64_t tsLastPlayedDeltaMs = (RTTimeNanoTS() - pHstStrmOut->tsLastPlayedNs) / 1000 / 1000;
+        uint32_t cbElapsed           = (pHstStrmOut->Props.uHz / 1000 /* ms */) * tsLastPlayedDeltaMs * 4; /** @todo Use a define for the frame size. */
+#endif
+        uint32_t cbAvail             = AUDIOMIXBUF_S2B(&pHstStrmOut->MixBuf, AudioMixBufUsed(&pHstStrmOut->MixBuf));
 
-                LogFunc(("\t%p: Disabling stream\n", pHstStrmOut));
-            }
-            else
-                LogFunc(("\t%p: Backend vetoed against closing output stream, rc=%Rrc\n",
-                         pHstStrmOut, rc2));
+        Log2Func(("[%s] %RU64ms (%zu bytes) elapsed, %zu bytes available\n",
+                  pHstStrmOut->MixBuf.pszName, tsLastPlayedDeltaMs, cbElapsed, cbAvail));
 
+        if (!cbAvail) /* Nothing to play back? Skip. */
             continue;
-        }
-#endif
 
         uint32_t cSamplesPlayed = 0;
         int rc2 = pThis->pHostDrvAudio->pfnPlayOut(pThis->pHostDrvAudio, pHstStrmOut, &cSamplesPlayed);
         if (RT_FAILURE(rc2))
         {
+            if (RT_FAILURE(rc2))
+                LogRel2(("Audio: Playback of '%s' failed: %Rrc\n", pHstStrmOut->MixBuf.pszName, rc2));
+
+#ifdef DEBUG_andy
+            AssertRC(rc2);
+#endif
             rc2 = pThis->pHostDrvAudio->pfnControlOut(pThis->pHostDrvAudio, pHstStrmOut, PDMAUDIOSTREAMCMD_DISABLE);
             AssertRC(rc2);
+            break;
         }
-        else
-            cSamplesPlayedMax = RT_MAX(cSamplesPlayed, cSamplesPlayedMax);
 
-        LogFlowFunc(("\t[%s] cSamplesPlayed=%RU32, cSamplesPlayedMax=%RU32, rc=%Rrc\n",
-                     pHstStrmOut->MixBuf.pszName, cSamplesPlayed, cSamplesPlayedMax, rc2));
+        if (cSamplesPlayed)
+            Log2Func(("[%s] %RU32 samples played (%zu bytes)\n",
+                      pHstStrmOut->MixBuf.pszName, cSamplesPlayed, AUDIOMIXBUF_S2B(&pHstStrmOut->MixBuf, cSamplesPlayed)));
+
+        pHstStrmOut->tsLastPlayedNs = RTTimeNanoTS();
 
         bool fNeedsCleanup = false;
 
@@ -1580,6 +1620,11 @@ static DECLCALLBACK(int) drvAudioPlayOut(PPDMIAUDIOCONNECTOR pInterface, uint32_
                 && pGstStrmOut->State.fEmpty)
                 continue;
 
+            Log2Func(("\t[%s] Current playback delay: %RU64ms\n",
+                      pGstStrmOut->MixBuf.pszName, (pHstStrmOut->tsLastPlayedNs - pGstStrmOut->tsLastWrittenNs) / 1000 / 1000));
+
+            Log2Func(("\t[%s] %RU32 samples left\n", pGstStrmOut->MixBuf.pszName, AudioMixBufUsed(&pGstStrmOut->MixBuf)));
+
             if (AudioMixBufIsEmpty(&pGstStrmOut->MixBuf))
             {
                 pGstStrmOut->State.fEmpty = true;
@@ -1603,6 +1648,8 @@ static DECLCALLBACK(int) drvAudioPlayOut(PPDMIAUDIOCONNECTOR pInterface, uint32_
             *pcSamplesPlayed = cSamplesPlayedMax;
     }
 
+    Log2Func(("Leave\n"));
+
     int rc2 = RTCritSectLeave(&pThis->CritSect);
     if (RT_SUCCESS(rc))
         rc = rc2;
@@ -1879,8 +1926,6 @@ static DECLCALLBACK(int) drvAudioInit(PCFGMNODE pCfgHandle, PPDMDRVINS pDrvIns)
     AssertPtrReturn(pCfgHandle, VERR_INVALID_POINTER);
     AssertPtrReturn(pDrvIns, VERR_INVALID_POINTER);
 
-    LogRel(("Audio: Using VBox 5.0.x audio code!\n"));
-
     PDRVAUDIO pThis = PDMINS_2_DATA(pDrvIns, PDRVAUDIO);
     LogFlowFunc(("pDrvAudio=%p, pDrvIns=%p\n", pThis, pDrvIns));
 
@@ -1932,6 +1977,8 @@ static DECLCALLBACK(int) drvAudioRead(PPDMIAUDIOCONNECTOR pInterface, PPDMAUDIOG
     if (RT_FAILURE(rc))
         return rc;
 
+    LogFlowFuncEnter();
+
     if (!pThis->pHostDrvAudio->pfnIsEnabled(pThis->pHostDrvAudio, PDMAUDIODIR_IN))
     {
         if (pcbRead)
@@ -1946,27 +1993,52 @@ static DECLCALLBACK(int) drvAudioRead(PPDMIAUDIOCONNECTOR pInterface, PPDMAUDIOG
     AssertMsg(pGstStrmIn->pHstStrmIn->fStatus & PDMAUDIOSTRMSTS_FLAG_ENABLED,
               ("Reading from disabled host input stream \"%s\" not possible\n", pGstStrmIn->MixBuf.pszName));
 
+    uint32_t cReadTotal = 0;
+
     /*
      * Read from the parent buffer (that is, the guest buffer) which
      * should have the audio data in the format the guest needs.
      */
-    uint32_t cRead;
-    rc = AudioMixBufReadCirc(&pGstStrmIn->MixBuf, pvBuf, cbBuf, &cRead);
-    if (RT_SUCCESS(rc))
+    uint32_t cToRead = RT_MIN(AUDIOMIXBUF_B2S(&pGstStrmIn->MixBuf, cbBuf), AudioMixBufUsed(&pGstStrmIn->MixBuf));
+    while (cToRead)
     {
-        AudioMixBufFinish(&pGstStrmIn->MixBuf, cRead);
+        uint32_t cRead;
+        rc = AudioMixBufReadCirc(&pGstStrmIn->MixBuf, (uint8_t *)pvBuf + AUDIOMIXBUF_S2B(&pGstStrmIn->MixBuf, cReadTotal),
+                                 AUDIOMIXBUF_S2B(&pGstStrmIn->MixBuf, cToRead), &cRead);
+        if (RT_FAILURE(rc))
+            break;
 
-        if (pcbRead)
-            *pcbRead = AUDIOMIXBUF_S2B(&pGstStrmIn->MixBuf, cRead);
+        Assert(cToRead >= cRead);
+        cToRead -= cRead;
+
+        cReadTotal += cRead;
     }
 
-    LogFlowFunc(("cRead=%RU32 (%RU32 bytes), rc=%Rrc\n",
-                 cRead, AUDIOMIXBUF_S2B(&pGstStrmIn->MixBuf, cRead), rc));
+    if (cReadTotal)
+        AudioMixBufFinish(&pGstStrmIn->MixBuf, cReadTotal);
+
+    const uint32_t cbReadTotal = AUDIOMIXBUF_S2B(&pGstStrmIn->MixBuf, cReadTotal);
+
+#ifdef VBOX_AUDIO_DEBUG_DUMP_PCM_DATA
+    if (cbReadTotal)
+    {
+        RTFILE fh;
+        RTFileOpen(&fh, VBOX_AUDIO_DEBUG_DUMP_PCM_DATA_PATH "drvAudioRead.pcm",
+                   RTFILE_O_OPEN_CREATE | RTFILE_O_APPEND | RTFILE_O_WRITE | RTFILE_O_DENY_NONE);
+        RTFileWrite(fh, pvBuf, cbReadTotal, NULL);
+        RTFileClose(fh);
+    }
+#endif
+
+    LogFlowFunc(("cReadTotal=%RU32 (%RU32 bytes), rc=%Rrc\n", cReadTotal, cbReadTotal, rc));
 
     int rc2 = RTCritSectLeave(&pThis->CritSect);
     if (RT_SUCCESS(rc))
         rc = rc2;
 
+    if (pcbRead)
+        *pcbRead = cbReadTotal;
+
     return rc;
 }
 
@@ -2034,7 +2106,7 @@ static DECLCALLBACK(int) drvAudioEnableOut(PPDMIAUDIOCONNECTOR pInterface,
         if (RT_SUCCESS(rc))
             pGstStrmOut->State.fActive = fEnable;
 
-        LogFlowFunc(("%s: fEnable=%RTbool, fStatus=0x%x, rc=%Rrc\n",
+        LogFlowFunc(("[%s] fEnable=%RTbool, fStatus=0x%x, rc=%Rrc\n",
                      pGstStrmOut->MixBuf.pszName, fEnable, pHstStrmOut->fStatus, rc));
     }
 
@@ -2056,14 +2128,14 @@ static DECLCALLBACK(int) drvAudioEnableIn(PPDMIAUDIOCONNECTOR pInterface,
         PPDMAUDIOHSTSTRMIN pHstStrmIn = pGstStrmIn->pHstStrmIn;
         AssertPtr(pHstStrmIn);
 
-        LogFlowFunc(("%s: fEnable=%RTbool\n", pGstStrmIn->MixBuf.pszName, fEnable));
+        LogFlowFunc(("[%s] fEnable=%RTbool\n", pGstStrmIn->MixBuf.pszName, fEnable));
 
         rc = drvAudioControlHstIn(pThis, pHstStrmIn,
                                   fEnable ? PDMAUDIOSTREAMCMD_ENABLE : PDMAUDIOSTREAMCMD_DISABLE);
         if (RT_SUCCESS(rc))
             pGstStrmIn->State.fActive = fEnable;
 
-        LogFlowFunc(("%s: fEnable=%RTbool, rc=%Rrc\n", pGstStrmIn->MixBuf.pszName, fEnable, rc));
+        LogFlowFunc(("[%s] fEnable=%RTbool, rc=%Rrc\n", pGstStrmIn->MixBuf.pszName, fEnable, rc));
     }
 
     return rc;
@@ -2595,7 +2667,7 @@ const PDMDRVREG g_DrvAUDIO =
     /* fClass */
     PDM_DRVREG_CLASS_AUDIO,
     /* cMaxInstances */
-    2,
+    UINT32_MAX,
     /* cbInstance */
     sizeof(DRVAUDIO),
     /* pfnConstruct */
diff --git a/src/VBox/Devices/Audio/DrvAudio.h b/src/VBox/Devices/Audio/DrvAudio.h
index e48c62a..88abbd8 100644
--- a/src/VBox/Devices/Audio/DrvAudio.h
+++ b/src/VBox/Devices/Audio/DrvAudio.h
@@ -4,7 +4,7 @@
  */
 
 /*
- * Copyright (C) 2006-2016 Oracle Corporation
+ * Copyright (C) 2006-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;
@@ -47,11 +47,26 @@
 
 #include <iprt/circbuf.h>
 #include <iprt/critsect.h>
+#include <iprt/dir.h>
+#include <iprt/file.h>
+#include <iprt/path.h>
 
 #include <VBox/vmm/pdmdev.h>
 #include <VBox/vmm/pdm.h>
 #include <VBox/vmm/pdmaudioifs.h>
 
+#ifdef DEBUG_andy
+# define VBOX_AUDIO_DEBUG_DUMP_PCM_DATA
+#endif
+
+#ifdef VBOX_AUDIO_DEBUG_DUMP_PCM_DATA
+# ifdef RT_OS_WINDOWS
+#  define VBOX_AUDIO_DEBUG_DUMP_PCM_DATA_PATH "c:\\temp\\"
+# else
+#  define VBOX_AUDIO_DEBUG_DUMP_PCM_DATA_PATH "/tmp/"
+# endif
+#endif /* VBOX_AUDIO_DEBUG_DUMP_PCM_DATA */
+
 typedef enum
 {
     AUD_OPT_INT,
@@ -115,8 +130,10 @@ typedef struct DRVAUDIO
 const char *drvAudioHlpFormatToString(PDMAUDIOFMT enmFormat);
 const char *drvAudioRecSourceToString(PDMAUDIORECSOURCE enmRecSource);
 PDMAUDIOFMT drvAudioHlpStringToFormat(const char *pszFormat);
+int DrvAudioHlpGetFileName(char *pszFile, size_t cchFile, const char *pszPath, const char *pszName);
 
-bool drvAudioPCMPropsAreEqual(PPDMPCMPROPS info, PPDMAUDIOSTREAMCFG pCfg);
+bool drvAudioPCMPropsAreEqual(PPDMAUDIOPCMPROPS info, PPDMAUDIOSTREAMCFG pCfg);
+bool DrvAudioHlpPCMPropsAreValid(const PPDMAUDIOPCMPROPS pProps);
 void drvAudioStreamCfgPrint(PPDMAUDIOSTREAMCFG pCfg);
 
 /* AUDIO IN function declarations. */
@@ -150,7 +167,7 @@ int drvAudioHlpPcmHwAddOut(PDRVAUDIO pDrvAudio, PPDMAUDIOSTREAMCFG pCfg, PPDMAUD
 int drvAudioHlpPcmCreateVoicePairOut(PDRVAUDIO pDrvAudio, const char *pszName, PPDMAUDIOSTREAMCFG pCfg, PPDMAUDIOGSTSTRMOUT *ppGstStrmOut);
 
 /* Common functions between DrvAudio and backends (host audio drivers). */
-void DrvAudioClearBuf(PPDMPCMPROPS pPCMInfo, void *pvBuf, size_t cbBuf, uint32_t cSamples);
-int DrvAudioStreamCfgToProps(PPDMAUDIOSTREAMCFG pCfg, PPDMPCMPROPS pProps);
+void DrvAudioClearBuf(PPDMAUDIOPCMPROPS pPCMInfo, void *pvBuf, size_t cbBuf, uint32_t cSamples);
+int DrvAudioStreamCfgToProps(PPDMAUDIOSTREAMCFG pCfg, PPDMAUDIOPCMPROPS pProps);
 
 #endif /* DRV_AUDIO_H */
diff --git a/src/VBox/Devices/Audio/DrvAudioCommon.cpp b/src/VBox/Devices/Audio/DrvAudioCommon.cpp
index 12c1e2c..b17bdbb 100644
--- a/src/VBox/Devices/Audio/DrvAudioCommon.cpp
+++ b/src/VBox/Devices/Audio/DrvAudioCommon.cpp
@@ -60,7 +60,7 @@
 #include "DrvAudio.h"
 #include "AudioMixBuffer.h"
 
-bool drvAudioPCMPropsAreEqual(PPDMPCMPROPS pProps, PPDMAUDIOSTREAMCFG pCfg);
+bool drvAudioPCMPropsAreEqual(PPDMAUDIOPCMPROPS pProps, PPDMAUDIOSTREAMCFG pCfg);
 
 const char *drvAudioRecSourceToString(PDMAUDIORECSOURCE enmRecSource)
 {
@@ -269,7 +269,7 @@ uint32_t drvAudioGstOutGetFreeBytes(PPDMAUDIOGSTSTRMOUT pGstStrmOut)
 }
 #endif
 
-bool drvAudioPCMPropsAreEqual(PPDMPCMPROPS pProps, PPDMAUDIOSTREAMCFG pCfg)
+bool drvAudioPCMPropsAreEqual(PPDMAUDIOPCMPROPS pProps, PPDMAUDIOSTREAMCFG pCfg)
 {
     int cBits = 8;
     bool fSigned = false;
@@ -278,17 +278,20 @@ bool drvAudioPCMPropsAreEqual(PPDMPCMPROPS pProps, PPDMAUDIOSTREAMCFG pCfg)
     {
         case AUD_FMT_S8:
             fSigned = true;
+            /* fall thru */
         case AUD_FMT_U8:
             break;
 
         case AUD_FMT_S16:
             fSigned = true;
+            /* fall thru */
         case AUD_FMT_U16:
             cBits = 16;
             break;
 
         case AUD_FMT_S32:
             fSigned = true;
+            /* fall thru */
         case AUD_FMT_U32:
             cBits = 32;
             break;
@@ -309,13 +312,55 @@ bool drvAudioPCMPropsAreEqual(PPDMPCMPROPS pProps, PPDMAUDIOSTREAMCFG pCfg)
 }
 
 /**
+ * Checks whether given PCM properties are valid or not.
+ *
+ * Returns @c true if properties are valid, @c false if not.
+ * @param   pProps              PCM properties to check.
+ *
+ * @remarks Does *not* support surround (> 2 channels) yet! This is intentional, as
+ *          we consider surround support as experimental / not enabled by default for now.
+ */
+bool DrvAudioHlpPCMPropsAreValid(const PPDMAUDIOPCMPROPS pProps)
+{
+    AssertPtrReturn(pProps, false);
+
+    bool fValid = (   pProps->cChannels == 1
+                   || pProps->cChannels == 2); /* Either stereo (2) or mono (1), per stream. */
+
+    if (fValid)
+    {
+        switch (pProps->cBits)
+        {
+            case 8:
+            case 16:
+            /** @todo Do we need support for 24-bit samples? */
+            case 32:
+                break;
+            default:
+                fValid = false;
+                break;
+        }
+    }
+
+    if (!fValid)
+        return false;
+
+    fValid &= pProps->uHz > 0;
+    fValid &= pProps->cShift == PDMAUDIOPCMPROPS_MAKE_SHIFT_PARMS(pProps->cBits, pProps->cChannels);
+
+    fValid &= pProps->fSwapEndian == false; /** @todo Handling Big Endian audio data is not supported yet. */
+
+    return fValid;
+}
+
+/**
  * Converts an audio stream configuration to matching PCM properties.
  *
  * @return  IPRT status code.
  * @param   pCfg                    Audio stream configuration to convert.
  * @param   pProps                  PCM properties to save result to.
  */
-int DrvAudioStreamCfgToProps(PPDMAUDIOSTREAMCFG pCfg, PPDMPCMPROPS pProps)
+int DrvAudioStreamCfgToProps(PPDMAUDIOSTREAMCFG pCfg, PPDMAUDIOPCMPROPS pProps)
 {
     AssertPtrReturn(pCfg,   VERR_INVALID_POINTER);
     AssertPtrReturn(pProps, VERR_INVALID_POINTER);
@@ -329,11 +374,13 @@ int DrvAudioStreamCfgToProps(PPDMAUDIOSTREAMCFG pCfg, PPDMPCMPROPS pProps)
     {
         case AUD_FMT_S8:
             fSigned = true;
+            /* fall thru */
         case AUD_FMT_U8:
             break;
 
         case AUD_FMT_S16:
             fSigned = true;
+            /* fall thru */
         case AUD_FMT_U16:
             cBits = 16;
             cShift = 1;
@@ -341,6 +388,7 @@ int DrvAudioStreamCfgToProps(PPDMAUDIOSTREAMCFG pCfg, PPDMPCMPROPS pProps)
 
         case AUD_FMT_S32:
             fSigned = true;
+            /* fall thru */
         case AUD_FMT_U32:
             cBits = 32;
             cShift = 2;
@@ -411,3 +459,111 @@ void drvAudioStreamCfgPrint(PPDMAUDIOSTREAMCFG pCfg)
             break;
     }
 }
+
+/**
+* Sanitizes the file name component so that unsupported characters
+* will be replaced by an underscore ("_").
+*
+* @return  IPRT status code.
+* @param   pszPath             Path to sanitize.
+* @param   cbPath              Size (in bytes) of path to sanitize.
+*/
+int DrvAudioHlpSanitizeFileName(char *pszPath, size_t cbPath)
+{
+    RT_NOREF(cbPath);
+    int rc = VINF_SUCCESS;
+#ifdef RT_OS_WINDOWS
+    /* Filter out characters not allowed on Windows platforms, put in by
+    RTTimeSpecToString(). */
+    /** @todo Use something like RTPathSanitize() if available later some time. */
+    static RTUNICP const s_uszValidRangePairs[] =
+    {
+        ' ', ' ',
+        '(', ')',
+        '-', '.',
+        '0', '9',
+        'A', 'Z',
+        'a', 'z',
+        '_', '_',
+        0xa0, 0xd7af,
+        '\0'
+    };
+    ssize_t cReplaced = RTStrPurgeComplementSet(pszPath, s_uszValidRangePairs, '_' /* Replacement */);
+    if (cReplaced < 0)
+        rc = VERR_INVALID_UTF8_ENCODING;
+#else
+    RT_NOREF(pszPath);
+#endif
+    return rc;
+}
+
+/**
+* Constructs an unique file name, based on the given path and the audio file type.
+*
+* @returns IPRT status code.
+* @param   pszFile             Where to store the constructed file name.
+* @param   cchFile             Size (in characters) of the file name buffer.
+* @param   pszPath             Base path to use.
+* @param   pszName             A name for better identifying the file. Optional.
+*/
+int DrvAudioHlpGetFileName(char *pszFile, size_t cchFile, const char *pszPath, const char *pszName)
+{
+    AssertPtrReturn(pszFile, VERR_INVALID_POINTER);
+    AssertReturn(cchFile, VERR_INVALID_PARAMETER);
+    AssertPtrReturn(pszPath, VERR_INVALID_POINTER);
+    int rc;
+
+    do
+    {
+        char szFilePath[RTPATH_MAX];
+        RTStrPrintf(szFilePath, sizeof(szFilePath), "%s", pszPath);
+
+        /* Create it when necessary. */
+        if (!RTDirExists(szFilePath))
+        {
+            rc = RTDirCreateFullPath(szFilePath, RTFS_UNIX_IRWXU);
+            if (RT_FAILURE(rc))
+                break;
+        }
+
+        /* The actually drop directory consist of the current time stamp and a
+        * unique number when necessary. */
+        char pszTime[64];
+        RTTIMESPEC time;
+        if (!RTTimeSpecToString(RTTimeNow(&time), pszTime, sizeof(pszTime)))
+        {
+            rc = VERR_BUFFER_OVERFLOW;
+            break;
+        }
+
+        rc = DrvAudioHlpSanitizeFileName(pszTime, sizeof(pszTime));
+        if (RT_FAILURE(rc))
+            break;
+
+        rc = RTPathAppend(szFilePath, sizeof(szFilePath), pszTime);
+        if (RT_FAILURE(rc))
+            break;
+
+        if (pszName) /* Optional name given? */
+        {
+            rc = RTStrCat(szFilePath, sizeof(szFilePath), "-");
+            if (RT_FAILURE(rc))
+                break;
+
+            rc = RTStrCat(szFilePath, sizeof(szFilePath), pszName);
+            if (RT_FAILURE(rc))
+                break;
+        }
+
+        rc = RTStrCat(szFilePath, sizeof(szFilePath), ".wav");
+
+        if (RT_FAILURE(rc))
+            break;
+
+        RTStrPrintf(pszFile, cchFile, "%s", szFilePath);
+
+    } while (0);
+
+    LogFlowFuncLeaveRC(rc);
+    return rc;
+}
diff --git a/src/VBox/Devices/Audio/DrvHostALSAAudio.cpp b/src/VBox/Devices/Audio/DrvHostALSAAudio.cpp
index 23b4c3a..60732a3 100644
--- a/src/VBox/Devices/Audio/DrvHostALSAAudio.cpp
+++ b/src/VBox/Devices/Audio/DrvHostALSAAudio.cpp
@@ -4,7 +4,7 @@
  */
 
 /*
- * Copyright (C) 2006-2015 Oracle Corporation
+ * Copyright (C) 2006-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;
@@ -754,6 +754,11 @@ static DECLCALLBACK(int) drvHostALSAAudioInit(PPDMIHOSTAUDIO pInterface)
 
     LogFlowFuncEnter();
 
+#ifdef VBOX_AUDIO_DEBUG_DUMP_PCM_DATA
+    RTFileDelete(VBOX_AUDIO_DEBUG_DUMP_PCM_DATA_PATH "alsaCaptureIn.pcm");
+    RTFileDelete(VBOX_AUDIO_DEBUG_DUMP_PCM_DATA_PATH "alsaPlayOut.pcm");
+#endif
+
     int rc = audioLoadAlsaLib();
     if (RT_FAILURE(rc))
         LogRel(("ALSA: Failed to load the ALSA shared library, rc=%Rrc\n", rc));
@@ -815,26 +820,14 @@ static DECLCALLBACK(int) drvHostALSAAudioCaptureIn(PPDMIHOSTAUDIO pInterface, PP
         }
     }
 
-    /*
-     * Check how much we can read from the capture device without overflowing
-     * the mixer buffer.
-     */
-    Assert(cAvail);
-    size_t cbMixFree = AudioMixBufFreeBytes(&pHstStrmIn->MixBuf);
-    size_t cbToRead = RT_MIN((size_t)AUDIOMIXBUF_S2B(&pHstStrmIn->MixBuf, cAvail), cbMixFree);
-
-    LogFlowFunc(("cbToRead=%zu, cAvail=%RI32\n", cbToRead, cAvail));
+    uint32_t cMixedTotal = 0;
 
-    uint32_t cWrittenTotal = 0;
-    snd_pcm_uframes_t cToRead;
+    snd_pcm_uframes_t cToRead = cAvail;
     snd_pcm_sframes_t cRead;
 
-    while (   cbToRead
+    while (   cToRead
            && RT_SUCCESS(rc))
     {
-        cToRead = RT_MIN(AUDIOMIXBUF_B2S(&pHstStrmIn->MixBuf, cbToRead),
-                         AUDIOMIXBUF_B2S(&pHstStrmIn->MixBuf, pThisStrmIn->cbBuf));
-        AssertBreakStmt(cToRead, rc = VERR_NO_DATA);
         cRead = snd_pcm_readi(pThisStrmIn->phPCM, pThisStrmIn->pvBuf, cToRead);
         if (cRead <= 0)
         {
@@ -854,7 +847,7 @@ static DECLCALLBACK(int) drvHostALSAAudioCaptureIn(PPDMIHOSTAUDIO pInterface, PP
                      * available at the moment, try later. As we might have read some frames
                      * already these need to be processed instead.
                      */
-                    cbToRead = 0;
+                    cToRead = 0;
                     break;
                 }
 
@@ -878,40 +871,36 @@ static DECLCALLBACK(int) drvHostALSAAudioCaptureIn(PPDMIHOSTAUDIO pInterface, PP
         }
         else
         {
+#ifdef VBOX_AUDIO_DEBUG_DUMP_PCM_DATA
+            RTFILE fh;
+            RTFileOpen(&fh, VBOX_AUDIO_DEBUG_DUMP_PCM_DATA_PATH "alsaCaptureIn.pcm",
+                       RTFILE_O_OPEN_CREATE | RTFILE_O_APPEND | RTFILE_O_WRITE | RTFILE_O_DENY_NONE);
+            RTFileWrite(fh, pThisStrmIn->pvBuf, AUDIOMIXBUF_S2B(&pHstStrmIn->MixBuf, cRead), NULL);
+            RTFileClose(fh);
+#endif
             uint32_t cWritten;
-            rc = AudioMixBufWriteCirc(&pHstStrmIn->MixBuf,
-                                      pThisStrmIn->pvBuf, AUDIOMIXBUF_S2B(&pHstStrmIn->MixBuf, cRead),
-                                      &cWritten);
+            rc = AudioMixBufWriteAt(&pHstStrmIn->MixBuf, 0 /* Offset */,
+                                    pThisStrmIn->pvBuf, AUDIOMIXBUF_S2B(&pHstStrmIn->MixBuf, cRead),
+                                    &cWritten);
             if (RT_FAILURE(rc))
                 break;
 
-            /*
-             * We should not run into a full mixer buffer or we loose samples and
-             * run into an endless loop if ALSA keeps producing samples ("null"
-             * capture device for example).
-             */
-            AssertLogRelMsgBreakStmt(cWritten > 0, ("Mixer buffer shouldn't be full at this point!\n"),
-                                     rc = VERR_INTERNAL_ERROR);
-            uint32_t cbWritten = AUDIOMIXBUF_S2B(&pHstStrmIn->MixBuf, cWritten);
-
-            Assert(cbToRead >= cbWritten);
-            cbToRead -= cbWritten;
-            cWrittenTotal += cWritten;
+            uint32_t cMixed = 0;
+            rc = AudioMixBufMixToParentEx(&pHstStrmIn->MixBuf, 0 /* Offset */, cWritten, &cMixed);
+            if (RT_FAILURE(rc))
+                break;
+
+            Assert(cToRead >= cWritten);
+            cToRead -= cWritten;
+
+            cMixedTotal += cMixed;
         }
     }
 
     if (RT_SUCCESS(rc))
     {
-        uint32_t cProcessed = 0;
-        if (cWrittenTotal)
-            rc = AudioMixBufMixToParent(&pHstStrmIn->MixBuf, cWrittenTotal,
-                                        &cProcessed);
-
         if (pcSamplesCaptured)
-            *pcSamplesCaptured = cWrittenTotal;
-
-        LogFlowFunc(("cWrittenTotal=%RU32 (%RU32 processed), rc=%Rrc\n",
-                     cWrittenTotal, cProcessed, rc));
+            *pcSamplesCaptured = cMixedTotal;
     }
 
     LogFlowFuncLeaveRC(rc);
@@ -942,21 +931,29 @@ static DECLCALLBACK(int) drvHostALSAAudioPlayOut(PPDMIHOSTAUDIO pInterface, PPDM
         size_t cbToRead = RT_MIN(AUDIOMIXBUF_S2B(&pHstStrmOut->MixBuf,
                                                  (uint32_t)cAvail), /* cAvail is always >= 0 */
                                  AUDIOMIXBUF_S2B(&pHstStrmOut->MixBuf,
-                                                 AudioMixBufAvail(&pHstStrmOut->MixBuf)));
-        LogFlowFunc(("cbToRead=%zu, cbAvail=%zu\n",
-                     cbToRead, AUDIOMIXBUF_S2B(&pHstStrmOut->MixBuf, cAvail)));
+                                                 AudioMixBufLive(&pHstStrmOut->MixBuf)));
+
+        Log2Func(("cLive=%zu, cAvail=%zu\n", AudioMixBufLive(&pHstStrmOut->MixBuf), cAvail));
 
         uint32_t cRead, cbRead;
         snd_pcm_sframes_t cWritten;
         while (cbToRead)
         {
-            rc = AudioMixBufReadCirc(&pHstStrmOut->MixBuf, pThisStrmOut->pvBuf, cbToRead, &cRead);
+            rc = AudioMixBufReadCirc(&pHstStrmOut->MixBuf, pThisStrmOut->pvBuf, RT_MIN(pThisStrmOut->cbBuf, cbToRead), &cRead);
             if (RT_FAILURE(rc))
                 break;
 
+            AssertBreak(cRead);
             cbRead = AUDIOMIXBUF_S2B(&pHstStrmOut->MixBuf, cRead);
             AssertBreak(cbRead);
 
+#ifdef VBOX_AUDIO_DEBUG_DUMP_PCM_DATA
+            RTFILE fh;
+            RTFileOpen(&fh, VBOX_AUDIO_DEBUG_DUMP_PCM_DATA_PATH "alsaPlayOut.pcm",
+                       RTFILE_O_OPEN_CREATE | RTFILE_O_APPEND | RTFILE_O_WRITE | RTFILE_O_DENY_NONE);
+            RTFileWrite(fh, pThisStrmOut->pvBuf, cbRead, NULL);
+            RTFileClose(fh);
+#endif
             /* Don't try infinitely on recoverable errors. */
             unsigned iTry;
             for (iTry = 0; iTry < ALSA_RECOVERY_TRIES_MAX; iTry++)
@@ -964,6 +961,8 @@ static DECLCALLBACK(int) drvHostALSAAudioPlayOut(PPDMIHOSTAUDIO pInterface, PPDM
                 cWritten = snd_pcm_writei(pThisStrmOut->phPCM, pThisStrmOut->pvBuf, cRead);
                 if (cWritten <= 0)
                 {
+                    LogRel2(("ALSA: Write #%u failed with: %s\n",  iTry, snd_strerror(cWritten)));
+
                     switch (cWritten)
                     {
                         case 0:
@@ -979,7 +978,7 @@ static DECLCALLBACK(int) drvHostALSAAudioPlayOut(PPDMIHOSTAUDIO pInterface, PPDM
                             if (RT_FAILURE(rc))
                                 break;
 
-                            LogFlowFunc(("Recovered from playback\n"));
+                            LogFunc(("Recovered from playback\n"));
                             continue;
                         }
 
@@ -993,15 +992,16 @@ static DECLCALLBACK(int) drvHostALSAAudioPlayOut(PPDMIHOSTAUDIO pInterface, PPDM
                                 break;
                             }
 
-                            LogFlowFunc(("Resumed suspended output stream\n"));
+                            LogFunc(("Resumed suspended output stream\n"));
                             continue;
                         }
 
-                        default:
-                            LogFlowFunc(("Failed to write %RI32 output frames, rc=%Rrc\n",
-                                         cRead, rc));
+                       default:
+                       {
                             rc = VERR_GENERAL_FAILURE; /** @todo */
+                            LogFunc(("Failed to write %RI32 output frames, rc=%Rrc\n", cRead, rc));
                             break;
+                       }
                     }
                 }
                 else
@@ -1022,18 +1022,15 @@ static DECLCALLBACK(int) drvHostALSAAudioPlayOut(PPDMIHOSTAUDIO pInterface, PPDM
     }
     while (0);
 
-    if (RT_SUCCESS(rc))
-    {
-        uint32_t cReadTotal = AUDIOMIXBUF_B2S(&pHstStrmOut->MixBuf, cbReadTotal);
-        if (cReadTotal)
-            AudioMixBufFinish(&pHstStrmOut->MixBuf, cReadTotal);
+    uint32_t cReadTotal = AUDIOMIXBUF_B2S(&pHstStrmOut->MixBuf, cbReadTotal);
 
-        if (pcSamplesPlayed)
-            *pcSamplesPlayed = cReadTotal;
+    if (cReadTotal)
+        AudioMixBufFinish(&pHstStrmOut->MixBuf, cReadTotal);
 
-        LogFlowFunc(("cReadTotal=%RU32 (%RU32 bytes), rc=%Rrc\n",
-                     cReadTotal, cbReadTotal, rc));
-    }
+    if (pcSamplesPlayed)
+        *pcSamplesPlayed = cReadTotal;
+
+    Log2Func(("cReadTotal=%RU32 (%RU32 bytes), rc=%Rrc\n", cReadTotal, cbReadTotal, rc));
 
     LogFlowFuncLeaveRC(rc);
     return rc;
@@ -1394,32 +1391,3 @@ const PDMDRVREG g_DrvHostALSAAudio =
     PDM_DRVREG_VERSION
 };
 
-#if 0 // unused
-static struct audio_option alsa_options[] =
-{
-    {"DACSizeInUsec", AUD_OPT_BOOL, &s_ALSAConf.size_in_usec_out,
-     "DAC period/buffer size in microseconds (otherwise in frames)", NULL, 0},
-    {"DACPeriodSize", AUD_OPT_INT, &s_ALSAConf.period_size_out,
-     "DAC period size", &s_ALSAConf.period_size_out_overriden, 0},
-    {"DACBufferSize", AUD_OPT_INT, &s_ALSAConf.buffer_size_out,
-     "DAC buffer size", &s_ALSAConf.buffer_size_out_overriden, 0},
-
-    {"ADCSizeInUsec", AUD_OPT_BOOL, &s_ALSAConf.size_in_usec_in,
-     "ADC period/buffer size in microseconds (otherwise in frames)", NULL, 0},
-    {"ADCPeriodSize", AUD_OPT_INT, &s_ALSAConf.period_size_in,
-     "ADC period size", &s_ALSAConf.period_size_in_overriden, 0},
-    {"ADCBufferSize", AUD_OPT_INT, &s_ALSAConf.buffer_size_in,
-     "ADC buffer size", &s_ALSAConf.buffer_size_in_overriden, 0},
-
-    {"Threshold", AUD_OPT_INT, &s_ALSAConf.threshold,
-     "(undocumented)", NULL, 0},
-
-    {"DACDev", AUD_OPT_STR, &s_ALSAConf.pcm_name_out,
-     "DAC device name (for instance dmix)", NULL, 0},
-
-    {"ADCDev", AUD_OPT_STR, &s_ALSAConf.pcm_name_in,
-     "ADC device name", NULL, 0},
-
-    NULL
-};
-#endif
diff --git a/src/VBox/Devices/Audio/DrvHostCoreAudio.cpp b/src/VBox/Devices/Audio/DrvHostCoreAudio.cpp
index 11daedf..08ac511 100644
--- a/src/VBox/Devices/Audio/DrvHostCoreAudio.cpp
+++ b/src/VBox/Devices/Audio/DrvHostCoreAudio.cpp
@@ -4,7 +4,7 @@
  */
 
 /*
- * Copyright (C) 2010-2016 Oracle Corporation
+ * Copyright (C) 2010-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;
@@ -40,16 +40,6 @@
 #define AQ_BUF_TOTAL    (AQ_BUF_COUNT * AQ_BUF_SIZE)
 #define AQ_BUF_SAMPLES  (AQ_BUF_TOTAL / 4)  /* Hardcoded 4 bytes per sample! */
 
-#if 0
-# include <iprt/file.h>
-# define DEBUG_DUMP_PCM_DATA
-# ifdef RT_OS_WINDOWS
-#  define DEBUG_DUMP_PCM_DATA_PATH "c:\\temp\\"
-# else
-#  define DEBUG_DUMP_PCM_DATA_PATH "/tmp/"
-# endif
-#endif
-
 /* Enables utilizing the Core Audio converter unit for converting
  * input / output from/to our requested formats. That might be more
  * performant than using our own routines later down the road. */
@@ -57,8 +47,8 @@
 //# define VBOX_WITH_AUDIO_CA_CONVERTER
 
 #ifdef DEBUG_andy
-# undef  DEBUG_DUMP_PCM_DATA_PATH
-# define DEBUG_DUMP_PCM_DATA_PATH "/Users/anloeffl/Documents/"
+# undef  VBOX_AUDIO_DEBUG_DUMP_PCM_DATA_PATH
+# define VBOX_AUDIO_DEBUG_DUMP_PCM_DATA_PATH "/Users/anloeffl/Documents/"
 # undef  VBOX_WITH_AUDIO_CA_CONVERTER
 #endif
 
@@ -126,7 +116,7 @@ static void drvHostCoreAudioPrintASBD(const char *pszDesc, const AudioStreamBasi
     LogRel2(("CoreAudio:\tBytesPerPacket  : %RU32\n", pASBD->mBytesPerPacket));
 }
 
-static int drvHostCoreAudioPCMPropsToASBD(PPDMPCMPROPS pPCMProps, AudioStreamBasicDescription *pASBD)
+static int drvHostCoreAudioPCMPropsToASBD(PPDMAUDIOPCMPROPS pPCMProps, AudioStreamBasicDescription *pASBD)
 {
     AssertPtrReturn(pPCMProps, VERR_INVALID_PARAMETER);
     AssertPtrReturn(pASBD,     VERR_INVALID_PARAMETER);
@@ -152,7 +142,7 @@ static int drvHostCoreAudioStreamCfgToASBD(PPDMAUDIOSTREAMCFG pCfg, AudioStreamB
     AssertPtrReturn(pCfg,  VERR_INVALID_PARAMETER);
     AssertPtrReturn(pASBD, VERR_INVALID_PARAMETER);
 
-    PDMPCMPROPS Props;
+    PDMAUDIOPCMPROPS Props;
     int rc = DrvAudioStreamCfgToProps(pCfg, &Props);
     if (RT_SUCCESS(rc))
         rc = drvHostCoreAudioPCMPropsToASBD(&Props, pASBD);
@@ -754,7 +744,7 @@ static DECLCALLBACK(int) coreAudioQueueThread(RTTHREAD hThreadSelf, void *pvUser
 
     ///@todo: The following code may cause subsequent AudioQueueStart to fail
     // with !dev error (560227702). If we skip it entirely, we end up using the
-    // default device, which is what we're doing anyway. 
+    // default device, which is what we're doing anyway.
 #if 0
     /*
      * Assign device to queue.
@@ -846,15 +836,18 @@ int coreAudioInputQueueProcBuffer(PCOREAUDIOSTREAM pCAStream, AudioQueueBufferRe
         /* Try to acquire the necessary block from the ring buffer. */
         RTCircBufAcquireWriteBlock(pCircBuf, cbLeft, (void **)&pvDst, &cbToWrite);
 
-        if (!cbToWrite)
-            break;
-
-        /* Copy the data from our ring buffer to the core audio buffer. */
-        memcpy((UInt8 *)pvDst, pvSrc + cbWritten, cbToWrite);
+        if (cbToWrite)
+        {
+            /* Copy the data from our ring buffer to the core audio buffer. */
+            memcpy((UInt8 *)pvDst, pvSrc + cbWritten, cbToWrite);
+        }
 
         /* Release the read buffer, so it could be used for new data. */
         RTCircBufReleaseWriteBlock(pCircBuf, cbToWrite);
 
+        if (!cbToWrite)
+            break;
+
         cbWritten += cbToWrite;
 
         Assert(cbLeft >= cbToWrite);
@@ -1180,7 +1173,7 @@ static int drvHostCoreAudioReinitInput(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTST
             int rc2;
             rc2 = RTCritSectInit(&pStreamIn->cbCtx.pStream->CritSect);
             AssertRC(rc2);
-                   
+
             rc = coreAudioStreamInitQueue(pStreamIn->cbCtx.pStream, true /* fInput */, &CfgAcq /* pCfgReq */, NULL /* pCfgAcq */);
             if (RT_SUCCESS(rc))
             {
@@ -1299,9 +1292,9 @@ static DECLCALLBACK(OSStatus) drvHostCoreAudioConverterCb(AudioConverterRef
             ioData->mBuffers[0].mDataByteSize   = cbAvail;
             ioData->mBuffers[0].mData           = pvAvail;
 
-#ifdef DEBUG_DUMP_PCM_DATA
+#ifdef VBOX_AUDIO_DEBUG_DUMP_PCM_DATA
             RTFILE fh;
-            int rc = RTFileOpen(&fh, DEBUG_DUMP_PCM_DATA_PATH "ca-converter-cb-input.pcm",
+            int rc = RTFileOpen(&fh, VBOX_AUDIO_DEBUG_DUMP_PCM_DATA_PATH "caCaptureConverterCb.pcm",
                                 RTFILE_O_OPEN_CREATE | RTFILE_O_APPEND | RTFILE_O_WRITE | RTFILE_O_DENY_NONE);
             if (RT_SUCCESS(rc))
             {
@@ -1400,6 +1393,12 @@ static DECLCALLBACK(int) drvHostCoreAudioInit(PPDMIHOSTAUDIO pInterface)
 
     LogFlowFuncEnter();
 
+#ifdef VBOX_AUDIO_DEBUG_DUMP_PCM_DATA
+    RTFileDelete(VBOX_AUDIO_DEBUG_DUMP_PCM_DATA_PATH "caCaptureConverterCb.pcm");
+    RTFileDelete(VBOX_AUDIO_DEBUG_DUMP_PCM_DATA_PATH "caCaptureIn.pcm");
+    RTFileDelete(VBOX_AUDIO_DEBUG_DUMP_PCM_DATA_PATH "caPlayOut.pcm");
+#endif
+
     return VINF_SUCCESS;
 }
 
@@ -1424,18 +1423,20 @@ static DECLCALLBACK(int) drvHostCoreAudioCaptureIn(PPDMIHOSTAUDIO pInterface, PP
     AssertPtr(pCircBuf);
 
     int rc = VINF_SUCCESS;
-    uint32_t cbWrittenTotal = 0;
+    uint32_t cMixedTotal = 0;
 
     do
     {
-        size_t cbBuf     = AudioMixBufSizeBytes(&pHstStrmIn->MixBuf);
-        size_t cbToWrite = RT_MIN(cbBuf, RTCircBufUsed(pCircBuf));
+        /* As we mix the captured data to the guest mixing buffer (parent) immediately,
+         * determine how much space there currently is for capturing. */
+        AssertPtr(pHstStrmIn->pGstStrmIn);
+        size_t cbFree    = AudioMixBufFreeBytes(&pHstStrmIn->pGstStrmIn->MixBuf);
+        size_t cbToWrite = RT_MIN(cbFree, RTCircBufUsed(pCircBuf));
 
-        uint32_t cWritten, cbWritten;
         uint8_t *puBuf;
         size_t   cbToRead;
 
-        Log3Func(("cbBuf=%zu, cbToWrite=%zu/%zu\n", cbBuf, cbToWrite, RTCircBufSize(pCircBuf)));
+        Log3Func(("cbFree=%zu, cbToWrite=%zu/%zu\n", cbFree, cbToWrite, RTCircBufSize(pCircBuf)));
 
         while (cbToWrite)
         {
@@ -1444,60 +1445,58 @@ static DECLCALLBACK(int) drvHostCoreAudioCaptureIn(PPDMIHOSTAUDIO pInterface, PP
 
             if (cbToRead)
             {
-#ifdef DEBUG_DUMP_PCM_DATA
+#ifdef VBOX_AUDIO_DEBUG_DUMP_PCM_DATA
                 RTFILE fh;
-                rc = RTFileOpen(&fh, DEBUG_DUMP_PCM_DATA_PATH "ca-capture.pcm",
-                                RTFILE_O_OPEN_CREATE | RTFILE_O_APPEND | RTFILE_O_WRITE | RTFILE_O_DENY_NONE);
-                if (RT_SUCCESS(rc))
+                int rc2 = RTFileOpen(&fh, VBOX_AUDIO_DEBUG_DUMP_PCM_DATA_PATH "caCaptureIn.pcm",
+                                     RTFILE_O_OPEN_CREATE | RTFILE_O_APPEND | RTFILE_O_WRITE | RTFILE_O_DENY_NONE);
+                if (RT_SUCCESS(rc2))
                 {
-                    RTFileWrite(fh, puBuf + cbWrittenTotal, cbToRead, NULL);
+                    RTFileWrite(fh, puBuf, cbToRead, NULL);
                     RTFileClose(fh);
                 }
                 else
                     AssertFailed();
 #endif
-                rc = AudioMixBufWriteCirc(&pHstStrmIn->MixBuf, puBuf, cbToRead, &cWritten);
+                uint32_t cWritten;
+                rc = AudioMixBufWriteAt(&pHstStrmIn->MixBuf, 0 /* Offset */, puBuf, cbToRead, &cWritten);
+                if (RT_FAILURE(rc))
+                    break;
+
+                uint32_t cMixed = 0;
+                rc = AudioMixBufMixToParentEx(&pHstStrmIn->MixBuf, 0 /* Offset */, cWritten, &cMixed);
+                if (RT_FAILURE(rc))
+                    break;
+
+                const uint32_t cbWritten = AUDIOMIXBUF_S2B(&pHstStrmIn->MixBuf, cWritten);
+
+                Assert(cbToWrite >= cbWritten);
+                cbToWrite      -= cbWritten;
+
+                cMixedTotal    += cMixed;
+
+                Log3Func(("cbWritten=%RU32, cbToWrite=%RU32, cWritten=%RU32, cMixed=%RU32 -> cMixedTotal=%RU32\n",
+                          cbWritten, cbToWrite, cWritten, cMixed, cMixedTotal));
             }
 
             /* Release the read buffer, so it could be used for new data. */
             RTCircBufReleaseReadBlock(pCircBuf, cbToRead);
 
             if (   RT_FAILURE(rc)
-                || !cWritten)
+                || !cbToRead)
             {
                 break;
             }
-
-            cbWritten = AUDIOMIXBUF_S2B(&pHstStrmIn->MixBuf, cWritten);
-
-            Assert(cbToWrite >= cbWritten);
-            cbToWrite      -= cbWritten;
-            cbWrittenTotal += cbWritten;
         }
-
-        Log3Func(("cbToWrite=%zu, cbToRead=%zu, cbWrittenTotal=%RU32, rc=%Rrc\n", cbToWrite, cbToRead, cbWrittenTotal, rc));
     }
     while (0);
 
     if (RT_SUCCESS(rc))
     {
-        uint32_t cCaptured     = 0;
-        uint32_t cWrittenTotal = AUDIOMIXBUF_B2S(&pHstStrmIn->MixBuf, cbWrittenTotal);
-        if (cWrittenTotal)
-            rc = AudioMixBufMixToParent(&pHstStrmIn->MixBuf, cWrittenTotal, &cCaptured);
-
-        Log3Func(("cWrittenTotal=%RU32 (%RU32 bytes), cCaptured=%RU32, rc=%Rrc\n", cWrittenTotal, cbWrittenTotal, cCaptured, rc));
-
-        if (cCaptured)
-            LogFlowFunc(("%RU32 samples captured\n", cCaptured));
-
         if (pcSamplesCaptured)
-            *pcSamplesCaptured = cCaptured;
+            *pcSamplesCaptured = cMixedTotal;
     }
 
-    if (RT_FAILURE(rc))
-        LogFunc(("Failed with rc=%Rrc\n", rc));
-
+    LogFlowFuncLeaveRC(rc);
     return rc;
 }
 
@@ -1516,7 +1515,7 @@ static DECLCALLBACK(int) drvHostCoreAudioPlayOut(PPDMIHOSTAUDIO pInterface, PPDM
             return rc;
     }
 
-    uint32_t cLive = AudioMixBufAvail(&pHstStrmOut->MixBuf);
+    uint32_t cLive = AudioMixBufLive(&pHstStrmOut->MixBuf);
     if (!cLive) /* Not samples to play? Bail out. */
     {
         if (pcSamplesPlayed)
@@ -2081,7 +2080,7 @@ static DECLCALLBACK(int) drvHostCoreAudioInitOut(PPDMIHOSTAUDIO pInterface,
     pStreamOut->cbCtx.pStream = &pStreamOut->Stream;
 
     PCOREAUDIOSTREAM pCAStream = pStreamOut->cbCtx.pStream;
-    
+
     int rc = RTCritSectInit(&pCAStream->CritSect);
     if (RT_FAILURE(rc))
         return rc;
diff --git a/src/VBox/Devices/Audio/DrvHostDSound.cpp b/src/VBox/Devices/Audio/DrvHostDSound.cpp
index 150cccb..8a1f8dc 100644
--- a/src/VBox/Devices/Audio/DrvHostDSound.cpp
+++ b/src/VBox/Devices/Audio/DrvHostDSound.cpp
@@ -4,7 +4,7 @@
  */
 
 /*
- * Copyright (C) 2006-2016 Oracle Corporation
+ * Copyright (C) 2006-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;
@@ -366,7 +366,7 @@ static HRESULT directSoundCaptureUnlock(LPDIRECTSOUNDCAPTUREBUFFER8 pDSCB,
 }
 
 static HRESULT directSoundPlayLock(PDRVHOSTDSOUND pThis,
-                                   LPDIRECTSOUNDBUFFER8 pDSB, PDMPCMPROPS *pProps,
+                                   LPDIRECTSOUNDBUFFER8 pDSB, PDMAUDIOPCMPROPS *pProps,
                                    DWORD dwOffset, DWORD dwBytes,
                                    LPVOID *ppv1, LPVOID *ppv2,
                                    DWORD *pcb1, DWORD *pcb2,
@@ -414,7 +414,7 @@ static HRESULT directSoundPlayLock(PDRVHOSTDSOUND pThis,
     return S_OK;
 }
 
-static HRESULT directSoundCaptureLock(LPDIRECTSOUNDCAPTUREBUFFER8 pDSCB, PPDMPCMPROPS pProps,
+static HRESULT directSoundCaptureLock(LPDIRECTSOUNDCAPTUREBUFFER8 pDSCB, PPDMAUDIOPCMPROPS pProps,
                                       DWORD dwOffset, DWORD dwBytes,
                                       LPVOID *ppv1, LPVOID *ppv2,
                                       DWORD *pcb1, DWORD *pcb2,
@@ -1526,7 +1526,7 @@ static DECLCALLBACK(int) drvHostDSoundPlayOut(PPDMIHOSTAUDIO pInterface, PPDMAUD
             break;
         cbFree     -= cbSample;
 
-        uint32_t csLive = AudioMixBufAvail(&pHstStrmOut->MixBuf);
+        uint32_t csLive = AudioMixBufLive(&pHstStrmOut->MixBuf);
         uint32_t cbLive = AUDIOMIXBUF_S2B(&pHstStrmOut->MixBuf, csLive);
 
         /* Do not write more than available space in the DirectSound playback buffer. */
@@ -1773,7 +1773,7 @@ static DECLCALLBACK(int) drvHostDSoundCaptureIn(PPDMIHOSTAUDIO pInterface, PPDMA
 
     int rc = VINF_SUCCESS;
 
-    uint32_t cCaptured = 0;
+    uint32_t csCapturedTotal = 0;
 
     do
     {
@@ -1807,33 +1807,34 @@ static DECLCALLBACK(int) drvHostDSoundCaptureIn(PPDMIHOSTAUDIO pInterface, PPDMA
         DWORD csReadPos = cbReadPos >> pHstStrmIn->Props.cShift;
 
         /* Number of samples available in the DirectSound capture buffer. */
-        DWORD csCaptured = dsoundRingDistance(csReadPos, pDSoundStrmIn->csCaptureReadPos, pDSoundStrmIn->csCaptureBufferSize);
-        if (csCaptured == 0)
+        DWORD csToCapture = dsoundRingDistance(csReadPos, pDSoundStrmIn->csCaptureReadPos, pDSoundStrmIn->csCaptureBufferSize);
+        if (csToCapture == 0)
             break;
 
         /* Using as an intermediate not circular buffer. */
         AudioMixBufReset(&pHstStrmIn->MixBuf);
 
         /* Get number of free samples in the mix buffer and check that is has free space */
-        uint32_t csMixFree = AudioMixBufFree(&pHstStrmIn->MixBuf);
-        if (csMixFree == 0)
+        AssertPtr(pHstStrmIn->pGstStrmIn);
+        uint32_t csFree = AudioMixBufFree(&pHstStrmIn->pGstStrmIn->MixBuf);
+        if (csFree == 0)
         {
             DSLOGF(("DSound: Capture buffer full\n"));
             break;
         }
 
-        DSLOGF(("DSound: Capture csMixFree=%RU32, csReadPos=%ld, csCaptureReadPos=%ld, csCaptured=%ld\n",
-                csMixFree, csReadPos, pDSoundStrmIn->csCaptureReadPos, csCaptured));
+        DSLOGF(("DSound: Capture csFree=%RU32, csReadPos=%ld, csCaptureReadPos=%ld, csCaptured=%ld\n",
+                csFree, csReadPos, pDSoundStrmIn->csCaptureReadPos, csToCapture));
 
         /* No need to fetch more samples than mix buffer can receive. */
-        csCaptured = RT_MIN(csCaptured, csMixFree);
+        csToCapture = RT_MIN(csToCapture, csFree);
 
         /* Lock relevant range in the DirectSound capture buffer. */
         LPVOID pv1, pv2;
         DWORD cb1, cb2;
         hr = directSoundCaptureLock(pDSCB, &pHstStrmIn->Props,
                                     AUDIOMIXBUF_S2B(&pHstStrmIn->MixBuf, pDSoundStrmIn->csCaptureReadPos), /* dwOffset */
-                                    AUDIOMIXBUF_S2B(&pHstStrmIn->MixBuf, csCaptured),                      /* dwBytes */
+                                    AUDIOMIXBUF_S2B(&pHstStrmIn->MixBuf, csToCapture),                     /* dwBytes */
                                     &pv1, &pv2, &cb1, &cb2,
                                     0 /* dwFlags */);
         if (FAILED(hr))
@@ -1845,36 +1846,77 @@ static DECLCALLBACK(int) drvHostDSoundCaptureIn(PPDMIHOSTAUDIO pInterface, PPDMA
         DWORD len1 = AUDIOMIXBUF_B2S(&pHstStrmIn->MixBuf, cb1);
         DWORD len2 = AUDIOMIXBUF_B2S(&pHstStrmIn->MixBuf, cb2);
 
+        LogFlowFunc(("csMixFree=%RU32, csLen1=%ld, csLen2=%ld\n", csFree, len1, len2));
+
         uint32_t csWrittenTotal = 0;
+
         uint32_t csWritten;
         if (pv1 && len1)
         {
-            rc = AudioMixBufWriteAt(&pHstStrmIn->MixBuf, 0 /* offWrite */,
+#ifdef VBOX_AUDIO_DEBUG_DUMP_PCM_DATA
+            RTFILE fh;
+            int rc2 = RTFileOpen(&fh, VBOX_AUDIO_DEBUG_DUMP_PCM_DATA_PATH "dsoundCaptureIn.pcm",
+                                 RTFILE_O_OPEN_CREATE | RTFILE_O_APPEND | RTFILE_O_WRITE | RTFILE_O_DENY_NONE);
+            if (RT_SUCCESS(rc2))
+            {
+                RTFileWrite(fh, pv1, cb1, NULL);
+                RTFileClose(fh);
+            }
+            else
+                AssertFailed();
+#endif
+            rc = AudioMixBufWriteAt(&pHstStrmIn->MixBuf, 0 /* offSamples */,
                                     pv1, cb1, &csWritten);
-            if (RT_SUCCESS(rc))
+            if (   RT_SUCCESS(rc)
+                && csWritten)
+            {
                 csWrittenTotal += csWritten;
+
+                uint32_t csCaptured = 0;
+                rc = AudioMixBufMixToParent(&pHstStrmIn->MixBuf, csWritten, &csCaptured);
+                if (RT_SUCCESS(rc))
+                    csCapturedTotal += csCaptured;
+            }
         }
 
         if (   RT_SUCCESS(rc)
             && csWrittenTotal == len1
             && pv2 && len2)
         {
-            rc = AudioMixBufWriteAt(&pHstStrmIn->MixBuf, csWrittenTotal,
+#ifdef VBOX_AUDIO_DEBUG_DUMP_PCM_DATA
+            RTFILE fh;
+            int rc2 = RTFileOpen(&fh, VBOX_AUDIO_DEBUG_DUMP_PCM_DATA_PATH "dsoundCaptureIn.pcm",
+                                 RTFILE_O_OPEN_CREATE | RTFILE_O_APPEND | RTFILE_O_WRITE | RTFILE_O_DENY_NONE);
+            if (RT_SUCCESS(rc2))
+            {
+                RTFileWrite(fh, pv2, cb2, NULL);
+                RTFileClose(fh);
+            }
+            else
+                AssertFailed();
+#endif
+            csWritten = 0;
+            rc = AudioMixBufWriteAt(&pHstStrmIn->MixBuf, 0 /* offSamples */,
                                     pv2, cb2, &csWritten);
-            if (RT_SUCCESS(rc))
+            if (   RT_SUCCESS(rc)
+                || csWritten)
+            {
                 csWrittenTotal += csWritten;
+
+                uint32_t csCaptured = 0;
+                rc = AudioMixBufMixToParent(&pHstStrmIn->MixBuf, csWritten, &csCaptured);
+                if (RT_SUCCESS(rc))
+                    csCapturedTotal += csCaptured;
+            }
         }
 
         directSoundCaptureUnlock(pDSCB, pv1, pv2, cb1, cb2);
 
-        if (csWrittenTotal) /* Captured something? */
-            rc = AudioMixBufMixToParent(&pHstStrmIn->MixBuf, csWrittenTotal, &cCaptured);
-
         if (RT_SUCCESS(rc))
         {
-            pDSoundStrmIn->csCaptureReadPos = (pDSoundStrmIn->csCaptureReadPos + cCaptured) % pDSoundStrmIn->csCaptureBufferSize;
+            pDSoundStrmIn->csCaptureReadPos = (pDSoundStrmIn->csCaptureReadPos + csCapturedTotal) % pDSoundStrmIn->csCaptureBufferSize;
             DSLOGF(("DSound: Capture %ld (%ld+%ld), processed %RU32/%RU32\n",
-                    csCaptured, len1, len2, cCaptured, csWrittenTotal));
+                    csToCapture, len1, len2, csCapturedTotal, csWrittenTotal));
         }
 
     } while (0);
@@ -1886,10 +1928,10 @@ static DECLCALLBACK(int) drvHostDSoundCaptureIn(PPDMIHOSTAUDIO pInterface, PPDMA
     else
     {
         if (pcSamplesCaptured)
-            *pcSamplesCaptured = cCaptured;
+            *pcSamplesCaptured = csCapturedTotal;
     }
 
-    LogFlowFuncLeaveRC(rc);
+    LogFlowFunc(("csCapturedTotal=%RU32, rc=%Rrc\n", csCapturedTotal, rc));
     return rc;
 }
 
@@ -2120,6 +2162,11 @@ static DECLCALLBACK(int) drvHostDSoundInit(PPDMIHOSTAUDIO pInterface)
         rc = VERR_NOT_SUPPORTED;
     }
 
+#ifdef VBOX_AUDIO_DEBUG_DUMP_PCM_DATA
+    RTFileDelete(VBOX_AUDIO_DEBUG_DUMP_PCM_DATA_PATH "dsoundCaptureIn.pcm");
+    RTFileDelete(VBOX_AUDIO_DEBUG_DUMP_PCM_DATA_PATH "dsoundPlayOut.pcm");
+#endif
+
     LogFlowFuncLeaveRC(rc);
     return rc;
 }
diff --git a/src/VBox/Devices/Audio/DrvHostNullAudio.cpp b/src/VBox/Devices/Audio/DrvHostNullAudio.cpp
index a91d7db..4f7e5f9 100644
--- a/src/VBox/Devices/Audio/DrvHostNullAudio.cpp
+++ b/src/VBox/Devices/Audio/DrvHostNullAudio.cpp
@@ -5,7 +5,7 @@
  */
 
 /*
- * Copyright (C) 2006-2015 Oracle Corporation
+ * Copyright (C) 2006-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;
@@ -64,6 +64,7 @@ typedef struct NULLAUDIOSTREAMIN
 {
     /** Note: Always must come first! */
     PDMAUDIOHSTSTRMIN  streamIn;
+    uint64_t           u64TicksLast;
 } NULLAUDIOSTREAMIN, *PNULLAUDIOSTREAMIN;
 
 /**
@@ -166,7 +167,7 @@ static DECLCALLBACK(int) drvHostNullAudioPlayOut(PPDMIHOSTAUDIO pInterface, PPDM
     PNULLAUDIOSTREAMOUT pNullStrmOut = (PNULLAUDIOSTREAMOUT)pHstStrmOut;
 
     /* Consume as many samples as would be played at the current frequency since last call. */
-    uint32_t csLive          = AudioMixBufAvail(&pHstStrmOut->MixBuf);
+    uint32_t csLive          = AudioMixBufLive(&pHstStrmOut->MixBuf);
     uint64_t u64TicksNow     = PDMDrvHlpTMGetVirtualTime(pDrv->pDrvIns);
     uint64_t u64TicksElapsed = u64TicksNow  - pNullStrmOut->u64TicksLast;
     uint64_t u64TicksFreq    = PDMDrvHlpTMGetVirtualFreq(pDrv->pDrvIns);
@@ -200,12 +201,55 @@ static DECLCALLBACK(int) drvHostNullAudioPlayOut(PPDMIHOSTAUDIO pInterface, PPDM
 static DECLCALLBACK(int) drvHostNullAudioCaptureIn(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMIN pHstStrmIn,
                                                    uint32_t *pcSamplesCaptured)
 {
-    RT_NOREF(pInterface, pHstStrmIn);
-    /* Never capture anything. */
+    PDRVHOSTNULLAUDIO pDrv = RT_FROM_MEMBER(pInterface, DRVHOSTNULLAUDIO, IHostAudio);
+    PNULLAUDIOSTREAMIN pNullStrmIn = (PNULLAUDIOSTREAMIN)pHstStrmIn;
+
+    /* Consume as many samples as would have been captured at the current frequency since last call. */
+    uint64_t u64TicksNow     = PDMDrvHlpTMGetVirtualTime(pDrv->pDrvIns);
+    uint64_t u64TicksElapsed = u64TicksNow  - pNullStrmIn->u64TicksLast;
+    uint64_t u64TicksFreq    = PDMDrvHlpTMGetVirtualFreq(pDrv->pDrvIns);
+
+    /* Remember when samples were consumed. */
+    pNullStrmIn->u64TicksLast = u64TicksNow;
+
+    /*
+     * Minimize the rounding error by adding 0.5: samples = int((u64TicksElapsed * samplesFreq) / u64TicksFreq + 0.5).
+     * If rounding is not taken into account then the capturing rate will be consistently lower that expected.
+     */
+    uint64_t cbCaptured = AUDIOMIXBUF_S2B(&pHstStrmIn->MixBuf,
+                                          (2 * u64TicksElapsed * pHstStrmIn->Props.uHz + u64TicksFreq) / u64TicksFreq / 2);
+    AssertPtr(pHstStrmIn->pGstStrmIn);
+    uint32_t cbFree     = AudioMixBufFreeBytes(&pHstStrmIn->pGstStrmIn->MixBuf);
+
+    /* Don't capture more than free (available). */
+    if (cbCaptured > cbFree)
+        cbCaptured = cbFree;
+
+    /* Create NULL audio input data on-the-fly. */
+    size_t   cbBuf = cbCaptured;
+    AssertReturn(cbBuf, VERR_INVALID_PARAMETER);
+    uint8_t *paBuf = (uint8_t *)RTMemAllocZ(cbBuf);
+    AssertPtrReturn(paBuf, VERR_NO_MEMORY);
+
+    uint32_t csCapturedTotal = 0;
+
+    uint32_t csWritten;
+    int rc = AudioMixBufWriteAt(&pHstStrmIn->MixBuf, 0 /* Offset */, paBuf, (uint32_t)cbBuf, &csWritten);
+    if (RT_SUCCESS(rc))
+    {
+        uint32_t csMixed = 0;
+        rc = AudioMixBufMixToParentEx(&pHstStrmIn->MixBuf, 0 /* Offset */, csWritten, &csMixed);
+        if (RT_SUCCESS(rc))
+            csCapturedTotal = csMixed;
+    }
+
+    RTMemFree(paBuf);
+    paBuf = NULL;
+
     if (pcSamplesCaptured)
-        *pcSamplesCaptured = 0;
+        *pcSamplesCaptured = csCapturedTotal;
 
-    return VINF_SUCCESS;
+    return rc;
 }
 
 static DECLCALLBACK(int) drvHostNullAudioControlIn(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMIN pHstStrmIn,
diff --git a/src/VBox/Devices/Audio/DrvHostOSSAudio.cpp b/src/VBox/Devices/Audio/DrvHostOSSAudio.cpp
index 098df56..49a1ac3 100644
--- a/src/VBox/Devices/Audio/DrvHostOSSAudio.cpp
+++ b/src/VBox/Devices/Audio/DrvHostOSSAudio.cpp
@@ -4,7 +4,7 @@
  */
 
 /*
- * Copyright (C) 2014-2015 Oracle Corporation
+ * Copyright (C) 2014-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;
@@ -207,7 +207,7 @@ static int drvHostOSSAudioOSSToFmt(int fmt,
 
 static int drvHostOSSAudioClose(int *phFile)
 {
-    if (!phFile || !*phFile)
+    if (!phFile || *phFile < 1)
         return VINF_SUCCESS;
 
     int rc;
@@ -235,7 +235,7 @@ static int drvHostOSSAudioOpen(bool fIn,
     AssertPtrReturn(phFile, VERR_INVALID_POINTER);
 
     int rc;
-    int hFile;
+    int hFile = -1;
 
     do
     {
@@ -251,7 +251,8 @@ static int drvHostOSSAudioOpen(bool fIn,
         hFile = open(pszDev, (fIn ? O_RDONLY : O_WRONLY) | O_NONBLOCK);
         if (hFile == -1)
         {
-            LogRel(("OSS: Failed to open %s: %s(%d)\n", pszDev, strerror(errno), errno));
+            LogRel(("OSS: Failed to open %s for %s: %s(%d)\n",
+                    pszDev, fIn ? "input" : "output", strerror(errno), errno));
             rc = RTErrConvertFromErrno(errno);
             break;
         }
@@ -259,7 +260,7 @@ static int drvHostOSSAudioOpen(bool fIn,
         int iFormat = drvHostOSSAudioFmtToOSS(pReq->enmFormat);
         if (ioctl(hFile, SNDCTL_DSP_SAMPLESIZE, &iFormat))
         {
-            LogRel(("OSS: Failed to set audio format to %ld errno=%s(%d)\n", iFormat, strerror(errno), errno));
+            LogRel(("OSS: Failed to set audio format to %d errno=%s(%d)\n", iFormat, strerror(errno), errno));
             rc = RTErrConvertFromErrno(errno);
             break;
         }
@@ -402,6 +403,11 @@ static DECLCALLBACK(int) drvHostOSSAudioInit(PPDMIHOSTAUDIO pInterface)
 
     LogFlowFuncEnter();
 
+#ifdef VBOX_AUDIO_DEBUG_DUMP_PCM_DATA
+    RTFileDelete(VBOX_AUDIO_DEBUG_DUMP_PCM_DATA_PATH "ossCaptureIn.pcm");
+    RTFileDelete(VBOX_AUDIO_DEBUG_DUMP_PCM_DATA_PATH "ossPlayOut.pcm");
+#endif
+
     return VINF_SUCCESS;
 }
 
@@ -414,24 +420,22 @@ static DECLCALLBACK(int) drvHostOSSAudioCaptureIn(PPDMIHOSTAUDIO pInterface, PPD
     POSSAUDIOSTREAMIN pThisStrmIn = (POSSAUDIOSTREAMIN)pHstStrmIn;
 
     int rc = VINF_SUCCESS;
-    size_t cbToRead = RT_MIN(pThisStrmIn->cbPCMBuf,
-                             AudioMixBufFreeBytes(&pHstStrmIn->MixBuf));
 
-    LogFlowFunc(("cbToRead=%zu\n", cbToRead));
+    AssertPtr(pHstStrmIn->pGstStrmIn);
+    size_t cbToRead = RT_MIN(pThisStrmIn->cbPCMBuf, AudioMixBufFreeBytes(&pHstStrmIn->pGstStrmIn->MixBuf));
 
-    uint32_t cWrittenTotal = 0;
-    uint32_t cbTemp;
-    ssize_t  cbRead;
+    uint32_t csCapturedTotal = 0;
     size_t   offWrite = 0;
 
+    /* Using the host side buffer as an intermediate (and not circular) buffer. */
+    AudioMixBufReset(&pHstStrmIn->MixBuf);
+
     while (cbToRead)
     {
-        cbTemp = RT_MIN(cbToRead, pThisStrmIn->cbPCMBuf);
-        AssertBreakStmt(cbTemp, rc = VERR_NO_DATA);
-        cbRead = read(pThisStrmIn->hFile, (uint8_t *)pThisStrmIn->pvPCMBuf + offWrite, cbTemp);
+        uint32_t cbChunk = RT_MIN(cbToRead, AudioMixBufFreeBytes(&pHstStrmIn->pGstStrmIn->MixBuf));
+        ssize_t  cbRead  = read(pThisStrmIn->hFile, (uint8_t *)pThisStrmIn->pvPCMBuf + offWrite, cbChunk);
 
-        LogFlowFunc(("cbRead=%zi, cbTemp=%RU32, cbToRead=%zu\n",
-                     cbRead, cbTemp, cbToRead));
+        LogFlowFunc(("cbRead=%zi, cbChunk=%RU32, cbToRead=%zu\n", cbRead, cbChunk, cbToRead));
 
         if (cbRead < 0)
         {
@@ -451,7 +455,7 @@ static DECLCALLBACK(int) drvHostOSSAudioCaptureIn(PPDMIHOSTAUDIO pInterface, PPD
 
                 default:
                     LogFlowFunc(("Failed to read %zu input frames, rc=%Rrc\n",
-                                 cbTemp, rc));
+                                 cbChunk, rc));
                     rc = VERR_GENERAL_FAILURE; /** @todo */
                     break;
             }
@@ -461,19 +465,33 @@ static DECLCALLBACK(int) drvHostOSSAudioCaptureIn(PPDMIHOSTAUDIO pInterface, PPD
         }
         else if (cbRead)
         {
-            uint32_t cWritten;
-            rc = AudioMixBufWriteCirc(&pHstStrmIn->MixBuf,
-                                      pThisStrmIn->pvPCMBuf, cbRead,
-                                      &cWritten);
+#ifdef VBOX_AUDIO_DEBUG_DUMP_PCM_DATA
+            RTFILE fh;
+            RTFileOpen(&fh, VBOX_AUDIO_DEBUG_DUMP_PCM_DATA_PATH "ossCaptureIn.pcm",
+                       RTFILE_O_OPEN_CREATE | RTFILE_O_APPEND | RTFILE_O_WRITE | RTFILE_O_DENY_NONE);
+            RTFileWrite(fh, (uint8_t *)pThisStrmIn->pvPCMBuf + offWrite, cbRead, NULL);
+            RTFileClose(fh);
+#endif
+            uint32_t csWritten = 0;
+            rc = AudioMixBufWriteAt(&pHstStrmIn->MixBuf, 0 /* Offset */,
+                                    (uint8_t *)pThisStrmIn->pvPCMBuf + offWrite, cbRead,
+                                    &csWritten);
             if (RT_FAILURE(rc))
                 break;
 
-            uint32_t cbWritten = AUDIOMIXBUF_S2B(&pHstStrmIn->MixBuf, cWritten);
+            uint32_t csMixed = 0;
+            rc = AudioMixBufMixToParentEx(&pHstStrmIn->MixBuf, 0 /* Offset */, csWritten, &csMixed);
+            if (RT_FAILURE(rc))
+                break;
+
+            const uint32_t cbWritten = AUDIOMIXBUF_S2B(&pHstStrmIn->MixBuf, csWritten);
 
             Assert(cbToRead >= cbWritten);
-            cbToRead      -= cbWritten;
-            offWrite      += cbWritten;
-            cWrittenTotal += cWritten;
+            cbToRead        -= cbWritten;
+            offWrite        += cbWritten;
+            Assert(offWrite <= pThisStrmIn->cbPCMBuf);
+
+            csCapturedTotal += csMixed;
         }
         else /* No more data, try next round. */
             break;
@@ -484,16 +502,8 @@ static DECLCALLBACK(int) drvHostOSSAudioCaptureIn(PPDMIHOSTAUDIO pInterface, PPD
 
     if (RT_SUCCESS(rc))
     {
-        uint32_t cProcessed = 0;
-        if (cWrittenTotal)
-            rc = AudioMixBufMixToParent(&pHstStrmIn->MixBuf, cWrittenTotal,
-                                        &cProcessed);
-
         if (pcSamplesCaptured)
-            *pcSamplesCaptured = cWrittenTotal;
-
-        LogFlowFunc(("cWrittenTotal=%RU32 (%RU32 processed), rc=%Rrc\n",
-                     cWrittenTotal, cProcessed, rc));
+            *pcSamplesCaptured = csCapturedTotal;
     }
 
     LogFlowFuncLeaveRC(rc);
@@ -796,7 +806,7 @@ static DECLCALLBACK(int) drvHostOSSAudioPlayOut(PPDMIHOSTAUDIO pInterface, PPDMA
     {
         size_t cbBuf = AudioMixBufSizeBytes(&pHstStrmOut->MixBuf);
 
-        uint32_t cLive = AudioMixBufAvail(&pHstStrmOut->MixBuf);
+        uint32_t cLive = AudioMixBufLive(&pHstStrmOut->MixBuf);
         uint32_t cToRead;
 
 #ifndef RT_OS_L4
@@ -878,11 +888,24 @@ static DECLCALLBACK(int) drvHostOSSAudioPlayOut(PPDMIHOSTAUDIO pInterface, PPDMA
                                       cbRead);
             if (cbWritten == -1)
             {
-                LogRel(("OSS: Failed writing output data: %s\n", strerror(errno)));
                 rc = RTErrConvertFromErrno(errno);
+                if (rc == VERR_TRY_AGAIN) /* OSS is busy -- do not report this back as error. */
+                {
+                    rc = VINF_SUCCESS;
+                    break;
+                }
+
+                LogRel(("OSS: Failed writing output data: %s\n", strerror(errno)));
                 break;
             }
 
+#ifdef VBOX_AUDIO_DEBUG_DUMP_PCM_DATA
+            RTFILE fh;
+            RTFileOpen(&fh, VBOX_AUDIO_DEBUG_DUMP_PCM_DATA_PATH "ossPlayOut.pcm",
+                       RTFILE_O_OPEN_CREATE | RTFILE_O_APPEND | RTFILE_O_WRITE | RTFILE_O_DENY_NONE);
+            RTFileWrite(fh, pThisStrmOut->pvPCMBuf, cbRead, NULL);
+            RTFileClose(fh);
+#endif
             Assert(cbToRead >= cbRead);
             cbToRead -= cbRead;
             cbReadTotal += cbRead;
diff --git a/src/VBox/Devices/Audio/DrvHostPulseAudio.cpp b/src/VBox/Devices/Audio/DrvHostPulseAudio.cpp
index 951ab17..6302b4e 100644
--- a/src/VBox/Devices/Audio/DrvHostPulseAudio.cpp
+++ b/src/VBox/Devices/Audio/DrvHostPulseAudio.cpp
@@ -4,7 +4,7 @@
  */
 
 /*
- * Copyright (C) 2006-2016 Oracle Corporation
+ * Copyright (C) 2006-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;
@@ -40,7 +40,10 @@ RT_C_DECLS_END
 
 #include "VBoxDD.h"
 
-#define VBOX_PULSEAUDIO_MAX_LOG_REL_ERRORS 32 /** @todo Make this configurable thru driver options. */
+#define PULSEAUDIO_MAX_LOG_REL_ERRORS 32 /** @todo Make this configurable thru driver options. */
+
+/* Whether to use PulseAudio's asynchronous handling or not. */
+//#define PULSEAUDIO_ASYNC /** @todo Make this configurable thru driver options. */
 
 #ifndef PA_STREAM_NOFLAGS
 # define PA_STREAM_NOFLAGS (pa_context_flags_t)0x0000U /* since 0.9.19 */
@@ -106,6 +109,10 @@ typedef struct PULSEAUDIOSTREAM
     /** Our offset (in bytes) in peeking buffer. */
     size_t                 offPeekBuf;
     pa_operation          *pDrainOp;
+    /** Number of occurred audio data underflows. */
+    uint32_t               cUnderflows;
+    /** Current latency (in us). */
+    uint64_t               curLatencyUs;
 } PULSEAUDIOSTREAM, *PPULSEAUDIOSTREAM;
 
 /* The desired buffer length in milliseconds. Will be the target total stream
@@ -128,6 +135,11 @@ static PULSEAUDIOCFG s_pulseCfg =
     ( (PDRVHOSTPULSEAUDIO)((uintptr_t)pInterface - RT_OFFSETOF(DRVHOSTPULSEAUDIO, IHostAudio)) )
 
 static int  drvHostPulseAudioError(PDRVHOSTPULSEAUDIO pThis, const char *szMsg);
+
+static void drvHostPulseAudioCbStreamUnderflow(pa_stream *pStream, void *pvContext);
+#ifdef PULSEAUDIO_ASYNC
+ static void drvHostPulseAudioCbStreamReqWrite(pa_stream *pStream, size_t cbLen, void *pvContext);
+#endif
 static void drvHostPulseAudioCbSuccess(pa_stream *pStream, int fSuccess, void *pvContext);
 
 /**
@@ -304,6 +316,60 @@ static void drvHostPulseAudioCbStreamState(pa_stream *pStream, void *pvContext)
     }
 }
 
+#ifdef PULSEAUDIO_ASYNC
+static void drvHostPulseAudioCbStreamReqWrite(pa_stream *pStream, size_t cbLen, void *pvContext)
+{
+    RT_NOREF(cbLen, pvContext);
+
+    PPULSEAUDIOSTREAM pStrm = (PPULSEAUDIOSTREAM)pvContext;
+    AssertPtrReturnVoid(pStrm);
+
+    pa_usec_t usec = 0;
+    int neg = 0;
+    pa_stream_get_latency(pStream, &usec, &neg);
+
+    Log2Func(("Requested %zu bytes -- Current latency is %RU64ms\n", cbLen, usec / 1000));
+}
+#endif /* PULSEAUDIO_ASYNC */
+
+static void drvHostPulseAudioCbStreamUnderflow(pa_stream *pStream, void *pvContext)
+{
+    PPULSEAUDIOSTREAM pStrm = (PPULSEAUDIOSTREAM)pvContext;
+    AssertPtrReturnVoid(pStrm);
+
+    pStrm->cUnderflows++;
+
+    pa_usec_t usec = 0;
+    int neg = 0;
+    pa_stream_get_latency(pStream, &usec, &neg);
+
+    Log2Func(("Warning: Hit underflow #%RU32 -- Current latency is %RU64ms\n", pStrm->cUnderflows, usec / 1000));
+
+    if (   pStrm->cUnderflows  >= 6                /** @todo Make this check configurable. */
+        && pStrm->curLatencyUs < 2000000 /* 2s */)
+    {
+        pStrm->curLatencyUs = (pStrm->curLatencyUs * 3) /2;
+        LogFunc(("Latency increased to %RU64ms\n", pStrm->curLatencyUs / 1000));
+
+        pStrm->BufAttr.maxlength = pa_usec_to_bytes(pStrm->curLatencyUs, &pStrm->SampleSpec);
+        pStrm->BufAttr.tlength   = pa_usec_to_bytes(pStrm->curLatencyUs, &pStrm->SampleSpec);
+
+        pa_stream_set_buffer_attr(pStream, &pStrm->BufAttr, NULL, NULL);
+
+        pStrm->cUnderflows = 0;
+    }
+
+#ifdef LOG_ENABLED
+    const pa_timing_info *pTInfo = pa_stream_get_timing_info(pStream);
+
+    Log2Func(("\t-> rPos=%RI64 (%RTbool), wPos=%RI64 (%RTbool) -> %RI64 bytes\n",
+              pTInfo->read_index,  RT_BOOL(pTInfo->read_index_corrupt),
+              pTInfo->write_index, RT_BOOL(pTInfo->write_index_corrupt), pTInfo->write_index - pTInfo->read_index));
+
+    Log2Func(("\t-> sourceMs=%RU64, sinkMs=%RU64\n", pTInfo->source_usec / 1000, pTInfo->sink_usec / 1000));
+#endif
+}
+
 static void drvHostPulseAudioCbSuccess(pa_stream *pStream, int fSuccess, void *pvContext)
 {
     AssertPtrReturnVoid(pStream);
@@ -319,19 +385,17 @@ static void drvHostPulseAudioCbSuccess(pa_stream *pStream, int fSuccess, void *p
         drvHostPulseAudioError(pStrm->pDrv, "Failed to finish stream operation");
 }
 
-static int drvHostPulseAudioOpen(bool fIn, const char *pszName,
-                                 pa_sample_spec *pSampleSpec, pa_buffer_attr *pBufAttr,
-                                 pa_stream **ppStream)
+static int drvHostPulseAudioOpen(bool fIn, const char *pszName, PPULSEAUDIOSTREAM pPAStream)
 {
-    AssertPtrReturn(pszName, VERR_INVALID_POINTER);
-    AssertPtrReturn(pSampleSpec, VERR_INVALID_POINTER);
-    AssertPtrReturn(pBufAttr, VERR_INVALID_POINTER);
-    AssertPtrReturn(ppStream, VERR_INVALID_POINTER);
+    AssertPtrReturn(pszName,   VERR_INVALID_POINTER);
+    AssertPtrReturn(pPAStream, VERR_INVALID_POINTER);
+
+    pa_sample_spec *pSampleSpec = &pPAStream->SampleSpec;
+    pa_buffer_attr *pBufAttr    = &pPAStream->BufAttr;
 
     if (!pa_sample_spec_valid(pSampleSpec))
     {
-        LogRel(("PulseAudio: Unsupported sample specification for stream \"%s\"\n",
-                pszName));
+        LogRel(("PulseAudio: Unsupported sample specification for stream \"%s\"\n", pszName));
         return VERR_NOT_SUPPORTED;
     }
 
@@ -356,17 +420,19 @@ static int drvHostPulseAudioOpen(bool fIn, const char *pszName,
             break;
         }
 
-        pa_stream_set_state_callback(pStream, drvHostPulseAudioCbStreamState, NULL);
+#ifdef PULSEAUDIO_ASYNC
+        pa_stream_set_write_callback(pStream, drvHostPulseAudioCbStreamReqWrite, pPAStream);
+#endif
+        pa_stream_set_underflow_callback(pStream, drvHostPulseAudioCbStreamUnderflow, pPAStream);
+        pa_stream_set_state_callback(pStream, drvHostPulseAudioCbStreamState, pPAStream);
 
 #if PA_API_VERSION >= 12
         /* XXX */
         flags |= PA_STREAM_ADJUST_LATENCY;
 #endif
-
-#if 0
-        /* Not applicable as we don't use pa_stream_get_latency() and pa_stream_get_time(). */
+        /* For using pa_stream_get_latency() and pa_stream_get_time(). */
         flags |= PA_STREAM_INTERPOLATE_TIMING | PA_STREAM_AUTO_TIMING_UPDATE;
-#endif
+
         /* No input/output right away after the stream was started. */
         flags |= PA_STREAM_START_CORKED;
 
@@ -447,7 +513,7 @@ static int drvHostPulseAudioOpen(bool fIn, const char *pszName,
             pa_stream_unref(pStream);
     }
     else
-        *ppStream = pStream;
+        pPAStream->pStream = pStream;
 
     LogFlowFuncLeaveRC(rc);
     return rc;
@@ -459,6 +525,11 @@ static DECLCALLBACK(int) drvHostPulseAudioInit(PPDMIHOSTAUDIO pInterface)
 
     LogFlowFuncEnter();
 
+#ifdef VBOX_AUDIO_DEBUG_DUMP_PCM_DATA
+    RTFileDelete(VBOX_AUDIO_DEBUG_DUMP_PCM_DATA_PATH "paCaptureIn.pcm");
+    RTFileDelete(VBOX_AUDIO_DEBUG_DUMP_PCM_DATA_PATH "paPlayOut.pcm");
+#endif
+
     int rc = audioLoadPulseLib();
     if (RT_FAILURE(rc))
     {
@@ -577,19 +648,19 @@ static DECLCALLBACK(int) drvHostPulseAudioInitOut(PPDMIHOSTAUDIO pInterface,
     pThisStrmOut->SampleSpec.rate     = pCfgReq->uHz;
     pThisStrmOut->SampleSpec.channels = pCfgReq->cChannels;
 
+    pThisStrmOut->curLatencyUs        = 100 * 1000; /** 100ms latency by default. @todo Make this configurable. */
+
+    pThisStrmOut->BufAttr.tlength     = pa_usec_to_bytes(pThisStrmOut->curLatencyUs, &pThisStrmOut->SampleSpec);
     /* Note that setting maxlength to -1 does not work on PulseAudio servers
-     * older than 0.9.10. So use the suggested value of 3/2 of tlength */
-    pThisStrmOut->BufAttr.tlength     =   (pa_bytes_per_second(&pThisStrmOut->SampleSpec)
-                                        * s_pulseCfg.buffer_msecs_out) / 1000;
+     * older than 0.9.10. So use the suggested value of 3/2 of tlength. */
     pThisStrmOut->BufAttr.maxlength   = (pThisStrmOut->BufAttr.tlength * 3) / 2;
-    pThisStrmOut->BufAttr.prebuf      = -1; /* Same as tlength */
-    pThisStrmOut->BufAttr.minreq      = -1; /* Pulse should set something sensible for minreq on it's own */
+    pThisStrmOut->BufAttr.prebuf      = -1; /* Same as tlength. */
+    pThisStrmOut->BufAttr.minreq      = pa_usec_to_bytes(0, &pThisStrmOut->SampleSpec);
 
     /* Note that the struct BufAttr is updated to the obtained values after this call! */
     char achName[64];
     RTStrPrintf(achName, sizeof(achName), "%.32s (out)", pDrv->pszStreamName);
-    int rc = drvHostPulseAudioOpen(false /* fIn */, achName, &pThisStrmOut->SampleSpec, &pThisStrmOut->BufAttr,
-                                   &pThisStrmOut->pStream);
+    int rc = drvHostPulseAudioOpen(false /* fIn */, achName, pThisStrmOut);
     if (RT_FAILURE(rc))
         return rc;
 
@@ -673,8 +744,7 @@ static DECLCALLBACK(int) drvHostPulseAudioInitIn(PPDMIHOSTAUDIO pInterface,
 
     char achName[64];
     RTStrPrintf(achName, sizeof(achName), "%.32s (in)", pDrv->pszStreamName);
-    int rc = drvHostPulseAudioOpen(true /* fIn */, achName, &pThisStrmIn->SampleSpec, &pThisStrmIn->BufAttr,
-                                   &pThisStrmIn->pStream);
+    int rc = drvHostPulseAudioOpen(true /* fIn */, achName, pThisStrmIn);
     if (RT_FAILURE(rc))
         return rc;
 
@@ -742,12 +812,14 @@ static DECLCALLBACK(int) drvHostPulseAudioCaptureIn(PPDMIHOSTAUDIO pInterface, P
     }
 
     int rc = VINF_SUCCESS;
-    size_t cbToRead = RT_MIN(cbAvail, AudioMixBufFreeBytes(&pHstStrmIn->MixBuf));
 
-    LogFlowFunc(("cbToRead=%zu, cbAvail=%zu, offPeekBuf=%zu, cbPeekBuf=%zu\n",
-                 cbToRead, cbAvail, pThisStrmIn->offPeekBuf, pThisStrmIn->cbPeekBuf));
+    LogFlowFunc(("cbAvail=%zu, offPeekBuf=%zu, cbPeekBuf=%zu\n",
+                 cbAvail, pThisStrmIn->offPeekBuf, pThisStrmIn->cbPeekBuf));
 
-    uint32_t cWrittenTotal = 0;
+    uint32_t csCapturedTotal = 0;
+
+    AssertPtr(pThisStrmIn->In.pGstStrmIn);
+    size_t cbToRead = RT_MIN(cbAvail, AudioMixBufFreeBytes(&pThisStrmIn->In.pGstStrmIn->MixBuf));
 
     while (cbToRead)
     {
@@ -774,25 +846,39 @@ static DECLCALLBACK(int) drvHostPulseAudioCaptureIn(PPDMIHOSTAUDIO pInterface, P
         Assert(pThisStrmIn->cbPeekBuf >= pThisStrmIn->offPeekBuf);
         size_t cbToWrite = RT_MIN(pThisStrmIn->cbPeekBuf - pThisStrmIn->offPeekBuf, cbToRead);
 
-        LogFlowFunc(("cbToRead=%zu, cbToWrite=%zu, offPeekBuf=%zu, cbPeekBuf=%zu, pu8PeekBuf=%p\n",
-                     cbToRead, cbToWrite,
-                     pThisStrmIn->offPeekBuf, pThisStrmIn->cbPeekBuf, pThisStrmIn->pu8PeekBuf));
+        LogFlowFunc(("cbToRead=%zu, cbToWrite=%zu, offPeekBuf=%zu, cbPeekBuf=%zu\n",
+                     cbToRead, cbToWrite, pThisStrmIn->offPeekBuf, pThisStrmIn->cbPeekBuf));
 
         if (cbToWrite)
         {
-            uint32_t cWritten;
-            rc = AudioMixBufWriteCirc(&pHstStrmIn->MixBuf,
-                                      pThisStrmIn->pu8PeekBuf + pThisStrmIn->offPeekBuf,
-                                      cbToWrite, &cWritten);
+#ifdef VBOX_AUDIO_DEBUG_DUMP_PCM_DATA
+            RTFILE fh;
+            RTFileOpen(&fh, VBOX_AUDIO_DEBUG_DUMP_PCM_DATA_PATH "paCaptureIn.pcm",
+                       RTFILE_O_OPEN_CREATE | RTFILE_O_APPEND | RTFILE_O_WRITE | RTFILE_O_DENY_NONE);
+            RTFileWrite(fh, pThisStrmIn->pu8PeekBuf + pThisStrmIn->offPeekBuf, cbToWrite, NULL);
+            RTFileClose(fh);
+#endif
+            uint32_t csWritten;
+            rc = AudioMixBufWriteAt(&pHstStrmIn->MixBuf, 0 /* Offset */,
+                                    pThisStrmIn->pu8PeekBuf + pThisStrmIn->offPeekBuf,
+                                    cbToWrite, &csWritten);
+            if (RT_FAILURE(rc))
+                break;
+
+            uint32_t csMixed = 0;
+            rc = AudioMixBufMixToParentEx(&pHstStrmIn->MixBuf, 0 /* Offset */, csWritten, &csMixed);
             if (RT_FAILURE(rc))
                 break;
 
-            uint32_t cbWritten = AUDIOMIXBUF_S2B(&pHstStrmIn->MixBuf, cWritten);
+            const uint32_t cbWritten = AUDIOMIXBUF_S2B(&pHstStrmIn->MixBuf, csWritten);
 
             Assert(cbToRead >= cbWritten);
             cbToRead -= cbWritten;
-            cWrittenTotal += cWritten;
             pThisStrmIn->offPeekBuf += cbWritten;
+
+            csCapturedTotal += csMixed;
+
+            LogFlowFunc(("csWritten=%RU32, csMixed=%RU32\n", csWritten, csMixed));
         }
 
         if (/* Nothing to write anymore? Drop the buffer. */
@@ -812,19 +898,11 @@ static DECLCALLBACK(int) drvHostPulseAudioCaptureIn(PPDMIHOSTAUDIO pInterface, P
 
     if (RT_SUCCESS(rc))
     {
-        uint32_t cProcessed = 0;
-        if (cWrittenTotal)
-            rc = AudioMixBufMixToParent(&pHstStrmIn->MixBuf, cWrittenTotal,
-                                        &cProcessed);
-
         if (pcSamplesCaptured)
-            *pcSamplesCaptured = cWrittenTotal;
-
-        LogFlowFunc(("cWrittenTotal=%RU32 (%RU32 processed), rc=%Rrc\n",
-                     cWrittenTotal, cProcessed, rc));
+            *pcSamplesCaptured = csCapturedTotal;
     }
 
-    LogFlowFuncLeaveRC(rc);
+    LogFlowFunc(("csCapturedTotal=%RU32, rc=%Rrc\n", csCapturedTotal, rc));
     return rc;
 }
 
@@ -840,7 +918,7 @@ static DECLCALLBACK(int) drvHostPulseAudioPlayOut(PPDMIHOSTAUDIO pInterface, PPD
     int rc = VINF_SUCCESS;
     uint32_t cbReadTotal = 0;
 
-    uint32_t cLive = AudioMixBufAvail(&pHstStrmOut->MixBuf);
+    uint32_t cLive = AudioMixBufLive(&pHstStrmOut->MixBuf);
     if (!cLive)
     {
         LogFlowFunc(("%p: No live samples, skipping\n", pHstStrmOut));
@@ -872,13 +950,19 @@ static DECLCALLBACK(int) drvHostPulseAudioPlayOut(PPDMIHOSTAUDIO pInterface, PPD
         {
             rc = AudioMixBufReadCirc(&pHstStrmOut->MixBuf, pThisStrmOut->pvPCMBuf,
                                      RT_MIN(cbToRead, pThisStrmOut->cbPCMBuf), &cRead);
-            if (   !cRead
-                || RT_FAILURE(rc))
-            {
+            if (RT_FAILURE(rc))
                 break;
-            }
 
+            AssertBreak(cRead);
             cbRead = AUDIOMIXBUF_S2B(&pHstStrmOut->MixBuf, cRead);
+
+#ifdef VBOX_AUDIO_DEBUG_DUMP_PCM_DATA
+            RTFILE fh;
+            RTFileOpen(&fh, VBOX_AUDIO_DEBUG_DUMP_PCM_DATA_PATH "paPlayOut.pcm",
+                       RTFILE_O_OPEN_CREATE | RTFILE_O_APPEND | RTFILE_O_WRITE | RTFILE_O_DENY_NONE);
+            RTFileWrite(fh, pThisStrmOut->pvPCMBuf, cbRead, NULL);
+            RTFileClose(fh);
+#endif
             if (pa_stream_write(pThisStrmOut->pStream, pThisStrmOut->pvPCMBuf, cbRead, NULL /* Cleanup callback */,
                                 0, PA_SEEK_RELATIVE) < 0)
             {
@@ -920,7 +1004,7 @@ static int drvHostPulseAudioError(PDRVHOSTPULSEAUDIO pThis, const char *szMsg)
     AssertPtrReturn(pThis, VERR_INVALID_POINTER);
     AssertPtrReturn(szMsg, VERR_INVALID_POINTER);
 
-    if (pThis->cLogErrors++ < VBOX_PULSEAUDIO_MAX_LOG_REL_ERRORS)
+    if (pThis->cLogErrors++ < PULSEAUDIO_MAX_LOG_REL_ERRORS)
     {
         int rc2 = pa_context_errno(g_pContext);
         LogRel(("PulseAudio: %s: %s\n", szMsg, pa_strerror(rc2)));
@@ -1244,14 +1328,3 @@ const PDMDRVREG g_DrvHostPulseAudio =
     PDM_DRVREG_VERSION
 };
 
-#if 0 // unused
-static struct audio_option pulse_options[] =
-{
-    {"DAC_MS", AUD_OPT_INT, &s_pulseCfg.buffer_msecs_out,
-     "DAC period size in milliseconds", NULL, 0},
-    {"ADC_MS", AUD_OPT_INT, &s_pulseCfg.buffer_msecs_in,
-     "ADC period size in milliseconds", NULL, 0},
-
-    NULL
-};
-#endif
diff --git a/src/VBox/Devices/Audio/HDACodec.cpp b/src/VBox/Devices/Audio/HDACodec.cpp
index ba6d027..f648fd9 100644
--- a/src/VBox/Devices/Audio/HDACodec.cpp
+++ b/src/VBox/Devices/Audio/HDACodec.cpp
@@ -1,6 +1,6 @@
 /* $Id: HDACodec.cpp $ */
 /** @file
- * DevIchHdaCodec - VBox ICH Intel HD Audio Codec.
+ * HDACodec.cpp - VBox ICH Intel HD Audio Codec.
  *
  * Implemented against "Intel I/O Controller Hub 6 (ICH6) High Definition
  * Audio / AC '97 - Programmer's Reference Manual (PRM)", document number
@@ -8,7 +8,7 @@
  */
 
 /*
- * Copyright (C) 2006-2016 Oracle Corporation
+ * Copyright (C) 2006-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;
@@ -34,7 +34,7 @@
 #include <iprt/cpp/utils.h>
 
 #include "VBoxDD.h"
-#include "DevIchHdaCodec.h"
+#include "HDACodec.h"
 
 
 /*********************************************************************************************************************************
@@ -898,7 +898,7 @@ static DECLCALLBACK(int) stac9220ResetNode(PHDACODEC pThis, uint8_t nodenum, PCO
         case 3:
         case 4:
         case 5:
-            memset(pNode->dac.B_params, 0, AMPLIFIER_SIZE);
+            RT_ZERO(pNode->dac.B_params);
             pNode->dac.u32A_param = CODEC_MAKE_A(0, 1, CODEC_A_MULT_1X, CODEC_A_DIV_1X, CODEC_A_16_BIT, 1);//RT_BIT(14)|(0x1 << 4)|0x1; /* 44100Hz/16bit/2ch */
 
             AMPLIFIER_REGISTER(pNode->dac.B_params, AMPLIFIER_OUT, AMPLIFIER_LEFT, 0) = 0x7F | RT_BIT(7);
@@ -1129,7 +1129,7 @@ static DECLCALLBACK(int) stac9220ResetNode(PHDACODEC pThis, uint8_t nodenum, PCO
             pNode->node.au32F00_param[0xe] = CODEC_MAKE_F00_0E(0, 0x7);
             pNode->node.au32F00_param[0x12] = (0x27 << 16)|(0x4 << 8);
             /* STAC 9220 v10 6.21-22.{4,5} both(left and right) out amplefiers inited with 0*/
-            memset(pNode->adcmux.B_params, 0, AMPLIFIER_SIZE);
+            RT_ZERO(pNode->adcmux.B_params);
             pNode->node.au32F02_param[0] = RT_MAKE_U32_FROM_U8(0xe, 0x15, 0xf, 0xb);
             pNode->node.au32F02_param[4] = RT_MAKE_U32_FROM_U8(0xc, 0xd, 0xa, 0x0);
             break;
@@ -1139,7 +1139,7 @@ static DECLCALLBACK(int) stac9220ResetNode(PHDACODEC pThis, uint8_t nodenum, PCO
                                          | CODEC_F00_09_CAP_OUT_AMP_PRESENT;//(7 << 20) | RT_BIT(3) | RT_BIT(2);
             pNode->node.au32F00_param[0x12] = (0x17 << 16)|(0x3 << 8)| 0x3;
             pNode->pcbeep.u32F0a_param = 0;
-            memset(pNode->pcbeep.B_params, 0, AMPLIFIER_SIZE);
+            RT_ZERO(pNode->pcbeep.B_params);
             break;
         case 0x15:
             pNode->node.au32F00_param[0x9] = CODEC_MAKE_F00_09(CODEC_F00_09_TYPE_PIN_COMPLEX, 0, 0)
@@ -1167,7 +1167,7 @@ static DECLCALLBACK(int) stac9220ResetNode(PHDACODEC pThis, uint8_t nodenum, PCO
         case 0x18:
             pNode->node.au32F02_param[0] = 0x13;
         adcvol_init:
-            memset(pNode->adcvol.B_params, 0, AMPLIFIER_SIZE);
+            RT_ZERO(pNode->adcvol.B_params);
 
             pNode->node.au32F00_param[0x9] = CODEC_MAKE_F00_09(CODEC_F00_09_TYPE_AUDIO_SELECTOR, 0, 0)
                                            | CODEC_F00_09_CAP_L_R_SWAP
@@ -2670,6 +2670,7 @@ int hdaCodecLoadState(PHDACODEC pThis, PSSMHANDLE pSSM, uint32_t uVersion)
         /* Since version 4 a flexible node count is supported. */
         case HDA_SSM_VERSION_4:
         case HDA_SSM_VERSION_5:
+        case HDA_SSM_VERSION_6:
         case HDA_SSM_VERSION:
         {
             uint32_t cNodes;
diff --git a/src/VBox/Devices/Audio/DevIchHdaCodec.h b/src/VBox/Devices/Audio/HDACodec.h
similarity index 92%
rename from src/VBox/Devices/Audio/DevIchHdaCodec.h
rename to src/VBox/Devices/Audio/HDACodec.h
index 825a553..db7920b 100644
--- a/src/VBox/Devices/Audio/DevIchHdaCodec.h
+++ b/src/VBox/Devices/Audio/HDACodec.h
@@ -1,10 +1,10 @@
-/* $Id: DevIchHdaCodec.h $ */
+/* $Id: HDACodec.h $ */
 /** @file
- * DevIchHdaCodec - VBox ICH Intel HD Audio Codec.
+ * HDACodec.h - VBox ICH Intel HD Audio Codec.
  */
 
 /*
- * Copyright (C) 2006-2016 Oracle Corporation
+ * Copyright (C) 2006-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;
@@ -131,7 +131,12 @@ int hdaCodecSaveState(PHDACODEC pThis, PSSMHANDLE pSSM);
 int hdaCodecLoadState(PHDACODEC pThis, PSSMHANDLE pSSM, uint32_t uVersion);
 int hdaCodecOpenStream(PHDACODEC pThis, ENMSOUNDSOURCE enmSoundSource, PPDMAUDIOSTREAMCFG pCfg);
 
-#define HDA_SSM_VERSION   6
+/** Added (Controller): Base time stamp for correctly handling the WALCLK register on resume.
+  * Added (Streams):    Ring buffer. This is optional and can be skipped if (not) needed.
+  * Added (Streams):    Struct aSSMStreamStateFields7. */
+#define HDA_SSM_VERSION   7
+/** Saves the current BDLE state. */
+#define HDA_SSM_VERSION_6 6
 /** Introduced dynamic number of streams + stream identifiers for serialization.
  *  Bug: Did not save the BDLE states correctly.
  *  Those will be skipped on load then. */
diff --git a/src/VBox/Devices/Audio/HDAStreamPeriod.cpp b/src/VBox/Devices/Audio/HDAStreamPeriod.cpp
new file mode 100644
index 0000000..a78491b
--- /dev/null
+++ b/src/VBox/Devices/Audio/HDAStreamPeriod.cpp
@@ -0,0 +1,419 @@
+/* $Id$ */
+/** @file
+ * HDAStreamPeriod.cpp - Stream period functions for HD Audio.
+ *
+ * Utility functions for handling HDA audio stream periods.
+ * Stream period handling is needed in order to keep track of a stream's timing
+ * and processed audio data.
+ *
+ * As the HDA device only has one bit clock (WALCLK) but audio streams can be processed
+ * at certain points in time, these functions can be used to estimate and schedule the
+ * wall clock (WALCLK) for all streams accordingly.
+ */
+
+/*
+ * 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.
+ */
+
+/*********************************************************************************************************************************
+*   Header Files                                                                                                                 *
+*********************************************************************************************************************************/
+#define LOG_GROUP LOG_GROUP_DEV_HDA
+#include <VBox/log.h>
+
+#include <VBox/vmm/pdmdev.h>
+#include <VBox/vmm/pdmaudioifs.h>
+
+#include "HDAStreamPeriod.h"
+#include "DevHDA.h"
+
+#ifdef IN_RING3
+/**
+ * Creates a stream period.
+ *
+ * @return  IPRT status code.
+ * @param   pPeriod             Stream period to initialize.
+ */
+int hdaStreamPeriodCreate(PHDASTREAMPERIOD pPeriod)
+{
+    Assert(!(pPeriod->fStatus & HDASTREAMPERIOD_FLAG_VALID));
+
+    int rc = RTCritSectInit(&pPeriod->CritSect);
+    if (RT_SUCCESS(rc))
+    {
+        pPeriod->fStatus = HDASTREAMPERIOD_FLAG_VALID;
+    }
+
+    return VINF_SUCCESS;
+}
+
+/**
+ * Destroys a formerly created stream period.
+ *
+ * @param   pPeriod             Stream period to destroy.
+ */
+void hdaStreamPeriodDestroy(PHDASTREAMPERIOD pPeriod)
+{
+    if (pPeriod->fStatus & HDASTREAMPERIOD_FLAG_VALID)
+    {
+        RTCritSectDelete(&pPeriod->CritSect);
+
+        pPeriod->fStatus = HDASTREAMPERIOD_FLAG_NONE;
+    }
+}
+
+/**
+ * Initializes a given stream period with needed parameters.
+ *
+ * @param   pPeriod             Stream period to (re-)initialize. Must be created with hdaStreamPeriodCreate() first.
+ * @param   u8SD                Stream descriptor (serial data #) number to assign this stream period to.
+ * @param   u16LVI              The HDA stream's LVI value to use for the period calculation.
+ * @param   u32CBL              The HDA stream's CBL value to use for the period calculation.
+ * @param   pStreamCfg          Audio stream configuration to use for this period.
+ */
+void hdaStreamPeriodInit(PHDASTREAMPERIOD pPeriod,
+                         uint8_t u8SD, uint16_t u16LVI, uint32_t u32CBL, PPDMAUDIOSTREAMCFG pStreamCfg)
+{
+    /*
+     * Linux guests (at least Ubuntu):
+     * 17632 bytes (CBL) / 4 (frame size) = 4408 frames / 4 (LVI) = 1102 frames per period
+     *
+     * Windows guests (Win10 AU):
+     * 3584  bytes (CBL) / 4 (frame size) = 896 frames / 2 (LVI)  = 448 frames per period
+     */
+    unsigned cTotalPeriods = u16LVI;
+
+    if (cTotalPeriods <= 1)
+        cTotalPeriods = 2; /* At least two periods *must* be present (LVI >= 1). */
+
+    uint32_t framesToTransfer = (u32CBL / 4 /** @todo Define frame size? */) / cTotalPeriods;
+
+    pPeriod->u8SD              = u8SD;
+    pPeriod->u64StartWalClk    = 0;
+    pPeriod->u32Hz             = pStreamCfg->uHz;
+    pPeriod->u64DurationWalClk = hdaStreamPeriodFramesToWalClk(pPeriod, framesToTransfer);
+    pPeriod->u64ElapsedWalClk  = 0;
+    pPeriod->i64DelayWalClk    = 0;
+    pPeriod->framesToTransfer  = framesToTransfer;
+    pPeriod->framesTransferred = 0;
+    pPeriod->cIntPending       = 0;
+
+    Log3Func(("[SD%RU8] %RU64 long, Hz=%RU32, CBL=%RU32, LVI=%RU16 -> %u periods, %RU32 frames each\n",
+              pPeriod->u8SD, pPeriod->u64DurationWalClk, pPeriod->u32Hz, u32CBL, u16LVI,
+              cTotalPeriods, pPeriod->framesToTransfer));
+}
+
+/**
+ * Resets a stream period to its initial state.
+ *
+ * @param   pPeriod             Stream period to reset.
+ */
+void hdaStreamPeriodReset(PHDASTREAMPERIOD pPeriod)
+{
+    Log3Func(("[SD%RU8]\n", pPeriod->u8SD));
+
+    if (pPeriod->cIntPending)
+        LogFunc(("Warning: %RU8 interrupts for stream #%RU8 still pending -- so a period reset might trigger audio hangs\n",
+                 pPeriod->cIntPending, pPeriod->u8SD));
+
+    pPeriod->fStatus          &= ~HDASTREAMPERIOD_FLAG_ACTIVE;
+    pPeriod->u64StartWalClk    = 0;
+    pPeriod->u64ElapsedWalClk  = 0;
+    pPeriod->framesTransferred = 0;
+    pPeriod->cIntPending       = 0;
+#ifdef DEBUG
+    pPeriod->Dbg.tsStartNs     = 0;
+#endif
+}
+
+/**
+ * Begins a new period life span of a given period.
+ *
+ * @return  IPRT status code.
+ * @param   pPeriod             Stream period to begin new life span for.
+ * @param   u64WalClk           Wall clock (WALCLK) value to set for the period's starting point.
+ */
+int hdaStreamPeriodBegin(PHDASTREAMPERIOD pPeriod, uint64_t u64WalClk)
+{
+    Assert(!(pPeriod->fStatus & HDASTREAMPERIOD_FLAG_ACTIVE)); /* No nested calls. */
+
+    pPeriod->fStatus          |= HDASTREAMPERIOD_FLAG_ACTIVE;
+    pPeriod->u64StartWalClk    = u64WalClk;
+    pPeriod->u64ElapsedWalClk  = 0;
+    pPeriod->framesTransferred = 0;
+    pPeriod->cIntPending       = 0;
+#ifdef DEBUG
+    pPeriod->Dbg.tsStartNs     = RTTimeNanoTS();
+#endif
+
+    Log3Func(("[SD%RU8] Starting @ %RU64 (%RU64 long)\n",
+              pPeriod->u8SD, pPeriod->u64StartWalClk, pPeriod->u64DurationWalClk));
+
+    return VINF_SUCCESS;
+}
+
+/**
+ * Ends a formerly begun period life span.
+ *
+ * @param   pPeriod             Stream period to end life span for.
+ */
+void hdaStreamPeriodEnd(PHDASTREAMPERIOD pPeriod)
+{
+    Log3Func(("[SD%RU8] Took %zuus\n", pPeriod->u8SD, (RTTimeNanoTS() - pPeriod->Dbg.tsStartNs) / 1000));
+
+    if (!(pPeriod->fStatus & HDASTREAMPERIOD_FLAG_ACTIVE))
+        return;
+
+    /* Sanity. */
+    AssertMsg(pPeriod->cIntPending == 0,
+              ("%RU8 interrupts for stream #%RU8 still pending -- so ending a period might trigger audio hangs\n",
+               pPeriod->cIntPending, pPeriod->u8SD));
+    Assert(hdaStreamPeriodIsComplete(pPeriod));
+
+    pPeriod->fStatus &= ~HDASTREAMPERIOD_FLAG_ACTIVE;
+}
+
+/**
+ * Pauses a period. All values remain intact.
+ *
+ * @param   pPeriod             Stream period to pause.
+ */
+void hdaStreamPeriodPause(PHDASTREAMPERIOD pPeriod)
+{
+    AssertMsg((pPeriod->fStatus & HDASTREAMPERIOD_FLAG_ACTIVE), ("Period %p already in inactive state\n", pPeriod));
+
+    pPeriod->fStatus &= ~HDASTREAMPERIOD_FLAG_ACTIVE;
+
+    Log3Func(("[SD%RU8]\n", pPeriod->u8SD));
+}
+
+/**
+ * Resumes a formerly paused period.
+ *
+ * @param   pPeriod             Stream period to resume.
+ */
+void hdaStreamPeriodResume(PHDASTREAMPERIOD pPeriod)
+{
+    AssertMsg(!(pPeriod->fStatus & HDASTREAMPERIOD_FLAG_ACTIVE), ("Period %p already in active state\n", pPeriod));
+
+    pPeriod->fStatus |= HDASTREAMPERIOD_FLAG_ACTIVE;
+
+    Log3Func(("[SD%RU8]\n", pPeriod->u8SD));
+}
+
+/**
+ * Locks a stream period for serializing access.
+ *
+ * @return  @true if locking was successful, @false if not.
+ * @param   pPeriod             Stream period to lock.
+ */
+bool hdaStreamPeriodLock(PHDASTREAMPERIOD pPeriod)
+{
+    return RT_SUCCESS(RTCritSectEnter(&pPeriod->CritSect));
+}
+
+/**
+ * Unlocks a formerly locked stream period.
+ *
+ * @param   pPeriod             Stream period to unlock.
+ */
+void hdaStreamPeriodUnlock(PHDASTREAMPERIOD pPeriod)
+{
+    int rc2 = RTCritSectLeave(&pPeriod->CritSect);
+    AssertRC(rc2);
+}
+
+/**
+ * Returns the wall clock (WALCLK) value for a given amount of stream period audio frames.
+ *
+ * @return  Calculated wall clock value.
+ * @param   pPeriod             Stream period to calculate wall clock value for.
+ * @param   uFrames             Number of audio frames to calculate wall clock value for.
+ *
+ * @remark  Calculation depends on the given stream period and assumes a 24 MHz wall clock counter (WALCLK).
+ */
+uint64_t hdaStreamPeriodFramesToWalClk(PHDASTREAMPERIOD pPeriod, uint32_t uFrames)
+{
+    /* Prevent division by zero. */
+    const uint32_t uHz = (pPeriod->u32Hz ? pPeriod->u32Hz : 1);
+
+    /* 24 MHz WallClock (WALCLK): 42ns resolution. */
+    return ((uFrames * 24000 /* 24 MHz */) / uHz) * 1000;
+}
+
+/**
+ * Returns the absolute wall clock (WALCLK) value for the already elapsed time of
+ * a given stream period.
+ *
+ * @return  Absolute elapsed time as wall clock (WALCLK) value.
+ * @param   pPeriod             Stream period to use.
+ */
+uint64_t hdaStreamPeriodGetAbsElapsedWalClk(PHDASTREAMPERIOD pPeriod)
+{
+    return   pPeriod->u64StartWalClk
+           + pPeriod->u64ElapsedWalClk
+           + pPeriod->i64DelayWalClk;
+}
+
+/**
+ * Returns the absolute wall clock (WALCLK) value for the calculated end time of
+ * a given stream period.
+ *
+ * @return  Absolute end time as wall clock (WALCLK) value.
+ * @param   pPeriod             Stream period to use.
+ */
+uint64_t hdaStreamPeriodGetAbsEndWalClk(PHDASTREAMPERIOD pPeriod)
+{
+    return pPeriod->u64StartWalClk + pPeriod->u64DurationWalClk;
+}
+
+/**
+ * Returns the remaining audio frames to process for a given stream period.
+ *
+ * @return  Number of remaining audio frames to process. 0 if all were processed.
+ * @param   pPeriod             Stream period to return value for.
+ */
+uint32_t hdaStreamPeriodGetRemainingFrames(PHDASTREAMPERIOD pPeriod)
+{
+    Assert(pPeriod->framesToTransfer >= pPeriod->framesTransferred);
+    return pPeriod->framesToTransfer - pPeriod->framesTransferred;
+}
+
+/**
+ * Tells whether a given stream period has elapsed (time-wise) or not.
+ *
+ * @return  @true if the stream period has elapsed, @false if not.
+ * @param   pPeriod             Stream period to get status for.
+ */
+bool hdaStreamPeriodHasElapsed(PHDASTREAMPERIOD pPeriod)
+{
+    return (pPeriod->u64ElapsedWalClk >= pPeriod->u64DurationWalClk);
+}
+
+/**
+ * Tells whether a given stream period has passed the given absolute wall clock (WALCLK)
+ * time or not
+ *
+ * @return  @true if the stream period has passed the given time, @false if not.
+ * @param   pPeriod             Stream period to get status for.
+ * @param   u64WalClk           Absolute wall clock (WALCLK) time to check for.
+ */
+bool hdaStreamPeriodHasPassedAbsWalClk(PHDASTREAMPERIOD pPeriod, uint64_t u64WalClk)
+{
+    /* Period not in use? */
+    if (!(pPeriod->fStatus & HDASTREAMPERIOD_FLAG_ACTIVE))
+        return true; /* ... implies that it has passed. */
+
+    if (hdaStreamPeriodHasElapsed(pPeriod))
+        return true; /* Period already has elapsed. */
+
+    return (pPeriod->u64StartWalClk + pPeriod->u64ElapsedWalClk) >= u64WalClk;
+}
+
+/**
+ * Tells whether a given stream period has some required interrupts pending or not.
+ *
+ * @return  @true if period has interrupts pending, @false if not.
+ * @param   pPeriod             Stream period to get status for.
+ */
+bool hdaStreamPeriodNeedsInterrupt(PHDASTREAMPERIOD pPeriod)
+{
+    return pPeriod->cIntPending > 0;
+}
+
+/**
+ * Acquires (references) an (pending) interrupt for a given stream period.
+ *
+ * @param   pPeriod             Stream period to acquire interrupt for.
+ *
+ * @remark  This routine does not do any actual interrupt processing; it only
+ *          keeps track of the required (pending) interrupts for a stream period.
+ */
+void hdaStreamPeriodAcquireInterrupt(PHDASTREAMPERIOD pPeriod)
+{
+    uint32_t cIntPending = pPeriod->cIntPending;
+    if (cIntPending)
+    {
+        Log3Func(("[SD%RU8] Already pending\n", pPeriod->u8SD));
+        return;
+    }
+
+    pPeriod->cIntPending++;
+
+    Log3Func(("[SD%RU8] %RU32\n", pPeriod->u8SD, pPeriod->cIntPending));
+}
+
+/**
+ * Releases (dereferences) a pending interrupt.
+ *
+ * @param   pPeriod             Stream period to release pending interrupt for.
+ */
+void hdaStreamPeriodReleaseInterrupt(PHDASTREAMPERIOD pPeriod)
+{
+    Assert(pPeriod->cIntPending);
+    pPeriod->cIntPending--;
+
+    Log3Func(("[SD%RU8] %RU32\n", pPeriod->u8SD, pPeriod->cIntPending));
+}
+
+/**
+ * Adds an amount of (processed) audio frames to a given stream period.
+ *
+ * @return  IPRT status code.
+ * @param   pPeriod             Stream period to add audio frames to.
+ * @param   framesInc           Audio frames to add.
+ */
+void hdaStreamPeriodInc(PHDASTREAMPERIOD pPeriod, uint32_t framesInc)
+{
+    pPeriod->framesTransferred += framesInc;
+    Assert(pPeriod->framesTransferred <= pPeriod->framesToTransfer);
+
+    pPeriod->u64ElapsedWalClk   = hdaStreamPeriodFramesToWalClk(pPeriod, pPeriod->framesTransferred);
+    Assert(pPeriod->u64ElapsedWalClk <= pPeriod->u64DurationWalClk);
+
+    Log3Func(("[SD%RU8] cbTransferred=%RU32, u64ElapsedWalClk=%RU64\n",
+              pPeriod->u8SD, pPeriod->framesTransferred, pPeriod->u64ElapsedWalClk));
+}
+
+/**
+ * Tells whether a given stream period is considered as complete or not.
+ *
+ * @return  @true if stream period is complete, @false if not.
+ * @param   pPeriod             Stream period to report status for.
+ *
+ * @remark  A stream period is considered complete if it has 1) passed (elapsed) its calculated period time
+ *          and 2) processed all required audio frames.
+ */
+bool hdaStreamPeriodIsComplete(PHDASTREAMPERIOD pPeriod)
+{
+    const bool fIsComplete = /* Has the period elapsed time-wise? */
+                                hdaStreamPeriodHasElapsed(pPeriod)
+                             /* All frames transferred? */
+                             && pPeriod->framesTransferred >= pPeriod->framesToTransfer;
+#ifdef VBOX_STRICT
+    if (fIsComplete)
+    {
+        Assert(pPeriod->framesTransferred == pPeriod->framesToTransfer);
+        Assert(pPeriod->u64ElapsedWalClk  == pPeriod->u64DurationWalClk);
+    }
+#endif
+
+    Log3Func(("[SD%RU8] Period %s - runtime %RU64 / %RU64 (abs @ %RU64, starts @ %RU64, ends @ %RU64), %RU8 IRQs pending\n",
+              pPeriod->u8SD,
+              fIsComplete ? "COMPLETE" : "NOT COMPLETE YET",
+              pPeriod->u64ElapsedWalClk, pPeriod->u64DurationWalClk,
+              hdaStreamPeriodGetAbsElapsedWalClk(pPeriod), pPeriod->u64StartWalClk,
+              hdaStreamPeriodGetAbsEndWalClk(pPeriod), pPeriod->cIntPending));
+
+    return fIsComplete;
+}
+#endif /* IN_RING3 */
+
diff --git a/src/VBox/Devices/Audio/HDAStreamPeriod.h b/src/VBox/Devices/Audio/HDAStreamPeriod.h
new file mode 100644
index 0000000..cd16740
--- /dev/null
+++ b/src/VBox/Devices/Audio/HDAStreamPeriod.h
@@ -0,0 +1,109 @@
+/* $Id$ */
+/** @file
+ * HDAStreamPeriod.h - Stream period functions for HD Audio.
+ */
+
+/*
+ * 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.
+ */
+
+#ifndef HDA_STREAMPERIOD_H
+#define HDA_STREAMPERIOD_H
+
+#include <iprt/critsect.h>
+#ifdef DEBUG
+# include <iprt/time.h>
+#endif
+
+struct HDASTREAM;
+typedef HDASTREAM *PHDASTREAM;
+
+#ifdef DEBUG
+/**
+ * Structure for debug information of an HDA stream's period.
+ */
+typedef struct HDASTREAMPERIODDBGINFO
+{
+    /** Host start time (in ns) of the period. */
+    uint64_t                tsStartNs;
+} HDASTREAMPERIODDBGINFO, *PHDASTREAMPERIODDBGINFO;
+#endif
+
+/** No flags set. */
+#define HDASTREAMPERIOD_FLAG_NONE    0
+/** The stream period has been initialized and is in a valid state. */
+#define HDASTREAMPERIOD_FLAG_VALID   RT_BIT(0)
+/** The stream period is active. */
+#define HDASTREAMPERIOD_FLAG_ACTIVE  RT_BIT(1)
+
+/**
+ * Structure for keeping an HDA stream's (time) period.
+ * This is needed in order to keep track of stream timing and interrupt delivery.
+ */
+typedef struct HDASTREAMPERIOD
+{
+    /** Associated HDA stream descriptor (SD) number. */
+    uint8_t                 u8SD;
+    /** The period's status flags. */
+    uint8_t                 fStatus;
+    uint8_t                 Padding1[6];
+    /** Critical section for serializing access. */
+    RTCRITSECT              CritSect;
+    uint32_t                Padding2[1];
+    /** Hertz (Hz) rate this period runs with. */
+    uint32_t                u32Hz;
+    /** Period start time (in wall clock counts). */
+    uint64_t                u64StartWalClk;
+    /** Period duration (in wall clock counts). */
+    uint64_t                u64DurationWalClk;
+    /** The period's (relative) elapsed time (in wall clock counts). */
+    uint64_t                u64ElapsedWalClk;
+    /** Delay (in wall clock counts) for tweaking the period timing. Optional. */
+    int64_t                 i64DelayWalClk;
+    /** Number of audio frames to transfer for this period. */
+    uint32_t                framesToTransfer;
+    /** Number of audio frames already transfered. */
+    uint32_t                framesTransferred;
+    /** Number of pending interrupts required for this period. */
+    uint8_t                 cIntPending;
+    uint8_t                 Padding3[7];
+#ifdef DEBUG
+    /** Debugging information. */
+    HDASTREAMPERIODDBGINFO  Dbg;
+#endif
+} HDASTREAMPERIOD, *PHDASTREAMPERIOD;
+
+#ifdef IN_RING3
+int      hdaStreamPeriodCreate(PHDASTREAMPERIOD pPeriod);
+void     hdaStreamPeriodDestroy(PHDASTREAMPERIOD pPeriod);
+void     hdaStreamPeriodInit(PHDASTREAMPERIOD pPeriod, uint8_t u8SD, uint16_t u16LVI, uint32_t u32CBL, PPDMAUDIOSTREAMCFG pStreamCfg);
+void     hdaStreamPeriodReset(PHDASTREAMPERIOD pPeriod);
+int      hdaStreamPeriodBegin(PHDASTREAMPERIOD pPeriod, uint64_t u64WalClk);
+void     hdaStreamPeriodEnd(PHDASTREAMPERIOD pPeriod);
+void     hdaStreamPeriodPause(PHDASTREAMPERIOD pPeriod);
+void     hdaStreamPeriodResume(PHDASTREAMPERIOD pPeriod);
+bool     hdaStreamPeriodLock(PHDASTREAMPERIOD pPeriod);
+void     hdaStreamPeriodUnlock(PHDASTREAMPERIOD pPeriod);
+uint64_t hdaStreamPeriodFramesToWalClk(PHDASTREAMPERIOD pPeriod, uint32_t uFrames);
+uint64_t hdaStreamPeriodGetAbsEndWalClk(PHDASTREAMPERIOD pPeriod);
+uint64_t hdaStreamPeriodGetAbsElapsedWalClk(PHDASTREAMPERIOD pPeriod);
+uint32_t hdaStreamPeriodGetRemainingFrames(PHDASTREAMPERIOD pPeriod);
+bool     hdaStreamPeriodHasElapsed(PHDASTREAMPERIOD pPeriod);
+bool     hdaStreamPeriodHasPassedAbsWalClk(PHDASTREAMPERIOD pPeriod, uint64_t u64WalClk);
+bool     hdaStreamPeriodNeedsInterrupt(PHDASTREAMPERIOD pPeriod);
+void     hdaStreamPeriodAcquireInterrupt(PHDASTREAMPERIOD pPeriod);
+void     hdaStreamPeriodReleaseInterrupt(PHDASTREAMPERIOD pPeriod);
+void     hdaStreamPeriodInc(PHDASTREAMPERIOD pPeriod, uint32_t framesInc);
+bool     hdaStreamPeriodIsComplete(PHDASTREAMPERIOD pPeriod);
+#endif /* IN_RING3 */
+
+#endif /* !HDA_STREAMPERIOD_H */
+
diff --git a/src/VBox/Devices/Audio/pulse_mangling.h b/src/VBox/Devices/Audio/pulse_mangling.h
index 8b02ef3..ba80639 100644
--- a/src/VBox/Devices/Audio/pulse_mangling.h
+++ b/src/VBox/Devices/Audio/pulse_mangling.h
@@ -5,7 +5,7 @@
  */
 
 /*
- * Copyright (C) 2013-2015 Oracle Corporation
+ * Copyright (C) 2013-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;
@@ -29,7 +29,12 @@
 #define pa_stream_write                         PULSE_MANGLER(pa_stream_write)
 #define pa_stream_unref                         PULSE_MANGLER(pa_stream_unref)
 #define pa_stream_get_state                     PULSE_MANGLER(pa_stream_get_state)
+#define pa_stream_get_latency                   PULSE_MANGLER(pa_stream_get_latency)
+#define pa_stream_get_timing_info               PULSE_MANGLER(pa_stream_get_timing_info)
+#define pa_stream_set_buffer_attr               PULSE_MANGLER(pa_stream_set_buffer_attr)
 #define pa_stream_set_state_callback            PULSE_MANGLER(pa_stream_set_state_callback)
+#define pa_stream_set_underflow_callback        PULSE_MANGLER(pa_stream_set_underflow_callback)
+#define pa_stream_set_write_callback            PULSE_MANGLER(pa_stream_set_write_callback)
 #define pa_stream_flush                         PULSE_MANGLER(pa_stream_flush)
 #define pa_stream_drain                         PULSE_MANGLER(pa_stream_drain)
 #define pa_stream_trigger                       PULSE_MANGLER(pa_stream_trigger)
@@ -56,6 +61,7 @@
 #define pa_threaded_mainloop_start              PULSE_MANGLER(pa_threaded_mainloop_start)
 #define pa_threaded_mainloop_lock               PULSE_MANGLER(pa_threaded_mainloop_lock)
 #define pa_bytes_per_second                     PULSE_MANGLER(pa_bytes_per_second)
+#define pa_usec_to_bytes                        PULSE_MANGLER(pa_usec_to_bytes)
 #define pa_frame_size                           PULSE_MANGLER(pa_frame_size)
 #define pa_sample_format_to_string              PULSE_MANGLER(pa_sample_format_to_string)
 #define pa_sample_spec_valid                    PULSE_MANGLER(pa_sample_spec_valid)
diff --git a/src/VBox/Devices/Audio/pulse_stubs.c b/src/VBox/Devices/Audio/pulse_stubs.c
index c38c090..73f5ee2 100644
--- a/src/VBox/Devices/Audio/pulse_stubs.c
+++ b/src/VBox/Devices/Audio/pulse_stubs.c
@@ -4,7 +4,7 @@
  */
 
 /*
- * Copyright (C) 2006-2015 Oracle Corporation
+ * Copyright (C) 2006-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;
@@ -78,9 +78,24 @@ PROXY_STUB_VOID(pa_stream_unref,
 PROXY_STUB     (pa_stream_get_state, pa_stream_state_t,
                 (pa_stream *p),
                 (p))
+PROXY_STUB     (pa_stream_get_latency, int,
+                (pa_stream *s, pa_usec_t *r_usec, int *negative),
+                (s, r_usec, negative))
+PROXY_STUB     (pa_stream_get_timing_info, pa_timing_info*,
+                (pa_stream *s),
+                (s))
+PROXY_STUB      (pa_stream_set_buffer_attr, pa_operation *,
+                (pa_stream *s, const pa_buffer_attr *attr, pa_stream_success_cb_t cb, void *userdata),
+                (s, attr, cb, userdata))
 PROXY_STUB_VOID(pa_stream_set_state_callback,
                 (pa_stream *s, pa_stream_notify_cb_t cb, void *userdata),
                 (s, cb, userdata))
+PROXY_STUB_VOID(pa_stream_set_underflow_callback,
+                (pa_stream *s, pa_stream_notify_cb_t cb, void *userdata),
+                (s, cb, userdata))
+PROXY_STUB_VOID(pa_stream_set_write_callback,
+                (pa_stream *s, pa_stream_request_cb_t cb, void *userdata),
+                (s, cb, userdata))
 PROXY_STUB     (pa_stream_flush, pa_operation*,
                 (pa_stream *s, pa_stream_success_cb_t cb, void *userdata),
                 (s, cb, userdata))
@@ -161,6 +176,9 @@ PROXY_STUB_VOID(pa_threaded_mainloop_lock,
 PROXY_STUB     (pa_bytes_per_second, size_t,
                 (const pa_sample_spec *spec),
                 (spec))
+PROXY_STUB     (pa_usec_to_bytes, size_t,
+                (pa_usec_t t, const pa_sample_spec *spec),
+                (t, spec))
 PROXY_STUB     (pa_frame_size, size_t,
                 (const pa_sample_spec *spec),
                 (spec))
@@ -207,7 +225,12 @@ static SHARED_FUNC SharedFuncs[] =
     ELEMENT(pa_stream_write),
     ELEMENT(pa_stream_unref),
     ELEMENT(pa_stream_get_state),
+    ELEMENT(pa_stream_get_latency),
+    ELEMENT(pa_stream_get_timing_info),
+    ELEMENT(pa_stream_set_buffer_attr),
     ELEMENT(pa_stream_set_state_callback),
+    ELEMENT(pa_stream_set_underflow_callback),
+    ELEMENT(pa_stream_set_write_callback),
     ELEMENT(pa_stream_flush),
     ELEMENT(pa_stream_drain),
     ELEMENT(pa_stream_trigger),
@@ -234,6 +257,7 @@ static SHARED_FUNC SharedFuncs[] =
     ELEMENT(pa_threaded_mainloop_start),
     ELEMENT(pa_threaded_mainloop_lock),
     ELEMENT(pa_bytes_per_second),
+    ELEMENT(pa_usec_to_bytes),
     ELEMENT(pa_frame_size),
     ELEMENT(pa_sample_format_to_string),
     ELEMENT(pa_sample_spec_valid),
diff --git a/src/VBox/Devices/Audio/testcase/Makefile.kmk b/src/VBox/Devices/Audio/testcase/Makefile.kmk
index 5f4a4cd..22b923c 100644
--- a/src/VBox/Devices/Audio/testcase/Makefile.kmk
+++ b/src/VBox/Devices/Audio/testcase/Makefile.kmk
@@ -31,7 +31,7 @@ if defined(VBOX_WITH_TESTCASES) && !defined(VBOX_ONLY_ADDITIONS) && !defined(VBO
 	../DrvAudioCommon.cpp
  tstAudioMixBuffer_LIBS     = $(LIB_RUNTIME)
 
- $$(tstAudioMixBuffer_0_OUTDIR)/tstAudioMixBuffer.run: $$(tstAudioMixBuffer_1_STAGE_TARGET)
+ $$(tstAudioMixBuffer_0_OUTDIR)/tstAudioMixBuffer.run: $$(tstAudioMixBuffer_1_STAGE_TARGET) | $$(dir $$@)
 	export VBOX_LOG_DEST=nofile; $(tstAudioMixBuffer_1_STAGE_TARGET) quiet
 	$(QUIET)$(APPEND) -t "$@" "done"
 
diff --git a/src/VBox/Devices/Audio/testcase/tstAudioMixBuffer.cpp b/src/VBox/Devices/Audio/testcase/tstAudioMixBuffer.cpp
index b297c93..73263a4 100644
--- a/src/VBox/Devices/Audio/testcase/tstAudioMixBuffer.cpp
+++ b/src/VBox/Devices/Audio/testcase/tstAudioMixBuffer.cpp
@@ -4,7 +4,7 @@
  */
 
 /*
- * Copyright (C) 2014-2015 Oracle Corporation
+ * Copyright (C) 2014-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;
@@ -40,17 +40,19 @@ static int tstSingle(RTTEST hTest)
 {
     RTTestSubF(hTest, "Single buffer");
 
-    PDMAUDIOSTREAMCFG config =
+    /* 44100Hz, 2 Channels, S16 */
+    PDMAUDIOPCMPROPS config =
     {
-        44100,                   /* Hz */
-        2                        /* Channels */,
-        AUD_FMT_S16              /* Format */,
-        PDMAUDIOENDIANNESS_LITTLE /* ENDIANNESS */
+        16,                                                                 /* Bits */
+        true,                                                               /* Signed */
+        PDMAUDIOPCMPROPS_MAKE_SHIFT_PARMS(16 /* Bits */, 2 /* Channels */), /* Shift */
+        2,                                                                  /* Channels */
+        0,                                                                  /* Alignment mask */
+        44100,                                                              /* Hz */
+        false                                                               /* Swap Endian */
     };
-    PDMPCMPROPS props;
 
-    int rc = DrvAudioStreamCfgToProps(&config, &props);
-    AssertRC(rc);
+    RTTESTI_CHECK(DrvAudioHlpPCMPropsAreValid(&config));
 
     uint32_t cBufSize = _1K;
 
@@ -58,7 +60,7 @@ static int tstSingle(RTTEST hTest)
      * General stuff.
      */
     PDMAUDIOMIXBUF mb;
-    RTTESTI_CHECK_RC_OK(AudioMixBufInit(&mb, "Single", &props, cBufSize));
+    RTTESTI_CHECK_RC_OK(AudioMixBufInit(&mb, "Single", &config, cBufSize));
     RTTESTI_CHECK(AudioMixBufSize(&mb) == cBufSize);
     RTTESTI_CHECK(AUDIOMIXBUF_B2S(&mb, AudioMixBufSizeBytes(&mb)) == cBufSize);
     RTTESTI_CHECK(AUDIOMIXBUF_S2B(&mb, AudioMixBufSize(&mb)) == AudioMixBufSizeBytes(&mb));
@@ -68,64 +70,88 @@ static int tstSingle(RTTEST hTest)
     /*
      * Absolute writes.
      */
-    uint32_t read  = 0, written = 0, written_abs = 0;
+    uint32_t cSamplesRead  = 0, cSamplesWritten = 0, cSamplesWrittenAbs = 0;
     int8_t  samples8 [2] = { 0x12, 0x34 };
     int16_t samples16[2] = { 0xAA, 0xBB };
     int32_t samples32[2] = { 0xCC, 0xDD };
+    /* int64_t samples64[2] = { 0xEE, 0xFF }; - unused */
 
-    RTTESTI_CHECK_RC_OK(AudioMixBufWriteAt(&mb, 0, &samples8, sizeof(samples8), &written));
-    RTTESTI_CHECK(written == 0 /* Samples */);
+    RTTESTI_CHECK_RC_OK(AudioMixBufWriteAt(&mb, 0 /* Offset */, &samples8, sizeof(samples8), &cSamplesWritten));
+    RTTESTI_CHECK(cSamplesWritten == 0 /* Samples */);
+    RTTESTI_CHECK(AudioMixBufUsed(&mb) == 0);
 
-    RTTESTI_CHECK_RC_OK(AudioMixBufWriteAt(&mb, 0, &samples16, sizeof(samples16), &written));
-    RTTESTI_CHECK(written == 1 /* Samples */);
+    RTTESTI_CHECK_RC_OK(AudioMixBufWriteAt(&mb, 0 /* Offset */, &samples16, sizeof(samples16), &cSamplesWritten));
+    RTTESTI_CHECK(cSamplesWritten == 1 /* Samples */);
+    RTTESTI_CHECK(AudioMixBufUsed(&mb) == 1);
 
-    RTTESTI_CHECK_RC_OK(AudioMixBufWriteAt(&mb, 2, &samples32, sizeof(samples32), &written));
-    RTTESTI_CHECK(written == 2 /* Samples */);
-    written_abs = 0;
+    RTTESTI_CHECK_RC_OK(AudioMixBufWriteAt(&mb, 2 /* Offset */, &samples32, sizeof(samples32), &cSamplesWritten));
+    RTTESTI_CHECK(cSamplesWritten == 2 /* Samples */);
+    RTTESTI_CHECK(AudioMixBufUsed(&mb) == 2);
 
     /* Beyond buffer. */
     RTTESTI_CHECK_RC(AudioMixBufWriteAt(&mb, AudioMixBufSize(&mb) + 1, &samples16, sizeof(samples16),
-                                        &written), VERR_BUFFER_OVERFLOW);
+                                        &cSamplesWritten), VERR_BUFFER_OVERFLOW);
+
+    /* Offset wrap-around: When writing as much (or more) samples the mixing buffer can hold. */
+    size_t    cbSamples = cBufSize * sizeof(int16_t) * 2 /* Channels */;
+    RTTESTI_CHECK(cbSamples);
+    uint16_t *paSamples = (uint16_t *)RTMemAlloc(cbSamples);
+    RTTESTI_CHECK(paSamples);
+    RTTESTI_CHECK_RC_OK(AudioMixBufWriteAt(&mb, 0 /* Offset */, paSamples, (uint32_t)cbSamples, &cSamplesWritten));
+    RTTESTI_CHECK(cSamplesWritten == cBufSize /* Samples */);
+    RTTESTI_CHECK(AudioMixBufUsed(&mb) == cBufSize);
+    RTTESTI_CHECK(AudioMixBufReadPos(&mb) == 0);
+    RTTESTI_CHECK(AudioMixBufWritePos(&mb) == 0);
+    RTMemFree(paSamples);
+    cbSamples = 0;
 
     /*
      * Circular writes.
      */
-    uint32_t cToWrite = AudioMixBufSize(&mb) - written_abs - 1; /* -1 as padding plus -2 samples for above. */
+    AudioMixBufReset(&mb);
+
+    RTTESTI_CHECK_RC_OK(AudioMixBufWriteAt(&mb, 2 /* Offset */, &samples32, sizeof(samples32), &cSamplesWritten));
+    RTTESTI_CHECK(cSamplesWritten == 2 /* Samples */);
+    RTTESTI_CHECK(AudioMixBufUsed(&mb) == 2);
+
+    cSamplesWrittenAbs = AudioMixBufUsed(&mb);
+
+    uint32_t cToWrite = AudioMixBufSize(&mb) - cSamplesWrittenAbs - 1; /* -1 as padding plus -2 samples for above. */
     for (uint32_t i = 0; i < cToWrite; i++)
     {
-        RTTESTI_CHECK_RC_OK(AudioMixBufWriteCirc(&mb, &samples16, sizeof(samples16), &written));
-        RTTESTI_CHECK(written == 1);
+        RTTESTI_CHECK_RC_OK(AudioMixBufWriteCirc(&mb, &samples16, sizeof(samples16), &cSamplesWritten));
+        RTTESTI_CHECK(cSamplesWritten == 1);
     }
     RTTESTI_CHECK(!AudioMixBufIsEmpty(&mb));
     RTTESTI_CHECK(AudioMixBufFree(&mb) == 1);
     RTTESTI_CHECK(AudioMixBufFreeBytes(&mb) == AUDIOMIXBUF_S2B(&mb, 1U));
-    RTTESTI_CHECK(AudioMixBufProcessed(&mb) == cToWrite + written_abs /* + last absolute write */);
+    RTTESTI_CHECK(AudioMixBufUsed(&mb) == cToWrite + cSamplesWrittenAbs /* + last absolute write */);
 
-    RTTESTI_CHECK_RC_OK(AudioMixBufWriteCirc(&mb, &samples16, sizeof(samples16), &written));
-    RTTESTI_CHECK(written == 1);
+    RTTESTI_CHECK_RC_OK(AudioMixBufWriteCirc(&mb, &samples16, sizeof(samples16), &cSamplesWritten));
+    RTTESTI_CHECK(cSamplesWritten == 1);
     RTTESTI_CHECK(AudioMixBufFree(&mb) == 0);
-    RTTESTI_CHECK(AudioMixBufFreeBytes(&mb) == (uint32_t)AUDIOMIXBUF_S2B(&mb, 0));
-    RTTESTI_CHECK(AudioMixBufProcessed(&mb) == cBufSize);
+    RTTESTI_CHECK(AudioMixBufFreeBytes(&mb) == AUDIOMIXBUF_S2B(&mb, 0U));
+    RTTESTI_CHECK(AudioMixBufUsed(&mb) == cBufSize);
 
     /* Circular reads. */
-    uint32_t cToRead = AudioMixBufSize(&mb) - written_abs - 1;
-    for (uint32_t i = 0; i < cToWrite; i++)
+    uint32_t cToRead = AudioMixBufSize(&mb) - cSamplesWrittenAbs - 1;
+    for (uint32_t i = 0; i < cToRead; i++)
     {
-        RTTESTI_CHECK_RC_OK(AudioMixBufReadCirc(&mb, &samples16, sizeof(samples16), &read));
-        RTTESTI_CHECK(read == 1);
-        AudioMixBufFinish(&mb, read);
+        RTTESTI_CHECK_RC_OK(AudioMixBufReadCirc(&mb, &samples16, sizeof(samples16), &cSamplesRead));
+        RTTESTI_CHECK(cSamplesRead == 1);
+        AudioMixBufFinish(&mb, cSamplesRead);
     }
     RTTESTI_CHECK(!AudioMixBufIsEmpty(&mb));
-    RTTESTI_CHECK(AudioMixBufFree(&mb) == AudioMixBufSize(&mb) - written_abs - 1);
-    RTTESTI_CHECK(AudioMixBufFreeBytes(&mb) == AUDIOMIXBUF_S2B(&mb, cBufSize - written_abs - 1));
-    RTTESTI_CHECK(AudioMixBufProcessed(&mb) == cBufSize - cToRead + written_abs);
+    RTTESTI_CHECK(AudioMixBufFree(&mb) == AudioMixBufSize(&mb) - cSamplesWrittenAbs - 1);
+    RTTESTI_CHECK(AudioMixBufFreeBytes(&mb) == AUDIOMIXBUF_S2B(&mb, cBufSize - cSamplesWrittenAbs - 1));
+    RTTESTI_CHECK(AudioMixBufUsed(&mb) == cBufSize - cToRead);
 
-    RTTESTI_CHECK_RC_OK(AudioMixBufReadCirc(&mb, &samples16, sizeof(samples16), &read));
-    RTTESTI_CHECK(read == 1);
-    AudioMixBufFinish(&mb, read);
-    RTTESTI_CHECK(AudioMixBufFree(&mb) == cBufSize - written_abs);
-    RTTESTI_CHECK(AudioMixBufFreeBytes(&mb) == AUDIOMIXBUF_S2B(&mb, cBufSize - written_abs));
-    RTTESTI_CHECK(AudioMixBufProcessed(&mb) == written_abs);
+    RTTESTI_CHECK_RC_OK(AudioMixBufReadCirc(&mb, &samples16, sizeof(samples16), &cSamplesRead));
+    RTTESTI_CHECK(cSamplesRead == 1);
+    AudioMixBufFinish(&mb, cSamplesRead);
+    RTTESTI_CHECK(AudioMixBufFree(&mb) == cBufSize - cSamplesWrittenAbs);
+    RTTESTI_CHECK(AudioMixBufFreeBytes(&mb) == AUDIOMIXBUF_S2B(&mb, cBufSize - cSamplesWrittenAbs));
+    RTTESTI_CHECK(AudioMixBufUsed(&mb) == cSamplesWrittenAbs);
 
     AudioMixBufDestroy(&mb);
 
@@ -134,53 +160,62 @@ static int tstSingle(RTTEST hTest)
 
 static int tstParentChild(RTTEST hTest)
 {
-    RTTestSubF(hTest, "2 Children -> Parent");
+    uint32_t cParentBufSize = RTRandU32Ex(_1K /* Min */, _16K /* Max */); /* Enough room for random sizes */
 
-    uint32_t cBufSize = _1K;
-
-    PDMAUDIOSTREAMCFG cfg_p =
+    /* 44100Hz, 2 Channels, S16 */
+    PDMAUDIOPCMPROPS cfg_p =
     {
-        44100,                   /* Hz */
-        2                        /* Channels */,
-        AUD_FMT_S16              /* Format */,
-        PDMAUDIOENDIANNESS_LITTLE /* ENDIANNESS */
+        16,                                                                 /* Bits */
+        true,                                                               /* Signed */
+        PDMAUDIOPCMPROPS_MAKE_SHIFT_PARMS(16 /* Bits */, 2 /* Channels */), /* Shift */
+        2,                                                                  /* Channels */
+        0,                                                                  /* Alignment mask */
+        44100,                                                              /* Hz */
+        false                                                               /* Swap Endian */
     };
-    PDMPCMPROPS props;
 
-    int rc = DrvAudioStreamCfgToProps(&cfg_p, &props);
-    AssertRC(rc);
+    RTTESTI_CHECK(DrvAudioHlpPCMPropsAreValid(&cfg_p));
 
     PDMAUDIOMIXBUF parent;
-    RTTESTI_CHECK_RC_OK(AudioMixBufInit(&parent, "Parent", &props, cBufSize));
+    RTTESTI_CHECK_RC_OK(AudioMixBufInit(&parent, "Parent", &cfg_p, cParentBufSize));
 
-    PDMAUDIOSTREAMCFG cfg_c1 = /* Upmixing to parent */
+    /* 22050Hz, 2 Channels, S16 */
+    PDMAUDIOPCMPROPS cfg_c1 = /* Upmixing to parent */
     {
-        22100,                   /* Hz */
-        2                        /* Channels */,
-        AUD_FMT_S16              /* Format */,
-        PDMAUDIOENDIANNESS_LITTLE /* ENDIANNESS */
+        16,                                                                 /* Bits */
+        true,                                                               /* Signed */
+        PDMAUDIOPCMPROPS_MAKE_SHIFT_PARMS(16 /* Bits */, 2 /* Channels */), /* Shift */
+        2,                                                                  /* Channels */
+        0,                                                                  /* Alignment mask */
+        22050,                                                              /* Hz */
+        false                                                               /* Swap Endian */
     };
 
-    rc = DrvAudioStreamCfgToProps(&cfg_c1, &props);
-    AssertRC(rc);
+    RTTESTI_CHECK(DrvAudioHlpPCMPropsAreValid(&cfg_c1));
+
+    uint32_t cSamples      = 16;
+    uint32_t cChildBufSize = RTRandU32Ex(cSamples /* Min */, 64 /* Max */);
 
     PDMAUDIOMIXBUF child1;
-    RTTESTI_CHECK_RC_OK(AudioMixBufInit(&child1, "Child1", &props, cBufSize));
+    RTTESTI_CHECK_RC_OK(AudioMixBufInit(&child1, "Child1", &cfg_c1, cChildBufSize));
     RTTESTI_CHECK_RC_OK(AudioMixBufLinkTo(&child1, &parent));
 
-    PDMAUDIOSTREAMCFG cfg_c2 = /* Downmixing to parent */
+    /* 48000Hz, 2 Channels, S16 */
+    PDMAUDIOPCMPROPS cfg_c2 = /* Downmixing to parent */
     {
-        48000,                   /* Hz */
-        2                        /* Channels */,
-        AUD_FMT_S16              /* Format */,
-        PDMAUDIOENDIANNESS_LITTLE /* ENDIANNESS */
+        16,                                                                 /* Bits */
+        true,                                                               /* Signed */
+        PDMAUDIOPCMPROPS_MAKE_SHIFT_PARMS(16 /* Bits */, 2 /* Channels */), /* Shift */
+        2,                                                                  /* Channels */
+        0,                                                                  /* Alignment mask */
+        48000,                                                              /* Hz */
+        false                                                               /* Swap Endian */
     };
 
-    rc = DrvAudioStreamCfgToProps(&cfg_c2, &props);
-    AssertRC(rc);
+    RTTESTI_CHECK(DrvAudioHlpPCMPropsAreValid(&cfg_c2));
 
     PDMAUDIOMIXBUF child2;
-    RTTESTI_CHECK_RC_OK(AudioMixBufInit(&child2, "Child2", &props, cBufSize));
+    RTTESTI_CHECK_RC_OK(AudioMixBufInit(&child2, "Child2", &cfg_c2, cChildBufSize));
     RTTESTI_CHECK_RC_OK(AudioMixBufLinkTo(&child2, &parent));
 
     /*
@@ -189,49 +224,81 @@ static int tstParentChild(RTTEST hTest)
     uint32_t cbBuf = _1K;
     char pvBuf[_1K];
     int16_t samples[32] = { 0xAA, 0xBB };
-    uint32_t read , written, mixed, temp;
+    uint32_t cSamplesRead, cSamplesWritten, cSamplesMixed;
 
-    //unused//uint32_t cChild1Free     = cBufSize;
-    //unused//uint32_t cChild1Mixed    = 0;
-    //unused//uint32_t cSamplesParent1 = 16;
-    uint32_t cSamplesChild1  = 16;
+    uint32_t cSamplesChild1  = cSamples;
+    uint32_t cSamplesChild2  = cSamples;
 
-    //unused//uint32_t cChild2Free     = cBufSize;
-    //unused//uint32_t cChild2Mixed    = 0;
-    //unused//uint32_t cSamplesParent2 = 16;
-    uint32_t cSamplesChild2  = 16;
+    uint32_t t = RTRandU32() % 32;
 
-    uint32_t t = RTRandU32() % 64;
+    RTTestPrintf(hTest, RTTESTLVL_DEBUG,
+                 "cParentBufSize=%RU32, cChildBufSize=%RU32, %RU32 samples -> %RU32 iterations total\n",
+                 cParentBufSize, cChildBufSize, cSamples, t);
+
+    /*
+     * Using AudioMixBufWriteAt for writing to children.
+     */
+    RTTestSubF(hTest, "2 Children -> Parent (AudioMixBufWriteAt)");
+
+    uint32_t cChildrenSamplesMixedTotal = 0;
 
     for (uint32_t i = 0; i < t; i++)
     {
         RTTestPrintf(hTest, RTTESTLVL_DEBUG, "i=%RU32\n", i);
-        RTTESTI_CHECK_RC_OK_BREAK(AudioMixBufWriteAt(&child1, 0, &samples, sizeof(samples), &written));
-        RTTESTI_CHECK_MSG_BREAK(written == cSamplesChild1, ("Child1: Expected %RU32 written samples, got %RU32\n", cSamplesChild1, written));
-        RTTESTI_CHECK_RC_OK_BREAK(AudioMixBufMixToParent(&child1, written, &mixed));
-        temp = AudioMixBufProcessed(&parent) - AudioMixBufMixed(&child2);
-        RTTESTI_CHECK_MSG_BREAK(AudioMixBufMixed(&child1) == temp, ("Child1: Expected %RU32 mixed samples, got %RU32\n", AudioMixBufMixed(&child1), temp));
-
-        RTTESTI_CHECK_RC_OK_BREAK(AudioMixBufWriteAt(&child2, 0, &samples, sizeof(samples), &written));
-        RTTESTI_CHECK_MSG_BREAK(written == cSamplesChild2, ("Child2: Expected %RU32 written samples, got %RU32\n", cSamplesChild2, written));
-        RTTESTI_CHECK_RC_OK_BREAK(AudioMixBufMixToParent(&child2, written, &mixed));
-        temp = AudioMixBufProcessed(&parent) - AudioMixBufMixed(&child1);
-        RTTESTI_CHECK_MSG_BREAK(AudioMixBufMixed(&child2) == temp, ("Child2: Expected %RU32 mixed samples, got %RU32\n", AudioMixBufMixed(&child2), temp));
-    }
 
-    RTTESTI_CHECK(AudioMixBufProcessed(&parent) == AudioMixBufMixed(&child1) + AudioMixBufMixed(&child2));
+        uint32_t cChild1Writes = RTRandU32() % 8;
 
-    for (;;)
-    {
-        RTTESTI_CHECK_RC_OK_BREAK(AudioMixBufReadCirc(&parent, pvBuf, cbBuf, &read));
-        if (!read)
-            break;
-        AudioMixBufFinish(&parent, read);
+        for (uint32_t c1 = 0; c1 < cChild1Writes; c1++)
+        {
+            /* Child 1. */
+            RTTESTI_CHECK_RC_OK_BREAK(AudioMixBufWriteAt(&child1, 0, &samples, sizeof(samples), &cSamplesWritten));
+            RTTESTI_CHECK_MSG_BREAK(cSamplesWritten == cSamplesChild1, ("Child1: Expected %RU32 written samples, got %RU32\n", cSamplesChild1, cSamplesWritten));
+            RTTESTI_CHECK_RC_OK_BREAK(AudioMixBufMixToParent(&child1, cSamplesWritten, &cSamplesMixed));
+
+            cChildrenSamplesMixedTotal += cSamplesMixed;
+
+            RTTESTI_CHECK_MSG_BREAK(cSamplesWritten == cSamplesMixed, ("Child1: Expected %RU32 mixed samples, got %RU32\n", cSamplesWritten, cSamplesMixed));
+            RTTESTI_CHECK_MSG_BREAK(AudioMixBufUsed(&child1) == 0, ("Child1: Expected %RU32 used samples, got %RU32\n", 0, AudioMixBufUsed(&child1)));
+        }
+
+        uint32_t cChild2Writes = RTRandU32() % 8;
+
+        for (uint32_t c2 = 0; c2 < cChild2Writes; c2++)
+        {
+            /* Child 2. */
+            RTTESTI_CHECK_RC_OK_BREAK(AudioMixBufWriteAt(&child2, 0, &samples, sizeof(samples), &cSamplesWritten));
+            RTTESTI_CHECK_MSG_BREAK(cSamplesWritten == cSamplesChild2, ("Child2: Expected %RU32 written samples, got %RU32\n", cSamplesChild2, cSamplesWritten));
+            RTTESTI_CHECK_RC_OK_BREAK(AudioMixBufMixToParent(&child2, cSamplesWritten, &cSamplesMixed));
+
+            cChildrenSamplesMixedTotal += cSamplesMixed;
+
+            RTTESTI_CHECK_MSG_BREAK(cSamplesWritten == cSamplesMixed, ("Child2: Expected %RU32 mixed samples, got %RU32\n", cSamplesWritten, cSamplesMixed));
+            RTTESTI_CHECK_MSG_BREAK(AudioMixBufUsed(&child2) == 0, ("Child2: Expected %RU32 used samples, got %RU32\n", 0, AudioMixBufUsed(&child2)));
+        }
+
+        /*
+         * Read out all samples from the parent buffer and also mark the just-read samples as finished
+         * so that both connected children buffers can keep track of their stuff.
+         */
+        uint32_t cParentSamples = AudioMixBufUsed(&parent);
+        while (cParentSamples)
+        {
+            RTTESTI_CHECK_RC_OK_BREAK(AudioMixBufReadCirc(&parent, pvBuf, cbBuf, &cSamplesRead));
+            if (!cSamplesRead)
+                break;
+
+            AudioMixBufFinish(&parent, cSamplesRead);
+
+            RTTESTI_CHECK(cParentSamples >= cSamplesRead);
+            cParentSamples -= cSamplesRead;
+        }
+
+        RTTESTI_CHECK(cParentSamples == 0);
     }
 
-    RTTESTI_CHECK(AudioMixBufProcessed(&parent) == 0);
-    RTTESTI_CHECK(AudioMixBufMixed(&child1) == 0);
-    RTTESTI_CHECK(AudioMixBufMixed(&child2) == 0);
+    RTTESTI_CHECK(AudioMixBufUsed(&parent) == 0);
+    RTTESTI_CHECK(AudioMixBufLive(&child1) == 0);
+    RTTESTI_CHECK(AudioMixBufLive(&child2) == 0);
 
     AudioMixBufDestroy(&parent);
     AudioMixBufDestroy(&child1);
@@ -243,26 +310,27 @@ static int tstParentChild(RTTEST hTest)
 /* Test 8-bit sample conversion (8-bit -> internal -> 8-bit). */
 static int tstConversion8(RTTEST hTest)
 {
-    unsigned        i;
-    uint32_t        cBufSize = 256;
-    PDMPCMPROPS     props;
+    unsigned         i;
+    uint32_t         cBufSize = 256;
 
+    RTTestSubF(hTest, "Sample conversion (U8)");
 
-    RTTestSubF(hTest, "Sample conversion");
-
-    PDMAUDIOSTREAMCFG cfg_p =
+    /* 44100Hz, 1 Channel, U8 */
+    PDMAUDIOPCMPROPS cfg_p =
     {
-        44100,                   /* Hz */
-        1                        /* Channels */,
-        AUD_FMT_U8               /* Format */,
-        PDMAUDIOENDIANNESS_LITTLE /* ENDIANNESS */
+        8,                                                                 /* Bits */
+        false,                                                             /* Signed */
+        PDMAUDIOPCMPROPS_MAKE_SHIFT_PARMS(8 /* Bits */, 1 /* Channels */), /* Shift */
+        1,                                                                 /* Channels */
+        0,                                                                  /* Alignment mask */
+        44100,                                                             /* Hz */
+        false                                                              /* Swap Endian */
     };
 
-    int rc = DrvAudioStreamCfgToProps(&cfg_p, &props);
-    AssertRC(rc);
+    RTTESTI_CHECK(DrvAudioHlpPCMPropsAreValid(&cfg_p));
 
     PDMAUDIOMIXBUF parent;
-    RTTESTI_CHECK_RC_OK(AudioMixBufInit(&parent, "Parent", &props, cBufSize));
+    RTTESTI_CHECK_RC_OK(AudioMixBufInit(&parent, "Parent", &cfg_p, cBufSize));
 
     /* Child uses half the sample rate; that ensures the mixing engine can't
      * take shortcuts and performs conversion. Because conversion to double
@@ -271,57 +339,60 @@ static int tstConversion8(RTTEST hTest)
      * samples. However, the last source sample will be saved for later
      * interpolation and not immediately output.
      */
-    PDMAUDIOSTREAMCFG cfg_c =   /* Upmixing to parent */
+
+    /* 22050Hz, 1 Channel, U8 */
+    PDMAUDIOPCMPROPS cfg_c =   /* Upmixing to parent */
     {
-        22050,                   /* Hz */
-        1                        /* Channels */,
-        AUD_FMT_U8               /* Format */,
-        PDMAUDIOENDIANNESS_LITTLE /* ENDIANNESS */
+        8,                                                                 /* Bits */
+        false,                                                             /* Signed */
+        PDMAUDIOPCMPROPS_MAKE_SHIFT_PARMS(8 /* Bits */, 1 /* Channels */), /* Shift */
+        1,                                                                 /* Channels */
+        0,                                                                 /* Alignment mask */
+        22050,                                                             /* Hz */
+        false                                                              /* Swap Endian */
     };
 
-    rc = DrvAudioStreamCfgToProps(&cfg_c, &props);
-    AssertRC(rc);
+    RTTESTI_CHECK(DrvAudioHlpPCMPropsAreValid(&cfg_c));
 
     PDMAUDIOMIXBUF child;
-    RTTESTI_CHECK_RC_OK(AudioMixBufInit(&child, "Child", &props, cBufSize));
+    RTTESTI_CHECK_RC_OK(AudioMixBufInit(&child, "Child", &cfg_c, cBufSize));
     RTTESTI_CHECK_RC_OK(AudioMixBufLinkTo(&child, &parent));
 
     /* 8-bit unsigned samples. Often used with SB16 device. */
-    uint8_t     samples[16]  = { 0xAA, 0xBB, 0, 1, 43, 125, 126, 127,
-                                 128, 129, 130, 131, 132, UINT8_MAX - 1, UINT8_MAX, 0 };
+    uint8_t samples[16]  = { 0xAA, 0xBB, 0, 1, 43, 125, 126, 127,
+                             128, 129, 130, 131, 132, UINT8_MAX - 1, UINT8_MAX, 0 };
 
     /*
      * Writing + mixing from child -> parent, sequential.
      */
     uint32_t    cbBuf = 256;
     char        achBuf[256];
-    uint32_t    read, written, mixed, temp;
+    uint32_t    cSamplesRead, cSamplesWritten, cSamplesMixed;
 
-    //unused//uint32_t cChildFree     = cBufSize;
-    //unused//uint32_t cChildMixed    = 0;
     uint32_t cSamplesChild  = 16;
     uint32_t cSamplesParent = cSamplesChild * 2 - 2;
-    uint32_t cSamplesRead   = 0;
+    uint32_t cSamplesTotalRead   = 0;
 
     /**** 8-bit unsigned samples ****/
     RTTestPrintf(hTest, RTTESTLVL_DEBUG, "Conversion test %uHz %uch 8-bit\n", cfg_c.uHz, cfg_c.cChannels);
-    RTTESTI_CHECK_RC_OK(AudioMixBufWriteAt(&child, 0, &samples, sizeof(samples), &written));
-    RTTESTI_CHECK_MSG(written == cSamplesChild, ("Child: Expected %RU32 written samples, got %RU32\n", cSamplesChild, written));
-    RTTESTI_CHECK_RC_OK(AudioMixBufMixToParent(&child, written, &mixed));
-    temp = AudioMixBufProcessed(&parent);
-    RTTESTI_CHECK_MSG(AudioMixBufMixed(&child) == temp, ("Child: Expected %RU32 mixed samples, got %RU32\n", AudioMixBufMixed(&child), temp));
+    RTTESTI_CHECK_RC_OK(AudioMixBufWriteCirc(&child, &samples, sizeof(samples), &cSamplesWritten));
+    RTTESTI_CHECK_MSG(cSamplesWritten == cSamplesChild, ("Child: Expected %RU32 written samples, got %RU32\n", cSamplesChild, cSamplesWritten));
+    RTTESTI_CHECK_RC_OK(AudioMixBufMixToParent(&child, cSamplesWritten, &cSamplesMixed));
+    uint32_t cSamples = AudioMixBufUsed(&parent);
+    RTTESTI_CHECK_MSG(AudioMixBufLive(&child) == cSamples, ("Child: Expected %RU32 mixed samples, got %RU32\n", AudioMixBufLive(&child), cSamples));
 
-    RTTESTI_CHECK(AudioMixBufProcessed(&parent) == AudioMixBufMixed(&child));
+    RTTESTI_CHECK(AudioMixBufUsed(&parent) == AudioMixBufLive(&child));
 
     for (;;)
     {
-        RTTESTI_CHECK_RC_OK_BREAK(AudioMixBufReadCirc(&parent, achBuf, cbBuf, &read));
-        if (!read)
+        RTTESTI_CHECK_RC_OK_BREAK(AudioMixBufReadCirc(&parent, achBuf, cbBuf, &cSamplesRead));
+        if (!cSamplesRead)
             break;
-        cSamplesRead += read;
-        AudioMixBufFinish(&parent, read);
+        cSamplesTotalRead += cSamplesRead;
+        AudioMixBufFinish(&parent, cSamplesRead);
     }
-    RTTESTI_CHECK_MSG(cSamplesRead == cSamplesParent, ("Parent: Expected %RU32 mixed samples, got %RU32\n", cSamplesParent, cSamplesRead));
+
+    RTTESTI_CHECK_MSG(cSamplesTotalRead == cSamplesParent, ("Parent: Expected %RU32 mixed samples, got %RU32\n", cSamplesParent, cSamplesTotalRead));
 
     /* Check that the samples came out unharmed. Every other sample is interpolated and we ignore it. */
     /* NB: This also checks that the default volume setting is 0dB attenuation. */
@@ -335,8 +406,8 @@ static int tstConversion8(RTTEST hTest)
         pDst8 += 2;
     }
 
-    RTTESTI_CHECK(AudioMixBufProcessed(&parent) == 0);
-    RTTESTI_CHECK(AudioMixBufMixed(&child) == 0);
+    RTTESTI_CHECK(AudioMixBufUsed(&parent) == 0);
+    RTTESTI_CHECK(AudioMixBufLive(&child)  == 0);
 
     AudioMixBufDestroy(&parent);
     AudioMixBufDestroy(&child);
@@ -347,40 +418,44 @@ static int tstConversion8(RTTEST hTest)
 /* Test 16-bit sample conversion (16-bit -> internal -> 16-bit). */
 static int tstConversion16(RTTEST hTest)
 {
-    unsigned        i;
-    uint32_t        cBufSize = 256;
-    PDMPCMPROPS     props;
-
+    unsigned         i;
+    uint32_t         cBufSize = 256;
 
-    RTTestSubF(hTest, "Sample conversion 16-bit");
+    RTTestSubF(hTest, "Sample conversion (S16)");
 
-    PDMAUDIOSTREAMCFG cfg_p =
+    /* 44100Hz, 1 Channel, S16 */
+    PDMAUDIOPCMPROPS cfg_p =
     {
-        44100,                   /* Hz */
-        1                        /* Channels */,
-        AUD_FMT_S16              /* Format */,
-        PDMAUDIOENDIANNESS_LITTLE /* ENDIANNESS */
+        16,                                                                 /* Bits */
+        true,                                                               /* Signed */
+        PDMAUDIOPCMPROPS_MAKE_SHIFT_PARMS(16 /* Bits */, 1 /* Channels */), /* Shift */
+        1,                                                                  /* Channels */
+        0,                                                                  /* Alignment mask */
+        44100,                                                              /* Hz */
+        false                                                               /* Swap Endian */
     };
 
-    int rc = DrvAudioStreamCfgToProps(&cfg_p, &props);
-    AssertRC(rc);
+    RTTESTI_CHECK(DrvAudioHlpPCMPropsAreValid(&cfg_p));
 
     PDMAUDIOMIXBUF parent;
-    RTTESTI_CHECK_RC_OK(AudioMixBufInit(&parent, "Parent", &props, cBufSize));
+    RTTESTI_CHECK_RC_OK(AudioMixBufInit(&parent, "Parent", &cfg_p, cBufSize));
 
-    PDMAUDIOSTREAMCFG cfg_c =   /* Upmixing to parent */
+    /* 22050Hz, 1 Channel, S16 */
+    PDMAUDIOPCMPROPS cfg_c =   /* Upmixing to parent */
     {
-        22050,                   /* Hz */
-        1                        /* Channels */,
-        AUD_FMT_S16              /* Format */,
-        PDMAUDIOENDIANNESS_LITTLE /* ENDIANNESS */
+        16,                                                                 /* Bits */
+        true,                                                               /* Signed */
+        PDMAUDIOPCMPROPS_MAKE_SHIFT_PARMS(16 /* Bits */, 1 /* Channels */), /* Shift */
+        1,                                                                  /* Channels */
+        0,                                                                  /* Alignment mask */
+        22050,                                                              /* Hz */
+        false                                                               /* Swap Endian */
     };
 
-    rc = DrvAudioStreamCfgToProps(&cfg_c, &props);
-    AssertRC(rc);
+    RTTESTI_CHECK(DrvAudioHlpPCMPropsAreValid(&cfg_c));
 
     PDMAUDIOMIXBUF child;
-    RTTESTI_CHECK_RC_OK(AudioMixBufInit(&child, "Child", &props, cBufSize));
+    RTTESTI_CHECK_RC_OK(AudioMixBufInit(&child, "Child", &cfg_c, cBufSize));
     RTTESTI_CHECK_RC_OK(AudioMixBufLinkTo(&child, &parent));
 
     /* 16-bit signed. More or less exclusively used as output, and usually as input, too. */
@@ -392,33 +467,31 @@ static int tstConversion16(RTTEST hTest)
      */
     uint32_t    cbBuf = 256;
     char        achBuf[256];
-    uint32_t    read, written, mixed, temp;
+    uint32_t    cSamplesRead, cSamplesWritten, cSamplesMixed;
 
-    //unused//uint32_t cChildFree     = cBufSize;
-    //unused//uint32_t cChildMixed    = 0;
     uint32_t cSamplesChild  = 16;
     uint32_t cSamplesParent = cSamplesChild * 2 - 2;
-    uint32_t cSamplesRead   = 0;
+    uint32_t cSamplesTotalRead   = 0;
 
     /**** 16-bit signed samples ****/
     RTTestPrintf(hTest, RTTESTLVL_DEBUG, "Conversion test %uHz %uch 16-bit\n", cfg_c.uHz, cfg_c.cChannels);
-    RTTESTI_CHECK_RC_OK(AudioMixBufWriteAt(&child, 0, &samples, sizeof(samples), &written));
-    RTTESTI_CHECK_MSG(written == cSamplesChild, ("Child: Expected %RU32 written samples, got %RU32\n", cSamplesChild, written));
-    RTTESTI_CHECK_RC_OK(AudioMixBufMixToParent(&child, written, &mixed));
-    temp = AudioMixBufProcessed(&parent);
-    RTTESTI_CHECK_MSG(AudioMixBufMixed(&child) == temp, ("Child: Expected %RU32 mixed samples, got %RU32\n", AudioMixBufMixed(&child), temp));
+    RTTESTI_CHECK_RC_OK(AudioMixBufWriteCirc(&child, &samples, sizeof(samples), &cSamplesWritten));
+    RTTESTI_CHECK_MSG(cSamplesWritten == cSamplesChild, ("Child: Expected %RU32 written samples, got %RU32\n", cSamplesChild, cSamplesWritten));
+    RTTESTI_CHECK_RC_OK(AudioMixBufMixToParent(&child, cSamplesWritten, &cSamplesMixed));
+    uint32_t cSamples = AudioMixBufUsed(&parent);
+    RTTESTI_CHECK_MSG(AudioMixBufLive(&child) == cSamples, ("Child: Expected %RU32 mixed samples, got %RU32\n", AudioMixBufLive(&child), cSamples));
 
-    RTTESTI_CHECK(AudioMixBufProcessed(&parent) == AudioMixBufMixed(&child));
+    RTTESTI_CHECK(AudioMixBufUsed(&parent) == AudioMixBufLive(&child));
 
     for (;;)
     {
-        RTTESTI_CHECK_RC_OK_BREAK(AudioMixBufReadCirc(&parent, achBuf, cbBuf, &read));
-        if (!read)
+        RTTESTI_CHECK_RC_OK_BREAK(AudioMixBufReadCirc(&parent, achBuf, cbBuf, &cSamplesRead));
+        if (!cSamplesRead)
             break;
-        cSamplesRead += read;
-        AudioMixBufFinish(&parent, read);
+        cSamplesTotalRead += cSamplesRead;
+        AudioMixBufFinish(&parent, cSamplesRead);
     }
-    RTTESTI_CHECK_MSG(cSamplesRead == cSamplesParent, ("Parent: Expected %RU32 mixed samples, got %RU32\n", cSamplesParent, cSamplesRead));
+    RTTESTI_CHECK_MSG(cSamplesTotalRead == cSamplesParent, ("Parent: Expected %RU32 mixed samples, got %RU32\n", cSamplesParent, cSamplesTotalRead));
 
     /* Check that the samples came out unharmed. Every other sample is interpolated and we ignore it. */
     /* NB: This also checks that the default volume setting is 0dB attenuation. */
@@ -432,8 +505,8 @@ static int tstConversion16(RTTEST hTest)
         pDst16 += 2;
     }
 
-    RTTESTI_CHECK(AudioMixBufProcessed(&parent) == 0);
-    RTTESTI_CHECK(AudioMixBufMixed(&child) == 0);
+    RTTESTI_CHECK(AudioMixBufUsed(&parent) == 0);
+    RTTESTI_CHECK(AudioMixBufLive(&child)  == 0);
 
     AudioMixBufDestroy(&parent);
     AudioMixBufDestroy(&child);
@@ -444,31 +517,32 @@ static int tstConversion16(RTTEST hTest)
 /* Test volume control. */
 static int tstVolume(RTTEST hTest)
 {
-    unsigned        i;
-    uint32_t        cBufSize = 256;
-    PDMPCMPROPS     props;
-
+    unsigned         i;
+    uint32_t         cBufSize = 256;
 
     RTTestSubF(hTest, "Volume control");
 
     /* Same for parent/child. */
-    PDMAUDIOSTREAMCFG cfg =
+    /* 44100Hz, 2 Channels, S16 */
+    PDMAUDIOPCMPROPS cfg =
     {
-        44100,                   /* Hz */
-        2                        /* Channels */,
-        AUD_FMT_S16              /* Format */,
-        PDMAUDIOENDIANNESS_LITTLE /* ENDIANNESS */
+        16,                                                                 /* Bits */
+        true,                                                               /* Signed */
+        PDMAUDIOPCMPROPS_MAKE_SHIFT_PARMS(16 /* Bits */, 2 /* Channels */), /* Shift */
+        2,                                                                  /* Channels */
+        0,                                                                  /* Alignment mask */
+        44100,                                                              /* Hz */
+        false                                                               /* Swap Endian */
     };
 
-    int rc = DrvAudioStreamCfgToProps(&cfg, &props);
-    AssertRC(rc);
+    RTTESTI_CHECK(DrvAudioHlpPCMPropsAreValid(&cfg));
 
     PDMAUDIOVOLUME vol = { false, 0, 0 };   /* Not muted. */
     PDMAUDIOMIXBUF parent;
-    RTTESTI_CHECK_RC_OK(AudioMixBufInit(&parent, "Parent", &props, cBufSize));
+    RTTESTI_CHECK_RC_OK(AudioMixBufInit(&parent, "Parent", &cfg, cBufSize));
 
     PDMAUDIOMIXBUF child;
-    RTTESTI_CHECK_RC_OK(AudioMixBufInit(&child, "Child", &props, cBufSize));
+    RTTESTI_CHECK_RC_OK(AudioMixBufInit(&child, "Child", &cfg, cBufSize));
     RTTESTI_CHECK_RC_OK(AudioMixBufLinkTo(&child, &parent));
 
     /* A few 16-bit signed samples. */
@@ -480,13 +554,11 @@ static int tstVolume(RTTEST hTest)
      */
     uint32_t    cbBuf = 256;
     char        achBuf[256];
-    uint32_t    read, written, mixed;
+    uint32_t    cSamplesRead, cSamplesWritten, cSamplesMixed;
 
-    //unused//uint32_t cChildFree     = cBufSize;
-    //unused//uint32_t cChildMixed    = 0;
     uint32_t cSamplesChild  = 8;
     uint32_t cSamplesParent = cSamplesChild;
-    uint32_t cSamplesRead;
+    uint32_t cSamplesTotalRead;
     int16_t *pSrc16;
     int16_t *pDst16;
 
@@ -497,20 +569,20 @@ static int tstVolume(RTTEST hTest)
     vol.uLeft = vol.uRight = 255;
     AudioMixBufSetVolume(&child, &vol);
 
-    RTTESTI_CHECK_RC_OK(AudioMixBufWriteAt(&child, 0, &samples, sizeof(samples), &written));
-    RTTESTI_CHECK_MSG(written == cSamplesChild, ("Child: Expected %RU32 written samples, got %RU32\n", cSamplesChild, written));
-    RTTESTI_CHECK_RC_OK(AudioMixBufMixToParent(&child, written, &mixed));
+    RTTESTI_CHECK_RC_OK(AudioMixBufWriteCirc(&child, &samples, sizeof(samples), &cSamplesWritten));
+    RTTESTI_CHECK_MSG(cSamplesWritten == cSamplesChild, ("Child: Expected %RU32 written samples, got %RU32\n", cSamplesChild, cSamplesWritten));
+    RTTESTI_CHECK_RC_OK(AudioMixBufMixToParent(&child, cSamplesWritten, &cSamplesMixed));
 
-    cSamplesRead = 0;
+    cSamplesTotalRead = 0;
     for (;;)
     {
-        RTTESTI_CHECK_RC_OK_BREAK(AudioMixBufReadCirc(&parent, achBuf, cbBuf, &read));
-        if (!read)
+        RTTESTI_CHECK_RC_OK_BREAK(AudioMixBufReadCirc(&parent, achBuf, cbBuf, &cSamplesRead));
+        if (!cSamplesRead)
             break;
-        cSamplesRead += read;
-        AudioMixBufFinish(&parent, read);
+        cSamplesTotalRead += cSamplesRead;
+        AudioMixBufFinish(&parent, cSamplesRead);
     }
-    RTTESTI_CHECK_MSG(cSamplesRead == cSamplesParent, ("Parent: Expected %RU32 mixed samples, got %RU32\n", cSamplesParent, cSamplesRead));
+    RTTESTI_CHECK_MSG(cSamplesTotalRead == cSamplesParent, ("Parent: Expected %RU32 mixed samples, got %RU32\n", cSamplesParent, cSamplesTotalRead));
 
     /* Check that at 0dB the samples came out unharmed. */
     pSrc16 = &samples[0];
@@ -528,20 +600,20 @@ static int tstVolume(RTTEST hTest)
     vol.uLeft = vol.uRight = 255 - 16;
     AudioMixBufSetVolume(&child, &vol);
 
-    RTTESTI_CHECK_RC_OK(AudioMixBufWriteAt(&child, 0, &samples, sizeof(samples), &written));
-    RTTESTI_CHECK_MSG(written == cSamplesChild, ("Child: Expected %RU32 written samples, got %RU32\n", cSamplesChild, written));
-    RTTESTI_CHECK_RC_OK(AudioMixBufMixToParent(&child, written, &mixed));
+    RTTESTI_CHECK_RC_OK(AudioMixBufWriteCirc(&child, &samples, sizeof(samples), &cSamplesWritten));
+    RTTESTI_CHECK_MSG(cSamplesWritten == cSamplesChild, ("Child: Expected %RU32 written samples, got %RU32\n", cSamplesChild, cSamplesWritten));
+    RTTESTI_CHECK_RC_OK(AudioMixBufMixToParent(&child, cSamplesWritten, &cSamplesMixed));
 
-    cSamplesRead = 0;
+    cSamplesTotalRead = 0;
     for (;;)
     {
-        RTTESTI_CHECK_RC_OK_BREAK(AudioMixBufReadCirc(&parent, achBuf, cbBuf, &read));
-        if (!read)
+        RTTESTI_CHECK_RC_OK_BREAK(AudioMixBufReadCirc(&parent, achBuf, cbBuf, &cSamplesRead));
+        if (!cSamplesRead)
             break;
-        cSamplesRead += read;
-        AudioMixBufFinish(&parent, read);
+        cSamplesTotalRead += cSamplesRead;
+        AudioMixBufFinish(&parent, cSamplesRead);
     }
-    RTTESTI_CHECK_MSG(cSamplesRead == cSamplesParent, ("Parent: Expected %RU32 mixed samples, got %RU32\n", cSamplesParent, cSamplesRead));
+    RTTESTI_CHECK_MSG(cSamplesTotalRead == cSamplesParent, ("Parent: Expected %RU32 mixed samples, got %RU32\n", cSamplesParent, cSamplesTotalRead));
 
     /* Check that at -6dB the sample values are halved. */
     pSrc16 = &samples[0];
diff --git a/src/VBox/Devices/Bus/DevPCI.cpp b/src/VBox/Devices/Bus/DevPCI.cpp
index bd724f3..ed15c62 100644
--- a/src/VBox/Devices/Bus/DevPCI.cpp
+++ b/src/VBox/Devices/Bus/DevPCI.cpp
@@ -1986,15 +1986,6 @@ static DECLCALLBACK(void) pciR3Relocate(PPDMDEVINS pDevIns, RTGCINTPTR offDelta)
 
 
 /**
- * @interface_method_impl{PDMDEVREG,pfnReset}
- */
-static DECLCALLBACK(void) pciR3Reset(PPDMDEVINS pDevIns)
-{
-    pciR3FakePCIBIOS(pDevIns);
-}
-
-
-/**
  * @interface_method_impl{PDMDEVREG,pfnConstruct}
  */
 static DECLCALLBACK(int)   pciR3Construct(PPDMDEVINS pDevIns, int iInstance, PCFGMNODE pCfg)
@@ -2184,7 +2175,7 @@ const PDMDEVREG g_DevicePCI =
     /* pfnPowerOn */
     NULL,
     /* pfnReset */
-    pciR3Reset,
+    NULL,
     /* pfnSuspend */
     NULL,
     /* pfnResume */
diff --git a/src/VBox/Devices/Bus/DevPciIch9.cpp b/src/VBox/Devices/Bus/DevPciIch9.cpp
index 11042d6..f2c3198 100644
--- a/src/VBox/Devices/Bus/DevPciIch9.cpp
+++ b/src/VBox/Devices/Bus/DevPciIch9.cpp
@@ -190,7 +190,6 @@ typedef struct
 static void ich9pciSetIrqInternal(PICH9PCIGLOBALS pGlobals, uint8_t uDevFn, PPDMPCIDEV pPciDev,
                                   int iIrq, int iLevel, uint32_t uTagSrc);
 #ifdef IN_RING3
-static void ich9pcibridgeReset(PPDMDEVINS pDevIns);
 static DECLCALLBACK(uint32_t) ich9pciConfigReadDev(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, uint32_t u32Address, unsigned len);
 static DECLCALLBACK(void)     ich9pciConfigWriteDev(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, uint32_t u32Address, uint32_t val, unsigned len);
 DECLINLINE(PPDMPCIDEV) ich9pciFindBridge(PICH9PCIBUS pBus, uint8_t uBus);
@@ -2565,13 +2564,13 @@ static DECLCALLBACK(void) ich9pciConfigWriteDev(PPDMDEVINS pDevIns, PPDMPCIDEV p
                 break;
             case VBOX_PCI_ROM_ADDRESS:    case VBOX_PCI_ROM_ADDRESS   +1: case VBOX_PCI_ROM_ADDRESS   +2: case VBOX_PCI_ROM_ADDRESS   +3:
                 fRom = true;
+                /* fall thru */
             case VBOX_PCI_BASE_ADDRESS_0: case VBOX_PCI_BASE_ADDRESS_0+1: case VBOX_PCI_BASE_ADDRESS_0+2: case VBOX_PCI_BASE_ADDRESS_0+3:
             case VBOX_PCI_BASE_ADDRESS_1: case VBOX_PCI_BASE_ADDRESS_1+1: case VBOX_PCI_BASE_ADDRESS_1+2: case VBOX_PCI_BASE_ADDRESS_1+3:
             case VBOX_PCI_BASE_ADDRESS_2: case VBOX_PCI_BASE_ADDRESS_2+1: case VBOX_PCI_BASE_ADDRESS_2+2: case VBOX_PCI_BASE_ADDRESS_2+3:
             case VBOX_PCI_BASE_ADDRESS_3: case VBOX_PCI_BASE_ADDRESS_3+1: case VBOX_PCI_BASE_ADDRESS_3+2: case VBOX_PCI_BASE_ADDRESS_3+3:
             case VBOX_PCI_BASE_ADDRESS_4: case VBOX_PCI_BASE_ADDRESS_4+1: case VBOX_PCI_BASE_ADDRESS_4+2: case VBOX_PCI_BASE_ADDRESS_4+3:
             case VBOX_PCI_BASE_ADDRESS_5: case VBOX_PCI_BASE_ADDRESS_5+1: case VBOX_PCI_BASE_ADDRESS_5+2: case VBOX_PCI_BASE_ADDRESS_5+3:
-            {
                 /* We check that, as same PCI register numbers as BARs may mean different registers for bridges */
                 if (!fP2PBridge)
                 {
@@ -2605,7 +2604,7 @@ static DECLCALLBACK(void) ich9pciConfigWriteDev(PPDMDEVINS pDevIns, PPDMPCIDEV p
                         u8Val |= 0x01;
                 }
                 /* fall thru (bridge config space which isn't a BAR) */
-            }
+                /* fall thru */
             default:
             default_case:
                 if (fWritable)
@@ -3025,6 +3024,21 @@ static DECLCALLBACK(int) ich9pciConstruct(PPDMDEVINS pDevIns, int iInstance, PCF
     return VINF_SUCCESS;
 }
 
+/**
+ * @interface_method_impl{PDMDEVREG,pfnDestruct}
+ */
+static DECLCALLBACK(int) ich9pciDestruct(PPDMDEVINS pDevIns)
+{
+    PICH9PCIGLOBALS pGlobals = PDMINS_2_DATA(pDevIns, PICH9PCIGLOBALS);
+    PICH9PCIBUS     pBus     = &pGlobals->aPciBus;
+    if (pBus->papBridgesR3)
+    {
+        PDMDevHlpMMHeapFree(pDevIns, pBus->papBridgesR3);
+        pBus->papBridgesR3 = NULL;
+    }
+    return VINF_SUCCESS;
+}
+
 static void ich9pciResetDevice(PPDMPCIDEV pDev)
 {
     /* Clear regions */
@@ -3033,8 +3047,13 @@ static void ich9pciResetDevice(PPDMPCIDEV pDev)
         PCIIORegion* pRegion = &pDev->Int.s.aIORegions[iRegion];
         if (pRegion->size == 0)
             continue;
+        bool const f64Bit =    (pRegion->type & ((uint8_t)(PCI_ADDRESS_SPACE_BAR64 | PCI_ADDRESS_SPACE_IO)))
+                            == PCI_ADDRESS_SPACE_BAR64;
 
         ich9pciUnmapRegion(pDev, iRegion);
+
+        if (f64Bit)
+            iRegion++;
     }
 
     if (pciDevIsPassthrough(pDev))
@@ -3061,22 +3080,53 @@ static void ich9pciResetDevice(PPDMPCIDEV pDev)
         /* Reset MSI message control. */
         if (pciDevIsMsiCapable(pDev))
         {
-            /* Extracted from MsiPciConfigWrite(). */
-            pDev->abConfig[pDev->Int.s.u8MsiCapOffset + VBOX_MSI_CAP_MESSAGE_CONTROL] &= 0x8e;
+            ich9pciSetWord(pDev, pDev->Int.s.u8MsiCapOffset + VBOX_MSI_CAP_MESSAGE_CONTROL,
+                           ich9pciGetWord(pDev, pDev->Int.s.u8MsiCapOffset + VBOX_MSI_CAP_MESSAGE_CONTROL) & 0xff8e);
         }
 
         /* Reset MSI-X message control. */
         if (pciDevIsMsixCapable(pDev))
         {
-            /* Extracted from MsixPciConfigWrite(); no side effects. */
-            pDev->abConfig[pDev->Int.s.u8MsixCapOffset + VBOX_MSIX_CAP_MESSAGE_CONTROL + 1] &= 0x3f;
+            ich9pciSetWord(pDev, pDev->Int.s.u8MsixCapOffset + VBOX_MSIX_CAP_MESSAGE_CONTROL,
+                           ich9pciGetWord(pDev, pDev->Int.s.u8MsixCapOffset + VBOX_MSIX_CAP_MESSAGE_CONTROL) & 0x3fff);
         }
     }
 }
 
 
 /**
- * @copydoc FNPDMDEVRESET
+ * Recursive worker for ich9pciReset.
+ *
+ * @param   pDevIns     ICH9 bridge (must be PCI-to-PCI, not root) instance.
+ */
+static void ich9pciResetBridge(PPDMDEVINS pDevIns)
+{
+    PICH9PCIBUS pBus = PDMINS_2_DATA(pDevIns, PICH9PCIBUS);
+
+    /* PCI-specific reset for each device. */
+    for (uint32_t i = 0; i < RT_ELEMENTS(pBus->apDevices); i++)
+    {
+        if (pBus->apDevices[i])
+            ich9pciResetDevice(pBus->apDevices[i]);
+    }
+
+    for (uint32_t iBridge = 0; iBridge < pBus->cBridges; iBridge++)
+    {
+        if (pBus->papBridgesR3[iBridge])
+            ich9pciResetBridge(pBus->papBridgesR3[iBridge]->Int.s.CTX_SUFF(pDevIns));
+    }
+
+    /* Reset topology config. Last thing to do, otherwise the secondary and
+     * subordinate are instantly unreachable. */
+    ich9pciSetByte(&pBus->aPciDev, VBOX_PCI_PRIMARY_BUS, 0);
+    ich9pciSetByte(&pBus->aPciDev, VBOX_PCI_SECONDARY_BUS, 0);
+    ich9pciSetByte(&pBus->aPciDev, VBOX_PCI_SUBORDINATE_BUS, 0);
+    /* Not resetting the address decoders of the bridge to 0, since the
+     * PCI-to-PCI Bridge spec says that there is no default value. */
+}
+
+/**
+ * @interface_method_impl{PDMDEVREG,pfnReset}
  */
 static DECLCALLBACK(void) ich9pciReset(PPDMDEVINS pDevIns)
 {
@@ -3093,10 +3143,8 @@ static DECLCALLBACK(void) ich9pciReset(PPDMDEVINS pDevIns)
     for (uint32_t iBridge = 0; iBridge < pBus->cBridges; iBridge++)
     {
         if (pBus->papBridgesR3[iBridge])
-            ich9pcibridgeReset(pBus->papBridgesR3[iBridge]->Int.s.CTX_SUFF(pDevIns));
+            ich9pciResetBridge(pBus->papBridgesR3[iBridge]->Int.s.CTX_SUFF(pDevIns));
     }
-
-    ich9pciFakePCIBIOS(pDevIns);
 }
 
 static void ich9pciRelocateDevice(PPDMPCIDEV pDev, RTGCINTPTR offDelta)
@@ -3341,26 +3389,19 @@ static DECLCALLBACK(int)   ich9pcibridgeConstruct(PPDMDEVINS pDevIns,
 }
 
 /**
- * @copydoc FNPDMDEVRESET
+ * @interface_method_impl{PDMDEVREG,pfnDestruct}
  */
-static void ich9pcibridgeReset(PPDMDEVINS pDevIns)
+static DECLCALLBACK(int) ich9pcibridgeDestruct(PPDMDEVINS pDevIns)
 {
     PICH9PCIBUS pBus = PDMINS_2_DATA(pDevIns, PICH9PCIBUS);
-
-    /* Reset config space to default values. */
-    ich9pciSetByte(&pBus->aPciDev, VBOX_PCI_PRIMARY_BUS, 0);
-    ich9pciSetByte(&pBus->aPciDev, VBOX_PCI_SECONDARY_BUS, 0);
-    ich9pciSetByte(&pBus->aPciDev, VBOX_PCI_SUBORDINATE_BUS, 0);
-
-    /* PCI-specific reset for each device. */
-    for (uint32_t i = 0; i < RT_ELEMENTS(pBus->apDevices); i++)
+    if (pBus->papBridgesR3)
     {
-        if (pBus->apDevices[i])
-            ich9pciResetDevice(pBus->apDevices[i]);
+        PDMDevHlpMMHeapFree(pDevIns, pBus->papBridgesR3);
+        pBus->papBridgesR3 = NULL;
     }
+    return VINF_SUCCESS;
 }
 
-
 /**
  * @copydoc FNPDMDEVRELOCATE
  */
@@ -3400,7 +3441,7 @@ const PDMDEVREG g_DevicePciIch9 =
     /* pfnConstruct */
     ich9pciConstruct,
     /* pfnDestruct */
-    NULL,
+    ich9pciDestruct,
     /* pfnRelocate */
     ich9pciRelocate,
     /* pfnMemSetup */
@@ -3456,7 +3497,7 @@ const PDMDEVREG g_DevicePciIch9Bridge =
     /* pfnConstruct */
     ich9pcibridgeConstruct,
     /* pfnDestruct */
-    NULL,
+    ich9pcibridgeDestruct,
     /* pfnRelocate */
     ich9pcibridgeRelocate,
     /* pfnMemSetup */
diff --git a/src/VBox/Devices/EFI/DevEFI.cpp b/src/VBox/Devices/EFI/DevEFI.cpp
index d0f3eec..228881a 100644
--- a/src/VBox/Devices/EFI/DevEFI.cpp
+++ b/src/VBox/Devices/EFI/DevEFI.cpp
@@ -227,6 +227,10 @@ typedef struct DEVEFI
     uint32_t                cxUgaResolution;
     /** Uga mode vertical resolution. */
     uint32_t                cyUgaResolution;
+    /** Physical address of PCI config space MMIO region */
+    uint64_t                u64McfgBase;
+    /** Length of PCI config space MMIO region */
+    uint64_t                cbMcfgLength;
 
 
     /** NVRAM state variables. */
@@ -1111,6 +1115,8 @@ static uint32_t efiInfoSize(PDEVEFI pThis)
         case EFI_INFO_INDEX_FSB_FREQUENCY:
         case EFI_INFO_INDEX_CPU_FREQUENCY:
         case EFI_INFO_INDEX_TSC_FREQUENCY:
+        case EFI_INFO_INDEX_MCFG_BASE:
+        case EFI_INFO_INDEX_MCFG_SIZE:
             return 8;
     }
     return UINT32_MAX;
@@ -1190,6 +1196,8 @@ static uint8_t efiInfoNextByte(PDEVEFI pThis)
         /* Keep in sync with value in EfiThunk.asm */
         case EFI_INFO_INDEX_STACK_BASE:         return efiInfoNextByteU32(pThis,  VBOX_EFI_TOP_OF_STACK - _128K); /* 2M - 128 K */
         case EFI_INFO_INDEX_STACK_SIZE:         return efiInfoNextByteU32(pThis, _128K);
+        case EFI_INFO_INDEX_MCFG_BASE:          return efiInfoNextByteU64(pThis, pThis->u64McfgBase);
+        case EFI_INFO_INDEX_MCFG_SIZE:          return efiInfoNextByteU64(pThis, pThis->cbMcfgLength);
 
         default:
             PDMDevHlpDBGFStop(pThis->pDevIns, RT_SRC_POS, "%#x", pThis->iInfoSelector);
@@ -2139,6 +2147,8 @@ static DECLCALLBACK(int)  efiConstruct(PPDMDEVINS pDevIns, int iInstance, PCFGMN
     if (!CFGMR3AreValuesValid(pCfg,
                               "EfiRom\0"
                               "NumCPUs\0"
+                              "McfgBase\0"
+                              "McfgLength\0"
                               "UUID\0"
                               "IOAPIC\0"
                               "APIC\0"
@@ -2188,6 +2198,15 @@ static DECLCALLBACK(int)  efiConstruct(PPDMDEVINS pDevIns, int iInstance, PCFGMN
     rc = CFGMR3QueryU32Def(pCfg, "NumCPUs", &pThis->cCpus, 1);
     AssertLogRelRCReturn(rc, rc);
 
+    rc = CFGMR3QueryU64Def(pCfg, "McfgBase", &pThis->u64McfgBase, 0);
+    if (RT_FAILURE(rc))
+        return PDMDEV_SET_ERROR(pDevIns, rc,
+                                N_("Configuration error: Querying \"\" as integer failed"));
+    rc = CFGMR3QueryU64Def(pCfg, "McfgLength", &pThis->cbMcfgLength, 0);
+    if (RT_FAILURE(rc))
+        return PDMDEV_SET_ERROR(pDevIns, rc,
+                                N_("Configuration error: Querying \"McfgLength\" as integer failed"));
+
     rc = CFGMR3QueryU8Def(pCfg, "IOAPIC", &pThis->u8IOAPIC, 1);
     if (RT_FAILURE (rc))
         return PDMDEV_SET_ERROR(pDevIns, rc,
diff --git a/src/VBox/Devices/EFI/DevEFI.h b/src/VBox/Devices/EFI/DevEFI.h
index b87e729..cb6ee8c 100644
--- a/src/VBox/Devices/EFI/DevEFI.h
+++ b/src/VBox/Devices/EFI/DevEFI.h
@@ -68,6 +68,8 @@ typedef enum
     EFI_INFO_INDEX_GOP_MODE,
     EFI_INFO_INDEX_UGA_HORIZONTAL_RESOLUTION,
     EFI_INFO_INDEX_UGA_VERTICAL_RESOLUTION,
+    EFI_INFO_INDEX_MCFG_BASE,
+    EFI_INFO_INDEX_MCFG_SIZE,
     EFI_INFO_INDEX_END
 } EfiInfoIndex;
 
diff --git a/src/VBox/Devices/EFI/Firmware/AppPkg/Applications/Python/PyMod-2.7.2/Lib/ntpath.py b/src/VBox/Devices/EFI/Firmware/AppPkg/Applications/Python/PyMod-2.7.2/Lib/ntpath.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Scripts/ConvertMasmToNasm.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Scripts/ConvertMasmToNasm.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Scripts/UpdateBuildVersions.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Scripts/UpdateBuildVersions.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/PyEfiCompressor/setup.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/PyEfiCompressor/setup.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/PyUtility/setup.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/PyUtility/setup.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/AutoGen/AutoGen.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/AutoGen/AutoGen.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/AutoGen/BuildEngine.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/AutoGen/BuildEngine.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/AutoGen/GenC.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/AutoGen/GenC.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/AutoGen/GenDepex.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/AutoGen/GenDepex.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/AutoGen/GenMake.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/AutoGen/GenMake.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/AutoGen/GenPcdDb.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/AutoGen/GenPcdDb.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/AutoGen/InfSectionParser.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/AutoGen/InfSectionParser.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/AutoGen/StrGather.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/AutoGen/StrGather.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/AutoGen/UniClassObject.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/AutoGen/UniClassObject.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/BPDG/BPDG.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/BPDG/BPDG.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/BPDG/GenVpd.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/BPDG/GenVpd.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Common/Database.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Common/Database.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Common/DecClassObject.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Common/DecClassObject.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Common/Dictionary.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Common/Dictionary.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Common/DscClassObject.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Common/DscClassObject.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Common/EdkIIWorkspace.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Common/EdkIIWorkspace.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Common/EdkIIWorkspaceBuild.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Common/EdkIIWorkspaceBuild.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Common/EdkLogger.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Common/EdkLogger.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Common/Expression.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Common/Expression.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Common/FdfClassObject.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Common/FdfClassObject.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Common/FdfParserLite.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Common/FdfParserLite.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Common/Identification.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Common/Identification.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Common/InfClassObject.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Common/InfClassObject.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Common/LongFilePathOs.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Common/LongFilePathOs.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Common/LongFilePathOsPath.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Common/LongFilePathOsPath.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Common/LongFilePathSupport.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Common/LongFilePathSupport.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Common/MigrationUtilities.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Common/MigrationUtilities.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Common/Misc.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Common/Misc.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Common/Parsing.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Common/Parsing.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Common/String.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Common/String.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Common/TargetTxtClassObject.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Common/TargetTxtClassObject.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Common/ToolDefClassObject.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Common/ToolDefClassObject.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Common/VpdInfoFile.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Common/VpdInfoFile.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/CommonDataClass/CommonClass.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/CommonDataClass/CommonClass.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/CommonDataClass/FdfClass.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/CommonDataClass/FdfClass.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/CommonDataClass/ModuleClass.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/CommonDataClass/ModuleClass.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/CommonDataClass/PackageClass.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/CommonDataClass/PackageClass.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/CommonDataClass/PlatformClass.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/CommonDataClass/PlatformClass.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Ecc/C.g b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Ecc/C.g
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Ecc/CLexer.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Ecc/CLexer.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Ecc/CParser.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Ecc/CParser.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Ecc/Check.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Ecc/Check.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Ecc/CodeFragment.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Ecc/CodeFragment.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Ecc/CodeFragmentCollector.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Ecc/CodeFragmentCollector.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Ecc/Configuration.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Ecc/Configuration.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Ecc/Database.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Ecc/Database.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Ecc/Ecc.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Ecc/Ecc.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Ecc/Exception.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Ecc/Exception.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Ecc/FileProfile.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Ecc/FileProfile.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Ecc/MetaDataParser.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Ecc/MetaDataParser.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Ecc/MetaFileWorkspace/MetaDataTable.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Ecc/MetaFileWorkspace/MetaDataTable.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Ecc/MetaFileWorkspace/MetaFileParser.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Ecc/MetaFileWorkspace/MetaFileParser.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Ecc/MetaFileWorkspace/MetaFileTable.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Ecc/MetaFileWorkspace/MetaFileTable.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Ecc/ParserWarning.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Ecc/ParserWarning.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Ecc/Xml/XmlRoutines.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Ecc/Xml/XmlRoutines.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Ecc/c.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Ecc/c.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Eot/CLexer.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Eot/CLexer.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Eot/CParser.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Eot/CParser.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Eot/CodeFragment.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Eot/CodeFragment.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Eot/CodeFragmentCollector.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Eot/CodeFragmentCollector.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Eot/Database.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Eot/Database.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Eot/Eot.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Eot/Eot.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Eot/EotGlobalData.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Eot/EotGlobalData.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Eot/FileProfile.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Eot/FileProfile.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Eot/FvImage.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Eot/FvImage.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Eot/InfParserLite.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Eot/InfParserLite.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Eot/Parser.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Eot/Parser.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Eot/ParserWarning.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Eot/ParserWarning.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Eot/Report.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Eot/Report.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Eot/c.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Eot/c.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/AprioriSection.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/AprioriSection.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/Attribute.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/Attribute.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/Capsule.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/Capsule.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/CapsuleData.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/CapsuleData.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/ComponentStatement.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/ComponentStatement.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/CompressSection.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/CompressSection.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/DataSection.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/DataSection.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/DepexSection.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/DepexSection.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/EfiSection.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/EfiSection.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/Fd.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/Fd.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/FdfParser.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/FdfParser.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/Ffs.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/Ffs.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/FfsFileStatement.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/FfsFileStatement.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/FfsInfStatement.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/FfsInfStatement.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/Fv.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/Fv.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/FvImageSection.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/FvImageSection.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/GenFds.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/GenFds.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/GenFdsGlobalVariable.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/GenFdsGlobalVariable.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/GuidSection.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/GuidSection.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/OptRomFileStatement.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/OptRomFileStatement.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/OptRomInfStatement.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/OptRomInfStatement.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/OptionRom.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/OptionRom.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/Region.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/Region.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/Rule.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/Rule.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/RuleComplexFile.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/RuleComplexFile.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/RuleSimpleFile.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/RuleSimpleFile.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/Section.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/Section.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/UiSection.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/UiSection.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/VerSection.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/VerSection.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/Vtf.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/Vtf.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenPatchPcdTable/GenPatchPcdTable.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenPatchPcdTable/GenPatchPcdTable.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/PatchPcdValue/PatchPcdValue.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/PatchPcdValue/PatchPcdValue.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Rsa2048Sha256Sign/Rsa2048Sha256GenerateKeys.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Rsa2048Sha256Sign/Rsa2048Sha256GenerateKeys.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Rsa2048Sha256Sign/Rsa2048Sha256Sign.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Rsa2048Sha256Sign/Rsa2048Sha256Sign.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Table/Table.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Table/Table.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Table/TableDataModel.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Table/TableDataModel.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Table/TableDec.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Table/TableDec.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Table/TableDsc.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Table/TableDsc.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Table/TableEotReport.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Table/TableEotReport.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Table/TableFdf.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Table/TableFdf.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Table/TableFile.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Table/TableFile.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Table/TableFunction.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Table/TableFunction.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Table/TableIdentifier.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Table/TableIdentifier.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Table/TableInf.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Table/TableInf.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Table/TablePcd.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Table/TablePcd.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Table/TableQuery.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Table/TableQuery.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Table/TableReport.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Table/TableReport.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/TargetTool/TargetTool.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/TargetTool/TargetTool.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Trim/Trim.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Trim/Trim.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Core/DependencyRules.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Core/DependencyRules.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Core/DistributionPackageClass.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Core/DistributionPackageClass.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Core/FileHook.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Core/FileHook.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Core/IpiDb.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Core/IpiDb.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Core/PackageFile.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Core/PackageFile.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/GenMetaFile/GenDecFile.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/GenMetaFile/GenDecFile.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/GenMetaFile/GenInfFile.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/GenMetaFile/GenInfFile.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/GenMetaFile/GenMetaFileMisc.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/GenMetaFile/GenMetaFileMisc.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/InstallPkg.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/InstallPkg.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/InventoryWs.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/InventoryWs.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Library/CommentGenerating.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Library/CommentGenerating.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Library/CommentParsing.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Library/CommentParsing.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Library/ExpressionValidate.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Library/ExpressionValidate.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Library/Misc.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Library/Misc.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Library/ParserValidate.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Library/ParserValidate.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Library/Parsing.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Library/Parsing.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Library/String.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Library/String.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Library/UniClassObject.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Library/UniClassObject.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Library/Xml/XmlRoutines.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Library/Xml/XmlRoutines.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Logger/Log.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Logger/Log.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/MkPkg.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/MkPkg.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Object/POM/CommonObject.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Object/POM/CommonObject.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Object/POM/ModuleObject.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Object/POM/ModuleObject.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Object/POM/PackageObject.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Object/POM/PackageObject.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Object/Parser/DecObject.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Object/Parser/DecObject.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Object/Parser/InfBinaryObject.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Object/Parser/InfBinaryObject.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Object/Parser/InfBuildOptionObject.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Object/Parser/InfBuildOptionObject.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Object/Parser/InfCommonObject.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Object/Parser/InfCommonObject.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Object/Parser/InfDefineCommonObject.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Object/Parser/InfDefineCommonObject.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Object/Parser/InfDefineObject.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Object/Parser/InfDefineObject.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Object/Parser/InfDepexObject.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Object/Parser/InfDepexObject.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Object/Parser/InfGuidObject.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Object/Parser/InfGuidObject.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Object/Parser/InfHeaderObject.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Object/Parser/InfHeaderObject.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Object/Parser/InfLibraryClassesObject.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Object/Parser/InfLibraryClassesObject.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Object/Parser/InfMisc.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Object/Parser/InfMisc.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Object/Parser/InfPackagesObject.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Object/Parser/InfPackagesObject.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Object/Parser/InfPcdObject.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Object/Parser/InfPcdObject.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Object/Parser/InfPpiObject.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Object/Parser/InfPpiObject.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Object/Parser/InfProtocolObject.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Object/Parser/InfProtocolObject.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Object/Parser/InfSoucesObject.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Object/Parser/InfSoucesObject.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Object/Parser/InfUserExtensionObject.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Object/Parser/InfUserExtensionObject.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/DecParser.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/DecParser.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/DecParserMisc.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/DecParserMisc.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/InfAsBuiltProcess.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/InfAsBuiltProcess.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/InfBinarySectionParser.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/InfBinarySectionParser.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/InfBuildOptionSectionParser.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/InfBuildOptionSectionParser.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/InfDefineSectionParser.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/InfDefineSectionParser.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/InfDepexSectionParser.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/InfDepexSectionParser.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/InfGuidPpiProtocolSectionParser.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/InfGuidPpiProtocolSectionParser.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/InfLibrarySectionParser.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/InfLibrarySectionParser.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/InfPackageSectionParser.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/InfPackageSectionParser.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/InfParser.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/InfParser.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/InfParserMisc.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/InfParserMisc.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/InfPcdSectionParser.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/InfPcdSectionParser.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/InfSectionParser.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/InfSectionParser.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/InfSourceSectionParser.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/InfSourceSectionParser.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/PomAdapter/DecPomAlignment.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/PomAdapter/DecPomAlignment.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/PomAdapter/InfPomAlignment.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/PomAdapter/InfPomAlignment.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/PomAdapter/InfPomAlignmentMisc.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/PomAdapter/InfPomAlignmentMisc.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/ReplacePkg.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/ReplacePkg.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/RmPkg.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/RmPkg.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/UPT.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/UPT.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/UnitTest/CommentGeneratingUnitTest.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/UnitTest/CommentGeneratingUnitTest.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/UnitTest/CommentParsingUnitTest.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/UnitTest/CommentParsingUnitTest.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/UnitTest/DecParserTest.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/UnitTest/DecParserTest.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/UnitTest/DecParserUnitTest.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/UnitTest/DecParserUnitTest.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/UnitTest/InfBinarySectionTest.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/UnitTest/InfBinarySectionTest.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Xml/CommonXml.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Xml/CommonXml.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Xml/GuidProtocolPpiXml.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Xml/GuidProtocolPpiXml.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Xml/IniToXml.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Xml/IniToXml.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Xml/ModuleSurfaceAreaXml.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Xml/ModuleSurfaceAreaXml.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Xml/PackageSurfaceAreaXml.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Xml/PackageSurfaceAreaXml.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Xml/PcdXml.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Xml/PcdXml.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Xml/XmlParser.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Xml/XmlParser.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Xml/XmlParserMisc.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Xml/XmlParserMisc.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Workspace/BuildClassObject.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Workspace/BuildClassObject.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Workspace/MetaDataTable.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Workspace/MetaDataTable.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Workspace/MetaFileCommentParser.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Workspace/MetaFileCommentParser.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Workspace/MetaFileParser.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Workspace/MetaFileParser.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Workspace/MetaFileTable.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Workspace/MetaFileTable.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Workspace/WorkspaceCommon.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Workspace/WorkspaceCommon.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Workspace/WorkspaceDatabase.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Workspace/WorkspaceDatabase.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/build/BuildReport.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/build/BuildReport.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/build/build.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/build/build.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/IntelFspPkg/FspSecCore/Vtf0/Build.py b/src/VBox/Devices/EFI/Firmware/IntelFspPkg/FspSecCore/Vtf0/Build.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/IntelFspPkg/FspSecCore/Vtf0/Tools/FixupForRawSection.py b/src/VBox/Devices/EFI/Firmware/IntelFspPkg/FspSecCore/Vtf0/Tools/FixupForRawSection.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/IntelFspPkg/Tools/GenCfgOpt.py b/src/VBox/Devices/EFI/Firmware/IntelFspPkg/Tools/GenCfgOpt.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/IntelFspPkg/Tools/PatchFv.py b/src/VBox/Devices/EFI/Firmware/IntelFspPkg/Tools/PatchFv.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/IntelFspWrapperPkg/FspWrapperSecCore/Vtf0/Build.py b/src/VBox/Devices/EFI/Firmware/IntelFspWrapperPkg/FspWrapperSecCore/Vtf0/Build.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/IntelFspWrapperPkg/FspWrapperSecCore/Vtf0/Tools/FixupForRawSection.py b/src/VBox/Devices/EFI/Firmware/IntelFspWrapperPkg/FspWrapperSecCore/Vtf0/Tools/FixupForRawSection.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/PlatformPei/Platform.c b/src/VBox/Devices/EFI/Firmware/OvmfPkg/PlatformPei/Platform.c
index 3521984..e098012 100644
--- a/src/VBox/Devices/EFI/Firmware/OvmfPkg/PlatformPei/Platform.c
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/PlatformPei/Platform.c
@@ -39,6 +39,12 @@
 #include "Platform.h"
 #include "Cmos.h"
 
+#ifdef VBOX
+# include "VBoxPkg.h"
+# include "DevEFI.h"
+# include "iprt/asm.h"
+#endif
+
 EFI_MEMORY_TYPE_INFORMATION mDefaultMemoryTypeInformation[] = {
   { EfiACPIMemoryNVS,       0x004 },
   { EfiACPIReclaimMemory,   0x008 },
@@ -64,6 +70,22 @@ EFI_BOOT_MODE mBootMode = BOOT_WITH_FULL_CONFIGURATION;
 
 BOOLEAN mS3Supported = FALSE;
 
+#ifdef VBOX
+static UINT32
+GetVmVariable(UINT32 Variable, CHAR8 *pbBuf, UINT32 cbBuf)
+{
+  UINT32 cbVar, offBuf;
+
+  ASMOutU32(EFI_INFO_PORT, Variable);
+  cbVar = ASMInU32(EFI_INFO_PORT);
+
+  for (offBuf = 0; offBuf < cbVar && offBuf < cbBuf; offBuf++)
+    pbBuf[offBuf] = ASMInU8(EFI_INFO_PORT);
+
+  return cbVar;
+}
+#endif
+
 
 VOID
 AddIoMemoryBaseSizeHob (
@@ -224,6 +246,8 @@ MemMapInitialization (
 #ifdef VBOX
   EFI_PHYSICAL_ADDRESS RsdPtr;
   EFI_PHYSICAL_ADDRESS AcpiTables;
+  UINT64 McfgBase = 0;
+  UINT64 McfgSize = 0;
 #endif
   //
   // Create Memory Type Information HOB
@@ -268,8 +292,20 @@ MemMapInitialization (
     // 0xFED00400    gap                         1023 KB
     // 0xFEE00000    LAPIC                          1 MB
     //
+#ifdef VBOX
+    GetVmVariable(EFI_INFO_INDEX_MCFG_BASE, (CHAR8 *)&McfgBase, sizeof(McfgBase));
+    GetVmVariable(EFI_INFO_INDEX_MCFG_SIZE, (CHAR8 *)&McfgSize, sizeof(McfgSize));
+    if (TopOfLowRam < BASE_2GB)
+      TopOfLowRam = BASE_2GB;
+    if (McfgBase == 0)
+      McfgBase = TopOfLowRam;   // backward compatibilit with old DevEFI
+    if (TopOfLowRam < McfgBase)
+      AddIoMemoryRangeHob (TopOfLowRam, McfgBase);
+    AddIoMemoryRangeHob (McfgBase + McfgSize, 0xFC000000);
+#else
     AddIoMemoryRangeHob (TopOfLowRam < BASE_2GB ?
                          BASE_2GB : TopOfLowRam, 0xFC000000);
+#endif
     AddIoMemoryBaseSizeHob (0xFEC00000, SIZE_4KB);
     AddIoMemoryBaseSizeHob (0xFED00000, SIZE_1KB);
     AddIoMemoryBaseSizeHob (PcdGet32(PcdCpuLocalApicBaseAddress), SIZE_1MB);
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/PlatformPei/PlatformPei.inf b/src/VBox/Devices/EFI/Firmware/OvmfPkg/PlatformPei/PlatformPei.inf
index 9c996de..f3d465e 100644
--- a/src/VBox/Devices/EFI/Firmware/OvmfPkg/PlatformPei/PlatformPei.inf
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/PlatformPei/PlatformPei.inf
@@ -41,6 +41,7 @@
   MdeModulePkg/MdeModulePkg.dec
   UefiCpuPkg/UefiCpuPkg.dec
   OvmfPkg/OvmfPkg.dec
+  VBoxPkg/VBoxPkg.dec                           # VBox specific so the code can find some necessary headers
 
 [Guids]
   gEfiMemoryTypeInformationGuid
diff --git a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/ResetVector/Vtf0/Build.py b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/ResetVector/Vtf0/Build.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Devices/EFI/FirmwareBin/VBoxEFI32.fd b/src/VBox/Devices/EFI/FirmwareBin/VBoxEFI32.fd
index 073d562..0c847f1 100644
Binary files a/src/VBox/Devices/EFI/FirmwareBin/VBoxEFI32.fd and b/src/VBox/Devices/EFI/FirmwareBin/VBoxEFI32.fd differ
diff --git a/src/VBox/Devices/EFI/FirmwareBin/VBoxEFI64.fd b/src/VBox/Devices/EFI/FirmwareBin/VBoxEFI64.fd
index 065ffde..62dce60 100644
Binary files a/src/VBox/Devices/EFI/FirmwareBin/VBoxEFI64.fd and b/src/VBox/Devices/EFI/FirmwareBin/VBoxEFI64.fd differ
diff --git a/src/VBox/Devices/Graphics/DevVGA-SVGA3d-internal.h b/src/VBox/Devices/Graphics/DevVGA-SVGA3d-internal.h
index 46df775..5fa1484 100644
--- a/src/VBox/Devices/Graphics/DevVGA-SVGA3d-internal.h
+++ b/src/VBox/Devices/Graphics/DevVGA-SVGA3d-internal.h
@@ -522,6 +522,7 @@ typedef struct VMSVGA3DSURFACE
 #endif
     SVGA3dSurfaceFace       faces[SVGA3D_MAX_SURFACE_FACES];
     uint32_t                cFaces;
+    uint32_t                cMipmapLevels;
     PVMSVGA3DMIPMAPLEVEL    pMipmapLevels;
     uint32_t                multiSampleCount;
     SVGA3dTextureFilter     autogenFilter;
@@ -1059,5 +1060,11 @@ int  vmsvga3dBackSurfaceDMACopyBox(PVGASTATE pThis, PVMSVGA3DSTATE pState, PVMSV
 int  vmsvga3dBackCreateTexture(PVMSVGA3DSTATE pState, PVMSVGA3DCONTEXT pContext, uint32_t idAssociatedContext,
                                PVMSVGA3DSURFACE pSurface);
 
+void vmsvgaClipCopyBox(const SVGA3dSize *pSizeSrc,
+                       const SVGA3dSize *pSizeDest,
+                       SVGA3dCopyBox *pBox);
+void vmsvgaClipBox(const SVGA3dSize *pSize,
+                   SVGA3dBox *pBox);
+
 #endif
 
diff --git a/src/VBox/Devices/Graphics/DevVGA-SVGA3d-ogl.cpp b/src/VBox/Devices/Graphics/DevVGA-SVGA3d-ogl.cpp
index b7d1311..7ec23a3 100644
--- a/src/VBox/Devices/Graphics/DevVGA-SVGA3d-ogl.cpp
+++ b/src/VBox/Devices/Graphics/DevVGA-SVGA3d-ogl.cpp
@@ -1904,14 +1904,14 @@ int vmsvga3dSurfaceCopy(PVGASTATE pThis, SVGA3dSurfaceImageId dest, SVGA3dSurfac
         srcBox.z = pBox[i].srcz;
         srcBox.w = pBox[i].w;
         srcBox.h = pBox[i].h;
-        srcBox.d = pBox[i].z; /* XXX what about pBox[i].d? */
+        srcBox.d = pBox[i].d;
 
         destBox.x = pBox[i].x;
         destBox.y = pBox[i].y;
         destBox.z = pBox[i].z;
         destBox.w = pBox[i].w;
         destBox.h = pBox[i].h;
-        destBox.z = pBox[i].z; /* XXX initializing destBox.z again? What about pBox[i].d and destBox.d? */
+        destBox.d = pBox[i].d;
 
         rc = vmsvga3dSurfaceStretchBlt(pThis, &dest, &destBox, &src, &srcBox, SVGA3D_STRETCH_BLT_LINEAR);
         AssertRCReturn(rc, rc);
@@ -2924,14 +2924,14 @@ int vmsvga3dCommandPresent(PVGASTATE pThis, uint32_t sid, uint32_t cRects, SVGA3
         else
             continue;
 
-        if (RT_LIKELY(ClippedRect.w < VMSVGA_MAX_Y))
+        if (RT_LIKELY(ClippedRect.w < VMSVGA_MAX_X))
         { /* likely */ }
         else
-            ClippedRect.w = VMSVGA_MAX_Y;
-        if (RT_LIKELY(ClippedRect.w < VMSVGA_MAX_Y))
+            ClippedRect.w = VMSVGA_MAX_X;
+        if (RT_LIKELY(ClippedRect.h < VMSVGA_MAX_Y))
         { /* likely */ }
         else
-            ClippedRect.w = VMSVGA_MAX_Y;
+            ClippedRect.h = VMSVGA_MAX_Y;
 
 
         /*
diff --git a/src/VBox/Devices/Graphics/DevVGA-SVGA3d-shared.cpp b/src/VBox/Devices/Graphics/DevVGA-SVGA3d-shared.cpp
index 750048c..507c842 100644
--- a/src/VBox/Devices/Graphics/DevVGA-SVGA3d-shared.cpp
+++ b/src/VBox/Devices/Graphics/DevVGA-SVGA3d-shared.cpp
@@ -1051,3 +1051,76 @@ const char *vmsvga3dPrimitiveType2String(SVGA3dPrimitiveType PrimitiveType)
 
 #endif /* LOG_ENABLED */
 
+/** Unsigned coordinates in pBox. Clip to [0; pSizeSrc), [0;pSizeDest).
+ *
+ * @param pSizeSrc  Source surface dimensions.
+ * @param pSizeDest Destination surface dimensions.
+ * @param pBox      Coordinates to be clipped.
+ */
+void vmsvgaClipCopyBox(const SVGA3dSize *pSizeSrc,
+                       const SVGA3dSize *pSizeDest,
+                       SVGA3dCopyBox *pBox)
+{
+    /* Src x, w */
+    if (pBox->srcx > pSizeSrc->width)
+        pBox->srcx = pSizeSrc->width;
+    if (pBox->w > pSizeSrc->width - pBox->srcx)
+        pBox->w = pSizeSrc->width - pBox->srcx;
+
+    /* Src y, h */
+    if (pBox->srcy > pSizeSrc->height)
+        pBox->srcy = pSizeSrc->height;
+    if (pBox->h > pSizeSrc->height - pBox->srcy)
+        pBox->h = pSizeSrc->height - pBox->srcy;
+
+    /* Src z, d */
+    if (pBox->srcz > pSizeSrc->depth)
+        pBox->srcz = pSizeSrc->depth;
+    if (pBox->d > pSizeSrc->depth - pBox->srcz)
+        pBox->d = pSizeSrc->depth - pBox->srcz;
+
+    /* Dest x, w */
+    if (pBox->x > pSizeDest->width)
+        pBox->x = pSizeDest->width;
+    if (pBox->w > pSizeDest->width - pBox->x)
+        pBox->w = pSizeDest->width - pBox->x;
+
+    /* Dest y, h */
+    if (pBox->y > pSizeDest->height)
+        pBox->y = pSizeDest->height;
+    if (pBox->h > pSizeDest->height - pBox->y)
+        pBox->h = pSizeDest->height - pBox->y;
+
+    /* Dest z, d */
+    if (pBox->z > pSizeDest->depth)
+        pBox->z = pSizeDest->depth;
+    if (pBox->d > pSizeDest->depth - pBox->z)
+        pBox->d = pSizeDest->depth - pBox->z;
+}
+
+/** Unsigned coordinates in pBox. Clip to [0; pSize).
+ *
+ * @param pSize     Source surface dimensions.
+ * @param pBox      Coordinates to be clipped.
+ */
+void vmsvgaClipBox(const SVGA3dSize *pSize,
+                   SVGA3dBox *pBox)
+{
+    /* x, w */
+    if (pBox->x > pSize->width)
+        pBox->x = pSize->width;
+    if (pBox->w > pSize->width - pBox->x)
+        pBox->w = pSize->width - pBox->x;
+
+    /* y, h */
+    if (pBox->y > pSize->height)
+        pBox->y = pSize->height;
+    if (pBox->h > pSize->height - pBox->y)
+        pBox->h = pSize->height - pBox->y;
+
+    /* z, d */
+    if (pBox->z > pSize->depth)
+        pBox->z = pSize->depth;
+    if (pBox->d > pSize->depth - pBox->z)
+        pBox->d = pSize->depth - pBox->z;
+}
diff --git a/src/VBox/Devices/Graphics/DevVGA-SVGA3d-win.cpp b/src/VBox/Devices/Graphics/DevVGA-SVGA3d-win.cpp
index f6cc17b..1708f9c 100644
--- a/src/VBox/Devices/Graphics/DevVGA-SVGA3d-win.cpp
+++ b/src/VBox/Devices/Graphics/DevVGA-SVGA3d-win.cpp
@@ -1226,7 +1226,7 @@ static int vmsvga3dSurfaceTrackUsage(PVMSVGA3DSTATE pState, PVMSVGA3DCONTEXT pCo
     if (pSurface->pSharedObjectTree == NULL)
         return VINF_SUCCESS;
 
-    Log(("vmsvga3dSurfaceTrackUsage: track usage of surface id=%x (cid=%x)\n", pSurface->id, pContext->id));
+    Log(("vmsvga3dSurfaceTrackUsage: track usage of sid=%x (cid=%d) for cid=%d\n", pSurface->id, pSurface->idAssociatedContext, pContext->id));
 
     /* Release the previous query object. */
     if (pSurface->pQuery)
@@ -1318,8 +1318,12 @@ int vmsvga3dSurfaceCopy(PVGASTATE pThis, SVGA3dSurfaceImageId dest, SVGA3dSurfac
     AssertReturn(pSurfaceSrc->faces[0].numMipLevels > src.mipmap, VERR_INVALID_PARAMETER);
     AssertReturn(pSurfaceDest->faces[0].numMipLevels > dest.mipmap, VERR_INVALID_PARAMETER);
 
+    const VMSVGA3DMIPMAPLEVEL *pMipmapLevelSrc = &pSurfaceSrc->pMipmapLevels[src.mipmap];
+    const VMSVGA3DMIPMAPLEVEL *pMipmapLevelDest = &pSurfaceDest->pMipmapLevels[dest.mipmap];
+
    // AssertMsgReturn(pSurfaceSrc->format == pSurfaceDest->format, ("Format mismatch (%d vs %d)!!\n", pSurfaceSrc->format, pSurfaceDest->format), VERR_INVALID_PARAMETER);
 
+    /** @todo Support cubemaps. */
     bool fSrcTexture  = !!(pSurfaceSrc->flags & SVGA3D_SURFACE_HINT_TEXTURE);
     bool fDestTexture = !!(pSurfaceDest->flags & SVGA3D_SURFACE_HINT_TEXTURE);
 
@@ -1340,7 +1344,7 @@ int vmsvga3dSurfaceCopy(PVGASTATE pThis, SVGA3dSurfaceImageId dest, SVGA3dSurfac
         }
         pContext = pState->papContexts[cid];
 
-        Log(("vmsvga3dSurfaceCopy: create texture surface id=%x type=%d format=%d -> create texture\n", sidDest, pSurfaceDest->flags, pSurfaceDest->format));
+        Log(("vmsvga3dSurfaceCopy: create texture sid=%x type=%d format=%d -> create texture\n", sidDest, pSurfaceDest->flags, pSurfaceDest->format));
         rc = vmsvga3dBackCreateTexture(pState, pContext, cid, pSurfaceDest);
         AssertRCReturn(rc, rc);
     }
@@ -1370,7 +1374,7 @@ int vmsvga3dSurfaceCopy(PVGASTATE pThis, SVGA3dSurfaceImageId dest, SVGA3dSurfac
         if (    fSrcTexture
             &&  pSurfaceSrc->idAssociatedContext != cid)
         {
-            Log(("vmsvga3dSurfaceCopy; using texture %x created for another context (%d vs %d)\n", sidSrc, pSurfaceSrc->idAssociatedContext, cid));
+            Log(("vmsvga3dSurfaceCopy; using texture sid=%x created for another context (%d vs %d)\n", sidSrc, pSurfaceSrc->idAssociatedContext, cid));
 
             PVMSVGA3DSHAREDSURFACE pSharedSurface = vmsvga3dSurfaceGetSharedCopy(pThis, pContext, pSurfaceSrc);
             AssertReturn(pSharedSurface, VERR_INTERNAL_ERROR);
@@ -1387,26 +1391,36 @@ int vmsvga3dSurfaceCopy(PVGASTATE pThis, SVGA3dSurfaceImageId dest, SVGA3dSurfac
             IDirect3DSurface9 *pSrc;
             IDirect3DSurface9 *pDest;
 
-            RectSrc.left    = pBox[i].srcx;
-            RectSrc.top     = pBox[i].srcy;
-            RectSrc.right   = pBox[i].srcx + pBox[i].w;   /* exclusive */
-            RectSrc.bottom  = pBox[i].srcy + pBox[i].h;   /* exclusive */
-            RectDest.left   = pBox[i].x;
-            RectDest.top    = pBox[i].y;
-            RectDest.right  = pBox[i].x + pBox[i].w;   /* exclusive */
-            RectDest.bottom = pBox[i].y + pBox[i].h;   /* exclusive */
+            SVGA3dCopyBox clipBox = pBox[i];
+            vmsvgaClipCopyBox(&pMipmapLevelSrc->size, &pMipmapLevelDest->size, &clipBox);
+            if (   !clipBox.w
+                || !clipBox.h
+                || !clipBox.d)
+            {
+                LogFunc(("Skipped empty box.\n"));
+                continue;
+            }
+
+            RectSrc.left    = clipBox.srcx;
+            RectSrc.top     = clipBox.srcy;
+            RectSrc.right   = clipBox.srcx + clipBox.w;   /* exclusive */
+            RectSrc.bottom  = clipBox.srcy + clipBox.h;   /* exclusive */
+            RectDest.left   = clipBox.x;
+            RectDest.top    = clipBox.y;
+            RectDest.right  = clipBox.x + clipBox.w;   /* exclusive */
+            RectDest.bottom = clipBox.y + clipBox.h;   /* exclusive */
 
             Log(("vmsvga3dSurfaceCopy: (StretchRect) copy src sid=%x face=%d mipmap=%d (%d,%d)(%d,%d) to dest sid=%x face=%d mipmap=%d (%d,%d)\n", sidSrc, src.face, src.mipmap, RectSrc.left, RectSrc.top, RectSrc.right, RectSrc.bottom, sidDest, dest.face, dest.mipmap, pBox[i].x, pBox[i].y));
 
             if (    sidSrc == sidDest
-                &&  pBox[i].srcx == pBox[i].x
-                &&  pBox[i].srcy == pBox[i].y)
+                &&  clipBox.srcx == clipBox.x
+                &&  clipBox.srcy == clipBox.y)
             {
                 Log(("vmsvga3dSurfaceCopy: redundant copy to the same surface at the same coordinates. Ignore. \n"));
                 continue;
             }
             Assert(sidSrc != sidDest);
-            Assert(!pBox[i].srcz && !pBox[i].z);
+            Assert(!clipBox.srcz && !clipBox.z);
 
             if (fSrcTexture)
             {
@@ -1445,28 +1459,52 @@ int vmsvga3dSurfaceCopy(PVGASTATE pThis, SVGA3dSurfaceImageId dest, SVGA3dSurfac
     else
     for (uint32_t i = 0; i < cCopyBoxes; i++)
     {
-        HRESULT        hr = D3D_OK;
+        HRESULT        hr;
         D3DLOCKED_RECT LockedSrcRect;
         D3DLOCKED_RECT LockedDestRect;
-        RECT           Rect;
+        RECT           RectSrc;
+        RECT           RectDest;
+
+        SVGA3dCopyBox clipBox = pBox[i];
+        vmsvgaClipCopyBox(&pMipmapLevelSrc->size, &pMipmapLevelDest->size, &clipBox);
+        if (   !clipBox.w
+            || !clipBox.h
+            || !clipBox.d)
+        {
+            LogFunc(("Skipped empty box.\n"));
+            continue;
+        }
 
-        Rect.left   = pBox[i].srcx;
-        Rect.top    = pBox[i].srcy;
-        Rect.right  = pBox[i].srcx + pBox[i].w;   /* exclusive */
-        Rect.bottom = pBox[i].srcy + pBox[i].h;   /* exclusive */
+        RectSrc.left    = clipBox.srcx;
+        RectSrc.top     = clipBox.srcy;
+        RectSrc.right   = clipBox.srcx + clipBox.w;   /* exclusive */
+        RectSrc.bottom  = clipBox.srcy + clipBox.h;   /* exclusive */
+        RectDest.left   = clipBox.x;
+        RectDest.top    = clipBox.y;
+        RectDest.right  = clipBox.x + clipBox.w;   /* exclusive */
+        RectDest.bottom = clipBox.y + clipBox.h;   /* exclusive */
 
-        Log(("vmsvga3dSurfaceCopy: (manual) copy src=%x src=%x face=%d (%d,%d)(%d,%d) to dest=%x src=%x face=%d (%d,%d)\n", sidSrc, src.face, src.mipmap, Rect.left, Rect.top, Rect.right, Rect.bottom, sidDest, dest.face, dest.mipmap, pBox[i].x, pBox[i].y));
+        LogFunc(("(manual) copy sid=%x face=%d mipmap=%d (%d,%d)(%d,%d) to sid=%x face=%d mipmap=%d (%d,%d)\n",
+                 sidSrc, src.face, src.mipmap, RectSrc.left, RectSrc.top, RectSrc.right, RectSrc.bottom,
+                 sidDest, dest.face, dest.mipmap, pBox[i].x, pBox[i].y));
 
-        Assert(!pBox[i].srcz && !pBox[i].z);
+        Assert(!clipBox.srcz && !clipBox.z);
+        Assert(pSurfaceSrc->cbBlock == pSurfaceDest->cbBlock);
 
         if (!pSurfaceSrc->u.pSurface)
         {
-            LockedSrcRect.pBits = (void *)pSurfaceSrc->pMipmapLevels[src.mipmap].pSurfaceData;
-            LockedSrcRect.Pitch  = pSurfaceSrc->pMipmapLevels[src.mipmap].cbSurfacePitch;
+            LockedSrcRect.pBits = (uint8_t *)pMipmapLevelSrc->pSurfaceData +
+                                  pMipmapLevelSrc->cbSurfacePitch * clipBox.srcy + pSurfaceSrc->cbBlock * clipBox.srcx;
+            LockedSrcRect.Pitch = pMipmapLevelSrc->cbSurfacePitch;
         }
         else
         {
-            /* Must flush the other context's 3d pipeline to make sure all drawing is complete for the surface we're about to use. */
+            /** @todo This branch is dead code. Because if the source is a hardware surface, then
+             *  the code above creates hardware surface for the destination and does the copy in hardware.
+             *  I.e. we can not get here with pSurfaceSrc->u.pSurface != NULL.
+             */
+
+            /* Must flush the context's 3d pipeline to make sure all drawing is complete for the surface we're about to use. */
             vmsvga3dSurfaceFlush(pThis, pSurfaceSrc);
 
             if (fSrcTexture)
@@ -1474,47 +1512,58 @@ int vmsvga3dSurfaceCopy(PVGASTATE pThis, SVGA3dSurfaceImageId dest, SVGA3dSurfac
                 Assert(!pSurfaceSrc->bounce.pTexture);
                 hr = pSurfaceSrc->u.pTexture->LockRect(src.mipmap, /* Texture level */
                                                        &LockedSrcRect,
-                                                       &Rect,
+                                                       &RectSrc,
                                                        D3DLOCK_READONLY);
             }
             else
                 hr = pSurfaceSrc->u.pSurface->LockRect(&LockedSrcRect,
-                                                       &Rect,
+                                                       &RectSrc,
                                                        D3DLOCK_READONLY);
-            AssertMsgReturn(hr == D3D_OK, ("vmsvga3dSurfaceCopy: LockRect failed with %x\n", hr), VERR_INTERNAL_ERROR);
+            AssertMsgReturn(hr == D3D_OK, ("LockRect failed with %x\n", hr), VERR_INTERNAL_ERROR);
         }
 
         if (!pSurfaceDest->u.pSurface)
         {
-            LockedDestRect.pBits = (void *)pSurfaceDest->pMipmapLevels[dest.mipmap].pSurfaceData;
-            LockedDestRect.Pitch  = pSurfaceDest->pMipmapLevels[dest.mipmap].cbSurfacePitch;
+            LockedDestRect.pBits = (uint8_t *)pMipmapLevelDest->pSurfaceData +
+                                   pMipmapLevelDest->cbSurfacePitch * clipBox.y + pSurfaceDest->cbBlock * clipBox.x;
+            LockedDestRect.Pitch = pMipmapLevelDest->cbSurfacePitch;
         }
         else
         {
-            /* Must flush the other context's 3d pipeline to make sure all drawing is complete for the surface we're about to use. */
+            /* Must flush the context's 3d pipeline to make sure all drawing is complete for the surface we're about to use. */
             vmsvga3dSurfaceFlush(pThis, pSurfaceDest);
 
             if (fDestTexture)
             {
-                Assert(!pSurfaceDest->bounce.pTexture);
-                hr = pSurfaceDest->u.pTexture->LockRect(dest.mipmap, /* texture level */
-                                                        &LockedDestRect,
-                                                        &Rect,
-                                                        0);
+                if (pSurfaceDest->bounce.pTexture)
+                {
+                    /* pSurfaceDest->u.pTexture can't be locked, see vmsvga3dBackCreateTexture */
+                    hr = pSurfaceDest->bounce.pTexture->LockRect(dest.mipmap, /* texture level */
+                                                                 &LockedDestRect,
+                                                                 &RectDest,
+                                                                 0);
+                }
+                else
+                {
+                    hr = pSurfaceDest->u.pTexture->LockRect(dest.mipmap, /* texture level */
+                                                            &LockedDestRect,
+                                                            &RectDest,
+                                                            0);
+                }
             }
             else
                 hr = pSurfaceDest->u.pSurface->LockRect(&LockedDestRect,
-                                                        &Rect,
+                                                        &RectDest,
                                                         0);
-            AssertMsgReturn(hr == D3D_OK, ("vmsvga3dSurfaceCopy: LockRect failed with %x\n", hr), VERR_INTERNAL_ERROR);
+            AssertMsgReturn(hr == D3D_OK, ("LockRect failed with %x\n", hr), VERR_INTERNAL_ERROR);
         }
 
-        uint8_t *pDest = (uint8_t *)LockedDestRect.pBits + LockedDestRect.Pitch * pBox[i].y + pBox[i].x * pSurfaceDest->cbBlock;
-        uint8_t *pSrc  = (uint8_t *)LockedSrcRect.pBits + LockedSrcRect.Pitch * pBox[i].srcy + pBox[i].srcx * pSurfaceSrc->cbBlock;
+        uint8_t *pDest = (uint8_t *)LockedDestRect.pBits;
+        const uint8_t *pSrc = (uint8_t *)LockedSrcRect.pBits;
 
-        for (int32_t j = Rect.top; j < Rect.bottom; j++)
+        for (uint32_t j = 0; j < clipBox.h; ++j)
         {
-            memcpy(pDest, pSrc, pBox[i].w * pSurfaceSrc->cbBlock);
+            memcpy(pDest, pSrc, clipBox.w * pSurfaceSrc->cbBlock);
 
             pDest += LockedDestRect.Pitch;
             pSrc  += LockedSrcRect.Pitch;
@@ -1523,10 +1572,33 @@ int vmsvga3dSurfaceCopy(PVGASTATE pThis, SVGA3dSurfaceImageId dest, SVGA3dSurfac
         if (pSurfaceDest->u.pSurface)
         {
             if (fDestTexture)
-                hr = pSurfaceDest->u.pTexture->UnlockRect(dest.mipmap /* Texture level */);
+            {
+                if (pSurfaceDest->bounce.pTexture)
+                {
+                    hr = pSurfaceDest->bounce.pTexture->UnlockRect(dest.mipmap /* Texture level */);
+
+                    /** @todo stricter checks for associated context */
+                    PVMSVGA3DCONTEXT pContext = NULL;
+                    const uint32_t cid = pSurfaceDest->idAssociatedContext;
+                    if (   cid < pState->cContexts
+                        && pState->papContexts[cid]->id == cid)
+                        pContext = pState->papContexts[cid];
+                    else
+                        AssertFailed();
+
+                    if (pContext)
+                    {
+                        /* Copy the new content to the actual texture object. */
+                        HRESULT hr2 = pContext->pDevice->UpdateTexture(pSurfaceDest->bounce.pTexture, pSurfaceDest->u.pTexture);
+                        AssertMsg(hr2 == D3D_OK, ("UpdateTexture failed with %x\n", hr2)); RT_NOREF(hr2);
+                    }
+                }
+                else
+                    hr = pSurfaceDest->u.pTexture->UnlockRect(dest.mipmap /* Texture level */);
+            }
             else
                 hr = pSurfaceDest->u.pSurface->UnlockRect();
-            AssertMsgReturn(hr == D3D_OK, ("vmsvga3dSurfaceCopy: Unlock failed with %x\n", hr), VERR_INTERNAL_ERROR);
+            AssertMsgReturn(hr == D3D_OK, ("Unlock failed with %x\n", hr), VERR_INTERNAL_ERROR);
         }
 
         if (pSurfaceSrc->u.pSurface)
@@ -1535,7 +1607,7 @@ int vmsvga3dSurfaceCopy(PVGASTATE pThis, SVGA3dSurfaceImageId dest, SVGA3dSurfac
                 hr = pSurfaceSrc->u.pTexture->UnlockRect(src.mipmap /* Texture level */);
             else
                 hr = pSurfaceSrc->u.pSurface->UnlockRect();
-            AssertMsgReturn(hr == D3D_OK, ("vmsvga3dSurfaceCopy: Unlock failed with %x\n", hr), VERR_INTERNAL_ERROR);
+            AssertMsgReturn(hr == D3D_OK, ("Unlock failed with %x\n", hr), VERR_INTERNAL_ERROR);
         }
     }
 
@@ -1629,56 +1701,57 @@ int vmsvga3dBackCreateTexture(PVMSVGA3DSTATE pState, PVMSVGA3DCONTEXT pContext,
         AssertMsg(hr == D3D_OK, ("vmsvga3dBackCreateTexture: SetAutoGenFilterType failed with %x\n", hr));
     }
 
-    if (pSurface->fDirty)
+    /*
+     * Always initialize all mipmap levels using the in memory data
+     * to make sure that the just created texture has the up-to-date content.
+     * The OpenGL backend does this too.
+     */
+    Log(("vmsvga3dBackCreateTexture: sync texture\n"));
+    for (uint32_t i = 0; i < pSurface->faces[0].numMipLevels; i++)
     {
-        Log(("vmsvga3dBackCreateTexture: sync dirty texture\n"));
-        for (uint32_t i = 0; i < pSurface->faces[0].numMipLevels; i++)
-        {
-            if (pSurface->pMipmapLevels[i].fDirty)
-            {
-                D3DLOCKED_RECT LockedRect;
+        D3DLOCKED_RECT LockedRect;
 
-                hr = pTexture->LockRect(i, /* texture level */
-                                        &LockedRect,
-                                        NULL,   /* entire texture */
-                                        0);
+        hr = pTexture->LockRect(i, /* texture level */
+                                &LockedRect,
+                                NULL,   /* entire texture */
+                                0);
 
-                AssertMsgReturn(hr == D3D_OK, ("vmsvga3dBackCreateTexture: LockRect failed with %x\n", hr), VERR_INTERNAL_ERROR);
+        AssertMsgReturn(hr == D3D_OK, ("vmsvga3dBackCreateTexture: LockRect failed with %x\n", hr), VERR_INTERNAL_ERROR);
 
-                Log(("vmsvga3dBackCreateTexture: sync dirty texture mipmap level %d (pitch %x vs %x)\n", i, LockedRect.Pitch, pSurface->pMipmapLevels[i].cbSurfacePitch));
+        Log(("vmsvga3dBackCreateTexture: sync texture mipmap level %d (pitch %x vs %x)\n", i, LockedRect.Pitch, pSurface->pMipmapLevels[i].cbSurfacePitch));
 
-                uint8_t *pDest = (uint8_t *)LockedRect.pBits;
-                uint8_t *pSrc  = (uint8_t *)pSurface->pMipmapLevels[i].pSurfaceData;
-                for (uint32_t j = 0; j < pSurface->pMipmapLevels[i].size.height; j++)
-                {
-                    memcpy(pDest, pSrc, pSurface->pMipmapLevels[i].cbSurfacePitch);
+        uint8_t *pDest = (uint8_t *)LockedRect.pBits;
+        uint8_t *pSrc  = (uint8_t *)pSurface->pMipmapLevels[i].pSurfaceData;
+        for (uint32_t j = 0; j < pSurface->pMipmapLevels[i].size.height; j++)
+        {
+            memcpy(pDest, pSrc, pSurface->pMipmapLevels[i].cbSurfacePitch);
 
-                    pDest += LockedRect.Pitch;
-                    pSrc  += pSurface->pMipmapLevels[i].cbSurfacePitch;
-                }
+            pDest += LockedRect.Pitch;
+            pSrc  += pSurface->pMipmapLevels[i].cbSurfacePitch;
+        }
 
-                hr = pTexture->UnlockRect(i /* texture level */);
-                AssertMsgReturn(hr == D3D_OK, ("vmsvga3dBackCreateTexture: UnlockRect failed with %x\n", hr), VERR_INTERNAL_ERROR);
+        hr = pTexture->UnlockRect(i /* texture level */);
+        AssertMsgReturn(hr == D3D_OK, ("vmsvga3dBackCreateTexture: UnlockRect failed with %x\n", hr), VERR_INTERNAL_ERROR);
 
-                pSurface->pMipmapLevels[i].fDirty = false;
-            }
-        }
-        if (pSurface->bounce.pTexture)
-        {
-            Log(("vmsvga3dBackCreateTexture: sync dirty texture from bounce buffer\n"));
+        pSurface->pMipmapLevels[i].fDirty = false;
+    }
+
+    if (pSurface->bounce.pTexture)
+    {
+        Log(("vmsvga3dBackCreateTexture: sync dirty texture from bounce buffer\n"));
 
-            hr = pContext->pDevice->UpdateTexture(pSurface->bounce.pTexture, pSurface->u.pTexture);
-            AssertMsgReturn(hr == D3D_OK, ("vmsvga3dBackCreateTexture: UpdateTexture failed with %x\n", hr), VERR_INTERNAL_ERROR);
+        hr = pContext->pDevice->UpdateTexture(pSurface->bounce.pTexture, pSurface->u.pTexture);
+        AssertMsgReturn(hr == D3D_OK, ("vmsvga3dBackCreateTexture: UpdateTexture failed with %x\n", hr), VERR_INTERNAL_ERROR);
 
-            /* We will now use the bounce texture for all memory accesses, so free our surface memory buffer. */
-            for (uint32_t i = 0; i < pSurface->faces[0].numMipLevels; i++)
-            {
-                RTMemFree(pSurface->pMipmapLevels[i].pSurfaceData);
-                pSurface->pMipmapLevels[i].pSurfaceData = NULL;
-            }
+        /* We will now use the bounce texture for all memory accesses, so free our surface memory buffer. */
+        for (uint32_t i = 0; i < pSurface->faces[0].numMipLevels; i++)
+        {
+            RTMemFree(pSurface->pMipmapLevels[i].pSurfaceData);
+            pSurface->pMipmapLevels[i].pSurfaceData = NULL;
         }
-        pSurface->fDirty = false;
     }
+    pSurface->fDirty = false;
+
     pSurface->flags              |= SVGA3D_SURFACE_HINT_TEXTURE;
     pSurface->idAssociatedContext = idAssociatedContext;
     return VINF_SUCCESS;
@@ -1881,9 +1954,9 @@ int vmsvga3dBackSurfaceDMACopyBox(PVGASTATE pThis, PVMSVGA3DSTATE pState, PVMSVG
         AssertMsgReturn(hr == D3D_OK, ("vmsvga3dSurfaceDMA: LockRect failed with %x\n", hr), VERR_INTERNAL_ERROR);
 
         if (fTexture)
-            Log(("Lock TEXTURE (bounce=%d) memory for rectangle (%d,%d)(%d,%d)\n", !!(pSurface->bounce.pTexture), Rect.left, Rect.top, Rect.right, Rect.bottom));
+            Log(("Lock sid=%x TEXTURE (bounce=%d) memory for rectangle (%d,%d)(%d,%d)\n", pSurface->id, !!(pSurface->bounce.pTexture), Rect.left, Rect.top, Rect.right, Rect.bottom));
         else
-            Log(("Lock %s memory for rectangle (%d,%d)(%d,%d)\n", (pSurface->flags & SVGA3D_SURFACE_HINT_DEPTHSTENCIL) ? "DEPTH-STENCIL" : "RENDERTARGET", Rect.left, Rect.top, Rect.right, Rect.bottom));
+            Log(("Lock sid=%x %s memory for rectangle (%d,%d)(%d,%d)\n", pSurface->id, (pSurface->flags & SVGA3D_SURFACE_HINT_DEPTHSTENCIL) ? "DEPTH-STENCIL" : "RENDERTARGET", Rect.left, Rect.top, Rect.right, Rect.bottom));
 
         rc = vmsvgaGMRTransfer(pThis,
                                transfer,
@@ -1991,7 +2064,7 @@ int vmsvga3dBackSurfaceDMACopyBox(PVGASTATE pThis, PVMSVGA3DSTATE pState, PVMSVG
 int vmsvga3dSurfaceBlitToScreen(PVGASTATE pThis, uint32_t dest, SVGASignedRect destRect, SVGA3dSurfaceImageId src, SVGASignedRect srcRect, uint32_t cRects, SVGASignedRect *pRect)
 {
     /* Requires SVGA_FIFO_CAP_SCREEN_OBJECT support */
-    Log(("vmsvga3dSurfaceBlitToScreen: dest=%d (%d,%d)(%d,%d) surface=%x (face=%d, mipmap=%d) (%d,%d)(%d,%d) cRects=%d\n", dest, destRect.left, destRect.top, destRect.right, destRect.bottom, src.sid, src.face, src.mipmap, srcRect.left, srcRect.top, srcRect.right, srcRect.bottom, cRects));
+    Log(("vmsvga3dSurfaceBlitToScreen: dest=%d (%d,%d)(%d,%d) sid=%x (face=%d, mipmap=%d) (%d,%d)(%d,%d) cRects=%d\n", dest, destRect.left, destRect.top, destRect.right, destRect.bottom, src.sid, src.face, src.mipmap, srcRect.left, srcRect.top, srcRect.right, srcRect.bottom, cRects));
     for (uint32_t i = 0; i < cRects; i++)
     {
         Log(("vmsvga3dSurfaceBlitToScreen: clipping rect %d (%d,%d)(%d,%d)\n", i, pRect[i].left, pRect[i].top, pRect[i].right, pRect[i].bottom));
@@ -2140,7 +2213,7 @@ int vmsvga3dGenerateMipmaps(PVGASTATE pThis, uint32_t sid, SVGA3dTextureFilter f
         pContext = pState->papContexts[cid];
 
         /* Unknown surface type; turn it into a texture. */
-        Log(("vmsvga3dGenerateMipmaps: unknown src surface id=%x type=%d format=%d -> create texture\n", sid, pSurface->flags, pSurface->format));
+        Log(("vmsvga3dGenerateMipmaps: unknown src surface sid=%x type=%d format=%d -> create texture\n", sid, pSurface->flags, pSurface->format));
         rc = vmsvga3dBackCreateTexture(pState, pContext, cid, pSurface);
         AssertRCReturn(rc, rc);
     }
@@ -2538,7 +2611,7 @@ int vmsvga3dContextDestroy(PVGASTATE pThis, uint32_t cid)
             {
                 int rc;
 
-                Log(("vmsvga3dContextDestroy: remove all dependencies for surface %x\n", sid));
+                Log(("vmsvga3dContextDestroy: remove all dependencies for surface sid=%x\n", sid));
 
                 uint32_t            surfaceFlags = pSurface->flags;
                 SVGA3dSurfaceFormat format = pSurface->format;
@@ -2579,7 +2652,7 @@ int vmsvga3dContextDestroy(PVGASTATE pThis, uint32_t cid)
                 PVMSVGA3DSHAREDSURFACE pSharedSurface = (PVMSVGA3DSHAREDSURFACE)RTAvlU32Get(&pSurface->pSharedObjectTree, cid);
                 if (pSharedSurface)
                 {
-                    Log(("vmsvga3dContextDestroy: remove shared dependency for surface %x\n", sid));
+                    Log(("vmsvga3dContextDestroy: remove shared dependency for surface sid=%x\n", sid));
 
                     switch (pSurface->flags & (SVGA3D_SURFACE_HINT_INDEXBUFFER | SVGA3D_SURFACE_HINT_VERTEXBUFFER | SVGA3D_SURFACE_HINT_TEXTURE | SVGA3D_SURFACE_HINT_RENDERTARGET | SVGA3D_SURFACE_HINT_DEPTHSTENCIL | SVGA3D_SURFACE_CUBEMAP))
                     {
@@ -3753,7 +3826,7 @@ int vmsvga3dSetRenderTarget(PVGASTATE pThis, uint32_t cid, SVGA3dRenderTargetTyp
     AssertReturn(type < SVGA3D_RT_MAX, VERR_INVALID_PARAMETER);
     AssertReturn(target.face == 0, VERR_INVALID_PARAMETER);
 
-    Log(("vmsvga3dSetRenderTarget cid=%x type=%x surface id=%x\n", cid, type, target.sid));
+    Log(("vmsvga3dSetRenderTarget cid=%x type=%x sid=%x\n", cid, type, target.sid));
 
     if (    cid >= pState->cContexts
         ||  pState->papContexts[cid]->id != cid)
@@ -3963,7 +4036,7 @@ int vmsvga3dSetRenderTarget(PVGASTATE pThis, uint32_t cid, SVGA3dRenderTargetTyp
             /* A texture surface can be used as a render target to fill it and later on used as a texture. */
             if (!pRenderTarget->u.pTexture)
             {
-                Log(("vmsvga3dSetRenderTarget: create texture to be used as render target; surface id=%x type=%d format=%d -> create texture\n", target.sid, pRenderTarget->flags, pRenderTarget->format));
+                Log(("vmsvga3dSetRenderTarget: create texture to be used as render target; sid=%x type=%d format=%d -> create texture\n", target.sid, pRenderTarget->flags, pRenderTarget->format));
                 int rc = vmsvga3dBackCreateTexture(pState, pContext, cid, pRenderTarget);
                 AssertRCReturn(rc, rc);
             }
@@ -3971,7 +4044,7 @@ int vmsvga3dSetRenderTarget(PVGASTATE pThis, uint32_t cid, SVGA3dRenderTargetTyp
 #ifndef VBOX_VMSVGA3D_WITH_WINE_OPENGL
             if (pRenderTarget->idAssociatedContext != cid)
             {
-                Log(("vmsvga3dSetRenderTarget; using texture %x created for another context (%d vs %d)\n", target.sid, pRenderTarget->idAssociatedContext, cid));
+                Log(("vmsvga3dSetRenderTarget; using texture sid=%x created for another context (%d vs %d)\n", target.sid, pRenderTarget->idAssociatedContext, cid));
 
                 PVMSVGA3DSHAREDSURFACE pSharedSurface = vmsvga3dSurfaceGetSharedCopy(pThis, pContext, pRenderTarget);
                 AssertReturn(pSharedSurface, VERR_INTERNAL_ERROR);
@@ -4299,7 +4372,7 @@ int vmsvga3dSetTextureState(PVGASTATE pThis, uint32_t cid, uint32_t cTextureStat
         case SVGA3D_TS_BIND_TEXTURE:                /* SVGA3dSurfaceId */
             if (pTextureState[i].value == SVGA3D_INVALID_ID)
             {
-                Log(("SVGA3D_TS_BIND_TEXTURE: stage %d, texture surface id=%x\n", currentStage, pTextureState[i].value));
+                Log(("SVGA3D_TS_BIND_TEXTURE: stage %d, texture sid=%x\n", currentStage, pTextureState[i].value));
 
                 pContext->aSidActiveTexture[currentStage] = SVGA3D_INVALID_ID;
                 /* Unselect the currently associated texture. */
@@ -4316,7 +4389,7 @@ int vmsvga3dSetTextureState(PVGASTATE pThis, uint32_t cid, uint32_t cTextureStat
 
                 PVMSVGA3DSURFACE pSurface = pState->papSurfaces[sid];
 
-                Log(("SVGA3D_TS_BIND_TEXTURE: stage %d, texture surface id=%x (%d,%d)\n", currentStage, pTextureState[i].value, pSurface->pMipmapLevels[0].size.width, pSurface->pMipmapLevels[0].size.height));
+                Log(("SVGA3D_TS_BIND_TEXTURE: stage %d, texture sid=%x (%d,%d)\n", currentStage, pTextureState[i].value, pSurface->pMipmapLevels[0].size.width, pSurface->pMipmapLevels[0].size.height));
 
                 if (!pSurface->u.pTexture)
                 {
@@ -4334,7 +4407,7 @@ int vmsvga3dSetTextureState(PVGASTATE pThis, uint32_t cid, uint32_t cTextureStat
 #ifndef VBOX_VMSVGA3D_WITH_WINE_OPENGL
                 if (pSurface->idAssociatedContext != cid)
                 {
-                    Log(("vmsvga3dSetTextureState; using texture %x created for another context (%d vs %d)\n", sid, pSurface->idAssociatedContext, cid));
+                    Log(("vmsvga3dSetTextureState; using texture sid=%x created for another context (%d vs %d)\n", sid, pSurface->idAssociatedContext, cid));
 
                     PVMSVGA3DSHAREDSURFACE pSharedSurface = vmsvga3dSurfaceGetSharedCopy(pThis, pContext, pSurface);
                     AssertReturn(pSharedSurface, VERR_INTERNAL_ERROR);
@@ -4792,7 +4865,7 @@ int vmsvga3dDrawPrimitivesProcessVertexDecls(PVMSVGA3DSTATE pState, PVMSVGA3DCON
         AssertReturn(sidVertex < pState->cSurfaces && pState->papSurfaces[sidVertex]->id == sidVertex, VERR_INVALID_PARAMETER);
 
         pVertexSurface = pState->papSurfaces[sidVertex];
-        Log(("vmsvga3dDrawPrimitives: vertex surface %x stream %d\n", sidVertex, idStream));
+        Log(("vmsvga3dDrawPrimitives: vertex sid=%x stream %d\n", sidVertex, idStream));
         Log(("vmsvga3dDrawPrimitives: type=%s (%d) method=%s (%d) usage=%s (%d) usageIndex=%d stride=%d offset=%d\n", vmsvgaDeclType2String(pVertexDecl[iVertex].identity.type), pVertexDecl[iVertex].identity.type, vmsvgaDeclMethod2String(pVertexDecl[iVertex].identity.method), pVertexDecl[iVertex].identity.method, vmsvgaDeclUsage2String(pVertexDecl[iVertex].identity.usage), pVertexDecl[iVertex].identity.usage, pVertexDecl[iVertex].identity.usageIndex, pVertexDecl[iVertex].array.stride, pVe [...]
 
         rc = vmsvga3dVertexDecl2D3D(pVertexDecl[iVertex].identity, &pVertexElement[iVertex]);
@@ -5009,7 +5082,7 @@ int vmsvga3dDrawPrimitives(PVGASTATE pThis, uint32_t cid, uint32_t numVertexDecl
                 goto internal_error;
             }
             pIndexSurface = pState->papSurfaces[sidIndex];
-            Log(("vmsvga3dDrawPrimitives: index surface %x\n", sidIndex));
+            Log(("vmsvga3dDrawPrimitives: index sid=%x\n", sidIndex));
 
             if (!pIndexSurface->u.pIndexBuffer)
             {
diff --git a/src/VBox/Devices/Graphics/DevVGA-SVGA3d.cpp b/src/VBox/Devices/Graphics/DevVGA-SVGA3d.cpp
index 0e9a5e7..987f214 100644
--- a/src/VBox/Devices/Graphics/DevVGA-SVGA3d.cpp
+++ b/src/VBox/Devices/Graphics/DevVGA-SVGA3d.cpp
@@ -74,6 +74,7 @@ int vmsvga3dSurfaceDefine(PVGASTATE pThis, uint32_t sid, uint32_t surfaceFlags,
      * Since only plain surfaces (cFaces == 1) and cubemaps (cFaces == 6) are supported
      * (see also SVGA3dCmdDefineSurface definition in svga3d_reg.h), we ignore anything else.
      */
+    uint32_t cRemainingMipLevels = cMipLevels;
     uint32_t cFaces = 0;
     for (uint32_t i = 0; i < SVGA3D_MAX_SURFACE_FACES; ++i)
     {
@@ -82,6 +83,11 @@ int vmsvga3dSurfaceDefine(PVGASTATE pThis, uint32_t sid, uint32_t surfaceFlags,
 
         /* All SVGA3dSurfaceFace structures must have the same value of numMipLevels field */
         AssertReturn(face[i].numMipLevels == face[0].numMipLevels, VERR_INVALID_PARAMETER);
+
+        /* numMipLevels value can't be greater than the number of remaining elements in the paMipLevelSizes array. */
+        AssertReturn(face[i].numMipLevels <= cRemainingMipLevels, VERR_INVALID_PARAMETER);
+        cRemainingMipLevels -= face[i].numMipLevels;
+
         ++cFaces;
     }
     for (uint32_t i = cFaces; i < SVGA3D_MAX_SURFACE_FACES; ++i)
@@ -89,7 +95,9 @@ int vmsvga3dSurfaceDefine(PVGASTATE pThis, uint32_t sid, uint32_t surfaceFlags,
 
     /* cFaces must be 6 for a cubemap and 1 otherwise. */
     AssertReturn(cFaces == (uint32_t)((surfaceFlags & SVGA3D_SURFACE_CUBEMAP) ? 6 : 1), VERR_INVALID_PARAMETER);
-    AssertReturn(cMipLevels == cFaces * face[0].numMipLevels, VERR_INVALID_PARAMETER);
+
+    /* Sum of face[i].numMipLevels must be equal to cMipLevels. */
+    AssertReturn(cRemainingMipLevels == 0, VERR_INVALID_PARAMETER);
 
     if (sid >= pState->cSurfaces)
     {
@@ -211,6 +219,7 @@ int vmsvga3dSurfaceDefine(PVGASTATE pThis, uint32_t sid, uint32_t surfaceFlags,
     pSurface->autogenFilter     = autogenFilter;
     Assert(autogenFilter != SVGA3D_TEX_FILTER_FLATCUBIC);
     Assert(autogenFilter != SVGA3D_TEX_FILTER_GAUSSIANCUBIC);
+    pSurface->cMipmapLevels     = cMipLevels;
     pSurface->pMipmapLevels     = (PVMSVGA3DMIPMAPLEVEL)RTMemAllocZ(cMipLevels * sizeof(VMSVGA3DMIPMAPLEVEL));
     AssertReturn(pSurface->pMipmapLevels, VERR_NO_MEMORY);
 
@@ -218,6 +227,7 @@ int vmsvga3dSurfaceDefine(PVGASTATE pThis, uint32_t sid, uint32_t surfaceFlags,
         pSurface->pMipmapLevels[i].size = paMipLevelSizes[i];
 
     pSurface->cbBlock = vmsvga3dSurfaceFormatSize(format);
+    AssertReturn(pSurface->cbBlock, VERR_INVALID_PARAMETER);
 
 #ifdef VMSVGA3D_DIRECT3D
     /* Translate the format and usage flags to D3D. */
@@ -275,16 +285,41 @@ int vmsvga3dSurfaceDefine(PVGASTATE pThis, uint32_t sid, uint32_t surfaceFlags,
     Assert(!VMSVGA3DSURFACE_HAS_HW_SURFACE(pSurface));
 
     /* Allocate buffer to hold the surface data until we can move it into a D3D object */
+    uint32_t cbMemRemaining = SVGA3D_MAX_SURFACE_MEM_SIZE; /* Do not allow more than this for a surface. */
     for (uint32_t i = 0; i < cMipLevels; ++i)
     {
         PVMSVGA3DMIPMAPLEVEL pMipmapLevel = &pSurface->pMipmapLevels[i];
-        LogFunc(("[%d] face %d mip level %d (%d,%d,%d)\n", i, i / pSurface->faces[0].numMipLevels, i % pSurface->faces[0].numMipLevels, pMipmapLevel->size.width, pMipmapLevel->size.height, pMipmapLevel->size.depth));
-        LogFunc(("cbPitch=0x%x cbBlock=0x%x\n", pSurface->cbBlock * pMipmapLevel->size.width, pSurface->cbBlock));
-
-        pMipmapLevel->cbSurfacePitch = pSurface->cbBlock * pMipmapLevel->size.width;
-        pMipmapLevel->cbSurface      = pMipmapLevel->cbSurfacePitch * pMipmapLevel->size.height * pMipmapLevel->size.depth;
-        pMipmapLevel->pSurfaceData   = RTMemAllocZ(pMipmapLevel->cbSurface);
+        LogFunc(("[%d] face %d mip level %d (%d,%d,%d) cbBlock=0x%x\n",
+                 i, i / pSurface->faces[0].numMipLevels, i % pSurface->faces[0].numMipLevels,
+                 pMipmapLevel->size.width, pMipmapLevel->size.height, pMipmapLevel->size.depth, pSurface->cbBlock));
+
+        if (   pMipmapLevel->size.width == 0
+            || pMipmapLevel->size.height == 0
+            || pMipmapLevel->size.depth == 0)
+            return VERR_INVALID_PARAMETER;
+
+        const uint32_t cMaxWidth = cbMemRemaining / pSurface->cbBlock;
+        if (pMipmapLevel->size.width > cMaxWidth)
+            return VERR_INVALID_PARAMETER;
+        const uint32_t cbSurfacePitch = pSurface->cbBlock * pMipmapLevel->size.width;
+        LogFunc(("cbPitch=0x%x\n", cbSurfacePitch));
+
+        const uint32_t cMaxHeight = cbMemRemaining / cbSurfacePitch;
+        if (pMipmapLevel->size.height > cMaxHeight)
+            return VERR_INVALID_PARAMETER;
+        const uint32_t cbSurfacePlane = cbSurfacePitch * pMipmapLevel->size.height;
+
+        const uint32_t cMaxDepth = cbMemRemaining / cbSurfacePlane;
+        if (pMipmapLevel->size.depth > cMaxDepth)
+            return VERR_INVALID_PARAMETER;
+        const uint32_t cbSurface = cbSurfacePlane * pMipmapLevel->size.depth;
+
+        pMipmapLevel->cbSurfacePitch = cbSurfacePitch;
+        pMipmapLevel->cbSurface      = cbSurface;
+        pMipmapLevel->pSurfaceData   = RTMemAllocZ(cbSurface);
         AssertReturn(pMipmapLevel->pSurfaceData, VERR_NO_MEMORY);
+
+        cbMemRemaining -= cbSurface;
     }
     return VINF_SUCCESS;
 }
@@ -327,15 +362,8 @@ int vmsvga3dSurfaceDestroy(PVGASTATE pThis, uint32_t sid)
 
         if (pSurface->pMipmapLevels)
         {
-            for (uint32_t face=0; face < pSurface->cFaces; face++)
-            {
-                for (uint32_t i=0; i < pSurface->faces[face].numMipLevels; i++)
-                {
-                    uint32_t idx = i + face * pSurface->faces[0].numMipLevels;
-                    if (pSurface->pMipmapLevels[idx].pSurfaceData)
-                        RTMemFree(pSurface->pMipmapLevels[idx].pSurfaceData);
-                }
-            }
+            for (uint32_t i = 0; i < pSurface->cMipmapLevels; ++i)
+                RTMemFree(pSurface->pMipmapLevels[i].pSurfaceData);
             RTMemFree(pSurface->pMipmapLevels);
         }
 
@@ -427,9 +455,14 @@ int vmsvga3dSurfaceStretchBlt(PVGASTATE pThis, SVGA3dSurfaceImageId const *pDstS
         AssertRCReturn(rc, rc);
     }
 
+    SVGA3dBox clipSrcBox = *pSrcBox;
+    SVGA3dBox clipDstBox = *pDstBox;
+    vmsvgaClipBox(&pSrcSurface->pMipmapLevels[pSrcSfcImg->mipmap].size, &clipSrcBox);
+    vmsvgaClipBox(&pDstSurface->pMipmapLevels[pDstSfcImg->mipmap].size, &clipDstBox);
+
     return vmsvga3dBackSurfaceStretchBlt(pThis, pState,
-                                         pDstSurface, pDstSfcImg->mipmap, pDstBox,
-                                         pSrcSurface, pSrcSfcImg->mipmap, pSrcBox,
+                                         pDstSurface, pDstSfcImg->mipmap, &clipDstBox,
+                                         pSrcSurface, pSrcSfcImg->mipmap, &clipSrcBox,
                                          enmMode, pContext);
 }
 
@@ -484,33 +517,26 @@ int vmsvga3dSurfaceDMA(PVGASTATE pThis, SVGA3dGuestImage guest, SVGA3dSurfaceIma
             uint8_t *pBufferStart;
 
             Log(("Copy box %d (%d,%d,%d)(%d,%d,%d) dest (%d,%d)\n", i, paBoxes[i].srcx, paBoxes[i].srcy, paBoxes[i].srcz, paBoxes[i].w, paBoxes[i].h, paBoxes[i].d, paBoxes[i].x, paBoxes[i].y));
+
             /* Apparently we're supposed to clip it (gmr test sample) */
-            if (paBoxes[i].x + paBoxes[i].w > pMipLevel->size.width)
-                paBoxes[i].w = pMipLevel->size.width - paBoxes[i].x;
-            if (paBoxes[i].y + paBoxes[i].h > pMipLevel->size.height)
-                paBoxes[i].h = pMipLevel->size.height - paBoxes[i].y;
-            if (paBoxes[i].z + paBoxes[i].d > pMipLevel->size.depth)
-                paBoxes[i].d = pMipLevel->size.depth - paBoxes[i].z;
-
-            if (    !paBoxes[i].w
-                ||  !paBoxes[i].h
-                ||  !paBoxes[i].d
-                ||   paBoxes[i].x > pMipLevel->size.width
-                ||   paBoxes[i].y > pMipLevel->size.height
-                ||   paBoxes[i].z > pMipLevel->size.depth)
+            SVGA3dCopyBox clipBox = paBoxes[i];
+            vmsvgaClipCopyBox(&pMipLevel->size, &pMipLevel->size, &clipBox);
+            if (   !clipBox.w
+                || !clipBox.h
+                || !clipBox.d)
             {
                 Log(("Empty box; skip\n"));
                 continue;
             }
 
-            uDestOffset = paBoxes[i].x * pSurface->cbBlock + paBoxes[i].y * pMipLevel->cbSurfacePitch + paBoxes[i].z * pMipLevel->size.height * pMipLevel->cbSurfacePitch;
-            AssertReturn(uDestOffset + paBoxes[i].w * pSurface->cbBlock * paBoxes[i].h * paBoxes[i].d <= pMipLevel->cbSurface, VERR_INTERNAL_ERROR);
+            uDestOffset = clipBox.x * pSurface->cbBlock + clipBox.y * pMipLevel->cbSurfacePitch + clipBox.z * pMipLevel->size.height * pMipLevel->cbSurfacePitch;
+            AssertReturn(uDestOffset + clipBox.w * pSurface->cbBlock * clipBox.h * clipBox.d <= pMipLevel->cbSurface, VERR_INTERNAL_ERROR);
 
-            cbSrcPitch = (guest.pitch == 0) ? paBoxes[i].w * pSurface->cbBlock : guest.pitch;
+            cbSrcPitch = (guest.pitch == 0) ? clipBox.w * pSurface->cbBlock : guest.pitch;
 #ifdef MANUAL_FLIP_SURFACE_DATA
             pBufferStart =    (uint8_t *)pMipLevel->pSurfaceData
-                            + paBoxes[i].x * pSurface->cbBlock
-                            + pMipLevel->cbSurface - paBoxes[i].y * pMipLevel->cbSurfacePitch
+                            + clipBox.x * pSurface->cbBlock
+                            + pMipLevel->cbSurface - clipBox.y * pMipLevel->cbSurfacePitch
                             - pMipLevel->cbSurfacePitch;      /* flip image during copy */
 #else
             pBufferStart = (uint8_t *)pMipLevel->pSurfaceData + uDestOffset;
@@ -524,10 +550,10 @@ int vmsvga3dSurfaceDMA(PVGASTATE pThis, SVGA3dGuestImage guest, SVGA3dSurfaceIma
                                    (int32_t)pMipLevel->cbSurfacePitch,
 #endif
                                    guest.ptr,
-                                   paBoxes[i].srcx * pSurface->cbBlock + (paBoxes[i].srcy + paBoxes[i].srcz * paBoxes[i].h) * cbSrcPitch,
+                                   clipBox.srcx * pSurface->cbBlock + (clipBox.srcy + clipBox.srcz * clipBox.h) * cbSrcPitch,
                                    cbSrcPitch,
-                                   paBoxes[i].w * pSurface->cbBlock,
-                                   paBoxes[i].d * paBoxes[i].h);
+                                   clipBox.w * pSurface->cbBlock,
+                                   clipBox.d * clipBox.h);
 
             Log4(("first line:\n%.*Rhxd\n", pMipLevel->cbSurfacePitch, pMipLevel->pSurfaceData));
 
@@ -554,30 +580,25 @@ int vmsvga3dSurfaceDMA(PVGASTATE pThis, SVGA3dGuestImage guest, SVGA3dSurfaceIma
 
         for (unsigned i = 0; i < cCopyBoxes; i++)
         {
-            /* Apparently we're supposed to clip it (gmr test sample) */
-            if (paBoxes[i].x + paBoxes[i].w > pMipLevel->size.width)
-                paBoxes[i].w = pMipLevel->size.width - paBoxes[i].x;
-            if (paBoxes[i].y + paBoxes[i].h > pMipLevel->size.height)
-                paBoxes[i].h = pMipLevel->size.height - paBoxes[i].y;
-            if (paBoxes[i].z + paBoxes[i].d > pMipLevel->size.depth)
-                paBoxes[i].d = pMipLevel->size.depth - paBoxes[i].z;
+            Log(("Copy box %d (%d,%d,%d)(%d,%d,%d) dest (%d,%d)\n", i, paBoxes[i].srcx, paBoxes[i].srcy, paBoxes[i].srcz, paBoxes[i].w, paBoxes[i].h, paBoxes[i].d, paBoxes[i].x, paBoxes[i].y));
 
+            /** @todo Is d == 0 valid? */
             Assert((paBoxes[i].d == 1 || paBoxes[i].d == 0) && paBoxes[i].z == 0);
 
-            if (    !paBoxes[i].w
-                ||  !paBoxes[i].h
-                ||   paBoxes[i].x > pMipLevel->size.width
-                ||   paBoxes[i].y > pMipLevel->size.height)
+            /* Apparently we're supposed to clip it (gmr test sample) */
+            SVGA3dCopyBox clipBox = paBoxes[i];
+            vmsvgaClipCopyBox(&pMipLevel->size, &pMipLevel->size, &clipBox);
+            if (   !clipBox.w
+                || !clipBox.h
+                || !clipBox.d)
             {
                 Log(("Empty box; skip\n"));
                 continue;
             }
 
-            Log(("Copy box %d (%d,%d,%d)(%d,%d,%d) dest (%d,%d)\n", i, paBoxes[i].srcx, paBoxes[i].srcy, paBoxes[i].srcz, paBoxes[i].w, paBoxes[i].h, paBoxes[i].d, paBoxes[i].x, paBoxes[i].y));
-
-            uint32_t cbSrcPitch = (guest.pitch == 0) ? paBoxes[i].w * pSurface->cbBlock : guest.pitch;
+            uint32_t cbSrcPitch = (guest.pitch == 0) ? clipBox.w * pSurface->cbBlock : guest.pitch;
             rc = vmsvga3dBackSurfaceDMACopyBox(pThis, pState, pSurface, host.mipmap, guest.ptr, cbSrcPitch, transfer,
-                                               &paBoxes[i], pContext, rc, i);
+                                               &clipBox, pContext, rc, i);
         }
     }
 
diff --git a/src/VBox/Devices/Graphics/DevVGA-SVGA3d.h b/src/VBox/Devices/Graphics/DevVGA-SVGA3d.h
index 9f8bc42..079a978 100644
--- a/src/VBox/Devices/Graphics/DevVGA-SVGA3d.h
+++ b/src/VBox/Devices/Graphics/DevVGA-SVGA3d.h
@@ -30,6 +30,8 @@
 #define SVGA3D_MAX_TEXTURE_STAGE                8
 /** Arbitrary upper limit; seen 8 so far. */
 #define SVGA3D_MAX_LIGHTS                       32
+/** Arbitrary upper limit; 2GB enough for 32768x16384*4. */
+#define SVGA3D_MAX_SURFACE_MEM_SIZE             0x80000000
 
 
 /**@def FLOAT_FMT_STR
diff --git a/src/VBox/Devices/Graphics/DevVGA.cpp b/src/VBox/Devices/Graphics/DevVGA.cpp
index 3f6b74b..841fe31 100644
--- a/src/VBox/Devices/Graphics/DevVGA.cpp
+++ b/src/VBox/Devices/Graphics/DevVGA.cpp
@@ -4406,7 +4406,7 @@ static DECLCALLBACK(void) vgaInfoSR(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, cons
 
     pHlp->pfnPrintf(pHlp, "VGA Sequencer (3C5): SR index 3C4:%02X\n", pThis->sr_index);
     Assert(sizeof(pThis->sr) >= 8);
-    for (i = 0; i < 5; ++i)
+    for (i = 0; i < 8; ++i)
         pHlp->pfnPrintf(pHlp, " SR%02X:%02X", i, pThis->sr[i]);
     pHlp->pfnPrintf(pHlp, "\n");
 }
diff --git a/src/VBox/Devices/Graphics/DevVGA_VDMA.cpp b/src/VBox/Devices/Graphics/DevVGA_VDMA.cpp
index 06da24a..710da81 100644
--- a/src/VBox/Devices/Graphics/DevVGA_VDMA.cpp
+++ b/src/VBox/Devices/Graphics/DevVGA_VDMA.cpp
@@ -2656,6 +2656,7 @@ static DECLCALLBACK(int) vboxVDMAWorkerThread(RTTHREAD hThreadSelf, void *pvUser
                 if (fContinue)
                     break;
             }
+            /* fall thru */
             case VBVAEXHOST_DATA_TYPE_NO_DATA:
                 rc = VBoxVDMAThreadEventWait(&pVdma->Thread, RT_INDEFINITE_WAIT);
                 AssertRC(rc);
diff --git a/src/VBox/Devices/Input/DevPS2.cpp b/src/VBox/Devices/Input/DevPS2.cpp
index 82fed87..d8152ae 100644
--- a/src/VBox/Devices/Input/DevPS2.cpp
+++ b/src/VBox/Devices/Input/DevPS2.cpp
@@ -718,6 +718,7 @@ PDMBOTHCBDECL(int) kbdIOPortStatusRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPOR
     switch (cb) {
     case 2:
         fluff = 0xff00;
+        /* fall thru */
     case 1:
         *pu32 = fluff | kbd_read_status(pThis, Port);
         Log2(("kbdIOPortStatusRead: Port=%#x cb=%d -> *pu32=%#x\n", Port, cb, *pu32));
diff --git a/src/VBox/Devices/Input/PS2K.cpp b/src/VBox/Devices/Input/PS2K.cpp
index 80eae0f..c318f12 100644
--- a/src/VBox/Devices/Input/PS2K.cpp
+++ b/src/VBox/Devices/Input/PS2K.cpp
@@ -750,6 +750,7 @@ int PS2KByteToKbd(PPS2K pThis, uint8_t cmd)
             /* Fall through only to handle unrecognized commands. */
             if (fHandled)
                 break;
+            /* fall thru */
 
         case KCMD_INVALID_1:
         case KCMD_INVALID_2:
diff --git a/src/VBox/Devices/Input/PS2M.cpp b/src/VBox/Devices/Input/PS2M.cpp
index d5c9c47..9f5cadd 100644
--- a/src/VBox/Devices/Input/PS2M.cpp
+++ b/src/VBox/Devices/Input/PS2M.cpp
@@ -777,6 +777,7 @@ int PS2MByteToAux(PPS2M pThis, uint8_t cmd)
             /* Fall through only to handle unrecognized commands. */
             if (fHandled)
                 break;
+            /* fall thru */
 
         case ACMD_INVALID_1:
         case ACMD_INVALID_2:
diff --git a/src/VBox/Devices/Makefile.kmk b/src/VBox/Devices/Makefile.kmk
index 05b6164..6abd94f 100644
--- a/src/VBox/Devices/Makefile.kmk
+++ b/src/VBox/Devices/Makefile.kmk
@@ -4,7 +4,7 @@
 #
 
 #
-# Copyright (C) 2006-2016 Oracle Corporation
+# Copyright (C) 2006-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;
@@ -540,16 +540,18 @@ if !defined(VBOX_ONLY_EXTPACKS)         # Goes on almost to the end of the file.
  	Audio/DevSB16.cpp \
  	Audio/DevHDA.cpp \
  	Audio/HDACodec.cpp \
+ 	Audio/HDAStreamPeriod.cpp \
  	Audio/AudioMixBuffer.cpp \
  	Audio/AudioMixer.cpp \
  	Audio/DrvAudio.cpp \
  	Audio/DrvAudioCommon.cpp \
  	Audio/DrvHostNullAudio.cpp
 
- ifdef VBOX_WITH_AUDIO_DEBUG
-  VBoxDD_DEFS    += VBOX_WITH_AUDIO_DEBUG
+ VBoxDD_DEFS += $(if $(VBOX_AUDIO_DEBUG_DUMP_PCM_DATA),VBOX_AUDIO_DEBUG_DUMP_PCM_DATA,)
+ ifdef VBOX_WITH_AUDIO_VALIDATIONKIT
+  VBoxDD_DEFS    += VBOX_WITH_AUDIO_VALIDATIONKIT
   VBoxDD_SOURCES += \
-	Audio/DrvHostDebugAudio.cpp
+	Audio/DrvHostValidationKit.cpp
  endif
 
  ifeq ($(KBUILD_TARGET),darwin)
diff --git a/src/VBox/Devices/Misc/VirtualKD.cpp b/src/VBox/Devices/Misc/VirtualKD.cpp
index 5c13904..68be83a 100644
--- a/src/VBox/Devices/Misc/VirtualKD.cpp
+++ b/src/VBox/Devices/Misc/VirtualKD.cpp
@@ -73,7 +73,7 @@ typedef struct VIRTUALKD
     bool fChannelDetectSuccessful;
     RTLDRMOD hLib;
     IKDClient *pKDClient;
-    char abCmdBody[262144];
+    char abCmdBody[_256K];
 } VIRTUALKD;
 
 
@@ -107,17 +107,17 @@ static DECLCALLBACK(int) vkdPortWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT
     {
         VKDREQUESTHDR RequestHeader = {0, };
         int rc = PDMDevHlpPhysRead(pDevIns, (RTGCPHYS)u32, &RequestHeader, sizeof(RequestHeader));
-        if (!RT_SUCCESS(rc) || !RequestHeader.cbData)
+        if (   !RT_SUCCESS(rc)
+            || !RequestHeader.cbData)
             return VINF_SUCCESS;
-        rc = PDMDevHlpPhysRead(pDevIns, (RTGCPHYS)(u32 + sizeof(RequestHeader)), pThis->abCmdBody, RequestHeader.cbData);
+
+        unsigned cbData = RT_MIN(RequestHeader.cbData, sizeof(pThis->abCmdBody));
+        rc = PDMDevHlpPhysRead(pDevIns, (RTGCPHYS)(u32 + sizeof(RequestHeader)), pThis->abCmdBody, cbData);
         if (!RT_SUCCESS(rc))
             return VINF_SUCCESS;
 
         char *pReply = NULL;
-        unsigned cbReply;
-        cbReply = pThis->pKDClient->OnRequest(pThis->abCmdBody,
-                                              RequestHeader.cbData,
-                                              &pReply);
+        unsigned cbReply = pThis->pKDClient->OnRequest(pThis->abCmdBody, cbData, &pReply);
 
         if (!pReply)
             cbReply = 0;
diff --git a/src/VBox/Devices/Network/DevE1000.cpp b/src/VBox/Devices/Network/DevE1000.cpp
index 83e79f4..790434a 100644
--- a/src/VBox/Devices/Network/DevE1000.cpp
+++ b/src/VBox/Devices/Network/DevE1000.cpp
@@ -3720,7 +3720,6 @@ DECLINLINE(int) e1kXmitAllocBuf(PE1KSTATE pThis, bool fGso)
                  pThis->szPrf, pThis->cbTxAlloc,
                  pThis->fVTag ? "VLAN " : "",
                  pThis->fGSO ? "GSO " : ""));
-        pThis->cbTxAlloc = 0;
     }
     else
     {
@@ -3736,6 +3735,7 @@ DECLINLINE(int) e1kXmitAllocBuf(PE1KSTATE pThis, bool fGso)
         pSg->aSegs[0].pvSeg = pThis->aTxPacketFallback;
         pSg->aSegs[0].cbSeg = sizeof(pThis->aTxPacketFallback);
     }
+    pThis->cbTxAlloc = 0;
 
     pThis->CTX_SUFF(pTxSg) = pSg;
     return VINF_SUCCESS;
@@ -4019,6 +4019,13 @@ static void e1kInsertChecksum(PE1KSTATE pThis, uint8_t *pPkt, uint16_t u16PktLen
 
     if (cse == 0)
         cse = u16PktLen - 1;
+    else if (cse < css)
+    {
+        E1kLog2(("%s css(%X) is greater than cse(%X), checksum is not inserted\n",
+                 pThis->szPrf, css, cse));
+        return;
+    }
+
     uint16_t u16ChkSum = e1kCSum16(pPkt + css, cse - css + 1);
     E1kLog2(("%s Inserting csum: %04X at %02X, old value: %04X\n", pThis->szPrf,
              u16ChkSum, cso, *(uint16_t*)(pPkt + cso)));
@@ -4354,13 +4361,21 @@ static int e1kFallbackAddToFrame(PE1KSTATE pThis, E1KTXDESC *pDesc, bool fOnWork
 #endif
 
     uint16_t u16MaxPktLen = pThis->contextTSE.dw3.u8HDRLEN + pThis->contextTSE.dw3.u16MSS;
-    Assert(u16MaxPktLen != 0);
-    Assert(u16MaxPktLen < E1K_MAX_TX_PKT_SIZE);
+    if (RT_UNLIKELY(u16MaxPktLen <= pThis->contextTSE.dw3.u8HDRLEN))
+    {
+        E1kLog(("%s Transmit packet is too small: %u <= %u(min)\n", pThis->szPrf, u16MaxPktLen, pThis->contextTSE.dw3.u8HDRLEN));
+        return VINF_SUCCESS; // @todo consider VERR_BUFFER_UNDERFLOW;
+    }
+    if (RT_UNLIKELY(u16MaxPktLen > E1K_MAX_TX_PKT_SIZE || u16MaxPktLen > pThis->CTX_SUFF(pTxSg)->cbAvailable))
+    {
+        E1kLog(("%s Transmit packet is too large: %u > %u(max)\n", pThis->szPrf, u16MaxPktLen, E1K_MAX_TX_PKT_SIZE));
+        return VINF_SUCCESS; // @todo consider VERR_BUFFER_OVERFLOW;
+    }
 
     /*
      * Carve out segments.
      */
-    int rc;
+    int rc = VINF_SUCCESS;
     do
     {
         /* Calculate how many bytes we have left in this TCP segment */
@@ -4394,7 +4409,7 @@ static int e1kFallbackAddToFrame(PE1KSTATE pThis, E1KTXDESC *pDesc, bool fOnWork
         e1kXmitFreeBuf(pThis);
     }
 
-    return false;
+    return VINF_SUCCESS; // @todo consider rc;
 }
 #endif /* E1K_WITH_TXD_CACHE */
 
diff --git a/src/VBox/Devices/Network/DevVirtioNet.cpp b/src/VBox/Devices/Network/DevVirtioNet.cpp
index acda3cf..ef91d55 100644
--- a/src/VBox/Devices/Network/DevVirtioNet.cpp
+++ b/src/VBox/Devices/Network/DevVirtioNet.cpp
@@ -1145,9 +1145,104 @@ DECLINLINE(uint16_t) vnetCSum16(const void *pvBuf, size_t cb)
 
 DECLINLINE(void) vnetCompleteChecksum(uint8_t *pBuf, size_t cbSize, uint16_t uStart, uint16_t uOffset)
 {
+    AssertReturnVoid(uStart < cbSize);
+    AssertReturnVoid(uStart + uOffset + sizeof(uint16_t) <= cbSize);
     *(uint16_t*)(pBuf + uStart + uOffset) = vnetCSum16(pBuf + uStart, cbSize - uStart);
 }
 
+static bool vnetReadHeader(PVNETSTATE pThis, RTGCPHYS GCPhys, PVNETHDR pHdr, uint32_t cbMax)
+{
+    int rc = PDMDevHlpPhysRead(pThis->VPCI.CTX_SUFF(pDevIns), GCPhys, pHdr, sizeof(*pHdr));
+    if (RT_FAILURE(rc))
+        return false;
+
+    Log4(("virtio-net: header flags=%x gso-type=%x len=%x gso-size=%x csum-start=%x csum-offset=%x cb=%x\n",
+          pHdr->u8Flags, pHdr->u8GSOType, pHdr->u16HdrLen, pHdr->u16GSOSize, pHdr->u16CSumStart, pHdr->u16CSumOffset, cbMax));
+
+    if (pHdr->u8GSOType)
+    {
+        uint32_t u32MinHdrSize;
+
+        /* Segmentation offloading cannot be done without checksumming. */
+        if (RT_UNLIKELY(!(pHdr->u8Flags & VNETHDR_F_NEEDS_CSUM)))
+            return false;
+        /* We do not support ECN. */
+        if (RT_UNLIKELY(pHdr->u8GSOType & VNETHDR_GSO_ECN))
+            return false;
+        switch (pHdr->u8GSOType)
+        {
+            case VNETHDR_GSO_TCPV4:
+            case VNETHDR_GSO_TCPV6:
+                u32MinHdrSize = sizeof(RTNETTCP);
+                break;
+            case VNETHDR_GSO_UDP:
+                u32MinHdrSize = 0;
+                break;
+            default:
+                return false;
+        }
+        /* Header+MSS must not exceed the packet size. */
+        if (RT_UNLIKELY(u32MinHdrSize + pHdr->u16CSumStart + pHdr->u16GSOSize > cbMax))
+            return false;
+    }
+    /* Checksum must fit into the frame (validating both checksum fields). */
+    if (   (pHdr->u8Flags & VNETHDR_F_NEEDS_CSUM)
+        && sizeof(uint16_t) + pHdr->u16CSumStart + pHdr->u16CSumOffset > cbMax)
+        return false;
+    Log4(("virtio-net: return true\n"));
+    return true;
+}
+
+static int vnetTransmitFrame(PVNETSTATE pThis, PPDMSCATTERGATHER pSgBuf, PPDMNETWORKGSO pGso, PVNETHDR pHdr)
+{
+    vnetPacketDump(pThis, (uint8_t *)pSgBuf->aSegs[0].pvSeg, pSgBuf->cbUsed, "--> Outgoing");
+    if (pGso)
+    {
+        /* Some guests (RHEL) may report HdrLen excluding transport layer header! */
+        /*
+         * We cannot use cdHdrs provided by the guest because of different ways
+         * it gets filled out by different versions of kernels.
+         */
+        //if (pGso->cbHdrs < pHdr->u16CSumStart + pHdr->u16CSumOffset + 2)
+        {
+            Log4(("%s vnetTransmitPendingPackets: HdrLen before adjustment %d.\n",
+                  INSTANCE(pThis), pGso->cbHdrsTotal));
+            switch (pGso->u8Type)
+            {
+                case PDMNETWORKGSOTYPE_IPV4_TCP:
+                case PDMNETWORKGSOTYPE_IPV6_TCP:
+                    pGso->cbHdrsTotal = pHdr->u16CSumStart +
+                        ((PRTNETTCP)(((uint8_t*)pSgBuf->aSegs[0].pvSeg) + pHdr->u16CSumStart))->th_off * 4;
+                    pGso->cbHdrsSeg   = pGso->cbHdrsTotal;
+                    break;
+                case PDMNETWORKGSOTYPE_IPV4_UDP:
+                    pGso->cbHdrsTotal = (uint8_t)(pHdr->u16CSumStart + sizeof(RTNETUDP));
+                    pGso->cbHdrsSeg   = pHdr->u16CSumStart;
+                    break;
+            }
+            /* Update GSO structure embedded into the frame */
+            ((PPDMNETWORKGSO)pSgBuf->pvUser)->cbHdrsTotal = pGso->cbHdrsTotal;
+            ((PPDMNETWORKGSO)pSgBuf->pvUser)->cbHdrsSeg   = pGso->cbHdrsSeg;
+            Log4(("%s vnetTransmitPendingPackets: adjusted HdrLen to %d.\n",
+                  INSTANCE(pThis), pGso->cbHdrsTotal));
+        }
+        Log2(("%s vnetTransmitPendingPackets: gso type=%x cbHdrsTotal=%u cbHdrsSeg=%u mss=%u off1=0x%x off2=0x%x\n",
+              INSTANCE(pThis), pGso->u8Type, pGso->cbHdrsTotal, pGso->cbHdrsSeg, pGso->cbMaxSeg, pGso->offHdr1, pGso->offHdr2));
+        STAM_REL_COUNTER_INC(&pThis->StatTransmitGSO);
+    }
+    else if (pHdr->u8Flags & VNETHDR_F_NEEDS_CSUM)
+    {
+        STAM_REL_COUNTER_INC(&pThis->StatTransmitCSum);
+        /*
+         * This is not GSO frame but checksum offloading is requested.
+         */
+        vnetCompleteChecksum((uint8_t*)pSgBuf->aSegs[0].pvSeg, pSgBuf->cbUsed,
+                             pHdr->u16CSumStart, pHdr->u16CSumOffset);
+    }
+
+    return pThis->pDrv->pfnSendBuf(pThis->pDrv, pSgBuf, false);
+}
+
 static void vnetTransmitPendingPackets(PVNETSTATE pThis, PVQUEUE pQueue, bool fOnWorkerThread)
 {
     /*
@@ -1203,6 +1298,7 @@ static void vnetTransmitPendingPackets(PVNETSTATE pThis, PVQUEUE pQueue, bool fO
         }
         else
         {
+            VNETHDR Hdr;
             unsigned int uSize = 0;
             STAM_PROFILE_ADV_START(&pThis->StatTransmit, a);
             /* Compute total frame size. */
@@ -1213,14 +1309,10 @@ static void vnetTransmitPendingPackets(PVNETSTATE pThis, PVQUEUE pQueue, bool fO
             /* Truncate oversized frames. */
             if (uSize > VNET_MAX_FRAME_SIZE)
                 uSize = VNET_MAX_FRAME_SIZE;
-            if (pThis->pDrv)
+            if (pThis->pDrv && vnetReadHeader(pThis, elem.aSegsOut[0].addr, &Hdr, uSize))
             {
-                VNETHDR Hdr;
                 PDMNETWORKGSO Gso, *pGso;
 
-                PDMDevHlpPhysRead(pThis->VPCI.CTX_SUFF(pDevIns), elem.aSegsOut[0].addr,
-                                  &Hdr, sizeof(Hdr));
-
                 STAM_REL_COUNTER_INC(&pThis->StatTransmitPackets);
 
                 STAM_PROFILE_START(&pThis->StatTransmitSend, a);
@@ -1243,52 +1335,7 @@ static void vnetTransmitPendingPackets(PVNETSTATE pThis, PVQUEUE pQueue, bool fO
                         uOffset += cbSegment;
                         uSize -= cbSegment;
                     }
-                    vnetPacketDump(pThis, (uint8_t *)pSgBuf->aSegs[0].pvSeg, pSgBuf->cbUsed, "--> Outgoing");
-                    if (pGso)
-                    {
-                        /* Some guests (RHEL) may report HdrLen excluding transport layer header! */
-                        /*
-                         * We cannot use cdHdrs provided by the guest because of different ways
-                         * it gets filled out by different versions of kernels.
-                         */
-                        //if (pGso->cbHdrs < Hdr.u16CSumStart + Hdr.u16CSumOffset + 2)
-                        {
-                            Log4(("%s vnetTransmitPendingPackets: HdrLen before adjustment %d.\n",
-                                  INSTANCE(pThis), pGso->cbHdrsTotal));
-                            switch (pGso->u8Type)
-                            {
-                                case PDMNETWORKGSOTYPE_IPV4_TCP:
-                                case PDMNETWORKGSOTYPE_IPV6_TCP:
-                                    pGso->cbHdrsTotal = Hdr.u16CSumStart +
-                                        ((PRTNETTCP)(((uint8_t*)pSgBuf->aSegs[0].pvSeg) + Hdr.u16CSumStart))->th_off * 4;
-                                    pGso->cbHdrsSeg   = pGso->cbHdrsTotal;
-                                    break;
-                                case PDMNETWORKGSOTYPE_IPV4_UDP:
-                                    pGso->cbHdrsTotal = (uint8_t)(Hdr.u16CSumStart + sizeof(RTNETUDP));
-                                    pGso->cbHdrsSeg   = Hdr.u16CSumStart;
-                                    break;
-                            }
-                            /* Update GSO structure embedded into the frame */
-                            ((PPDMNETWORKGSO)pSgBuf->pvUser)->cbHdrsTotal = pGso->cbHdrsTotal;
-                            ((PPDMNETWORKGSO)pSgBuf->pvUser)->cbHdrsSeg   = pGso->cbHdrsSeg;
-                            Log4(("%s vnetTransmitPendingPackets: adjusted HdrLen to %d.\n",
-                                  INSTANCE(pThis), pGso->cbHdrsTotal));
-                        }
-                        Log2(("%s vnetTransmitPendingPackets: gso type=%x cbHdrsTotal=%u cbHdrsSeg=%u mss=%u off1=0x%x off2=0x%x\n",
-                              INSTANCE(pThis), pGso->u8Type, pGso->cbHdrsTotal, pGso->cbHdrsSeg, pGso->cbMaxSeg, pGso->offHdr1, pGso->offHdr2));
-                        STAM_REL_COUNTER_INC(&pThis->StatTransmitGSO);
-                    }
-                    else if (Hdr.u8Flags & VNETHDR_F_NEEDS_CSUM)
-                    {
-                        STAM_REL_COUNTER_INC(&pThis->StatTransmitCSum);
-                        /*
-                         * This is not GSO frame but checksum offloading is requested.
-                         */
-                        vnetCompleteChecksum((uint8_t*)pSgBuf->aSegs[0].pvSeg, pSgBuf->cbUsed,
-                                             Hdr.u16CSumStart, Hdr.u16CSumOffset);
-                    }
-
-                    rc = pThis->pDrv->pfnSendBuf(pThis->pDrv, pSgBuf, false);
+                    rc = vnetTransmitFrame(pThis, pSgBuf, pGso, &Hdr);
                 }
                 else
                 {
diff --git a/src/VBox/Devices/Network/slirp/libalias/alias_ftp.c b/src/VBox/Devices/Network/slirp/libalias/alias_ftp.c
index 9c218ad..aa81dd9 100644
--- a/src/VBox/Devices/Network/slirp/libalias/alias_ftp.c
+++ b/src/VBox/Devices/Network/slirp/libalias/alias_ftp.c
@@ -340,6 +340,7 @@ ParseFtpPortCommand(struct libalias *la, char *sptr, int dlen)
                 break;
             else
                 state++;
+            /* FALLTHRU */
         case 1:
         case 3:
         case 5:
diff --git a/src/VBox/Devices/PC/DevACPI.cpp b/src/VBox/Devices/PC/DevACPI.cpp
index b4337b5..febadf5 100644
--- a/src/VBox/Devices/PC/DevACPI.cpp
+++ b/src/VBox/Devices/PC/DevACPI.cpp
@@ -383,9 +383,9 @@ typedef struct ACPIState
 
     uint32_t            Alignment1;
 
-    /* Physical address of PCI config space MMIO region */
+    /** Physical address of PCI config space MMIO region */
     uint64_t            u64PciConfigMMioAddress;
-    /* Length of PCI config space MMIO region */
+    /** Length of PCI config space MMIO region */
     uint64_t            u64PciConfigMMioLength;
     /** Serial 0 IRQ number */
     uint8_t             uSerial0Irq;
diff --git a/src/VBox/Devices/PC/DevDMA.cpp b/src/VBox/Devices/PC/DevDMA.cpp
index f4a0942..6d33dc6 100644
--- a/src/VBox/Devices/PC/DevDMA.cpp
+++ b/src/VBox/Devices/PC/DevDMA.cpp
@@ -433,6 +433,7 @@ static DECLCALLBACK(int) dmaReadCtl(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT p
             case CTL_R_MODE:
                 val = dc->ChState[dc->u8ModeCtr].u8Mode | 3;
                 dc->u8ModeCtr = (dc->u8ModeCtr + 1) & 3;
+                break;
             case CTL_R_SETBPTR:
                 dc->fHiByte = true;
                 break;
diff --git a/src/VBox/Devices/PC/DevPcBios.cpp b/src/VBox/Devices/PC/DevPcBios.cpp
index b72f9a6..37db999 100644
--- a/src/VBox/Devices/PC/DevPcBios.cpp
+++ b/src/VBox/Devices/PC/DevPcBios.cpp
@@ -198,8 +198,10 @@ typedef struct DEVPCBIOS
     uint16_t        au16NetBootDev[NET_BOOT_DEVS];
     /** Number of logical CPUs in guest */
     uint16_t        cCpus;
-    uint32_t        u32McfgBase;
-    uint32_t        cbMcfgLength;
+    /* Physical address of PCI config space MMIO region. Currently unused. */
+    uint64_t        u64McfgBase;
+    /* Length of PCI config space MMIO region. Currently unused. */
+    uint64_t        cbMcfgLength;
 
     /** Firmware registration structure.   */
     PDMFWREG        FwReg;
@@ -1158,11 +1160,11 @@ static DECLCALLBACK(int)  pcbiosConstruct(PPDMDEVINS pDevIns, int iInstance, PCF
         return PDMDEV_SET_ERROR(pDevIns, rc,
                                 N_("Configuration error: Querying \"NumCPUs\" as integer failed"));
 
-    rc = CFGMR3QueryU32Def(pCfg, "McfgBase", &pThis->u32McfgBase, 0);
+    rc = CFGMR3QueryU64Def(pCfg, "McfgBase", &pThis->u64McfgBase, 0);
     if (RT_FAILURE(rc))
         return PDMDEV_SET_ERROR(pDevIns, rc,
                                 N_("Configuration error: Querying \"\" as integer failed"));
-    rc = CFGMR3QueryU32Def(pCfg, "McfgLength", &pThis->cbMcfgLength, 0);
+    rc = CFGMR3QueryU64Def(pCfg, "McfgLength", &pThis->cbMcfgLength, 0);
     if (RT_FAILURE(rc))
         return PDMDEV_SET_ERROR(pDevIns, rc,
                                 N_("Configuration error: Querying \"McfgLength\" as integer failed"));
diff --git a/src/VBox/Devices/PC/ipxe/src/include/curses.h b/src/VBox/Devices/PC/ipxe/src/include/curses.h
index 2069779..9b2a765 100644
--- a/src/VBox/Devices/PC/ipxe/src/include/curses.h
+++ b/src/VBox/Devices/PC/ipxe/src/include/curses.h
@@ -430,7 +430,7 @@ extern int wborder ( WINDOW *, chtype, chtype, chtype, chtype, chtype, chtype,
 extern int wclrtobot ( WINDOW * ) __nonnull;
 extern int wclrtoeol ( WINDOW * ) __nonnull;
 extern void wcursyncup ( WINDOW * );
-extern int wcolour_set ( WINDOW *, short, void * ) __nonnull;
+extern int wcolour_set ( WINDOW *, short, void * ) /*__nonnull*/;
 #define wcolor_set(w,s,v) wcolour_set((w),(s),(v))
 extern int wdelch ( WINDOW * ) __nonnull;
 extern int wdeleteln ( WINDOW * ) __nonnull;
diff --git a/src/VBox/Devices/Storage/DevAHCI.cpp b/src/VBox/Devices/Storage/DevAHCI.cpp
index 98e8ee6..ab4dd6b 100644
--- a/src/VBox/Devices/Storage/DevAHCI.cpp
+++ b/src/VBox/Devices/Storage/DevAHCI.cpp
@@ -4350,6 +4350,7 @@ static int atapiReadDVDStructureSS(PAHCIREQ pAhciReq, PAHCIPort pAhciPort, size_
             /** @todo BD support, fall through for now */
 
         /* Generic disk structures */
+        /* fall thru */
         case 0x80: /** @todo AACS volume identifier */
         case 0x81: /** @todo AACS media serial number */
         case 0x82: /** @todo AACS media identifier */
@@ -6435,6 +6436,7 @@ static AHCITXDIR ahciProcessCmd(PAHCIPort pAhciPort, PAHCIREQ pAhciReq, uint8_t
             break;
         case ATA_READ_DMA_EXT:
             fLBA48 = true;
+            /* fall through */
         case ATA_READ_DMA:
         {
             pAhciReq->cbTransfer = ahciGetNSectors(pCmdFis, fLBA48) * pAhciPort->cbSector;
@@ -6444,6 +6446,7 @@ static AHCITXDIR ahciProcessCmd(PAHCIPort pAhciPort, PAHCIREQ pAhciReq, uint8_t
         }
         case ATA_WRITE_DMA_EXT:
             fLBA48 = true;
+            /* fall through */
         case ATA_WRITE_DMA:
         {
             pAhciReq->cbTransfer = ahciGetNSectors(pCmdFis, fLBA48) * pAhciPort->cbSector;
@@ -6561,6 +6564,7 @@ static AHCITXDIR ahciProcessCmd(PAHCIPort pAhciPort, PAHCIREQ pAhciReq, uint8_t
             }
             /* else: fall through and report error to the guest. */
         }
+        /* fall thru */
         /* All not implemented commands go below. */
         case ATA_SECURITY_FREEZE_LOCK:
         case ATA_SMART:
@@ -8574,8 +8578,9 @@ static DECLCALLBACK(int) ahciR3Construct(PPDMDEVINS pDevIns, int iInstance, PCFG
     /* Attach drivers to every available port. */
     for (i = 0; i < pThis->cPortsImpl; i++)
     {
-        char szName[24];
-        RTStrPrintf(szName, sizeof(szName), "Port%u", i);
+        char *pszName;
+        if (RTStrAPrintf(&pszName, "Port%u", i) <= 0)
+            AssertLogRelFailedReturn(VERR_NO_MEMORY);
 
         PAHCIPort pAhciPort      = &pThis->ahciPort[i];
         /*
@@ -8589,7 +8594,7 @@ static DECLCALLBACK(int) ahciR3Construct(PPDMDEVINS pDevIns, int iInstance, PCFG
         pAhciPort->fWrkThreadSleeping                   = true;
 
         /* Query per port configuration options if available. */
-        PCFGMNODE pCfgPort = CFGMR3GetChild(pDevIns->pCfg, szName);
+        PCFGMNODE pCfgPort = CFGMR3GetChild(pDevIns->pCfg, pszName);
         if (pCfgPort)
         {
             rc = CFGMR3QueryBoolDef(pCfgPort, "Hotpluggable", &pAhciPort->fHotpluggable, true);
@@ -8601,13 +8606,13 @@ static DECLCALLBACK(int) ahciR3Construct(PPDMDEVINS pDevIns, int iInstance, PCFG
         /*
          * Attach the block driver
          */
-        rc = PDMDevHlpDriverAttach(pDevIns, pAhciPort->iLUN, &pAhciPort->IBase, &pAhciPort->pDrvBase, szName);
+        rc = PDMDevHlpDriverAttach(pDevIns, pAhciPort->iLUN, &pAhciPort->IBase, &pAhciPort->pDrvBase, pszName);
         if (RT_SUCCESS(rc))
         {
             rc = ahciR3ConfigureLUN(pDevIns, pAhciPort);
             if (RT_FAILURE(rc))
             {
-                Log(("%s: Failed to configure the %s.\n", __FUNCTION__, szName));
+                Log(("%s: Failed to configure the %s.\n", __FUNCTION__, pszName));
                 return rc;
             }
 
@@ -8618,7 +8623,7 @@ static DECLCALLBACK(int) ahciR3Construct(PPDMDEVINS pDevIns, int iInstance, PCFG
             /*
              * Init vendor product data.
              */
-            rc = ahciR3VpdInit(pDevIns, pAhciPort, szName);
+            rc = ahciR3VpdInit(pDevIns, pAhciPort, pszName);
             if (RT_FAILURE(rc))
                 return rc;
 
@@ -8644,20 +8649,20 @@ static DECLCALLBACK(int) ahciR3Construct(PPDMDEVINS pDevIns, int iInstance, PCFG
                                            N_("AHCI: Failed to create SUP event semaphore"));
 
             rc = PDMDevHlpThreadCreate(pDevIns, &pAhciPort->pAsyncIOThread, pAhciPort, ahciAsyncIOLoop,
-                                       ahciAsyncIOLoopWakeUp, 0, RTTHREADTYPE_IO, szName);
+                                       ahciAsyncIOLoopWakeUp, 0, RTTHREADTYPE_IO, pszName);
             if (RT_FAILURE(rc))
                 return PDMDevHlpVMSetError(pDevIns, rc, RT_SRC_POS,
-                                           N_("AHCI: Failed to create worker thread %s"), szName);
+                                           N_("AHCI: Failed to create worker thread %s"), pszName);
         }
         else if (rc == VERR_PDM_NO_ATTACHED_DRIVER)
         {
             pAhciPort->pDrvBase = NULL;
             rc = VINF_SUCCESS;
-            LogRel(("AHCI: %s: No driver attached\n", szName));
+            LogRel(("AHCI: %s: No driver attached\n", pszName));
         }
         else
             return PDMDevHlpVMSetError(pDevIns, rc, RT_SRC_POS,
-                                       N_("AHCI: Failed to attach drive to %s"), szName);
+                                       N_("AHCI: Failed to attach drive to %s"), pszName);
     }
 
     /*
diff --git a/src/VBox/Devices/Storage/DevATA.cpp b/src/VBox/Devices/Storage/DevATA.cpp
index 4dea902..28702c2 100644
--- a/src/VBox/Devices/Storage/DevATA.cpp
+++ b/src/VBox/Devices/Storage/DevATA.cpp
@@ -2415,6 +2415,7 @@ static bool atapiR3ReadDVDStructureSS(ATADevState *s)
                 break;
             }
             /** @todo BD support, fall through for now */
+            /* fall thru */
 
         /* Generic disk structures */
         case 0x80: /** @todo AACS volume identifier */
@@ -4070,6 +4071,7 @@ static void ataR3ParseCmd(ATADevState *s, uint8_t cmd)
             break;
         case ATA_READ_VERIFY_SECTORS_EXT:
             s->fLBA48 = true;
+            /* fall thru */
         case ATA_READ_VERIFY_SECTORS:
         case ATA_READ_VERIFY_SECTORS_WITHOUT_RETRIES:
             /* do sector number check ? */
@@ -4078,6 +4080,7 @@ static void ataR3ParseCmd(ATADevState *s, uint8_t cmd)
             break;
         case ATA_READ_SECTORS_EXT:
             s->fLBA48 = true;
+            /* fall thru */
         case ATA_READ_SECTORS:
         case ATA_READ_SECTORS_WITHOUT_RETRIES:
             if (!s->pDrvMedia || s->fATAPI)
@@ -4087,6 +4090,7 @@ static void ataR3ParseCmd(ATADevState *s, uint8_t cmd)
             break;
         case ATA_WRITE_SECTORS_EXT:
             s->fLBA48 = true;
+            /* fall thru */
         case ATA_WRITE_SECTORS:
         case ATA_WRITE_SECTORS_WITHOUT_RETRIES:
             if (!s->pDrvMedia || s->fATAPI)
@@ -4096,6 +4100,7 @@ static void ataR3ParseCmd(ATADevState *s, uint8_t cmd)
             break;
         case ATA_READ_MULTIPLE_EXT:
             s->fLBA48 = true;
+            /* fall thru */
         case ATA_READ_MULTIPLE:
             if (!s->pDrvMedia || !s->cMultSectors || s->fATAPI)
                 goto abort_cmd;
@@ -4104,6 +4109,7 @@ static void ataR3ParseCmd(ATADevState *s, uint8_t cmd)
             break;
         case ATA_WRITE_MULTIPLE_EXT:
             s->fLBA48 = true;
+            /* fall thru */
         case ATA_WRITE_MULTIPLE:
             if (!s->pDrvMedia || !s->cMultSectors || s->fATAPI)
                 goto abort_cmd;
@@ -4112,6 +4118,7 @@ static void ataR3ParseCmd(ATADevState *s, uint8_t cmd)
             break;
         case ATA_READ_DMA_EXT:
             s->fLBA48 = true;
+            /* fall thru */
         case ATA_READ_DMA:
         case ATA_READ_DMA_WITHOUT_RETRIES:
             if (!s->pDrvMedia || s->fATAPI)
@@ -4122,6 +4129,7 @@ static void ataR3ParseCmd(ATADevState *s, uint8_t cmd)
             break;
         case ATA_WRITE_DMA_EXT:
             s->fLBA48 = true;
+            /* fall thru */
         case ATA_WRITE_DMA:
         case ATA_WRITE_DMA_WITHOUT_RETRIES:
             if (!s->pDrvMedia || s->fATAPI)
diff --git a/src/VBox/Devices/Storage/DevBusLogic.cpp b/src/VBox/Devices/Storage/DevBusLogic.cpp
index 53bc5b0..ae8a3b3 100644
--- a/src/VBox/Devices/Storage/DevBusLogic.cpp
+++ b/src/VBox/Devices/Storage/DevBusLogic.cpp
@@ -4155,7 +4155,9 @@ static DECLCALLBACK(int) buslogicR3Construct(PPDMDEVINS pDevIns, int iInstance,
         char szName[24];
         PBUSLOGICDEVICE pDevice = &pThis->aDeviceStates[i];
 
-        RTStrPrintf(szName, sizeof(szName), "Device%u", i);
+        char *pszName;
+        if (RTStrAPrintf(&pszName, "Device%u", i) < 0)
+            AssertLogRelFailedReturn(VERR_NO_MEMORY);
 
         /* Initialize static parts of the device. */
         pDevice->iLUN = i;
@@ -4169,7 +4171,7 @@ static DECLCALLBACK(int) buslogicR3Construct(PPDMDEVINS pDevIns, int iInstance,
         pDevice->ILed.pfnQueryStatusLed            = buslogicR3DeviceQueryStatusLed;
 
         /* Attach SCSI driver. */
-        rc = PDMDevHlpDriverAttach(pDevIns, pDevice->iLUN, &pDevice->IBase, &pDevice->pDrvBase, szName);
+        rc = PDMDevHlpDriverAttach(pDevIns, pDevice->iLUN, &pDevice->IBase, &pDevice->pDrvBase, pszName);
         if (RT_SUCCESS(rc))
         {
             /* Get SCSI connector interface. */
diff --git a/src/VBox/Devices/Storage/DevLsiLogicSCSI.cpp b/src/VBox/Devices/Storage/DevLsiLogicSCSI.cpp
index 8149bad..38a69cc 100644
--- a/src/VBox/Devices/Storage/DevLsiLogicSCSI.cpp
+++ b/src/VBox/Devices/Storage/DevLsiLogicSCSI.cpp
@@ -1673,6 +1673,7 @@ static int lsilogicRegisterRead(PLSILOGICSCSI pThis, uint32_t offReg, uint32_t *
 #endif
             }
         }
+        /* fall thru */
         case LSILOGIC_REG_DIAG_RW_ADDRESS:
         {
             if (pThis->fDiagRegsEnabled)
@@ -1684,6 +1685,7 @@ static int lsilogicRegisterRead(PLSILOGICSCSI pThis, uint32_t offReg, uint32_t *
 #endif
             }
         }
+        /* fall thru */
         case LSILOGIC_REG_TEST_BASE_ADDRESS: /* The spec doesn't say anything about these registers, so we just ignore them */
         default: /* Ignore. */
         {
@@ -5546,7 +5548,6 @@ static DECLCALLBACK(int) lsilogicR3Construct(PPDMDEVINS pDevIns, int iInstance,
 
     for (unsigned i = 0; i < pThis->cDeviceStates; i++)
     {
-        char szName[24];
         PLSILOGICDEVICE pDevice = &pThis->paDeviceStates[i];
 
         /* Initialize static parts of the device. */
@@ -5558,10 +5559,12 @@ static DECLCALLBACK(int) lsilogicR3Construct(PPDMDEVINS pDevIns, int iInstance,
         pDevice->ISCSIPort.pfnQueryDeviceLocation  = lsilogicR3QueryDeviceLocation;
         pDevice->ILed.pfnQueryStatusLed            = lsilogicR3DeviceQueryStatusLed;
 
-        RTStrPrintf(szName, sizeof(szName), "Device%u", i);
+        char *pszName;
+        if (RTStrAPrintf(&pszName, "Device%u", i) <= 0)
+            AssertLogRelFailedReturn(VERR_NO_MEMORY);
 
         /* Attach SCSI driver. */
-        rc = PDMDevHlpDriverAttach(pDevIns, pDevice->iLUN, &pDevice->IBase, &pDevice->pDrvBase, szName);
+        rc = PDMDevHlpDriverAttach(pDevIns, pDevice->iLUN, &pDevice->IBase, &pDevice->pDrvBase, pszName);
         if (RT_SUCCESS(rc))
         {
             /* Get SCSI connector interface. */
@@ -5572,11 +5575,11 @@ static DECLCALLBACK(int) lsilogicR3Construct(PPDMDEVINS pDevIns, int iInstance,
         {
             pDevice->pDrvBase = NULL;
             rc = VINF_SUCCESS;
-            Log(("LsiLogic: no driver attached to device %s\n", szName));
+            Log(("LsiLogic: no driver attached to device %s\n", pszName));
         }
         else
         {
-            AssertLogRelMsgFailed(("LsiLogic: Failed to attach %s\n", szName));
+            AssertLogRelMsgFailed(("LsiLogic: Failed to attach %s\n", pszName));
             return rc;
         }
     }
diff --git a/src/VBox/Devices/Storage/DrvVD.cpp b/src/VBox/Devices/Storage/DrvVD.cpp
index 7a6f781..0b43ac2 100644
--- a/src/VBox/Devices/Storage/DrvVD.cpp
+++ b/src/VBox/Devices/Storage/DrvVD.cpp
@@ -5168,6 +5168,7 @@ static DECLCALLBACK(int) drvvdConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfg, uint
                 case PDMMEDIATYPE_FLOPPY_FAKE_15_6:
                     if (cbFloppyImg > 255 * 2 * 63 * 512)
                         pThis->enmType = PDMMEDIATYPE_FLOPPY_FAKE_63_5;
+                    /* fall thru */
                 case PDMMEDIATYPE_FLOPPY_FAKE_63_5:
                     if (cbFloppyImg > 255 * 2 * 255 * 512)
                         LogRel(("Warning: Floppy image is larger that 63.5 MB! (%llu bytes)\n", cbFloppyImg));
diff --git a/src/VBox/Devices/Storage/UsbMsd.cpp b/src/VBox/Devices/Storage/UsbMsd.cpp
index da0c021..77f2538 100644
--- a/src/VBox/Devices/Storage/UsbMsd.cpp
+++ b/src/VBox/Devices/Storage/UsbMsd.cpp
@@ -1881,9 +1881,8 @@ static int usbMsdHandleBulkDevToHost(PUSBMSD pThis, PUSBMSDEP pEp, PVUSBURB pUrb
                 Log(("usbMsd: Failed sending SCSI request to driver: %Rrc\n", rc));
                 return usbMsdCompleteStall(pThis, NULL, pUrb, "SCSI Submit #3");
             }
-
-            /* fall thru */
         }
+        /* fall thru */
 
         /*
          * The SCSI command is still pending, queue the URB awaiting its
diff --git a/src/VBox/Devices/Storage/VSCSI/VSCSILunMmc.cpp b/src/VBox/Devices/Storage/VSCSI/VSCSILunMmc.cpp
index 521c237..998ec34 100644
--- a/src/VBox/Devices/Storage/VSCSI/VSCSILunMmc.cpp
+++ b/src/VBox/Devices/Storage/VSCSI/VSCSILunMmc.cpp
@@ -389,6 +389,7 @@ static DECLCALLBACK(int) vscsiLunMmcReqProcess(PVSCSILUNINT pVScsiLun, PVSCSIREQ
                         break;
                     }
                 }
+                /* fall thru */
                 default:
                     rcReq = vscsiLunReqSenseErrorSet(pVScsiLun, pVScsiReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET, 0x00);
             }
@@ -445,6 +446,7 @@ static DECLCALLBACK(int) vscsiLunMmcReqProcess(PVSCSILUNINT pVScsiLun, PVSCSIREQ
             break;
         }
 
+        /* fall thru */
         default:
             //AssertMsgFailed(("Command %#x [%s] not implemented\n", pVScsiReq->pbCDB[0], SCSICmdText(pVScsiReq->pbCDB[0])));
             rcReq = vscsiLunReqSenseErrorSet(pVScsiLun, pVScsiReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_ILLEGAL_OPCODE, 0x00);
diff --git a/src/VBox/Devices/Storage/VSCSI/VSCSILunSbc.cpp b/src/VBox/Devices/Storage/VSCSI/VSCSILunSbc.cpp
index b642be7..c2f4884 100644
--- a/src/VBox/Devices/Storage/VSCSI/VSCSILunSbc.cpp
+++ b/src/VBox/Devices/Storage/VSCSI/VSCSILunSbc.cpp
@@ -447,6 +447,7 @@ static DECLCALLBACK(int) vscsiLunSbcReqProcess(PVSCSILUNINT pVScsiLun, PVSCSIREQ
                         break;
                     }
                 }
+                /* fall thru */
                 default:
                     rcReq = vscsiLunReqSenseErrorSet(pVScsiLun, pVScsiReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET, 0x00);
             }
diff --git a/src/VBox/Devices/USB/USBProxyDevice.cpp b/src/VBox/Devices/USB/USBProxyDevice.cpp
index 706f58c..baf8dc6 100644
--- a/src/VBox/Devices/USB/USBProxyDevice.cpp
+++ b/src/VBox/Devices/USB/USBProxyDevice.cpp
@@ -1058,6 +1058,15 @@ static DECLCALLBACK(int) usbProxyConstruct(PPDMUSBINS pUsbIns, int iInstance, PC
     else
         AssertRCReturn(rc, rc);
 
+    bool fEditAudioSyncEp;
+    rc = CFGMR3QueryBool(pCfg, "EditAudioSyncEp", &fEditAudioSyncEp);
+    if (rc == VERR_CFGM_VALUE_NOT_FOUND)
+        rc = CFGMR3QueryBool(pCfgGlobalDev, "EditAudioSyncEp", &fEditAudioSyncEp);
+    if (rc == VERR_CFGM_VALUE_NOT_FOUND)
+        fEditAudioSyncEp = true;    /* NB: On by default! */
+    else
+        AssertRCReturn(rc, rc);
+
     /*
      * If we're masking interfaces, edit the descriptors.
      */
@@ -1113,6 +1122,48 @@ static DECLCALLBACK(int) usbProxyConstruct(PPDMUSBINS pUsbIns, int iInstance, PC
 
 
     /*
+     * Turn asynchronous audio endpoints into synchronous ones, see @bugref{8769}
+     */
+    if (fEditAudioSyncEp)
+    {
+        PVUSBDESCCONFIGEX paCfgs = pThis->paCfgDescs;
+        for (unsigned iCfg = 0; iCfg < pThis->DevDesc.bNumConfigurations; iCfg++)
+        {
+            PVUSBINTERFACE paIfs = (PVUSBINTERFACE)paCfgs[iCfg].paIfs;
+            for (unsigned iIf = 0; iIf < paCfgs[iCfg].Core.bNumInterfaces; iIf++)
+                for (uint32_t iAlt = 0; iAlt < paIfs[iIf].cSettings; iAlt++)
+                {
+                    /* If not an audio class interface, skip. */
+                    if (paIfs[iIf].paSettings[iAlt].Core.bInterfaceClass != 1)
+                        continue;
+
+                    /* If not a streaming interface, skip. */
+                    if (paIfs[iIf].paSettings[iAlt].Core.bInterfaceSubClass != 2)
+                        continue;
+
+                    PVUSBDESCENDPOINTEX paEps = (PVUSBDESCENDPOINTEX)paIfs[iIf].paSettings[iAlt].paEndpoints;
+                    for (unsigned iEp = 0; iEp < paIfs[iIf].paSettings[iAlt].Core.bNumEndpoints; iEp++)
+                    {
+                        /* isoch/asynch/data*/
+                        if ((paEps[iEp].Core.bmAttributes == 5) && (paEps[iEp].Core.bLength == 9))
+                        {
+                            uint8_t *pbExtra = (uint8_t *)paEps[iEp].pvMore;    /* unconst*/
+                            if (pbExtra[1] == 0)
+                                continue;   /* If bSynchAddress is zero, leave the descriptor alone. */
+
+                            Log(("usb-proxy: pProxyDev=%s async audio with bmAttr=%02X [%02X, %02X] on EP %02X\n",
+                                 pUsbIns->pszName, paEps[iEp].Core.bmAttributes, pbExtra[0], pbExtra[1], paEps[iEp].Core.bEndpointAddress));
+                            paEps[iEp].Core.bmAttributes = 0xD; /* isoch/synch/data*/
+                            pbExtra[1] = 0; /* Clear bSynchAddress. */
+                            fEdited = true;
+                            LogRel(("VUSB: Modified '%s' async audio endpoint 0x%02x\n", pUsbIns->pszName, paEps[iEp].Core.bEndpointAddress));
+                        }
+                    }
+                }
+        }
+    }
+
+    /*
      * Init the PDM/VUSB descriptor cache.
      */
     pThis->DescCache.pDevice = &pThis->DevDesc;
diff --git a/src/VBox/Devices/build/VBoxDD.cpp b/src/VBox/Devices/build/VBoxDD.cpp
index 728a6f6..7131ba4 100644
--- a/src/VBox/Devices/build/VBoxDD.cpp
+++ b/src/VBox/Devices/build/VBoxDD.cpp
@@ -279,6 +279,11 @@ extern "C" DECLEXPORT(int) VBoxDriversRegister(PCPDMDRVREGCB pCallbacks, uint32_
     if (RT_FAILURE(rc))
         return rc;
 #endif
+#ifdef VBOX_WITH_AUDIO_VALIDATIONKIT
+    rc = pCallbacks->pfnRegister(pCallbacks, &g_DrvHostValidationKitAudio);
+    if (RT_FAILURE(rc))
+        return rc;
+#endif
     rc = pCallbacks->pfnRegister(pCallbacks, &g_DrvHostNullAudio);
     if (RT_FAILURE(rc))
         return rc;
diff --git a/src/VBox/Devices/build/VBoxDD.h b/src/VBox/Devices/build/VBoxDD.h
index 4dc0d17..c2e8dee 100644
--- a/src/VBox/Devices/build/VBoxDD.h
+++ b/src/VBox/Devices/build/VBoxDD.h
@@ -122,6 +122,9 @@ extern const PDMDRVREG g_DrvAUDIO;
 #ifdef VBOX_WITH_AUDIO_DEBUG
 extern const PDMDRVREG g_DrvHostDebugAudio;
 #endif
+#ifdef VBOX_WITH_AUDIO_VALIDATIONKIT
+extern const PDMDRVREG g_DrvHostValidationKitAudio;
+#endif
 extern const PDMDRVREG g_DrvHostNullAudio;
 #if defined(RT_OS_WINDOWS)
 extern const PDMDRVREG g_DrvHostDSound;
diff --git a/src/VBox/Devices/testcase/tstDeviceStructSizeRC.cpp b/src/VBox/Devices/testcase/tstDeviceStructSizeRC.cpp
index 4e0e34b..d3617e2 100644
--- a/src/VBox/Devices/testcase/tstDeviceStructSizeRC.cpp
+++ b/src/VBox/Devices/testcase/tstDeviceStructSizeRC.cpp
@@ -7,7 +7,7 @@
  */
 
 /*
- * Copyright (C) 2006-2016 Oracle Corporation
+ * Copyright (C) 2006-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;
@@ -1914,7 +1914,7 @@ int main()
     GEN_CHECK_SIZE(AC97DRIVER);
     GEN_CHECK_OFF(AC97DRIVER, Node);
     GEN_CHECK_OFF(AC97DRIVER, pAC97State);
-    GEN_CHECK_OFF(AC97DRIVER, Flags);
+    GEN_CHECK_OFF(AC97DRIVER, fFlags);
     GEN_CHECK_OFF(AC97DRIVER, uLUN);
     GEN_CHECK_OFF(AC97DRIVER, fAttached);
     GEN_CHECK_OFF(AC97DRIVER, pConnector);
@@ -1933,7 +1933,7 @@ int main()
     GEN_CHECK_SIZE(HDADRIVER);
     GEN_CHECK_OFF(HDADRIVER, Node);
     GEN_CHECK_OFF(HDADRIVER, pHDAState);
-    GEN_CHECK_OFF(HDADRIVER, Flags);
+    GEN_CHECK_OFF(HDADRIVER, fFlags);
     GEN_CHECK_OFF(HDADRIVER, uLUN);
     GEN_CHECK_OFF(HDADRIVER, fAttached);
     GEN_CHECK_OFF(HDADRIVER, pConnector);
@@ -1946,23 +1946,26 @@ int main()
     GEN_CHECK_SIZE(HDABDLESTATE);
     GEN_CHECK_OFF(HDABDLESTATE, u32BDLIndex);
     GEN_CHECK_OFF(HDABDLESTATE, cbBelowFIFOW);
-    GEN_CHECK_OFF(HDABDLESTATE, au8FIFO);
     GEN_CHECK_OFF(HDABDLESTATE, u32BufOff);
 
+    GEN_CHECK_SIZE(HDABDLEDESC);
+    GEN_CHECK_OFF(HDABDLEDESC, u64BufAdr);
+    GEN_CHECK_OFF(HDABDLEDESC, u32BufSize);
+    GEN_CHECK_OFF(HDABDLEDESC, fFlags);
+
     GEN_CHECK_SIZE(HDABDLE);
-    GEN_CHECK_OFF(HDABDLE, u64BufAdr);
-    GEN_CHECK_OFF(HDABDLE, u32BufSize);
-    GEN_CHECK_OFF(HDABDLE, fIntOnCompletion);
+    GEN_CHECK_OFF(HDABDLE, Desc);
     GEN_CHECK_OFF(HDABDLE, State);
 
+    GEN_CHECK_SIZE(HDASTREAMPERIOD);
+
     GEN_CHECK_SIZE(HDASTREAMSTATE);
     GEN_CHECK_OFF(HDASTREAMSTATE, uCurBDLE);
     GEN_CHECK_OFF(HDASTREAMSTATE, BDLE);
 
     GEN_CHECK_SIZE(HDASTREAM);
-    GEN_CHECK_OFF(HDASTREAM, u8Strm);
+    GEN_CHECK_OFF(HDASTREAM, u8SD);
     GEN_CHECK_OFF(HDASTREAM, u64BDLBase);
-    GEN_CHECK_OFF(HDASTREAM, u16FMT);
     GEN_CHECK_OFF(HDASTREAM, u16FIFOS);
     GEN_CHECK_OFF(HDASTREAM, u16LVI);
     GEN_CHECK_OFF(HDASTREAM, State);
@@ -1976,9 +1979,9 @@ int main()
     GEN_CHECK_OFF(HDASTATE, MMIOBaseAddr);
     GEN_CHECK_OFF(HDASTATE, au32Regs[0]);
     GEN_CHECK_OFF(HDASTATE, au32Regs[HDA_NREGS]);
-    GEN_CHECK_OFF(HDASTATE, StrmStLineIn);
-    GEN_CHECK_OFF(HDASTATE, StrmStOut);
-    GEN_CHECK_OFF(HDASTATE, StrmStMicIn);
+    GEN_CHECK_OFF(HDASTATE, LineIn);
+    GEN_CHECK_OFF(HDASTATE, Out);
+    GEN_CHECK_OFF(HDASTATE, MicIn);
     GEN_CHECK_OFF(HDASTATE, u64CORBBase);
     GEN_CHECK_OFF(HDASTATE, u64RIRBBase);
     GEN_CHECK_OFF(HDASTATE, u64DPBase);
@@ -1992,7 +1995,6 @@ int main()
 #ifndef VBOX_WITH_AUDIO_CALLBACKS
     GEN_CHECK_OFF(HDASTATE, pTimer);
     GEN_CHECK_OFF(HDASTATE, cTimerTicks);
-    GEN_CHECK_OFF(HDASTATE, uTimerTS);
 #endif
 #ifdef VBOX_WITH_STATISTICS
 # ifndef VBOX_WITH_AUDIO_CALLBACKS
@@ -2008,8 +2010,9 @@ int main()
 #ifdef VBOX_WITH_HDA_MIC_IN
     GEN_CHECK_OFF(HDASTATE, pSinkMicIn);
 #endif
-    GEN_CHECK_OFF(HDASTATE, u64BaseTS);
+    GEN_CHECK_OFF(HDASTATE, u64WalClk);
     GEN_CHECK_OFF(HDASTATE, u8RespIntCnt);
+    GEN_CHECK_OFF(HDASTATE, u8IRQL);
 
 #ifdef VBOX_WITH_NVME_IMPL
     GEN_CHECK_SIZE(NVMEQUEUEHDR);
diff --git a/src/VBox/Disassembler/DisasmCore.cpp b/src/VBox/Disassembler/DisasmCore.cpp
index d5adb89..c42f17d 100644
--- a/src/VBox/Disassembler/DisasmCore.cpp
+++ b/src/VBox/Disassembler/DisasmCore.cpp
@@ -976,7 +976,7 @@ static size_t UseModRM(size_t const offInstr, PCDISOPCODE pOp, PDISSTATE pDis, P
                 if (mod != 3)
                     break;  /* memory operand */
                 reg = rm; /* the RM field specifies the xmm register */
-                /* else no break */
+                /* fall thru */
 
             case OP_PARM_P: //MMX register
                 reg &= 7;   /* REX.R has no effect here */
@@ -999,9 +999,11 @@ static size_t UseModRM(size_t const offInstr, PCDISOPCODE pOp, PDISSTATE pDis, P
             case OP_PARM_W: //XMM register or memory operand
                 if (mod != 3)
                     break;  /* memory operand */
+                /* fall thru */
+
             case OP_PARM_U: // XMM/YMM register
                 reg = rm; /* the RM field specifies the xmm register */
-                /* else no break */
+                /* fall thru */
 
             case OP_PARM_V: //XMM register
                 if (VEXREG_IS256B(pDis->bVexDestReg)
diff --git a/src/VBox/Disassembler/DisasmFormatYasm.cpp b/src/VBox/Disassembler/DisasmFormatYasm.cpp
index 818498a..f91d710 100644
--- a/src/VBox/Disassembler/DisasmFormatYasm.cpp
+++ b/src/VBox/Disassembler/DisasmFormatYasm.cpp
@@ -710,6 +710,7 @@ DISDECL(size_t) DISFormatYasmEx(PCDISSTATE pDis, char *pszBuf, size_t cchBuf, ui
                             case DISCPUMODE_16BIT: if (OP_PARM_VSUBTYPE(pParam->fParam) != OP_PARM_y) PUT_SZ("word "); break; \
                             case DISCPUMODE_32BIT: \
                                 if (pDis->pCurInstr->uOpcode != OP_GATHER || pDis->bVexWFlag) { PUT_SZ("dword "); break; } \
+                                /* fall thru */ \
                             case DISCPUMODE_64BIT: PUT_SZ("qword "); break; \
                             default: break; \
                         } \
@@ -741,7 +742,7 @@ DISDECL(size_t) DISFormatYasmEx(PCDISSTATE pDis, char *pszBuf, size_t cchBuf, ui
                        break; \
                     case OP_PARM_ps: \
                     case OP_PARM_pd: \
-                    case OP_PARM_x: if (VEXREG_IS256B(pDis->bVexDestReg)) { PUT_SZ("yword "); break; } \
+                    case OP_PARM_x: if (VEXREG_IS256B(pDis->bVexDestReg)) { PUT_SZ("yword "); break; } /* fall thru */ \
                     case OP_PARM_ss: \
                     case OP_PARM_sd: \
                     case OP_PARM_dq: PUT_SZ("oword "); break; \
diff --git a/src/VBox/ExtPacks/VBoxDTrace/onnv/cmd/dtrace/demo/mkdemo.pl b/src/VBox/ExtPacks/VBoxDTrace/onnv/cmd/dtrace/demo/mkdemo.pl
old mode 100644
new mode 100755
diff --git a/src/VBox/ExtPacks/VBoxDTrace/onnv/cmd/dtrace/test/tst/common/ip/tst.ipv4localtcp.ksh b/src/VBox/ExtPacks/VBoxDTrace/onnv/cmd/dtrace/test/tst/common/ip/tst.ipv4localtcp.ksh
old mode 100644
new mode 100755
diff --git a/src/VBox/ExtPacks/VBoxDTrace/onnv/cmd/dtrace/test/tst/common/ip/tst.ipv4localudp.ksh b/src/VBox/ExtPacks/VBoxDTrace/onnv/cmd/dtrace/test/tst/common/ip/tst.ipv4localudp.ksh
old mode 100644
new mode 100755
diff --git a/src/VBox/ExtPacks/VBoxDTrace/onnv/cmd/dtrace/test/tst/common/ip/tst.ipv4remotetcp.ksh b/src/VBox/ExtPacks/VBoxDTrace/onnv/cmd/dtrace/test/tst/common/ip/tst.ipv4remotetcp.ksh
old mode 100644
new mode 100755
diff --git a/src/VBox/ExtPacks/VBoxDTrace/onnv/cmd/dtrace/test/tst/common/ip/tst.ipv4remoteudp.ksh b/src/VBox/ExtPacks/VBoxDTrace/onnv/cmd/dtrace/test/tst/common/ip/tst.ipv4remoteudp.ksh
old mode 100644
new mode 100755
diff --git a/src/VBox/ExtPacks/VBoxDTrace/onnv/cmd/dtrace/test/tst/common/ip/tst.localtcpstate.ksh b/src/VBox/ExtPacks/VBoxDTrace/onnv/cmd/dtrace/test/tst/common/ip/tst.localtcpstate.ksh
old mode 100644
new mode 100755
diff --git a/src/VBox/ExtPacks/VBoxDTrace/onnv/cmd/dtrace/test/tst/common/ip/tst.remotetcpstate.ksh b/src/VBox/ExtPacks/VBoxDTrace/onnv/cmd/dtrace/test/tst/common/ip/tst.remotetcpstate.ksh
old mode 100644
new mode 100755
diff --git a/src/VBox/ExtPacks/VBoxDTrace/onnv/cmd/dtrace/test/tst/common/scripting/err.D_MACRO_UNDEF.invalidargs.d b/src/VBox/ExtPacks/VBoxDTrace/onnv/cmd/dtrace/test/tst/common/scripting/err.D_MACRO_UNDEF.invalidargs.d
old mode 100644
new mode 100755
diff --git a/src/VBox/ExtPacks/VBoxDTrace/onnv/cmd/dtrace/test/tst/common/scripting/err.D_OP_LVAL.rdonly.d b/src/VBox/ExtPacks/VBoxDTrace/onnv/cmd/dtrace/test/tst/common/scripting/err.D_OP_LVAL.rdonly.d
old mode 100644
new mode 100755
diff --git a/src/VBox/ExtPacks/VBoxDTrace/onnv/cmd/dtrace/test/tst/common/scripting/err.D_OP_WRITE.usepidmacro.d b/src/VBox/ExtPacks/VBoxDTrace/onnv/cmd/dtrace/test/tst/common/scripting/err.D_OP_WRITE.usepidmacro.d
old mode 100644
new mode 100755
diff --git a/src/VBox/ExtPacks/VBoxDTrace/onnv/cmd/dtrace/test/tst/common/scripting/err.D_SYNTAX.inval.d b/src/VBox/ExtPacks/VBoxDTrace/onnv/cmd/dtrace/test/tst/common/scripting/err.D_SYNTAX.inval.d
old mode 100644
new mode 100755
diff --git a/src/VBox/ExtPacks/VBoxDTrace/onnv/cmd/dtrace/test/tst/common/scripting/err.D_SYNTAX.pid.d b/src/VBox/ExtPacks/VBoxDTrace/onnv/cmd/dtrace/test/tst/common/scripting/err.D_SYNTAX.pid.d
old mode 100644
new mode 100755
diff --git a/src/VBox/ExtPacks/VBoxDTrace/onnv/cmd/dtrace/test/tst/common/scripting/tst.arg0.d b/src/VBox/ExtPacks/VBoxDTrace/onnv/cmd/dtrace/test/tst/common/scripting/tst.arg0.d
old mode 100644
new mode 100755
diff --git a/src/VBox/ExtPacks/VBoxDTrace/onnv/cmd/dtrace/test/tst/common/scripting/tst.assign.d b/src/VBox/ExtPacks/VBoxDTrace/onnv/cmd/dtrace/test/tst/common/scripting/tst.assign.d
old mode 100644
new mode 100755
diff --git a/src/VBox/ExtPacks/VBoxDTrace/onnv/cmd/dtrace/test/tst/common/scripting/tst.basic.d b/src/VBox/ExtPacks/VBoxDTrace/onnv/cmd/dtrace/test/tst/common/scripting/tst.basic.d
old mode 100644
new mode 100755
diff --git a/src/VBox/ExtPacks/VBoxDTrace/onnv/cmd/dtrace/test/tst/common/scripting/tst.egid.d b/src/VBox/ExtPacks/VBoxDTrace/onnv/cmd/dtrace/test/tst/common/scripting/tst.egid.d
old mode 100644
new mode 100755
diff --git a/src/VBox/ExtPacks/VBoxDTrace/onnv/cmd/dtrace/test/tst/common/scripting/tst.euid.d b/src/VBox/ExtPacks/VBoxDTrace/onnv/cmd/dtrace/test/tst/common/scripting/tst.euid.d
old mode 100644
new mode 100755
diff --git a/src/VBox/ExtPacks/VBoxDTrace/onnv/cmd/dtrace/test/tst/common/scripting/tst.gid.d b/src/VBox/ExtPacks/VBoxDTrace/onnv/cmd/dtrace/test/tst/common/scripting/tst.gid.d
old mode 100644
new mode 100755
diff --git a/src/VBox/ExtPacks/VBoxDTrace/onnv/cmd/dtrace/test/tst/common/scripting/tst.pgid.d b/src/VBox/ExtPacks/VBoxDTrace/onnv/cmd/dtrace/test/tst/common/scripting/tst.pgid.d
old mode 100644
new mode 100755
diff --git a/src/VBox/ExtPacks/VBoxDTrace/onnv/cmd/dtrace/test/tst/common/scripting/tst.pid.d b/src/VBox/ExtPacks/VBoxDTrace/onnv/cmd/dtrace/test/tst/common/scripting/tst.pid.d
old mode 100644
new mode 100755
diff --git a/src/VBox/ExtPacks/VBoxDTrace/onnv/cmd/dtrace/test/tst/common/scripting/tst.ppid.d b/src/VBox/ExtPacks/VBoxDTrace/onnv/cmd/dtrace/test/tst/common/scripting/tst.ppid.d
old mode 100644
new mode 100755
diff --git a/src/VBox/ExtPacks/VBoxDTrace/onnv/cmd/dtrace/test/tst/common/scripting/tst.projid.d b/src/VBox/ExtPacks/VBoxDTrace/onnv/cmd/dtrace/test/tst/common/scripting/tst.projid.d
old mode 100644
new mode 100755
diff --git a/src/VBox/ExtPacks/VBoxDTrace/onnv/cmd/dtrace/test/tst/common/scripting/tst.quite.d b/src/VBox/ExtPacks/VBoxDTrace/onnv/cmd/dtrace/test/tst/common/scripting/tst.quite.d
old mode 100644
new mode 100755
diff --git a/src/VBox/ExtPacks/VBoxDTrace/onnv/cmd/dtrace/test/tst/common/scripting/tst.sid.d b/src/VBox/ExtPacks/VBoxDTrace/onnv/cmd/dtrace/test/tst/common/scripting/tst.sid.d
old mode 100644
new mode 100755
diff --git a/src/VBox/ExtPacks/VBoxDTrace/onnv/cmd/dtrace/test/tst/common/scripting/tst.taskid.d b/src/VBox/ExtPacks/VBoxDTrace/onnv/cmd/dtrace/test/tst/common/scripting/tst.taskid.d
old mode 100644
new mode 100755
diff --git a/src/VBox/ExtPacks/VBoxDTrace/onnv/cmd/dtrace/test/tst/common/scripting/tst.trace.d b/src/VBox/ExtPacks/VBoxDTrace/onnv/cmd/dtrace/test/tst/common/scripting/tst.trace.d
old mode 100644
new mode 100755
diff --git a/src/VBox/ExtPacks/VBoxDTrace/onnv/cmd/dtrace/test/tst/common/scripting/tst.uid.d b/src/VBox/ExtPacks/VBoxDTrace/onnv/cmd/dtrace/test/tst/common/scripting/tst.uid.d
old mode 100644
new mode 100755
diff --git a/src/VBox/ExtPacks/VBoxDTrace/onnv/cmd/dtrace/test/tst/common/speculation/err.D_ACT_SPEC.SpeculateWithBreakPoint.d b/src/VBox/ExtPacks/VBoxDTrace/onnv/cmd/dtrace/test/tst/common/speculation/err.D_ACT_SPEC.SpeculateWithBreakPoint.d
old mode 100644
new mode 100755
diff --git a/src/VBox/ExtPacks/VBoxDTrace/onnv/cmd/dtrace/test/tst/common/speculation/err.D_ACT_SPEC.SpeculateWithChill.d b/src/VBox/ExtPacks/VBoxDTrace/onnv/cmd/dtrace/test/tst/common/speculation/err.D_ACT_SPEC.SpeculateWithChill.d
old mode 100644
new mode 100755
diff --git a/src/VBox/ExtPacks/VBoxDTrace/onnv/cmd/dtrace/test/tst/common/speculation/err.D_ACT_SPEC.SpeculateWithCopyOut.d b/src/VBox/ExtPacks/VBoxDTrace/onnv/cmd/dtrace/test/tst/common/speculation/err.D_ACT_SPEC.SpeculateWithCopyOut.d
old mode 100644
new mode 100755
diff --git a/src/VBox/ExtPacks/VBoxDTrace/onnv/cmd/dtrace/test/tst/common/speculation/err.D_ACT_SPEC.SpeculateWithCopyOutStr.d b/src/VBox/ExtPacks/VBoxDTrace/onnv/cmd/dtrace/test/tst/common/speculation/err.D_ACT_SPEC.SpeculateWithCopyOutStr.d
old mode 100644
new mode 100755
diff --git a/src/VBox/ExtPacks/VBoxDTrace/onnv/cmd/dtrace/test/tst/common/speculation/err.D_ACT_SPEC.SpeculateWithPanic.d b/src/VBox/ExtPacks/VBoxDTrace/onnv/cmd/dtrace/test/tst/common/speculation/err.D_ACT_SPEC.SpeculateWithPanic.d
old mode 100644
new mode 100755
diff --git a/src/VBox/ExtPacks/VBoxDTrace/onnv/cmd/dtrace/test/tst/common/speculation/err.D_ACT_SPEC.SpeculateWithRaise.d b/src/VBox/ExtPacks/VBoxDTrace/onnv/cmd/dtrace/test/tst/common/speculation/err.D_ACT_SPEC.SpeculateWithRaise.d
old mode 100644
new mode 100755
diff --git a/src/VBox/ExtPacks/VBoxDTrace/onnv/cmd/dtrace/test/tst/common/speculation/err.D_ACT_SPEC.SpeculateWithStop.d b/src/VBox/ExtPacks/VBoxDTrace/onnv/cmd/dtrace/test/tst/common/speculation/err.D_ACT_SPEC.SpeculateWithStop.d
old mode 100644
new mode 100755
diff --git a/src/VBox/ExtPacks/VBoxDTrace/onnv/cmd/dtrace/test/tst/common/usdt/tst.corruptenv.ksh b/src/VBox/ExtPacks/VBoxDTrace/onnv/cmd/dtrace/test/tst/common/usdt/tst.corruptenv.ksh
old mode 100644
new mode 100755
diff --git a/src/VBox/ExtPacks/VBoxDTrace/onnv/lib/libdtrace/common/mkerrtags.sh b/src/VBox/ExtPacks/VBoxDTrace/onnv/lib/libdtrace/common/mkerrtags.sh
old mode 100644
new mode 100755
diff --git a/src/VBox/Frontends/VBoxManage/VBoxManageControlVM.cpp b/src/VBox/Frontends/VBoxManage/VBoxManageControlVM.cpp
index 68750f7..ef6dea8 100644
--- a/src/VBox/Frontends/VBoxManage/VBoxManageControlVM.cpp
+++ b/src/VBox/Frontends/VBoxManage/VBoxManageControlVM.cpp
@@ -1476,7 +1476,7 @@ RTEXITCODE handleControlVM(HandlerArg *a)
                 break;
             }
 
-            CHECK_ERROR_BREAK(sessionMachine, COMSETTER(VideoCaptureFile)(Bstr(a->argv[3]).raw()));
+            CHECK_ERROR_BREAK(sessionMachine, COMSETTER(VideoCaptureFile)(Bstr(a->argv[2]).raw()));
         }
         else if (!strcmp(a->argv[1], "videocapres"))
         {
diff --git a/src/VBox/Frontends/VBoxManage/VBoxManageDisk.cpp b/src/VBox/Frontends/VBoxManage/VBoxManageDisk.cpp
index 03a6b21..caad2db 100644
--- a/src/VBox/Frontends/VBoxManage/VBoxManageDisk.cpp
+++ b/src/VBox/Frontends/VBoxManage/VBoxManageDisk.cpp
@@ -506,7 +506,7 @@ RTEXITCODE handleModifyMedium(HandlerArg *a)
     bool fModifyLocation = false;
     uint64_t cbResize = 0;
     const char *pszFilenameOrUuid = NULL;
-    const char *pszNewLocation = NULL;
+    char *pszNewLocation = NULL;
 
     int c;
     RTGETOPTUNION ValueUnion;
@@ -599,7 +599,7 @@ RTEXITCODE handleModifyMedium(HandlerArg *a)
 
             case 'm':   // --move
                 /* Get a new location  */
-                pszNewLocation = RTStrDup(ValueUnion.psz);
+                pszNewLocation = RTPathAbsDup(ValueUnion.psz);
                 fModifyLocation = true;
                 break;
 
@@ -745,7 +745,8 @@ RTEXITCODE handleModifyMedium(HandlerArg *a)
         {
             ComPtr<IProgress> pProgress;
             Utf8Str strLocation(pszNewLocation);
-            CHECK_ERROR(pMedium, SetLocation(Bstr(pszNewLocation).raw(), pProgress.asOutParam()));
+            RTStrFree(pszNewLocation);
+            CHECK_ERROR(pMedium, SetLocation(Bstr(strLocation).raw(), pProgress.asOutParam()));
 
             if (SUCCEEDED(rc) && !pProgress.isNull())
             {
diff --git a/src/VBox/Frontends/VBoxManage/VBoxManageHelp.cpp b/src/VBox/Frontends/VBoxManage/VBoxManageHelp.cpp
index 061a430..93dce86 100644
--- a/src/VBox/Frontends/VBoxManage/VBoxManageHelp.cpp
+++ b/src/VBox/Frontends/VBoxManage/VBoxManageHelp.cpp
@@ -1131,7 +1131,7 @@ void printUsage(USAGECATEGORY fCategory, uint32_t fSubCategory, PRTSTREAM pStrm)
                      "                            [--property <name=[value]>]\n"
                      "                            [--compact]\n"
                      "                            [--resize <megabytes>|--resizebyte <bytes>]\n"
-                     "                            [--move <full path to a new location>]"
+                     "                            [--move <path>]"
                      "\n", SEP);
 
     if (fCategory & USAGE_CLONEMEDIUM)
diff --git a/src/VBox/Frontends/VBoxManage/VBoxManageModifyVM.cpp b/src/VBox/Frontends/VBoxManage/VBoxManageModifyVM.cpp
index b4d8459..314149a 100644
--- a/src/VBox/Frontends/VBoxManage/VBoxManageModifyVM.cpp
+++ b/src/VBox/Frontends/VBoxManage/VBoxManageModifyVM.cpp
@@ -2427,6 +2427,7 @@ RTEXITCODE handleModifyVM(HandlerArg *a)
 
             case MODIFYVM_VRDPPORT:
                 vrdeWarningDeprecatedOption("port");
+                /* fall thru */
 
             case MODIFYVM_VRDEPORT:
             {
@@ -2443,6 +2444,7 @@ RTEXITCODE handleModifyVM(HandlerArg *a)
 
             case MODIFYVM_VRDPADDRESS:
                 vrdeWarningDeprecatedOption("address");
+                /* fall thru */
 
             case MODIFYVM_VRDEADDRESS:
             {
@@ -2456,6 +2458,7 @@ RTEXITCODE handleModifyVM(HandlerArg *a)
 
             case MODIFYVM_VRDPAUTHTYPE:
                 vrdeWarningDeprecatedOption("authtype");
+                /* fall thru */
             case MODIFYVM_VRDEAUTHTYPE:
             {
                 ComPtr<IVRDEServer> vrdeServer;
@@ -2503,6 +2506,7 @@ RTEXITCODE handleModifyVM(HandlerArg *a)
 
             case MODIFYVM_VRDPMULTICON:
                 vrdeWarningDeprecatedOption("multicon");
+                /* fall thru */
             case MODIFYVM_VRDEMULTICON:
             {
                 ComPtr<IVRDEServer> vrdeServer;
@@ -2515,6 +2519,7 @@ RTEXITCODE handleModifyVM(HandlerArg *a)
 
             case MODIFYVM_VRDPREUSECON:
                 vrdeWarningDeprecatedOption("reusecon");
+                /* fall thru */
             case MODIFYVM_VRDEREUSECON:
             {
                 ComPtr<IVRDEServer> vrdeServer;
@@ -2527,6 +2532,7 @@ RTEXITCODE handleModifyVM(HandlerArg *a)
 
             case MODIFYVM_VRDPVIDEOCHANNEL:
                 vrdeWarningDeprecatedOption("videochannel");
+                /* fall thru */
             case MODIFYVM_VRDEVIDEOCHANNEL:
             {
                 ComPtr<IVRDEServer> vrdeServer;
@@ -2540,6 +2546,7 @@ RTEXITCODE handleModifyVM(HandlerArg *a)
 
             case MODIFYVM_VRDPVIDEOCHANNELQUALITY:
                 vrdeWarningDeprecatedOption("videochannelquality");
+                /* fall thru */
             case MODIFYVM_VRDEVIDEOCHANNELQUALITY:
             {
                 ComPtr<IVRDEServer> vrdeServer;
@@ -2553,6 +2560,7 @@ RTEXITCODE handleModifyVM(HandlerArg *a)
 
             case MODIFYVM_VRDP:
                 vrdeWarningDeprecatedOption("");
+                /* fall thru */
             case MODIFYVM_VRDE:
             {
                 ComPtr<IVRDEServer> vrdeServer;
diff --git a/src/VBox/Frontends/VBoxSDL/VBoxSDL.cpp b/src/VBox/Frontends/VBoxSDL/VBoxSDL.cpp
index e972c74..e0d98d6 100644
--- a/src/VBox/Frontends/VBoxSDL/VBoxSDL.cpp
+++ b/src/VBox/Frontends/VBoxSDL/VBoxSDL.cpp
@@ -2561,8 +2561,8 @@ DECLEXPORT(int) TrustedMain(int argc, char **argv, char **envp)
                             ProcessKey(&event.key);
                             break;
                         }
-                        /* fall through if no two-key sequence is used */
                     }
+                    /* fall through */
 
                     case HKEYSTATE_DOWN:
                     {
diff --git a/src/VBox/Frontends/VirtualBox/nls/VirtualBox_bg.ts b/src/VBox/Frontends/VirtualBox/nls/VirtualBox_bg.ts
index ed61acd..7e2e2ba 100644
--- a/src/VBox/Frontends/VirtualBox/nls/VirtualBox_bg.ts
+++ b/src/VBox/Frontends/VirtualBox/nls/VirtualBox_bg.ts
@@ -4294,7 +4294,7 @@ p, li { white-space: pre-wrap; </style></head><body style="
         <translation>IPv6 адрес</translation>
     </message>
     <message>
-        <source>IPv6 Network Mask Length</source>
+        <source>IPv6 Prefix Length</source>
         <translation>Дължина на IPv6 мрежовата маска</translation>
     </message>
     <message>
@@ -4548,7 +4548,7 @@ p, li { white-space: pre-wrap; </style></head><body style="
         <translation>Редактира избраната само-хост мрежа.</translation>
     </message>
     <message>
-        <source>Host interface <b>%1</b> does not currently have a valid IPv6 network mask prefix length.</source>
+        <source>Host interface <b>%1</b> does not currently have a valid IPv6 prefix length.</source>
         <translation>Реалният интерфейс <b>%1</b> текущо няма валидна дължина на префикса на IPv6 мрежова маска.</translation>
     </message>
 </context>
@@ -4595,11 +4595,11 @@ p, li { white-space: pre-wrap; </style></head><body style="
         <translation type="obsolete">Показва IPv6 адреса на хоста за този адаптер, ако се поддържа IPv6.</translation>
     </message>
     <message>
-        <source>IPv6 Network Mask &Length:</source>
+        <source>IPv6 Prefix &Length:</source>
         <translation type="obsolete">&Дължина на IPv6 мрежовата маска:</translation>
     </message>
     <message>
-        <source>Holds the host IPv6 network mask prefix length for this adapter if IPv6 is supported.</source>
+        <source>Holds the host IPv6 prefix length for this adapter if IPv6 is supported.</source>
         <translation type="obsolete">Показва префиксната дължина на IPv6 мрежовата маска на хоста за този адаптер, ако се поддържа IPv6.</translation>
     </message>
     <message>
@@ -4690,11 +4690,11 @@ p, li { white-space: pre-wrap; </style></head><body style="
         <translation>Задава IPv6 адреса на хоста за този адаптер, ако се поддържа IPv6.</translation>
     </message>
     <message>
-        <source>IPv6 Network Mask &Length:</source>
+        <source>IPv6 Prefix &Length:</source>
         <translation>&Дължина на IPv6 мрежовата маска:</translation>
     </message>
     <message>
-        <source>Holds the host IPv6 network mask prefix length for this adapter if IPv6 is supported.</source>
+        <source>Holds the host IPv6 prefix length for this adapter if IPv6 is supported.</source>
         <translation>Задава префиксната дължина на IPv6 мрежовата маска на хоста за този адаптер, ако се поддържа IPv6.</translation>
     </message>
     <message>
diff --git a/src/VBox/Frontends/VirtualBox/nls/VirtualBox_ca.ts b/src/VBox/Frontends/VirtualBox/nls/VirtualBox_ca.ts
index 163dbdd..25be051 100644
--- a/src/VBox/Frontends/VirtualBox/nls/VirtualBox_ca.ts
+++ b/src/VBox/Frontends/VirtualBox/nls/VirtualBox_ca.ts
@@ -2038,7 +2038,7 @@
         <translation>Adreça IPv6</translation>
     </message>
     <message>
-        <source>IPv6 Network Mask Length</source>
+        <source>IPv6 Prefix Length</source>
         <translation>Mida de la màscara de xarxa IPv6</translation>
     </message>
     <message>
@@ -2255,7 +2255,7 @@
         <translation>Edita la xarxa de només amfitrió seleccionada.</translation>
     </message>
     <message>
-        <source>Host interface <b>%1</b> does not currently have a valid IPv6 network mask prefix length.</source>
+        <source>Host interface <b>%1</b> does not currently have a valid IPv6 prefix length.</source>
         <translation type="unfinished"></translation>
     </message>
 </context>
@@ -2298,11 +2298,11 @@
         <translation>Gestiona l'adreça IPv6 de l'amfitrió d'aquest adaptador si IPv6 està suportat.</translation>
     </message>
     <message>
-        <source>IPv6 Network Mask &Length:</source>
+        <source>IPv6 Prefix &Length:</source>
         <translation>&Longitud de la màscara de xarxa IPv6:</translation>
     </message>
     <message>
-        <source>Holds the host IPv6 network mask prefix length for this adapter if IPv6 is supported.</source>
+        <source>Holds the host IPv6 prefix length for this adapter if IPv6 is supported.</source>
         <translation>Gestiona la longitud de l'adreça de la màscara de xarxa IPv6 de l'amfitrió per a aquest adaptador si IPv6 està suportat.</translation>
     </message>
     <message>
diff --git a/src/VBox/Frontends/VirtualBox/nls/VirtualBox_ca_VA.ts b/src/VBox/Frontends/VirtualBox/nls/VirtualBox_ca_VA.ts
index b3d6912..48d1233 100644
--- a/src/VBox/Frontends/VirtualBox/nls/VirtualBox_ca_VA.ts
+++ b/src/VBox/Frontends/VirtualBox/nls/VirtualBox_ca_VA.ts
@@ -4239,7 +4239,7 @@ p, li { white-space: pre-wrap; }
         <translation>Adreça IPv6</translation>
     </message>
     <message>
-        <source>IPv6 Network Mask Length</source>
+        <source>IPv6 Prefix Length</source>
         <translation>Mida de la màscara de xarxa IPv6</translation>
     </message>
     <message>
@@ -4493,7 +4493,7 @@ p, li { white-space: pre-wrap; }
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <source>Host interface <b>%1</b> does not currently have a valid IPv6 network mask prefix length.</source>
+        <source>Host interface <b>%1</b> does not currently have a valid IPv6 prefix length.</source>
         <translation type="unfinished"></translation>
     </message>
 </context>
@@ -4540,11 +4540,11 @@ p, li { white-space: pre-wrap; }
         <translation type="obsolete">Mostra l'adreça IPv6 de l'amfitrió d'este adaptador si IPv6 està suportat.</translation>
     </message>
     <message>
-        <source>IPv6 Network Mask &Length:</source>
+        <source>IPv6 Prefix &Length:</source>
         <translation type="obsolete">&Longitud de la màscara de xarxa IPv6:</translation>
     </message>
     <message>
-        <source>Holds the host IPv6 network mask prefix length for this adapter if IPv6 is supported.</source>
+        <source>Holds the host IPv6 prefix length for this adapter if IPv6 is supported.</source>
         <translation type="obsolete">Mostra la longitud de l'adreça de la màscara de xarxa IPv6 de l'amfitrió per a este adaptador si IPv6 està suportat.</translation>
     </message>
     <message>
@@ -4635,11 +4635,11 @@ p, li { white-space: pre-wrap; }
         <translation>Gestiona l'adreça IPv6 de l'amfitrió d'este adaptador si IPv6 està suportat.</translation>
     </message>
     <message>
-        <source>IPv6 Network Mask &Length:</source>
+        <source>IPv6 Prefix &Length:</source>
         <translation>&Longitud de la màscara de xarxa IPv6:</translation>
     </message>
     <message>
-        <source>Holds the host IPv6 network mask prefix length for this adapter if IPv6 is supported.</source>
+        <source>Holds the host IPv6 prefix length for this adapter if IPv6 is supported.</source>
         <translation>Gestiona la longitud de l'adreça de la màscara de xarxa IPv6 de l'amfitrió per a este adaptador si IPv6 està suportat.</translation>
     </message>
     <message>
diff --git a/src/VBox/Frontends/VirtualBox/nls/VirtualBox_cs.ts b/src/VBox/Frontends/VirtualBox/nls/VirtualBox_cs.ts
index a0c2752..a647086 100644
--- a/src/VBox/Frontends/VirtualBox/nls/VirtualBox_cs.ts
+++ b/src/VBox/Frontends/VirtualBox/nls/VirtualBox_cs.ts
@@ -4312,7 +4312,7 @@ p, li { white-space: pre-wrap; }
         <translation>IPv6 adresa</translation>
     </message>
     <message>
-        <source>IPv6 Network Mask Length</source>
+        <source>IPv6 Prefix Length</source>
         <translation>Délka masky pro IPv6</translation>
     </message>
     <message>
@@ -4566,7 +4566,7 @@ p, li { white-space: pre-wrap; }
         <translation>Upravit vybranou síť mezi hostem.</translation>
     </message>
     <message>
-        <source>Host interface <b>%1</b> does not currently have a valid IPv6 network mask prefix length.</source>
+        <source>Host interface <b>%1</b> does not currently have a valid IPv6 prefix length.</source>
         <translation type="unfinished"></translation>
     </message>
 </context>
@@ -4613,11 +4613,11 @@ p, li { white-space: pre-wrap; }
         <translation type="obsolete">Pokud je IPv6 podporováno, zobrazí adresu hosta pro toto síťové rozhraní.</translation>
     </message>
     <message>
-        <source>IPv6 Network Mask &Length:</source>
+        <source>IPv6 Prefix &Length:</source>
         <translation type="obsolete">&Délka masky pro IPv6:</translation>
     </message>
     <message>
-        <source>Holds the host IPv6 network mask prefix length for this adapter if IPv6 is supported.</source>
+        <source>Holds the host IPv6 prefix length for this adapter if IPv6 is supported.</source>
         <translation type="obsolete">Pokud je IPv6 podporováno, zobrazí délku prefixu IPv6 masky hosta pro toto síťové rozhraní.</translation>
     </message>
     <message>
@@ -4708,11 +4708,11 @@ p, li { white-space: pre-wrap; }
         <translation>Pokud je IPv6 podporováno, zobrazí adresu hosta pro toto síťové rozhraní.</translation>
     </message>
     <message>
-        <source>IPv6 Network Mask &Length:</source>
+        <source>IPv6 Prefix &Length:</source>
         <translation>&Délka masky pro IPv6:</translation>
     </message>
     <message>
-        <source>Holds the host IPv6 network mask prefix length for this adapter if IPv6 is supported.</source>
+        <source>Holds the host IPv6 prefix length for this adapter if IPv6 is supported.</source>
         <translation>Pokud je IPv6 podporováno, zobrazí délku prefixu IPv6 masky hosta pro toto síťové rozhraní.</translation>
     </message>
     <message>
diff --git a/src/VBox/Frontends/VirtualBox/nls/VirtualBox_da.ts b/src/VBox/Frontends/VirtualBox/nls/VirtualBox_da.ts
index 39a86bb..5532ffd 100644
--- a/src/VBox/Frontends/VirtualBox/nls/VirtualBox_da.ts
+++ b/src/VBox/Frontends/VirtualBox/nls/VirtualBox_da.ts
@@ -4165,7 +4165,7 @@ p, li { white-space: pre-wrap; }
         <translation>IPv6-adresse</translation>
     </message>
     <message>
-        <source>IPv6 Network Mask Length</source>
+        <source>IPv6 Prefix Length</source>
         <translation>Længde på IPv6-netværksmaske</translation>
     </message>
     <message>
@@ -4419,7 +4419,7 @@ p, li { white-space: pre-wrap; }
         <translation>Tilpasser valgt værtsbegrænset netværk.</translation>
     </message>
     <message>
-        <source>Host interface <b>%1</b> does not currently have a valid IPv6 network mask prefix length.</source>
+        <source>Host interface <b>%1</b> does not currently have a valid IPv6 prefix length.</source>
         <translation type="unfinished"></translation>
     </message>
 </context>
@@ -4466,11 +4466,11 @@ p, li { white-space: pre-wrap; }
         <translation type="obsolete">Viser værtens IPv6-adresse for dette netværkskort.</translation>
     </message>
     <message>
-        <source>IPv6 Network Mask &Length:</source>
+        <source>IPv6 Prefix &Length:</source>
         <translation type="obsolete">&Længde på IPv6-netværksmaske:</translation>
     </message>
     <message>
-        <source>Holds the host IPv6 network mask prefix length for this adapter if IPv6 is supported.</source>
+        <source>Holds the host IPv6 prefix length for this adapter if IPv6 is supported.</source>
         <translation type="obsolete">Viser præfix-længden af værtens IPv6-netværksmaske for dette netværkskort, hvis IPv6 understøttes.</translation>
     </message>
     <message>
@@ -4561,11 +4561,11 @@ p, li { white-space: pre-wrap; }
         <translation>Viser værtens IPv6-adresse for dette netværkskort, hvis IPv6 er understøttet.</translation>
     </message>
     <message>
-        <source>IPv6 Network Mask &Length:</source>
+        <source>IPv6 Prefix &Length:</source>
         <translation>&Længde på IPv6-netværksmaske:</translation>
     </message>
     <message>
-        <source>Holds the host IPv6 network mask prefix length for this adapter if IPv6 is supported.</source>
+        <source>Holds the host IPv6 prefix length for this adapter if IPv6 is supported.</source>
         <translation>Viser præfix-længden af værtens IPv6-netværksmaske for dette netværkskort, hvis IPv6 er understøttet.</translation>
     </message>
     <message>
diff --git a/src/VBox/Frontends/VirtualBox/nls/VirtualBox_de.ts b/src/VBox/Frontends/VirtualBox/nls/VirtualBox_de.ts
index 3482d18..70ba7fa 100644
--- a/src/VBox/Frontends/VirtualBox/nls/VirtualBox_de.ts
+++ b/src/VBox/Frontends/VirtualBox/nls/VirtualBox_de.ts
@@ -2014,8 +2014,8 @@
         <translation>IPv6-Adresse</translation>
     </message>
     <message>
-        <source>IPv6 Network Mask Length</source>
-        <translation>IPv6 Netzmasken-Länge</translation>
+        <source>IPv6 Prefix Length</source>
+        <translation>IPv6-Präfixlänge</translation>
     </message>
     <message>
         <source>Not set</source>
@@ -2231,8 +2231,8 @@
         <translation>Ändert das ausgewählte Host-only Netzwerk.</translation>
     </message>
     <message>
-        <source>Host interface <b>%1</b> does not currently have a valid IPv6 network mask prefix length.</source>
-        <translation></translation>
+        <source>Host interface <b>%1</b> does not currently have a valid IPv6 prefix length.</source>
+        <translation>Das Host-Netzinterface <b>%1</b> hat keine gültige IPv6-Präfixlänge.</translation>
     </message>
 </context>
 <context>
@@ -2274,12 +2274,12 @@
         <translation>Zeigt die IPv6-Adresse für diesen Adapter falls IPv6 unterstützt wird.</translation>
     </message>
     <message>
-        <source>IPv6 Network Mask &Length:</source>
-        <translation>IPv6 Netzmasken-&Länge:</translation>
+        <source>IPv6 Prefix &Length:</source>
+        <translation>IPv6-Präfix&länge:</translation>
     </message>
     <message>
-        <source>Holds the host IPv6 network mask prefix length for this adapter if IPv6 is supported.</source>
-        <translation>Zeigt die IPv6 Netzmasken-Prefixlänge für diesen Adapter falls IPv6 unterstützt wird.</translation>
+        <source>Holds the host IPv6 prefix length for this adapter if IPv6 is supported.</source>
+        <translation>Zeigt die IPv6-Präfixlänge für diesen Adapter falls IPv6 unterstützt wird.</translation>
     </message>
     <message>
         <source>&DHCP Server</source>
@@ -7296,11 +7296,11 @@
     </message>
     <message>
         <source>Storage on physical hard disk</source>
-        <translation></translation>
+        <translation>Art der Speicherung</translation>
     </message>
     <message>
         <source>Please choose whether the new virtual hard disk file should grow as it is used (dynamically allocated) or if it should be created at its maximum size (fixed size).</source>
-        <translation></translation>
+        <translation>Bitte wählen Sie, ob die neue virtuelle Festplatte erst nach und nach zur Laufzeit (dynamisch) alloziert werden soll oder ob die Platte jetzt sofort vollständig alloziert werden soll (feste Größe).</translation>
     </message>
     <message>
         <source><p>A <b>dynamically allocated</b> hard disk file will only use space on your physical hard disk as it fills up (up to a maximum <b>fixed size</b>), although it will not shrink again automatically when space on it is freed.</p></source>
diff --git a/src/VBox/Frontends/VirtualBox/nls/VirtualBox_el.ts b/src/VBox/Frontends/VirtualBox/nls/VirtualBox_el.ts
index 3c8b4f2..39f9dd4 100644
--- a/src/VBox/Frontends/VirtualBox/nls/VirtualBox_el.ts
+++ b/src/VBox/Frontends/VirtualBox/nls/VirtualBox_el.ts
@@ -6,7 +6,7 @@
     <message>
         <source>English</source>
         <comment>Native language name</comment>
-        <translatorcomment>2017-03-13</translatorcomment>
+        <translatorcomment>2017-05-04</translatorcomment>
         <translation>Ελληνικά</translation>
     </message>
     <message>
@@ -196,7 +196,7 @@
     </message>
     <message>
         <source>Take a snapshot of the virtual machine</source>
-        <translation>Πάρτε ένα στιγμιότυπο της εικονικής μηχανής</translation>
+        <translation>Λήψη ενός στιγμιοτύπου της εικονικής μηχανής</translation>
     </message>
     <message>
         <source>&Pause</source>
@@ -659,7 +659,7 @@
     </message>
     <message>
         <source>Automatically resize the guest display when the window is resized</source>
-        <translation>Αυτόματα αλλάζει η ανάλυση του επισκέπτη όταν το αλλάζει το παράθυρο</translation>
+        <translation>Αυτόματα αλλάζει την ανάλυση οθόνης επισκέπτη όταν αλλάζει το παράθυρο</translation>
     </message>
     <message>
         <source>Take guest display screenshot</source>
@@ -1110,11 +1110,11 @@
     <name>UIApplianceImportEditorWidget</name>
     <message>
         <source>Importing Appliance ...</source>
-        <translation>Εισάγεται η Συσκευή ...</translation>
+        <translation>Εισαγωγή Συσκευής ...</translation>
     </message>
     <message>
         <source>Reading Appliance ...</source>
-        <translation>Διαβάζεται η Συσκευή ...</translation>
+        <translation>Ανάγνωση Συσκευής ...</translation>
     </message>
 </context>
 <context>
@@ -2039,7 +2039,7 @@
         <translation>Διεύθυνση IPv6</translation>
     </message>
     <message>
-        <source>IPv6 Network Mask Length</source>
+        <source>IPv6 Prefix Length</source>
         <translation>Μήκος Μάσκας Δικτύου IPv6</translation>
     </message>
     <message>
@@ -2256,7 +2256,7 @@
         <translation>Επεξεργασία του επιλεγμένου μόνο-με-οικοδεσπότη δίκτυο.</translation>
     </message>
     <message>
-        <source>Host interface <b>%1</b> does not currently have a valid IPv6 network mask prefix length.</source>
+        <source>Host interface <b>%1</b> does not currently have a valid IPv6 prefix length.</source>
         <translation>Η κάρτα δικτύου <b>%1</b> δεν έχει έγκυρο μήκος προθέματος της μάσκας δικτύου IPv6.</translation>
     </message>
 </context>
@@ -2299,11 +2299,11 @@
         <translation>Δείχνει τη διεύθυνση IPv6 του οικοδεσπότη για αυτή την κάρτα δικτύου αν το IPv6 υποστηρίζεται.</translation>
     </message>
     <message>
-        <source>IPv6 Network Mask &Length:</source>
+        <source>IPv6 Prefix &Length:</source>
         <translation>Μήκος Μάσκας Δικτύου IPv6:</translation>
     </message>
     <message>
-        <source>Holds the host IPv6 network mask prefix length for this adapter if IPv6 is supported.</source>
+        <source>Holds the host IPv6 prefix length for this adapter if IPv6 is supported.</source>
         <translation>Δείχνει το μήκος προθέματος της μάσκας δικτύου IPv6 του οικοδεσπότη για αυτή την κάρτα δικτύου αν το IPv6 υποστηρίζεται.</translation>
     </message>
     <message>
@@ -6114,11 +6114,11 @@
     </message>
     <message>
         <source>SSL authentication failed</source>
-        <translation>Απέτυχε η πιστοποίηση SSL</translation>
+        <translation>Αποτυχία πιστοποίησης SSL</translation>
     </message>
     <message>
         <source>Unknown reason</source>
-        <translation>Άγνωστος λόγος</translation>
+        <translation>Άγνωστη αιτία</translation>
     </message>
     <message>
         <source>%1: %2</source>
@@ -6139,7 +6139,7 @@
     </message>
     <message>
         <source>Proxy not found</source>
-        <translation>Δεν βρέθεκε διαμεσολαβητής</translation>
+        <translation>Δεν βρέθηκε διαμεσολαβητής</translation>
     </message>
     <message>
         <source>Url not found on the server</source>
@@ -6154,7 +6154,7 @@
     </message>
     <message>
         <source>During certificate downloading</source>
-        <translation>Κατά τη διάρκεια του κατεβάσματος του πιστοποιητικού</translation>
+        <translation>Κατά τη διάρκεια της λήψης πιστοποιητικού</translation>
     </message>
     <message>
         <source>During network request</source>
@@ -6227,7 +6227,7 @@
     <name>UIProgressDialog</name>
     <message>
         <source>A few seconds remaining</source>
-        <translation>Λίγα δευτερόλεπτα παραμένουν</translation>
+        <translation>Λίγα δευτερόλεπτα απομένουν</translation>
     </message>
     <message>
         <source>Canceling...</source>
@@ -6239,17 +6239,17 @@
     </message>
     <message>
         <source>Cancel the current operation</source>
-        <translation>Ακύρωση της διαδικασίας δικτύου</translation>
+        <translation>Ακύρωση της τρέχουσας διαδικασίας</translation>
     </message>
     <message>
         <source>%1, %2 remaining</source>
         <comment>You may wish to translate this more like "Time remaining: %1, %2"</comment>
-        <translation>%1, %2 παραμένουν</translation>
+        <translation>%1, %2 απομένουν</translation>
     </message>
     <message>
         <source>%1 remaining</source>
         <comment>You may wish to translate this more like "Time remaining: %1"</comment>
-        <translation>%1 παραμένουν</translation>
+        <translation>%1 απομένουν</translation>
     </message>
 </context>
 <context>
@@ -6798,11 +6798,11 @@
     </message>
     <message>
         <source>&Guided Mode</source>
-        <translation>Καθοδηγημένη Λειτουργία</translation>
+        <translation>Καθοδηγούμενη Λειτουργία</translation>
     </message>
     <message>
         <source>Switch to <nobr><b>Guided Mode</b></nobr>, a step-by-step dialog with detailed explanations.</source>
-        <translation>Εναλλαγή σε <nobr><b>Καθοδηγημένη Λειτουργία</b></nobr>, βήμα προς βήμα ρυθμίσεις με λεπτομερείς εξηγήσεις.</translation>
+        <translation>Εναλλαγή σε <nobr><b>Καθοδηγούμενη Λειτουργία</b></nobr>, βήμα προς βήμα ρυθμίσεις με λεπτομερείς εξηγήσεις.</translation>
     </message>
 </context>
 <context>
@@ -6878,11 +6878,11 @@
     </message>
     <message>
         <source>New hard disk to create</source>
-        <translation>Νέος σκληρός δίσκος για δημιουργία</translation>
+        <translation>Δημιουργία νέου σκληρού δίσκου</translation>
     </message>
     <message>
         <source>Please type the name of the new virtual hard disk file into the box below or click on the folder icon to select a different folder to create the file in.</source>
-        <translation>Συμπληρώστε το όνομα του αρχείου του νέου εικονικού σκληρού δίσκου στο κουτί παρακάτω ή κάντε κλικ στο εικονίδιο φακέλου για να επιλέξετε ένα φάκελο στον οποίο θα δημιουργηθεί το αρχείο.</translation>
+        <translation>Παρακαλώ συμπληρώστε το όνομα του αρχείου του νέου εικονικού σκληρού δίσκου στο κουτί παρακάτω ή κάντε κλικ στο εικονίδιο φακέλου για να επιλέξετε ένα φάκελο στον οποίο θα δημιουργηθεί το αρχείο.</translation>
     </message>
     <message>
         <source>Choose a location for new virtual hard disk file...</source>
@@ -6929,7 +6929,7 @@
     </message>
     <message>
         <source><p>Please choose a name for the new virtual machine. The new machine will be a clone of the machine <b>%1</b>.</p></source>
-        <translation><p>Επιλέξτε ένα όνομα για τη νέα εικονική μηχανή. Η νέα μηχανή θα είναι κλώνος της μηχανής  <b>%1</b>.</p></translation>
+        <translation><p>Παρακαλώ επιλέξτε ένα όνομα για τη νέα εικονική μηχανή. Η νέα μηχανή θα είναι κλώνος της μηχανής  <b>%1</b>.</p></translation>
     </message>
     <message>
         <source>When checked a new unique MAC address will be assigned to all configured network cards.</source>
@@ -6949,7 +6949,7 @@
     </message>
     <message>
         <source>&Full clone</source>
-        <translation>Πλήρες κλώνος</translation>
+        <translation>Πλήρης κλώνος</translation>
     </message>
     <message>
         <source>&Linked clone</source>
@@ -6985,7 +6985,7 @@
     </message>
     <message>
         <source>&Everything</source>
-        <translation>Τα πάντα</translation>
+        <translation>Όλα</translation>
     </message>
     <message>
         <source>New machine &name</source>
@@ -7016,11 +7016,11 @@
     </message>
     <message>
         <source>Exporting Appliance ...</source>
-        <translation>Εξάγεται η Συσκευή ...</translation>
+        <translation>Εξαγωγή Συσκευής ...</translation>
     </message>
     <message>
         <source>Export Virtual Appliance</source>
-        <translation>Εξάγετε Εικονική Συσκευή</translation>
+        <translation>Εξαγωγή Εικονικής Συσκευής</translation>
     </message>
     <message>
         <source>Restore Defaults</source>
@@ -7032,11 +7032,11 @@
     </message>
     <message>
         <source>Virtual machines to export</source>
-        <translation>Εικονικές μηχανές για εξαγωγή</translation>
+        <translation>Εικονικές μηχανές προς εξαγωγή</translation>
     </message>
     <message>
         <source><p>Please select the virtual machines that should be added to the appliance. You can select more than one. Please note that these machines have to be turned off before they can be exported.</p></source>
-        <translation><p>Επιλέξτε τις εικονικές μηχανές που θα προστεθούν στη συσκευή. Μπορείτε να επιλέξετε παραπάνω από μία. Σημειώστε οτι αυτές οι μηχανές πρέπει να έχουν τερματίσει τη λειτουργία τους πριν να τις εξάγετε.</p></translation>
+        <translation><p>Παρακαλώ επιλέξτε τις εικονικές μηχανές που θα προστεθούν στη συσκευή. Μπορείτε να επιλέξετε παραπάνω από μία. Σημειώστε οτι αυτές οι μηχανές πρέπει να έχουν τερματίσει τη λειτουργία τους πριν να μπορούν να εξαχθούν.</p></translation>
     </message>
     <message>
         <source>Appliance settings</source>
@@ -7044,11 +7044,11 @@
     </message>
     <message>
         <source>Please choose where to create the virtual appliance. You can create it on your own computer, on the Sun Cloud service or on an S3 storage server.</source>
-        <translation>Επιλέξτε πού θα δημιουργήσετε την εικονική συσκευή. Μπορείτε να τις δημιουργήσετε στον υπολογιστή σας, στις υπηρεσίες Sun Cloud ή σε διακομιστή αποθήκευσης S3.</translation>
+        <translation>Παρακαλώ επιλέξτε πού θα δημιουργήσετε την εικονική συσκευή. Μπορείτε να τις δημιουργήσετε στον υπολογιστή σας, στις υπηρεσίες Sun Cloud ή σε διακομιστή αποθήκευσης S3.</translation>
     </message>
     <message>
         <source>Create on</source>
-        <translation>Δημιουργήστε στο</translation>
+        <translation>Δημιουργία στο</translation>
     </message>
     <message>
         <source>&This computer</source>
@@ -7060,7 +7060,7 @@
     </message>
     <message>
         <source>&Simple Storage System (S3)</source>
-        <translation>Απλό σύστημα αποθήκευσης (Amazon S3)</translation>
+        <translation>Απλό Σύστημα Αποθήκευσης (Amazon S3)</translation>
     </message>
     <message>
         <source>Appliance</source>
@@ -7068,7 +7068,7 @@
     </message>
     <message>
         <source>&Username:</source>
-        <translation>Όνομα:</translation>
+        <translation>Όνομα χρήστη:</translation>
     </message>
     <message>
         <source>&Password:</source>
@@ -7171,11 +7171,11 @@
     </message>
     <message>
         <source>Please complete the additional fields like the username, password and the bucket, and provide a filename for the OVF target.</source>
-        <translation>Συμπληρώστε τα πρόσθετα πεδία όπως το όνομα χρήστη, τον κωδικό και το δοχείο, και επιλέξτε το όνομα για το αρχείο OVF.</translation>
+        <translation>Παρακαλώ συμπληρώστε τα πρόσθετα πεδία όπως το όνομα χρήστη, τον κωδικό και το δοχείο, και επιλέξτε ένα όνομα για το αρχείο OVF.</translation>
     </message>
     <message>
         <source>Please complete the additional fields like the username, password, hostname and the bucket, and provide a filename for the OVF target.</source>
-        <translation>Συμπληρώστε τα πρόσθετα πεδία όπως το όνομα χρήστη, τον κωδικό, το όνομα του οικοδεσπότη και το δοχείο, και επιλέξτε το όνομα για το αρχείο OVF.</translation>
+        <translation>Παρακαλώ συμπληρώστε τα πρόσθετα πεδία όπως το όνομα χρήστη, τον κωδικό, το όνομα του οικοδεσπότη και το δοχείο, και επιλέξτε ένα όνομα για το αρχείο OVF.</translation>
     </message>
     <message>
         <source>Choose a file to export the virtual appliance to...</source>
@@ -7186,14 +7186,14 @@
     <name>UIWizardExportAppPageExpert</name>
     <message>
         <source>Choose a file to export the virtual appliance to...</source>
-        <translation>Επιλέξτε ένα αρχείο στο οποίο θα εξάγετε την εικονική μηχανή...</translation>
+        <translation>Επιλογή ενός αρχείου στο οποίο θα εξαχθεί η εικονική μηχανή...</translation>
     </message>
 </context>
 <context>
     <name>UIWizardFirstRun</name>
     <message>
         <source>Select start-up disk</source>
-        <translation>Διαλέξτε δίσκο εκκίνησης</translation>
+        <translation>Επιλογή δίσκου εκκίνησης</translation>
     </message>
     <message>
         <source>Start</source>
@@ -7205,11 +7205,11 @@
     </message>
     <message>
         <source><p>Please select a virtual optical disk file or a physical optical drive containing a disk to start your new virtual machine from.</p><p>The disk should be suitable for starting a computer from. As this virtual machine has no hard drive you will not be able to install an operating system on it at the moment.</p></source>
-        <translation><p>Παρακαλώ επιλέξτε ένα αρχείο εικονικού οπτικού δίσκου ή μία φυσική μονάδα οπτικού δίσκου που περιέχει ένα δίσκο από τον οποίο θα ξεκινήσει η νέα εικονική μηχανή.</p><p>Ο δίσκος θα πρέπει να είναι κατάλληλος να ξεκινήσει ένας υπολογιστής. Μιας και αυτή η εικονική μηχανή δεν έχει σκληρό δίσκο δεν θα μπορέσετε να εγκαταστήσετε ένα λειτουργικό σύστημα τώρα.<p></translation>
+        <translation><p>Παρακαλώ επιλέξτε ένα αρχείο εικονικού οπτικού δίσκου ή μία φυσική μονάδα οπτικού δίσκου που περιέχει ένα δίσκο από τον οποίο θα ξεκινήσει η νέα εικονική μηχανή.</p><p>Ο δίσκος θα πρέπει να είναι κατάλληλος να ξεκινήσει ένας υπολογιστής. Επειδή αυτή η εικονική μηχανή δεν έχει σκληρό δίσκο δεν θα μπορέσετε να εγκαταστήσετε ένα λειτουργικό σύστημα τώρα.<p></translation>
     </message>
     <message>
         <source>Choose a virtual optical disk file...</source>
-        <translation>Επιλέξτε έναν εικονικό οπτικό δίσκο...</translation>
+        <translation>Επιλογή ενός εικονικού οπτικού δίσκου...</translation>
     </message>
 </context>
 <context>
@@ -7374,11 +7374,11 @@
     <name>UIWizardNewVM</name>
     <message>
         <source>Create Virtual Machine</source>
-        <translation>Δημιουργήστε Εικονική Μηχανή</translation>
+        <translation>Δημιουργία Εικονικής Μηχανής</translation>
     </message>
     <message>
         <source>Create</source>
-        <translation>Δημιουργήστε</translation>
+        <translation>Δημιουργία</translation>
     </message>
     <message>
         <source>Name and operating system</source>
@@ -7452,7 +7452,7 @@
     <name>VBoxEmptyFileSelector</name>
     <message>
         <source>Choose...</source>
-        <translation type="vanished">Επιλέξτε...</translation>
+        <translation type="vanished">Επιλογή...</translation>
     </message>
 </context>
 <context>
@@ -7650,7 +7650,7 @@
     <message>
         <source>Running</source>
         <comment>MachineState</comment>
-        <translation>Τρέχει</translation>
+        <translation>Σε λειτουργία</translation>
     </message>
     <message>
         <source>Paused</source>
@@ -7670,7 +7670,7 @@
     <message>
         <source>Saving</source>
         <comment>MachineState</comment>
-        <translation>Σώζεται</translation>
+        <translation>Αποθηκεύεται</translation>
     </message>
     <message>
         <source>Restoring</source>
@@ -8010,7 +8010,7 @@
     <message>
         <source>Checking...</source>
         <comment>medium</comment>
-        <translation>Ελέγχω...</translation>
+        <translation>Έλεγχος...</translation>
     </message>
     <message>
         <source>Inaccessible</source>
@@ -8210,7 +8210,7 @@
     <message>
         <source>Deleting Snapshot</source>
         <comment>MachineState</comment>
-        <translation>Σβήνεται Στιγμιότυπο</translation>
+        <translation>Διαγράφεται Στιγμιότυπο</translation>
     </message>
     <message>
         <source>Floppy</source>
@@ -8274,7 +8274,7 @@
     </message>
     <message>
         <source>You can also change this while the machine is running.</source>
-        <translation>Μπορείτε να το αλλάξετε ενώ η μηχανή τρέχει.</translation>
+        <translation>Αυτό μπορεί επίσης να αλλαχθεί ενώ η μηχανή είναι σε λειτουργία.</translation>
     </message>
     <message>
         <source><b>No disk image files available</b></source>
@@ -8508,7 +8508,7 @@
     <message>
         <source>Shareable</source>
         <comment>MediumType</comment>
-        <translation>Διαμοιρασμένο</translation>
+        <translation>Διαμοιράσιμο</translation>
     </message>
     <message>
         <source>Readonly</source>
@@ -8533,7 +8533,7 @@
     <message>
         <source>Fixed size storage</source>
         <comment>MediumVariant</comment>
-        <translation>Πάγια αποθήκευση</translation>
+        <translation>Πάγιο μέγεθος αποθήκευσης</translation>
     </message>
     <message>
         <source>Dynamically allocated storage split into files of less than 2GB</source>
@@ -8563,12 +8563,12 @@
     <message>
         <source>Fixed size ESX storage</source>
         <comment>MediumVariant</comment>
-        <translation>Πάγια αποθήκευση ESX</translation>
+        <translation>Πάγιο μέγεθος αποθήκευσης ESX</translation>
     </message>
     <message>
         <source>Fixed size storage on raw disk</source>
         <comment>MediumVariant</comment>
-        <translation>Πάγια αποθήκευση σε πηγαίο δίσκο</translation>
+        <translation>Πάγιο μέγεθος αποθήκευσης σε πηγαίο δίσκο</translation>
     </message>
     <message>
         <source>Deny</source>
@@ -8588,12 +8588,12 @@
     <message>
         <source>Ignore</source>
         <comment>USBDeviceFilterAction</comment>
-        <translation>Αγνοήστε</translation>
+        <translation>Αγνόηση</translation>
     </message>
     <message>
         <source>Hold</source>
         <comment>USBDeviceFilterAction</comment>
-        <translation>Κρατήστε</translation>
+        <translation>Κράτηση</translation>
     </message>
     <message>
         <source>UDP</source>
@@ -8707,7 +8707,7 @@
     </message>
     <message>
         <source>Please choose a virtual optical disk file</source>
-        <translation>Παρακαλώ επιλέξτε έναν εικονικό οπτικό δίσκο</translation>
+        <translation>Παρακαλώ επιλέξτε ένα αρχείο εικονικού οπτικού δίσκου</translation>
     </message>
     <message>
         <source>All virtual optical disk files (%1)</source>
@@ -8929,7 +8929,7 @@
     </message>
     <message>
         <source>Please choose a virtual hard disk file</source>
-        <translation>Παρακαλώ επιλέξτε έναν εικονικό σκληρό δίσκο</translation>
+        <translation>Παρακαλώ επιλέξτε ένα αρχείο εικονικού σκληρού δίσκου</translation>
     </message>
     <message>
         <source>All virtual hard disk files (%1)</source>
@@ -8938,7 +8938,7 @@
     <message>
         <source>Attaching this hard disk will be performed indirectly using a newly created differencing hard disk.</source>
         <comment>medium</comment>
-        <translation>Προσαρτώντας αυτόν το σκληρό δίσκο θα γίνει έμμεσα χρησιμοποιώντας ένα καινούριο διαφορικό σκληρό δίσκο.</translation>
+        <translation>Η προσάρτησηση αυτού του σκληρού δίσκου θα γίνει έμμεσα χρησιμοποιώντας έναν καινούριο διαφορικό σκληρό δίσκο.</translation>
     </message>
     <message>
         <source>Some of the files in this hard disk chain are inaccessible. Please use the Virtual Medium Manager to inspect these files.</source>
@@ -9052,7 +9052,7 @@
     <message>
         <source>Storage statistics</source>
         <comment>InformationElementType</comment>
-        <translation>Στατιστικά αποθήκευσης</translation>
+        <translation>Στατιστικά μέσων αποθήκευσης</translation>
     </message>
     <message>
         <source>Network statistics</source>
@@ -9094,7 +9094,7 @@
     <name>VBoxMediaManagerDlg</name>
     <message>
         <source>&Actions</source>
-        <translation>Δράσεις</translation>
+        <translation>Ενέργειες</translation>
     </message>
     <message>
         <source>R&emove</source>
@@ -9122,7 +9122,7 @@
     </message>
     <message>
         <source>Checking accessibility</source>
-        <translation>Checking accessibility</translation>
+        <translation>Έλεγχος προσβασιμότητας</translation>
     </message>
     <message>
         <source><i>Not&nbsp;Attached</i></source>
@@ -9225,7 +9225,7 @@
     </message>
     <message>
         <source>Click to enlarge the screenshot.</source>
-        <translation>Κλικ για μεγένθυση του στιγμιότυπου οθόνης.</translation>
+        <translation>Κλικ για μεγέθυνση του στιγμιότυπου οθόνης.</translation>
     </message>
     <message>
         <source>&Name:</source>
@@ -9233,7 +9233,7 @@
     </message>
     <message>
         <source>Taken:</source>
-        <translation>Πιασμένο:</translation>
+        <translation>Λήψη:</translation>
     </message>
     <message>
         <source>&Description:</source>
@@ -9253,7 +9253,7 @@
     <message>
         <source>Current State (changed)</source>
         <comment>Current State (Modified)</comment>
-        <translation>Τρέχουσα κατάσταση (άλλαξε)</translation>
+        <translation>Τρέχουσα κατάσταση (αλλαγμένη)</translation>
     </message>
     <message>
         <source>Current State</source>
@@ -9266,32 +9266,32 @@
     </message>
     <message>
         <source>The current state is identical to the state stored in the current snapshot</source>
-        <translation>Η τρέχουσα κατάσταση είναι πανομοιότυπη με την κατάσταση που είναι αποθηκευμένη στο τρέχον στιγμιότυπο</translation>
+        <translation>Η τρέχουσα κατάσταση είναι ίδια με την κατάσταση που είναι αποθηκευμένη στο τρέχον στιγμιότυπο</translation>
     </message>
     <message>
         <source> (current, </source>
         <comment>Snapshot details</comment>
-        <translation> (τρέχουσα, </translation>
+        <translation> (τρέχον, </translation>
     </message>
     <message>
         <source>online)</source>
         <comment>Snapshot details</comment>
-        <translation>συνδεδεμένη)</translation>
+        <translation>συνδεδεμένο)</translation>
     </message>
     <message>
         <source>offline)</source>
         <comment>Snapshot details</comment>
-        <translation>αποσυνδεδεμένη)</translation>
+        <translation>αποσυνδεδεμένο)</translation>
     </message>
     <message>
         <source>Taken at %1</source>
         <comment>Snapshot (time)</comment>
-        <translation>Πάρθηκε στις %1</translation>
+        <translation>Λήψη στις %1</translation>
     </message>
     <message>
         <source>Taken on %1</source>
         <comment>Snapshot (date + time)</comment>
-        <translation>Πάρθηκε την %1</translation>
+        <translation>Λήψη την %1</translation>
     </message>
     <message>
         <source>%1 since %2</source>
@@ -9312,7 +9312,7 @@
     </message>
     <message>
         <source>Take a snapshot of the current virtual machine state</source>
-        <translation>Πάρτε ένα στιγμιότυπο της τρέχουσας εικονικής μηχανής</translation>
+        <translation>Λήψη ενός στιγμιοτύπου της τρέχουσας κατάστασης της εικονικής μηχανής</translation>
     </message>
     <message>
         <source> (%1)</source>
@@ -9348,14 +9348,14 @@
     </message>
     <message>
         <source>Clone selected virtual machine</source>
-        <translation>Κλωνοποιήστε την επιλεγμένη εικονική μηχανή</translation>
+        <translation>Κλωνοποίηση της επιλεγμένης εικονικής μηχανής</translation>
     </message>
 </context>
 <context>
     <name>VBoxTakeSnapshotDlg</name>
     <message>
         <source>Take Snapshot of Virtual Machine</source>
-        <translation>Πάρτε Στιγμιότυπο της Εικονικής Μηχανής</translation>
+        <translation>Λήψη Στιγμιοτύπου Εικονικής Μηχανής</translation>
     </message>
     <message>
         <source>Snapshot &Name</source>
@@ -9368,8 +9368,8 @@
     <message numerus="yes">
         <source>Warning: You are taking a snapshot of a running machine which has %n immutable image(s) attached to it. As long as you are working from this snapshot the immutable image(s) will not be reset to avoid loss of data.</source>
         <translation>
-            <numerusform>Προειδοποίηση: Παίρνετε ένα στιγμιότυπο μίας εικονικής μηχανής που τρέχει και έχει %n αμετάβλητη εικόνα προσαρτημένη. Όσο δουλεύετε με αυτό το στιγμιότυπο η αμετάβλητη εικόνα δεν θα επαναφερθεί για να αποφευχθεί το χάσιμο δεδομένων.</numerusform>
-            <numerusform>Προειδοποίηση: Παίρνετε ένα στιγμιότυπο μίας εικονικής μηχανής που τρέχει και έχει %n αμετάβλητες εικόνες προσαρτημένες. Όσο δουλεύετε με αυτό το στιγμιότυπο οι αμετάβλητες εικόνες δεν θα επαναφερθούν για να αποφευχθεί το χάσιμο δεδομένων.</numerusform>
+            <numerusform>Προειδοποίηση: Παίρνετε ένα στιγμιότυπο μίας εικονικής μηχανής σε λειτουργία που έχει %n αμετάβλητη εικόνα προσαρτημένη σε αυτό. Όσο δουλεύετε με αυτό το στιγμιότυπο η αμετάβλητη εικόνα δεν θα επαναφερθεί για να αποφευχθεί η απώλεια δεδομένων.</numerusform>
+            <numerusform>Προειδοποίηση: Παίρνετε ένα στιγμιότυπο μίας εικονικής μηχανής σε λειτουργία που έχει %n αμετάβλητες εικόνες προσαρτημένες σε αυτό. Όσο δουλεύετε με αυτό το στιγμιότυπο οι αμετάβλητες εικόνες δεν θα επαναφερθούν για να αποφευχθεί η απώλεια δεδομένων.</numerusform>
         </translation>
     </message>
     <message>
@@ -9387,7 +9387,7 @@
     <message>
         <source>No supported devices connected to the host PC</source>
         <comment>USB device tooltip</comment>
-        <translation>Καμία συνδεδεμένη υποστηριζόμενη συσκευή στον οικοδεσπότη</translation>
+        <translation>Καμία υποστηριζόμενη συνδεδεμένη συσκευή στον οικοδεσπότη</translation>
     </message>
 </context>
 </TS>
diff --git a/src/VBox/Frontends/VirtualBox/nls/VirtualBox_es.ts b/src/VBox/Frontends/VirtualBox/nls/VirtualBox_es.ts
index 9fade3c..4681020 100644
--- a/src/VBox/Frontends/VirtualBox/nls/VirtualBox_es.ts
+++ b/src/VBox/Frontends/VirtualBox/nls/VirtualBox_es.ts
@@ -4386,7 +4386,7 @@ p, li { white-space: pre-wrap; }
         <translation>Dirección IPv6</translation>
     </message>
     <message>
-        <source>IPv6 Network Mask Length</source>
+        <source>IPv6 Prefix Length</source>
         <translation>Longitud de máscara de red IPv6</translation>
     </message>
     <message>
@@ -4644,7 +4644,7 @@ p, li { white-space: pre-wrap; }
         <translation>Edita red sólo-anfitrión.</translation>
     </message>
     <message>
-        <source>Host interface <b>%1</b> does not currently have a valid IPv6 network mask prefix length.</source>
+        <source>Host interface <b>%1</b> does not currently have a valid IPv6 prefix length.</source>
         <translation>La interfaz anfitrión <b>%1</b> actualmente no tiene una longitud de prefijo para la máscara de red IPv6 válida.</translation>
     </message>
 </context>
@@ -4691,11 +4691,11 @@ p, li { white-space: pre-wrap; }
         <translation type="obsolete">Muestra la dirección IPv6 del anfitrión para este adaptador si IPv6 es soportado.</translation>
     </message>
     <message>
-        <source>IPv6 Network Mask &Length:</source>
+        <source>IPv6 Prefix &Length:</source>
         <translation type="obsolete">&Longitud de máscara de red IPv6:</translation>
     </message>
     <message>
-        <source>Holds the host IPv6 network mask prefix length for this adapter if IPv6 is supported.</source>
+        <source>Holds the host IPv6 prefix length for this adapter if IPv6 is supported.</source>
         <translation type="obsolete">Muestra la longitud del prefijo de máscara de red IPv6 del anfitrión para este adaptador si IPv6 es soportado.</translation>
     </message>
     <message>
@@ -4786,11 +4786,11 @@ p, li { white-space: pre-wrap; }
         <translation>Muestra la dirección IPv6 del anfitrión para este adaptador si IPv6 es soportado.</translation>
     </message>
     <message>
-        <source>IPv6 Network Mask &Length:</source>
+        <source>IPv6 Prefix &Length:</source>
         <translation>&Longitud de máscara de red IPv6:</translation>
     </message>
     <message>
-        <source>Holds the host IPv6 network mask prefix length for this adapter if IPv6 is supported.</source>
+        <source>Holds the host IPv6 prefix length for this adapter if IPv6 is supported.</source>
         <translation>Muestra la longitud del prefijo de máscara de red IPv6 del anfitrión para este adaptador si IPv6 es soportado.</translation>
     </message>
     <message>
diff --git a/src/VBox/Frontends/VirtualBox/nls/VirtualBox_eu.ts b/src/VBox/Frontends/VirtualBox/nls/VirtualBox_eu.ts
index 37ae536..0a7fb69 100644
--- a/src/VBox/Frontends/VirtualBox/nls/VirtualBox_eu.ts
+++ b/src/VBox/Frontends/VirtualBox/nls/VirtualBox_eu.ts
@@ -3395,7 +3395,7 @@
     </message>
     <message>
         <location line="+9"/>
-        <source>Host interface <b>%1</b> does not currently have a valid IPv6 network mask prefix length.</source>
+        <source>Host interface <b>%1</b> does not currently have a valid IPv6 prefix length.</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
@@ -3467,7 +3467,7 @@
     </message>
     <message>
         <location line="+4"/>
-        <source>IPv6 Network Mask Length</source>
+        <source>IPv6 Prefix Length</source>
         <translation>IPv6 Sare Mozorro Luzera</translation>
     </message>
     <message>
@@ -3695,7 +3695,7 @@
         <translation type="obsolete">Hostalariaren IPv6 helbidea erakusten du egokitzaile honentzat IPv6 sostengatzen bada.</translation>
     </message>
     <message>
-        <source>IPv6 Network Mask &Length:</source>
+        <source>IPv6 Prefix &Length:</source>
         <translation type="obsolete">IPv6 Sare Mozorro &Luzera:</translation>
     </message>
     <message>
@@ -3785,12 +3785,12 @@
     </message>
     <message>
         <location line="+7"/>
-        <source>IPv6 Network Mask &Length:</source>
+        <source>IPv6 Prefix &Length:</source>
         <translation>IPv6 Sare Mozorro &Luzera:</translation>
     </message>
     <message>
         <location line="+19"/>
-        <source>Holds the host IPv6 network mask prefix length for this adapter if IPv6 is supported.</source>
+        <source>Holds the host IPv6 prefix length for this adapter if IPv6 is supported.</source>
         <translation>Hostalariaren IPv6 sare mozorro aurrizki luzera erakusten du egokitzaile honentzat IPv6 sostengatzen bada.</translation>
     </message>
     <message>
@@ -9404,7 +9404,7 @@
 <context>
     <name>UIMiniToolBar</name>
     <message>
-        <location filename="../src/widgets/UIMiniToolBar.cpp" line="+298"/>
+        <location filename="../src/widgets/UIMiniToolBar.cpp" line="+296"/>
         <source>Always show the toolbar</source>
         <translation>Betik erakutsi tresnabarra</translation>
     </message>
diff --git a/src/VBox/Frontends/VirtualBox/nls/VirtualBox_fa_IR.ts b/src/VBox/Frontends/VirtualBox/nls/VirtualBox_fa_IR.ts
index 2e6b36c..2040ba6 100644
--- a/src/VBox/Frontends/VirtualBox/nls/VirtualBox_fa_IR.ts
+++ b/src/VBox/Frontends/VirtualBox/nls/VirtualBox_fa_IR.ts
@@ -2811,7 +2811,7 @@
         <translation>آدرس IPv6</translation>
     </message>
     <message>
-        <source>IPv6 Network Mask Length</source>
+        <source>IPv6 Prefix Length</source>
         <translation>طول ماسک شبکه IPv6</translation>
     </message>
     <message>
@@ -3056,7 +3056,7 @@
         <translation>ویرایش شبکه فقط-میزبان انتخاب شده</translation>
     </message>
     <message>
-        <source>Host interface <b>%1</b> does not currently have a valid IPv6 network mask prefix length.</source>
+        <source>Host interface <b>%1</b> does not currently have a valid IPv6 prefix length.</source>
         <translation type="unfinished"></translation>
     </message>
 </context>
@@ -3103,11 +3103,11 @@
         <translation type="obsolete">آدرس میزبان IPv6 برای این آداپتور اگر IPv6 پشتیبانی شده باشد را نشان میدهد.</translation>
     </message>
     <message>
-        <source>IPv6 Network Mask &Length:</source>
+        <source>IPv6 Prefix &Length:</source>
         <translation type="obsolete">طول ماسک ش&بکه IPv6:</translation>
     </message>
     <message>
-        <source>Holds the host IPv6 network mask prefix length for this adapter if IPv6 is supported.</source>
+        <source>Holds the host IPv6 prefix length for this adapter if IPv6 is supported.</source>
         <translation type="obsolete">طول پیشوند ماسک شبکه میزبان IPv6 برای این آداپتور اگر  IPv6 پشتیبانی شده باشد را نشان میدهد.</translation>
     </message>
     <message>
@@ -3198,11 +3198,11 @@
         <translation>آدرس میزبان IPv6 برای این آداپتور اگر IPv6 پشتیبانی شده باشد را نشان میدهد.</translation>
     </message>
     <message>
-        <source>IPv6 Network Mask &Length:</source>
+        <source>IPv6 Prefix &Length:</source>
         <translation>طول ماسک ش&بکه IPv6:</translation>
     </message>
     <message>
-        <source>Holds the host IPv6 network mask prefix length for this adapter if IPv6 is supported.</source>
+        <source>Holds the host IPv6 prefix length for this adapter if IPv6 is supported.</source>
         <translation>طول پیشوند ماسک شبکه میزبان IPv6 برای این آداپتور اگر  IPv6 پشتیبانی شده باشد را نشان میدهد.</translation>
     </message>
     <message>
diff --git a/src/VBox/Frontends/VirtualBox/nls/VirtualBox_fi.ts b/src/VBox/Frontends/VirtualBox/nls/VirtualBox_fi.ts
index 50690d3..63c61d8 100644
--- a/src/VBox/Frontends/VirtualBox/nls/VirtualBox_fi.ts
+++ b/src/VBox/Frontends/VirtualBox/nls/VirtualBox_fi.ts
@@ -3267,7 +3267,7 @@ p, li { white-space: pre-wrap; }
         <translation>IPv6-osoite</translation>
     </message>
     <message>
-        <source>IPv6 Network Mask Length</source>
+        <source>IPv6 Prefix Length</source>
         <translation>IPv6-verkkopeitteen pituus</translation>
     </message>
     <message>
@@ -3505,7 +3505,7 @@ p, li { white-space: pre-wrap; }
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <source>Host interface <b>%1</b> does not currently have a valid IPv6 network mask prefix length.</source>
+        <source>Host interface <b>%1</b> does not currently have a valid IPv6 prefix length.</source>
         <translation type="unfinished"></translation>
     </message>
 </context>
@@ -3552,11 +3552,11 @@ p, li { white-space: pre-wrap; }
         <translation type="obsolete">Näyttää tämän sovittimen IPv6-osoitteen, jos IPv6 on tuettu.</translation>
     </message>
     <message>
-        <source>IPv6 Network Mask &Length:</source>
+        <source>IPv6 Prefix &Length:</source>
         <translation type="obsolete">IPv6-verkkopeitteen &pituus:</translation>
     </message>
     <message>
-        <source>Holds the host IPv6 network mask prefix length for this adapter if IPv6 is supported.</source>
+        <source>Holds the host IPv6 prefix length for this adapter if IPv6 is supported.</source>
         <translation type="obsolete">Näyttää tämän sovittimen IPv6-verkkopeitteen pituuden, jos IPv6 on tuettu.</translation>
     </message>
     <message>
@@ -3647,11 +3647,11 @@ p, li { white-space: pre-wrap; }
         <translation type="unfinished">Näyttää tämän sovittimen IPv6-osoitteen, jos IPv6 on tuettu.</translation>
     </message>
     <message>
-        <source>IPv6 Network Mask &Length:</source>
+        <source>IPv6 Prefix &Length:</source>
         <translation type="unfinished">IPv6-verkkopeitteen &pituus:</translation>
     </message>
     <message>
-        <source>Holds the host IPv6 network mask prefix length for this adapter if IPv6 is supported.</source>
+        <source>Holds the host IPv6 prefix length for this adapter if IPv6 is supported.</source>
         <translation type="unfinished">Näyttää tämän sovittimen IPv6-verkkopeitteen pituuden, jos IPv6 on tuettu.</translation>
     </message>
     <message>
diff --git a/src/VBox/Frontends/VirtualBox/nls/VirtualBox_fr.ts b/src/VBox/Frontends/VirtualBox/nls/VirtualBox_fr.ts
index 5895af3..cbf9c08 100644
--- a/src/VBox/Frontends/VirtualBox/nls/VirtualBox_fr.ts
+++ b/src/VBox/Frontends/VirtualBox/nls/VirtualBox_fr.ts
@@ -3860,7 +3860,7 @@
         <translation>Adresse IPv6</translation>
     </message>
     <message>
-        <source>IPv6 Network Mask Length</source>
+        <source>IPv6 Prefix Length</source>
         <translation>Longueur du masque réseau IPv6</translation>
     </message>
     <message>
@@ -4092,7 +4092,7 @@
         <translation>Édite le réseau privé hôte sélectionné.</translation>
     </message>
     <message>
-        <source>Host interface <b>%1</b> does not currently have a valid IPv6 network mask prefix length.</source>
+        <source>Host interface <b>%1</b> does not currently have a valid IPv6 prefix length.</source>
         <translation type="unfinished"></translation>
     </message>
 </context>
@@ -4163,11 +4163,11 @@
         <translation type="obsolete">Affiche l'adresse IPv6 hôte pour cette interface si l'IPv6 est supporté.</translation>
     </message>
     <message>
-        <source>IPv6 Network Mask &Length:</source>
+        <source>IPv6 Prefix &Length:</source>
         <translation type="obsolete">&Longueur du masque réseau IPv6 :</translation>
     </message>
     <message>
-        <source>Holds the host IPv6 network mask prefix length for this adapter if IPv6 is supported.</source>
+        <source>Holds the host IPv6 prefix length for this adapter if IPv6 is supported.</source>
         <translation type="obsolete">Affiche la longueur du préfixe du masque réseau IPv6 pour cette interface si l'IPv6 est supporté.</translation>
     </message>
     <message>
@@ -4234,11 +4234,11 @@
         <translation>Affiche l'adresse IPv6 hôte pour cette carte si l'IPv6 est supporté.</translation>
     </message>
     <message>
-        <source>IPv6 Network Mask &Length:</source>
+        <source>IPv6 Prefix &Length:</source>
         <translation>&Longueur du masque réseau IPv6 :</translation>
     </message>
     <message>
-        <source>Holds the host IPv6 network mask prefix length for this adapter if IPv6 is supported.</source>
+        <source>Holds the host IPv6 prefix length for this adapter if IPv6 is supported.</source>
         <translation>Affiche la longueur du préfixe du masque réseau IPv6 pour cette carte si l'IPv6 est supporté.</translation>
     </message>
     <message>
diff --git a/src/VBox/Frontends/VirtualBox/nls/VirtualBox_gl_ES.ts b/src/VBox/Frontends/VirtualBox/nls/VirtualBox_gl_ES.ts
index aaab468..c975af0 100644
--- a/src/VBox/Frontends/VirtualBox/nls/VirtualBox_gl_ES.ts
+++ b/src/VBox/Frontends/VirtualBox/nls/VirtualBox_gl_ES.ts
@@ -3449,7 +3449,7 @@ p, li { white-space: pre-wrap; }
         <translation>Enderezo IPv6</translation>
     </message>
     <message>
-        <source>IPv6 Network Mask Length</source>
+        <source>IPv6 Prefix Length</source>
         <translation>Lonxitude da máscara de rede IPv6</translation>
     </message>
     <message>
@@ -3687,7 +3687,7 @@ p, li { white-space: pre-wrap; }
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <source>Host interface <b>%1</b> does not currently have a valid IPv6 network mask prefix length.</source>
+        <source>Host interface <b>%1</b> does not currently have a valid IPv6 prefix length.</source>
         <translation type="unfinished"></translation>
     </message>
 </context>
@@ -3734,11 +3734,11 @@ p, li { white-space: pre-wrap; }
         <translation type="obsolete">Mostrar o enderezo IPv6 do equipo para este adaptador de se permitir IPv6.</translation>
     </message>
     <message>
-        <source>IPv6 Network Mask &Length:</source>
+        <source>IPv6 Prefix &Length:</source>
         <translation type="obsolete">&Lonxitude da máscara de rede IPv6:</translation>
     </message>
     <message>
-        <source>Holds the host IPv6 network mask prefix length for this adapter if IPv6 is supported.</source>
+        <source>Holds the host IPv6 prefix length for this adapter if IPv6 is supported.</source>
         <translation type="obsolete">Mostra a lonxitude do prefixo da máscara de rede IPv6 do anfitrión para este adaptador de se permitir IPv6.</translation>
     </message>
     <message>
@@ -3829,11 +3829,11 @@ p, li { white-space: pre-wrap; }
         <translation type="unfinished">Mostrar o enderezo IPv6 do equipo para este adaptador de se permitir IPv6.</translation>
     </message>
     <message>
-        <source>IPv6 Network Mask &Length:</source>
+        <source>IPv6 Prefix &Length:</source>
         <translation type="unfinished">&Lonxitude da máscara de rede IPv6:</translation>
     </message>
     <message>
-        <source>Holds the host IPv6 network mask prefix length for this adapter if IPv6 is supported.</source>
+        <source>Holds the host IPv6 prefix length for this adapter if IPv6 is supported.</source>
         <translation type="unfinished">Mostra a lonxitude do prefixo da máscara de rede IPv6 do anfitrión para este adaptador de se permitir IPv6.</translation>
     </message>
     <message>
diff --git a/src/VBox/Frontends/VirtualBox/nls/VirtualBox_he.ts b/src/VBox/Frontends/VirtualBox/nls/VirtualBox_he.ts
index 87002ab..ef1084f 100644
--- a/src/VBox/Frontends/VirtualBox/nls/VirtualBox_he.ts
+++ b/src/VBox/Frontends/VirtualBox/nls/VirtualBox_he.ts
@@ -2201,7 +2201,7 @@
         <translation>כתובת IPv6</translation>
     </message>
     <message>
-        <source>IPv6 Network Mask Length</source>
+        <source>IPv6 Prefix Length</source>
         <translation>אורך מסיכת רשת IPv6</translation>
     </message>
     <message>
@@ -2382,7 +2382,7 @@
         <translation type="vanished">&ערוך רשת NAT</translation>
     </message>
     <message>
-        <source>Host interface <b>%1</b> does not currently have a valid IPv6 network mask prefix length.</source>
+        <source>Host interface <b>%1</b> does not currently have a valid IPv6 prefix length.</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
@@ -2473,11 +2473,11 @@
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <source>IPv6 Network Mask &Length:</source>
+        <source>IPv6 Prefix &Length:</source>
         <translation>&אורך מסיכת רשת IPv6:</translation>
     </message>
     <message>
-        <source>Holds the host IPv6 network mask prefix length for this adapter if IPv6 is supported.</source>
+        <source>Holds the host IPv6 prefix length for this adapter if IPv6 is supported.</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
diff --git a/src/VBox/Frontends/VirtualBox/nls/VirtualBox_hu.ts b/src/VBox/Frontends/VirtualBox/nls/VirtualBox_hu.ts
index 6a3ed73..a4297d5 100644
--- a/src/VBox/Frontends/VirtualBox/nls/VirtualBox_hu.ts
+++ b/src/VBox/Frontends/VirtualBox/nls/VirtualBox_hu.ts
@@ -4306,7 +4306,7 @@ p, li { white-space: pre-wrap; }
         <translation>IPv6 cím</translation>
     </message>
     <message>
-        <source>IPv6 Network Mask Length</source>
+        <source>IPv6 Prefix Length</source>
         <translation>IPv6 hálózati maszk hossza</translation>
     </message>
     <message>
@@ -4560,7 +4560,7 @@ p, li { white-space: pre-wrap; }
         <translation>A kiválasztott host-only hálózat szerkesztése.</translation>
     </message>
     <message>
-        <source>Host interface <b>%1</b> does not currently have a valid IPv6 network mask prefix length.</source>
+        <source>Host interface <b>%1</b> does not currently have a valid IPv6 prefix length.</source>
         <translation type="unfinished"></translation>
     </message>
 </context>
@@ -4607,11 +4607,11 @@ p, li { white-space: pre-wrap; }
         <translation type="obsolete">A gazda IPv6 címe ehhez a kártyához, ha az IPv6 támogatott.</translation>
     </message>
     <message>
-        <source>IPv6 Network Mask &Length:</source>
+        <source>IPv6 Prefix &Length:</source>
         <translation type="obsolete">IPv6 há&lózati maszk hossza:</translation>
     </message>
     <message>
-        <source>Holds the host IPv6 network mask prefix length for this adapter if IPv6 is supported.</source>
+        <source>Holds the host IPv6 prefix length for this adapter if IPv6 is supported.</source>
         <translation type="obsolete">A gazda IPv6 hálózati maszkjának hossza ehhez a kártyához, ha IPv6 támogatott.</translation>
     </message>
     <message>
@@ -4702,11 +4702,11 @@ p, li { white-space: pre-wrap; }
         <translation>A gazda IPv6 címe ehhez a kártyához, ha az IPv6 támogatott.</translation>
     </message>
     <message>
-        <source>IPv6 Network Mask &Length:</source>
+        <source>IPv6 Prefix &Length:</source>
         <translation>IPv6 há&lózati maszk hossza:</translation>
     </message>
     <message>
-        <source>Holds the host IPv6 network mask prefix length for this adapter if IPv6 is supported.</source>
+        <source>Holds the host IPv6 prefix length for this adapter if IPv6 is supported.</source>
         <translation>A gazda IPv6 hálózati maszkjának hossza ehhez a kártyához, ha IPv6 támogatott.</translation>
     </message>
     <message>
diff --git a/src/VBox/Frontends/VirtualBox/nls/VirtualBox_id.ts b/src/VBox/Frontends/VirtualBox/nls/VirtualBox_id.ts
index af657ce..6e3a97b 100644
--- a/src/VBox/Frontends/VirtualBox/nls/VirtualBox_id.ts
+++ b/src/VBox/Frontends/VirtualBox/nls/VirtualBox_id.ts
@@ -3848,7 +3848,7 @@
         <translation>Alamat IPv6</translation>
     </message>
     <message>
-        <source>IPv6 Network Mask Length</source>
+        <source>IPv6 Prefix Length</source>
         <translation>Panjang Mask Jaringan IPv6</translation>
     </message>
     <message>
@@ -4093,7 +4093,7 @@
         <translation>Menyunting jaringan hanya-host yang dipilih.</translation>
     </message>
     <message>
-        <source>Host interface <b>%1</b> does not currently have a valid IPv6 network mask prefix length.</source>
+        <source>Host interface <b>%1</b> does not currently have a valid IPv6 prefix length.</source>
         <translation>Antar muka host <b>%1</b> saat ini tidak memiliki panjang prefiks mask jaringan IPv6 yang valid.</translation>
     </message>
 </context>
@@ -4140,11 +4140,11 @@
         <translation type="obsolete">Tampilkan alamat IPv6 host bagi adaptor ini bila IPv6 didukung.</translation>
     </message>
     <message>
-        <source>IPv6 Network Mask &Length:</source>
+        <source>IPv6 Prefix &Length:</source>
         <translation type="obsolete">&Panjang Mask Jaringan IPv6:</translation>
     </message>
     <message>
-        <source>Holds the host IPv6 network mask prefix length for this adapter if IPv6 is supported.</source>
+        <source>Holds the host IPv6 prefix length for this adapter if IPv6 is supported.</source>
         <translation type="obsolete">Tampilkan panjang prefiks mask jaringan IPv6 host bagi adaptor ini bila IPv6 didukung.</translation>
     </message>
     <message>
@@ -4235,11 +4235,11 @@
         <translation>Menyimpan alamat IPv6 host bagi adaptor ini bila IPv6 didukung.</translation>
     </message>
     <message>
-        <source>IPv6 Network Mask &Length:</source>
+        <source>IPv6 Prefix &Length:</source>
         <translation>&Panjang Mask Jaringan IPv6:</translation>
     </message>
     <message>
-        <source>Holds the host IPv6 network mask prefix length for this adapter if IPv6 is supported.</source>
+        <source>Holds the host IPv6 prefix length for this adapter if IPv6 is supported.</source>
         <translation>Menyimpan panjang prefiks mask jaringan IPv6 host bagi adaptor ini bila IPv6 didukung.</translation>
     </message>
     <message>
diff --git a/src/VBox/Frontends/VirtualBox/nls/VirtualBox_it.ts b/src/VBox/Frontends/VirtualBox/nls/VirtualBox_it.ts
index f5879c9..e57bd42 100644
--- a/src/VBox/Frontends/VirtualBox/nls/VirtualBox_it.ts
+++ b/src/VBox/Frontends/VirtualBox/nls/VirtualBox_it.ts
@@ -4764,7 +4764,7 @@ p, li { white-space: pre-wrap; }
         <translation>Indirizzo IPv6</translation>
     </message>
     <message>
-        <source>IPv6 Network Mask Length</source>
+        <source>IPv6 Prefix Length</source>
         <translation>Lunghezza della maschera di rete IPv6</translation>
     </message>
     <message>
@@ -5023,7 +5023,7 @@ p, li { white-space: pre-wrap; }
         <translation>Modifica la rete solo host selezionata.</translation>
     </message>
     <message>
-        <source>Host interface <b>%1</b> does not currently have a valid IPv6 network mask prefix length.</source>
+        <source>Host interface <b>%1</b> does not currently have a valid IPv6 prefix length.</source>
         <translation>L'interfaccia host <b>%1</b> non ha attualmente una lunghezza del prefisso della maschera di rete IPv6 valida.</translation>
     </message>
 </context>
@@ -5070,11 +5070,11 @@ p, li { white-space: pre-wrap; }
         <translation type="obsolete">Visualizza l'indirizzo host IPv6 per questa scheda se l'IPv6 è supportato.</translation>
     </message>
     <message>
-        <source>IPv6 Network Mask &Length:</source>
+        <source>IPv6 Prefix &Length:</source>
         <translation type="obsolete">&Lunghezza maschera di rete IPv6:</translation>
     </message>
     <message>
-        <source>Holds the host IPv6 network mask prefix length for this adapter if IPv6 is supported.</source>
+        <source>Holds the host IPv6 prefix length for this adapter if IPv6 is supported.</source>
         <translation type="obsolete">Visualizza la lunghezza del prefisso della maschera di rete host IPv6 per questa scheda se l'IPv6 è supportato.</translation>
     </message>
     <message>
@@ -5165,11 +5165,11 @@ p, li { white-space: pre-wrap; }
         <translation>Contiene l'indirizzo IPv6 dell'host per questa scheda se l'IPv6 è supportato.</translation>
     </message>
     <message>
-        <source>IPv6 Network Mask &Length:</source>
+        <source>IPv6 Prefix &Length:</source>
         <translation>&Lunghezza maschera di rete IPv6:</translation>
     </message>
     <message>
-        <source>Holds the host IPv6 network mask prefix length for this adapter if IPv6 is supported.</source>
+        <source>Holds the host IPv6 prefix length for this adapter if IPv6 is supported.</source>
         <translation>Contiene la lunghezza del prefisso della maschera di rete IPv6 dell'host per questa scheda se l'IPv6 è supportato.</translation>
     </message>
     <message>
diff --git a/src/VBox/Frontends/VirtualBox/nls/VirtualBox_ja.ts b/src/VBox/Frontends/VirtualBox/nls/VirtualBox_ja.ts
index 567f3b9..b098810 100644
--- a/src/VBox/Frontends/VirtualBox/nls/VirtualBox_ja.ts
+++ b/src/VBox/Frontends/VirtualBox/nls/VirtualBox_ja.ts
@@ -4362,7 +4362,7 @@ p, li { white-space: pre-wrap; }
         <translation>IPv6 アドレス</translation>
     </message>
     <message>
-        <source>IPv6 Network Mask Length</source>
+        <source>IPv6 Prefix Length</source>
         <translation>IPv6 ネットマスク</translation>
     </message>
     <message>
@@ -4524,7 +4524,7 @@ p, li { white-space: pre-wrap; }
         <translation>選択したホストオンリーネットワークを編集します。</translation>
     </message>
     <message>
-        <source>Host interface <b>%1</b> does not currently have a valid IPv6 network mask prefix length.</source>
+        <source>Host interface <b>%1</b> does not currently have a valid IPv6 prefix length.</source>
         <translation>ホストインターフェース <b>%1</b> は正しいIPv6ネットワークマスクプレフィックス長ではありません。</translation>
     </message>
 </context>
@@ -4571,11 +4571,11 @@ p, li { white-space: pre-wrap; }
         <translation type="obsolete">IPv6がサポートされるとき、このアダプターのホスト IPv6 アドレスを指定します。</translation>
     </message>
     <message>
-        <source>IPv6 Network Mask &Length:</source>
+        <source>IPv6 Prefix &Length:</source>
         <translation type="obsolete">IPv6 ネットマスク長(&L):</translation>
     </message>
     <message>
-        <source>Holds the host IPv6 network mask prefix length for this adapter if IPv6 is supported.</source>
+        <source>Holds the host IPv6 prefix length for this adapter if IPv6 is supported.</source>
         <translation type="obsolete">IPv6がサポートされるとき、このアダプターのホスト IPv6 ネットマスクのプレフィックス長を指定します。</translation>
     </message>
     <message>
@@ -4666,11 +4666,11 @@ p, li { white-space: pre-wrap; }
         <translation>IPv6がサポートされるとき、このアダプターのホスト IPv6 アドレスを指定します。</translation>
     </message>
     <message>
-        <source>IPv6 Network Mask &Length:</source>
+        <source>IPv6 Prefix &Length:</source>
         <translation>IPv6 ネットマスク長(&L):</translation>
     </message>
     <message>
-        <source>Holds the host IPv6 network mask prefix length for this adapter if IPv6 is supported.</source>
+        <source>Holds the host IPv6 prefix length for this adapter if IPv6 is supported.</source>
         <translation>IPv6がサポートされるとき、このアダプターのホスト IPv6 ネットマスクのプレフィックス長を指定します。</translation>
     </message>
     <message>
diff --git a/src/VBox/Frontends/VirtualBox/nls/VirtualBox_km_KH.ts b/src/VBox/Frontends/VirtualBox/nls/VirtualBox_km_KH.ts
index 2f08a2b..49ee2a8 100644
--- a/src/VBox/Frontends/VirtualBox/nls/VirtualBox_km_KH.ts
+++ b/src/VBox/Frontends/VirtualBox/nls/VirtualBox_km_KH.ts
@@ -3266,7 +3266,7 @@ mask</comment>
         <translation>អាសយ​ដ្ឋាន​ IPv6</translation>
     </message>
     <message>
-        <source>IPv6 Network Mask Length</source>
+        <source>IPv6 Prefix Length</source>
         <translation>ប្រវែង​របាំង​បណ្តាញ​ IPv6</translation>
     </message>
     <message>
@@ -3574,7 +3574,7 @@ creating/removing host-only network</comment>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <source>Host interface <b>%1</b> does not currently have a valid IPv6 network mask prefix length.</source>
+        <source>Host interface <b>%1</b> does not currently have a valid IPv6 prefix length.</source>
         <translation type="unfinished"></translation>
     </message>
 </context>
@@ -3621,11 +3621,11 @@ creating/removing host-only network</comment>
         <translation type="obsolete">បង្ហាញ​​អា​សយដ្ឋាន​ម៉ាស៊ីន​ IPv6 សម្រាប់​​អាដាប់​ទ័រ​​នេះ ​ប្រ​សិន​បើ​​ IPv6 ត្រូវ​បាន​គាំ​ទ្រ ។</translation>
     </message>
     <message>
-        <source>IPv6 Network Mask &Length:</source>
+        <source>IPv6 Prefix &Length:</source>
         <translation type="obsolete">ប្រ​វែង​របាំង​បណ្តាញ​ IPv6 ៖</translation>
     </message>
     <message>
-        <source>Holds the host IPv6 network mask prefix length for this adapter if IPv6 is supported.</source>
+        <source>Holds the host IPv6 prefix length for this adapter if IPv6 is supported.</source>
         <translation type="obsolete">បង្ហាញ​ប្រ​វែង​​បុព្វបទ​របាំង​បណ្តាញ​ម៉ាស៊ីន​ IPv6​ សម្រាប់​​អាដាប់​ទ័រ​​នេះ ​ប្រ​សិន​បើ​ IPv6 ត្រូវ​បាន​គាំ​ទ្រ​ ។</translation>
     </message>
     <message>
@@ -3716,11 +3716,11 @@ creating/removing host-only network</comment>
         <translation type="unfinished">បង្ហាញ​​អា​សយដ្ឋាន​ម៉ាស៊ីន​ IPv6 សម្រាប់​​អាដាប់​ទ័រ​​នេះ ​ប្រ​សិន​បើ​​ IPv6 ត្រូវ​បាន​គាំ​ទ្រ ។</translation>
     </message>
     <message>
-        <source>IPv6 Network Mask &Length:</source>
+        <source>IPv6 Prefix &Length:</source>
         <translation type="unfinished">ប្រ​វែង​របាំង​បណ្តាញ​ IPv6 ៖</translation>
     </message>
     <message>
-        <source>Holds the host IPv6 network mask prefix length for this adapter if IPv6 is supported.</source>
+        <source>Holds the host IPv6 prefix length for this adapter if IPv6 is supported.</source>
         <translation type="unfinished">បង្ហាញ​ប្រ​វែង​​បុព្វបទ​របាំង​បណ្តាញ​ម៉ាស៊ីន​ IPv6​ សម្រាប់​​អាដាប់​ទ័រ​​នេះ ​ប្រ​សិន​បើ​ IPv6 ត្រូវ​បាន​គាំ​ទ្រ​ ។</translation>
     </message>
     <message>
diff --git a/src/VBox/Frontends/VirtualBox/nls/VirtualBox_ko.ts b/src/VBox/Frontends/VirtualBox/nls/VirtualBox_ko.ts
index 0f5dc3c..d2d3d82 100644
--- a/src/VBox/Frontends/VirtualBox/nls/VirtualBox_ko.ts
+++ b/src/VBox/Frontends/VirtualBox/nls/VirtualBox_ko.ts
@@ -4314,7 +4314,7 @@ p, li { white-space: pre-wrap; }
         <translation>IPv6 주소</translation>
     </message>
     <message>
-        <source>IPv6 Network Mask Length</source>
+        <source>IPv6 Prefix Length</source>
         <translation>IPv6 네트워크 마스크 길이</translation>
     </message>
     <message>
@@ -4568,7 +4568,7 @@ p, li { white-space: pre-wrap; }
         <translation>선택한 호스트 전용 네트워크를 편집합니다.</translation>
     </message>
     <message>
-        <source>Host interface <b>%1</b> does not currently have a valid IPv6 network mask prefix length.</source>
+        <source>Host interface <b>%1</b> does not currently have a valid IPv6 prefix length.</source>
         <translation>호스트 인터페이스 <b>%1</b>에 올바른 IPv6 네트워크 마스크 접두사 길이가 없습니다.</translation>
     </message>
 </context>
@@ -4615,11 +4615,11 @@ p, li { white-space: pre-wrap; }
         <translation type="obsolete">IPv6을 지원하는 경우 이 어댑터의 호스트 IPv6 주소를 표시합니다.</translation>
     </message>
     <message>
-        <source>IPv6 Network Mask &Length:</source>
+        <source>IPv6 Prefix &Length:</source>
         <translation type="obsolete">IPv6 네트워크 마스크 길이(&L):</translation>
     </message>
     <message>
-        <source>Holds the host IPv6 network mask prefix length for this adapter if IPv6 is supported.</source>
+        <source>Holds the host IPv6 prefix length for this adapter if IPv6 is supported.</source>
         <translation type="obsolete">IPv6을 지원하는 경우 이 어댑터의 호스트 IPv6 네트워크 마스크 접두사를 표시합니다.</translation>
     </message>
     <message>
@@ -4710,11 +4710,11 @@ p, li { white-space: pre-wrap; }
         <translation>IPv6을 지원하는 경우 이 어댑터의 호스트 IPv6 주소를 표시합니다.</translation>
     </message>
     <message>
-        <source>IPv6 Network Mask &Length:</source>
+        <source>IPv6 Prefix &Length:</source>
         <translation>IPv6 네트워크 마스크 길이(&L):</translation>
     </message>
     <message>
-        <source>Holds the host IPv6 network mask prefix length for this adapter if IPv6 is supported.</source>
+        <source>Holds the host IPv6 prefix length for this adapter if IPv6 is supported.</source>
         <translation>IPv6을 지원하는 경우 이 어댑터의 호스트 IPv6 네트워크 마스크 접두사를 표시합니다.</translation>
     </message>
     <message>
diff --git a/src/VBox/Frontends/VirtualBox/nls/VirtualBox_lt.ts b/src/VBox/Frontends/VirtualBox/nls/VirtualBox_lt.ts
index 1c8f4eb..2c432d6 100644
--- a/src/VBox/Frontends/VirtualBox/nls/VirtualBox_lt.ts
+++ b/src/VBox/Frontends/VirtualBox/nls/VirtualBox_lt.ts
@@ -3765,7 +3765,7 @@
         <translation>IPv6 adresas</translation>
     </message>
     <message>
-        <source>IPv6 Network Mask Length</source>
+        <source>IPv6 Prefix Length</source>
         <translation>IPv6 tinklo kaukės ilgis</translation>
     </message>
     <message>
@@ -3986,7 +3986,7 @@
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <source>Host interface <b>%1</b> does not currently have a valid IPv6 network mask prefix length.</source>
+        <source>Host interface <b>%1</b> does not currently have a valid IPv6 prefix length.</source>
         <translation type="unfinished"></translation>
     </message>
 </context>
@@ -4033,11 +4033,11 @@
         <translation type="obsolete">Rodo šio pagrindinio kompiuterio IPv4 adresą šiai plokštei, jei palaikomas IPv6.</translation>
     </message>
     <message>
-        <source>IPv6 Network Mask &Length:</source>
+        <source>IPv6 Prefix &Length:</source>
         <translation type="obsolete">IPv6 tinklo kaukės i&lgis:</translation>
     </message>
     <message>
-        <source>Holds the host IPv6 network mask prefix length for this adapter if IPv6 is supported.</source>
+        <source>Holds the host IPv6 prefix length for this adapter if IPv6 is supported.</source>
         <translation type="obsolete">Rodo šio pagrindinio kompiuterio IPv4 tinklo kaukės prefikso ilgį šiai plokštei, jei palaikomas IPv6.</translation>
     </message>
     <message>
@@ -4128,11 +4128,11 @@
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <source>IPv6 Network Mask &Length:</source>
+        <source>IPv6 Prefix &Length:</source>
         <translation type="unfinished">IPv6 tinklo kaukės i&lgis:</translation>
     </message>
     <message>
-        <source>Holds the host IPv6 network mask prefix length for this adapter if IPv6 is supported.</source>
+        <source>Holds the host IPv6 prefix length for this adapter if IPv6 is supported.</source>
         <translation type="unfinished">Rodo šio pagrindinio kompiuterio IPv4 tinklo kaukės prefikso ilgį šiai plokštei, jei palaikomas IPv6.</translation>
     </message>
     <message>
@@ -12180,7 +12180,7 @@
         <translation type="obsolete">IPv6 adresas</translation>
     </message>
     <message>
-        <source>IPv6 Network Mask Length</source>
+        <source>IPv6 Prefix Length</source>
         <translation type="obsolete">IPv6 tinklo kaukės ilgis</translation>
     </message>
     <message>
@@ -12302,11 +12302,11 @@
 IPv6.</translation>
     </message>
     <message>
-        <source>IPv6 Network Mask &Length:</source>
+        <source>IPv6 Prefix &Length:</source>
         <translation type="obsolete">IPv6 tinklo kaukės i&lgis:</translation>
     </message>
     <message>
-        <source>Holds the host IPv6 network mask prefix length for this adapter if IPv6 is supported.</source>
+        <source>Holds the host IPv6 prefix length for this adapter if IPv6 is supported.</source>
         <translation type="obsolete">Rodo šio pagrindinio kompiuterio IPv4 tinklo kaukės prefikso ilgį šiai plokštei, jei palaikomas IPv6.</translation>
     </message>
     <message>
diff --git a/src/VBox/Frontends/VirtualBox/nls/VirtualBox_nl.ts b/src/VBox/Frontends/VirtualBox/nls/VirtualBox_nl.ts
index 99d9f3c..fe44ae5 100644
--- a/src/VBox/Frontends/VirtualBox/nls/VirtualBox_nl.ts
+++ b/src/VBox/Frontends/VirtualBox/nls/VirtualBox_nl.ts
@@ -3787,7 +3787,7 @@
         <translation>IPv6-adres</translation>
     </message>
     <message>
-        <source>IPv6 Network Mask Length</source>
+        <source>IPv6 Prefix Length</source>
         <translation>Lengte IPv6-netmasker</translation>
     </message>
     <message>
@@ -4032,7 +4032,7 @@
         <translation>Bewerkt geselecteerd host only netwerk.</translation>
     </message>
     <message>
-        <source>Host interface <b>%1</b> does not currently have a valid IPv6 network mask prefix length.</source>
+        <source>Host interface <b>%1</b> does not currently have a valid IPv6 prefix length.</source>
         <translation>Hostinterface <b>%1</b> heeft op dit moment geen geldige IPv4-netwerkmaskerprefixlengte.</translation>
     </message>
 </context>
@@ -4079,11 +4079,11 @@
         <translation type="obsolete">Toont het host-IPv6-adres voor deze adapter indien IPv6 ondersteund wordt.</translation>
     </message>
     <message>
-        <source>IPv6 Network Mask &Length:</source>
+        <source>IPv6 Prefix &Length:</source>
         <translation type="obsolete">&Lengte IPv6-netmasker:</translation>
     </message>
     <message>
-        <source>Holds the host IPv6 network mask prefix length for this adapter if IPv6 is supported.</source>
+        <source>Holds the host IPv6 prefix length for this adapter if IPv6 is supported.</source>
         <translation type="obsolete">Toont de prefixlengte van het host-IPv6-netmasker voor deze adapter indien IPv6 ondersteund wordt.</translation>
     </message>
     <message>
@@ -4174,11 +4174,11 @@
         <translation>Toont het host-IPv6-adres voor deze adapter indien IPv6 ondersteund wordt.</translation>
     </message>
     <message>
-        <source>IPv6 Network Mask &Length:</source>
+        <source>IPv6 Prefix &Length:</source>
         <translation>&Lengte IPv6-netwerkmasker:</translation>
     </message>
     <message>
-        <source>Holds the host IPv6 network mask prefix length for this adapter if IPv6 is supported.</source>
+        <source>Holds the host IPv6 prefix length for this adapter if IPv6 is supported.</source>
         <translation>Toont de prefixlengte van het host-IPv6-netwerkmasker voor deze adapter indien IPv6 ondersteund wordt.</translation>
     </message>
     <message>
diff --git a/src/VBox/Frontends/VirtualBox/nls/VirtualBox_pl.ts b/src/VBox/Frontends/VirtualBox/nls/VirtualBox_pl.ts
index 9d68dda..f0a5330 100644
--- a/src/VBox/Frontends/VirtualBox/nls/VirtualBox_pl.ts
+++ b/src/VBox/Frontends/VirtualBox/nls/VirtualBox_pl.ts
@@ -2056,7 +2056,7 @@
     </message>
     <message>
         <source>Verifying %1...</source>
-        <translation type="unfinished"></translation>
+        <translation>Weryfikowanie %1...</translation>
     </message>
 </context>
 <context>
@@ -3683,7 +3683,7 @@ p, li { white-space: pre-wrap; }
         <translation>Adres IPv6</translation>
     </message>
     <message>
-        <source>IPv6 Network Mask Length</source>
+        <source>IPv6 Prefix Length</source>
         <translation>Długość maski sieci IPv6</translation>
     </message>
     <message>
@@ -3921,7 +3921,7 @@ p, li { white-space: pre-wrap; }
         <translation>Edytuje wybraną sieć izolowaną.</translation>
     </message>
     <message>
-        <source>Host interface <b>%1</b> does not currently have a valid IPv6 network mask prefix length.</source>
+        <source>Host interface <b>%1</b> does not currently have a valid IPv6 prefix length.</source>
         <translation>Interfejs gospodarza <b>%1</b> nie posiada obecnie ważnego prefiksu maski sieci IPv6.</translation>
     </message>
 </context>
@@ -3968,11 +3968,11 @@ p, li { white-space: pre-wrap; }
         <translation type="obsolete">Przechowuje adres IPv6 gospodarza dla tej karty, jeśli IPv6 jest dostępne.</translation>
     </message>
     <message>
-        <source>IPv6 Network Mask &Length:</source>
+        <source>IPv6 Prefix &Length:</source>
         <translation type="obsolete">Dł&ugość maski sieci IPv6:</translation>
     </message>
     <message>
-        <source>Holds the host IPv6 network mask prefix length for this adapter if IPv6 is supported.</source>
+        <source>Holds the host IPv6 prefix length for this adapter if IPv6 is supported.</source>
         <translation type="obsolete">Przechowuje długość prefiksu maski sieci IPv6 gospodarza dla tej karty, jeśli IPv6 jest dostępne.</translation>
     </message>
     <message>
@@ -4063,11 +4063,11 @@ p, li { white-space: pre-wrap; }
         <translation>Przechowuje adres IPv6 gospodarza dla tej karty, jeśli IPv6 jest dostępne.</translation>
     </message>
     <message>
-        <source>IPv6 Network Mask &Length:</source>
+        <source>IPv6 Prefix &Length:</source>
         <translation>Dł&ugość maski sieci IPv6:</translation>
     </message>
     <message>
-        <source>Holds the host IPv6 network mask prefix length for this adapter if IPv6 is supported.</source>
+        <source>Holds the host IPv6 prefix length for this adapter if IPv6 is supported.</source>
         <translation>Przechowuje długość prefiksu maski sieci IPv6 gospodarza dla tej karty, jeśli IPv6 jest obsługiwane.</translation>
     </message>
     <message>
@@ -6734,11 +6734,11 @@ p, li { white-space: pre-wrap; }
     </message>
     <message>
         <source>When checked, the virtual machine will assume that the pipe or socket specified in the <b>Path/Address</b> field exists and try to use it. Otherwise, the pipe or socket will be created by the virtual machine when it starts.</source>
-        <translation>Po zaznaczeniu tej opcji, maszyna wirtualna będzie zakładać, że rura lub gniazdo określone w  <b>Ścieżka/Adres</b> istnieje i spróbuje je użyć. W przeciwnym wypadku, rura lub gniazdo zostanie utworzone przez wirtualną maszynę, gdy wystartuje.</translation>
+        <translation>Po zaznaczeniu tej opcji, maszyna wirtualna będzie zakładać, że łącze komunikacyjne lub gniazdo określone w  <b>Ścieżka/Adres</b> istnieje i spróbuje je użyć. W przeciwnym wypadku, łącze komunikacyjne lub gniazdo zostanie utworzone przez wirtualną maszynę, gdy wystartuje.</translation>
     </message>
     <message>
         <source>&Connect to existing pipe/socket</source>
-        <translation>&Podłącz do istniejącej rury/gniazda</translation>
+        <translation>&Podłącz do istniejącego łącza komunikacyjnego/gniazda</translation>
     </message>
     <message>
         <source>&Path/Address:</source>
@@ -6746,7 +6746,8 @@ p, li { white-space: pre-wrap; }
     </message>
     <message>
         <source><p>In <b>Host Pipe</b> mode: Holds the path to the serial port's pipe on the host. Examples: "\\.\pipe\myvbox" or "/tmp/myvbox", for Windows and UNIX-like systems respectively.</p><p>In <b>Host Device</b> mode: Holds the host serial device name. Examples: "COM1" or "/dev/ttyS0".</p><p>In <b>Raw File</b> mode: Holds the file-path on the host system, where the seri [...]
-        <translation><p>W <b>trybie Host Pipe</b>: przechowuje ścieżkę do portu szeregowego rury na hoście. Przykładowo: "\\.\pipe\myvbox" lub "/tmp/myvbox", odpowiednio dla systemów Windows i UNIX.</p><p>W <b>trybie urządzenia gospodarza</b>: przechowuje seryjną nazwę gospodarza. Przykładowo: "COM1" lub "/dev/ttyS0".</p><p>W <b>trybie plików RAW</b>: przechowuje ścieżkę do pliku w s [...]
+        <translatorcomment>pipe - łącze komunikacyjne</translatorcomment>
+        <translation><p>W <b>trybie Łącze komunikacyjne gospodarza</b>: przechowuje ścieżkę do portu szeregowego łącza komunikacyjnego na hoście. Przykładowo: "\\.\pipe\myvbox" lub "/tmp/myvbox", odpowiednio dla systemów Windows i UNIX.</p><p>W <b>trybie urządzenia gospodarza</b>: przechowuje seryjną nazwę gospodarza. Przykładowo: "COM1" lub "/dev/ttyS0".</p><p>W <b>trybie plików RAW</b [...]
     </message>
     <message>
         <source>No IRQ is currently specified.</source>
@@ -9744,27 +9745,27 @@ p, li { white-space: pre-wrap; }
     <message>
         <source>Delete</source>
         <comment>extension pack</comment>
-        <translation type="unfinished"></translation>
+        <translation>Usuń</translation>
     </message>
     <message>
         <source>Do you want to delete the downloaded file <nobr><b>%1</b></nobr>?</source>
-        <translation type="unfinished"></translation>
+        <translation>Czy chcesz usunąć pobrany plik <nobr><b>%1</b></nobr>?</translation>
     </message>
     <message>
         <source>Do you want to delete following list of files <nobr><b>%1</b></nobr>?</source>
-        <translation type="unfinished"></translation>
+        <translation>Czy chcesz usunąć następującą listę plików <nobr><b>%1</b></nobr>?</translation>
     </message>
     <message>
         <source><p>The reason for this error are most likely wrong permissions of the IPC daemon socket due to an installation problem. Please check the permissions of <font color=blue>'/tmp'</font> and <font color=blue>'/tmp/.vbox-*-ipc/'</font></p></source>
-        <translation type="unfinished"></translation>
+        <translation><p>Przyczyną tego błędu najprawdopodobniej są złe uprawnienia gniazda demona IPC z powodu problemów z instalacją. Proszę sprawdzić uprawnienia <font color=blue>'/tmp'</font> i <font color=blue>'/tmp/.vbox-*-ipc/'</font></p></translation>
     </message>
     <message>
         <source><p>The <b>VirtualBox Guest Additions</b> disk image file has been successfully downloaded from <nobr><a href="%1">%1</a></nobr> and saved locally as <nobr><b>%2</b>, </nobr>but the SHA-256 checksum verification failed.</p><p>Please do the download, installation and verification manually.</p></source>
-        <translation type="unfinished"></translation>
+        <translation><p>Plik obrazu dysku<b>Dodatki gościa VirtualBox</b> został pomyślnie pobrany z <nobr><a href="%1">%1</a></nobr> i zapisany lokalnie jako <nobr><b>%2</b>, </nobr>ale nie powiodła się weryfikacja sum kontrolnych SHA-256.</p><p>Proszę ręcznie pobrać, zainstalować i zweryfikować.</p></translation>
     </message>
     <message>
         <source><p>The <b><nobr>%1</nobr></b> has been successfully downloaded from <nobr><a href="%2">%2</a></nobr> and saved locally as <nobr><b>%3</b>, </nobr>but the SHA-256 checksum verification failed.</p><p>Please do the download, installation and verification manually.</p></source>
-        <translation type="unfinished"></translation>
+        <translation><p><b><nobr>%1</nobr></b> został pomyślnie pobrany z <nobr><a href="%1">%1</a></nobr> i zapisany lokalnie jako <nobr><b>%2</b>, </nobr>ale nie powiodła się weryfikacja sum kontrolnych SHA-256.</p><p>Proszę ręcznie pobrać, zainstalować i zweryfikować.</p></translation>
     </message>
 </context>
 <context>
@@ -13982,7 +13983,8 @@ Wersja %1</translation>
     <message>
         <source>Host Pipe</source>
         <comment>PortMode</comment>
-        <translation>Host Pipe</translation>
+        <translatorcomment>Pipe - łącze komunikacyjne</translatorcomment>
+        <translation>Łącze komunikacyjne gospodarza</translation>
     </message>
     <message>
         <source>Host Device</source>
diff --git a/src/VBox/Frontends/VirtualBox/nls/VirtualBox_pt.ts b/src/VBox/Frontends/VirtualBox/nls/VirtualBox_pt.ts
index bbb05e8..6d68c62 100644
--- a/src/VBox/Frontends/VirtualBox/nls/VirtualBox_pt.ts
+++ b/src/VBox/Frontends/VirtualBox/nls/VirtualBox_pt.ts
@@ -3575,7 +3575,7 @@
         <translation>Endereço IPv6</translation>
     </message>
     <message>
-        <source>IPv6 Network Mask Length</source>
+        <source>IPv6 Prefix Length</source>
         <translation>Comprimento da Máscara de Rede IPv6</translation>
     </message>
     <message>
@@ -3808,7 +3808,7 @@
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <source>Host interface <b>%1</b> does not currently have a valid IPv6 network mask prefix length.</source>
+        <source>Host interface <b>%1</b> does not currently have a valid IPv6 prefix length.</source>
         <translation type="unfinished"></translation>
     </message>
 </context>
@@ -3855,11 +3855,11 @@
         <translation type="obsolete">Mostra o endereço IPv6 do hospedeiro para este adaptador se o IPv6 for suportado.</translation>
     </message>
     <message>
-        <source>IPv6 Network Mask &Length:</source>
+        <source>IPv6 Prefix &Length:</source>
         <translation type="obsolete">&Comprimento da Máscara de Rede IPv6:</translation>
     </message>
     <message>
-        <source>Holds the host IPv6 network mask prefix length for this adapter if IPv6 is supported.</source>
+        <source>Holds the host IPv6 prefix length for this adapter if IPv6 is supported.</source>
         <translation type="obsolete">Mostra o comprimento da máscara de rede IPv6 do hospedeiro para este adaptador se o IPv6 for suportado.</translation>
     </message>
     <message>
@@ -3950,11 +3950,11 @@
         <translation type="unfinished">Mostra o endereço IPv6 do hospedeiro para este adaptador se o IPv6 for suportado.</translation>
     </message>
     <message>
-        <source>IPv6 Network Mask &Length:</source>
+        <source>IPv6 Prefix &Length:</source>
         <translation type="unfinished">&Comprimento da Máscara de Rede IPv6:</translation>
     </message>
     <message>
-        <source>Holds the host IPv6 network mask prefix length for this adapter if IPv6 is supported.</source>
+        <source>Holds the host IPv6 prefix length for this adapter if IPv6 is supported.</source>
         <translation type="unfinished">Mostra o comprimento da máscara de rede IPv6 do hospedeiro para este adaptador se o IPv6 for suportado.</translation>
     </message>
     <message>
diff --git a/src/VBox/Frontends/VirtualBox/nls/VirtualBox_pt_BR.ts b/src/VBox/Frontends/VirtualBox/nls/VirtualBox_pt_BR.ts
index 3de5b1e..1163f01 100644
--- a/src/VBox/Frontends/VirtualBox/nls/VirtualBox_pt_BR.ts
+++ b/src/VBox/Frontends/VirtualBox/nls/VirtualBox_pt_BR.ts
@@ -4632,7 +4632,7 @@ p, li { white-space: pre-wrap; }
         <translation>Endereço IPv6</translation>
     </message>
     <message>
-        <source>IPv6 Network Mask Length</source>
+        <source>IPv6 Prefix Length</source>
         <translation>Tamanho da Máscara de Rede IPv6</translation>
     </message>
     <message>
@@ -4886,7 +4886,7 @@ p, li { white-space: pre-wrap; }
         <translation>Edita a rede exclusiva de hospedeiro selecionada.</translation>
     </message>
     <message>
-        <source>Host interface <b>%1</b> does not currently have a valid IPv6 network mask prefix length.</source>
+        <source>Host interface <b>%1</b> does not currently have a valid IPv6 prefix length.</source>
         <translation>A interface do hospedeiro <b>%1</b> não possui uma máscara IPv6 de tamanho válido.</translation>
     </message>
 </context>
@@ -4933,11 +4933,11 @@ p, li { white-space: pre-wrap; }
         <translation type="obsolete">Exibe o endereço IPv6 para esta placa se IPv6 for suportado.</translation>
     </message>
     <message>
-        <source>IPv6 Network Mask &Length:</source>
+        <source>IPv6 Prefix &Length:</source>
         <translation type="obsolete">Tamanho da Máscara de Rede IPv6 (&L):</translation>
     </message>
     <message>
-        <source>Holds the host IPv6 network mask prefix length for this adapter if IPv6 is supported.</source>
+        <source>Holds the host IPv6 prefix length for this adapter if IPv6 is supported.</source>
         <translation type="obsolete">Exibe o tamanho do prefixo da máscara de rede IPv6 para esta placa se IPv6 for suportado.</translation>
     </message>
     <message>
@@ -5028,11 +5028,11 @@ p, li { white-space: pre-wrap; }
         <translation>Contém o endereço IPv6 para esta placa se IPv6 for suportado.</translation>
     </message>
     <message>
-        <source>IPv6 Network Mask &Length:</source>
+        <source>IPv6 Prefix &Length:</source>
         <translation>Tamanho da Máscara de Rede IPv6 (&L):</translation>
     </message>
     <message>
-        <source>Holds the host IPv6 network mask prefix length for this adapter if IPv6 is supported.</source>
+        <source>Holds the host IPv6 prefix length for this adapter if IPv6 is supported.</source>
         <translation>Contém o tamanho do prefixo da máscara de rede IPv6 para esta placa se IPv6 for suportado.</translation>
     </message>
     <message>
diff --git a/src/VBox/Frontends/VirtualBox/nls/VirtualBox_ro.ts b/src/VBox/Frontends/VirtualBox/nls/VirtualBox_ro.ts
index 6c5ba1a..a09b9e8 100644
--- a/src/VBox/Frontends/VirtualBox/nls/VirtualBox_ro.ts
+++ b/src/VBox/Frontends/VirtualBox/nls/VirtualBox_ro.ts
@@ -3441,7 +3441,7 @@ Acest director este folosit, dacă nu este explicit specificat altfel, atunci c
         <translation>Adresă IPv6</translation>
     </message>
     <message>
-        <source>IPv6 Network Mask Length</source>
+        <source>IPv6 Prefix Length</source>
         <translation>Lungime mască rețea IPv6</translation>
     </message>
     <message>
@@ -3679,7 +3679,7 @@ Acest director este folosit, dacă nu este explicit specificat altfel, atunci c
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <source>Host interface <b>%1</b> does not currently have a valid IPv6 network mask prefix length.</source>
+        <source>Host interface <b>%1</b> does not currently have a valid IPv6 prefix length.</source>
         <translation type="unfinished"></translation>
     </message>
 </context>
@@ -3726,11 +3726,11 @@ Acest director este folosit, dacă nu este explicit specificat altfel, atunci c
         <translation type="obsolete">Afișează adresa IPv6 pentru această placă de rețea, dacă IPv6 este suportat.</translation>
     </message>
     <message>
-        <source>IPv6 Network Mask &Length:</source>
+        <source>IPv6 Prefix &Length:</source>
         <translation type="obsolete">&Lungime mască rețea IPv6:</translation>
     </message>
     <message>
-        <source>Holds the host IPv6 network mask prefix length for this adapter if IPv6 is supported.</source>
+        <source>Holds the host IPv6 prefix length for this adapter if IPv6 is supported.</source>
         <translation type="obsolete">Afișează lungimea prefixului măștii de rețea IPv6 pentru această placă de rețea, dacă IPv6 este suportat.</translation>
     </message>
     <message>
@@ -3801,11 +3801,11 @@ Acest director este folosit, dacă nu este explicit specificat altfel, atunci c
         <translation type="unfinished">Afișează adresa IPv6 pentru această placă de rețea, dacă IPv6 este suportat.</translation>
     </message>
     <message>
-        <source>IPv6 Network Mask &Length:</source>
+        <source>IPv6 Prefix &Length:</source>
         <translation type="unfinished">&Lungime mască rețea IPv6:</translation>
     </message>
     <message>
-        <source>Holds the host IPv6 network mask prefix length for this adapter if IPv6 is supported.</source>
+        <source>Holds the host IPv6 prefix length for this adapter if IPv6 is supported.</source>
         <translation type="unfinished">Afișează lungimea prefixului măștii de rețea IPv6 pentru această placă de rețea, dacă IPv6 este suportat.</translation>
     </message>
     <message>
diff --git a/src/VBox/Frontends/VirtualBox/nls/VirtualBox_ru.ts b/src/VBox/Frontends/VirtualBox/nls/VirtualBox_ru.ts
index 5bce5f4..0c1c89f 100644
--- a/src/VBox/Frontends/VirtualBox/nls/VirtualBox_ru.ts
+++ b/src/VBox/Frontends/VirtualBox/nls/VirtualBox_ru.ts
@@ -4230,7 +4230,7 @@ p, li { white-space: pre-wrap; }
         <translation>IPv6 адрес</translation>
     </message>
     <message>
-        <source>IPv6 Network Mask Length</source>
+        <source>IPv6 Prefix Length</source>
         <translation>IPv6 длина маски сети</translation>
     </message>
     <message>
@@ -4484,7 +4484,7 @@ p, li { white-space: pre-wrap; }
         <translation>Изменяет выбранную виртуальную сеть хоста.</translation>
     </message>
     <message>
-        <source>Host interface <b>%1</b> does not currently have a valid IPv6 network mask prefix length.</source>
+        <source>Host interface <b>%1</b> does not currently have a valid IPv6 prefix length.</source>
         <translation>Виртуальный интерфейс хоста <b>%1</b> имеет неверную длину IPv6 маски сети.</translation>
     </message>
 </context>
@@ -4531,11 +4531,11 @@ p, li { white-space: pre-wrap; }
         <translation type="obsolete">Отображает IPv6 адрес адаптера хоста данной виртуальной сети, если IPv6 поддерживается.</translation>
     </message>
     <message>
-        <source>IPv6 Network Mask &Length:</source>
+        <source>IPv6 Prefix &Length:</source>
         <translation type="obsolete">IPv6 д&лина маски сети:</translation>
     </message>
     <message>
-        <source>Holds the host IPv6 network mask prefix length for this adapter if IPv6 is supported.</source>
+        <source>Holds the host IPv6 prefix length for this adapter if IPv6 is supported.</source>
         <translation type="obsolete">Отображает длину IPv6 маски адаптера хоста данной виртуальной сети, если IPv6 поддерживается.</translation>
     </message>
     <message>
@@ -4626,11 +4626,11 @@ p, li { white-space: pre-wrap; }
         <translation>Определяет IPv6 адрес адаптера хоста данной виртуальной сети, если IPv6 поддерживается.</translation>
     </message>
     <message>
-        <source>IPv6 Network Mask &Length:</source>
+        <source>IPv6 Prefix &Length:</source>
         <translation>IPv6 д&лина маски сети:</translation>
     </message>
     <message>
-        <source>Holds the host IPv6 network mask prefix length for this adapter if IPv6 is supported.</source>
+        <source>Holds the host IPv6 prefix length for this adapter if IPv6 is supported.</source>
         <translation>Определяет длину IPv6 маски адаптера хоста данной виртуальной сети, если IPv6 поддерживается.</translation>
     </message>
     <message>
diff --git a/src/VBox/Frontends/VirtualBox/nls/VirtualBox_sk.ts b/src/VBox/Frontends/VirtualBox/nls/VirtualBox_sk.ts
index 294a3b0..93afeb3 100644
--- a/src/VBox/Frontends/VirtualBox/nls/VirtualBox_sk.ts
+++ b/src/VBox/Frontends/VirtualBox/nls/VirtualBox_sk.ts
@@ -3754,7 +3754,7 @@
         <translation>IPv6 adresa</translation>
     </message>
     <message>
-        <source>IPv6 Network Mask Length</source>
+        <source>IPv6 Prefix Length</source>
         <translation>Dĺžka sieťovej masky IPv6</translation>
     </message>
     <message>
@@ -3992,7 +3992,7 @@
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <source>Host interface <b>%1</b> does not currently have a valid IPv6 network mask prefix length.</source>
+        <source>Host interface <b>%1</b> does not currently have a valid IPv6 prefix length.</source>
         <translation type="unfinished"></translation>
     </message>
 </context>
@@ -4039,11 +4039,11 @@
         <translation type="obsolete">Zobrazí IPv6 adresu hostiteľa pre tento adaptér, ak je IPv6 podporovaná.</translation>
     </message>
     <message>
-        <source>IPv6 Network Mask &Length:</source>
+        <source>IPv6 Prefix &Length:</source>
         <translation type="obsolete">Dĺžka sieťove&j masky IPv6:</translation>
     </message>
     <message>
-        <source>Holds the host IPv6 network mask prefix length for this adapter if IPv6 is supported.</source>
+        <source>Holds the host IPv6 prefix length for this adapter if IPv6 is supported.</source>
         <translation type="obsolete">Zobrazí dĺžku prefixu IPv6 adresy hostiteľa pre tento adaptér, ak je IPv6 podporovaná.</translation>
     </message>
     <message>
@@ -4134,11 +4134,11 @@
         <translation type="unfinished">Zobrazí IPv6 adresu hostiteľa pre tento adaptér, ak je IPv6 podporovaná.</translation>
     </message>
     <message>
-        <source>IPv6 Network Mask &Length:</source>
+        <source>IPv6 Prefix &Length:</source>
         <translation type="unfinished">Dĺžka sieťove&j masky IPv6:</translation>
     </message>
     <message>
-        <source>Holds the host IPv6 network mask prefix length for this adapter if IPv6 is supported.</source>
+        <source>Holds the host IPv6 prefix length for this adapter if IPv6 is supported.</source>
         <translation type="unfinished">Zobrazí dĺžku prefixu IPv6 adresy hostiteľa pre tento adaptér, ak je IPv6 podporovaná.</translation>
     </message>
     <message>
diff --git a/src/VBox/Frontends/VirtualBox/nls/VirtualBox_sl.ts b/src/VBox/Frontends/VirtualBox/nls/VirtualBox_sl.ts
index 3a8597d..55ec75b 100644
--- a/src/VBox/Frontends/VirtualBox/nls/VirtualBox_sl.ts
+++ b/src/VBox/Frontends/VirtualBox/nls/VirtualBox_sl.ts
@@ -2553,7 +2553,7 @@
     </message>
     <message>
         <location line="+4"/>
-        <source>IPv6 Network Mask Length</source>
+        <source>IPv6 Prefix Length</source>
         <translation>Dolžina maske omrežja IPv6</translation>
     </message>
     <message>
@@ -2829,7 +2829,7 @@
     </message>
     <message>
         <location line="-420"/>
-        <source>Host interface <b>%1</b> does not currently have a valid IPv6 network mask prefix length.</source>
+        <source>Host interface <b>%1</b> does not currently have a valid IPv6 prefix length.</source>
         <translation>Vmesnik gostitelja <b>%1</b> trenutno nima veljavne dolžine predpone maske omrežja IPv6.</translation>
     </message>
 </context>
@@ -2882,12 +2882,12 @@
     </message>
     <message>
         <location line="+7"/>
-        <source>IPv6 Network Mask &Length:</source>
+        <source>IPv6 Prefix &Length:</source>
         <translation>&Dolžina maske omrežja IPv6:</translation>
     </message>
     <message>
         <location line="+19"/>
-        <source>Holds the host IPv6 network mask prefix length for this adapter if IPv6 is supported.</source>
+        <source>Holds the host IPv6 prefix length for this adapter if IPv6 is supported.</source>
         <translation>Vsebuje dolžino predpone maske omrežja IPv6 gostitelja za ta vmesnik, če je IPv6 podprt.</translation>
     </message>
     <message>
@@ -7503,7 +7503,7 @@
 <context>
     <name>UIMiniToolBar</name>
     <message>
-        <location filename="../src/widgets/UIMiniToolBar.cpp" line="+298"/>
+        <location filename="../src/widgets/UIMiniToolBar.cpp" line="+296"/>
         <source>Always show the toolbar</source>
         <translation>Vedno prikaži orodno vrstico</translation>
     </message>
diff --git a/src/VBox/Frontends/VirtualBox/nls/VirtualBox_sr.ts b/src/VBox/Frontends/VirtualBox/nls/VirtualBox_sr.ts
index dbd3253..76e76e9 100644
--- a/src/VBox/Frontends/VirtualBox/nls/VirtualBox_sr.ts
+++ b/src/VBox/Frontends/VirtualBox/nls/VirtualBox_sr.ts
@@ -3900,7 +3900,7 @@ p, li { white-space: pre-wrap; }
         <translation>IPv6 адреса</translation>
     </message>
     <message>
-        <source>IPv6 Network Mask Length</source>
+        <source>IPv6 Prefix Length</source>
         <translation>Дужина IPv6 мрежне маске</translation>
     </message>
     <message>
@@ -4138,7 +4138,7 @@ p, li { white-space: pre-wrap; }
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <source>Host interface <b>%1</b> does not currently have a valid IPv6 network mask prefix length.</source>
+        <source>Host interface <b>%1</b> does not currently have a valid IPv6 prefix length.</source>
         <translation type="unfinished"></translation>
     </message>
 </context>
@@ -4185,11 +4185,11 @@ p, li { white-space: pre-wrap; }
         <translation type="obsolete">Покажи IPv6 адресу са овај адаптер ако је IPv6 подржено.</translation>
     </message>
     <message>
-        <source>IPv6 Network Mask &Length:</source>
+        <source>IPv6 Prefix &Length:</source>
         <translation type="obsolete">Дужина IPv6 мрежне маске:</translation>
     </message>
     <message>
-        <source>Holds the host IPv6 network mask prefix length for this adapter if IPv6 is supported.</source>
+        <source>Holds the host IPv6 prefix length for this adapter if IPv6 is supported.</source>
         <translation type="obsolete">Покажи IPv6 дужину маске за овај адаптер ако је IPv6 подржено.</translation>
     </message>
     <message>
@@ -4280,11 +4280,11 @@ p, li { white-space: pre-wrap; }
         <translation type="unfinished">Покажи IPv6 адресу са овај адаптер ако је IPv6 подржено.</translation>
     </message>
     <message>
-        <source>IPv6 Network Mask &Length:</source>
+        <source>IPv6 Prefix &Length:</source>
         <translation type="unfinished">Дужина IPv6 мрежне маске:</translation>
     </message>
     <message>
-        <source>Holds the host IPv6 network mask prefix length for this adapter if IPv6 is supported.</source>
+        <source>Holds the host IPv6 prefix length for this adapter if IPv6 is supported.</source>
         <translation type="unfinished">Покажи IPv6 дужину маске за овај адаптер ако је IPv6 подржено.</translation>
     </message>
     <message>
diff --git a/src/VBox/Frontends/VirtualBox/nls/VirtualBox_sv.ts b/src/VBox/Frontends/VirtualBox/nls/VirtualBox_sv.ts
index 1ea14fe..2283323 100644
--- a/src/VBox/Frontends/VirtualBox/nls/VirtualBox_sv.ts
+++ b/src/VBox/Frontends/VirtualBox/nls/VirtualBox_sv.ts
@@ -4320,7 +4320,7 @@ p, li { white-space: pre-wrap; }
         <translation>IPv6-adress</translation>
     </message>
     <message>
-        <source>IPv6 Network Mask Length</source>
+        <source>IPv6 Prefix Length</source>
         <translation>Masklängd för IPv6-nätverk</translation>
     </message>
     <message>
@@ -4574,7 +4574,7 @@ p, li { white-space: pre-wrap; }
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <source>Host interface <b>%1</b> does not currently have a valid IPv6 network mask prefix length.</source>
+        <source>Host interface <b>%1</b> does not currently have a valid IPv6 prefix length.</source>
         <translation type="unfinished"></translation>
     </message>
 </context>
@@ -4621,11 +4621,11 @@ p, li { white-space: pre-wrap; }
         <translation type="obsolete">Visar värdens IPv6-adress för detta kort om IPv6 stöds.</translation>
     </message>
     <message>
-        <source>IPv6 Network Mask &Length:</source>
+        <source>IPv6 Prefix &Length:</source>
         <translation type="obsolete">Mask&längd för IPv6-nätverk:</translation>
     </message>
     <message>
-        <source>Holds the host IPv6 network mask prefix length for this adapter if IPv6 is supported.</source>
+        <source>Holds the host IPv6 prefix length for this adapter if IPv6 is supported.</source>
         <translation type="obsolete">Visar prefixlängd för värdens IPv6-nätverksmask för detta kort om IPv6 stöds.</translation>
     </message>
     <message>
@@ -4716,11 +4716,11 @@ p, li { white-space: pre-wrap; }
         <translation>Innehåller värdens IPv6-adress för denna adapter om IPv6 stöds.</translation>
     </message>
     <message>
-        <source>IPv6 Network Mask &Length:</source>
+        <source>IPv6 Prefix &Length:</source>
         <translation>Mask&längd för IPv6-nätverk:</translation>
     </message>
     <message>
-        <source>Holds the host IPv6 network mask prefix length for this adapter if IPv6 is supported.</source>
+        <source>Holds the host IPv6 prefix length for this adapter if IPv6 is supported.</source>
         <translation>Innehåller prefixlängd för värdens IPv6-nätverksmask för denna adapter om IPv6 stöds.</translation>
     </message>
     <message>
diff --git a/src/VBox/Frontends/VirtualBox/nls/VirtualBox_th.ts b/src/VBox/Frontends/VirtualBox/nls/VirtualBox_th.ts
index c7b0d82..f5ecd07 100644
--- a/src/VBox/Frontends/VirtualBox/nls/VirtualBox_th.ts
+++ b/src/VBox/Frontends/VirtualBox/nls/VirtualBox_th.ts
@@ -2009,7 +2009,7 @@
         <translation>ที่อยู่ IPv6</translation>
     </message>
     <message>
-        <source>IPv6 Network Mask Length</source>
+        <source>IPv6 Prefix Length</source>
         <translation>ความยาวมาสก์เครือข่าย IPv6</translation>
     </message>
     <message>
@@ -2226,7 +2226,7 @@
         <translation>แก้ไขเครือข่ายเฉพาะโฮสต์ที่เลือกไว้</translation>
     </message>
     <message>
-        <source>Host interface <b>%1</b> does not currently have a valid IPv6 network mask prefix length.</source>
+        <source>Host interface <b>%1</b> does not currently have a valid IPv6 prefix length.</source>
         <translation>แผงวงจรเครือข่ายของโฮสต์ <b>%1</b> ไม่ได้กำหนดความยาวส่วนขยายเน็ตมาสก์ IPv6 ที่ถูกต้องไว้</translation>
     </message>
 </context>
@@ -2269,11 +2269,11 @@
         <translation>เก็บที่อยู่ IPv6 สำหรับแผงวงจรนี้หากรองรับ IPv6</translation>
     </message>
     <message>
-        <source>IPv6 Network Mask &Length:</source>
+        <source>IPv6 Prefix &Length:</source>
         <translation>ความ&ยาวมาสก์เครือข่าย IPv6:</translation>
     </message>
     <message>
-        <source>Holds the host IPv6 network mask prefix length for this adapter if IPv6 is supported.</source>
+        <source>Holds the host IPv6 prefix length for this adapter if IPv6 is supported.</source>
         <translation>เก็บความยาวส่วนขยายมาสก์ด้านหน้าเครือข่าย IPv6 ของโฮสต์สำหรับแผงวงจรนี้หากรองรับ IPv6</translation>
     </message>
     <message>
diff --git a/src/VBox/Frontends/VirtualBox/nls/VirtualBox_tr.ts b/src/VBox/Frontends/VirtualBox/nls/VirtualBox_tr.ts
index 5f3937b..a5cf094 100644
--- a/src/VBox/Frontends/VirtualBox/nls/VirtualBox_tr.ts
+++ b/src/VBox/Frontends/VirtualBox/nls/VirtualBox_tr.ts
@@ -3716,7 +3716,7 @@
         <translation>IPv6 Adresi</translation>
     </message>
     <message>
-        <source>IPv6 Network Mask Length</source>
+        <source>IPv6 Prefix Length</source>
         <translation>IPv6 Ağ Maskesi Uzunluğu</translation>
     </message>
     <message>
@@ -3961,7 +3961,7 @@
         <translation>Seçilen yalnızca-anamakine ağını düzenler.</translation>
     </message>
     <message>
-        <source>Host interface <b>%1</b> does not currently have a valid IPv6 network mask prefix length.</source>
+        <source>Host interface <b>%1</b> does not currently have a valid IPv6 prefix length.</source>
         <translation>Anamakine arayüzü <b>%1</b>, şu anda geçerli bir IPv6 ağ maskesi öneki uzunluğuna sahip değil.</translation>
     </message>
 </context>
@@ -4008,11 +4008,11 @@
         <translation type="obsolete">Eğer IPv6 destekleniyorsa bu bağdaştırıcı için anamakine IPv6 adresini gösterir.</translation>
     </message>
     <message>
-        <source>IPv6 Network Mask &Length:</source>
+        <source>IPv6 Prefix &Length:</source>
         <translation type="obsolete">IPv6 Ağ Maskesi &Uzunluğu:</translation>
     </message>
     <message>
-        <source>Holds the host IPv6 network mask prefix length for this adapter if IPv6 is supported.</source>
+        <source>Holds the host IPv6 prefix length for this adapter if IPv6 is supported.</source>
         <translation type="obsolete">Eğer IPv6 destekleniyorsa bu bağdaştırıcı için anamakine IPv6 ağ maskesi ön ek uzunluğunu gösterir.</translation>
     </message>
     <message>
@@ -4103,11 +4103,11 @@
         <translation>Eğer IPv6 destekleniyorsa bu bağdaştırıcı için anamakine IPv6 adresini tutar.</translation>
     </message>
     <message>
-        <source>IPv6 Network Mask &Length:</source>
+        <source>IPv6 Prefix &Length:</source>
         <translation>IPv6 Ağ Maskesi &Uzunluğu:</translation>
     </message>
     <message>
-        <source>Holds the host IPv6 network mask prefix length for this adapter if IPv6 is supported.</source>
+        <source>Holds the host IPv6 prefix length for this adapter if IPv6 is supported.</source>
         <translation>Eğer IPv6 destekleniyorsa bu bağdaştırıcı için anamakine IPv6 ağ maskesi ön ek uzunluğunu tutar.</translation>
     </message>
     <message>
diff --git a/src/VBox/Frontends/VirtualBox/nls/VirtualBox_uk.ts b/src/VBox/Frontends/VirtualBox/nls/VirtualBox_uk.ts
index 1d0e72f..47a1cdc 100644
--- a/src/VBox/Frontends/VirtualBox/nls/VirtualBox_uk.ts
+++ b/src/VBox/Frontends/VirtualBox/nls/VirtualBox_uk.ts
@@ -3941,7 +3941,7 @@ p, li { white-space: pre-wrap; }
         <translation>Адреса IPv6</translation>
     </message>
     <message>
-        <source>IPv6 Network Mask Length</source>
+        <source>IPv6 Prefix Length</source>
         <translation>Відрізок маски мережі IPv6</translation>
     </message>
     <message>
@@ -4183,7 +4183,7 @@ p, li { white-space: pre-wrap; }
         <translation>Змінює вибрану віртуальну мережу хосту.</translation>
     </message>
     <message>
-        <source>Host interface <b>%1</b> does not currently have a valid IPv6 network mask prefix length.</source>
+        <source>Host interface <b>%1</b> does not currently have a valid IPv6 prefix length.</source>
         <translation type="unfinished"></translation>
     </message>
 </context>
@@ -4230,11 +4230,11 @@ p, li { white-space: pre-wrap; }
         <translation type="obsolete">Показує головну адресу IPv6 для цього адаптера, якщо IPv6 підтримується.</translation>
     </message>
     <message>
-        <source>IPv6 Network Mask &Length:</source>
+        <source>IPv6 Prefix &Length:</source>
         <translation type="obsolete">&Відрізок маски мережі IPv6:</translation>
     </message>
     <message>
-        <source>Holds the host IPv6 network mask prefix length for this adapter if IPv6 is supported.</source>
+        <source>Holds the host IPv6 prefix length for this adapter if IPv6 is supported.</source>
         <translation type="obsolete">Показує відрізок головної маски мережі IPv6 для цього адаптера, якщо IPv6 підтримується.</translation>
     </message>
     <message>
@@ -4325,11 +4325,11 @@ p, li { white-space: pre-wrap; }
         <translation>Показує головну адресу IPv6 для цього адаптера, якщо IPv6 підтримується.</translation>
     </message>
     <message>
-        <source>IPv6 Network Mask &Length:</source>
+        <source>IPv6 Prefix &Length:</source>
         <translation>&Відрізок маски мережі IPv6:</translation>
     </message>
     <message>
-        <source>Holds the host IPv6 network mask prefix length for this adapter if IPv6 is supported.</source>
+        <source>Holds the host IPv6 prefix length for this adapter if IPv6 is supported.</source>
         <translation>Показує відрізок головної маски мережі IPv6 для цього адаптера, якщо IPv6 підтримується.</translation>
     </message>
     <message>
diff --git a/src/VBox/Frontends/VirtualBox/nls/VirtualBox_xx_YY.ts b/src/VBox/Frontends/VirtualBox/nls/VirtualBox_xx_YY.ts
index 394188d..aad7951 100644
--- a/src/VBox/Frontends/VirtualBox/nls/VirtualBox_xx_YY.ts
+++ b/src/VBox/Frontends/VirtualBox/nls/VirtualBox_xx_YY.ts
@@ -2009,7 +2009,7 @@
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <source>IPv6 Network Mask Length</source>
+        <source>IPv6 Prefix Length</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
@@ -2226,7 +2226,7 @@
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <source>Host interface <b>%1</b> does not currently have a valid IPv6 network mask prefix length.</source>
+        <source>Host interface <b>%1</b> does not currently have a valid IPv6 prefix length.</source>
         <translation type="unfinished"></translation>
     </message>
 </context>
@@ -2269,11 +2269,11 @@
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <source>IPv6 Network Mask &Length:</source>
+        <source>IPv6 Prefix &Length:</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <source>Holds the host IPv6 network mask prefix length for this adapter if IPv6 is supported.</source>
+        <source>Holds the host IPv6 prefix length for this adapter if IPv6 is supported.</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
diff --git a/src/VBox/Frontends/VirtualBox/nls/VirtualBox_zh_CN.ts b/src/VBox/Frontends/VirtualBox/nls/VirtualBox_zh_CN.ts
index 42b45c7..25e730b 100644
--- a/src/VBox/Frontends/VirtualBox/nls/VirtualBox_zh_CN.ts
+++ b/src/VBox/Frontends/VirtualBox/nls/VirtualBox_zh_CN.ts
@@ -3778,7 +3778,7 @@
         <translation>IPv6 地址</translation>
     </message>
     <message>
-        <source>IPv6 Network Mask Length</source>
+        <source>IPv6 Prefix Length</source>
         <translation>IPv6 网络掩码长度</translation>
     </message>
     <message>
@@ -4023,7 +4023,7 @@
         <translation>编辑仅主机(Host-Only)网络。</translation>
     </message>
     <message>
-        <source>Host interface <b>%1</b> does not currently have a valid IPv6 network mask prefix length.</source>
+        <source>Host interface <b>%1</b> does not currently have a valid IPv6 prefix length.</source>
         <translatorcomment>todo</translatorcomment>
         <translation>主机网卡 <b>%1</b> 目前没有有效的 IPv6 掩码前缀长度。</translation>
     </message>
@@ -4071,11 +4071,11 @@
         <translation type="obsolete">显示主机虚拟网络界面的 IPv6 地址.</translation>
     </message>
     <message>
-        <source>IPv6 Network Mask &Length:</source>
+        <source>IPv6 Prefix &Length:</source>
         <translation type="obsolete">IPv6 网络掩码长度(&L):</translation>
     </message>
     <message>
-        <source>Holds the host IPv6 network mask prefix length for this adapter if IPv6 is supported.</source>
+        <source>Holds the host IPv6 prefix length for this adapter if IPv6 is supported.</source>
         <translation type="obsolete">显示主机虚拟网络界面的 IPv6 网络掩码前缀.</translation>
     </message>
     <message>
@@ -4167,11 +4167,11 @@
         <translation>显示主机虚拟网络界面的 IPv6 地址.</translation>
     </message>
     <message>
-        <source>IPv6 Network Mask &Length:</source>
+        <source>IPv6 Prefix &Length:</source>
         <translation>IPv6 网络掩码长度(&L):</translation>
     </message>
     <message>
-        <source>Holds the host IPv6 network mask prefix length for this adapter if IPv6 is supported.</source>
+        <source>Holds the host IPv6 prefix length for this adapter if IPv6 is supported.</source>
         <translation>显示主机虚拟网络界面的 IPv6 网络掩码前缀.</translation>
     </message>
     <message>
diff --git a/src/VBox/Frontends/VirtualBox/nls/VirtualBox_zh_TW.ts b/src/VBox/Frontends/VirtualBox/nls/VirtualBox_zh_TW.ts
index 66e5837..ad4fe58 100644
--- a/src/VBox/Frontends/VirtualBox/nls/VirtualBox_zh_TW.ts
+++ b/src/VBox/Frontends/VirtualBox/nls/VirtualBox_zh_TW.ts
@@ -2009,7 +2009,7 @@
         <translation>IPv6 位址</translation>
     </message>
     <message>
-        <source>IPv6 Network Mask Length</source>
+        <source>IPv6 Prefix Length</source>
         <translation>IPv6 網路遮罩長度</translation>
     </message>
     <message>
@@ -2226,7 +2226,7 @@
         <translation>編輯選取的「僅限主機」網路。</translation>
     </message>
     <message>
-        <source>Host interface <b>%1</b> does not currently have a valid IPv6 network mask prefix length.</source>
+        <source>Host interface <b>%1</b> does not currently have a valid IPv6 prefix length.</source>
         <translation>主機介面 <b>%1</b> 目前的 IPv6 網路遮罩前置長度無效。</translation>
     </message>
 </context>
@@ -2269,11 +2269,11 @@
         <translation>保留這個網路卡的 IPv6 位址,如果支援 IPv6。</translation>
     </message>
     <message>
-        <source>IPv6 Network Mask &Length:</source>
+        <source>IPv6 Prefix &Length:</source>
         <translation>IPv6 網路遮罩長度(&L):</translation>
     </message>
     <message>
-        <source>Holds the host IPv6 network mask prefix length for this adapter if IPv6 is supported.</source>
+        <source>Holds the host IPv6 prefix length for this adapter if IPv6 is supported.</source>
         <translation>保留這個網路卡的主機 IPv6 網路遮罩前置長度,如果支援 IPv6。</translation>
     </message>
     <message>
diff --git a/src/VBox/Frontends/VirtualBox/nls/qt_el.ts b/src/VBox/Frontends/VirtualBox/nls/qt_el.ts
index 34de9ad..e5e4c8a 100644
--- a/src/VBox/Frontends/VirtualBox/nls/qt_el.ts
+++ b/src/VBox/Frontends/VirtualBox/nls/qt_el.ts
@@ -29,8 +29,8 @@
     </message>
     <message>
         <source>About %1</source>
-        <translatorcomment>2017-03-13</translatorcomment>
-        <translation>Πληροφορίες για το %1</translation>
+        <translatorcomment>2017-05-04</translatorcomment>
+        <translation>Σχετικά με %1</translation>
     </message>
 </context>
 <context>
@@ -52,7 +52,7 @@
     <name>Phonon::</name>
     <message>
         <source>Notifications</source>
-        <translation>Γνωστοποιήσεις</translation>
+        <translation>Ειδοποιήσεις</translation>
     </message>
     <message>
         <source>Music</source>
@@ -97,7 +97,7 @@
 
 Check your Gstreamer installation and make sure you 
 have libgstreamer-plugins-base installed.</source>
-        <translation>Δεν είναι δυνατή η αναπαραγωγή. 
+        <translation>Αδυναμία αναπαραγωγής. 
 
 Ελέξτε την εγκατάσταση του Gstreamer και σιγουρευτείτε οτι
 έχετε εγκαταστήσει το  libgstreamer-plugins-base.</translation>
@@ -115,7 +115,7 @@ have libgstreamer-plugins-base installed.</source>
     </message>
     <message>
         <source>Invalid source type.</source>
-        <translation>Μή έγκυρος τύπος πηγής.</translation>
+        <translation>Μη έγκυρος τύπος πηγής.</translation>
     </message>
     <message>
         <source>Could not locate media source.</source>
@@ -127,7 +127,7 @@ have libgstreamer-plugins-base installed.</source>
     </message>
     <message>
         <source>Could not decode media source.</source>
-        <translation>Δεν ήταν δυνατή η αποκωδικοποίηση της πηγής μέσου.</translation>
+        <translation>Αδυναμία αποκωδικοποίησης της πηγής μέσου.</translation>
     </message>
 </context>
 <context>
@@ -145,11 +145,11 @@ have libgstreamer-plugins-base installed.</source>
     <name>Q3Accel</name>
     <message>
         <source>%1, %2 not defined</source>
-        <translation>%1, %2 δεν έχει καθοριστεί</translation>
+        <translation>%1, %2 δεν έχουν καθοριστεί</translation>
     </message>
     <message>
         <source>Ambiguous %1 not handled</source>
-        <translation>Αμφίβολο %1 δεν μπορεί να χειριστεί</translation>
+        <translation>Αμφίβολο %1 δεν μπορεί να χρησιμοποιηθεί</translation>
     </message>
 </context>
 <context>
@@ -179,7 +179,7 @@ have libgstreamer-plugins-base installed.</source>
     <name>Q3FileDialog</name>
     <message>
         <source>Copy or Move a File</source>
-        <translation>Αντιγραφή ή Μετακίνηση αρχείου</translation>
+        <translation>Αντιγραφή ή Μετακίνηση ενός αρχείου</translation>
     </message>
     <message>
         <source>Read: %1</source>
@@ -223,7 +223,7 @@ have libgstreamer-plugins-base installed.</source>
     </message>
     <message>
         <source>Look &in:</source>
-        <translation>Ψάξε σε:</translation>
+        <translation>Αναζήτηση σε:</translation>
     </message>
     <message>
         <source>File &name:</source>
@@ -239,7 +239,7 @@ have libgstreamer-plugins-base installed.</source>
     </message>
     <message>
         <source>One directory up</source>
-        <translation>Επάνω</translation>
+        <translation>Ένας κατάλογος επάνω</translation>
     </message>
     <message>
         <source>Create New Folder</source>
@@ -267,11 +267,11 @@ have libgstreamer-plugins-base installed.</source>
     </message>
     <message>
         <source>Read-only</source>
-        <translation>Ανάγνωση μόνο</translation>
+        <translation>Μόνο Ανάγνωση</translation>
     </message>
     <message>
         <source>Write-only</source>
-        <translation>Εγγραφή-μόνο</translation>
+        <translation>Μόνο Εγγραφή</translation>
     </message>
     <message>
         <source>Inaccessible</source>
@@ -283,11 +283,11 @@ have libgstreamer-plugins-base installed.</source>
     </message>
     <message>
         <source>Symlink to Directory</source>
-        <translation>Σύνδεσμος σε φάκελλο</translation>
+        <translation>Σύνδεσμος σε Κατάλογο</translation>
     </message>
     <message>
         <source>Symlink to Special</source>
-        <translation>Σύνδεσμος σε ειδικό</translation>
+        <translation>Σύνδεσμος σε Ειδικό</translation>
     </message>
     <message>
         <source>File</source>
@@ -327,7 +327,7 @@ have libgstreamer-plugins-base installed.</source>
     </message>
     <message>
         <source>R&eload</source>
-        <translation>Φόρτωμα</translation>
+        <translation>Επαναφόρτωση</translation>
     </message>
     <message>
         <source>Sort by &Name</source>
@@ -359,7 +359,7 @@ have libgstreamer-plugins-base installed.</source>
     </message>
     <message>
         <source>the directory</source>
-        <translation>ο φάκελος</translation>
+        <translation>ο κατάλογος</translation>
     </message>
     <message>
         <source>the symlink</source>
@@ -395,15 +395,15 @@ have libgstreamer-plugins-base installed.</source>
     </message>
     <message>
         <source>Find Directory</source>
-        <translation>Εύρεση Φακέλου</translation>
+        <translation>Εύρεση Καταλόγου</translation>
     </message>
     <message>
         <source>Directories</source>
-        <translation>Φάκελοι</translation>
+        <translation>Κατάλογοι</translation>
     </message>
     <message>
         <source>Directory:</source>
-        <translation>Φάκελος:</translation>
+        <translation>Κατάλογος:</translation>
     </message>
     <message>
         <source>Error</source>
@@ -415,7 +415,7 @@ File not found.
 Check path and filename.</source>
         <translation>%1
 Το αρχείο δεν βρέθηκε.
-Ελέγξτε την διαδρομή και το όνομα του αρχείου.</translation>
+Ελέγξτε τη διαδρομή και το όνομα του αρχείου.</translation>
     </message>
 </context>
 <context>
@@ -423,19 +423,19 @@ Check path and filename.</source>
     <message>
         <source>Could not read directory
 %1</source>
-        <translation>Δεν ήταν δυνατή η ανάγνωση του φακέλου
+        <translation>Αδυναμία ανάγνωσης του καταλόγου
 %1</translation>
     </message>
     <message>
         <source>Could not create directory
 %1</source>
-        <translation>Δεν ήταν δυνατή η δημιουργία του φακέλου
+        <translation>Αδυναμία δημιουργίας του καταλόγου
 %1</translation>
     </message>
     <message>
         <source>Could not remove file or directory
 %1</source>
-        <translation>Δεν ήταν δυνατή η διαγραφή του αρχείου ή του φακέλου
+        <translation>Αδυναμία διαγραφής του αρχείου ή του καταλόγου
 %1</translation>
     </message>
     <message>
@@ -443,7 +443,7 @@ Check path and filename.</source>
 %1
 to
 %2</source>
-        <translation>Δεν ήταν δυνατή η μετονομασία
+        <translation>Αδυναμία μετονομασίας
 %1
 σε
 %2</translation>
@@ -451,13 +451,13 @@ to
     <message>
         <source>Could not open
 %1</source>
-        <translation>Δεν ήταν δυνατό το άνοιγμα
+        <translation>Αδυναμία ανοίγματος
 %1</translation>
     </message>
     <message>
         <source>Could not write
 %1</source>
-        <translation>Δεν ήταν δυνατή η εγγραφή
+        <translation>Αδυναμία εγγραφής
 %1</translation>
     </message>
 </context>
@@ -483,7 +483,7 @@ to
     <name>Q3ProgressDialog</name>
     <message>
         <source>Cancel</source>
-        <translation>Άκυρο</translation>
+        <translation>Ακύρωση</translation>
     </message>
 </context>
 <context>
@@ -502,11 +502,11 @@ to
     </message>
     <message>
         <source>Defaults</source>
-        <translation>Επαναφορά σε αρχικά</translation>
+        <translation>Προκαθορισμένα</translation>
     </message>
     <message>
         <source>Cancel</source>
-        <translation>Άκυρο</translation>
+        <translation>Ακύρωση</translation>
     </message>
 </context>
 <context>
@@ -517,7 +517,7 @@ to
     </message>
     <message>
         <source>&Redo</source>
-        <translation>Ακύρωση Αναίρεσης</translation>
+        <translation>Επαναφορά</translation>
     </message>
     <message>
         <source>Cu&t</source>
@@ -568,11 +568,11 @@ to
     </message>
     <message>
         <source>Contains commands to manipulate the window</source>
-        <translation>Περιέχει εντολές για τον έλεγχο του παραθύρου</translation>
+        <translation>Περιέχει εντολές για τη ρύθμιση του παραθύρου</translation>
     </message>
     <message>
         <source>Puts a minimized back to normal</source>
-        <translation>Θετεί από ελαχιστοποίηση σε κανονικό μέγεθος</translation>
+        <translation>Επαναφορά από ελαχιστοποιημένη σε κανονική μορφή</translation>
     </message>
     <message>
         <source>Moves the window out of the way</source>
@@ -580,19 +580,19 @@ to
     </message>
     <message>
         <source>Puts a maximized window back to normal</source>
-        <translation>Θέτει το παράθυρο από μεγιστοποίηση σε κανονικό μέγεθος</translation>
+        <translation>Επαναφορά παραθύρου από μεγιστοποιημένη σε κανονική μορφή</translation>
     </message>
     <message>
         <source>Makes the window full screen</source>
-        <translation>Θέτει το παράθυρο σε πλήρη οθόνη</translation>
+        <translation>Παράθυρο σε πλήρη οθόνη</translation>
     </message>
     <message>
         <source>Closes the window</source>
-        <translation>Κλείνει το παράθυρο</translation>
+        <translation>Κλείσιμο παραθύρου</translation>
     </message>
     <message>
         <source>Holds the name of the window and contains controls to manipulate it</source>
-        <translation>Εμφανίζει το όνομα του παραθύρου και περιέχει εντολές για τον έλεγχο του</translation>
+        <translation>Εμφανίζει το όνομα του παραθύρου και περιέχει εντολές για τη ρύθμισή του</translation>
     </message>
 </context>
 <context>
@@ -610,19 +610,19 @@ to
     </message>
     <message>
         <source>The protocol `%1' does not support listing directories</source>
-        <translation>Το πρωτόκολλο '%1' δεν υποστηρίζει τον κατάλογο φακέλων</translation>
+        <translation>Το πρωτόκολλο '%1' δεν υποστηρίζει την εμφάνιση σε λίστα των καταλόγων</translation>
     </message>
     <message>
         <source>The protocol `%1' does not support creating new directories</source>
-        <translation>Το πρωτόκολλο '%1' δεν υποστηρίζει την δημιουργία νέων φακέλων</translation>
+        <translation>Το πρωτόκολλο '%1' δεν υποστηρίζει την δημιουργία νέων καταλόγων</translation>
     </message>
     <message>
         <source>The protocol `%1' does not support removing files or directories</source>
-        <translation>Το πρωτόκολλο '%1' δεν υποστηρίζει την μετακίνηση αρχείων ή φακέλων</translation>
+        <translation>Το πρωτόκολλο '%1' δεν υποστηρίζει την μετακίνηση αρχείων ή καταλόγων</translation>
     </message>
     <message>
         <source>The protocol `%1' does not support renaming files or directories</source>
-        <translation>Το πρωτόκολλο '%1' δεν υποστηρίζει την μετονομασία αρχείων ή φακέλων</translation>
+        <translation>Το πρωτόκολλο '%1' δεν υποστηρίζει την μετονομασία αρχείων ή καταλόγων</translation>
     </message>
     <message>
         <source>The protocol `%1' does not support getting files</source>
@@ -634,7 +634,7 @@ to
     </message>
     <message>
         <source>The protocol `%1' does not support copying or moving files or directories</source>
-        <translation>Το πρωτόκολλο '%1' δεν υποστηρίζει την αντιγραφή ή μεταφορά αρχείων ή φακέλων</translation>
+        <translation>Το πρωτόκολλο '%1' δεν υποστηρίζει την αντιγραφή ή μεταφορά αρχείων ή καταλόγων</translation>
     </message>
     <message>
         <source>(unknown)</source>
@@ -645,7 +645,7 @@ to
     <name>Q3Wizard</name>
     <message>
         <source>&Cancel</source>
-        <translation>Άκυρο</translation>
+        <translation>Ακύρωση</translation>
     </message>
     <message>
         <source>< &Back</source>
@@ -719,14 +719,14 @@ to
     </message>
     <message>
         <source>Activates the program's main window</source>
-        <translation>Ενεργοποιεί το κεντρικό παράθυρο της εφαρμογής</translation>
+        <translation>Ενεργοποιεί το κύριο παράθυρο της εφαρμογής</translation>
     </message>
 </context>
 <context>
     <name>QCheckBox</name>
     <message>
         <source>Uncheck</source>
-        <translation>Απεπιλογή</translation>
+        <translation>Αποεπιλογή</translation>
     </message>
     <message>
         <source>Check</source>
@@ -777,11 +777,11 @@ to
     </message>
     <message>
         <source>&Add to Custom Colors</source>
-        <translation>Πρόσθεση σε ειδικά χρώματα</translation>
+        <translation>Προσθήκη σε ειδικά χρώματα</translation>
     </message>
     <message>
         <source>Select color</source>
-        <translation>Επιλέξτε χρώμα</translation>
+        <translation>Επιλογή χρώματος</translation>
     </message>
 </context>
 <context>
@@ -833,7 +833,7 @@ to
     <message>
         <source>%1: key is empty</source>
         <comment>QSystemSemaphore</comment>
-        <translation>%1: το κλειδί είναι άδειο</translation>
+        <translation>%1: το κλειδί είναι κενό</translation>
     </message>
     <message>
         <source>%1: unable to make key</source>
@@ -850,65 +850,65 @@ to
     <name>QDB2Driver</name>
     <message>
         <source>Unable to connect</source>
-        <translation>Δεν ήταν δυνατή η σύνδεση</translation>
+        <translation>Αδυναμία σύνδεσης</translation>
     </message>
     <message>
         <source>Unable to commit transaction</source>
-        <translation>Δεν ήταν δυνατή η εκτέλεση της συνδιαλλαγής</translation>
+        <translation>Αδυναμία εκτέλεσης συνδιαλλαγής</translation>
     </message>
     <message>
         <source>Unable to rollback transaction</source>
-        <translation>Δεν ήταν δυνατή η ακύρωση της συνδιαλλαγής</translation>
+        <translation>Αδυναμία ακύρωσης συνδιαλλαγής</translation>
     </message>
     <message>
         <source>Unable to set autocommit</source>
-        <translation>Δεν ήταν δυνατος ο ορισμός της αυτόματης αντιστοίχησης</translation>
+        <translation>Αδυναμία ορισμού αυτόματης αντιστοίχησης</translation>
     </message>
 </context>
 <context>
     <name>QDB2Result</name>
     <message>
         <source>Unable to execute statement</source>
-        <translation>Δεν ήταν δυνατή η εκτέλεση της πρότασης</translation>
+        <translation>Αδυναμία εκτέλεσης πρότασης</translation>
     </message>
     <message>
         <source>Unable to prepare statement</source>
-        <translation>Δεν ήταν δυνατή η προετοιμασία της πρότασης</translation>
+        <translation>Αδυναμία προετοιμασίας πρότασης</translation>
     </message>
     <message>
         <source>Unable to bind variable</source>
-        <translation>Δεν ήταν δυνατή η δέσμευση της μεταβλητής</translation>
+        <translation>Αδυναμία δέσμευσης μεταβλητής</translation>
     </message>
     <message>
         <source>Unable to fetch record %1</source>
-        <translation>Δεν ήταν δυνατή η προσκόμιση της εγγραφής %1</translation>
+        <translation>Αδυναμία προσκόμισης εγγραφής %1</translation>
     </message>
     <message>
         <source>Unable to fetch next</source>
-        <translation>Δεν ήταν δυνατή η προσκόμιση του επόμενου</translation>
+        <translation>Αδυναμία προσκόμισης επόμενου</translation>
     </message>
     <message>
         <source>Unable to fetch first</source>
-        <translation>Δεν ήταν δυνατή η προσκόμιση του πρώτου</translation>
+        <translation>Αδυναμία προσκόμισης του πρώτου</translation>
     </message>
 </context>
 <context>
     <name>QDateTimeEdit</name>
     <message>
         <source>AM</source>
-        <translation>ΜΜ</translation>
+        <translation>ΠΜ</translation>
     </message>
     <message>
         <source>am</source>
-        <translation>μμ</translation>
+        <translation>πμ</translation>
     </message>
     <message>
         <source>PM</source>
-        <translation>ΠΜ</translation>
+        <translation>ΜΜ</translation>
     </message>
     <message>
         <source>pm</source>
-        <translation>πμ</translation>
+        <translation>μμ</translation>
     </message>
 </context>
 <context>
@@ -953,7 +953,7 @@ to
     </message>
     <message>
         <source>Cancel</source>
-        <translation>Άκυρο</translation>
+        <translation>Ακύρωση</translation>
     </message>
     <message>
         <source>Close</source>
@@ -965,7 +965,7 @@ to
     </message>
     <message>
         <source>Reset</source>
-        <translation>Επανέναρξη</translation>
+        <translation>Επαναφορά στα προκαθορισμένα</translation>
     </message>
     <message>
         <source>Help</source>
@@ -973,7 +973,7 @@ to
     </message>
     <message>
         <source>Don't Save</source>
-        <translation>Μην αποθηκεύσεις</translation>
+        <translation>Όχι αποθήκευση</translation>
     </message>
     <message>
         <source>Discard</source>
@@ -1001,19 +1001,19 @@ to
     </message>
     <message>
         <source>Abort</source>
-        <translation>Ματαίωσε</translation>
+        <translation>Ματαίωση</translation>
     </message>
     <message>
         <source>Retry</source>
-        <translation>Προσπάθησε πάλι</translation>
+        <translation>Προσπάθεια πάλι</translation>
     </message>
     <message>
         <source>Ignore</source>
-        <translation>Αγνόησε</translation>
+        <translation>Αγνόηση</translation>
     </message>
     <message>
         <source>Restore Defaults</source>
-        <translation>Επανέφερε τα αρχικά</translation>
+        <translation>Επαναφορά Προκαθορισμένων</translation>
     </message>
     <message>
         <source>Close without Saving</source>
@@ -1106,7 +1106,7 @@ to
     </message>
     <message>
         <source>Directories</source>
-        <translation>Φάκελοι</translation>
+        <translation>Κατάλογοι</translation>
     </message>
     <message>
         <source>&Open</source>
@@ -1164,7 +1164,7 @@ Please verify the correct file name was given.</source>
     </message>
     <message>
         <source>Detail View</source>
-        <translation>Προβολή με Λεπτομέρειες</translation>
+        <translation>Λεπτομερής Προβολή</translation>
     </message>
     <message>
         <source>Files of type:</source>
@@ -1172,15 +1172,15 @@ Please verify the correct file name was given.</source>
     </message>
     <message>
         <source>Directory:</source>
-        <translation>Φάκελος:</translation>
+        <translation>Κατάλογος:</translation>
     </message>
     <message>
         <source>%1
 Directory not found.
 Please verify the correct directory name was given.</source>
         <translation>%1
-Ο φάκελος δεν βρέθηκε.
-Παρακαλώ επιβεβαιώστε το όνομα του φακέλου.</translation>
+Ο κατάλογος δεν βρέθηκε.
+Παρακαλώ επιβεβαιώστε το όνομα του καταλόγου.</translation>
     </message>
     <message>
         <source>'%1' is write protected.
@@ -1194,7 +1194,7 @@ Do you want to delete it anyway?</source>
     </message>
     <message>
         <source>Could not delete directory.</source>
-        <translation>Δεν ήταν δυνατή η διαγραφή του φακέλου.</translation>
+        <translation>Δεν ήταν δυνατή η διαγραφή του καταλόγου.</translation>
     </message>
     <message>
         <source>Save As</source>
@@ -1214,7 +1214,7 @@ Do you want to delete it anyway?</source>
     </message>
     <message>
         <source>Find Directory</source>
-        <translation>Εύρεση φακέλου</translation>
+        <translation>Εύρεση καταλόγου</translation>
     </message>
     <message>
         <source>Show </source>
@@ -1226,7 +1226,7 @@ Do you want to delete it anyway?</source>
     </message>
     <message>
         <source>New Folder</source>
-        <translation>Νέος Φάκελος</translation>
+        <translation>Νέος Κατάλογος</translation>
     </message>
     <message>
         <source>&New Folder</source>
@@ -1246,11 +1246,11 @@ Do you want to delete it anyway?</source>
     </message>
     <message>
         <source>Look in:</source>
-        <translation>Ψάξε σε :</translation>
+        <translation>Αναζήτηση σε :</translation>
     </message>
     <message>
         <source>Create New Folder</source>
-        <translation>Δημιουργία Νέου Φακέλου</translation>
+        <translation>Δημιουργία Νέου Καταλόγου</translation>
     </message>
 </context>
 <context>
@@ -1501,7 +1501,7 @@ Do you want to delete it anyway?</source>
     </message>
     <message>
         <source>Stri&keout</source>
-        <translation>Γράμμιση</translation>
+        <translation>Διαγράμμιση</translation>
     </message>
     <message>
         <source>&Underline</source>
@@ -1513,7 +1513,7 @@ Do you want to delete it anyway?</source>
     </message>
     <message>
         <source>Wr&iting System</source>
-        <translation>Σύστημα εγγραφής</translation>
+        <translation>Σύστημα γραφής</translation>
     </message>
     <message>
         <source>Select Font</source>
@@ -1555,49 +1555,49 @@ Do you want to delete it anyway?</source>
     <message>
         <source>Login failed:
 %1</source>
-        <translation>Η είσοδςο απέτυχε :
+        <translation>Η είσοδος απέτυχε :
 %1</translation>
     </message>
     <message>
         <source>Listing directory failed:
 %1</source>
-        <translation>Η λίστα φακέλων απέτυχε :
+        <translation>Η λίστα καταλόγων απέτυχε :
 %1</translation>
     </message>
     <message>
         <source>Changing directory failed:
 %1</source>
-        <translation>Η αλλαγή φακέλου απέτυχε :
+        <translation>Η αλλαγή καταλόγου απέτυχε :
 %1</translation>
     </message>
     <message>
         <source>Downloading file failed:
 %1</source>
-        <translation>Το κατέβασμα του αρχείου απέτυχε :
+        <translation>Η λήψη αρχείου απέτυχε :
 %1</translation>
     </message>
     <message>
         <source>Uploading file failed:
 %1</source>
-        <translation>Το ανέβασμα του αρχείου απέτυχε :
+        <translation>Το ανέβασμα αρχείου απέτυχε :
 %1</translation>
     </message>
     <message>
         <source>Removing file failed:
 %1</source>
-        <translation>Η διαγραφή του αρχείου απέτυχε :
+        <translation>Η διαγραφή αρχείου απέτυχε:
 %1</translation>
     </message>
     <message>
         <source>Creating directory failed:
 %1</source>
-        <translation>Η δημιουργία του φακέλου απέτυχε:
+        <translation>Η δημιουργία καταλόγου απέτυχε:
 %1</translation>
     </message>
     <message>
         <source>Removing directory failed:
 %1</source>
-        <translation>Η διαγραφή του φακέλου απέτυχε:
+        <translation>Η διαγραφή καταλόγου απέτυχε:
 %1</translation>
     </message>
     <message>
@@ -1711,11 +1711,11 @@ Do you want to delete it anyway?</source>
     </message>
     <message>
         <source>Proxy authentication required</source>
-        <translation>Ο διαμεσολαβητής απαιτεί αυθεντικοποίηση</translation>
+        <translation>Ο διαμεσολαβητής απαιτεί πιστοποίηση</translation>
     </message>
     <message>
         <source>Authentication required</source>
-        <translation>Απαιτείται αυθεντικοποίηση</translation>
+        <translation>Απαιτείται πιστοποίηση</translation>
     </message>
     <message>
         <source>Connection refused (or timed out)</source>
@@ -1723,23 +1723,23 @@ Do you want to delete it anyway?</source>
     </message>
     <message>
         <source>Proxy requires authentication</source>
-        <translation>Ο διαμεσολαβητής απαιτεί αυθεντικοποίηση</translation>
+        <translation>Ο διαμεσολαβητής απαιτεί πιστοποίηση</translation>
     </message>
     <message>
         <source>Host requires authentication</source>
-        <translation>Ο διακομιστής απαιτεί αυθεντικοποίηση</translation>
+        <translation>Ο διακομιστής απαιτεί πιστοποίηση</translation>
     </message>
     <message>
         <source>Data corrupted</source>
-        <translation>Διαβρωμένα δεδομένα</translation>
+        <translation>Κατεστραμένα δεδομένα</translation>
     </message>
     <message>
         <source>Unknown protocol specified</source>
-        <translation>Προσδιορίστηκε άγνωστο πρωτόκολλο</translation>
+        <translation>Επιλέχθηκεε άγνωστο πρωτόκολλο</translation>
     </message>
     <message>
         <source>SSL handshake failed</source>
-        <translation>Η χειραψία SSL απέτυχε</translation>
+        <translation>Η πιστοποίηση SSL απέτυχε</translation>
     </message>
     <message>
         <source>HTTPS connection requested but SSL support not compiled in</source>
@@ -1750,7 +1750,7 @@ Do you want to delete it anyway?</source>
     <name>QHttpSocketEngine</name>
     <message>
         <source>Authentication required</source>
-        <translation>Απαιτείται αυθεντικοποίηση</translation>
+        <translation>Απαιτείται πιστοποίηση</translation>
     </message>
 </context>
 <context>
@@ -1761,38 +1761,38 @@ Do you want to delete it anyway?</source>
     </message>
     <message>
         <source>Could not start transaction</source>
-        <translation>Δεν ήταν δυνατή η εκκίνηση της συνδιαλλαγής</translation>
+        <translation>Αδυναμία εκκίνησης της συνδιαλλαγής</translation>
     </message>
     <message>
         <source>Unable to commit transaction</source>
-        <translation>Δεν ήταν δυνατή η εκτέλεση της συνδιαλλαγής</translation>
+        <translation>Αδυναμία εκτέλεσης της συνδιαλλαγής</translation>
     </message>
     <message>
         <source>Unable to rollback transaction</source>
-        <translation>Δεν ήταν δυνατή η ακύρωση της συνδιαλλαγής</translation>
+        <translation>Αδυναμία ακύρωσης της συνδιαλλαγής</translation>
     </message>
 </context>
 <context>
     <name>QIBaseResult</name>
     <message>
         <source>Unable to create BLOB</source>
-        <translation>Δεν ήταν δυνατή η δημιουργία BLOB</translation>
+        <translation>Αδυναμία δημιουργίας BLOB</translation>
     </message>
     <message>
         <source>Unable to write BLOB</source>
-        <translation>Δεν ήταν δυνατή η εγγραφή BLOB</translation>
+        <translation>Αδυναμία εγγραφής BLOB</translation>
     </message>
     <message>
         <source>Unable to open BLOB</source>
-        <translation>Δεν ήταν δυνατό το άνοιγμα BLOB</translation>
+        <translation>Αδυναμία ανοίγματος BLOB</translation>
     </message>
     <message>
         <source>Unable to read BLOB</source>
-        <translation>Δεν ήταν δυνατή η ανάγνωση BLOB</translation>
+        <translation>Αδυναμία ανάγνωσης BLOB</translation>
     </message>
     <message>
         <source>Could not find array</source>
-        <translation>Δεν ήταν δυνατή η εύρεση του πίνακα</translation>
+        <translation>Αδυναμία εύρεσης πίνακα</translation>
     </message>
     <message>
         <source>Could not get array data</source>
@@ -1893,7 +1893,7 @@ Do you want to delete it anyway?</source>
     </message>
     <message>
         <source>QLibrary::unload_sys: Cannot unload %1 (%2)</source>
-        <translation>QLibrary::load_sys: Δεν μπορεί να ξεφορτωθεί %1 (%2)</translation>
+        <translation>QLibrary::load_sys: Δεν μπορεί να αποφορτωθεί %1 (%2)</translation>
     </message>
     <message>
         <source>QLibrary::resolve_sys: Symbol "%1" undefined in %2 (%3)</source>
@@ -1944,7 +1944,7 @@ Do you want to delete it anyway?</source>
     </message>
     <message>
         <source>&Redo</source>
-        <translation>Ακύρωση Αναίρεσης</translation>
+        <translation>Επαναφορά</translation>
     </message>
     <message>
         <source>Cu&t</source>
@@ -2146,7 +2146,7 @@ Do you want to delete it anyway?</source>
     </message>
     <message>
         <source>Stay on &Top</source>
-        <translation>Παραμονή στην επιφάνεια</translation>
+        <translation>Παραμονή σε πρώτο πλάνο</translation>
     </message>
     <message>
         <source>&Close</source>
@@ -2208,7 +2208,7 @@ Do you want to delete it anyway?</source>
     </message>
     <message>
         <source>About Qt</source>
-        <translation>Πληροφορίες για το Qt</translation>
+        <translation>Σχετικά με το Qt</translation>
     </message>
     <message>
         <source><p>This program uses Qt version %1.</p></source>
@@ -2224,7 +2224,7 @@ Do you want to delete it anyway?</source>
     </message>
     <message>
         <source><p>This program uses Qt Open Source Edition version %1.</p><p>Qt Open Source Edition is intended for the development of Open Source applications. You need a commercial Qt license for development of proprietary (closed source) applications.</p><p>Please see <a href="http://www.trolltech.com/company/model/">www.trolltech.com/company/model/</a> for an overview of Qt licensing.</p></source>
-        <translation><p>Αυτο το πρόγραμμα χρησιμοποιεί την Qt Open Source Edition version %1.</p><p>Το Qt Open Source Edition αποσκοπεί στην ανάπτυξη Open Source εφαρμογών. Για την ανάπτυξη ιδιωτικών (closed source) εφαρμογών απαιτείται η εμπορική άδεια Qt</p><p>Για την επισκόπηση της Qt άδειας χρήσης δείτε <a  href="http://www.trolltech.com/company/model/' www.trolltech.com/company/model</a>.</p></translation>
+        <translation><p>Αυτο το πρόγραμμα χρησιμοποιεί την Qt Open Source Edition version %1.</p><p>Το Qt Open Source Edition αποσκοπεί στην ανάπτυξη Open Source εφαρμογών. Για την ανάπτυξη ιδιωτικών (closed source) εφαρμογών απαιτείται η εμπορική άδεια Qt</p><p>Για την εμφάνιση της Qt άδειας χρήσης δείτε <a  href="http://www.trolltech.com/company/model/' www.trolltech.com/company/model</a>.</p></translation>
     </message>
     <message>
         <source><h3>About Qt</h3>%1<p>Qt is a C++ toolkit for cross-platform application development.</p><p>Qt provides single-source portability across MS&nbsp;Windows, Mac&nbsp;OS&nbsp;X, Linux, and all major commercial Unix variants. Qt is also available for embedded devices as Qt for Embedded Linux and Qt for Windows CE.</p><p>Qt is a Nokia product. See <a href="http://www.trolltech.com/qt/">www.trolltech.com/qt/&l [...]
@@ -2273,7 +2273,7 @@ Do you want to delete it anyway?</source>
     </message>
     <message>
         <source>Invalid socket descriptor</source>
-        <translation>Μη έγκυρη οπεριγραφή socket</translation>
+        <translation>Μη έγκυρη περιγραφή socket</translation>
     </message>
     <message>
         <source>Network unreachable</source>
@@ -2420,125 +2420,125 @@ Do you want to delete it anyway?</source>
     <name>QOCIDriver</name>
     <message>
         <source>Unable to logon</source>
-        <translation>Αδύνατη η σύνδεση</translation>
+        <translation>Αδυναμία σύνδεσης</translation>
     </message>
     <message>
         <source>Unable to initialize</source>
         <comment>QOCIDriver</comment>
-        <translation>Αδύνατη η αρχικοποίηση</translation>
+        <translation>Αδυναμία εκκίνησης</translation>
     </message>
     <message>
         <source>Unable to begin transaction</source>
-        <translation>Δεν ήταν δυνατή η εκκίνηση της συνδιαλλαγής</translation>
+        <translation>Αδυναμία εκκίνησης συνδιαλλαγής</translation>
     </message>
     <message>
         <source>Unable to commit transaction</source>
-        <translation>Δεν ήταν δυνατή η εκτέλεση της συνδιαλλαγής</translation>
+        <translation>Αδυναμία εκτέλεσης συνδιαλλαγής</translation>
     </message>
     <message>
         <source>Unable to rollback transaction</source>
-        <translation>Δεν ήταν δυνατή η ακύρωση της συνδιαλλαγής</translation>
+        <translation>Αδυναμία ακύρωσης συνδιαλλαγής</translation>
     </message>
 </context>
 <context>
     <name>QOCIResult</name>
     <message>
         <source>Unable to bind column for batch execute</source>
-        <translation>Δεν ήταν δυνατή η δέσμευση της στήλης για την εκτέλεση της δέσμης</translation>
+        <translation>Αδυναμία δέσμευσης στήλης για εκτέλεση δέσμης</translation>
     </message>
     <message>
         <source>Unable to execute batch statement</source>
-        <translation>Δεν ήταν δυνατή η εκτέλεση της πρότασης της δέσμης</translation>
+        <translation>Αδυναμία εκτέλεσης πρότασης δέσμης</translation>
     </message>
     <message>
         <source>Unable to goto next</source>
-        <translation>Δεν ήταν δυνατή η συνέχιση στο επόμενο</translation>
+        <translation>Αδυναμία συνέχισης στο επόμενο</translation>
     </message>
     <message>
         <source>Unable to alloc statement</source>
-        <translation>Δεν ήταν δυνατός ο εντοπισμός της πρότασης</translation>
+        <translation>Αδυναμία εντοπισμού της πρότασης</translation>
     </message>
     <message>
         <source>Unable to prepare statement</source>
-        <translation>Δεν ήταν δυνατή η προετοιμασία της πρότασης</translation>
+        <translation>Αδυναμία προετοιμασίας πρότασης</translation>
     </message>
     <message>
         <source>Unable to bind value</source>
-        <translation>Δεν ήταν δυνατή η δέσμευση της τιμής</translation>
+        <translation>Αδυναμία δέσμευσης τιμής</translation>
     </message>
     <message>
         <source>Unable to execute select statement</source>
-        <translation>Δεν ήταν δυνατή η εκτέλεση της πρότασης επιλογής</translation>
+        <translation>Αδυναμία εκτέλεσης πρότασης επιλογής</translation>
     </message>
     <message>
         <source>Unable to execute statement</source>
-        <translation>Δεν ήταν δυνατή η εκτέλεση της πρότασης</translation>
+        <translation>Αδυναμία εκτέλεσης πρότασης</translation>
     </message>
 </context>
 <context>
     <name>QODBCDriver</name>
     <message>
         <source>Unable to connect</source>
-        <translation>Δεν ήταν δυνατή η σύνδεση</translation>
+        <translation>Αδυναμία σύνδεσης</translation>
     </message>
     <message>
         <source>Unable to connect - Driver doesn't support all needed functionality</source>
-        <translation>Δεν ήταν δυνατή η σύνδεση - Ο οδηγός δεν υποστηρίζει την απαραίτητη λειτουργικότητα</translation>
+        <translation>Αδυναμία σύνδεσης - Ο οδηγός δεν υποστηρίζει την απαραίτητη λειτουργικότητα</translation>
     </message>
     <message>
         <source>Unable to disable autocommit</source>
-        <translation>Δεν ήταν δυνατή η απενεργοποίηση του αυτόματου ορισμού</translation>
+        <translation>Αδυναμία απενεργοποίησης αυτόματου ορισμού</translation>
     </message>
     <message>
         <source>Unable to commit transaction</source>
-        <translation>Δεν ήταν δυνατή η εκτέλεση της συνδιαλλαγής</translation>
+        <translation>Αδυναμία εκτέλεσης συνδιαλλαγής</translation>
     </message>
     <message>
         <source>Unable to rollback transaction</source>
-        <translation>Δεν ήταν δυνατή η ακύρωση της συνδιαλλαγής</translation>
+        <translation>Αδυναμία ακύρωσης συνδιαλλαγής</translation>
     </message>
     <message>
         <source>Unable to enable autocommit</source>
-        <translation>Δεν ήταν δυνατή η ενεργοποίηση του αυτόματου ορισμού</translation>
+        <translation>Αδυναμία ενεργοποίησης αυτόματου ορισμού</translation>
     </message>
 </context>
 <context>
     <name>QODBCResult</name>
     <message>
         <source>QODBCResult::reset: Unable to set 'SQL_CURSOR_STATIC' as statement attribute. Please check your ODBC driver configuration</source>
-        <translation>QODBCResult: Δεν ήταν δυνατός ο ορισμός του 'SQL_CURSOS_STATIC' σαν παράμετρο της πρότασης. Ελέγξτε τις ρυθμίσεις του οδηγού ODBC</translation>
+        <translation>QODBCResult: Αδυναμία ορισμού του 'SQL_CURSOS_STATIC' σαν παράμετρο της πρότασης. Ελέγξτε τις ρυθμίσεις του οδηγού ODBC</translation>
     </message>
     <message>
         <source>Unable to execute statement</source>
-        <translation>Δεν ήταν δυνατή η εκτέλεση της πρότασης</translation>
+        <translation>Αδυναμία εκτέλεσης πρότασης</translation>
     </message>
     <message>
         <source>Unable to fetch next</source>
-        <translation>Δεν ήταν δυνατή η προσκόμιση του επόμενου</translation>
+        <translation>Αδυναμία προσκόμισης επόμενου</translation>
     </message>
     <message>
         <source>Unable to prepare statement</source>
-        <translation>Δεν ήταν δυνατή η προετοιμασία της πρότασης</translation>
+        <translation>Αδυναμία προετοιμασίας πρότασης</translation>
     </message>
     <message>
         <source>Unable to bind variable</source>
-        <translation>Δεν ήταν δυνατή η δέσμευση της τιμής</translation>
+        <translation>Αδυναμία δέσμευσης τιμής</translation>
     </message>
     <message>
         <source>Unable to fetch last</source>
-        <translation>Δεν ήταν δυνατή η προσκόμιση του τελευταίου</translation>
+        <translation>Αδυναμία προσκόμισης τελευταίου</translation>
     </message>
     <message>
         <source>Unable to fetch</source>
-        <translation>Δεν ήταν δυνατή η προσκόμιση</translation>
+        <translation>Αδυναμία προσκόμισης</translation>
     </message>
     <message>
         <source>Unable to fetch first</source>
-        <translation>Δεν ήταν δυνατή η προσκόμιση του πρώτου</translation>
+        <translation>Αδυναμία προσκόμισης πρώτου</translation>
     </message>
     <message>
         <source>Unable to fetch previous</source>
-        <translation>Δεν ήταν δυνατή η προσκόμιση του προηγούμενου</translation>
+        <translation>Αδυναμία προσκόμισης προηγούμενου</translation>
     </message>
 </context>
 <context>
@@ -2587,38 +2587,38 @@ Do you want to delete it anyway?</source>
     <name>QPSQLDriver</name>
     <message>
         <source>Unable to connect</source>
-        <translation>Δεν ήταν δυνατή η σύνδεση</translation>
+        <translation>Αδυναμία σύνδεσης</translation>
     </message>
     <message>
         <source>Could not begin transaction</source>
-        <translation>Δεν ήταν δυνατή η εκκίνηση της συνδιαλλαγής</translation>
+        <translation>Αδυναμία εκκίνησης συνδιαλλαγής</translation>
     </message>
     <message>
         <source>Could not commit transaction</source>
-        <translation>Δεν ήταν δυνατή η εκτέλεση της συνδιαλλαγής</translation>
+        <translation>Αδυναμία εκτέλεσης συνδιαλλαγής</translation>
     </message>
     <message>
         <source>Could not rollback transaction</source>
-        <translation>Δεν ήταν δυνατή η ακύρωση της συνδιαλλαγής</translation>
+        <translation>Αδυναμία ακύρωσης συνδιαλλαγής</translation>
     </message>
     <message>
         <source>Unable to subscribe</source>
-        <translation>Δεν ήταν δυνατή η συνδρομή</translation>
+        <translation>Αδυναμία συνδρομής</translation>
     </message>
     <message>
         <source>Unable to unsubscribe</source>
-        <translation>Δεν ήταν δυνατή η αποσυνδρομή</translation>
+        <translation>Αδυναμία αποσυνδρομής</translation>
     </message>
 </context>
 <context>
     <name>QPSQLResult</name>
     <message>
         <source>Unable to create query</source>
-        <translation>Δεν ήταν δυνατή η δημιουργία του ερωτήματος</translation>
+        <translation>Αδυναμία δημιουργίας ερωτήματος</translation>
     </message>
     <message>
         <source>Unable to prepare statement</source>
-        <translation>Δεν ήταν δυνατή η προετοιμασία της πρότασης</translation>
+        <translation>Αδυναμία προετοιμασίας πρότασης</translation>
     </message>
 </context>
 <context>
@@ -2719,11 +2719,11 @@ Do you want to delete it anyway?</source>
     <name>QPrintDialog</name>
     <message>
         <source>locally connected</source>
-        <translation>Συνδεδεμένος τοπικά</translation>
+        <translation>Τοπική σύνδεση</translation>
     </message>
     <message>
         <source>Aliases: %1</source>
-        <translation>Αναγνωριστικό : %1</translation>
+        <translation>Αναγνωριστικά : %1</translation>
     </message>
     <message>
         <source>unknown</source>
@@ -2731,7 +2731,7 @@ Do you want to delete it anyway?</source>
     </message>
     <message>
         <source>Print To File ...</source>
-        <translation>Εκτύπωση σε αρχείο ...</translation>
+        <translation>Εκτύπωση στο αρχείο ...</translation>
     </message>
     <message>
         <source>File %1 is not writable.
@@ -2743,13 +2743,13 @@ Please choose a different file name.</source>
         <source>%1 already exists.
 Do you want to overwrite it?</source>
         <translation>%1 υπάρχει ήδη.
-Θέλετε να επαναγραφτεί ?</translation>
+Θέλετε να επαναεγγραφεί;</translation>
     </message>
     <message>
         <source>%1 is a directory.
 Please choose a different file name.</source>
         <translation>%1 είναι φάκελος.
-Παρακαλώ διαλέξτε άλλο όνομα αρχείου.</translation>
+Παρακαλώ επιλέξτε άλλο όνομα αρχείου.</translation>
     </message>
     <message>
         <source>A0</source>
@@ -3105,7 +3105,7 @@ Please choose a different file name.</source>
     </message>
     <message>
         <source>Output &file:</source>
-        <translation>Όνομα αρχείου:</translation>
+        <translation>Εξαγώμενο αρχείο:</translation>
     </message>
     <message>
         <source>...</source>
@@ -3116,7 +3116,7 @@ Please choose a different file name.</source>
     <name>QProgressDialog</name>
     <message>
         <source>Cancel</source>
-        <translation>Άκυρο</translation>
+        <translation>Ακύρωση</translation>
     </message>
 </context>
 <context>
@@ -3137,7 +3137,7 @@ Please choose a different file name.</source>
     <name>QRegExp</name>
     <message>
         <source>no error occurred</source>
-        <translation>δεν δημιουργήθηκαν προβλήματα</translation>
+        <translation>δεν προέκυψαν προβλήματα</translation>
     </message>
     <message>
         <source>disabled feature used</source>
@@ -3176,15 +3176,15 @@ Please choose a different file name.</source>
     <name>QSQLite2Driver</name>
     <message>
         <source>Error to open database</source>
-        <translation>Λάθος στο άνοιγμα της βάσης δεδομένων</translation>
+        <translation>Λάθος ανοίγματος βάσης δεδομένων</translation>
     </message>
     <message>
         <source>Unable to begin transaction</source>
-        <translation>Δεν ήταν δυνατή η εκκίνηση της συνδιαλλαγής</translation>
+        <translation>Αδυναμία εκκίνησης συνδιαλλαγής</translation>
     </message>
     <message>
         <source>Unable to commit transaction</source>
-        <translation>Δεν ήταν δυνατή η εκτέλεση της συνδιαλλαγής</translation>
+        <translation>Αδυναμία εκτέλεσης συνδιαλλαγής</translation>
     </message>
     <message>
         <source>Unable to rollback Transaction</source>
@@ -3195,11 +3195,11 @@ Please choose a different file name.</source>
     <name>QSQLite2Result</name>
     <message>
         <source>Unable to fetch results</source>
-        <translation>Δεν ήταν δυνατή η προσκόμιση των αποτελεσμάτων</translation>
+        <translation>Αδυναμία προσκόμισης αποτελεσμάτων</translation>
     </message>
     <message>
         <source>Unable to execute statement</source>
-        <translation>Δεν ήταν δυνατή η εκτέλεση της πρότασης</translation>
+        <translation>Αδυναμία εκτέλεσης πρότασης</translation>
     </message>
 </context>
 <context>
@@ -3256,7 +3256,7 @@ Please choose a different file name.</source>
     <name>QScrollBar</name>
     <message>
         <source>Scroll here</source>
-        <translation>Κύλισε εδώ</translation>
+        <translation>Κύλιση εδώ</translation>
     </message>
     <message>
         <source>Left edge</source>
@@ -3323,7 +3323,7 @@ Please choose a different file name.</source>
     <name>QSharedMemory</name>
     <message>
         <source>%1: unable to set key on lock</source>
-        <translation>%1: αδύνατο να τεθεί το κλειδί</translation>
+        <translation>%1: αδυναμία ορισμού κλειδιού κατά το κλείδωμα</translation>
     </message>
     <message>
         <source>%1: create size is less then 0</source>
@@ -3331,11 +3331,11 @@ Please choose a different file name.</source>
     </message>
     <message>
         <source>%1: unable to lock</source>
-        <translation>%1: αδύνατο το κλείδωμα</translation>
+        <translation>%1: αδυναμία κλειδώματος</translation>
     </message>
     <message>
         <source>%1: unable to unlock</source>
-        <translation>%1: αδύνατο το ξεκλείδωμα</translation>
+        <translation>%1: αδυναμία ξεκλειδώματος</translation>
     </message>
     <message>
         <source>%1: permission denied</source>
@@ -3347,7 +3347,7 @@ Please choose a different file name.</source>
     </message>
     <message>
         <source>%1: doesn't exists</source>
-        <translation>%1: υπάρχει ήδη</translation>
+        <translation>%1: δεν υπάρχει</translation>
     </message>
     <message>
         <source>%1: out of resources</source>
@@ -3359,7 +3359,7 @@ Please choose a different file name.</source>
     </message>
     <message>
         <source>%1: key is empty</source>
-        <translation>%1: το κλειδί είναι άδειο</translation>
+        <translation>%1: το κλειδί είναι κενό</translation>
     </message>
     <message>
         <source>%1: unix key file doesn't exists</source>
@@ -3371,7 +3371,7 @@ Please choose a different file name.</source>
     </message>
     <message>
         <source>%1: unable to make key</source>
-        <translation>%1: αδύνατη η δημιουργία κλειδιού</translation>
+        <translation>%1: αδυναμία δημιουργίας κλειδιού</translation>
     </message>
     <message>
         <source>%1: system-imposed size restrictions</source>
@@ -3379,7 +3379,7 @@ Please choose a different file name.</source>
     </message>
     <message>
         <source>%1: not attached</source>
-        <translation></translation>
+        <translation>%1: Μη συνδεδεμένο</translation>
     </message>
 </context>
 <context>
@@ -3806,7 +3806,7 @@ Please choose a different file name.</source>
     </message>
     <message>
         <source>Delete this record?</source>
-        <translation>Θέλετε να διαγράψετε αυτή την εγγραφή ?</translation>
+        <translation>Διαγραφή εγγραφής;</translation>
     </message>
     <message>
         <source>Yes</source>
@@ -3826,7 +3826,7 @@ Please choose a different file name.</source>
     </message>
     <message>
         <source>Save edits?</source>
-        <translation>Αποθήκευση αλλαγών ?</translation>
+        <translation>Αποθήκευση αλλαγών;</translation>
     </message>
     <message>
         <source>Cancel</source>
@@ -3960,7 +3960,7 @@ Please choose a different file name.</source>
     <name>QUdpSocket</name>
     <message>
         <source>This platform does not support IPv6</source>
-        <translation>Η πλατφόρμα δεν υποστηρίζει το IPv6</translation>
+        <translation>Αυτή η πλατφόρμα δεν υποστηρίζει IPv6</translation>
     </message>
 </context>
 <context>
@@ -4051,11 +4051,11 @@ Please choose a different file name.</source>
     </message>
     <message>
         <source>Cannot show URL</source>
-        <translation>Δεν μπορεί να εμφανιστεί το URL</translation>
+        <translation>Αδυναμία εμφάνισης URL</translation>
     </message>
     <message>
         <source>Frame load interruped by policy change</source>
-        <translation>Η φόρτωση του πλαισίου διακόπηκε λόγω αλλαγής πολιτικής</translation>
+        <translation>Η φόρτωση του πλαισίου διακόπηκε λόγω αλλαγής κανόνων</translation>
     </message>
     <message>
         <source>Cannot show mimetype</source>
@@ -4445,7 +4445,7 @@ Please choose a different file name.</source>
     </message>
     <message>
         <source>error triggered by consumer</source>
-        <translation>σφάλμα ενεργοποιήθηκε από τον καταναλωτή</translation>
+        <translation>σφάλμα ενεργοποιημένο από τον καταναλωτή</translation>
     </message>
     <message>
         <source>unexpected end of file</source>
@@ -4477,7 +4477,7 @@ Please choose a different file name.</source>
     </message>
     <message>
         <source>version expected while reading the XML declaration</source>
-        <translation>αναμενόταν η έκδοση ενώ διαβαζόταν η δήλωση XML</translation>
+        <translation>αναμενόταν η έκδοση κατά την ανάγνωση της δήλωσης XML</translation>
     </message>
     <message>
         <source>wrong value for standalone declaration</source>
@@ -5253,18 +5253,18 @@ Please choose a different file name.</source>
     </message>
     <message>
         <source>Attribute %1 can't be serialized because it appears at the top level.</source>
-        <translation></translation>
+        <translation>Η ιδιότητα %1 δε μπορεί να σειριοποιηθεί επειδή εμφανίζεται στο άνω επίπεδο.</translation>
     </message>
     <message>
         <source>The namespace for a user defined function cannot be empty (try the predefined prefix %1 which exists for cases like this)</source>
-        <translation></translation>
+        <translation>Ο χώρος ονομάτων για μια συνάρτηση ορισμένη από το χρήστη δε μπορεί να ειναι κενός (δοκιμάστε το προκαθορισμένο πρόθεμα %1 που υπάρχει για περιπτώσεις σαν αυτή)</translation>
     </message>
 </context>
 <context>
     <name>VolumeSlider</name>
     <message>
         <source>Muted</source>
-        <translation>Σιώπηση</translation>
+        <translation>Αθόρυβο</translation>
     </message>
     <message>
         <source>Volume: %1%</source>
@@ -5275,7 +5275,7 @@ Please choose a different file name.</source>
     <name>WebCore::PlatformScrollbar</name>
     <message>
         <source>Scroll here</source>
-        <translation>Κύλισε εδώ</translation>
+        <translation>Κύλιση εδώ</translation>
     </message>
     <message>
         <source>Left edge</source>
@@ -5311,19 +5311,19 @@ Please choose a different file name.</source>
     </message>
     <message>
         <source>Scroll left</source>
-        <translation>Κύλισε αριστερά</translation>
+        <translation>Κύλιση αριστερά</translation>
     </message>
     <message>
         <source>Scroll up</source>
-        <translation>Κύλισε πάνω</translation>
+        <translation>Κύλιση πάνω</translation>
     </message>
     <message>
         <source>Scroll right</source>
-        <translation>Κύλισε δεξιά</translation>
+        <translation>Κύλιση δεξιά</translation>
     </message>
     <message>
         <source>Scroll down</source>
-        <translation>Κύλισε κάτω</translation>
+        <translation>Κύλιση κάτω</translation>
     </message>
 </context>
 </TS>
diff --git a/src/VBox/Frontends/VirtualBox/nls/qt_pl.ts b/src/VBox/Frontends/VirtualBox/nls/qt_pl.ts
index d679bdf..f9b6182 100644
--- a/src/VBox/Frontends/VirtualBox/nls/qt_pl.ts
+++ b/src/VBox/Frontends/VirtualBox/nls/qt_pl.ts
@@ -29,7 +29,7 @@
     </message>
     <message>
         <source>About %1</source>
-        <translation>O programie %1…</translation>
+        <translation>O programie %1</translation>
     </message>
 </context>
 <context>
@@ -104,7 +104,7 @@ zainstalowałeś libgstreamer-plugins-base.</translation>
     <message numerus="yes">
         <source>A required codec is missing. You need to install the following codec(s) to play this content: %0</source>
         <translation>
-            <numerusform>Brak wymaganego kodeka. Aby odtworzyć zawartość musisz zainstalować poniższy kodek: %0</numerusform>
+            <numerusform>Brak wymaganego kodeka. Aby odtworzyć zawartość musisz zainstalować poniższe kodeki: %0</numerusform>
             <numerusform>Brak wymaganego kodeka. Aby odtworzyć zawartość musisz zainstalować poniższe kodeki: %0</numerusform>
             <numerusform>Brak wymaganego kodeka. Aby odtworzyć zawartość musisz zainstalować poniższe kodeki: %0</numerusform>
         </translation>
@@ -4903,7 +4903,7 @@ Proszę wybrać inną nazwę pliku.</translation>
     </message>
     <message>
         <source>In the replacement string, %1 must be followed by at least one digit when not escaped.</source>
-        <translation>W ciągu zastępczym, po %1 musi następować przynajmniej jedna cyfra</translation>
+        <translation>W ciągu zastępczym, po %1 musi się znajdować przynajmniej jedna cyfra.</translation>
     </message>
     <message>
         <source>In the replacement string, %1 can only be used to escape itself or %2, not %3</source>
diff --git a/src/VBox/Frontends/VirtualBox/nls/qt_sr.ts b/src/VBox/Frontends/VirtualBox/nls/qt_sr.ts
index c7489cb..853d356 100644
--- a/src/VBox/Frontends/VirtualBox/nls/qt_sr.ts
+++ b/src/VBox/Frontends/VirtualBox/nls/qt_sr.ts
@@ -1,6 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
 <!DOCTYPE TS><TS version="1.1" language="fr_FR">
-<defaultcodec></defaultcodec>
 <context>
     <name>MAC_APPLICATION_MENU</name>
     <message>
diff --git a/src/VBox/Frontends/VirtualBox/src/VBoxFBOverlay.cpp b/src/VBox/Frontends/VirtualBox/src/VBoxFBOverlay.cpp
index 719290d..ed002b8 100644
--- a/src/VBox/Frontends/VirtualBox/src/VBoxFBOverlay.cpp
+++ b/src/VBox/Frontends/VirtualBox/src/VBoxFBOverlay.cpp
@@ -4868,6 +4868,8 @@ void VBoxQGLOverlay::vboxDoVHWACmdExec(void *cmd)
             Assert(!mGlOn == !mOverlayImage.hasSurfaces());
             initGl();
             Assert(!mGlOn == !mOverlayImage.hasSurfaces());
+            pCmd->rc = VINF_SUCCESS;
+            break;
         case VBOXVHWACMD_TYPE_DISABLE:
             pCmd->rc = VINF_SUCCESS;
             break;
diff --git a/src/VBox/Frontends/VirtualBox/src/extradata/UIExtraDataDefs.cpp b/src/VBox/Frontends/VirtualBox/src/extradata/UIExtraDataDefs.cpp
index 0abba9c..e7e4db7 100644
--- a/src/VBox/Frontends/VirtualBox/src/extradata/UIExtraDataDefs.cpp
+++ b/src/VBox/Frontends/VirtualBox/src/extradata/UIExtraDataDefs.cpp
@@ -91,6 +91,7 @@ const char* UIExtraDataDefs::GUI_Geometry_State_Max = "max";
 #ifndef VBOX_WS_MAC
 const char* UIExtraDataDefs::GUI_MenuBar_Enabled = "GUI/MenuBar/Enabled";
 #endif /* !VBOX_WS_MAC */
+const char* UIExtraDataDefs::GUI_MenuBar_ContextMenu_Enabled = "GUI/MenuBar/ContextMenu/Enabled";
 const char* UIExtraDataDefs::GUI_RestrictedRuntimeMenus = "GUI/RestrictedRuntimeMenus";
 const char* UIExtraDataDefs::GUI_RestrictedRuntimeApplicationMenuActions = "GUI/RestrictedRuntimeApplicationMenuActions";
 const char* UIExtraDataDefs::GUI_RestrictedRuntimeMachineMenuActions = "GUI/RestrictedRuntimeMachineMenuActions";
@@ -131,6 +132,7 @@ const char* UIExtraDataDefs::GUI_MiniToolBarAutoHide = "GUI/MiniToolBarAutoHide"
 const char* UIExtraDataDefs::GUI_MiniToolBarAlignment = "GUI/MiniToolBarAlignment";
 #endif /* !VBOX_WS_MAC */
 const char* UIExtraDataDefs::GUI_StatusBar_Enabled = "GUI/StatusBar/Enabled";
+const char* UIExtraDataDefs::GUI_StatusBar_ContextMenu_Enabled = "GUI/StatusBar/ContextMenu/Enabled";
 const char* UIExtraDataDefs::GUI_RestrictedStatusBarIndicators = "GUI/RestrictedStatusBarIndicators";
 const char* UIExtraDataDefs::GUI_StatusBar_IndicatorOrder = "GUI/StatusBar/IndicatorOrder";
 #ifdef VBOX_WS_MAC
diff --git a/src/VBox/Frontends/VirtualBox/src/extradata/UIExtraDataDefs.h b/src/VBox/Frontends/VirtualBox/src/extradata/UIExtraDataDefs.h
index ccbfaed..d11ae9a 100644
--- a/src/VBox/Frontends/VirtualBox/src/extradata/UIExtraDataDefs.h
+++ b/src/VBox/Frontends/VirtualBox/src/extradata/UIExtraDataDefs.h
@@ -157,6 +157,8 @@ namespace UIExtraDataDefs
         /** Holds Runtime UI menu-bar availability status. */
         extern const char* GUI_MenuBar_Enabled;
 #endif /* !VBOX_WS_MAC */
+        /** Holds Runtime UI menu-bar context-menu availability status. */
+        extern const char* GUI_MenuBar_ContextMenu_Enabled;
         /** Holds restricted Runtime UI menu types. */
         extern const char* GUI_RestrictedRuntimeMenus;
         /** Holds restricted Runtime UI action types for 'Application' menu. */
@@ -230,6 +232,8 @@ namespace UIExtraDataDefs
 #endif /* !VBOX_WS_MAC */
         /** Holds Runtime UI status-bar availability status. */
         extern const char* GUI_StatusBar_Enabled;
+        /** Holds Runtime UI status-bar context-menu availability status. */
+        extern const char* GUI_StatusBar_ContextMenu_Enabled;
         /** Holds restricted Runtime UI status-bar indicators. */
         extern const char* GUI_RestrictedStatusBarIndicators;
         /** Holds Runtime UI status-bar indicator order. */
diff --git a/src/VBox/Frontends/VirtualBox/src/extradata/UIExtraDataManager.cpp b/src/VBox/Frontends/VirtualBox/src/extradata/UIExtraDataManager.cpp
index 14aed8e..d5c33e2 100644
--- a/src/VBox/Frontends/VirtualBox/src/extradata/UIExtraDataManager.cpp
+++ b/src/VBox/Frontends/VirtualBox/src/extradata/UIExtraDataManager.cpp
@@ -1967,6 +1967,10 @@ QStringList UIExtraDataManagerWindow::knownExtraDataKeys()
            << GUI_MachineWindowIcons << GUI_MachineWindowNamePostfix
 #endif /* !VBOX_WS_MAC */
            << GUI_LastNormalWindowPosition << GUI_LastScaleWindowPosition
+#ifndef VBOX_WS_MAC
+           << GUI_MenuBar_Enabled
+#endif
+           << GUI_MenuBar_ContextMenu_Enabled
            << GUI_RestrictedRuntimeMenus
            << GUI_RestrictedRuntimeApplicationMenuActions
            << GUI_RestrictedRuntimeMachineMenuActions
@@ -1997,7 +2001,7 @@ QStringList UIExtraDataManagerWindow::knownExtraDataKeys()
 #ifndef VBOX_WS_MAC
            << GUI_ShowMiniToolBar << GUI_MiniToolBarAutoHide << GUI_MiniToolBarAlignment
 #endif /* !VBOX_WS_MAC */
-           << GUI_StatusBar_Enabled << GUI_RestrictedStatusBarIndicators << GUI_StatusBar_IndicatorOrder
+           << GUI_StatusBar_Enabled << GUI_StatusBar_ContextMenu_Enabled << GUI_RestrictedStatusBarIndicators << GUI_StatusBar_IndicatorOrder
 #ifdef VBOX_WS_MAC
            << GUI_RealtimeDockIconUpdateEnabled << GUI_RealtimeDockIconUpdateMonitor << GUI_DockIconDisableOverlay
 #endif /* VBOX_WS_MAC */
@@ -2771,6 +2775,18 @@ void UIExtraDataManager::setMenuBarEnabled(bool fEnabled, const QString &strID)
 }
 #endif /* !VBOX_WS_MAC */
 
+bool UIExtraDataManager::menuBarContextMenuEnabled(const QString &strID)
+{
+    /* 'True' unless feature restricted: */
+    return !isFeatureRestricted(GUI_MenuBar_ContextMenu_Enabled, strID);
+}
+
+void UIExtraDataManager::setMenuBarContextMenuEnabled(bool fEnabled, const QString &strID)
+{
+    /* 'False' if feature restricted, null-string otherwise: */
+    setExtraDataString(GUI_MenuBar_ContextMenu_Enabled, toFeatureRestricted(!fEnabled), strID);
+}
+
 UIExtraDataMetaDefs::MenuType UIExtraDataManager::restrictedRuntimeMenuTypes(const QString &strID)
 {
     /* Prepare result: */
@@ -3479,6 +3495,18 @@ void UIExtraDataManager::setStatusBarEnabled(bool fEnabled, const QString &strID
     setExtraDataString(GUI_StatusBar_Enabled, toFeatureRestricted(!fEnabled), strID);
 }
 
+bool UIExtraDataManager::statusBarContextMenuEnabled(const QString &strID)
+{
+    /* 'True' unless feature restricted: */
+    return !isFeatureRestricted(GUI_StatusBar_ContextMenu_Enabled, strID);
+}
+
+void UIExtraDataManager::setStatusBarContextMenuEnabled(bool fEnabled, const QString &strID)
+{
+    /* 'False' if feature restricted, null-string otherwise: */
+    setExtraDataString(GUI_StatusBar_ContextMenu_Enabled, toFeatureRestricted(!fEnabled), strID);
+}
+
 QList<IndicatorType> UIExtraDataManager::restrictedStatusBarIndicators(const QString &strID)
 {
     /* Prepare result: */
diff --git a/src/VBox/Frontends/VirtualBox/src/extradata/UIExtraDataManager.h b/src/VBox/Frontends/VirtualBox/src/extradata/UIExtraDataManager.h
index 8cca037..bb85f0e 100644
--- a/src/VBox/Frontends/VirtualBox/src/extradata/UIExtraDataManager.h
+++ b/src/VBox/Frontends/VirtualBox/src/extradata/UIExtraDataManager.h
@@ -318,6 +318,11 @@ public:
         void setMenuBarEnabled(bool fEnabled, const QString &strID);
 #endif /* !VBOX_WS_MAC */
 
+        /** Returns whether Runtime UI menu-bar context-menu is enabled. */
+        bool menuBarContextMenuEnabled(const QString &strID);
+        /** Defines whether Runtime UI menu-bar context-menu is @a fEnabled. */
+        void setMenuBarContextMenuEnabled(bool fEnabled, const QString &strID);
+
         /** Returns restricted Runtime UI menu types. */
         UIExtraDataMetaDefs::MenuType restrictedRuntimeMenuTypes(const QString &strID);
         /** Defines restricted Runtime UI menu types. */
@@ -446,6 +451,11 @@ public:
         /** Defines whether Runtime UI status-bar is @a fEnabled. */
         void setStatusBarEnabled(bool fEnabled, const QString &strID);
 
+        /** Returns whether Runtime UI status-bar context-menu is enabled. */
+        bool statusBarContextMenuEnabled(const QString &strID);
+        /** Defines whether Runtime UI status-bar context-menu is @a fEnabled. */
+        void setStatusBarContextMenuEnabled(bool fEnabled, const QString &strID);
+
         /** Returns restricted Runtime UI status-bar indicator list. */
         QList<IndicatorType> restrictedStatusBarIndicators(const QString &strID);
         /** Defines restricted Runtime UI status-bar indicator @a list. */
diff --git a/src/VBox/Frontends/VirtualBox/src/precomp.h b/src/VBox/Frontends/VirtualBox/src/precomp.h
index a18ca23..344513f 100644
--- a/src/VBox/Frontends/VirtualBox/src/precomp.h
+++ b/src/VBox/Frontends/VirtualBox/src/precomp.h
@@ -106,8 +106,6 @@
 #endif
 #include <QMainWindow>
 #include <QMap>
-#include <QMdiArea>
-#include <QMdiSubWindow>
 #include <QMenu>
 #include <QMenuBar>
 #include <QMessageBox>
diff --git a/src/VBox/Frontends/VirtualBox/src/runtime/UIMachineView.cpp b/src/VBox/Frontends/VirtualBox/src/runtime/UIMachineView.cpp
index 262b9bd..627a779 100644
--- a/src/VBox/Frontends/VirtualBox/src/runtime/UIMachineView.cpp
+++ b/src/VBox/Frontends/VirtualBox/src/runtime/UIMachineView.cpp
@@ -311,30 +311,37 @@ void UIMachineView::sltPerformGuestResize(const QSize &toSize)
 
     /* Send new size-hint to the guest: */
     LogRel(("GUI: UIMachineView::sltPerformGuestResize: "
-            "Sending guest size-hint to screen %d as %dx%d\n",
+            "Sending guest size-hint to screen %d as %dx%d if necessary\n",
             (int)screenId(), size.width(), size.height()));
 
     /* If auto-mount of guest-screens (auto-pilot) enabled: */
     if (gEDataManager->autoMountGuestScreensEnabled(vboxGlobal().managedVMUuid()))
     {
-        /* If host and guest have same opinion about guest-screen visibility: */
-        if (uisession()->isScreenVisible(screenId()) == uisession()->isScreenVisibleHostDesires(screenId()))
-            display().SetVideoModeHint(screenId(),
-                                       uisession()->isScreenVisible(screenId()),
-                                       false, 0, 0, size.width(), size.height(), 0);
-        /* If host desires to have guest-screen disabled and guest-screen is enabled, retrying: */
-        else if (!uisession()->isScreenVisibleHostDesires(screenId()))
-            display().SetVideoModeHint(screenId(), false, false, 0, 0, 0, 0, 0);
-        /* If host desires to have guest-screen enabled and guest-screen is disabled, retrying: */
-        else if (uisession()->isScreenVisibleHostDesires(screenId()))
-            display().SetVideoModeHint(screenId(), true, false, 0, 0, size.width(), size.height(), 0);
+        /* Do not send a hint if nothing has changed to prevent the guest being notified about its own changes: */
+        if (   (int)m_pFrameBuffer->width() != size.width() || (int)m_pFrameBuffer->height() != size.height()
+            || uisession()->isScreenVisible(screenId()) != uisession()->isScreenVisibleHostDesires(screenId()))
+        {
+            /* If host and guest have same opinion about guest-screen visibility: */
+            if (uisession()->isScreenVisible(screenId()) == uisession()->isScreenVisibleHostDesires(screenId()))
+                display().SetVideoModeHint(screenId(),
+                                           uisession()->isScreenVisible(screenId()),
+                                           false, 0, 0, size.width(), size.height(), 0);
+            /* If host desires to have guest-screen disabled and guest-screen is enabled, retrying: */
+            else if (!uisession()->isScreenVisibleHostDesires(screenId()))
+                display().SetVideoModeHint(screenId(), false, false, 0, 0, 0, 0, 0);
+            /* If host desires to have guest-screen enabled and guest-screen is disabled, retrying: */
+            else if (uisession()->isScreenVisibleHostDesires(screenId()))
+                display().SetVideoModeHint(screenId(), true, false, 0, 0, size.width(), size.height(), 0);
+        }
     }
     /* If auto-mount of guest-screens (auto-pilot) disabled: */
     else
     {
-        display().SetVideoModeHint(screenId(),
-                                   uisession()->isScreenVisible(screenId()),
-                                   false, 0, 0, size.width(), size.height(), 0);
+        /* Do not send a hint if nothing has changed to prevent the guest being notified about its own changes: */
+        if ((int)m_pFrameBuffer->width() != size.width() || (int)m_pFrameBuffer->height() != size.height())
+            display().SetVideoModeHint(screenId(),
+                                       uisession()->isScreenVisible(screenId()),
+                                       false, 0, 0, size.width(), size.height(), 0);
     }
 }
 
@@ -352,64 +359,60 @@ void UIMachineView::sltHandleNotifyChange(int iWidth, int iHeight)
     if (uisession()->isGuestScreenUnDrawable())
         return;
 
-    /* If machine-window is visible: */
-    if (uisession()->isScreenVisible(m_uScreenId))
-    {
-        /* Get old frame-buffer size: */
-        const QSize frameBufferSizeOld = QSize(frameBuffer()->width(),
-                                               frameBuffer()->height());
+    /* Get old frame-buffer size: */
+    const QSize frameBufferSizeOld = QSize(frameBuffer()->width(),
+                                           frameBuffer()->height());
 
-        /* Perform frame-buffer mode-change: */
-        frameBuffer()->handleNotifyChange(iWidth, iHeight);
+    /* Perform frame-buffer mode-change: */
+    frameBuffer()->handleNotifyChange(iWidth, iHeight);
 
-        /* Get new frame-buffer size: */
-        const QSize frameBufferSizeNew = QSize(frameBuffer()->width(),
-                                               frameBuffer()->height());
+    /* Get new frame-buffer size: */
+    const QSize frameBufferSizeNew = QSize(frameBuffer()->width(),
+                                           frameBuffer()->height());
 
-        /* For 'scale' mode: */
-        if (visualStateType() == UIVisualStateType_Scale)
-        {
-            /* Assign new frame-buffer logical-size: */
-            frameBuffer()->setScaledSize(size());
+    /* For 'scale' mode: */
+    if (visualStateType() == UIVisualStateType_Scale)
+    {
+        /* Assign new frame-buffer logical-size: */
+        frameBuffer()->setScaledSize(size());
 
-            /* Forget the last full-screen size: */
-            uisession()->setLastFullScreenSize(screenId(), QSize(-1, -1));
-        }
-        /* For other than 'scale' mode: */
-        else
-        {
-            /* Adjust maximum-size restriction for machine-view: */
-            setMaximumSize(sizeHint());
+        /* Forget the last full-screen size: */
+        uisession()->setLastFullScreenSize(screenId(), QSize(-1, -1));
+    }
+    /* For other than 'scale' mode: */
+    else
+    {
+        /* Adjust maximum-size restriction for machine-view: */
+        setMaximumSize(sizeHint());
 
-            /* Disable the resize hint override hack and forget the last full-screen size: */
-            m_sizeHintOverride = QSize(-1, -1);
-            if (visualStateType() == UIVisualStateType_Normal)
-                uisession()->setLastFullScreenSize(screenId(), QSize(-1, -1));
+        /* Disable the resize hint override hack and forget the last full-screen size: */
+        m_sizeHintOverride = QSize(-1, -1);
+        if (visualStateType() == UIVisualStateType_Normal)
+            uisession()->setLastFullScreenSize(screenId(), QSize(-1, -1));
 
-            /* Force machine-window update own layout: */
-            QCoreApplication::sendPostedEvents(0, QEvent::LayoutRequest);
+        /* Force machine-window update own layout: */
+        QCoreApplication::sendPostedEvents(0, QEvent::LayoutRequest);
 
-            /* Update machine-view sliders: */
-            updateSliders();
+        /* Update machine-view sliders: */
+        updateSliders();
 
-            /* By some reason Win host forgets to update machine-window central-widget
-             * after main-layout was updated, let's do it for all the hosts: */
-            machineWindow()->centralWidget()->update();
+        /* By some reason Win host forgets to update machine-window central-widget
+         * after main-layout was updated, let's do it for all the hosts: */
+        machineWindow()->centralWidget()->update();
 
-            /* Normalize 'normal' machine-window geometry if necessary: */
-            if (visualStateType() == UIVisualStateType_Normal &&
-                frameBufferSizeNew != frameBufferSizeOld)
-                machineWindow()->normalizeGeometry(true /* adjust position */);
-        }
+        /* Normalize 'normal' machine-window geometry if necessary: */
+        if (visualStateType() == UIVisualStateType_Normal &&
+            frameBufferSizeNew != frameBufferSizeOld)
+            machineWindow()->normalizeGeometry(true /* adjust position */);
+    }
 
-        /* Perform frame-buffer rescaling: */
-        frameBuffer()->performRescale();
+    /* Perform frame-buffer rescaling: */
+    frameBuffer()->performRescale();
 
 #ifdef VBOX_WS_MAC
-        /* Update MacOS X dock icon size: */
-        machineLogic()->updateDockIconSize(screenId(), iWidth, iHeight);
+    /* Update MacOS X dock icon size: */
+    machineLogic()->updateDockIconSize(screenId(), iWidth, iHeight);
 #endif /* VBOX_WS_MAC */
-    }
 
     /* Notify frame-buffer resize: */
     emit sigFrameBufferResize();
diff --git a/src/VBox/Frontends/VirtualBox/src/runtime/UIMouseHandler.cpp b/src/VBox/Frontends/VirtualBox/src/runtime/UIMouseHandler.cpp
index f45f565..a8f9484 100644
--- a/src/VBox/Frontends/VirtualBox/src/runtime/UIMouseHandler.cpp
+++ b/src/VBox/Frontends/VirtualBox/src/runtime/UIMouseHandler.cpp
@@ -767,7 +767,9 @@ bool UIMouseHandler::eventFilter(QObject *pWatched, QEvent *pEvent)
                     }
 
                     /* This event should be also processed using next 'case': */
+                    /* fall thru */
                 }
+                /* fall thru */
                 case QEvent::MouseButtonPress:
                 case QEvent::MouseButtonDblClick:
                 {
diff --git a/src/VBox/Frontends/VirtualBox/src/runtime/UISlidingToolBar.cpp b/src/VBox/Frontends/VirtualBox/src/runtime/UISlidingToolBar.cpp
index b0f2405..37b4ffc 100644
--- a/src/VBox/Frontends/VirtualBox/src/runtime/UISlidingToolBar.cpp
+++ b/src/VBox/Frontends/VirtualBox/src/runtime/UISlidingToolBar.cpp
@@ -4,7 +4,7 @@
  */
 
 /*
- * Copyright (C) 2014-2016 Oracle Corporation
+ * Copyright (C) 2014-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;
@@ -20,9 +20,7 @@
 #else  /* !VBOX_WITH_PRECOMPILED_HEADERS */
 
 /* Qt includes: */
-# include <QMdiSubWindow>
 # include <QHBoxLayout>
-# include <QMdiArea>
 
 /* GUI includes: */
 # include "VBoxGlobal.h"
@@ -44,9 +42,8 @@ UISlidingToolBar::UISlidingToolBar(QWidget *pParentWidget, QWidget *pIndentWidge
     , m_pAnimation(0)
     , m_fExpanded(false)
     , m_pMainLayout(0)
-    , m_pMdiArea(0)
+    , m_pArea(0)
     , m_pWidget(pChildWidget)
-    , m_pEmbeddedWidget(0)
 {
     /* Prepare: */
     prepare();
@@ -101,17 +98,16 @@ void UISlidingToolBar::prepareContents()
         /* Configure main-layout: */
         m_pMainLayout->setContentsMargins(0, 0, 0, 0);
         m_pMainLayout->setSpacing(0);
-        /* Create mdi-area: */
-        m_pMdiArea = new QMdiArea;
-        AssertPtrReturnVoid(m_pMdiArea);
+        /* Create area: */
+        m_pArea = new QWidget;
+        AssertPtrReturnVoid(m_pArea);
         {
-            /* Configure mdi-area: */
-            m_pMdiArea->setAcceptDrops(true);
-            m_pMdiArea->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored);
-            QPalette pal1 = m_pMdiArea->palette();
+            /* Configure area: */
+            m_pArea->setAcceptDrops(true);
+            m_pArea->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored);
+            QPalette pal1 = m_pArea->palette();
             pal1.setColor(QPalette::Window, QColor(Qt::transparent));
-            m_pMdiArea->setPalette(pal1);
-            m_pMdiArea->setBackground(QColor(Qt::transparent));
+            m_pArea->setPalette(pal1);
             /* Make sure valid child-widget passed: */
             AssertPtrReturnVoid(m_pWidget);
             {
@@ -120,35 +116,34 @@ void UISlidingToolBar::prepareContents()
                 pal2.setColor(QPalette::Window, palette().color(QPalette::Window));
                 m_pWidget->setPalette(pal2);
                 connect(m_pWidget, SIGNAL(sigCancelClicked()), this, SLOT(close()));
-                /* Add child-widget into mdi-area: */
-                m_pEmbeddedWidget = m_pMdiArea->addSubWindow(m_pWidget, Qt::Window | Qt::FramelessWindowHint);
-                AssertPtrReturnVoid(m_pEmbeddedWidget);
+                /* Add child-widget into area: */
+                m_pWidget->setParent(m_pArea);
             }
-            /* Add mdi-area into main-layout: */
-            m_pMainLayout->addWidget(m_pMdiArea);
+            /* Add area into main-layout: */
+            m_pMainLayout->addWidget(m_pArea);
         }
     }
 }
 
 void UISlidingToolBar::prepareGeometry()
 {
-    /* Prepare geometry based on parent and mdi-sub-window size-hints,
-     * But move mdi-sub-window to initial position: */
-    const QSize sh = m_pEmbeddedWidget->sizeHint();
+    /* Prepare geometry based on parent and sub-window size-hints,
+     * But move sub-window to initial position: */
+    const QSize sh = m_pWidget->sizeHint();
     switch (m_position)
     {
         case Position_Top:
         {
             setGeometry(m_parentRect.x(), m_parentRect.y()                         + m_indentRect.height(),
                         qMax(m_parentRect.width(), sh.width()), sh.height());
-            m_pEmbeddedWidget->setGeometry(0, -sh.height(), qMax(width(), sh.width()), sh.height());
+            m_pWidget->setGeometry(0, -sh.height(), qMax(width(), sh.width()), sh.height());
             break;
         }
         case Position_Bottom:
         {
             setGeometry(m_parentRect.x(), m_parentRect.y() + m_parentRect.height() - m_indentRect.height() - sh.height(),
                         qMax(m_parentRect.width(), sh.width()), sh.height());
-            m_pEmbeddedWidget->setGeometry(0,  sh.height(), qMax(width(), sh.width()), sh.height());
+            m_pWidget->setGeometry(0,  sh.height(), qMax(width(), sh.width()), sh.height());
             break;
         }
     }
@@ -157,7 +152,7 @@ void UISlidingToolBar::prepareGeometry()
     if (!vboxGlobal().isCompositingManagerRunning())
     {
         /* Use Xshape otherwise: */
-        setMask(m_pEmbeddedWidget->geometry());
+        setMask(m_pWidget->geometry());
     }
 #endif /* VBOX_WS_X11 */
 
@@ -176,7 +171,7 @@ void UISlidingToolBar::prepareGeometry()
 
 void UISlidingToolBar::prepareAnimation()
 {
-    /* Prepare mdi-sub-window geometry animation itself: */
+    /* Prepare sub-window geometry animation itself: */
     connect(this, SIGNAL(sigShown()), this, SIGNAL(sigExpand()), Qt::QueuedConnection);
     m_pAnimation = UIAnimation::installPropertyAnimation(this,
                                                          "widgetGeometry",
@@ -190,8 +185,8 @@ void UISlidingToolBar::prepareAnimation()
 
 void UISlidingToolBar::adjustGeometry()
 {
-    /* Adjust geometry based on parent and mdi-sub-window size-hints: */
-    const QSize sh = m_pEmbeddedWidget->sizeHint();
+    /* Adjust geometry based on parent and sub-window size-hints: */
+    const QSize sh = m_pWidget->sizeHint();
     switch (m_position)
     {
         case Position_Top:
@@ -207,14 +202,14 @@ void UISlidingToolBar::adjustGeometry()
             break;
         }
     }
-    /* And move mdi-sub-window to corresponding position: */
-    m_pEmbeddedWidget->setGeometry(0, 0, qMax(width(), sh.width()), sh.height());
+    /* And move sub-window to corresponding position: */
+    m_pWidget->setGeometry(0, 0, qMax(width(), sh.width()), sh.height());
 
 #ifdef VBOX_WS_X11
     if (!vboxGlobal().isCompositingManagerRunning())
     {
         /* Use Xshape otherwise: */
-        setMask(m_pEmbeddedWidget->geometry());
+        setMask(m_pWidget->geometry());
     }
 #endif /* VBOX_WS_X11 */
 
@@ -230,8 +225,8 @@ void UISlidingToolBar::updateAnimation()
     if (!m_pAnimation)
         return;
 
-    /* Recalculate mdi-sub-window geometry animation boundaries based on size-hint: */
-    const QSize sh = m_pEmbeddedWidget->sizeHint();
+    /* Recalculate sub-window geometry animation boundaries based on size-hint: */
+    const QSize sh = m_pWidget->sizeHint();
     switch (m_position)
     {
         case Position_Top:    m_startWidgetGeometry = QRect(0, -sh.height(), qMax(width(), sh.width()), sh.height()); break;
@@ -299,21 +294,21 @@ bool UISlidingToolBar::event(QEvent *pEvent)
 
 void UISlidingToolBar::setWidgetGeometry(const QRect &rect)
 {
-    /* Apply mdi-sub-window geometry: */
-    m_pEmbeddedWidget->setGeometry(rect);
+    /* Apply sub-window geometry: */
+    m_pWidget->setGeometry(rect);
 
 #ifdef VBOX_WS_X11
     if (!vboxGlobal().isCompositingManagerRunning())
     {
         /* Use Xshape otherwise: */
-        setMask(m_pEmbeddedWidget->geometry());
+        setMask(m_pWidget->geometry());
     }
 #endif /* VBOX_WS_X11 */
 }
 
 QRect UISlidingToolBar::widgetGeometry() const
 {
-    /* Return mdi-sub-window geometry: */
-    return m_pEmbeddedWidget->geometry();
+    /* Return sub-window geometry: */
+    return m_pWidget->geometry();
 }
 
diff --git a/src/VBox/Frontends/VirtualBox/src/runtime/UISlidingToolBar.h b/src/VBox/Frontends/VirtualBox/src/runtime/UISlidingToolBar.h
index 7ea7dcb..7c478da 100644
--- a/src/VBox/Frontends/VirtualBox/src/runtime/UISlidingToolBar.h
+++ b/src/VBox/Frontends/VirtualBox/src/runtime/UISlidingToolBar.h
@@ -4,7 +4,7 @@
  */
 
 /*
- * Copyright (C) 2014-2016 Oracle Corporation
+ * Copyright (C) 2014-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;
@@ -22,8 +22,6 @@
 #include <QWidget>
 
 /* Forward declarations: */
-class QMdiArea;
-class QMdiSubWindow;
 class QHBoxLayout;
 class UIAnimation;
 
@@ -98,13 +96,13 @@ private:
     virtual bool event(QEvent *pEvent);
 #endif /* VBOX_WS_MAC */
 
-    /** Defines mdi-sub-window geometry. */
+    /** Defines sub-window geometry. */
     void setWidgetGeometry(const QRect &rect);
-    /** Returns mdi-sub-window geometry. */
+    /** Returns sub-window geometry. */
     QRect widgetGeometry() const;
-    /** Returns mdi-sub-window start-geometry. */
+    /** Returns sub-window start-geometry. */
     QRect startWidgetGeometry() const { return m_startWidgetGeometry; }
-    /** Returns mdi-sub-window final-geometry. */
+    /** Returns sub-window final-geometry. */
     QRect finalWidgetGeometry() const { return m_finalWidgetGeometry; }
 
     /** @name Geometry
@@ -123,9 +121,9 @@ private:
         UIAnimation *m_pAnimation;
         /** Holds whether window is expanded. */
         bool m_fExpanded;
-        /** Holds mdi-sub-window start-geometry. */
+        /** Holds sub-window start-geometry. */
         QRect m_startWidgetGeometry;
-        /** Holds mdi-sub-window final-geometry. */
+        /** Holds sub-window final-geometry. */
         QRect m_finalWidgetGeometry;
     /** @} */
 
@@ -133,12 +131,10 @@ private:
       * @{ */
         /** Holds the main-layout instance. */
         QHBoxLayout *m_pMainLayout;
-        /** Holds the mdi-area instance. */
-        QMdiArea *m_pMdiArea;
+        /** Holds the area instance. */
+        QWidget *m_pArea;
         /** Holds the child-widget reference. */
         QWidget *m_pWidget;
-        /** Holds the child-widget wrapper instance. */
-        QMdiSubWindow *m_pEmbeddedWidget;
     /** @} */
 };
 
diff --git a/src/VBox/Frontends/VirtualBox/src/runtime/fullscreen/UIMachineWindowFullscreen.cpp b/src/VBox/Frontends/VirtualBox/src/runtime/fullscreen/UIMachineWindowFullscreen.cpp
index d96fcb0..425df79 100644
--- a/src/VBox/Frontends/VirtualBox/src/runtime/fullscreen/UIMachineWindowFullscreen.cpp
+++ b/src/VBox/Frontends/VirtualBox/src/runtime/fullscreen/UIMachineWindowFullscreen.cpp
@@ -273,7 +273,8 @@ void UIMachineWindowFullscreen::prepareMiniToolbar()
     m_pMiniToolBar = new UIMiniToolBar(this,
                                        GeometryType_Full,
                                        gEDataManager->miniToolbarAlignment(vboxGlobal().managedVMUuid()),
-                                       gEDataManager->autoHideMiniToolbar(vboxGlobal().managedVMUuid()));
+                                       gEDataManager->autoHideMiniToolbar(vboxGlobal().managedVMUuid()),
+                                       screenId());
     AssertPtrReturnVoid(m_pMiniToolBar);
     {
         /* Configure mini-toolbar: */
diff --git a/src/VBox/Frontends/VirtualBox/src/runtime/normal/UIMachineWindowNormal.cpp b/src/VBox/Frontends/VirtualBox/src/runtime/normal/UIMachineWindowNormal.cpp
index d696ec6..0313679 100644
--- a/src/VBox/Frontends/VirtualBox/src/runtime/normal/UIMachineWindowNormal.cpp
+++ b/src/VBox/Frontends/VirtualBox/src/runtime/normal/UIMachineWindowNormal.cpp
@@ -157,7 +157,8 @@ void UIMachineWindowNormal::sltHandleMenuBarConfigurationChange(const QString &s
 void UIMachineWindowNormal::sltHandleMenuBarContextMenuRequest(const QPoint &position)
 {
     /* Raise action's context-menu: */
-    actionPool()->action(UIActionIndexRT_M_View_M_MenuBar)->menu()->exec(menuBar()->mapToGlobal(position));
+    if (gEDataManager->menuBarContextMenuEnabled(vboxGlobal().managedVMUuid()))
+        actionPool()->action(UIActionIndexRT_M_View_M_MenuBar)->menu()->exec(menuBar()->mapToGlobal(position));
 }
 #endif /* !RT_OS_DARWIN */
 
@@ -190,7 +191,8 @@ void UIMachineWindowNormal::sltHandleStatusBarConfigurationChange(const QString
 void UIMachineWindowNormal::sltHandleStatusBarContextMenuRequest(const QPoint &position)
 {
     /* Raise action's context-menu: */
-    actionPool()->action(UIActionIndexRT_M_View_M_StatusBar)->menu()->exec(statusBar()->mapToGlobal(position));
+    if (gEDataManager->statusBarContextMenuEnabled(vboxGlobal().managedVMUuid()))
+        actionPool()->action(UIActionIndexRT_M_View_M_StatusBar)->menu()->exec(statusBar()->mapToGlobal(position));
 }
 
 void UIMachineWindowNormal::sltHandleIndicatorContextMenuRequest(IndicatorType indicatorType, const QPoint &position)
@@ -521,6 +523,9 @@ void UIMachineWindowNormal::showInNecessaryMode()
     /* Show in normal mode: */
     show();
 
+    /* Normalize machine-window geometry: */
+    normalizeGeometry(true /* adjust position */);
+
     /* Make sure machine-view have focus: */
     m_pMachineView->setFocus();
 }
diff --git a/src/VBox/Frontends/VirtualBox/src/runtime/seamless/UIMachineWindowSeamless.cpp b/src/VBox/Frontends/VirtualBox/src/runtime/seamless/UIMachineWindowSeamless.cpp
index 3d81e93..d79e07c 100644
--- a/src/VBox/Frontends/VirtualBox/src/runtime/seamless/UIMachineWindowSeamless.cpp
+++ b/src/VBox/Frontends/VirtualBox/src/runtime/seamless/UIMachineWindowSeamless.cpp
@@ -137,7 +137,8 @@ void UIMachineWindowSeamless::prepareMiniToolbar()
     m_pMiniToolBar = new UIMiniToolBar(this,
                                        GeometryType_Available,
                                        gEDataManager->miniToolbarAlignment(vboxGlobal().managedVMUuid()),
-                                       gEDataManager->autoHideMiniToolbar(vboxGlobal().managedVMUuid()));
+                                       gEDataManager->autoHideMiniToolbar(vboxGlobal().managedVMUuid()),
+                                       screenId());
     AssertPtrReturnVoid(m_pMiniToolBar);
     {
         /* Configure mini-toolbar: */
diff --git a/src/VBox/Frontends/VirtualBox/src/selector/graphics/chooser/UIGChooserModel.cpp b/src/VBox/Frontends/VirtualBox/src/selector/graphics/chooser/UIGChooserModel.cpp
index f7f1586..2709e75 100644
--- a/src/VBox/Frontends/VirtualBox/src/selector/graphics/chooser/UIGChooserModel.cpp
+++ b/src/VBox/Frontends/VirtualBox/src/selector/graphics/chooser/UIGChooserModel.cpp
@@ -1594,6 +1594,7 @@ bool UIGChooserModel::processContextMenuEvent(QGraphicsSceneContextMenuEvent *pE
                             return true;
                         }
                     }
+                    /* fall thru */
                     case UIGChooserItemType_Machine:
                     {
                         /* Machine context menu for other Group/Machine cases: */
@@ -1624,6 +1625,7 @@ bool UIGChooserModel::processContextMenuEvent(QGraphicsSceneContextMenuEvent *pE
                             return true;
                         }
                     }
+                    /* fall thru */
                     case UIGChooserItemType_Machine:
                     {
                         /* Machine context menu for other Group/Machine cases: */
diff --git a/src/VBox/Frontends/VirtualBox/src/selector/graphics/details/UIGMachinePreview.cpp b/src/VBox/Frontends/VirtualBox/src/selector/graphics/details/UIGMachinePreview.cpp
index 55b736b..58e383f 100644
--- a/src/VBox/Frontends/VirtualBox/src/selector/graphics/details/UIGMachinePreview.cpp
+++ b/src/VBox/Frontends/VirtualBox/src/selector/graphics/details/UIGMachinePreview.cpp
@@ -444,6 +444,7 @@ void UIGMachinePreview::setUpdateInterval(PreviewUpdateIntervalType interval, bo
             m_pUpdateTimer->stop();
             /* And continue with other cases: */
         }
+        /* fall thru */
         case PreviewUpdateIntervalType_500ms:
         case PreviewUpdateIntervalType_1000ms:
         case PreviewUpdateIntervalType_2000ms:
diff --git a/src/VBox/Frontends/VirtualBox/src/settings/global/UIGlobalSettingsNetwork.cpp b/src/VBox/Frontends/VirtualBox/src/settings/global/UIGlobalSettingsNetwork.cpp
index 233454b..7dd24ad 100644
--- a/src/VBox/Frontends/VirtualBox/src/settings/global/UIGlobalSettingsNetwork.cpp
+++ b/src/VBox/Frontends/VirtualBox/src/settings/global/UIGlobalSettingsNetwork.cpp
@@ -271,7 +271,7 @@ bool UIItemNetworkHost::validate(UIValidationMessage &message)
                 || iMaskPrefixLength < 0
                 || iMaskPrefixLength > 128)
             {
-                message.second << UIGlobalSettingsNetwork::tr("Host interface <b>%1</b> does not currently have a valid IPv6 network mask prefix length.").arg(text(0));
+                message.second << UIGlobalSettingsNetwork::tr("Host interface <b>%1</b> does not currently have a valid IPv6 prefix length.").arg(text(0));
                 fPass = false;
             }
         }
@@ -339,7 +339,7 @@ void UIItemNetworkHost::updateInfo()
                                       .arg(m_data.m_interface.m_strInterfaceAddress6.isEmpty() ?
                                            UIGlobalSettingsNetwork::tr("Not set", "address") :
                                            m_data.m_interface.m_strInterfaceAddress6) +
-                          strSubHeader.arg(UIGlobalSettingsNetwork::tr("IPv6 Network Mask Length"))
+                          strSubHeader.arg(UIGlobalSettingsNetwork::tr("IPv6 Prefix Length"))
                                       .arg(m_data.m_interface.m_strInterfaceMaskLength6.isEmpty() ?
                                            UIGlobalSettingsNetwork::tr("Not set", "length") :
                                            m_data.m_interface.m_strInterfaceMaskLength6);
@@ -1134,7 +1134,7 @@ void UIGlobalSettingsNetwork::saveCacheItemNetworkHost(const UIDataSettingsGloba
             bool fIsMaskPrefixLengthNumber = false;
             const int iMaskPrefixLength = data.m_interface.m_strInterfaceMaskLength6.trimmed().toInt(&fIsMaskPrefixLengthNumber);
             AssertMsg(fIsMaskPrefixLengthNumber && iMaskPrefixLength >= 0 && iMaskPrefixLength <= 128,
-                      ("Interface IPv6 network mask prefix length must be empty or IPv6-valid!\n"));
+                      ("Interface IPv6 prefix length must be empty or IPv6-valid!\n"));
             if (   (   data.m_interface.m_strInterfaceAddress6.trimmed().isEmpty()
                     || RTNetIsIPv6AddrStr(data.m_interface.m_strInterfaceAddress6.toUtf8().constData()))
                 && (   fIsMaskPrefixLengthNumber
diff --git a/src/VBox/Frontends/VirtualBox/src/settings/global/UIGlobalSettingsNetworkDetailsHost.ui b/src/VBox/Frontends/VirtualBox/src/settings/global/UIGlobalSettingsNetworkDetailsHost.ui
index 4e97b3a..1c24028 100644
--- a/src/VBox/Frontends/VirtualBox/src/settings/global/UIGlobalSettingsNetworkDetailsHost.ui
+++ b/src/VBox/Frontends/VirtualBox/src/settings/global/UIGlobalSettingsNetworkDetailsHost.ui
@@ -136,7 +136,7 @@
        <item row="4" column="1">
         <widget class="QLabel" name="m_pNMv6Label">
          <property name="text">
-          <string>IPv6 Network Mask &Length:</string>
+          <string>IPv6 Prefix &Length:</string>
          </property>
          <property name="alignment">
           <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
@@ -155,7 +155,7 @@
           </sizepolicy>
          </property>
          <property name="toolTip">
-          <string>Holds the host IPv6 network mask prefix length for this adapter if IPv6 is supported.</string>
+          <string>Holds the host IPv6 prefix length for this adapter if IPv6 is supported.</string>
          </property>
         </widget>
        </item>
diff --git a/src/VBox/Frontends/VirtualBox/src/widgets/UIFilmContainer.cpp b/src/VBox/Frontends/VirtualBox/src/widgets/UIFilmContainer.cpp
old mode 100755
new mode 100644
diff --git a/src/VBox/Frontends/VirtualBox/src/widgets/UIMiniToolBar.cpp b/src/VBox/Frontends/VirtualBox/src/widgets/UIMiniToolBar.cpp
index eac3b9e..d295354 100644
--- a/src/VBox/Frontends/VirtualBox/src/widgets/UIMiniToolBar.cpp
+++ b/src/VBox/Frontends/VirtualBox/src/widgets/UIMiniToolBar.cpp
@@ -22,8 +22,6 @@
 /* Qt includes: */
 # include <QApplication>
 # include <QTimer>
-# include <QMdiArea>
-# include <QMdiSubWindow>
 # include <QLabel>
 # include <QMenu>
 # include <QToolButton>
@@ -346,9 +344,6 @@ void UIMiniToolBarPrivate::prepare()
 #else /* !VBOX_WS_X11 */
     m_spacings << widgetForAction(addWidget(new QWidget));
 #endif /* !VBOX_WS_X11 */
-
-    /* Resize to sizehint: */
-    resize(sizeHint());
 }
 
 void UIMiniToolBarPrivate::rebuildShape()
@@ -414,6 +409,7 @@ Qt::WindowFlags UIMiniToolBar::defaultWindowFlags(GeometryType geometryType)
         // By nor less strange reason, frameless full-screen *tool* windows
         // respects such relationship, so we are doing what WM want.
         case X11WMType_GNOMEShell:
+        case X11WMType_KWin:
         case X11WMType_Metacity:
         case X11WMType_Mutter:
             return geometryType == GeometryType_Full ?
@@ -430,17 +426,18 @@ Qt::WindowFlags UIMiniToolBar::defaultWindowFlags(GeometryType geometryType)
 UIMiniToolBar::UIMiniToolBar(QWidget *pParent,
                              GeometryType geometryType,
                              Qt::Alignment alignment,
-                             bool fAutoHide /* = true */)
+                             bool fAutoHide /* = true */,
+                             int iWindowIndex /* = -1 */)
     : QWidget(0, defaultWindowFlags(geometryType))
     /* Variables: General stuff: */
     , m_pParent(pParent)
     , m_geometryType(geometryType)
     , m_alignment(alignment)
     , m_fAutoHide(fAutoHide)
+    , m_iWindowIndex(iWindowIndex)
     /* Variables: Contents stuff: */
-    , m_pMdiArea(0)
+    , m_pArea(0)
     , m_pToolbar(0)
-    , m_pEmbeddedToolbar(0)
     /* Variables: Hover stuff: */
     , m_fHovered(false)
     , m_pHoverEnterTimer(0)
@@ -519,16 +516,16 @@ void UIMiniToolBar::addMenus(const QList<QMenu*> &menus)
 
 void UIMiniToolBar::adjustGeometry()
 {
-    /* Resize embedded-toolbar to minimum size: */
-    m_pEmbeddedToolbar->resize(m_pEmbeddedToolbar->sizeHint());
+    /* Resize toolbar to minimum size: */
+    m_pToolbar->resize(m_pToolbar->sizeHint());
 
-    /* Calculate embedded-toolbar position: */
+    /* Calculate toolbar position: */
     int iX = 0, iY = 0;
-    iX = width() / 2 - m_pEmbeddedToolbar->width() / 2;
+    iX = width() / 2 - m_pToolbar->width() / 2;
     switch (m_alignment)
     {
         case Qt::AlignTop:    iY = 0; break;
-        case Qt::AlignBottom: iY = height() - m_pEmbeddedToolbar->height(); break;
+        case Qt::AlignBottom: iY = height() - m_pToolbar->height(); break;
         default: break;
     }
 
@@ -536,20 +533,20 @@ void UIMiniToolBar::adjustGeometry()
     m_shownToolbarPosition = QPoint(iX, iY);
     switch (m_alignment)
     {
-        case Qt::AlignTop:    m_hiddenToolbarPosition = m_shownToolbarPosition - QPoint(0, m_pEmbeddedToolbar->height() - 3); break;
-        case Qt::AlignBottom: m_hiddenToolbarPosition = m_shownToolbarPosition + QPoint(0, m_pEmbeddedToolbar->height() - 3); break;
+        case Qt::AlignTop:    m_hiddenToolbarPosition = m_shownToolbarPosition - QPoint(0, m_pToolbar->height() - 3); break;
+        case Qt::AlignBottom: m_hiddenToolbarPosition = m_shownToolbarPosition + QPoint(0, m_pToolbar->height() - 3); break;
     }
     m_pAnimation->update();
 
-    /* Update embedded-toolbar geometry if known: */
+    /* Update toolbar geometry if known: */
     if (property("AnimationState").toString() == "Final")
-        m_pEmbeddedToolbar->move(m_shownToolbarPosition);
+        m_pToolbar->move(m_shownToolbarPosition);
     else
-        m_pEmbeddedToolbar->move(m_hiddenToolbarPosition);
+        m_pToolbar->move(m_hiddenToolbarPosition);
 
 #if defined(VBOX_WS_WIN) || defined(VBOX_WS_X11)
     /* Adjust window mask: */
-    setMask(m_pEmbeddedToolbar->geometry());
+    setMask(m_pToolbar->geometry());
 #endif /* VBOX_WS_WIN || VBOX_WS_X11 */
 }
 
@@ -588,7 +585,7 @@ void UIMiniToolBar::sltHoverLeave()
 
 void UIMiniToolBar::sltHide()
 {
-    LogRel2(("GUI: UIMiniToolBar::sltHide\n"));
+    LogRel(("GUI: Hide mini-toolbar for window #%d\n", m_iWindowIndex));
 
 #if defined(VBOX_WS_MAC)
 
@@ -614,7 +611,7 @@ void UIMiniToolBar::sltHide()
 
 void UIMiniToolBar::sltShow()
 {
-    LogRel2(("GUI: UIMiniToolBar::sltShow\n"));
+    LogRel(("GUI: Show mini-toolbar for window #%d\n", m_iWindowIndex));
 
     /* Update transience: */
     sltAdjustTransience();
@@ -625,6 +622,13 @@ void UIMiniToolBar::sltShow()
 
 #elif defined(VBOX_WS_WIN)
 
+    // WORKAROUND:
+    // If the host-screen is changed => we should
+    // reset window state to NONE first because
+    // we need an expose on showFullScreen call.
+    if (m_geometryType == GeometryType_Full)
+        setWindowState(Qt::WindowNoState);
+
     /* Adjust window: */
     sltAdjust();
     /* Show window in necessary mode: */
@@ -680,12 +684,31 @@ void UIMiniToolBar::sltShow()
 
 void UIMiniToolBar::sltAdjust()
 {
-    LogRel2(("GUI: UIMiniToolBar::sltAdjust\n"));
+    LogRel(("GUI: Adjust mini-toolbar for window #%d\n", m_iWindowIndex));
 
     /* Get corresponding host-screen: */
-    const int iHostScreen = gpDesktop->screenNumber(m_pParent);
-    Q_UNUSED(iHostScreen);
-    /* And corresponding working area: */
+    const int iHostScreenCount = gpDesktop->screenCount();
+    int iHostScreen = gpDesktop->screenNumber(m_pParent);
+    // WORKAROUND:
+    // When switching host-screen count, especially in complex cases where RDP client is "replacing" host-screen(s) with own virtual-screen(s),
+    // Qt could behave quite arbitrary and laggy, and due to racing there could be a situation when QDesktopWidget::screenNumber() returns -1
+    // as a host-screen number where the parent window is currently located. We should handle this situation anyway, so let's assume the parent
+    // window is located on primary (0) host-screen if it's present or ignore this request at all.
+    if (iHostScreen < 0 || iHostScreen >= iHostScreenCount)
+    {
+        if (iHostScreenCount > 0)
+        {
+            LogRel(("GUI:  Mini-toolbar parent window #%d is located on invalid host-screen #%d. Fallback to primary.\n", m_iWindowIndex, iHostScreen));
+            iHostScreen = 0;
+        }
+        else
+        {
+            LogRel(("GUI:  Mini-toolbar parent window #%d is located on invalid host-screen #%d. Ignore request.\n", m_iWindowIndex, iHostScreen));
+            return;
+        }
+    }
+
+    /* Get corresponding working area: */
     QRect workingArea;
     switch (m_geometryType)
     {
@@ -706,14 +729,14 @@ void UIMiniToolBar::sltAdjust()
         {
             /* Set appropriate window size: */
             const QSize newSize = workingArea.size();
-            LogRel2(("GUI: UIMiniToolBar::sltAdjust: Resize window to: %dx%d\n",
-                     newSize.width(), newSize.height()));
+            LogRel(("GUI:  Resize mini-toolbar for window #%d to %dx%d\n",
+                     m_iWindowIndex, newSize.width(), newSize.height()));
             resize(newSize);
 
             /* Move window onto required screen: */
             const QPoint newPosition = workingArea.topLeft();
-            LogRel2(("GUI: UIMiniToolBar::sltAdjust: Move window to: %dx%d\n",
-                     newPosition.x(), newPosition.y()));
+            LogRel(("GUI:  Move mini-toolbar for window #%d to %dx%d\n",
+                     m_iWindowIndex, newPosition.x(), newPosition.y()));
             move(newPosition);
 
             break;
@@ -721,14 +744,14 @@ void UIMiniToolBar::sltAdjust()
         case GeometryType_Full:
         {
             /* Map window onto required screen: */
-            LogRel2(("GUI: UIMiniToolBar::sltAdjust: Map window to screen: %d of: %d\n",
-                     iHostScreen, qApp->screens().size()));
+            LogRel(("GUI:  Map mini-toolbar for window #%d to screen %d of %d\n",
+                     m_iWindowIndex, iHostScreen, qApp->screens().size()));
             windowHandle()->setScreen(qApp->screens().at(iHostScreen));
 
             /* Set appropriate window size: */
             const QSize newSize = workingArea.size();
-            LogRel2(("GUI: UIMiniToolBar::sltAdjust: Resize window to: %dx%d\n",
-                     newSize.width(), newSize.height()));
+            LogRel(("GUI:  Resize mini-toolbar for window #%d to %dx%d\n",
+                     m_iWindowIndex, newSize.width(), newSize.height()));
             resize(newSize);
 
             break;
@@ -756,14 +779,14 @@ void UIMiniToolBar::sltAdjust()
                 // window size is more than the available geometry (working area) of that
                 // host-screen. So we are resizing it to a smaller size first of all:
                 const QSize newSize = workingArea.size() * .9;
-                LogRel(("GUI: UIMiniToolBar::sltAdjust: Resize window to smaller size: %dx%d\n",
-                        newSize.width(), newSize.height()));
+                LogRel(("GUI:  Resize mini-toolbar for window #%d to smaller size %dx%d\n",
+                        m_iWindowIndex, newSize.width(), newSize.height()));
                 resize(newSize);
 
                 /* Move window onto required screen: */
                 const QPoint newPosition = workingArea.topLeft();
-                LogRel(("GUI: UIMiniToolBar::sltAdjust: Move window to: %dx%d\n",
-                        newPosition.x(), newPosition.y()));
+                LogRel(("GUI:  Move mini-toolbar for window #%d to %dx%d\n",
+                        m_iWindowIndex, newPosition.x(), newPosition.y()));
                 move(newPosition);
             }
 
@@ -782,14 +805,14 @@ void UIMiniToolBar::sltAdjust()
 
             /* Set appropriate window size: */
             const QSize newSize = workingArea.size();
-            LogRel(("GUI: UIMiniToolBar::sltAdjust: Resize window to: %dx%d\n",
-                    newSize.width(), newSize.height()));
+            LogRel(("GUI:  Resize mini-toolbar for window #%d to %dx%d\n",
+                    m_iWindowIndex, newSize.width(), newSize.height()));
             resize(newSize);
 
             /* Move window onto required screen: */
             const QPoint newPosition = workingArea.topLeft();
-            LogRel(("GUI: UIMiniToolBar::sltAdjust: Move window to: %dx%d\n",
-                    newPosition.x(), newPosition.y()));
+            LogRel(("GUI:  Move mini-toolbar for window #%d to %dx%d\n",
+                    m_iWindowIndex, newPosition.x(), newPosition.y()));
             move(newPosition);
 
             /* Re-apply the full-screen state lost on above move(): */
@@ -838,24 +861,21 @@ void UIMiniToolBar::prepare()
     /* Make sure we have no focus: */
     setFocusPolicy(Qt::NoFocus);
 
-    /* Prepare mdi-area: */
-    m_pMdiArea = new QMdiArea;
+    /* Prepare area: */
+    m_pArea = new QWidget;
     {
-        /* Allow any MDI area size: */
-        m_pMdiArea->setMinimumSize(QSize(1, 1));
+        /* Allow any area size: */
+        m_pArea->setMinimumSize(QSize(1, 1));
         /* Configure own background: */
-        QPalette pal = m_pMdiArea->palette();
+        QPalette pal = m_pArea->palette();
         pal.setColor(QPalette::Window, QColor(Qt::transparent));
-        m_pMdiArea->setPalette(pal);
-        /* Configure viewport background: */
-        m_pMdiArea->setBackground(QColor(Qt::transparent));
-        /* Layout mdi-area according parent-widget: */
+        m_pArea->setPalette(pal);
+        /* Layout area according parent-widget: */
         QVBoxLayout *pMainLayout = new QVBoxLayout(this);
         pMainLayout->setContentsMargins(0, 0, 0, 0);
-        pMainLayout->addWidget(m_pMdiArea);
+        pMainLayout->addWidget(m_pArea);
         /* Make sure we have no focus: */
-        m_pMdiArea->setFocusPolicy(Qt::NoFocus);
-        m_pMdiArea->viewport()->setFocusPolicy(Qt::NoFocus);
+        m_pArea->setFocusPolicy(Qt::NoFocus);
     }
 
     /* Prepare mini-toolbar: */
@@ -876,10 +896,10 @@ void UIMiniToolBar::prepare()
         connect(m_pToolbar, SIGNAL(sigMinimizeAction()), this, SIGNAL(sigMinimizeAction()));
         connect(m_pToolbar, SIGNAL(sigExitAction()), this, SIGNAL(sigExitAction()));
         connect(m_pToolbar, SIGNAL(sigCloseAction()), this, SIGNAL(sigCloseAction()));
-        /* Add child to mdi-area: */
-        m_pEmbeddedToolbar = m_pMdiArea->addSubWindow(m_pToolbar, Qt::Window | Qt::FramelessWindowHint);
+        /* Add child to area: */
+        m_pToolbar->setParent(m_pArea);
         /* Make sure we have no focus: */
-        m_pEmbeddedToolbar->setFocusPolicy(Qt::NoFocus);
+        m_pToolbar->setFocusPolicy(Qt::NoFocus);
     }
 
     /* Prepare hover-enter/leave timers: */
@@ -921,13 +941,13 @@ void UIMiniToolBar::cleanup()
     if (m_pHoverLeaveTimer && m_pHoverLeaveTimer->isActive())
         m_pHoverLeaveTimer->stop();
 
-    /* Destroy animation before mdi-toolbar: */
+    /* Destroy animation before toolbar: */
     delete m_pAnimation;
     m_pAnimation = 0;
 
-    /* Destroy mdi-toolbar after animation: */
-    delete m_pEmbeddedToolbar;
-    m_pEmbeddedToolbar = 0;
+    /* Destroy toolbar after animation: */
+    delete m_pToolbar;
+    m_pToolbar = 0;
 }
 
 void UIMiniToolBar::enterEvent(QEvent*)
@@ -1120,20 +1140,20 @@ void UIMiniToolBar::simulateToolbarAutoHiding()
 void UIMiniToolBar::setToolbarPosition(QPoint point)
 {
     /* Update position: */
-    AssertPtrReturnVoid(m_pEmbeddedToolbar);
-    m_pEmbeddedToolbar->move(point);
+    AssertPtrReturnVoid(m_pToolbar);
+    m_pToolbar->move(point);
 
 #if defined(VBOX_WS_WIN) || defined(VBOX_WS_X11)
     /* Update window mask: */
-    setMask(m_pEmbeddedToolbar->geometry());
+    setMask(m_pToolbar->geometry());
 #endif /* VBOX_WS_WIN || VBOX_WS_X11 */
 }
 
 QPoint UIMiniToolBar::toolbarPosition() const
 {
     /* Return position: */
-    AssertPtrReturn(m_pEmbeddedToolbar, QPoint());
-    return m_pEmbeddedToolbar->pos();
+    AssertPtrReturn(m_pToolbar, QPoint());
+    return m_pToolbar->pos();
 }
 
 bool UIMiniToolBar::isParentMinimized() const
diff --git a/src/VBox/Frontends/VirtualBox/src/widgets/UIMiniToolBar.h b/src/VBox/Frontends/VirtualBox/src/widgets/UIMiniToolBar.h
index 628395f..a01ca1a 100644
--- a/src/VBox/Frontends/VirtualBox/src/widgets/UIMiniToolBar.h
+++ b/src/VBox/Frontends/VirtualBox/src/widgets/UIMiniToolBar.h
@@ -25,8 +25,6 @@
 class QMenu;
 class QTimer;
 class QLabel;
-class QMdiArea;
-class QMdiSubWindow;
 class UIAnimation;
 class UIMiniToolBarPrivate;
 
@@ -72,11 +70,13 @@ public:
     /** Constructor, passes @a pParent to the QWidget constructor.
       * @param geometryType determines the geometry type,
       * @param alignment    determines the alignment type,
-      * @param fAutoHide    determines whether we should auto-hide. */
+      * @param fAutoHide    determines whether we should auto-hide.
+      * @param iWindowIndex determines the parent window index. */
     UIMiniToolBar(QWidget *pParent,
                   GeometryType geometryType,
                   Qt::Alignment alignment,
-                  bool fAutoHide = true);
+                  bool fAutoHide = true,
+                  int iWindowIndex = -1);
     /** Destructor. */
     ~UIMiniToolBar();
 
@@ -167,14 +167,13 @@ private:
     Qt::Alignment m_alignment;
     /** Holds whether we should auto-hide. */
     bool m_fAutoHide;
+    /** Holds the parent window index. */
+    int m_iWindowIndex;
 
-    /** Holds the MDI-area. */
-    QMdiArea *m_pMdiArea;
+    /** Holds the area. */
+    QWidget *m_pArea;
     /** Holds the internal widget. */
     UIMiniToolBarPrivate *m_pToolbar;
-    /** Holds the pointer to the wrapped
-      * internal widget inside the MDI-area. */
-    QMdiSubWindow *m_pEmbeddedToolbar;
 
     /** Holds whether we are hovered. */
     bool m_fHovered;
diff --git a/src/VBox/GuestHost/OpenGL/error/error.py b/src/VBox/GuestHost/OpenGL/error/error.py
old mode 100755
new mode 100644
diff --git a/src/VBox/GuestHost/OpenGL/packer/opcodes.py b/src/VBox/GuestHost/OpenGL/packer/opcodes.py
old mode 100755
new mode 100644
diff --git a/src/VBox/GuestHost/OpenGL/packer/pack_client.c b/src/VBox/GuestHost/OpenGL/packer/pack_client.c
index b994a4e..28e8cc5 100644
--- a/src/VBox/GuestHost/OpenGL/packer/pack_client.c
+++ b/src/VBox/GuestHost/OpenGL/packer/pack_client.c
@@ -108,8 +108,8 @@ static void crPackVertexAttrib(const CRVertexArrays *array, unsigned int attr, G
                     case 4:
                         crPackVertexAttrib4usvARB(attr, usPtr);
                         break;
-                    case 3: usv[2] = usPtr[2];
-                    case 2: usv[1] = usPtr[1];
+                    case 3: usv[2] = usPtr[2]; /* fall thru */
+                    case 2: usv[1] = usPtr[1]; /* fall thru */
                     case 1:
                         usv[0] = usPtr[0];
                         crPackVertexAttrib4usvARB(attr, usv);
@@ -147,8 +147,8 @@ static void crPackVertexAttrib(const CRVertexArrays *array, unsigned int attr, G
                     case 4:
                         crPackVertexAttrib4ivARB(attr, iPtr);
                         break;
-                    case 3: iv[2] = iPtr[2];
-                    case 2: iv[1] = iPtr[1];
+                    case 3: iv[2] = iPtr[2]; /* fall thru */
+                    case 2: iv[1] = iPtr[1]; /* fall thru */
                     case 1:
                         iv[0] = iPtr[0];
                         crPackVertexAttrib4ivARB(attr, iv);
@@ -186,8 +186,8 @@ static void crPackVertexAttrib(const CRVertexArrays *array, unsigned int attr, G
                     case 4:
                         crPackVertexAttrib4uivARB(attr, uiPtr);
                         break;
-                    case 3: uiv[2] = uiPtr[2];
-                    case 2: uiv[1] = uiPtr[1];
+                    case 3: uiv[2] = uiPtr[2]; /* fall thru */
+                    case 2: uiv[1] = uiPtr[1]; /* fall thru */
                     case 1:
                         uiv[0] = uiPtr[0];
                         crPackVertexAttrib4uivARB(attr, uiv);
@@ -243,8 +243,8 @@ static void crPackVertexAttrib(const CRVertexArrays *array, unsigned int attr, G
                     case 4:
                         crPackVertexAttrib4bvARB(attr, bPtr);
                         break;
-                    case 3: bv[2] = bPtr[2];
-                    case 2: bv[1] = bPtr[1];
+                    case 3: bv[2] = bPtr[2]; /* fall thru */
+                    case 2: bv[1] = bPtr[1]; /* fall thru */
                     case 1:
                         bv[0] = bPtr[0];
                         crPackVertexAttrib4bvARB(attr, bv);
@@ -282,8 +282,8 @@ static void crPackVertexAttrib(const CRVertexArrays *array, unsigned int attr, G
                     case 4:
                         crPackVertexAttrib4ubvARB(attr, ubPtr);
                         break;
-                    case 3: ubv[2] = ubPtr[2];
-                    case 2: ubv[1] = ubPtr[1];
+                    case 3: ubv[2] = ubPtr[2]; /* fall thru */
+                    case 2: ubv[1] = ubPtr[1]; /* fall thru */
                     case 1:
                         ubv[0] = ubPtr[0];
                         crPackVertexAttrib4ubvARB(attr, ubv);
diff --git a/src/VBox/GuestHost/OpenGL/packer/pack_current.py b/src/VBox/GuestHost/OpenGL/packer/pack_current.py
old mode 100755
new mode 100644
diff --git a/src/VBox/GuestHost/OpenGL/packer/pack_currentheader.py b/src/VBox/GuestHost/OpenGL/packer/pack_currentheader.py
old mode 100755
new mode 100644
diff --git a/src/VBox/GuestHost/OpenGL/packer/pack_header.py b/src/VBox/GuestHost/OpenGL/packer/pack_header.py
old mode 100755
new mode 100644
diff --git a/src/VBox/GuestHost/OpenGL/packer/pack_swap.py b/src/VBox/GuestHost/OpenGL/packer/pack_swap.py
old mode 100755
new mode 100644
diff --git a/src/VBox/GuestHost/OpenGL/packer/packer.py b/src/VBox/GuestHost/OpenGL/packer/packer.py
old mode 100755
new mode 100644
diff --git a/src/VBox/GuestHost/OpenGL/packer/packer_bbox.py b/src/VBox/GuestHost/OpenGL/packer/packer_bbox.py
old mode 100755
new mode 100644
diff --git a/src/VBox/GuestHost/OpenGL/spu_loader/dispatch.py b/src/VBox/GuestHost/OpenGL/spu_loader/dispatch.py
old mode 100755
new mode 100644
diff --git a/src/VBox/GuestHost/OpenGL/spu_loader/dispatchheader.py b/src/VBox/GuestHost/OpenGL/spu_loader/dispatchheader.py
old mode 100755
new mode 100644
diff --git a/src/VBox/GuestHost/OpenGL/spu_loader/glloader.py b/src/VBox/GuestHost/OpenGL/spu_loader/glloader.py
old mode 100755
new mode 100644
diff --git a/src/VBox/GuestHost/OpenGL/spu_loader/spuchange.py b/src/VBox/GuestHost/OpenGL/spu_loader/spuchange.py
old mode 100755
new mode 100644
diff --git a/src/VBox/GuestHost/OpenGL/spu_loader/spucopy.py b/src/VBox/GuestHost/OpenGL/spu_loader/spucopy.py
old mode 100755
new mode 100644
diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/convert.py b/src/VBox/GuestHost/OpenGL/state_tracker/convert.py
old mode 100755
new mode 100644
diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/dump_gen.py b/src/VBox/GuestHost/OpenGL/state_tracker/dump_gen.py
old mode 100755
new mode 100644
diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/gendiffcode.py b/src/VBox/GuestHost/OpenGL/state_tracker/gendiffcode.py
old mode 100755
new mode 100644
diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/get_components.py b/src/VBox/GuestHost/OpenGL/state_tracker/get_components.py
old mode 100755
new mode 100644
diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_buffer.c b/src/VBox/GuestHost/OpenGL/state_tracker/state_buffer.c
index 90917ab..4520872 100644
--- a/src/VBox/GuestHost/OpenGL/state_tracker/state_buffer.c
+++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_buffer.c
@@ -194,6 +194,7 @@ void STATE_APIENTRY crStateBlendFunc (GLenum sfactor, GLenum dfactor)
             if (g->extensions.EXT_blend_color)
                 break; /* OK */
 #endif
+        /* fall thru */
         default:
             crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "Invalid sfactor passed to glBlendFunc: %d", sfactor);
             return;
@@ -218,6 +219,7 @@ void STATE_APIENTRY crStateBlendFunc (GLenum sfactor, GLenum dfactor)
             if (g->extensions.EXT_blend_color)
                 break; /* OK */
 #endif
+        /* fall thru */
         default:
             crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "Invalid dfactor passed to glBlendFunc: %d", dfactor);
             return;
@@ -288,6 +290,7 @@ void STATE_APIENTRY crStateBlendFuncSeparateEXT( GLenum sfactorRGB, GLenum dfact
             if (g->extensions.EXT_blend_color)
                 break; /* OK */
 #endif
+        /* fall thru */
         default:
             crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "Invalid sfactorRGB passed to glBlendFuncSeparateEXT: %d", sfactorRGB);
             return;
@@ -313,6 +316,7 @@ void STATE_APIENTRY crStateBlendFuncSeparateEXT( GLenum sfactorRGB, GLenum dfact
             if (g->extensions.EXT_blend_color)
                 break; /* OK */
 #endif
+        /* fall thru */
         default:
             crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "Invalid sfactorA passed to glBlendFuncSeparateEXT: %d", sfactorA);
             return;
@@ -340,6 +344,7 @@ void STATE_APIENTRY crStateBlendFuncSeparateEXT( GLenum sfactorRGB, GLenum dfact
             if (g->extensions.EXT_blend_color)
                 break; /* OK */
 #endif
+        /* fall thru */
         default:
             crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "Invalid dfactorRGB passed to glBlendFuncSeparateEXT: %d", dfactorRGB);
             return;
@@ -367,6 +372,7 @@ void STATE_APIENTRY crStateBlendFuncSeparateEXT( GLenum sfactorRGB, GLenum dfact
             if (g->extensions.EXT_blend_color)
                 break; /* OK */
 #endif
+        /* fall thru */
         default:
             crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "Invalid dfactorA passed to glBlendFuncSeparateEXT: %d", dfactorA);
             return;
diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_current.py b/src/VBox/GuestHost/OpenGL/state_tracker/state_current.py
old mode 100755
new mode 100644
diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_funcs.py b/src/VBox/GuestHost/OpenGL/state_tracker/state_funcs.py
old mode 100755
new mode 100644
diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_get.py b/src/VBox/GuestHost/OpenGL/state_tracker/state_get.py
old mode 100755
new mode 100644
diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_isenabled.py b/src/VBox/GuestHost/OpenGL/state_tracker/state_isenabled.py
old mode 100755
new mode 100644
diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_polygon.c b/src/VBox/GuestHost/OpenGL/state_tracker/state_polygon.c
index 611e2f1..97d17ed 100644
--- a/src/VBox/GuestHost/OpenGL/state_tracker/state_polygon.c
+++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_polygon.c
@@ -127,6 +127,7 @@ void  STATE_APIENTRY crStatePolygonMode (GLenum face, GLenum mode)
             break;
         case GL_FRONT_AND_BACK:
             p->frontMode = mode;
+            /* fall thru */
         case GL_BACK:
             p->backMode = mode;
             break;
diff --git a/src/VBox/GuestHost/OpenGL/util/debug_opcodes.py b/src/VBox/GuestHost/OpenGL/util/debug_opcodes.py
old mode 100755
new mode 100644
diff --git a/src/VBox/HostDrivers/Support/Makefile.kmk b/src/VBox/HostDrivers/Support/Makefile.kmk
index 9fb6450..e4ac7ab 100644
--- a/src/VBox/HostDrivers/Support/Makefile.kmk
+++ b/src/VBox/HostDrivers/Support/Makefile.kmk
@@ -311,6 +311,7 @@ if "$(KBUILD_TARGET)" == "win" && defined(VBOX_WITH_HARDENING) ## @todo some of
 	$(VBOX_PATH_RUNTIME_SRC)/common/path/RTPathExt.cpp \
 	$(VBOX_PATH_RUNTIME_SRC)/common/string/RTUtf16PrintHexBytes.cpp \
 	$(VBOX_PATH_RUNTIME_SRC)/common/string/RTUtf16ICmpAscii.cpp \
+	$(VBOX_PATH_RUNTIME_SRC)/common/string/RTUtf16NICmpAscii.cpp \
 	$(VBOX_PATH_RUNTIME_SRC)/common/string/RTUtf16CatAscii.cpp \
 	$(VBOX_PATH_RUNTIME_SRC)/common/string/RTUtf16CopyAscii.cpp \
 	$(VBOX_PATH_RUNTIME_SRC)/common/string/RTUtf16End.cpp \
diff --git a/src/VBox/HostDrivers/Support/SUPDrv.cpp b/src/VBox/HostDrivers/Support/SUPDrv.cpp
index 001a10d..051c2c9 100644
--- a/src/VBox/HostDrivers/Support/SUPDrv.cpp
+++ b/src/VBox/HostDrivers/Support/SUPDrv.cpp
@@ -198,6 +198,7 @@ static SUPFUNC g_aFunctions[] =
     { "SUPR0EnableVTx",                         (void *)(uintptr_t)SUPR0EnableVTx },
     { "SUPR0SuspendVTxOnCpu",                   (void *)(uintptr_t)SUPR0SuspendVTxOnCpu },
     { "SUPR0ResumeVTxOnCpu",                    (void *)(uintptr_t)SUPR0ResumeVTxOnCpu },
+    { "SUPR0GetCurrentGdtRw",                   (void *)(uintptr_t)SUPR0GetCurrentGdtRw },
     { "SUPR0GetKernelFeatures",                 (void *)(uintptr_t)SUPR0GetKernelFeatures },
     { "SUPR0GetPagingMode",                     (void *)(uintptr_t)SUPR0GetPagingMode },
     { "SUPR0GetSvmUsability",                   (void *)(uintptr_t)SUPR0GetSvmUsability },
@@ -216,6 +217,9 @@ static SUPFUNC g_aFunctions[] =
     { "SUPR0PageAllocEx",                       (void *)(uintptr_t)SUPR0PageAllocEx },
     { "SUPR0PageFree",                          (void *)(uintptr_t)SUPR0PageFree },
     { "SUPR0Printf",                            (void *)(uintptr_t)SUPR0Printf },
+    { "SUPR0GetSessionGVM",                     (void *)(uintptr_t)SUPR0GetSessionGVM },
+    { "SUPR0GetSessionVM",                      (void *)(uintptr_t)SUPR0GetSessionVM },
+    { "SUPR0SetSessionVM",                      (void *)(uintptr_t)SUPR0SetSessionVM },
     { "SUPR0TscDeltaMeasureBySetIndex",         (void *)(uintptr_t)SUPR0TscDeltaMeasureBySetIndex },
     { "SUPR0TracerDeregisterDrv",               (void *)(uintptr_t)SUPR0TracerDeregisterDrv },
     { "SUPR0TracerDeregisterImpl",              (void *)(uintptr_t)SUPR0TracerDeregisterImpl },
@@ -922,6 +926,18 @@ static void supdrvCleanupSession(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession)
     Log2(("release objects - done\n"));
 
     /*
+     * Make sure the associated VM pointers are NULL.
+     */
+    if (pSession->pSessionGVM || pSession->pSessionVM || pSession->pFastIoCtrlVM)
+    {
+        SUPR0Printf("supdrvCleanupSession: VM not disassociated! pSessionGVM=%p pSessionVM=%p pFastIoCtrlVM=%p\n",
+                    pSession->pSessionGVM, pSession->pSessionVM, pSession->pFastIoCtrlVM);
+        pSession->pSessionGVM   = NULL;
+        pSession->pSessionVM    = NULL;
+        pSession->pFastIoCtrlVM = NULL;
+    }
+
+    /*
      * Do tracer cleanups related to this session.
      */
     Log2(("release tracer stuff - start\n"));
@@ -1422,28 +1438,46 @@ static DECLCALLBACK(void) supdrvSessionObjHandleDelete(RTHANDLETABLE hHandleTabl
 int VBOXCALL supdrvIOCtlFast(uintptr_t uIOCtl, VMCPUID idCpu, PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession)
 {
     /*
-     * We check the two prereqs after doing this only to allow the compiler to optimize things better.
+     * Validate input and check that the VM has a session.
      */
-    if (RT_LIKELY(   RT_VALID_PTR(pSession)
-                  && pSession->pVM
-                  && pDevExt->pfnVMMR0EntryFast))
+    if (RT_LIKELY(RT_VALID_PTR(pSession)))
     {
-        switch (uIOCtl)
+        PVM  pVM  = pSession->pSessionVM;
+        PGVM pGVM = pSession->pSessionGVM;
+        if (RT_LIKELY(   pGVM != NULL
+                      && pVM  != NULL
+                      && pVM  == pSession->pFastIoCtrlVM))
         {
-            case SUP_IOCTL_FAST_DO_RAW_RUN:
-                pDevExt->pfnVMMR0EntryFast(pSession->pVM, idCpu, SUP_VMMR0_DO_RAW_RUN);
-                break;
-            case SUP_IOCTL_FAST_DO_HM_RUN:
-                pDevExt->pfnVMMR0EntryFast(pSession->pVM, idCpu, SUP_VMMR0_DO_HM_RUN);
-                break;
-            case SUP_IOCTL_FAST_DO_NOP:
-                pDevExt->pfnVMMR0EntryFast(pSession->pVM, idCpu, SUP_VMMR0_DO_NOP);
-                break;
-            default:
-                return VERR_INTERNAL_ERROR;
+            if (RT_LIKELY(pDevExt->pfnVMMR0EntryFast))
+            {
+                /*
+                 * Do the call.
+                 */
+                switch (uIOCtl)
+                {
+                    case SUP_IOCTL_FAST_DO_RAW_RUN:
+                        pDevExt->pfnVMMR0EntryFast(pGVM, pVM, idCpu, SUP_VMMR0_DO_RAW_RUN);
+                        break;
+                    case SUP_IOCTL_FAST_DO_HM_RUN:
+                        pDevExt->pfnVMMR0EntryFast(pGVM, pVM, idCpu, SUP_VMMR0_DO_HM_RUN);
+                        break;
+                    case SUP_IOCTL_FAST_DO_NOP:
+                        pDevExt->pfnVMMR0EntryFast(pGVM, pVM, idCpu, SUP_VMMR0_DO_NOP);
+                        break;
+                    default:
+                        return VERR_INTERNAL_ERROR;
+                }
+                return VINF_SUCCESS;
+            }
+
+            SUPR0Printf("supdrvIOCtlFast: pfnVMMR0EntryFast is NULL\n");
         }
-        return VINF_SUCCESS;
+        else
+            SUPR0Printf("supdrvIOCtlFast: Misconfig session: pGVM=%p pVM=%p pFastIoCtrlVM=%p\n",
+                        pGVM, pVM, pSession->pFastIoCtrlVM);
     }
+    else
+        SUPR0Printf("supdrvIOCtlFast: Bad session pointer %p\n", pSession);
     return VERR_INTERNAL_ERROR;
 }
 
@@ -1779,7 +1813,16 @@ static int supdrvIOCtlInnerUnrestricted(uintptr_t uIOCtl, PSUPDRVDEVEXT pDevExt,
 
                 /* execute */
                 if (RT_LIKELY(pDevExt->pfnVMMR0EntryEx))
-                    pReq->Hdr.rc = pDevExt->pfnVMMR0EntryEx(pReq->u.In.pVMR0, pReq->u.In.idCpu, pReq->u.In.uOperation, NULL, pReq->u.In.u64Arg, pSession);
+                {
+                    if (pReq->u.In.pVMR0 == NULL)
+                        pReq->Hdr.rc = pDevExt->pfnVMMR0EntryEx(NULL, NULL, pReq->u.In.idCpu,
+                                                                pReq->u.In.uOperation, NULL, pReq->u.In.u64Arg, pSession);
+                    else if (pReq->u.In.pVMR0 == pSession->pSessionVM)
+                        pReq->Hdr.rc = pDevExt->pfnVMMR0EntryEx(pSession->pSessionGVM, pSession->pSessionVM, pReq->u.In.idCpu,
+                                                                pReq->u.In.uOperation, NULL, pReq->u.In.u64Arg, pSession);
+                    else
+                        pReq->Hdr.rc = VERR_INVALID_VM_HANDLE;
+                }
                 else
                     pReq->Hdr.rc = VERR_WRONG_ORDER;
             }
@@ -1793,7 +1836,16 @@ static int supdrvIOCtlInnerUnrestricted(uintptr_t uIOCtl, PSUPDRVDEVEXT pDevExt,
 
                 /* execute */
                 if (RT_LIKELY(pDevExt->pfnVMMR0EntryEx))
-                    pReq->Hdr.rc = pDevExt->pfnVMMR0EntryEx(pReq->u.In.pVMR0, pReq->u.In.idCpu, pReq->u.In.uOperation, pVMMReq, pReq->u.In.u64Arg, pSession);
+                {
+                    if (pReq->u.In.pVMR0 == NULL)
+                        pReq->Hdr.rc = pDevExt->pfnVMMR0EntryEx(NULL, NULL, pReq->u.In.idCpu,
+                                                                pReq->u.In.uOperation, pVMMReq, pReq->u.In.u64Arg, pSession);
+                    else if (pReq->u.In.pVMR0 == pSession->pSessionVM)
+                        pReq->Hdr.rc = pDevExt->pfnVMMR0EntryEx(pSession->pSessionGVM, pSession->pSessionVM, pReq->u.In.idCpu,
+                                                                pReq->u.In.uOperation, pVMMReq, pReq->u.In.u64Arg, pSession);
+                    else
+                        pReq->Hdr.rc = VERR_INVALID_VM_HANDLE;
+                }
                 else
                     pReq->Hdr.rc = VERR_WRONG_ORDER;
             }
@@ -1825,7 +1877,15 @@ static int supdrvIOCtlInnerUnrestricted(uintptr_t uIOCtl, PSUPDRVDEVEXT pDevExt,
 
             /* execute */
             if (RT_LIKELY(pDevExt->pfnVMMR0EntryEx))
-                pReq->Hdr.rc = pDevExt->pfnVMMR0EntryEx(pReq->u.In.pVMR0, pReq->u.In.idCpu, pReq->u.In.uOperation, pVMMReq, pReq->u.In.u64Arg, pSession);
+            {
+                if (pReq->u.In.pVMR0 == NULL)
+                    pReq->Hdr.rc = pDevExt->pfnVMMR0EntryEx(NULL, NULL, pReq->u.In.idCpu, pReq->u.In.uOperation, pVMMReq, pReq->u.In.u64Arg, pSession);
+                else if (pReq->u.In.pVMR0 == pSession->pSessionVM)
+                    pReq->Hdr.rc = pDevExt->pfnVMMR0EntryEx(pSession->pSessionGVM, pSession->pSessionVM, pReq->u.In.idCpu,
+                                                            pReq->u.In.uOperation, pVMMReq, pReq->u.In.u64Arg, pSession);
+                else
+                    pReq->Hdr.rc = VERR_INVALID_VM_HANDLE;
+            }
             else
                 pReq->Hdr.rc = VERR_WRONG_ORDER;
 
@@ -1910,9 +1970,32 @@ static int supdrvIOCtlInnerUnrestricted(uintptr_t uIOCtl, PSUPDRVDEVEXT pDevExt,
                                ||   (   VALID_PTR(pReq->u.In.pVMR0)
                                      && !((uintptr_t)pReq->u.In.pVMR0 & (PAGE_SIZE - 1))),
                                ("SUP_IOCTL_SET_VM_FOR_FAST: pVMR0=%p!\n", pReq->u.In.pVMR0));
+
             /* execute */
-            pSession->pVM = pReq->u.In.pVMR0;
-            pReq->Hdr.rc = VINF_SUCCESS;
+            RTSpinlockAcquire(pDevExt->Spinlock);
+            if (pSession->pSessionVM == pReq->u.In.pVMR0)
+            {
+                if (pSession->pFastIoCtrlVM == NULL)
+                {
+                    pSession->pFastIoCtrlVM = pSession->pSessionVM;
+                    RTSpinlockRelease(pDevExt->Spinlock);
+                    pReq->Hdr.rc = VINF_SUCCESS;
+                }
+                else
+                {
+                    RTSpinlockRelease(pDevExt->Spinlock);
+                    OSDBGPRINT(("SUP_IOCTL_SET_VM_FOR_FAST: pSession->pFastIoCtrlVM=%p! (pVMR0=%p)\n",
+                                pSession->pFastIoCtrlVM, pReq->u.In.pVMR0));
+                    pReq->Hdr.rc = VERR_ALREADY_EXISTS;
+                }
+            }
+            else
+            {
+                RTSpinlockRelease(pDevExt->Spinlock);
+                OSDBGPRINT(("SUP_IOCTL_SET_VM_FOR_FAST: pSession->pSessionVM=%p vs pVMR0=%p)\n",
+                            pSession->pSessionVM, pReq->u.In.pVMR0));
+                pReq->Hdr.rc = pSession->pSessionVM ? VERR_ACCESS_DENIED : VERR_WRONG_ORDER;
+            }
             return 0;
         }
 
@@ -2301,6 +2384,19 @@ static int supdrvIOCtlInnerUnrestricted(uintptr_t uIOCtl, PSUPDRVDEVEXT pDevExt,
             return 0;
         }
 
+        case SUP_CTL_CODE_NO_SIZE(SUP_IOCTL_UCODE_REV):
+        {
+            /* validate */
+            PSUPUCODEREV pReq = (PSUPUCODEREV)pReqHdr;
+            REQ_CHECK_SIZES(SUP_IOCTL_UCODE_REV);
+    
+            /* execute */
+            pReq->Hdr.rc = SUPR0QueryUcodeRev(pSession, &pReq->u.Out.MicrocodeRev);
+            if (RT_FAILURE(pReq->Hdr.rc))
+                pReq->Hdr.cbOut = sizeof(pReq->Hdr);
+            return 0;
+        }
+    
         default:
             Log(("Unknown IOCTL %#lx\n", (long)uIOCtl));
             break;
@@ -2998,6 +3094,83 @@ SUPR0DECL(int) SUPR0ObjVerifyAccess(void *pvObj, PSUPDRVSESSION pSession, const
 
 
 /**
+ * API for the VMMR0 module to get the SUPDRVSESSION::pSessionVM member.
+ *
+ * @returns The associated VM pointer.
+ * @param   pSession    The session of the current thread.
+ */
+SUPR0DECL(PVM) SUPR0GetSessionVM(PSUPDRVSESSION pSession)
+{
+    AssertReturn(SUP_IS_SESSION_VALID(pSession), NULL);
+    return pSession->pSessionVM;
+}
+
+
+/**
+ * API for the VMMR0 module to get the SUPDRVSESSION::pSessionGVM member.
+ *
+ * @returns The associated GVM pointer.
+ * @param   pSession    The session of the current thread.
+ */
+SUPR0DECL(PGVM) SUPR0GetSessionGVM(PSUPDRVSESSION pSession)
+{
+    AssertReturn(SUP_IS_SESSION_VALID(pSession), NULL);
+    return pSession->pSessionGVM;
+}
+
+
+/**
+ * API for the VMMR0 module to work the SUPDRVSESSION::pSessionVM member.
+ *
+ * This will fail if there is already a VM associated with the session and pVM
+ * isn't NULL.
+ *
+ * @retval  VINF_SUCCESS
+ * @retval  VERR_ALREADY_EXISTS if there already is a VM associated with the
+ *          session.
+ * @retval  VERR_INVALID_PARAMETER if only one of the parameters are NULL or if
+ *          the session is invalid.
+ *
+ * @param   pSession    The session of the current thread.
+ * @param   pGVM        The GVM to associate with the session.  Pass NULL to
+ *                      dissassociate.
+ * @param   pVM         The VM to associate with the session.  Pass NULL to
+ *                      dissassociate.
+ */
+SUPR0DECL(int) SUPR0SetSessionVM(PSUPDRVSESSION pSession, PGVM pGVM, PVM pVM)
+{
+    AssertReturn(SUP_IS_SESSION_VALID(pSession), VERR_INVALID_PARAMETER);
+    AssertReturn((pGVM != NULL) == (pVM != NULL), VERR_INVALID_PARAMETER);
+
+    RTSpinlockAcquire(pSession->pDevExt->Spinlock);
+    if (pGVM)
+    {
+        if (!pSession->pSessionGVM)
+        {
+            pSession->pSessionGVM   = pGVM;
+            pSession->pSessionVM    = pVM;
+            pSession->pFastIoCtrlVM = NULL;
+        }
+        else
+        {
+            RTSpinlockRelease(pSession->pDevExt->Spinlock);
+            SUPR0Printf("SUPR0SetSessionVM: Unable to associated GVM/VM %p/%p with session %p as it has %p/%p already!\n",
+                        pGVM, pVM, pSession, pSession->pSessionGVM, pSession->pSessionVM);
+            return VERR_ALREADY_EXISTS;
+        }
+    }
+    else
+    {
+        pSession->pSessionGVM   = NULL;
+        pSession->pSessionVM    = NULL;
+        pSession->pFastIoCtrlVM = NULL;
+    }
+    RTSpinlockRelease(pSession->pDevExt->Spinlock);
+    return VINF_SUCCESS;
+}
+
+
+/**
  * Lock pages.
  *
  * @returns IPRT status code.
@@ -3876,6 +4049,17 @@ SUPR0DECL(void) SUPR0ResumeVTxOnCpu(bool fSuspended)
 }
 
 
+SUPR0DECL(int) SUPR0GetCurrentGdtRw(RTHCUINTPTR *pGdtRw)
+{
+#ifdef RT_OS_LINUX
+    return supdrvOSGetCurrentGdtRw(pGdtRw);
+#else
+    NOREF(pGdtRw);
+    return VERR_NOT_IMPLEMENTED;
+#endif
+}
+
+
 /**
  * Checks if Intel VT-x feature is usable on this CPU.
  *
@@ -4192,6 +4376,97 @@ SUPR0DECL(int) SUPR0QueryVTCaps(PSUPDRVSESSION pSession, uint32_t *pfCaps)
 
 
 /**
+ * Queries the CPU microcode revision.
+ *
+ * @returns VBox status code.
+ * @retval  VERR_UNSUPPORTED_CPU if not identifiable as a processor with
+ *          readable microcode rev.
+ *
+ * @param   puRevision      Where to store the microcode revision.
+ */
+int VBOXCALL supdrvQueryUcodeRev(uint32_t *puRevision)
+{
+    int  rc = VERR_UNSUPPORTED_CPU;
+    RTTHREADPREEMPTSTATE PreemptState = RTTHREADPREEMPTSTATE_INITIALIZER;
+
+    /*
+     * Input validation.
+     */
+    AssertPtrReturn(puRevision, VERR_INVALID_POINTER);
+
+    *puRevision = 0;
+
+    /* Disable preemption so we make sure we don't migrate CPUs, just in case. */
+    /* NB: We assume that there aren't mismatched microcode revs in the system. */
+    RTThreadPreemptDisable(&PreemptState);
+
+    if (ASMHasCpuId())
+    {
+        uint32_t uDummy, uTFMSEAX;
+        uint32_t uMaxId, uVendorEBX, uVendorECX, uVendorEDX;
+
+        ASMCpuId(0, &uMaxId, &uVendorEBX, &uVendorECX, &uVendorEDX);
+        ASMCpuId(1, &uTFMSEAX, &uDummy, &uDummy, &uDummy);
+
+        if (ASMIsValidStdRange(uMaxId))
+        {
+            uint64_t    uRevMsr;
+            if (ASMIsIntelCpuEx(uVendorEBX, uVendorECX, uVendorEDX))
+            {
+                /* Architectural MSR available on Pentium Pro and later. */
+                if (ASMGetCpuFamily(uTFMSEAX) >= 6)
+                {
+                    /* Revision is in the high dword. */
+                    uRevMsr = ASMRdMsr(MSR_IA32_BIOS_SIGN_ID);
+                    *puRevision = RT_HIDWORD(uRevMsr);
+                    rc = VINF_SUCCESS;
+                }
+            } 
+            else if (ASMIsAmdCpuEx(uVendorEBX, uVendorECX, uVendorEDX))
+            {
+                /* Not well documented, but at least all AMD64 CPUs support this. */
+                if (ASMGetCpuFamily(uTFMSEAX) >= 15)
+                {
+                    /* Revision is in the low dword. */
+                    uRevMsr = ASMRdMsr(MSR_IA32_BIOS_SIGN_ID);  /* Same MSR as Intel. */
+                    *puRevision = RT_LODWORD(uRevMsr);
+                    rc = VINF_SUCCESS;
+                }
+            }
+        }
+    }
+
+    RTThreadPreemptRestore(&PreemptState);
+
+    return rc;
+}
+
+/**
+ * Queries the CPU microcode revision.
+ *
+ * @returns VBox status code.
+ * @retval  VERR_UNSUPPORTED_CPU if not identifiable as a processor with
+ *          readable microcode rev.
+ *
+ * @param   pSession        The session handle.
+ * @param   puRevision      Where to store the microcode revision.
+ */
+SUPR0DECL(int) SUPR0QueryUcodeRev(PSUPDRVSESSION pSession, uint32_t *puRevision)
+{
+    /*
+     * Input validation.
+     */
+    AssertReturn(SUP_IS_SESSION_VALID(pSession), VERR_INVALID_PARAMETER);
+    AssertPtrReturn(puRevision, VERR_INVALID_POINTER);
+
+    /*
+     * Call common worker.
+     */
+    return supdrvQueryUcodeRev(puRevision);
+}
+
+
+/**
  * Register a component factory with the support driver.
  *
  * This is currently restricted to kernel sessions only.
diff --git a/src/VBox/HostDrivers/Support/SUPDrvIOC.h b/src/VBox/HostDrivers/Support/SUPDrvIOC.h
index 1d176a6..700a50a 100644
--- a/src/VBox/HostDrivers/Support/SUPDrvIOC.h
+++ b/src/VBox/HostDrivers/Support/SUPDrvIOC.h
@@ -214,7 +214,7 @@ typedef SUPREQHDR *PSUPREQHDR;
  * @todo Pending work on next major version change:
  *          - nothing.
  */
-#define SUPDRV_IOC_VERSION                              0x00280000
+#define SUPDRV_IOC_VERSION                              0x002a0000
 
 /** SUP_IOCTL_COOKIE. */
 typedef struct SUPCOOKIE
@@ -1596,6 +1596,32 @@ typedef struct SUPGIPSETFLAGS
 } SUPGIPSETFLAGS, *PSUPGIPSETFLAGS;
 /** @} */
 
+
+/** @name SUP_IOCTL_UCODE_REV
+ * Get the CPU microcode revision.
+ *
+ * @{
+ */
+#define SUP_IOCTL_UCODE_REV                             SUP_CTL_CODE_SIZE(40, SUP_IOCTL_VT_CAPS_SIZE)
+#define SUP_IOCTL_UCODE_REV_SIZE                        sizeof(SUPUCODEREV)
+#define SUP_IOCTL_UCODE_REV_SIZE_IN                     sizeof(SUPREQHDR)
+#define SUP_IOCTL_UCODE_REV_SIZE_OUT                    sizeof(SUPUCODEREV)
+typedef struct SUPUCODEREV
+{
+    /** The header. */
+    SUPREQHDR               Hdr;
+    union
+    {
+        struct
+        {
+            /** The microcode revision dword. */
+            uint32_t        MicrocodeRev;
+        } Out;
+    } u;
+} SUPUCODEREV, *PSUPUCODEREV;
+/** @} */
+
+
 #pragma pack()                          /* paranoia */
 
 #endif
diff --git a/src/VBox/HostDrivers/Support/SUPDrvInternal.h b/src/VBox/HostDrivers/Support/SUPDrvInternal.h
index f439508..15af8c4 100644
--- a/src/VBox/HostDrivers/Support/SUPDrvInternal.h
+++ b/src/VBox/HostDrivers/Support/SUPDrvInternal.h
@@ -487,8 +487,14 @@ typedef struct SUPDRVSESSION
      * This is NIL_RTR0PROCESS for kernel sessions and valid for user ones. */
     RTR0PROCESS                     R0Process;
 
-    /** The VM associated with the session. */
-    PVM                             pVM;
+    /** The GVM associated with the session.
+     * This is set by VMMR0.  */
+    PGVM                            pSessionGVM;
+    /** The VM associated with the session.
+     * This is set by VMMR0.  */
+    PVM                             pSessionVM;
+    /** Set to pSessionVM if fast I/O controlls are enabled. */
+    PVM                             pFastIoCtrlVM;
     /** Handle table for IPRT semaphore wrapper APIs.
      * This takes care of its own locking in an IRQ safe manner. */
     RTHANDLETABLE                   hHandleTable;
@@ -587,9 +593,10 @@ typedef struct SUPDRVDEVEXT
      * 0 if the code VMM isn't loaded and Idt are nops. */
     void * volatile                 pvVMMR0;
     /** VMMR0EntryFast() pointer. */
-    DECLR0CALLBACKMEMBER(void,      pfnVMMR0EntryFast, (PVM pVM, VMCPUID idCpu, unsigned uOperation));
+    DECLR0CALLBACKMEMBER(void,      pfnVMMR0EntryFast, (PGVM pGVM, PVM pVM, VMCPUID idCpu, uint32_t uOperation));
     /** VMMR0EntryEx() pointer. */
-    DECLR0CALLBACKMEMBER(int,       pfnVMMR0EntryEx, (PVM pVM, VMCPUID idCpu, unsigned uOperation, PSUPVMMR0REQHDR pReq, uint64_t u64Arg, PSUPDRVSESSION pSession));
+    DECLR0CALLBACKMEMBER(int,       pfnVMMR0EntryEx, (PGVM pGVM, PVM pVM, VMCPUID idCpu, uint32_t uOperation,
+                                                      PSUPVMMR0REQHDR pReq, uint64_t u64Arg, PSUPDRVSESSION pSession));
 
     /** Linked list of loaded code. */
     PSUPDRVLDRIMAGE volatile        pLdrImages;
@@ -841,6 +848,7 @@ int  VBOXCALL   supdrvOSEnableVTx(bool fEnabled);
 RTCCUINTREG VBOXCALL supdrvOSChangeCR4(RTCCUINTREG fOrMask, RTCCUINTREG fAndMask);
 bool VBOXCALL   supdrvOSSuspendVTxOnCpu(void);
 void VBOXCALL   supdrvOSResumeVTxOnCpu(bool fSuspended);
+int  VBOXCALL   supdrvOSGetCurrentGdtRw(RTHCUINTPTR *pGdtRw);
 
 /**
  * Try open the image using the native loader.
diff --git a/src/VBox/HostDrivers/Support/SUPLib.cpp b/src/VBox/HostDrivers/Support/SUPLib.cpp
index fc5f623..e2b162d 100644
--- a/src/VBox/HostDrivers/Support/SUPLib.cpp
+++ b/src/VBox/HostDrivers/Support/SUPLib.cpp
@@ -275,8 +275,8 @@ SUPR3DECL(int) SUPR3InitEx(bool fUnrestricted, PSUPDRVSESSION *ppSession)
         CookieReq.Hdr.rc = VERR_INTERNAL_ERROR;
         strcpy(CookieReq.u.In.szMagic, SUPCOOKIE_MAGIC);
         CookieReq.u.In.u32ReqVersion = SUPDRV_IOC_VERSION;
-        const uint32_t uMinVersion = (SUPDRV_IOC_VERSION & 0xffff0000) == 0x00230000
-                                   ? 0x00230003
+        const uint32_t uMinVersion = (SUPDRV_IOC_VERSION & 0xffff0000) == 0x00280000
+                                   ? 0x00280002
                                    : SUPDRV_IOC_VERSION & 0xffff0000;
         CookieReq.u.In.u32MinVersion = uMinVersion;
         rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_COOKIE, &CookieReq, SUP_IOCTL_COOKIE_SIZE);
@@ -1700,6 +1700,38 @@ SUPR3DECL(int) SUPR3QueryVTCaps(uint32_t *pfCaps)
 }
 
 
+SUPR3DECL(int) SUPR3QueryMicrocodeRev(uint32_t *uMicrocodeRev)
+{
+    AssertPtrReturn(uMicrocodeRev, VERR_INVALID_POINTER);
+
+    *uMicrocodeRev = 0;
+
+    /* fake */
+    if (RT_UNLIKELY(g_uSupFakeMode))
+        return VINF_SUCCESS;
+
+    /*
+     * Issue IOCtl to the SUPDRV kernel module.
+     */
+    SUPUCODEREV Req;
+    Req.Hdr.u32Cookie = g_u32Cookie;
+    Req.Hdr.u32SessionCookie = g_u32SessionCookie;
+    Req.Hdr.cbIn = SUP_IOCTL_UCODE_REV_SIZE_IN;
+    Req.Hdr.cbOut = SUP_IOCTL_UCODE_REV_SIZE_OUT;
+    Req.Hdr.fFlags = SUPREQHDR_FLAGS_DEFAULT;
+    Req.Hdr.rc = VERR_INTERNAL_ERROR;
+    Req.u.Out.MicrocodeRev = 0;
+    int rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_UCODE_REV, &Req, SUP_IOCTL_UCODE_REV_SIZE);
+    if (RT_SUCCESS(rc))
+    {
+        rc = Req.Hdr.rc;
+        if (RT_SUCCESS(rc))
+            *uMicrocodeRev = Req.u.Out.MicrocodeRev;
+    }
+    return rc;
+}
+
+
 SUPR3DECL(int) SUPR3TracerOpen(uint32_t uCookie, uintptr_t uArg)
 {
     /* fake */
diff --git a/src/VBox/HostDrivers/Support/SUPR3HardenedMain.cpp b/src/VBox/HostDrivers/Support/SUPR3HardenedMain.cpp
index 137ebfa..714f7cd 100644
--- a/src/VBox/HostDrivers/Support/SUPR3HardenedMain.cpp
+++ b/src/VBox/HostDrivers/Support/SUPR3HardenedMain.cpp
@@ -1041,6 +1041,7 @@ DECLHIDDEN(void) suplibHardenedPrintFV(const char *pszFormat, va_list va)
                             break;
                         case 'X':
                             fFlags |= RTSTR_F_CAPITAL;
+                            /* fall thru */
                         case 'x':
                             uBase = 16;
                             break;
diff --git a/src/VBox/HostDrivers/Support/SUPR3HardenedVerify.cpp b/src/VBox/HostDrivers/Support/SUPR3HardenedVerify.cpp
index ce0f288..6a9de22 100644
--- a/src/VBox/HostDrivers/Support/SUPR3HardenedVerify.cpp
+++ b/src/VBox/HostDrivers/Support/SUPR3HardenedVerify.cpp
@@ -86,6 +86,9 @@
 /** The max path length acceptable for a trusted path. */
 #define SUPR3HARDENED_MAX_PATH      260U
 
+/** Enable to resolve symlinks using realpath() instead of cooking our own stuff. */
+#define SUP_HARDENED_VERIFY_FOLLOW_SYMLINKS_USE_REALPATH 1
+
 #ifdef RT_OS_SOLARIS
 # define dirfd(d) ((d)->d_fd)
 #endif
@@ -1091,7 +1094,8 @@ static int supR3HardenedSetError2(int rc, PRTERRINFO pErrInfo, const char *pszMs
 #endif
 
 
-#if defined(RT_OS_DARWIN) || defined(RT_OS_LINUX)
+#ifndef SUP_HARDENED_VERIFY_FOLLOW_SYMLINKS_USE_REALPATH
+# if defined(RT_OS_DARWIN) || defined(RT_OS_LINUX)
 /**
  * Copies the error message to the error buffer and returns @a rc.
  *
@@ -1104,6 +1108,7 @@ static int supR3HardenedSetError(int rc, PRTERRINFO pErrInfo, const char *pszMsg
 {
     return supR3HardenedSetErrorN(rc, pErrInfo, 1, pszMsg);
 }
+# endif
 #endif
 
 
@@ -1893,7 +1898,9 @@ DECLHIDDEN(int) supR3HardenedVerifyFileFollowSymlinks(const char *pszFilename, R
     /*
      * Verify each component from the root up.
      */
+#ifndef SUP_HARDENED_VERIFY_FOLLOW_SYMLINKS_USE_REALPATH
     uint32_t                iLoops = 0;
+#endif
     SUPR3HARDENEDFSOBJSTATE FsObjState;
     uint32_t                iComponent = 0;
     while (iComponent < Info.cComponents)
@@ -1915,6 +1922,24 @@ DECLHIDDEN(int) supR3HardenedVerifyFileFollowSymlinks(const char *pszFilename, R
             if (   RT_SUCCESS(rc)
                 && S_ISLNK(FsObjState.Stat.st_mode))
             {
+#if SUP_HARDENED_VERIFY_FOLLOW_SYMLINKS_USE_REALPATH /* Another approach using realpath() and verifying the result when encountering a symlink. */
+                char *pszFilenameResolved = realpath(pszFilename, NULL);
+                if (pszFilenameResolved)
+                {
+                    rc = supR3HardenedVerifyFile(pszFilenameResolved, hNativeFile, fMaybe3rdParty, pErrInfo);
+                    free(pszFilenameResolved);
+                    return rc;
+                }
+                else
+                {
+                    int iErr = errno;
+                    supR3HardenedError(VERR_ACCESS_DENIED, false /*fFatal*/,
+                                       "supR3HardenedVerifyFileFollowSymlinks: Failed to resolve the real path '%s': %s (%d)\n",
+                                       pszFilename, strerror(iErr), iErr);
+                    return supR3HardenedSetError4(VERR_ACCESS_DENIED, pErrInfo,
+                                                  "realpath failed for '", pszFilename, "': ", strerror(iErr));
+                }
+#else
                 /* Don't loop forever. */
                 iLoops++;
                 if (iLoops < 8)
@@ -1989,6 +2014,7 @@ DECLHIDDEN(int) supR3HardenedVerifyFileFollowSymlinks(const char *pszFilename, R
                 else
                     return supR3HardenedSetError3(VERR_TOO_MANY_SYMLINKS, pErrInfo,
                                                   "Too many symbolic links: '", pszFilename, "'");
+#endif
             }
         }
         if (RT_FAILURE(rc))
diff --git a/src/VBox/HostDrivers/Support/linux/Makefile b/src/VBox/HostDrivers/Support/linux/Makefile
index 3e38a63..e9a4346 100644
--- a/src/VBox/HostDrivers/Support/linux/Makefile
+++ b/src/VBox/HostDrivers/Support/linux/Makefile
@@ -158,6 +158,7 @@ OBJS += math/gcc/divdi3.o \
 	math/gcc/moddi3.o \
 	math/gcc/qdivrem.o \
 	math/gcc/udivdi3.o \
+	math/gcc/udivmoddi4.o \
 	math/gcc/divdi3.o \
 	math/gcc/umoddi3.o
 endif
diff --git a/src/VBox/HostDrivers/Support/linux/SUPDrv-linux.c b/src/VBox/HostDrivers/Support/linux/SUPDrv-linux.c
index 0beb736..f14fbef 100644
--- a/src/VBox/HostDrivers/Support/linux/SUPDrv-linux.c
+++ b/src/VBox/HostDrivers/Support/linux/SUPDrv-linux.c
@@ -1,4 +1,4 @@
-/* $Rev: 109268 $ */
+/* $Rev: 115966 $ */
 /** @file
  * VBoxDrv - The VirtualBox Support Driver - Linux specifics.
  */
@@ -61,6 +61,8 @@
 # include <asm/msr.h>
 #endif
 
+#include <asm/desc.h>
+
 #include <iprt/asm-amd64-x86.h>
 
 
@@ -1400,6 +1402,9 @@ SUPR0DECL(uint32_t) SUPR0GetKernelFeatures(void)
 #ifdef CONFIG_PAX_KERNEXEC
     fFlags |= SUPKERNELFEATURES_GDT_READ_ONLY;
 #endif
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)
+    fFlags |= SUPKERNELFEATURES_GDT_NEED_WRITABLE;
+#endif
 #if defined(VBOX_STRICT) || defined(VBOX_WITH_EFLAGS_AC_SET_IN_VBOXDRV)
     fFlags |= SUPKERNELFEATURES_SMAP;
 #elif defined(CONFIG_X86_SMAP)
@@ -1410,6 +1415,17 @@ SUPR0DECL(uint32_t) SUPR0GetKernelFeatures(void)
 }
 
 
+int VBOXCALL    supdrvOSGetCurrentGdtRw(RTHCUINTPTR *pGdtRw)
+{
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)
+    *pGdtRw = (RTHCUINTPTR)get_current_gdt_rw();
+    return VINF_SUCCESS;
+#else
+    return VERR_NOT_IMPLEMENTED;
+#endif
+}
+
+
 module_init(VBoxDrvLinuxInit);
 module_exit(VBoxDrvLinuxUnload);
 
diff --git a/src/VBox/HostDrivers/Support/linux/files_vboxdrv b/src/VBox/HostDrivers/Support/linux/files_vboxdrv
index ba9b829..b804a67 100755
--- a/src/VBox/HostDrivers/Support/linux/files_vboxdrv
+++ b/src/VBox/HostDrivers/Support/linux/files_vboxdrv
@@ -65,6 +65,7 @@ FILES_VBOXDRV_NOBIN=" \
     ${PATH_ROOT}/include/iprt/timer.h=>include/iprt/timer.h \
     ${PATH_ROOT}/include/iprt/types.h=>include/iprt/types.h \
     ${PATH_ROOT}/include/iprt/uint128.h=>include/iprt/uint128.h \
+    ${PATH_ROOT}/include/iprt/uint64.h=>include/iprt/uint64.h \
     ${PATH_ROOT}/include/iprt/uni.h=>include/iprt/uni.h \
     ${PATH_ROOT}/include/iprt/utf16.h=>include/iprt/utf16.h \
     ${PATH_ROOT}/include/iprt/uuid.h=>include/iprt/uuid.h \
@@ -109,6 +110,7 @@ FILES_VBOXDRV_NOBIN=" \
     ${PATH_ROOT}/src/VBox/Runtime/common/math/gcc/qdivrem.c=>math/gcc/qdivrem.c \
     ${PATH_ROOT}/src/VBox/Runtime/common/math/gcc/quad.h=>math/gcc/quad.h \
     ${PATH_ROOT}/src/VBox/Runtime/common/math/gcc/udivdi3.c=>math/gcc/udivdi3.c \
+    ${PATH_ROOT}/src/VBox/Runtime/common/math/gcc/udivmoddi4.c=>math/gcc/udivmoddi4.c \
     ${PATH_ROOT}/src/VBox/Runtime/common/math/gcc/umoddi3.c=>math/gcc/umoddi3.c \
     ${PATH_ROOT}/src/VBox/Runtime/common/misc/RTAssertMsg1Weak.cpp=>common/misc/RTAssertMsg1Weak.c \
     ${PATH_ROOT}/src/VBox/Runtime/common/misc/RTAssertMsg2.cpp=>common/misc/RTAssertMsg2.c \
diff --git a/src/VBox/HostDrivers/Support/posix/SUPR3HardenedMain-posix.cpp b/src/VBox/HostDrivers/Support/posix/SUPR3HardenedMain-posix.cpp
index f8f4187..5ec157a 100644
--- a/src/VBox/HostDrivers/Support/posix/SUPR3HardenedMain-posix.cpp
+++ b/src/VBox/HostDrivers/Support/posix/SUPR3HardenedMain-posix.cpp
@@ -341,6 +341,7 @@ static int supR3HardenedMainPosixHookOne(const char *pszSymbol, PFNRT pfnHook, P
      * Patch 64-bit hosts.
      */
     uint32_t cRipRelMovs = 0;
+    uint32_t cRelCalls = 0;
 
     /* Just use the disassembler to skip 12 bytes or more, we might need to
        rewrite mov instructions using RIP relative addressing. */
@@ -349,7 +350,8 @@ static int supR3HardenedMainPosixHookOne(const char *pszSymbol, PFNRT pfnHook, P
         cbInstr = 1;
         int rc = DISInstr(pbTarget + offJmpBack, DISCPUMODE_64BIT, &Dis, &cbInstr);
         if (   RT_FAILURE(rc)
-            || (Dis.pCurInstr->fOpType & DISOPTYPE_CONTROLFLOW)
+            || (   Dis.pCurInstr->fOpType & DISOPTYPE_CONTROLFLOW
+                && Dis.pCurInstr->uOpcode != OP_CALL)
             || (   Dis.ModRM.Bits.Mod == 0
                 && Dis.ModRM.Bits.Rm  == 5 /* wrt RIP */
                 && Dis.pCurInstr->uOpcode != OP_MOV))
@@ -357,15 +359,23 @@ static int supR3HardenedMainPosixHookOne(const char *pszSymbol, PFNRT pfnHook, P
 
         if (Dis.ModRM.Bits.Mod == 0 && Dis.ModRM.Bits.Rm == 5 /* wrt RIP */)
             cRipRelMovs++;
+        if (   Dis.pCurInstr->uOpcode == OP_CALL
+            && (Dis.pCurInstr->fOpType & DISOPTYPE_RELATIVE_CONTROLFLOW))
+            cRelCalls++;
 
         offJmpBack += cbInstr;
         cbPatchMem += cbInstr;
     }
 
+    /*
+     * Each relative call requires extra bytes as it is converted to a pushq imm32
+     * + mov [RSP+4], imm32 + a jmp qword [$+8 wrt RIP] to avoid clobbering registers.
+     */
+    cbPatchMem += cRelCalls * RT_ALIGN_32(13 + 6 + 8, 8);
     cbPatchMem += 14; /* jmp qword [$+8 wrt RIP] + 8 byte address to jump to. */
     cbPatchMem = RT_ALIGN_32(cbPatchMem, 8);
 
-    /* Allocate suitable exectuable memory available. */
+    /* Allocate suitable executable memory available. */
     bool fConvRipRelMovs = false;
     uint8_t *pbPatchMem = supR3HardenedMainPosixExecMemAlloc(cbPatchMem, pbTarget, cRipRelMovs > 0);
     if (!pbPatchMem)
@@ -396,7 +406,8 @@ static int supR3HardenedMainPosixHookOne(const char *pszSymbol, PFNRT pfnHook, P
         cbInstr = 1;
         int rc = DISInstr(pbTarget + offInsn, DISCPUMODE_64BIT, &Dis, &cbInstr);
         if (   RT_FAILURE(rc)
-            || (Dis.pCurInstr->fOpType & DISOPTYPE_CONTROLFLOW))
+            || (   Dis.pCurInstr->fOpType & DISOPTYPE_CONTROLFLOW
+                && Dis.pCurInstr->uOpcode != OP_CALL))
             return VERR_SUPLIB_UNEXPECTED_INSTRUCTION;
 
         if (   Dis.ModRM.Bits.Mod == 0
@@ -439,6 +450,34 @@ static int supR3HardenedMainPosixHookOne(const char *pszSymbol, PFNRT pfnHook, P
                 pbPatchMem   += sizeof(int32_t);
             }
         }
+        else if (   Dis.pCurInstr->uOpcode == OP_CALL
+                 && (Dis.pCurInstr->fOpType & DISOPTYPE_RELATIVE_CONTROLFLOW))
+        {
+            /* Convert to absolute jump. */
+            uintptr_t uAddr = (uintptr_t)&pbTarget[offInsn + cbInstr] + (intptr_t)Dis.Param1.uValue;
+
+            /* Skip the push instructions till the return address is known. */
+            uint8_t *pbPatchMemPush = pbPatchMem;
+            pbPatchMem += 13;
+
+            *pbPatchMem++ = 0xff; /* jmp qword [$+8 wrt RIP] */
+            *pbPatchMem++ = 0x25;
+            *(uint32_t *)pbPatchMem = (uint32_t)(RT_ALIGN_PT(pbPatchMem + 4, 8, uint8_t *) - (pbPatchMem + 4));
+            pbPatchMem = RT_ALIGN_PT(pbPatchMem + 4, 8, uint8_t *);
+            *(uint64_t *)pbPatchMem = uAddr;
+            pbPatchMem += sizeof(uint64_t);
+
+            /* Push the return address onto stack. Difficult on amd64 without clobbering registers... */
+            uintptr_t uAddrReturn = (uintptr_t)pbPatchMem;
+            *pbPatchMemPush++ = 0x68; /* push imm32 sign-extended as 64-bit*/
+            *(uint32_t *)pbPatchMemPush = RT_LO_U32(uAddrReturn);
+            pbPatchMemPush += sizeof(uint32_t);
+            *pbPatchMemPush++ = 0xc7;
+            *pbPatchMemPush++ = 0x44;
+            *pbPatchMemPush++ = 0x24;
+            *pbPatchMemPush++ = 0x04; /* movl [RSP+4], imm32 */
+            *(uint32_t *)pbPatchMemPush = RT_HI_U32(uAddrReturn);
+        }
         else
         {
             memcpy(pbPatchMem, pbTarget + offInsn, cbInstr);
diff --git a/src/VBox/HostDrivers/Support/testcase/tstInt.cpp b/src/VBox/HostDrivers/Support/testcase/tstInt.cpp
index 562ad08..3ec5020 100644
--- a/src/VBox/HostDrivers/Support/testcase/tstInt.cpp
+++ b/src/VBox/HostDrivers/Support/testcase/tstInt.cpp
@@ -31,6 +31,7 @@
 #include <VBox/sup.h>
 #include <VBox/vmm/vm.h>
 #include <VBox/vmm/vmm.h>
+#include <VBox/vmm/gvmm.h>
 #include <VBox/err.h>
 #include <VBox/param.h>
 #include <iprt/asm-amd64-x86.h>
@@ -79,29 +80,30 @@ int main(int argc, char **argv)
         if (RT_SUCCESS(rc))
         {
             /*
-             * Create a fake 'VM'.
+             * Create a tiny dummy VM so we can do NOP calls into it using the fast I/O control path.
              */
-            PVMR0 pVMR0 = NIL_RTR0PTR;
-            PVM pVM = NULL;
-            const unsigned cPages = RT_ALIGN_Z(sizeof(*pVM), PAGE_SIZE) >> PAGE_SHIFT;
-            PSUPPAGE paPages = (PSUPPAGE)RTMemAllocZ(cPages * sizeof(SUPPAGE));
-            if (paPages)
-                rc = SUPR3LowAlloc(cPages, (void **)&pVM, &pVMR0, &paPages[0]);
-            else
-                rc = VERR_NO_MEMORY;
+            GVMMCREATEVMREQ CreateVMReq;
+            CreateVMReq.Hdr.u32Magic    = SUPVMMR0REQHDR_MAGIC;
+            CreateVMReq.Hdr.cbReq       = sizeof(CreateVMReq);
+            CreateVMReq.pSession        = pSession;
+            CreateVMReq.pVMR0           = NIL_RTR0PTR;
+            CreateVMReq.pVMR3           = NULL;
+            CreateVMReq.cCpus           = 1;
+            rc = SUPR3CallVMMR0Ex(NIL_RTR0PTR, NIL_VMCPUID, VMMR0_DO_GVMM_CREATE_VM, 0, &CreateVMReq.Hdr);
             if (RT_SUCCESS(rc))
             {
-                pVM->pVMRC = 0;
-                pVM->pVMR3 = pVM;
-                pVM->pVMR0 = pVMR0;
-                pVM->paVMPagesR3 = paPages;
-                pVM->pSession = pSession;
+                PVM pVM = CreateVMReq.pVMR3;
+                AssertRelease(VALID_PTR(pVM));
+                AssertRelease(pVM->pVMR0 == CreateVMReq.pVMR0);
+                AssertRelease(pVM->pSession == pSession);
+                AssertRelease(pVM->cCpus == 1);
+                AssertRelease(pVM->offVMCPU == RT_UOFFSETOF(VM, aCpus));
                 pVM->enmVMState = VMSTATE_CREATED;
+                PVMR0 const pVMR0 = pVM->pVMR0;
 
-                rc = SUPR3SetVMForFastIOCtl(pVMR0);
+                rc = SUPR3SetVMForFastIOCtl(pVM->pVMR0);
                 if (!rc)
                 {
-
                     /*
                      * Call VMM code with invalid function.
                      */
@@ -181,10 +183,17 @@ int main(int argc, char **argv)
                     RTPrintf("tstInt: SUPR3SetVMForFastIOCtl failed: %Rrc\n", rc);
                     rcRet++;
                 }
+
+                rc = SUPR3CallVMMR0Ex(pVM->pVMR0, 0 /*idCpu*/, VMMR0_DO_GVMM_DESTROY_VM, 0, NULL);
+                if (RT_FAILURE(rc))
+                {
+                    RTPrintf("tstInt: VMMR0_DO_GVMM_DESTROY_VM failed: %Rrc\n", rc);
+                    rcRet++;
+                }
             }
             else
             {
-                RTPrintf("tstInt: SUPR3ContAlloc(%#zx,,) failed\n", sizeof(*pVM));
+                RTPrintf("tstInt: VMMR0_DO_GVMM_CREATE_VM failed\n");
                 rcRet++;
             }
 
diff --git a/src/VBox/HostDrivers/Support/win/SUPDrv-win.cpp b/src/VBox/HostDrivers/Support/win/SUPDrv-win.cpp
index aba213f..3677923 100644
--- a/src/VBox/HostDrivers/Support/win/SUPDrv-win.cpp
+++ b/src/VBox/HostDrivers/Support/win/SUPDrv-win.cpp
@@ -2463,7 +2463,6 @@ static NTSTATUS     VBoxDrvNtErr2NtStatus(int rc)
 }
 
 
-#if 0 /* See alternative in SUPDrvA-win.asm */
 /**
  * Alternative version of SUPR0Printf for Windows.
  *
@@ -2473,7 +2472,7 @@ static NTSTATUS     VBoxDrvNtErr2NtStatus(int rc)
 SUPR0DECL(int) SUPR0Printf(const char *pszFormat, ...)
 {
     va_list va;
-    char    szMsg[512];
+    char    szMsg[384];
 
     va_start(va, pszFormat);
     size_t cch = RTStrPrintfV(szMsg, sizeof(szMsg) - 1, pszFormat, va);
@@ -2483,7 +2482,6 @@ SUPR0DECL(int) SUPR0Printf(const char *pszFormat, ...)
     RTLogWriteDebugger(szMsg, cch);
     return 0;
 }
-#endif
 
 
 SUPR0DECL(uint32_t) SUPR0GetKernelFeatures(void)
diff --git a/src/VBox/HostDrivers/Support/win/SUPDrvA-win.asm b/src/VBox/HostDrivers/Support/win/SUPDrvA-win.asm
index 6d9bf27..ed272d6 100644
--- a/src/VBox/HostDrivers/Support/win/SUPDrvA-win.asm
+++ b/src/VBox/HostDrivers/Support/win/SUPDrvA-win.asm
@@ -30,20 +30,6 @@
 %include "iprt/asmdefs.mac"
 
 BEGINCODE
-%ifdef RT_ARCH_AMD64
- %define _DbgPrint DbgPrint
-%endif
-extern _DbgPrint
-
-%if 1 ; see alternative in SUPDrv-win.cpp
-;;
-; Kind of alias for DbgPrint
-export NAME(SUPR0Printf)
-BEGINPROC SUPR0Printf
-        jmp     _DbgPrint
-ENDPROC SUPR0Printf
-%endif
-
 
 %ifdef VBOX_WITH_HARDENING
 
diff --git a/src/VBox/HostDrivers/Support/win/SUPHardenedVerifyProcess-win.cpp b/src/VBox/HostDrivers/Support/win/SUPHardenedVerifyProcess-win.cpp
index 30ef876..dd8d3f2 100644
--- a/src/VBox/HostDrivers/Support/win/SUPHardenedVerifyProcess-win.cpp
+++ b/src/VBox/HostDrivers/Support/win/SUPHardenedVerifyProcess-win.cpp
@@ -1200,7 +1200,9 @@ static int supHardNtVpNewImage(PSUPHNTVPSTATE pThis, PSUPHNTVPIMAGE pImage, PMEM
         rc83Exp = RTNtPathExpand8dot3Path(pTmp, false /*fPathOnly*/);
         Assert(rc83Exp == VINF_SUCCESS);
         Assert(pTmp->Buffer[pTmp->Length / sizeof(RTUTF16)] == '\0');
-        if (rc83Exp != VINF_SUCCESS)
+        if (rc83Exp == VINF_SUCCESS)
+            SUP_DPRINTF(("supHardNtVpNewImage: 8dot3 -> long: '%ls' -> '%ls'\n", pLongName->Buffer, pTmp->Buffer));
+        else
             SUP_DPRINTF(("supHardNtVpNewImage: RTNtPathExpand8dot3Path returns %Rrc for '%ls' (-> '%ls')\n",
                          rc83Exp, pLongName->Buffer, pTmp->Buffer));
 
diff --git a/src/VBox/HostDrivers/Support/win/SUPR3HardenedMain-win.cpp b/src/VBox/HostDrivers/Support/win/SUPR3HardenedMain-win.cpp
index 9392092..fdfadec 100644
--- a/src/VBox/HostDrivers/Support/win/SUPR3HardenedMain-win.cpp
+++ b/src/VBox/HostDrivers/Support/win/SUPR3HardenedMain-win.cpp
@@ -1567,6 +1567,7 @@ static NTSTATUS NTAPI
 supR3HardenedMonitor_NtCreateSection(PHANDLE phSection, ACCESS_MASK fAccess, POBJECT_ATTRIBUTES pObjAttribs,
                                      PLARGE_INTEGER pcbSection, ULONG fProtect, ULONG fAttribs, HANDLE hFile)
 {
+    bool fNeedUncChecking = false;
     if (   hFile != NULL
         && hFile != INVALID_HANDLE_VALUE)
     {
@@ -1576,6 +1577,7 @@ supR3HardenedMonitor_NtCreateSection(PHANDLE phSection, ACCESS_MASK fAccess, POB
                                                    | PAGE_EXECUTE_READWRITE));
         if (fImage || fExecMap || fExecProt)
         {
+            fNeedUncChecking = true;
             DWORD dwSavedLastError = RtlGetLastWin32Error();
 
             bool fCallRealApi;
@@ -1598,7 +1600,211 @@ supR3HardenedMonitor_NtCreateSection(PHANDLE phSection, ACCESS_MASK fAccess, POB
     /*
      * Call checked out OK, call the original.
      */
-    return g_pfnNtCreateSectionReal(phSection, fAccess, pObjAttribs, pcbSection, fProtect, fAttribs, hFile);
+    NTSTATUS rcNtReal = g_pfnNtCreateSectionReal(phSection, fAccess, pObjAttribs, pcbSection, fProtect, fAttribs, hFile);
+
+    /*
+     * Check that the image that got mapped bear some resemblance to the one that was
+     * requested.  Apparently there are ways to trick the NT cache manager to map a
+     * file different from hFile into memory using local UNC accesses.
+     */
+    if (   NT_SUCCESS(rcNtReal)
+        && fNeedUncChecking)
+    {
+        DWORD dwSavedLastError = RtlGetLastWin32Error();
+
+        bool fOkay = false;
+
+        /* To get the name of the file backing the section, we unfortunately have to map it. */
+        SIZE_T   cbView   = 0;
+        PVOID    pvTmpMap = NULL;
+        NTSTATUS rcNt = NtMapViewOfSection(*phSection, NtCurrentProcess(), &pvTmpMap, 0, 0, NULL /*poffSection*/, &cbView,
+                                           ViewUnmap, MEM_TOP_DOWN, PAGE_EXECUTE);
+        if (NT_SUCCESS(rcNt))
+        {
+            /* Query the name. */
+            union
+            {
+                UNICODE_STRING  UniStr;
+                RTUTF16         awcBuf[512];
+            } uBuf;
+            RT_ZERO(uBuf);
+            SIZE_T   cbActual = 0;
+            NTSTATUS rcNtQuery = NtQueryVirtualMemory(NtCurrentProcess(), pvTmpMap, MemorySectionName,
+                                                      &uBuf, sizeof(uBuf) - sizeof(RTUTF16), &cbActual);
+
+            /* Unmap the view. */
+            rcNt = NtUnmapViewOfSection(NtCurrentProcess(), pvTmpMap);
+            if (!NT_SUCCESS(rcNt))
+                SUP_DPRINTF(("supR3HardenedMonitor_NtCreateSection: NtUnmapViewOfSection failed on %p (hSection=%p, hFile=%p) with %#x!\n",
+                             pvTmpMap, *phSection, hFile, rcNt));
+
+            /* Process the name query result. */
+            if (NT_SUCCESS(rcNtQuery))
+            {
+                static UNICODE_STRING const s_UncPrefix = RTNT_CONSTANT_UNISTR(L"\\Device\\Mup");
+                if (!supHardViUniStrPathStartsWithUniStr(&uBuf.UniStr, &s_UncPrefix, true /*fCheckSlash*/))
+                    fOkay = true;
+                else
+                    supR3HardenedError(VINF_SUCCESS, false,
+                                       "supR3HardenedMonitor_NtCreateSection: Image section with UNC path is not trusted: '%.*ls'\n",
+                                       uBuf.UniStr.Length / sizeof(RTUTF16), uBuf.UniStr.Buffer);
+            }
+            else
+                SUP_DPRINTF(("supR3HardenedMonitor_NtCreateSection: NtQueryVirtualMemory failed on %p (hFile=%p) with %#x -> STATUS_TRUST_FAILURE\n",
+                             *phSection, hFile, rcNt));
+        }
+        else
+            SUP_DPRINTF(("supR3HardenedMonitor_NtCreateSection: NtMapViewOfSection failed on %p (hFile=%p) with %#x -> STATUS_TRUST_FAILURE\n",
+                         *phSection, hFile, rcNt));
+        if (!fOkay)
+        {
+            NtClose(*phSection);
+            *phSection = INVALID_HANDLE_VALUE;
+            RtlRestoreLastWin32Error(dwSavedLastError);
+            return STATUS_TRUST_FAILURE;
+        }
+
+        RtlRestoreLastWin32Error(dwSavedLastError);
+    }
+    return rcNtReal;
+}
+
+
+/**
+ * Checks if the given name is a valid ApiSet name.
+ *
+ * This is only called on likely looking names.
+ *
+ * @returns true if ApiSet name, false if not.
+ * @param   pName               The name to check out.
+ */
+static bool supR3HardenedIsApiSetDll(PUNICODE_STRING pName)
+{
+    /*
+     * API added in Windows 8, or so they say.
+     */
+    if (ApiSetQueryApiSetPresence != NULL)
+    {
+        BOOLEAN fPresent = FALSE;
+        NTSTATUS rcNt = ApiSetQueryApiSetPresence(pName, &fPresent);
+        SUP_DPRINTF(("supR3HardenedIsApiSetDll: ApiSetQueryApiSetPresence(%.*ls) -> %#x, fPresent=%d\n",
+                     pName->Length / sizeof(WCHAR), pName->Buffer, rcNt, fPresent));
+        return fPresent != 0;
+    }
+
+    /*
+     * Fallback needed for Windows 7.  Fortunately, there aren't too many fake DLLs here.
+     */
+    if (   g_uNtVerCombined >= SUP_NT_VER_W70
+        && (   supHardViUtf16PathStartsWithEx(pName->Buffer, pName->Length / sizeof(WCHAR),
+                                              L"api-ms-win-", 11, false /*fCheckSlash*/)
+            || supHardViUtf16PathStartsWithEx(pName->Buffer, pName->Length / sizeof(WCHAR),
+                                              L"ext-ms-win-", 11, false /*fCheckSlash*/) ))
+    {
+#define MY_ENTRY(a) { a, sizeof(a) - 1 }
+        static const struct { const char *psz; size_t cch; } s_aKnownSets[] =
+        {
+            MY_ENTRY("api-ms-win-core-console-l1-1-0 "),
+            MY_ENTRY("api-ms-win-core-datetime-l1-1-0"),
+            MY_ENTRY("api-ms-win-core-debug-l1-1-0"),
+            MY_ENTRY("api-ms-win-core-delayload-l1-1-0"),
+            MY_ENTRY("api-ms-win-core-errorhandling-l1-1-0"),
+            MY_ENTRY("api-ms-win-core-fibers-l1-1-0"),
+            MY_ENTRY("api-ms-win-core-file-l1-1-0"),
+            MY_ENTRY("api-ms-win-core-handle-l1-1-0"),
+            MY_ENTRY("api-ms-win-core-heap-l1-1-0"),
+            MY_ENTRY("api-ms-win-core-interlocked-l1-1-0"),
+            MY_ENTRY("api-ms-win-core-io-l1-1-0"),
+            MY_ENTRY("api-ms-win-core-libraryloader-l1-1-0"),
+            MY_ENTRY("api-ms-win-core-localization-l1-1-0"),
+            MY_ENTRY("api-ms-win-core-localregistry-l1-1-0"),
+            MY_ENTRY("api-ms-win-core-memory-l1-1-0"),
+            MY_ENTRY("api-ms-win-core-misc-l1-1-0"),
+            MY_ENTRY("api-ms-win-core-namedpipe-l1-1-0"),
+            MY_ENTRY("api-ms-win-core-processenvironment-l1-1-0"),
+            MY_ENTRY("api-ms-win-core-processthreads-l1-1-0"),
+            MY_ENTRY("api-ms-win-core-profile-l1-1-0"),
+            MY_ENTRY("api-ms-win-core-rtlsupport-l1-1-0"),
+            MY_ENTRY("api-ms-win-core-string-l1-1-0"),
+            MY_ENTRY("api-ms-win-core-synch-l1-1-0"),
+            MY_ENTRY("api-ms-win-core-sysinfo-l1-1-0"),
+            MY_ENTRY("api-ms-win-core-threadpool-l1-1-0"),
+            MY_ENTRY("api-ms-win-core-ums-l1-1-0"),
+            MY_ENTRY("api-ms-win-core-util-l1-1-0"),
+            MY_ENTRY("api-ms-win-core-xstate-l1-1-0"),
+            MY_ENTRY("api-ms-win-security-base-l1-1-0"),
+            MY_ENTRY("api-ms-win-security-lsalookup-l1-1-0"),
+            MY_ENTRY("api-ms-win-security-sddl-l1-1-0"),
+            MY_ENTRY("api-ms-win-service-core-l1-1-0"),
+            MY_ENTRY("api-ms-win-service-management-l1-1-0"),
+            MY_ENTRY("api-ms-win-service-management-l2-1-0"),
+            MY_ENTRY("api-ms-win-service-winsvc-l1-1-0"),
+        };
+#undef MY_ENTRY
+
+        /* drop the dll suffix if present. */
+        PCRTUTF16 pawcName = pName->Buffer;
+        size_t    cwcName  = pName->Length / sizeof(WCHAR);
+        if (   cwcName > 5
+            && (pawcName[cwcName - 1] == 'l' || pawcName[cwcName - 1] == 'L')
+            && (pawcName[cwcName - 2] == 'l' || pawcName[cwcName - 2] == 'L')
+            && (pawcName[cwcName - 3] == 'd' || pawcName[cwcName - 3] == 'D')
+            &&  pawcName[cwcName - 4] == '.')
+            cwcName -= 4;
+
+        /* Search the table. */
+        for (size_t i = 0; i < RT_ELEMENTS(s_aKnownSets); i++)
+            if (   cwcName == s_aKnownSets[i].cch
+                && RTUtf16NICmpAscii(pawcName, s_aKnownSets[i].psz, cwcName) == 0)
+            {
+                SUP_DPRINTF(("supR3HardenedIsApiSetDll: '%.*ls' -> true\n", pName->Length / sizeof(WCHAR)));
+                return true;
+            }
+
+        SUP_DPRINTF(("supR3HardenedIsApiSetDll: Warning! '%.*ls' looks like an API set, but it's not in the list!\n",
+                     pName->Length / sizeof(WCHAR), pName->Buffer));
+    }
+
+    SUP_DPRINTF(("supR3HardenedIsApiSetDll: '%.*ls' -> false\n", pName->Length / sizeof(WCHAR)));
+    return false;
+}
+
+
+/**
+ * Checks whether the given unicode string contains a path separator and at
+ * least one dash.
+ *
+ * This is used to check for likely ApiSet name.  So far, all the pseudo DLL
+ * names include multiple dashes, so we use that as a criteria for recognizing
+ * them.  By happy coincident, most regular DLLs doesn't include dashes.
+ *
+ * @returns true if it contains path separator, false if only a name.
+ * @param   pPath               The path to check.
+ */
+static bool supR3HardenedHasDashButNoPath(PUNICODE_STRING pPath)
+{
+    size_t    cDashes = 0;
+    size_t    cwcLeft = pPath->Length / sizeof(WCHAR);
+    PCRTUTF16 pwc     = pPath->Buffer;
+    while (cwcLeft-- > 0)
+    {
+        RTUTF16 wc = *pwc++;
+        switch (wc)
+        {
+            default:
+                break;
+
+            case '-':
+                cDashes++;
+                break;
+
+            case '\\':
+            case '/':
+            case ':':
+                return false;
+        }
+    }
+    return cDashes > 0;
 }
 
 
@@ -1707,6 +1913,9 @@ supR3HardenedMonitor_LdrLoadDll(PWSTR pwszSearchPath, PULONG pfFlags, PUNICODE_S
         RtlRestoreLastWin32Error(dwSavedLastError);
         return STATUS_INVALID_PARAMETER;
     }
+    PCWCHAR const  pawcOrgName = pName->Buffer;
+    uint32_t const cwcOrgName  = pName->Length / sizeof(WCHAR);
+
     /*SUP_DPRINTF(("supR3HardenedMonitor_LdrLoadDll: pName=%.*ls *pfFlags=%#x pwszSearchPath=%p:%ls\n",
                  (unsigned)pName->Length / sizeof(WCHAR), pName->Buffer, pfFlags ? *pfFlags : UINT32_MAX, pwszSearchPath,
                  !((uintptr_t)pwszSearchPath & 1) && (uintptr_t)pwszSearchPath >= 0x2000U ? pwszSearchPath : L"<flags>"));*/
@@ -1714,7 +1923,7 @@ supR3HardenedMonitor_LdrLoadDll(PWSTR pwszSearchPath, PULONG pfFlags, PUNICODE_S
     /*
      * Reject long paths that's close to the 260 limit without looking.
      */
-    if (pName->Length > 256 * sizeof(WCHAR))
+    if (cwcOrgName > 256)
     {
         supR3HardenedError(VINF_SUCCESS, false, "supR3HardenedMonitor_LdrLoadDll: too long name: %#x bytes\n", pName->Length);
         SUP_DPRINTF(("supR3HardenedMonitor_LdrLoadDll: returns rcNt=%#x\n", STATUS_NAME_TOO_LONG));
@@ -1723,6 +1932,21 @@ supR3HardenedMonitor_LdrLoadDll(PWSTR pwszSearchPath, PULONG pfFlags, PUNICODE_S
     }
 
     /*
+     * Reject all UNC-like paths as we cannot trust non-local files at all.
+     * Note! We may have to relax this to deal with long path specifications and NT pass thrus.
+     */
+    if (   cwcOrgName >= 3
+        && RTPATH_IS_SLASH(pawcOrgName[0])
+        && RTPATH_IS_SLASH(pawcOrgName[1])
+        && !RTPATH_IS_SLASH(pawcOrgName[2]))
+    {
+        supR3HardenedError(VINF_SUCCESS, false, "supR3HardenedMonitor_LdrLoadDll: rejecting UNC name '%.*ls'\n", cwcOrgName, pawcOrgName);
+        SUP_DPRINTF(("supR3HardenedMonitor_LdrLoadDll: returns rcNt=%#x\n", STATUS_REDIRECTOR_NOT_STARTED));
+        RtlRestoreLastWin32Error(dwSavedLastError);
+        return STATUS_REDIRECTOR_NOT_STARTED;
+    }
+
+    /*
      * Reject PGHook.dll as it creates a thread from its DllMain that breaks
      * our preconditions respawning the 2nd process, resulting in
      * VERR_SUP_VP_THREAD_NOT_ALONE.   The DLL is being loaded by a user APC
@@ -1745,7 +1969,7 @@ supR3HardenedMonitor_LdrLoadDll(PWSTR pwszSearchPath, PULONG pfFlags, PUNICODE_S
     }
 
     /*
-     * Absolute path?
+     * Resolve the path, copying the result into wszPath
      */
     NTSTATUS        rcNtResolve     = STATUS_SUCCESS;
     bool            fSkipValidation = false;
@@ -1757,12 +1981,35 @@ supR3HardenedMonitor_LdrLoadDll(PWSTR pwszSearchPath, PULONG pfFlags, PUNICODE_S
     PUNICODE_STRING pUniStrResult  = NULL;
     UNICODE_STRING  ResolvedName;
 
-    if (   (   pName->Length >= 4 * sizeof(WCHAR)
-            && RT_C_IS_ALPHA(pName->Buffer[0])
-            && pName->Buffer[1] == ':'
-            && RTPATH_IS_SLASH(pName->Buffer[2]) )
-        || (   pName->Length >= 1 * sizeof(WCHAR)
-            && RTPATH_IS_SLASH(pName->Buffer[1]) )
+    /*
+     * Process the name a little, checking if it needs a DLL suffix and is pathless.
+     */
+    uint32_t        offLastSlash = UINT32_MAX;
+    uint32_t        offLastDot   = UINT32_MAX;
+    for (uint32_t i = 0; i < cwcOrgName; i++)
+        switch (pawcOrgName[i])
+        {
+            case '\\':
+            case '/':
+                offLastSlash = i;
+                offLastDot = UINT32_MAX;
+                break;
+            case '.':
+                offLastDot = i;
+                break;
+        }
+    bool const fNeedDllSuffix = offLastDot == UINT32_MAX;
+    //bool const fTrailingDot   = offLastDot == cwcOrgName - 1;
+
+    /*
+     * Absolute path?
+     */
+    if (   (   cwcOrgName >= 4
+            && RT_C_IS_ALPHA(pawcOrgName[0])
+            && pawcOrgName[1] == ':'
+            && RTPATH_IS_SLASH(pawcOrgName[2]) )
+        || (   cwcOrgName >= 1
+            && RTPATH_IS_SLASH(pawcOrgName[0]) )
        )
     {
         rcNtResolve = RtlDosApplyFileIsolationRedirection_Ustr(1 /*fFlags*/,
@@ -1797,19 +2044,30 @@ supR3HardenedMonitor_LdrLoadDll(PWSTR pwszSearchPath, PULONG pfFlags, PUNICODE_S
         }
         else
         {
-            memcpy(wszPath, pName->Buffer, pName->Length);
-            wszPath[pName->Length / sizeof(WCHAR)] = '\0';
+            /* Copy the path. */
+            memcpy(wszPath, pawcOrgName, cwcOrgName * sizeof(WCHAR));
+            if (!fNeedDllSuffix)
+                wszPath[cwcOrgName] = '\0';
+            else
+            {
+                if (cwcOrgName + 4 >= RT_ELEMENTS(wszPath))
+                {
+                    supR3HardenedError(VINF_SUCCESS, false,
+                                       "supR3HardenedMonitor_LdrLoadDll: Name too long (abs): %.*ls\n", cwcOrgName, pawcOrgName);
+                    SUP_DPRINTF(("supR3HardenedMonitor_LdrLoadDll: returns rcNt=%#x\n", STATUS_NAME_TOO_LONG));
+                    RtlRestoreLastWin32Error(dwSavedLastError);
+                    return STATUS_NAME_TOO_LONG;
+                }
+                memcpy(&wszPath[cwcOrgName], L".dll", 5 * sizeof(WCHAR));
+            }
         }
     }
     /*
      * Not an absolute path.  Check if it's one of those special API set DLLs
      * or something we're known to use but should be taken from WinSxS.
      */
-    else if (   supHardViUtf16PathStartsWithEx(pName->Buffer, pName->Length / sizeof(WCHAR),
-                                               L"api-ms-win-", 11, false /*fCheckSlash*/)
-             || supHardViUtf16PathStartsWithEx(pName->Buffer, pName->Length / sizeof(WCHAR),
-                                               L"ext-ms-win-", 11, false /*fCheckSlash*/)
-            )
+    else if (   supR3HardenedHasDashButNoPath(pName)
+             && supR3HardenedIsApiSetDll(pName))
     {
         memcpy(wszPath, pName->Buffer, pName->Length);
         wszPath[pName->Length / sizeof(WCHAR)] = '\0';
@@ -1823,28 +2081,6 @@ supR3HardenedMonitor_LdrLoadDll(PWSTR pwszSearchPath, PULONG pfFlags, PUNICODE_S
      */
     else
     {
-        PCWCHAR  pawcName     = pName->Buffer;
-        uint32_t cwcName      = pName->Length / sizeof(WCHAR);
-        uint32_t offLastSlash = UINT32_MAX;
-        uint32_t offLastDot   = UINT32_MAX;
-        for (uint32_t i = 0; i < cwcName; i++)
-            switch (pawcName[i])
-            {
-                case '\\':
-                case '/':
-                    offLastSlash = i;
-                    offLastDot = UINT32_MAX;
-                    break;
-                case '.':
-                    offLastDot = i;
-                    break;
-            }
-
-        bool const fNeedDllSuffix = offLastDot == UINT32_MAX && offLastSlash == UINT32_MAX;
-
-        if (offLastDot != UINT32_MAX && offLastDot == cwcName - 1)
-            cwcName--;
-
         /*
          * Reject relative paths for now as they might be breakout attempts.
          */
@@ -1852,7 +2088,7 @@ supR3HardenedMonitor_LdrLoadDll(PWSTR pwszSearchPath, PULONG pfFlags, PUNICODE_S
         {
             supR3HardenedError(VINF_SUCCESS, false,
                                "supR3HardenedMonitor_LdrLoadDll: relative name not permitted: %.*ls\n",
-                               cwcName, pawcName);
+                               cwcOrgName, pawcOrgName);
             SUP_DPRINTF(("supR3HardenedMonitor_LdrLoadDll: returns rcNt=%#x\n", STATUS_OBJECT_NAME_INVALID));
             RtlRestoreLastWin32Error(dwSavedLastError);
             return STATUS_OBJECT_NAME_INVALID;
@@ -1894,18 +2130,18 @@ supR3HardenedMonitor_LdrLoadDll(PWSTR pwszSearchPath, PULONG pfFlags, PUNICODE_S
              */
             AssertCompile(sizeof(g_System32WinPath.awcBuffer) <= sizeof(wszPath));
             cwc = g_System32WinPath.UniStr.Length / sizeof(RTUTF16); Assert(cwc > 2);
-            if (cwc + 1 + cwcName + fNeedDllSuffix * 4 >= RT_ELEMENTS(wszPath))
+            if (cwc + 1 + cwcOrgName + fNeedDllSuffix * 4 >= RT_ELEMENTS(wszPath))
             {
                 supR3HardenedError(VINF_SUCCESS, false,
-                                   "supR3HardenedMonitor_LdrLoadDll: Name too long (system32): %.*ls\n", cwcName, pawcName);
+                                   "supR3HardenedMonitor_LdrLoadDll: Name too long (system32): %.*ls\n", cwcOrgName, pawcOrgName);
                 SUP_DPRINTF(("supR3HardenedMonitor_LdrLoadDll: returns rcNt=%#x\n", STATUS_NAME_TOO_LONG));
                 RtlRestoreLastWin32Error(dwSavedLastError);
                 return STATUS_NAME_TOO_LONG;
             }
             memcpy(wszPath, g_System32WinPath.UniStr.Buffer, cwc * sizeof(RTUTF16));
             wszPath[cwc++] = '\\';
-            memcpy(&wszPath[cwc], pawcName, cwcName * sizeof(WCHAR));
-            cwc += cwcName;
+            memcpy(&wszPath[cwc], pawcOrgName, cwcOrgName * sizeof(WCHAR));
+            cwc += cwcOrgName;
             if (!fNeedDllSuffix)
                 wszPath[cwc] = '\0';
             else
@@ -2017,6 +2253,7 @@ supR3HardenedMonitor_LdrLoadDll(PWSTR pwszSearchPath, PULONG pfFlags, PUNICODE_S
                 rcNtGetDll = LdrGetDllHandle(NULL /*DllPath*/, NULL /*pfFlags*/, pOrgName, phMod);
                 if (NT_SUCCESS(rcNtGetDll))
                 {
+                    RTNtPathFree(&NtPathUniStr, &hRootDir);
                     RtlRestoreLastWin32Error(dwSavedLastError);
                     return rcNtGetDll;
                 }
@@ -2025,6 +2262,11 @@ supR3HardenedMonitor_LdrLoadDll(PWSTR pwszSearchPath, PULONG pfFlags, PUNICODE_S
             SUP_DPRINTF(("supR3HardenedMonitor_LdrLoadDll: error opening '%ls': %u (NtPath=%.*ls; Input=%.*ls; rcNtGetDll=%#x\n",
                          wszPath, dwErr, NtPathUniStr.Length / sizeof(RTUTF16), NtPathUniStr.Buffer,
                          pOrgName->Length / sizeof(WCHAR), pOrgName->Buffer, rcNtGetDll));
+
+            RTNtPathFree(&NtPathUniStr, &hRootDir);
+            RtlRestoreLastWin32Error(dwSavedLastError);
+            SUP_DPRINTF(("supR3HardenedMonitor_LdrLoadDll: returns rcNt=%#x '%ls'\n", rcNt, wszPath));
+            return rcNt;
         }
         RTNtPathFree(&NtPathUniStr, &hRootDir);
     }
@@ -5806,7 +6048,7 @@ static uint32_t supR3HardenedWinFindAdversaries(void)
                     uBuf.szFileVersion[RT_ELEMENTS(uBuf.wszFileVersion)] = '\0';
 #define VER_IN_RANGE(a_pszFirst, a_pszLast) \
     (RTStrVersionCompare(uBuf.szFileVersion, a_pszFirst) >= 0 && RTStrVersionCompare(uBuf.szFileVersion, a_pszLast) <= 0)
-                    if (   VER_IN_RANGE("7.4.0.0000", "999999999.9.9.9999")
+                    if (   VER_IN_RANGE("7.3.2.0000", "999999999.9.9.9999")
                         || VER_IN_RANGE("7.3.1.1000", "7.3.1.3000")
                         || VER_IN_RANGE("7.3.0.3000", "7.3.0.999999999")
                         || VER_IN_RANGE("7.2.1.3000", "7.2.999999999.999999999") )
diff --git a/src/VBox/HostDrivers/Support/win/import-template-ntdll.h b/src/VBox/HostDrivers/Support/win/import-template-ntdll.h
index c9b7f7b..1d76649 100644
--- a/src/VBox/HostDrivers/Support/win/import-template-ntdll.h
+++ b/src/VBox/HostDrivers/Support/win/import-template-ntdll.h
@@ -62,6 +62,7 @@ SUPHARNT_IMPORT_SYSCALL(NtQueryVolumeInformationFile, 20)
 SUPHARNT_IMPORT_STDCALL_EARLY(LdrInitializeThunk, 12)
 SUPHARNT_IMPORT_STDCALL_EARLY_OPTIONAL(LdrRegisterDllNotification, 16)
 SUPHARNT_IMPORT_STDCALL_EARLY(LdrGetDllHandle, 16)
+SUPHARNT_IMPORT_STDCALL_EARLY_OPTIONAL(ApiSetQueryApiSetPresence, 8)
 
 SUPHARNT_IMPORT_STDCALL(RtlAddAccessAllowedAce, 16)
 SUPHARNT_IMPORT_STDCALL(RtlAddAccessDeniedAce, 16)
diff --git a/src/VBox/HostDrivers/VBoxNetAdp/linux/Makefile b/src/VBox/HostDrivers/VBoxNetAdp/linux/Makefile
index 55db43f..60b1829 100644
--- a/src/VBox/HostDrivers/VBoxNetAdp/linux/Makefile
+++ b/src/VBox/HostDrivers/VBoxNetAdp/linux/Makefile
@@ -68,6 +68,7 @@ OBJS += math/gcc/divdi3.o \
 	math/gcc/moddi3.o \
 	math/gcc/qdivrem.o \
 	math/gcc/udivdi3.o \
+	math/gcc/udivmoddi4.o \
         math/gcc/divdi3.o \
 	math/gcc/umoddi3.o
 endif
diff --git a/src/VBox/HostDrivers/VBoxNetAdp/linux/files_vboxnetadp b/src/VBox/HostDrivers/VBoxNetAdp/linux/files_vboxnetadp
index 78adefb..a825d16 100755
--- a/src/VBox/HostDrivers/VBoxNetAdp/linux/files_vboxnetadp
+++ b/src/VBox/HostDrivers/VBoxNetAdp/linux/files_vboxnetadp
@@ -1,5 +1,5 @@
 #!/bin/sh
-# $Revision: 106719 $
+# $Revision: 115996 $
 ## @files
 # Shared file between Makefile.kmk and export_modules
 #
@@ -49,6 +49,7 @@ VBOX_VBOXNETADP_SOURCES=" \
     ${PATH_ROOT}/include/iprt/time.h=>include/iprt/time.h \
     ${PATH_ROOT}/include/iprt/timer.h=>include/iprt/timer.h \
     ${PATH_ROOT}/include/iprt/types.h=>include/iprt/types.h \
+    ${PATH_ROOT}/include/iprt/uint64.h=>include/iprt/uint64.h \
     ${PATH_ROOT}/include/iprt/uni.h=>include/iprt/uni.h \
     ${PATH_ROOT}/include/iprt/utf16.h=>include/iprt/utf16.h \
     ${PATH_ROOT}/include/iprt/uuid.h=>include/iprt/uuid.h \
@@ -70,6 +71,7 @@ VBOX_VBOXNETADP_SOURCES=" \
     ${PATH_ROOT}/src/VBox/Runtime/common/math/gcc/qdivrem.c=>math/gcc/qdivrem.c \
     ${PATH_ROOT}/src/VBox/Runtime/common/math/gcc/quad.h=>math/gcc/quad.h \
     ${PATH_ROOT}/src/VBox/Runtime/common/math/gcc/udivdi3.c=>math/gcc/udivdi3.c \
+    ${PATH_ROOT}/src/VBox/Runtime/common/math/gcc/udivmoddi4.c=>math/gcc/udivmoddi4.c \
     ${PATH_ROOT}/src/VBox/Runtime/common/math/gcc/umoddi3.c=>math/gcc/umoddi3.c \
     ${PATH_ROOT}/src/VBox/Runtime/common/string/strformat.cpp=>common/string/strformat.c \
     ${PATH_ROOT}/src/VBox/Runtime/common/string/strformatrt.cpp=>common/string/strformatrt.c \
diff --git a/src/VBox/HostDrivers/VBoxNetFlt/linux/Makefile b/src/VBox/HostDrivers/VBoxNetFlt/linux/Makefile
index b79cf4c..7bfdc13 100644
--- a/src/VBox/HostDrivers/VBoxNetFlt/linux/Makefile
+++ b/src/VBox/HostDrivers/VBoxNetFlt/linux/Makefile
@@ -72,6 +72,7 @@ OBJS += math/gcc/divdi3.o \
 	math/gcc/moddi3.o \
 	math/gcc/qdivrem.o \
 	math/gcc/udivdi3.o \
+	math/gcc/udivmoddi4.o \
         math/gcc/divdi3.o \
 	math/gcc/umoddi3.o
 endif
diff --git a/src/VBox/HostDrivers/VBoxNetFlt/linux/files_vboxnetflt b/src/VBox/HostDrivers/VBoxNetFlt/linux/files_vboxnetflt
index 1bfb739..e9f2adb 100755
--- a/src/VBox/HostDrivers/VBoxNetFlt/linux/files_vboxnetflt
+++ b/src/VBox/HostDrivers/VBoxNetFlt/linux/files_vboxnetflt
@@ -49,6 +49,7 @@ VBOX_VBOXNETFLT_SOURCES=" \
     ${PATH_ROOT}/include/iprt/time.h=>include/iprt/time.h \
     ${PATH_ROOT}/include/iprt/timer.h=>include/iprt/timer.h \
     ${PATH_ROOT}/include/iprt/types.h=>include/iprt/types.h \
+    ${PATH_ROOT}/include/iprt/uint64.h=>include/iprt/uint64.h \
     ${PATH_ROOT}/include/iprt/uni.h=>include/iprt/uni.h \
     ${PATH_ROOT}/include/iprt/utf16.h=>include/iprt/utf16.h \
     ${PATH_ROOT}/include/iprt/uuid.h=>include/iprt/uuid.h \
@@ -77,6 +78,7 @@ VBOX_VBOXNETFLT_SOURCES=" \
     ${PATH_ROOT}/src/VBox/Runtime/common/math/gcc/qdivrem.c=>math/gcc/qdivrem.c \
     ${PATH_ROOT}/src/VBox/Runtime/common/math/gcc/quad.h=>math/gcc/quad.h \
     ${PATH_ROOT}/src/VBox/Runtime/common/math/gcc/udivdi3.c=>math/gcc/udivdi3.c \
+    ${PATH_ROOT}/src/VBox/Runtime/common/math/gcc/udivmoddi4.c=>math/gcc/udivmoddi4.c \
     ${PATH_ROOT}/src/VBox/Runtime/common/math/gcc/umoddi3.c=>math/gcc/umoddi3.c \
     ${PATH_ROOT}/src/VBox/Runtime/r0drv/linux/the-linux-kernel.h=>r0drv/linux/the-linux-kernel.h \
     ${PATH_OUT}/version-generated.h=>version-generated.h \
diff --git a/src/VBox/HostDrivers/VBoxNetFlt/win/cfg/VBoxNetCfg.cpp b/src/VBox/HostDrivers/VBoxNetFlt/win/cfg/VBoxNetCfg.cpp
index db962a7..1942ff8 100644
--- a/src/VBox/HostDrivers/VBoxNetFlt/win/cfg/VBoxNetCfg.cpp
+++ b/src/VBox/HostDrivers/VBoxNetFlt/win/cfg/VBoxNetCfg.cpp
@@ -1897,7 +1897,7 @@ static HRESULT netIfEnableStaticIpConfigV6(const GUID *pGuid, IN_BSTR aIPV6Addre
 static HRESULT netIfEnableStaticIpConfigV6(const GUID *pGuid, IN_BSTR aIPV6Address, ULONG aIPV6MaskPrefixLength)
 {
     RTNETADDRIPV6 Mask;
-    int rc = prefixLength2IPv6Address(aIPV6MaskPrefixLength, &Mask);
+    int rc = RTNetPrefixToMaskIPv6(aIPV6MaskPrefixLength, &Mask);
     if (RT_SUCCESS(rc))
     {
         Bstr maskStr = composeIPv6Address(&Mask);
diff --git a/src/VBox/HostDrivers/VBoxPci/linux/Makefile b/src/VBox/HostDrivers/VBoxPci/linux/Makefile
index 1861012..c6eae4e 100644
--- a/src/VBox/HostDrivers/VBoxPci/linux/Makefile
+++ b/src/VBox/HostDrivers/VBoxPci/linux/Makefile
@@ -72,6 +72,7 @@ OBJS += math/gcc/divdi3.o       \
 	math/gcc/moddi3.o 	\
 	math/gcc/qdivrem.o 	\
 	math/gcc/udivdi3.o 	\
+	math/gcc/udivmoddi4.o 	\
         math/gcc/divdi3.o 	\
 	math/gcc/umoddi3.o
 endif
diff --git a/src/VBox/HostDrivers/VBoxPci/linux/files_vboxpci b/src/VBox/HostDrivers/VBoxPci/linux/files_vboxpci
index 9c5a986..bcc4286 100755
--- a/src/VBox/HostDrivers/VBoxPci/linux/files_vboxpci
+++ b/src/VBox/HostDrivers/VBoxPci/linux/files_vboxpci
@@ -48,6 +48,7 @@ VBOX_VBOXPCI_SOURCES=" \
     ${PATH_ROOT}/include/iprt/time.h=>include/iprt/time.h \
     ${PATH_ROOT}/include/iprt/timer.h=>include/iprt/timer.h \
     ${PATH_ROOT}/include/iprt/types.h=>include/iprt/types.h \
+    ${PATH_ROOT}/include/iprt/uint64.h=>include/iprt/uint64.h \
     ${PATH_ROOT}/include/iprt/uni.h=>include/iprt/uni.h \
     ${PATH_ROOT}/include/iprt/utf16.h=>include/iprt/utf16.h \
     ${PATH_ROOT}/include/iprt/uuid.h=>include/iprt/uuid.h \
@@ -75,6 +76,7 @@ VBOX_VBOXPCI_SOURCES=" \
     ${PATH_ROOT}/src/VBox/Runtime/common/math/gcc/qdivrem.c=>math/gcc/qdivrem.c \
     ${PATH_ROOT}/src/VBox/Runtime/common/math/gcc/quad.h=>math/gcc/quad.h \
     ${PATH_ROOT}/src/VBox/Runtime/common/math/gcc/udivdi3.c=>math/gcc/udivdi3.c \
+    ${PATH_ROOT}/src/VBox/Runtime/common/math/gcc/udivmoddi4.c=>math/gcc/udivmoddi4.c \
     ${PATH_ROOT}/src/VBox/Runtime/common/math/gcc/umoddi3.c=>math/gcc/umoddi3.c \
     ${PATH_ROOT}/src/VBox/Runtime/r0drv/linux/the-linux-kernel.h=>r0drv/linux/the-linux-kernel.h \
     ${PATH_OUT}/version-generated.h=>version-generated.h \
diff --git a/src/VBox/HostDrivers/VBoxUSB/USBFilter.cpp b/src/VBox/HostDrivers/VBoxUSB/USBFilter.cpp
index c129082..5ea6c6b 100644
--- a/src/VBox/HostDrivers/VBoxUSB/USBFilter.cpp
+++ b/src/VBox/HostDrivers/VBoxUSB/USBFilter.cpp
@@ -1680,6 +1680,7 @@ USBLIB_DECL(bool) USBFilterIsNumericField(USBFILTERIDX enmFieldIdx)
 
         default:
             AssertMsgFailed(("%d\n", enmFieldIdx));
+            /* fall thru */
         case USBFILTERIDX_MANUFACTURER_STR:
         case USBFILTERIDX_PRODUCT_STR:
         case USBFILTERIDX_SERIAL_NUMBER_STR:
@@ -1700,6 +1701,7 @@ USBLIB_DECL(bool) USBFilterIsStringField(USBFILTERIDX enmFieldIdx)
     {
         default:
             AssertMsgFailed(("%d\n", enmFieldIdx));
+            /* fall thru */
         case USBFILTERIDX_VENDOR_ID:
         case USBFILTERIDX_PRODUCT_ID:
         case USBFILTERIDX_DEVICE:
@@ -1730,6 +1732,7 @@ USBLIB_DECL(bool) USBFilterIsMethodUsingNumericValue(USBFILTERMATCH enmMatchingM
     {
         default:
             AssertMsgFailed(("%d\n", enmMatchingMethod));
+            /* fall thru */
         case USBFILTERMATCH_IGNORE:
         case USBFILTERMATCH_PRESENT:
         case USBFILTERMATCH_NUM_EXPRESSION:
@@ -1759,6 +1762,7 @@ USBLIB_DECL(bool) USBFilterIsMethodUsingStringValue(USBFILTERMATCH enmMatchingMe
     {
         default:
             AssertMsgFailed(("%d\n", enmMatchingMethod));
+            /* fall thru */
         case USBFILTERMATCH_IGNORE:
         case USBFILTERMATCH_PRESENT:
         case USBFILTERMATCH_NUM_EXACT:
diff --git a/src/VBox/HostDrivers/adpctl/VBoxNetAdpCtl.cpp b/src/VBox/HostDrivers/adpctl/VBoxNetAdpCtl.cpp
index 9858f63..c4bd19f 100644
--- a/src/VBox/HostDrivers/adpctl/VBoxNetAdpCtl.cpp
+++ b/src/VBox/HostDrivers/adpctl/VBoxNetAdpCtl.cpp
@@ -20,7 +20,10 @@
 /*********************************************************************************************************************************
 *   Header Files                                                                                                                 *
 *********************************************************************************************************************************/
+#include <list>
+#include <errno.h>
 #include <stdio.h>
+#include <stdarg.h>
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
@@ -44,6 +47,8 @@ typedef __uint8_t u8;
 # include <sys/ioccom.h>
 #endif
 
+#define NOREF(x) (void)x
+
 /** @todo Error codes must be moved to some header file */
 #define ADPCTLERR_BAD_NAME         2
 #define ADPCTLERR_NO_CTL_DEV       3
@@ -65,18 +70,7 @@ typedef VBOXNETADPREQ *PVBOXNETADPREQ;
 
 #define VBOXADPCTL_IFCONFIG_PATH1 "/sbin/ifconfig"
 #define VBOXADPCTL_IFCONFIG_PATH2 "/bin/ifconfig"
-static char *g_pszIfConfig;
 
-#if defined(RT_OS_LINUX)
-# define VBOXADPCTL_DEL_CMD "del"
-# define VBOXADPCTL_ADD_CMD "add"
-#elif defined(RT_OS_SOLARIS)
-# define VBOXADPCTL_DEL_CMD "removeif"
-# define VBOXADPCTL_ADD_CMD "addif"
-#else
-# define VBOXADPCTL_DEL_CMD "delete"
-# define VBOXADPCTL_ADD_CMD "add"
-#endif
 
 static void showUsage(void)
 {
@@ -85,34 +79,311 @@ static void showUsage(void)
     fprintf(stderr, "     | VBoxNetAdpCtl <adapter> remove\n");
 }
 
-static void setPathIfConfig(void)
+
+/*
+ * A wrapper on standard list that provides '<<' operator for adding several list members in a single
+ * line dynamically. For example: "CmdList(arg1) << arg2 << arg3" produces a list with three members.
+ */
+class CmdList
 {
-    struct stat s;
-    if (   !stat(VBOXADPCTL_IFCONFIG_PATH1, &s)
-        && S_ISREG(s.st_mode))
-        g_pszIfConfig = (char*)VBOXADPCTL_IFCONFIG_PATH1;
-    else
-        g_pszIfConfig = (char*)VBOXADPCTL_IFCONFIG_PATH2;
+public:
+    /** Creates an empty list. */
+    CmdList() {};
+    /** Creates a list with a single member. */
+    CmdList(const char *pcszCommand) { m_list.push_back(pcszCommand); };
+    /** Provides access to the underlying standard list. */
+    const std::list<const char *>& getList(void) const { return m_list; };
+    /** Adds a member to the list. */
+    CmdList& operator<<(const char *pcszArgument);
+private:
+    std::list<const char *>m_list;
+};
+
+CmdList& CmdList::operator<<(const char *pcszArgument)
+{
+    m_list.push_back(pcszArgument);
+    return *this;
+}
+
+/** Simple helper to distinguish IPv4 and IPv6 addresses. */
+inline bool isAddrV6(const char *pcszAddress)
+{
+    return !!(strchr(pcszAddress, ':'));
+}
+
+
+/*********************************************************************************************************************************
+*   Generic address commands.                                                                                                    *
+*********************************************************************************************************************************/
+
+/**
+ * The base class for all address manipulation commands. While being an abstract class,
+ * it provides a generic implementation of 'set' and 'remove' methods, which rely on
+ * pure virtual methods like 'addV4' and 'removeV4' to perform actual command execution.
+ */
+class AddressCommand
+{
+public:
+    AddressCommand() : m_pszPath(0) {};
+    virtual ~AddressCommand() {};
+
+    /** returns true if underlying command (executable) is present in the system. */
+    bool isAvailable(void)
+        { struct stat s; return (!stat(m_pszPath, &s) && S_ISREG(s.st_mode)); };
+
+    /*
+     * Someday we may want to support several IP addresses per adapter, but for now we
+     * have 'set' method only, which replaces all addresses with the one specifed.
+     *
+     * virtual int add(const char *pcszAdapter, const char *pcszAddress, const char *pcszNetmask = 0) = 0;
+     */
+    /** replace existing address(es) */
+    virtual int set(const char *pcszAdapter, const char *pcszAddress, const char *pcszNetmask = 0);
+    /** remove address */
+    virtual int remove(const char *pcszAdapter, const char *pcszAddress);
+protected:
+    /** IPv4-specific handler used by generic implementation of 'set' method if 'setV4' is not supported. */
+    virtual int addV4(const char *pcszAdapter, const char *pcszAddress, const char *pcszNetmask = 0) = 0;
+    /** IPv6-specific handler used by generic implementation of 'set' method. */
+    virtual int addV6(const char *pcszAdapter, const char *pcszAddress, const char *pcszNetmask = 0) = 0;
+    /** IPv4-specific handler used by generic implementation of 'set' method. */
+    virtual int setV4(const char *pcszAdapter, const char *pcszAddress, const char *pcszNetmask = 0) = 0;
+    /** IPv4-specific handler used by generic implementation of 'remove' method. */
+    virtual int removeV4(const char *pcszAdapter, const char *pcszAddress) = 0;
+    /** IPv6-specific handler used by generic implementation of 'remove' method. */
+    virtual int removeV6(const char *pcszAdapter, const char *pcszAddress) = 0;
+    /** Composes the argument list of command that obtains all addresses assigned to the adapter. */
+    virtual CmdList getShowCommand(const char *pcszAdapter) const = 0;
+
+    /** Prepares an array of C strings needed for 'exec' call. */
+    char * const * allocArgv(const CmdList& commandList);
+    /** Hides process creation details. To be used in derived classes. */
+    int execute(CmdList& commandList);
+
+    /** A path to executable command. */
+    const char *m_pszPath;
+private:
+    /** Removes all previously asssigned addresses of a particular protocol family. */
+    int removeAddresses(const char *pcszAdapter, const char *pcszFamily);
+};
+
+/*
+ * A generic implementation of 'ifconfig' command for all platforms.
+ */
+class CmdIfconfig : public AddressCommand
+{
+public:
+    CmdIfconfig()
+        {
+            struct stat s;
+            if (   !stat(VBOXADPCTL_IFCONFIG_PATH1, &s)
+                && S_ISREG(s.st_mode))
+                m_pszPath = (char*)VBOXADPCTL_IFCONFIG_PATH1;
+            else
+                m_pszPath = (char*)VBOXADPCTL_IFCONFIG_PATH2;
+        };
+
+protected:
+    /** Returns platform-specific subcommand to add an address. */
+    virtual const char *addCmdArg(void) const = 0;
+    /** Returns platform-specific subcommand to remove an address. */
+    virtual const char *delCmdArg(void) const = 0;
+    virtual CmdList getShowCommand(const char *pcszAdapter) const
+        { return CmdList(pcszAdapter); };
+    virtual int addV4(const char *pcszAdapter, const char *pcszAddress, const char *pcszNetmask = 0)
+        { return ENOTSUP; NOREF(pcszAdapter); NOREF(pcszAddress); NOREF(pcszNetmask); };
+    virtual int addV6(const char *pcszAdapter, const char *pcszAddress, const char *pcszNetmask = 0)
+        {
+            return execute(CmdList(pcszAdapter) << "inet6" << addCmdArg() << pcszAddress);
+            NOREF(pcszNetmask);
+        };
+    virtual int setV4(const char *pcszAdapter, const char *pcszAddress, const char *pcszNetmask = 0)
+        {
+            if (!pcszNetmask)
+                return execute(CmdList(pcszAdapter) << pcszAddress);
+            return execute(CmdList(pcszAdapter) << pcszAddress << "netmask" << pcszNetmask);
+        };
+    virtual int removeV4(const char *pcszAdapter, const char *pcszAddress)
+        { return execute(CmdList(pcszAdapter) << delCmdArg() << pcszAddress); };
+    virtual int removeV6(const char *pcszAdapter, const char *pcszAddress)
+        { return execute(CmdList(pcszAdapter) << "inet6" << delCmdArg() << pcszAddress); };
+};
+
+
+/*********************************************************************************************************************************
+*   Platform-specific commands                                                                                                   *
+*********************************************************************************************************************************/
+
+class CmdIfconfigLinux : public CmdIfconfig
+{
+protected:
+    virtual int removeV4(const char *pcszAdapter, const char *pcszAddress)
+        { return execute(CmdList(pcszAdapter) << "0.0.0.0"); NOREF(pcszAddress); };
+    virtual const char *addCmdArg(void) const { return "add"; };
+    virtual const char *delCmdArg(void) const { return "del"; };
+};
+
+class CmdIfconfigDarwin : public CmdIfconfig
+{
+protected:
+    virtual const char *addCmdArg(void) const { return "add"; };
+    virtual const char *delCmdArg(void) const { return "delete"; };
+};
+
+class CmdIfconfigSolaris : public CmdIfconfig
+{
+public:
+    virtual int set(const char *pcszAdapter, const char *pcszAddress, const char *pcszNetmask = 0)
+        {
+            const char *pcszFamily = isAddrV6(pcszAddress) ? "inet6" : "inet";
+            if (execute(CmdList(pcszAdapter) << pcszFamily))
+                execute(CmdList(pcszAdapter) << pcszFamily << "plumb" << "up");
+            return CmdIfconfig::set(pcszAdapter, pcszAddress, pcszNetmask);
+        };
+protected:
+    /* We can umplumb IPv4 interfaces only! */
+    virtual int removeV4(const char *pcszAdapter, const char *pcszAddress)
+        {
+            int rc = CmdIfconfig::removeV4(pcszAdapter, pcszAddress);
+            execute(CmdList(pcszAdapter) << "inet" << "unplumb");
+            return rc;
+        };
+    virtual const char *addCmdArg(void) const { return "addif"; };
+    virtual const char *delCmdArg(void) const { return "removeif"; };
+};
+
+
+/*
+ * Linux-specific implementation of 'ip' command, as other platforms do not support it.
+ */
+class CmdIpLinux : public AddressCommand
+{
+public:
+    CmdIpLinux() { pszBuffer = 0; m_pszPath = "/sbin/ip"; };
+    virtual ~CmdIpLinux() { delete pszBuffer; };
+    /**
+     * IPv4 and IPv6 syntax is the same, so we override `remove` instead of implementing
+     * family-specific commands. It would be easier to use the same body in both
+     * 'removeV4' and 'removeV6', so we override 'remove' to illustrate how to do common
+     * implementation.
+     */
+    virtual int remove(const char *pcszAdapter, const char *pcszAddress)
+        { return execute(CmdList("addr") << "del" << pcszAddress << "dev" << pcszAdapter); };
+protected:
+    virtual int addV4(const char *pcszAdapter, const char *pcszAddress, const char *pcszNetmask = 0)
+        {
+            return execute(CmdList("addr") << "add" << combine(pcszAddress, pcszNetmask) <<
+                           "dev" << pcszAdapter);
+        };
+    virtual int addV6(const char *pcszAdapter, const char *pcszAddress, const char *pcszNetmask = 0)
+        {
+            return execute(CmdList("addr") << "add" << pcszAddress << "dev" << pcszAdapter);
+            NOREF(pcszNetmask);
+        };
+    /**
+     * Our command does not support 'replacing' addresses. Reporting this fact to generic implementation
+     * of 'set' causes it to remove all assigned addresses, then 'add' the new one.
+     */
+    virtual int setV4(const char *pcszAdapter, const char *pcszAddress, const char *pcszNetmask = 0)
+        { return ENOTSUP; NOREF(pcszAdapter); NOREF(pcszAddress); NOREF(pcszNetmask); };
+    /** We use family-agnostic command syntax. See 'remove' above. */
+    virtual int removeV4(const char *pcszAdapter, const char *pcszAddress)
+        { return ENOTSUP; NOREF(pcszAdapter); NOREF(pcszAddress); };
+    /** We use family-agnostic command syntax. See 'remove' above. */
+    virtual int removeV6(const char *pcszAdapter, const char *pcszAddress)
+        { return ENOTSUP; NOREF(pcszAdapter); NOREF(pcszAddress); };
+    virtual CmdList getShowCommand(const char *pcszAdapter) const
+        { return CmdList("addr") << "show" << "dev" << pcszAdapter; };
+private:
+    /** Converts address and network mask into a single string in CIDR notation (like 192.168.1.1/24) */
+    const char *combine(const char *pcszAddress, const char *pcszNetmask);
+
+    char *pszBuffer;
+};
+
+const char * CmdIpLinux::combine(const char *pcszAddress, const char *pcszNetmask)
+{
+    delete pszBuffer;
+    if (pcszNetmask)
+    {
+        unsigned cBits = 0;
+        unsigned m[4];
+        if (sscanf(pcszNetmask, "%u.%u.%u.%u", &m[0], &m[1], &m[2], &m[3]) == 4)
+        {
+            for (int i = 0; i < 4 && m[i]; ++i)
+            {
+                int mask = m[i];
+                while (mask & 0x80)
+                {
+                    cBits++;
+                    mask <<= 1;
+                }
+            }
+            const size_t cbBuf = strlen(pcszAddress) + 4;
+            pszBuffer = new char[cbBuf]; // '/xx\0'
+            snprintf(pszBuffer, cbBuf, "%s/%u", pcszAddress, cBits);
+            return pszBuffer;
+        }
+    }
+    return pcszAddress;
 }
 
-static int executeIfconfig(const char *pcszAdapterName, const char *pcszArg1,
-                           const char *pcszArg2 = NULL,
-                           const char *pcszArg3 = NULL,
-                           const char *pcszArg4 = NULL,
-                           const char *pcszArg5 = NULL)
+
+
+/*********************************************************************************************************************************
+*   Generic address command implementations                                                                                      *
+*********************************************************************************************************************************/
+
+int AddressCommand::set(const char *pcszAdapter, const char *pcszAddress, const char *pcszNetmask)
 {
-    const char * const argv[] =
+    if (isAddrV6(pcszAddress))
     {
-        g_pszIfConfig,
-        pcszAdapterName,
-        pcszArg1, /* [address family] */
-        pcszArg2, /* address */
-        pcszArg3, /* ['netmask'] */
-        pcszArg4, /* [network mask] */
-        pcszArg5, /* [network mask] */
-        NULL  /* terminator */
-    };
-    char * const envp[] = { (char*)"LC_ALL=C", NULL };
+        removeAddresses(pcszAdapter, "inet6");
+        return addV6(pcszAdapter, pcszAddress, pcszNetmask);
+    }
+    int rc = setV4(pcszAdapter, pcszAddress, pcszNetmask);
+    if (rc == ENOTSUP)
+    {
+        removeAddresses(pcszAdapter, "inet");
+        rc = addV4(pcszAdapter, pcszAddress, pcszNetmask);
+    }
+    return rc;
+}
+
+int AddressCommand::remove(const char *pcszAdapter, const char *pcszAddress)
+{
+    if (isAddrV6(pcszAddress))
+        return removeV6(pcszAdapter, pcszAddress);
+    return removeV4(pcszAdapter, pcszAddress);
+}
+
+/*
+ * Allocate an array of exec arguments. In addition to arguments provided
+ * we need to include the full path to the executable as well as "terminating"
+ * null pointer marking the end of the array.
+ */
+char * const * AddressCommand::allocArgv(const CmdList& list)
+{
+    int i = 0;
+    std::list<const char *>::const_iterator it;
+    const char **argv = (const char **)calloc(list.getList().size() + 2, sizeof(const char *));
+    if (argv)
+    {
+        argv[i++] = m_pszPath;
+        for (it = list.getList().begin(); it != list.getList().end(); ++it)
+            argv[i++] = *it;
+        argv[i++] = NULL;
+    }
+    return (char * const*)argv;
+}
+
+int AddressCommand::execute(CmdList& list)
+{
+    char * const pEnv[] = { (char*)"LC_ALL=C", NULL };
+    char * const* argv = allocArgv(list);
+    if (argv == NULL)
+        return EXIT_FAILURE;
+
     int rc = EXIT_SUCCESS;
     pid_t childPid = fork();
     switch (childPid)
@@ -122,7 +393,7 @@ static int executeIfconfig(const char *pcszAdapterName, const char *pcszArg1,
             rc = EXIT_FAILURE;
             break;
         case 0: /* Child process. */
-            if (execve(argv[0], (char * const*)argv, envp) == -1)
+            if (execve(argv[0], argv, pEnv) == -1)
                 rc = EXIT_FAILURE;
             break;
         default: /* Parent process. */
@@ -130,30 +401,31 @@ static int executeIfconfig(const char *pcszAdapterName, const char *pcszArg1,
             break;
     }
 
+    free((void*)argv);
     return rc;
 }
 
 #define MAX_ADDRESSES 128
 #define MAX_ADDRLEN   64
 
-static bool removeAddresses(char *pszAdapterName)
+int AddressCommand::removeAddresses(const char *pcszAdapter, const char *pcszFamily)
 {
     char szBuf[1024];
     char aszAddresses[MAX_ADDRESSES][MAX_ADDRLEN];
-    int rc;
+    int rc = EXIT_SUCCESS;
     int fds[2];
-    char * const argv[] = { g_pszIfConfig, pszAdapterName, NULL };
+    char * const * argv = allocArgv(getShowCommand(pcszAdapter));
     char * const envp[] = { (char*)"LC_ALL=C", NULL };
 
     memset(aszAddresses, 0, sizeof(aszAddresses));
 
     rc = pipe(fds);
     if (rc < 0)
-        return false;
+        return errno;
 
     pid_t pid = fork();
     if (pid < 0)
-        return false;
+        return errno;
 
     if (pid == 0)
     {
@@ -162,8 +434,9 @@ static bool removeAddresses(char *pszAdapterName)
         close(STDOUT_FILENO);
         rc = dup2(fds[1], STDOUT_FILENO);
         if (rc >= 0)
-            execve(argv[0], argv, envp);
-        return false;
+            if (execve(argv[0], argv, envp) == -1)
+                return errno;
+        return rc;
     }
 
     /* parent */
@@ -177,65 +450,145 @@ static bool removeAddresses(char *pszAdapterName)
     {
         int cbSkipWS = strspn(szBuf, " \t");
         char *pszWord = strtok(szBuf + cbSkipWS, " ");
-        /* We are concerned with IPv6 address lines only. */
-        if (!pszWord || strcmp(pszWord, "inet6"))
-            continue;
-#ifdef RT_OS_LINUX
-        pszWord = strtok(NULL, " ");
-        /* Skip "addr:". */
-        if (!pszWord || strcmp(pszWord, "addr:"))
+        /* We are concerned with particular family address lines only. */
+        if (!pszWord || strcmp(pszWord, pcszFamily))
             continue;
-#endif
+
         pszWord = strtok(NULL, " ");
-        /* Skip link-local addresses. */
+
+        /* Skip "addr:" word if present. */
+        if (pszWord && !strcmp(pszWord, "addr:"))
+            pszWord = strtok(NULL, " ");
+
+        /* Skip link-local address lines. */
         if (!pszWord || !strncmp(pszWord, "fe80", 4))
             continue;
         strncpy(aszAddresses[cAddrs++], pszWord, MAX_ADDRLEN-1);
     }
     fclose(fp);
 
-    for (int i = 0; i < cAddrs; i++)
-    {
-        if (executeIfconfig(pszAdapterName, "inet6",
-                            VBOXADPCTL_DEL_CMD, aszAddresses[i]) != EXIT_SUCCESS)
-            return false;
-    }
+    for (int i = 0; i < cAddrs && rc == EXIT_SUCCESS; i++)
+        rc = remove(pcszAdapter, aszAddresses[i]);
 
-    return true;
+    return rc;
 }
 
 
-#ifndef RT_OS_SOLARIS
-static int doIOCtl(unsigned long iCmd, VBOXNETADPREQ *pReq)
+/*********************************************************************************************************************************
+*   Adapter creation/removal implementations                                                                                     *
+*********************************************************************************************************************************/
+
+/*
+ * A generic implementation of adapter creation/removal ioctl calls.
+ */
+class Adapter
 {
-    int fd = open(VBOXNETADP_CTL_DEV_NAME, O_RDWR);
-    if (fd == -1)
+public:
+    int add(char *pszNameInOut);
+    int remove(const char *pcszName);
+    int checkName(const char *pcszNameIn, char *pszNameOut, size_t cbNameOut);
+protected:
+    virtual int doIOCtl(unsigned long iCmd, VBOXNETADPREQ *pReq);
+};
+
+/*
+ * Solaris does not support dynamic creation/removal of adapters.
+ */
+class AdapterSolaris : public Adapter
+{
+protected:
+    virtual int doIOCtl(unsigned long iCmd, VBOXNETADPREQ *pReq)
+        { return 1 /*ENOTSUP*/; NOREF(iCmd); NOREF(pReq); };
+};
+
+#if defined(RT_OS_LINUX)
+/*
+ * Linux implementation provides a 'workaround' to obtain adapter speed.
+ */
+class AdapterLinux : public Adapter
+{
+public:
+    int getSpeed(const char *pszName, unsigned *puSpeed);
+};
+
+int AdapterLinux::getSpeed(const char *pszName, unsigned *puSpeed)
+{
+    struct ifreq IfReq;
+    struct ethtool_value EthToolVal;
+    struct ethtool_cmd EthToolReq;
+    int fd = socket(AF_INET, SOCK_DGRAM, 0);
+    if (fd < 0)
     {
-        fprintf(stderr, "VBoxNetAdpCtl: Error while %s %s: ",
-                iCmd == VBOXNETADP_CTL_REMOVE ? "removing" : "adding",
-                pReq->szName[0] ? pReq->szName : "new interface");
-        perror("failed to open " VBOXNETADP_CTL_DEV_NAME);
-        return ADPCTLERR_NO_CTL_DEV;
+        fprintf(stderr, "VBoxNetAdpCtl: Error while retrieving link "
+                "speed for %s: ", pszName);
+        perror("VBoxNetAdpCtl: failed to open control socket");
+        return ADPCTLERR_SOCKET_FAILED;
     }
-
-    int rc = ioctl(fd, iCmd, pReq);
-    if (rc == -1)
+    /* Get link status first. */
+    memset(&EthToolVal, 0, sizeof(EthToolVal));
+    memset(&IfReq, 0, sizeof(IfReq));
+    snprintf(IfReq.ifr_name, sizeof(IfReq.ifr_name), "%s", pszName);
+
+    EthToolVal.cmd = ETHTOOL_GLINK;
+    IfReq.ifr_data = (caddr_t)&EthToolVal;
+    int rc = ioctl(fd, SIOCETHTOOL, &IfReq);
+    if (rc == 0)
     {
-        fprintf(stderr, "VBoxNetAdpCtl: Error while %s %s: ",
-                iCmd == VBOXNETADP_CTL_REMOVE ? "removing" : "adding",
-                pReq->szName[0] ? pReq->szName : "new interface");
-        perror("VBoxNetAdpCtl: ioctl failed for " VBOXNETADP_CTL_DEV_NAME);
+        if (EthToolVal.data)
+        {
+            memset(&IfReq, 0, sizeof(IfReq));
+            snprintf(IfReq.ifr_name, sizeof(IfReq.ifr_name), "%s", pszName);
+            EthToolReq.cmd = ETHTOOL_GSET;
+            IfReq.ifr_data = (caddr_t)&EthToolReq;
+            rc = ioctl(fd, SIOCETHTOOL, &IfReq);
+            if (rc == 0)
+            {
+                *puSpeed = EthToolReq.speed;
+            }
+            else
+            {
+                fprintf(stderr, "VBoxNetAdpCtl: Error while retrieving link "
+                        "speed for %s: ", pszName);
+                perror("VBoxNetAdpCtl: ioctl failed");
+                rc = ADPCTLERR_IOCTL_FAILED;
+            }
+        }
+        else
+            *puSpeed = 0;
+    }
+    else
+    {
+        fprintf(stderr, "VBoxNetAdpCtl: Error while retrieving link "
+                "status for %s: ", pszName);
+        perror("VBoxNetAdpCtl: ioctl failed");
         rc = ADPCTLERR_IOCTL_FAILED;
     }
 
     close(fd);
+    return rc;
+}
+#endif /* defined(RT_OS_LINUX) */
 
+int Adapter::add(char *pszName /* in/out */)
+{
+    VBOXNETADPREQ Req;
+    memset(&Req, '\0', sizeof(Req));
+    snprintf(Req.szName, sizeof(Req.szName), "%s", pszName);
+    int rc = doIOCtl(VBOXNETADP_CTL_ADD, &Req);
+    if (rc == 0)
+        strncpy(pszName, Req.szName, VBOXNETADP_MAX_NAME_LEN);
     return rc;
 }
-#endif /* !RT_OS_SOLARIS */
 
+int Adapter::remove(const char *pcszName)
+{
+    VBOXNETADPREQ Req;
+    memset(&Req, '\0', sizeof(Req));
+    snprintf(Req.szName, sizeof(Req.szName), "%s", pcszName);
+    return doIOCtl(VBOXNETADP_CTL_REMOVE, &Req);
+}
 
-static int checkAdapterName(const char *pcszNameIn, char *pszNameOut)
+int Adapter::checkName(const char *pcszNameIn, char *pszNameOut, size_t cbNameOut)
 {
     int iAdapterIndex = -1;
 
@@ -246,7 +599,7 @@ static int checkAdapterName(const char *pcszNameIn, char *pszNameOut)
         fprintf(stderr, "VBoxNetAdpCtl: Setting configuration for '%s' is not supported.\n", pcszNameIn);
         return ADPCTLERR_BAD_NAME;
     }
-    sprintf(pszNameOut, "vboxnet%d", iAdapterIndex);
+    snprintf(pszNameOut, cbNameOut, "vboxnet%d", iAdapterIndex);
     if (strcmp(pszNameOut, pcszNameIn))
     {
         fprintf(stderr, "VBoxNetAdpCtl: Invalid adapter name '%s'.\n", pcszNameIn);
@@ -256,18 +609,103 @@ static int checkAdapterName(const char *pcszNameIn, char *pszNameOut)
     return 0;
 }
 
+int Adapter::doIOCtl(unsigned long iCmd, VBOXNETADPREQ *pReq)
+{
+    int fd = open(VBOXNETADP_CTL_DEV_NAME, O_RDWR);
+    if (fd == -1)
+    {
+        fprintf(stderr, "VBoxNetAdpCtl: Error while %s %s: ",
+                iCmd == VBOXNETADP_CTL_REMOVE ? "removing" : "adding",
+                pReq->szName[0] ? pReq->szName : "new interface");
+        perror("failed to open " VBOXNETADP_CTL_DEV_NAME);
+        return ADPCTLERR_NO_CTL_DEV;
+    }
+
+    int rc = ioctl(fd, iCmd, pReq);
+    if (rc == -1)
+    {
+        fprintf(stderr, "VBoxNetAdpCtl: Error while %s %s: ",
+                iCmd == VBOXNETADP_CTL_REMOVE ? "removing" : "adding",
+                pReq->szName[0] ? pReq->szName : "new interface");
+        perror("VBoxNetAdpCtl: ioctl failed for " VBOXNETADP_CTL_DEV_NAME);
+        rc = ADPCTLERR_IOCTL_FAILED;
+    }
+
+    close(fd);
+
+    return rc;
+}
+
+/*********************************************************************************************************************************
+*   Main logic, argument parsing, etc.                                                                                           *
+*********************************************************************************************************************************/
+
+#if defined(RT_OS_LINUX)
+static CmdIfconfigLinux g_ifconfig;
+static AdapterLinux g_adapter;
+#elif defined(RT_OS_SOLARIS)
+static CmdIfconfigSolaris g_ifconfig;
+static AdapterSolaris g_adapter;
+#else
+static CmdIfconfigDarwin g_ifconfig;
+static Adapter g_adapter;
+#endif
+
+static AddressCommand& chooseAddressCommand()
+{
+#if defined(RT_OS_LINUX)
+    static CmdIpLinux g_ip;
+    if (g_ip.isAvailable())
+        return g_ip;
+#endif
+    return g_ifconfig;
+}
+
 int main(int argc, char *argv[])
 {
     char szAdapterName[VBOXNETADP_MAX_NAME_LEN];
-    char *pszAdapterName = NULL;
-    const char *pszAddress = NULL;
-    const char *pszNetworkMask = NULL;
-    const char *pszOption = NULL;
     int rc = EXIT_SUCCESS;
-    bool fRemove = false;
-    VBOXNETADPREQ Req;
 
-    setPathIfConfig();
+    AddressCommand& cmd = chooseAddressCommand();
+
+    if (argc < 2)
+    {
+        fprintf(stderr, "Insufficient number of arguments\n\n");
+        showUsage();
+        return 1;
+    }
+    else if (argc == 2 && !strcmp("add", argv[1]))
+    {
+        /* Create a new interface */
+        *szAdapterName = '\0';
+        rc = g_adapter.add(szAdapterName);
+        if (rc == 0)
+            puts(szAdapterName);
+        return rc;
+    }
+#ifdef RT_OS_LINUX
+    else if (argc == 3 && !strcmp("speed", argv[2]))
+    {
+        /*
+         * This ugly hack is needed for retrieving the link speed on
+         * pre-2.6.33 kernels (see @bugref{6345}).
+         */
+        if (strlen(argv[1]) >= IFNAMSIZ)
+        {
+            showUsage();
+            return -1;
+        }
+        unsigned uSpeed = 0;
+        rc = g_adapter.getSpeed(argv[1], &uSpeed);
+        if (!rc)
+            printf("%u", uSpeed);
+        return rc;
+    }
+#endif
+
+    rc = g_adapter.checkName(argv[1], szAdapterName, sizeof(szAdapterName));
+    if (rc)
+        return rc;
 
     switch (argc)
     {
@@ -280,10 +718,7 @@ int main(int argc, char *argv[])
                 showUsage();
                 return 1;
             }
-            pszOption = "netmask";
-            pszNetworkMask = argv[4];
-            pszAdapterName = argv[1];
-            pszAddress = argv[2];
+            rc = cmd.set(argv[1], argv[2], argv[4]);
             break;
         }
 
@@ -296,192 +731,35 @@ int main(int argc, char *argv[])
                 showUsage();
                 return 1;
             }
-            fRemove = true;
-            pszAdapterName = argv[1];
-            pszAddress = argv[2];
+            rc = cmd.remove(argv[1], argv[2]);
             break;
         }
 
         case 3:
         {
-            pszAdapterName = argv[1];
-            memset(&Req, '\0', sizeof(Req));
-#ifdef RT_OS_LINUX
-            if (strcmp("speed", argv[2]) == 0)
-            {
-                /*
-                 * This ugly hack is needed for retrieving the link speed on
-                 * pre-2.6.33 kernels (see @bugref{6345}).
-                 */
-                if (strlen(pszAdapterName) >= IFNAMSIZ)
-                {
-                    showUsage();
-                    return -1;
-                }
-                struct ifreq IfReq;
-                struct ethtool_value EthToolVal;
-                struct ethtool_cmd EthToolReq;
-                int fd = socket(AF_INET, SOCK_DGRAM, 0);
-                if (fd < 0)
-                {
-                    fprintf(stderr, "VBoxNetAdpCtl: Error while retrieving link "
-                            "speed for %s: ", pszAdapterName);
-                    perror("VBoxNetAdpCtl: failed to open control socket");
-                    return ADPCTLERR_SOCKET_FAILED;
-                }
-                /* Get link status first. */
-                memset(&EthToolVal, 0, sizeof(EthToolVal));
-                memset(&IfReq, 0, sizeof(IfReq));
-                snprintf(IfReq.ifr_name, sizeof(IfReq.ifr_name), "%s", pszAdapterName);
-
-                EthToolVal.cmd = ETHTOOL_GLINK;
-                IfReq.ifr_data = (caddr_t)&EthToolVal;
-                rc = ioctl(fd, SIOCETHTOOL, &IfReq);
-                if (rc == 0)
-                {
-                    if (EthToolVal.data)
-                    {
-                        memset(&IfReq, 0, sizeof(IfReq));
-                        snprintf(IfReq.ifr_name, sizeof(IfReq.ifr_name), "%s", pszAdapterName);
-                        EthToolReq.cmd = ETHTOOL_GSET;
-                        IfReq.ifr_data = (caddr_t)&EthToolReq;
-                        rc = ioctl(fd, SIOCETHTOOL, &IfReq);
-                        if (rc == 0)
-                        {
-                            printf("%u", EthToolReq.speed);
-                        }
-                        else
-                        {
-                            fprintf(stderr, "VBoxNetAdpCtl: Error while retrieving link "
-                                    "speed for %s: ", pszAdapterName);
-                            perror("VBoxNetAdpCtl: ioctl failed");
-                            rc = ADPCTLERR_IOCTL_FAILED;
-                        }
-                    }
-                    else
-                        printf("0");
-                }
-                else
-                {
-                    fprintf(stderr, "VBoxNetAdpCtl: Error while retrieving link "
-                            "status for %s: ", pszAdapterName);
-                    perror("VBoxNetAdpCtl: ioctl failed");
-                    rc = ADPCTLERR_IOCTL_FAILED;
-                }
-
-                close(fd);
-                return rc;
-            }
-#endif
-            rc = checkAdapterName(pszAdapterName, szAdapterName);
-            if (rc)
-                return rc;
-            snprintf(Req.szName, sizeof(Req.szName), "%s", szAdapterName);
-            pszAddress = argv[2];
-            if (strcmp("remove", pszAddress) == 0)
+            if (strcmp("remove", argv[2]) == 0)
             {
                 /* Remove an existing interface */
-#ifdef RT_OS_SOLARIS
-                return 1;
-#else
-                return doIOCtl(VBOXNETADP_CTL_REMOVE, &Req);
-#endif
+                rc = g_adapter.remove(argv[1]);
             }
-            else if (strcmp("add", pszAddress) == 0)
+            else if (strcmp("add", argv[2]) == 0)
             {
                 /* Create an interface with given name */
-#ifdef RT_OS_SOLARIS
-                return 1;
-#else
-                rc = doIOCtl(VBOXNETADP_CTL_ADD, &Req);
+                rc = g_adapter.add(szAdapterName);
                 if (rc == 0)
-                    puts(Req.szName);
-#endif
-                return rc;
+                    puts(szAdapterName);
             }
+            else
+                rc = cmd.set(argv[1], argv[2]);
             break;
         }
 
-        case 2:
-        {
-            /* Create a new interface */
-            if (strcmp("add", argv[1]) == 0)
-            {
-#ifdef RT_OS_SOLARIS
-                return 1;
-#else
-                memset(&Req, '\0', sizeof(Req));
-                rc = doIOCtl(VBOXNETADP_CTL_ADD, &Req);
-                if (rc == 0)
-                    puts(Req.szName);
-#endif
-                return rc;
-            }
-            /* Fall through */
-        }
-
         default:
             fprintf(stderr, "Invalid number of arguments.\n\n");
-            /* Fall through */
-        case 1:
             showUsage();
             return 1;
     }
 
-    rc = checkAdapterName(pszAdapterName, szAdapterName);
-    if (rc)
-        return rc;
-
-    pszAdapterName = szAdapterName;
-
-    if (fRemove)
-    {
-        if (strchr(pszAddress, ':'))
-            rc = executeIfconfig(pszAdapterName, "inet6", VBOXADPCTL_DEL_CMD, pszAddress);
-        else
-        {
-#if defined(RT_OS_LINUX)
-            rc = executeIfconfig(pszAdapterName, "0.0.0.0");
-#else
-            rc = executeIfconfig(pszAdapterName, VBOXADPCTL_DEL_CMD, pszAddress);
-#endif
-
-#ifdef RT_OS_SOLARIS
-            /* On Solaris we can unplumb the ipv4 interface */
-            executeIfconfig(pszAdapterName, "inet", "unplumb");
-#endif
-        }
-    }
-    else
-    {
-        /* We are setting/replacing address. */
-        if (strchr(pszAddress, ':'))
-        {
-#ifdef RT_OS_SOLARIS
-            /* On Solaris we need to plumb the interface first if it's not already plumbed. */
-            if (executeIfconfig(pszAdapterName, "inet6") != 0)
-                executeIfconfig(pszAdapterName, "inet6", "plumb", "up");
-#endif
-            /*
-             * Before we set IPv6 address we'd like to remove
-             * all previously assigned addresses except the
-             * self-assigned one.
-             */
-            if (!removeAddresses(pszAdapterName))
-                rc = EXIT_FAILURE;
-            else
-                rc = executeIfconfig(pszAdapterName, "inet6", VBOXADPCTL_ADD_CMD, pszAddress, pszOption, pszNetworkMask);
-        }
-        else
-        {
-#ifdef RT_OS_SOLARIS
-            /* On Solaris we need to plumb the interface first if it's not already plumbed. */
-            if (executeIfconfig(pszAdapterName, "inet") != 0)
-                executeIfconfig(pszAdapterName, "plumb", "up");
-#endif
-            rc = executeIfconfig(pszAdapterName, pszAddress, pszOption, pszNetworkMask);
-        }
-    }
     return rc;
 }
 
diff --git a/src/VBox/HostServices/SharedOpenGL/crserverlib/get_sizes.py b/src/VBox/HostServices/SharedOpenGL/crserverlib/get_sizes.py
old mode 100755
new mode 100644
diff --git a/src/VBox/HostServices/SharedOpenGL/crserverlib/server_dispatch.py b/src/VBox/HostServices/SharedOpenGL/crserverlib/server_dispatch.py
old mode 100755
new mode 100644
diff --git a/src/VBox/HostServices/SharedOpenGL/crserverlib/server_dispatch_header.py b/src/VBox/HostServices/SharedOpenGL/crserverlib/server_dispatch_header.py
old mode 100755
new mode 100644
diff --git a/src/VBox/HostServices/SharedOpenGL/crserverlib/server_get.py b/src/VBox/HostServices/SharedOpenGL/crserverlib/server_get.py
old mode 100755
new mode 100644
diff --git a/src/VBox/HostServices/SharedOpenGL/crserverlib/server_retval.py b/src/VBox/HostServices/SharedOpenGL/crserverlib/server_retval.py
old mode 100755
new mode 100644
diff --git a/src/VBox/HostServices/SharedOpenGL/crserverlib/server_simpleget.py b/src/VBox/HostServices/SharedOpenGL/crserverlib/server_simpleget.py
old mode 100755
new mode 100644
diff --git a/src/VBox/HostServices/SharedOpenGL/dlm/dlm_generated.py b/src/VBox/HostServices/SharedOpenGL/dlm/dlm_generated.py
old mode 100755
new mode 100644
diff --git a/src/VBox/HostServices/SharedOpenGL/unpacker/unpack.py b/src/VBox/HostServices/SharedOpenGL/unpacker/unpack.py
old mode 100755
new mode 100644
diff --git a/src/VBox/HostServices/SharedOpenGL/unpacker/unpack_extend.py b/src/VBox/HostServices/SharedOpenGL/unpacker/unpack_extend.py
old mode 100755
new mode 100644
diff --git a/src/VBox/HostServices/SharedOpenGL/unpacker/unpack_header.py b/src/VBox/HostServices/SharedOpenGL/unpacker/unpack_header.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Installer/Makefile.kmk b/src/VBox/Installer/Makefile.kmk
index 0861f19..5cf61b9 100644
--- a/src/VBox/Installer/Makefile.kmk
+++ b/src/VBox/Installer/Makefile.kmk
@@ -57,7 +57,6 @@ if defined(VBOX_ONLY_SDK) ## @todo || defined(VBOX_WITH_SDK)
  OTHER_CLEANS += $(VBOX_SDK_ZIP) \
                  $(wildcard $(PATH_STAGE_BIN)/VirtualBoxSDK-*-r*.zip)
 
- VBOX_ZIP     ?= zip
 # @todo: wrong, it must depend on everything included in SDK
 $(VBOX_SDK_ZIP): \
 		$(PATH_STAGE_BIN)/sdk \
diff --git a/src/VBox/Installer/linux/Makefile.kmk b/src/VBox/Installer/linux/Makefile.kmk
index 294ebb6..b811d82 100644
--- a/src/VBox/Installer/linux/Makefile.kmk
+++ b/src/VBox/Installer/linux/Makefile.kmk
@@ -516,6 +516,7 @@ BLDDIRS += $(foreach d,\
 	  archive/accessible),) \
 	$(if $(VBOX_WITH_QTGUI_V5),\
 	  archive/plugins/platforms \
+	  archive/plugins/xcbglintegrations \
 	  archive/legacy,) \
 	$(if $(VBOX_WITH_PYTHON),\
 	  archive/sdk/installer \
diff --git a/src/VBox/Installer/linux/distributions_rpm b/src/VBox/Installer/linux/distributions_rpm
index b928581..7cbd2b0 100644
--- a/src/VBox/Installer/linux/distributions_rpm
+++ b/src/VBox/Installer/linux/distributions_rpm
@@ -6,6 +6,7 @@ openSUSE113     = OPENSUSE_11_3
 sles11.0        = SLES_11_0
 sles10.1        = SLES_10_1
 mdv2011.0       = MANDRIVA_2011_0
+fedora26        = FEDORA_26
 fedora25        = FEDORA_25
 fedora24        = FEDORA_24
 fedora22        = FEDORA_22
diff --git a/src/VBox/Installer/linux/install.sh b/src/VBox/Installer/linux/install.sh
index bf79deb..d3a51e6 100755
--- a/src/VBox/Installer/linux/install.sh
+++ b/src/VBox/Installer/linux/install.sh
@@ -15,6 +15,13 @@
 # hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
 #
 
+# Testing:
+# * After successful installation, 0 is returned if the vboxdrv module version
+#   built matches the one loaded.
+# * If the kernel modules cannot be built (run the installer with KERN_DIR=/) or
+#   loaded (run with KERN_DIR=/lib/modules/<installed non-current version>/build)
+#   then 1 is returned.
+
 PATH=$PATH:/bin:/sbin:/usr/sbin
 
 # Include routines and utilities needed by the installer
@@ -52,6 +59,9 @@ fi
 VBOXUSB_MODE=0664
 VBOXUSB_GRP=$GROUPNAME
 
+## Were we able to stop any previously running Additions kernel modules?
+MODULES_STOPPED=1
+
 
 ##############################################################################
 # Helper routines                                                            #
@@ -380,6 +390,10 @@ if [ "$ACTION" = "install" ]; then
       START_SERVICES="--nostart"
     fi
     "${INSTALLATION_DIR}/prerm-common.sh" >> "${LOG}"
+
+    # Now check whether the kernel modules were stopped.
+    lsmod | grep -q vboxdrv && MODULES_STOPPED=
+
     "${INSTALLATION_DIR}/postinst-common.sh" ${START_SERVICES} >> "${LOG}"
 
     info ""
@@ -392,6 +406,14 @@ if [ "$ACTION" = "install" ]; then
     info ""
     info "We hope that you enjoy using VirtualBox."
     info ""
+
+    # And do a final test as to whether the kernel modules were properly created
+    # and loaded.  Return 0 if both are true, 1 if not.
+    test -n "${MODULES_STOPPED}" &&
+        modinfo vboxdrv >/dev/null 2>&1 &&
+        lsmod | grep -q vboxdrv ||
+        abort "The installation log file is at ${LOG}."
+
     log "Installation successful"
 elif [ "$ACTION" = "uninstall" ]; then
     . ./uninstall.sh
diff --git a/src/VBox/Installer/linux/postinst-common.sh b/src/VBox/Installer/linux/postinst-common.sh
index d9d77a7..3a69e89 100755
--- a/src/VBox/Installer/linux/postinst-common.sh
+++ b/src/VBox/Installer/linux/postinst-common.sh
@@ -102,9 +102,10 @@ test -n "${START}" &&
         echo "There were problems setting up VirtualBox.  To re-start the set-up process, run" >&2
         echo "  /sbin/vboxconfig" >&2
         echo "as root." >&2
+    else
+        start_init_script vboxdrv
+        start_init_script vboxballoonctrl-service
+        start_init_script vboxautostart-service
+        start_init_script vboxweb-service
     fi
-    start_init_script vboxdrv
-    start_init_script vboxballoonctrl-service
-    start_init_script vboxautostart-service
-    start_init_script vboxweb-service
 }
diff --git a/src/VBox/Installer/linux/routines.sh b/src/VBox/Installer/linux/routines.sh
index 9343662..685b8a8 100644
--- a/src/VBox/Installer/linux/routines.sh
+++ b/src/VBox/Installer/linux/routines.sh
@@ -124,19 +124,23 @@ systemd_wrap_init_script()
         { echo "$self: systemd unit path not found" >&2 && return 1; }
     description=`sed -n 's/# *Short-Description: *\(.*\)/\1/p' "${script}"`
     required=`sed -n 's/# *Required-Start: *\(.*\)/\1/p' "${script}" | sed 's/\$[a-z]*//'`
+    startbefore=`sed -n 's/# *X-Start-Before: *\(.*\)/\1/p' "${script}" | sed 's/\$[a-z]*//'`
     runlevels=`sed -n 's/# *Default-Start: *\(.*\)/\1/p' "${script}"`
-    before=`for i in ${runlevels}; do printf "runlevel${i}.target "; done`
+    servicetype=`sed -n 's/# *X-Service-Type: *\(.*\)/\1/p' "${script}"`
+    test -z "${servicetype}" && servicetype="forking"
+    targets=`for i in ${runlevels}; do printf "runlevel${i}.target "; done`
+    before=`for i in ${startbefore}; do printf "${i}.service "; done`
     after=`for i in ${required}; do printf "${i}.service "; done`
     cat > "${unit_path}/${name}.service" << EOF
 [Unit]
 SourcePath=${script}
 Description=${description}
-Before=${before}shutdown.target
+Before=${targets}shutdown.target ${before}
 After=${after}
 Conflicts=shutdown.target
 
 [Service]
-Type=forking
+Type=${servicetype}
 Restart=no
 TimeoutSec=5min
 IgnoreSIGPIPE=no
diff --git a/src/VBox/Installer/linux/rpm/VirtualBox.tmpl.spec b/src/VBox/Installer/linux/rpm/VirtualBox.tmpl.spec
index 06d6138..f3dbc0c 100644
--- a/src/VBox/Installer/linux/rpm/VirtualBox.tmpl.spec
+++ b/src/VBox/Installer/linux/rpm/VirtualBox.tmpl.spec
@@ -30,7 +30,7 @@ License:   GPLv2
 Group:     Applications/System
 Vendor:    Oracle Corporation
 BuildRoot: %BUILDROOT%
-Requires:  %INITSCRIPTS% %LIBASOUND% net-tools
+Requires:  %INITSCRIPTS% %LIBASOUND% %NETTOOLS%
 
 %if %{?rpm_suse:1}%{!?rpm_suse:0}
 %debug_package
@@ -172,7 +172,8 @@ mv * $RPM_BUILD_ROOT/usr/lib/virtualbox
 if [ -f $RPM_BUILD_ROOT/usr/lib/virtualbox/libQt5CoreVBox.so.5 ]; then
   $RPM_BUILD_ROOT/usr/lib/virtualbox/chrpath --keepgoing --replace /usr/lib/virtualbox \
     $RPM_BUILD_ROOT/usr/lib/virtualbox/*.so.5 \
-    $RPM_BUILD_ROOT/usr/lib/virtualbox/plugins/platforms/*.so || true
+    $RPM_BUILD_ROOT/usr/lib/virtualbox/plugins/platforms/*.so \
+    $RPM_BUILD_ROOT/usr/lib/virtualbox/plugins/xcbglintegrations/*.so || true
   echo "[Paths]" > $RPM_BUILD_ROOT/usr/lib/virtualbox/qt.conf
   echo "Plugins = /usr/lib/virtualbox/plugins" >> $RPM_BUILD_ROOT/usr/lib/virtualbox/qt.conf
   rm $RPM_BUILD_ROOT/usr/lib/virtualbox/chrpath
diff --git a/src/VBox/Installer/linux/rpm/rules b/src/VBox/Installer/linux/rpm/rules
index 14b620d..d5435b3 100755
--- a/src/VBox/Installer/linux/rpm/rules
+++ b/src/VBox/Installer/linux/rpm/rules
@@ -63,7 +63,7 @@ verpkg   := VirtualBox-5.1
 current  := $(shell pwd)
 vboxroot := $(shell while ! test -r configure && ! test "$PWD" = "/"; do cd ..; done; pwd)
 pkgdir   := $(if $(PKGDIR),$(PKGDIR),$(shell cd $(vboxroot)/..; pwd))
-builddir := $(current)/rpm/builddir
+builddir := $(vboxroot)/out/rpm/builddir
 rpmlib   := $(shell if [ `uname -m` = "x86_64" ]; then echo "lib64"; else echo "lib"; fi)
 chrarch  := $(shell if [ `uname -m` = "x86_64" ]; then echo "amd64"; else echo "x86"; fi)
 verfile  := $(builddir)/version-generated.mk
@@ -105,7 +105,7 @@ ifneq ($(MAKECMDGOALS),clean)
   $(error Cannot detect package distribution (rpmrel=$(rpmrel)))
  endif
 
- ifeq ($(filter-out el5 el6 el7 fedora18 fedora19 fedora20 fedora21 fedora22 fedora24 fedora25,$(rpmrel)),)
+ ifeq ($(filter-out el5 el6 el7 fedora18 fedora19 fedora20 fedora21 fedora22 fedora24 fedora25 fedora26,$(rpmrel)),)
   rpmspec := rpm_redhat
  endif
  ifeq ($(filter-out openSUSE110 openSUSE111 openSUSE112 openSUSE113 openSUSE114 openSUSE123 openSUSE131 openSUSE132,$(rpmrel)),)
@@ -228,7 +228,8 @@ binary: rpm/build-stamp
 	    -e 's|%INSTMOD%|$(instmod)|g' \
 	    -e 's|%LIBASOUND%|$(if $(filter lib64,$(rpmlib)),libasound.so.2()(64bit),libasound.so.2)|g' \
 	    -e 's|%INITSCRIPTS%|$(if $(filter fedora,$(rpmspec)),initscripts,)|g' \
-	    -e "s|%WEBSVC%|$(if $(NOWEBSVC),false,true)|g" \
+	    -e 's|%WEBSVC%|$(if $(NOWEBSVC),false,true)|g' \
+	    -e 's|%NETTOOLS%|$(if $(filter fedora18 fedora19 fedora20 fedora21 el5 openSUSE110 openSUSE111 openSUSE112 openSUSE113 openSUSE114,$(rpmrel)),net-tools,iproute)|g' \
 	    rpm/VirtualBox.tmpl.spec > $(archdir)/VirtualBox.spec
 	mv rpm/VirtualBox-$(ver) rpm/$(rpmname)
 	cp ../../../../tools/linux.$(chrarch)/bin/chrpath rpm/$(rpmname)
diff --git a/src/VBox/Installer/solaris/Makefile.kmk b/src/VBox/Installer/solaris/Makefile.kmk
index 894904e..4169ec0 100644
--- a/src/VBox/Installer/solaris/Makefile.kmk
+++ b/src/VBox/Installer/solaris/Makefile.kmk
@@ -355,6 +355,7 @@ ifdef VBOX_WITH_QTGUI
 	  libQt5X11ExtrasVBox.so.5 \
           libQt5WidgetsVBox.so.5 \
           plugins/platforms/libqxcb.so \
+          plugins/xcbglintegrations/libqxcb-glx-integration.so \
 	  $(if $(VBOX_GUI_USE_QGL),libQt5OpenGLVBox.so.5,)
   endif
  else # VBOX_WITH_QTGUI_V5
diff --git a/src/VBox/Main/Makefile.kmk b/src/VBox/Main/Makefile.kmk
index 847cf23..a5696c1 100644
--- a/src/VBox/Main/Makefile.kmk
+++ b/src/VBox/Main/Makefile.kmk
@@ -4,7 +4,7 @@
 #
 
 #
-# Copyright (C) 2004-2016 Oracle Corporation
+# Copyright (C) 2004-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;
@@ -273,6 +273,7 @@ VBoxSVC_DEFS = \
 	$(if $(VBOX_WITH_AUDIO_OSS),VBOX_WITH_AUDIO_OSS,) \
 	$(if $(VBOX_WITH_AUDIO_ALSA),VBOX_WITH_AUDIO_ALSA,) \
 	$(if $(VBOX_WITH_AUDIO_PULSE),VBOX_WITH_AUDIO_PULSE,) \
+	$(if $(VBOX_WITH_AUDIO_VALIDATIONKIT),VBOX_WITH_AUDIO_VALIDATIONKIT,) \
 	$(if $(VBOX_WITH_AUDIO_DEBUG),VBOX_WITH_AUDIO_DEBUG,) \
 	$(if $(VBOX_WITH_VRDE_AUDIO),VBOX_WITH_VRDE_AUDIO,) \
 	$(if $(VBOX_WITH_E1000),VBOX_WITH_E1000,) \
@@ -644,6 +645,7 @@ VBoxC_DEFS = \
 	$(if $(VBOX_WITH_AUDIO_OSS),VBOX_WITH_AUDIO_OSS,) \
 	$(if $(VBOX_WITH_AUDIO_ALSA),VBOX_WITH_AUDIO_ALSA,) \
 	$(if $(VBOX_WITH_AUDIO_PULSE),VBOX_WITH_AUDIO_PULSE,) \
+	$(if $(VBOX_WITH_AUDIO_VALIDATIONKIT),VBOX_WITH_AUDIO_VALIDATIONKIT,) \
 	$(if $(VBOX_WITH_AUDIO_DEBUG),VBOX_WITH_AUDIO_DEBUG,) \
 	$(if $(VBOX_WITH_VRDE_AUDIO),VBOX_WITH_VRDE_AUDIO,) \
 	$(if $(VBOX_WITH_E1000),VBOX_WITH_E1000,) \
diff --git a/src/VBox/Main/glue/constants-python.xsl b/src/VBox/Main/glue/constants-python.xsl
old mode 100755
new mode 100644
diff --git a/src/VBox/Main/glue/vboxapi.py b/src/VBox/Main/glue/vboxapi.py
old mode 100755
new mode 100644
diff --git a/src/VBox/Main/include/GuestCtrlImplPrivate.h b/src/VBox/Main/include/GuestCtrlImplPrivate.h
index d672b43..d4b6e16 100644
--- a/src/VBox/Main/include/GuestCtrlImplPrivate.h
+++ b/src/VBox/Main/include/GuestCtrlImplPrivate.h
@@ -4,7 +4,7 @@
  */
 
 /*
- * Copyright (C) 2011-2016 Oracle Corporation
+ * Copyright (C) 2011-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;
@@ -1095,7 +1095,7 @@ public:
     int generateContextID(uint32_t uSessionID, uint32_t uObjectID, uint32_t *puContextID);
     int registerWaitEvent(uint32_t uSessionID, uint32_t uObjectID, GuestWaitEvent **ppEvent);
     int registerWaitEvent(uint32_t uSessionID, uint32_t uObjectID, const GuestEventTypes &lstEvents, GuestWaitEvent **ppEvent);
-    void unregisterWaitEvent(GuestWaitEvent *pEvent);
+    int unregisterWaitEvent(GuestWaitEvent *pEvent);
     int waitForEvent(GuestWaitEvent *pEvent, uint32_t uTimeoutMS, VBoxEventType_T *pType, IEvent **ppEvent);
 
 protected:
diff --git a/src/VBox/Main/include/GuestOSTypeImpl.h b/src/VBox/Main/include/GuestOSTypeImpl.h
index bfa2862..19aff17 100644
--- a/src/VBox/Main/include/GuestOSTypeImpl.h
+++ b/src/VBox/Main/include/GuestOSTypeImpl.h
@@ -39,6 +39,7 @@ public:
 
     // public methods only for internal purposes
     const Bstr &i_id() const { return mID; }
+    const Bstr &i_familyId() const { return mFamilyID; }
     bool i_is64Bit() const { return !!(mOSHint & VBOXOSHINT_64BIT); }
     bool i_recommendedIOAPIC() const { return !!(mOSHint & VBOXOSHINT_IOAPIC); }
     bool i_recommendedX2APIC() const { return !!(mOSHint & VBOXOSHINT_X2APIC); }
diff --git a/src/VBox/Main/include/MachineImpl.h b/src/VBox/Main/include/MachineImpl.h
index e6c30a8..675fae0 100644
--- a/src/VBox/Main/include/MachineImpl.h
+++ b/src/VBox/Main/include/MachineImpl.h
@@ -494,6 +494,7 @@ public:
      * Intended to be used only after doing addCaller() manually and locking it
      * for reading.
      */
+    Utf8Str i_getOSTypeId() const { return mUserData->s.strOsType; }
     ChipsetType_T i_getChipsetType() const { return mHWData->mChipsetType; }
     ParavirtProvider_T i_getParavirtProvider() const { return mHWData->mParavirtProvider; }
     Utf8Str i_getParavirtDebug() const { return mHWData->mParavirtDebug; }
diff --git a/src/VBox/Main/include/NetworkAdapterImpl.h b/src/VBox/Main/include/NetworkAdapterImpl.h
index 0718e0e..422db94 100644
--- a/src/VBox/Main/include/NetworkAdapterImpl.h
+++ b/src/VBox/Main/include/NetworkAdapterImpl.h
@@ -110,7 +110,7 @@ private:
     void i_generateMACAddress();
     HRESULT i_updateMacAddress(Utf8Str aMacAddress);
     void i_updateBandwidthGroup(BandwidthGroup *aBwGroup);
-    HRESULT i_checkAndSwitchFromNatNetworking(com::Utf8Str networkName);
+    HRESULT i_switchFromNatNetworking(const com::Utf8Str &aNatnetworkName);
     HRESULT i_switchToNatNetworking(const com::Utf8Str &aNatNetworkName);
 
 
diff --git a/src/VBox/Main/include/netif.h b/src/VBox/Main/include/netif.h
index 51bb1b7..bd84d59 100644
--- a/src/VBox/Main/include/netif.h
+++ b/src/VBox/Main/include/netif.h
@@ -99,53 +99,25 @@ int NetIfAdpCtlOut(const char *pszName, const char *pszCmd, char *pszBuffer, siz
 
 DECLINLINE(Bstr) composeIPv6Address(PRTNETADDRIPV6 aAddrPtr)
 {
-    char szTmp[8*5] = "";
-
-    if (aAddrPtr->s.Lo || aAddrPtr->s.Hi)
-        RTStrPrintf(szTmp, sizeof(szTmp),
-                    "%02x%02x:%02x%02x:%02x%02x:%02x%02x:"
-                    "%02x%02x:%02x%02x:%02x%02x:%02x%02x",
-                    aAddrPtr->au8[0], aAddrPtr->au8[1],
-                    aAddrPtr->au8[2], aAddrPtr->au8[3],
-                    aAddrPtr->au8[4], aAddrPtr->au8[5],
-                    aAddrPtr->au8[6], aAddrPtr->au8[7],
-                    aAddrPtr->au8[8], aAddrPtr->au8[9],
-                    aAddrPtr->au8[10], aAddrPtr->au8[11],
-                    aAddrPtr->au8[12], aAddrPtr->au8[13],
-                    aAddrPtr->au8[14], aAddrPtr->au8[15]);
-    return Bstr(szTmp);
-}
-
-DECLINLINE(ULONG) composeIPv6PrefixLenghFromAddress(PRTNETADDRIPV6 aAddrPtr)
-{
-    int res = ASMBitFirstClear(aAddrPtr, sizeof(RTNETADDRIPV6)*8);
-    return res != -1 ? res : 128;
-}
-
-DECLINLINE(int) prefixLength2IPv6Address(ULONG cPrefix, PRTNETADDRIPV6 aAddrPtr)
-{
-    if (cPrefix > 128)
-        return VERR_INVALID_PARAMETER;
-    if (!aAddrPtr)
-        return VERR_INVALID_PARAMETER;
-
-    RT_ZERO(*aAddrPtr);
-
-    ASMBitSetRange(aAddrPtr, 0, cPrefix);
-
-    return VINF_SUCCESS;
+    /* We can't use %RTnaipv6 because that function is too clever, i.e. it
+     * shows abbreviations which the GUI isn't able to parse. */
+    return aAddrPtr->s.Lo || aAddrPtr->s.Hi
+        ? Bstr(Utf8StrFmt("%02x%02x:%02x%02x:%02x%02x:%02x%02x:"
+                          "%02x%02x:%02x%02x:%02x%02x:%02x%02x",
+                          aAddrPtr->au8[0], aAddrPtr->au8[1],
+                          aAddrPtr->au8[2], aAddrPtr->au8[3],
+                          aAddrPtr->au8[4], aAddrPtr->au8[5],
+                          aAddrPtr->au8[6], aAddrPtr->au8[7],
+                          aAddrPtr->au8[8], aAddrPtr->au8[9],
+                          aAddrPtr->au8[10], aAddrPtr->au8[11],
+                          aAddrPtr->au8[12], aAddrPtr->au8[13],
+                          aAddrPtr->au8[14], aAddrPtr->au8[15]))
+        : Bstr("");
 }
 
 DECLINLINE(Bstr) composeHardwareAddress(PRTMAC aMacPtr)
 {
-    char szTmp[6*3];
-
-    RTStrPrintf(szTmp, sizeof(szTmp),
-                "%02x:%02x:%02x:%02x:%02x:%02x",
-                aMacPtr->au8[0], aMacPtr->au8[1],
-                aMacPtr->au8[2], aMacPtr->au8[3],
-                aMacPtr->au8[4], aMacPtr->au8[5]);
-    return Bstr(szTmp);
+    return Bstr(Utf8StrFmt("%RTmac", aMacPtr));
 }
 
 DECLINLINE(Bstr) getDefaultIPv4Address(Bstr bstrIfName)
diff --git a/src/VBox/Main/src-all/Global.cpp b/src/VBox/Main/src-all/Global.cpp
index 70f7154..429f6bc 100644
--- a/src/VBox/Main/src-all/Global.cpp
+++ b/src/VBox/Main/src-all/Global.cpp
@@ -101,22 +101,22 @@ const Global::OSType Global::sOSTypes[] =
 
     { "Windows", "Microsoft Windows", "Windows2008",        "Windows 2008 (32-bit)",
       VBOXOSTYPE_Win2k8,           VBOXOSHINT_USBTABLET,
-       512,  16, 25 * _1G64, NetworkAdapterType_I82540EM, 0, StorageControllerType_IntelAhci, StorageBus_SATA,
+       1024, 16, 25 * _1G64, NetworkAdapterType_I82540EM, 0, StorageControllerType_IntelAhci, StorageBus_SATA,
         StorageControllerType_IntelAhci, StorageBus_SATA, ChipsetType_PIIX3, AudioControllerType_HDA, AudioCodecType_STAC9221  },
 
     { "Windows", "Microsoft Windows", "Windows2008_64",     "Windows 2008 (64-bit)",
       VBOXOSTYPE_Win2k8_x64,      VBOXOSHINT_64BIT | VBOXOSHINT_HWVIRTEX | VBOXOSHINT_IOAPIC | VBOXOSHINT_USBTABLET,
-       512,  16, 25 * _1G64, NetworkAdapterType_I82540EM, 0, StorageControllerType_IntelAhci, StorageBus_SATA,
+       2048, 16, 25 * _1G64, NetworkAdapterType_I82540EM, 0, StorageControllerType_IntelAhci, StorageBus_SATA,
         StorageControllerType_IntelAhci, StorageBus_SATA, ChipsetType_PIIX3, AudioControllerType_HDA, AudioCodecType_STAC9221  },
 
     { "Windows", "Microsoft Windows", "Windows7",           "Windows 7 (32-bit)",
       VBOXOSTYPE_Win7,             VBOXOSHINT_USBTABLET,
-       512,  16, 25 * _1G64, NetworkAdapterType_I82540EM, 0, StorageControllerType_IntelAhci, StorageBus_SATA,
+       1024, 16, 25 * _1G64, NetworkAdapterType_I82540EM, 0, StorageControllerType_IntelAhci, StorageBus_SATA,
         StorageControllerType_IntelAhci, StorageBus_SATA, ChipsetType_PIIX3, AudioControllerType_HDA, AudioCodecType_STAC9221  },
 
     { "Windows", "Microsoft Windows", "Windows7_64",        "Windows 7 (64-bit)",
       VBOXOSTYPE_Win7_x64,        VBOXOSHINT_64BIT | VBOXOSHINT_HWVIRTEX | VBOXOSHINT_IOAPIC | VBOXOSHINT_USBTABLET,
-       512,  16, 25 * _1G64, NetworkAdapterType_I82540EM, 0, StorageControllerType_IntelAhci, StorageBus_SATA,
+       2048, 16, 25 * _1G64, NetworkAdapterType_I82540EM, 0, StorageControllerType_IntelAhci, StorageBus_SATA,
         StorageControllerType_IntelAhci, StorageBus_SATA, ChipsetType_PIIX3, AudioControllerType_HDA, AudioCodecType_STAC9221  },
 
     { "Windows", "Microsoft Windows", "Windows8",           "Windows 8 (32-bit)",
diff --git a/src/VBox/Main/src-all/QMTranslatorImpl.cpp b/src/VBox/Main/src-all/QMTranslatorImpl.cpp
index 48b1e58..f7fec52 100644
--- a/src/VBox/Main/src-all/QMTranslatorImpl.cpp
+++ b/src/VBox/Main/src-all/QMTranslatorImpl.cpp
@@ -27,7 +27,8 @@
 
 /* QM File Magic Number */
 static const size_t MagicLength = 16;
-static const uint8_t Magic[MagicLength] = {
+static const uint8_t Magic[MagicLength] =
+{
     0x3c, 0xb8, 0x64, 0x18, 0xca, 0xef, 0x9c, 0x95,
     0xcd, 0x21, 0x1c, 0xbf, 0x60, 0xa1, 0xbd, 0xdd
 };
@@ -234,18 +235,18 @@ public:
             switch (sectionCode)
             {
                 case Messages:
-                parseMessages(stream, &hashSet, &messageArray, sLen);
-                break;
+                    parseMessages(stream, &hashSet, &messageArray, sLen);
+                    break;
                 case Hashes:
-                /* Only get size information to speed-up vector filling
-                 * if Hashes section goes in the file before Message section */
-                m_messageArray.reserve(sLen >> 3);
-                /* NB! NO BREAK HERE */
+                    /* Only get size information to speed-up vector filling
+                     * if Hashes section goes in the file before Message section */
+                    m_messageArray.reserve(sLen >> 3);
+                    /* fall thru */
                 case Context:
-                stream.seek(sLen);
-                break;
+                    stream.seek(sLen);
+                    break;
                 default:
-                throw QMException("Unkown section");
+                    throw QMException("Unkown section");
             }
         }
         /* Store the data into member variables.
@@ -302,18 +303,18 @@ private:
     /* Parse one message from the stream */
     static void parseMessageRecord(QMBytesStream &stream, QMMessage * const message)
     {
-        while(!stream.hasFinished())
+        while (!stream.hasFinished())
         {
             uint8_t type = stream.read8();
-            switch(type)
+            switch (type)
             {
                 case End:
-                return;
+                    return;
                 /* Ignored as obsolete */
                 case Context16:
                 case SourceText16:
-                stream.seek(stream.read32());
-                break;
+                    stream.seek(stream.read32());
+                    break;
                 case Translation:
                 {
                     com::Utf8Str str = stream.readUtf16String();
@@ -321,8 +322,8 @@ private:
                     break;
                 }
                 case Hash:
-                message->hash = stream.read32();
-                break;
+                    message->hash = stream.read32();
+                    break;
 
                 case SourceText:
                 {
@@ -346,9 +347,9 @@ private:
                 }
 
                 default:
-                /* Ignore unknown block */
-                LogRel(("QMTranslator::parseMessageRecord(): Unkown message block %x\n", type));
-                break;
+                    /* Ignore unknown block */
+                    LogRel(("QMTranslator::parseMessageRecord(): Unkown message block %x\n", type));
+                    break;
             }
         }
     }
diff --git a/src/VBox/Main/src-all/SecretKeyStore.cpp b/src/VBox/Main/src-all/SecretKeyStore.cpp
index 74be9e4..67a72ac 100644
--- a/src/VBox/Main/src-all/SecretKeyStore.cpp
+++ b/src/VBox/Main/src-all/SecretKeyStore.cpp
@@ -217,7 +217,10 @@ int SecretKeyStore::deleteAllSecretKeys(bool fSuspend, bool fForce)
         {
             AssertMsg(!pKey->refCount(), ("No one should access the stored key at this point anymore!\n"));
             delete pKey;
-            m_mapSecretKeys.erase(it++);
+            SecretKeyMap::iterator itNext = it;
+            ++itNext;
+            m_mapSecretKeys.erase(it);
+            it = itNext;
         }
         else
             ++it;
diff --git a/src/VBox/Main/src-client/ConsoleImpl.cpp b/src/VBox/Main/src-client/ConsoleImpl.cpp
index f718cc8..0f68ea4 100644
--- a/src/VBox/Main/src-client/ConsoleImpl.cpp
+++ b/src/VBox/Main/src-client/ConsoleImpl.cpp
@@ -1126,7 +1126,8 @@ int Console::i_VRDPClientLogon(uint32_t u32ClientId, const char *pszUser, const
             LogRel(("AUTH: Delegated to guest.\n"));
 
             LogFlowFunc(("External auth asked for guest judgement\n"));
-        } /* pass through */
+        }
+        /* fall thru */
 
         case AuthType_Guest:
         {
@@ -2052,14 +2053,12 @@ HRESULT Console::setUseHostClipboard(BOOL aUseHostClipboard)
 
 HRESULT Console::powerUp(ComPtr<IProgress> &aProgress)
 {
-    i_powerUp(aProgress.asOutParam(), false /* aPaused */);
-    return S_OK;
+    return i_powerUp(aProgress.asOutParam(), false /* aPaused */);
 }
 
 HRESULT Console::powerUpPaused(ComPtr<IProgress> &aProgress)
 {
-    i_powerUp(aProgress.asOutParam(), true /* aPaused */);
-    return S_OK;
+    return i_powerUp(aProgress.asOutParam(), true /* aPaused */);
 }
 
 HRESULT Console::powerDown(ComPtr<IProgress> &aProgress)
diff --git a/src/VBox/Main/src-client/ConsoleImpl2.cpp b/src/VBox/Main/src-client/ConsoleImpl2.cpp
index 393064a..2d34211 100644
--- a/src/VBox/Main/src-client/ConsoleImpl2.cpp
+++ b/src/VBox/Main/src-client/ConsoleImpl2.cpp
@@ -9,7 +9,7 @@
  */
 
 /*
- * Copyright (C) 2006-2016 Oracle Corporation
+ * Copyright (C) 2006-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;
@@ -1079,6 +1079,20 @@ int Console::i_configConstructorInner(PUVM pUVM, PVM pVM, AutoWriteLock *pAlock)
             }
         }
 
+        /* Sanitize valid/useful APIC combinations, see @bugref{8868}. */
+        if (!fEnableAPIC)
+        {
+            if (fIsGuest64Bit)
+                return VMR3SetError(pUVM, VERR_INVALID_PARAMETER, RT_SRC_POS, N_("Cannot disable the APIC for a 64-bit guest."));
+            if (cCpus > 1)
+                return VMR3SetError(pUVM, VERR_INVALID_PARAMETER, RT_SRC_POS, N_("Cannot disable the APIC for an SMP guest."));
+            if (fIOAPIC)
+            {
+                return VMR3SetError(pUVM, VERR_INVALID_PARAMETER, RT_SRC_POS,
+                                    N_("Cannot disable the APIC when the I/O APIC is present."));
+            }
+        }
+
         BOOL fHMEnabled;
         hrc = pMachine->GetHWVirtExProperty(HWVirtExPropertyType_Enabled, &fHMEnabled);     H();
         if (cCpus > 1 && !fHMEnabled)
@@ -1788,15 +1802,17 @@ int Console::i_configConstructorInner(PUVM pUVM, PVM pVM, AutoWriteLock *pAlock)
             InsertConfigNode(pDev,     "0", &pInst);
             InsertConfigInteger(pInst, "Trusted", 1); /* boolean */
             InsertConfigNode(pInst,    "Config", &pCfg);
-            InsertConfigInteger(pCfg,  "NumCPUs",          cCpus);
-            InsertConfigString(pCfg,   "EfiRom",           efiRomFile);
-            InsertConfigString(pCfg,   "BootArgs",         bootArgs);
-            InsertConfigString(pCfg,   "DeviceProps",      deviceProps);
-            InsertConfigInteger(pCfg,  "IOAPIC",           fIOAPIC);
-            InsertConfigInteger(pCfg,  "APIC",             uFwAPIC);
+            InsertConfigInteger(pCfg,  "NumCPUs",     cCpus);
+            InsertConfigInteger(pCfg,  "McfgBase",    uMcfgBase);
+            InsertConfigInteger(pCfg,  "McfgLength",  cbMcfgLength);
+            InsertConfigString(pCfg,   "EfiRom",      efiRomFile);
+            InsertConfigString(pCfg,   "BootArgs",    bootArgs);
+            InsertConfigString(pCfg,   "DeviceProps", deviceProps);
+            InsertConfigInteger(pCfg,  "IOAPIC",      fIOAPIC);
+            InsertConfigInteger(pCfg,  "APIC",        uFwAPIC);
             InsertConfigBytes(pCfg,    "UUID", &HardwareUuid,sizeof(HardwareUuid));
-            InsertConfigInteger(pCfg,  "64BitEntry", f64BitEntry); /* boolean */
-            InsertConfigInteger(pCfg,  "GopMode", u32GopMode);
+            InsertConfigInteger(pCfg,  "64BitEntry",  f64BitEntry); /* boolean */
+            InsertConfigInteger(pCfg,  "GopMode",     u32GopMode);
             InsertConfigInteger(pCfg,  "UgaHorizontalResolution", u32UgaHorizontal);
             InsertConfigInteger(pCfg,  "UgaVerticalResolution", u32UgaVertical);
 
@@ -2947,17 +2963,21 @@ int Console::i_configConstructorInner(PUVM pUVM, PVM pVM, AutoWriteLock *pAlock)
             InsertConfigInteger(pCfg, "ObjectVRDPServer", (uintptr_t)mConsoleVRDPServer);
 #endif
 
-#ifdef VBOX_WITH_AUDIO_DEBUG
+#ifdef VBOX_WITH_AUDIO_VALIDATIONKIT
+            /*
+            * The ValidationKit backend driver.
+            */
             InsertConfigNode(pInst, "LUN#2", &pLunL1);
             InsertConfigString(pLunL1, "Driver", "AUDIO");
 
             InsertConfigNode(pLunL1, "AttachedDriver", &pLunL1);
-            InsertConfigString(pLunL1, "Driver", "DebugAudio");
+            InsertConfigString(pLunL1, "Driver", "ValidationKitAudio");
 
             InsertConfigNode(pLunL1, "Config", &pCfg);
-            InsertConfigString(pCfg, "AudioDriver", "DebugAudio");
+            InsertConfigString(pCfg, "AudioDriver", "ValidationKitAudio");
             InsertConfigString(pCfg, "StreamName", bstr);
-#endif
+#endif /* VBOX_WITH_AUDIO_VALIDATIONKIT */
+
             /** @todo Add audio video recording driver here. */
         }
 
@@ -5644,7 +5664,7 @@ int Console::i_configNetwork(const char *pszDevice,
             case NetworkAttachmentType_Generic:
             case NetworkAttachmentType_NATNetwork:
             {
-                if (SUCCEEDED(hrc) && SUCCEEDED(rc))
+                if (SUCCEEDED(hrc) && RT_SUCCESS(rc))
                 {
                     if (fAttachDetach)
                     {
diff --git a/src/VBox/Main/src-client/DisplayImpl.cpp b/src/VBox/Main/src-client/DisplayImpl.cpp
index 79cfcc6..ddb435d 100644
--- a/src/VBox/Main/src-client/DisplayImpl.cpp
+++ b/src/VBox/Main/src-client/DisplayImpl.cpp
@@ -1128,7 +1128,7 @@ int Display::i_handleDisplayResize(unsigned uScreenId, uint32_t bpp, void *pvVRA
     if (mfSeamlessEnabled)
         i_handleSetVisibleRegion(mcRectVisibleRegion, mpRectVisibleRegion);
 
-#ifdef VBOX_WITH_VIDEOREC
+#ifdef VBOX_WITH_VPX
     videoCaptureScreenChanged(uScreenId);
 #endif
 
diff --git a/src/VBox/Main/src-client/DrvAudioVRDE.cpp b/src/VBox/Main/src-client/DrvAudioVRDE.cpp
index c8c6c71..d204405 100644
--- a/src/VBox/Main/src-client/DrvAudioVRDE.cpp
+++ b/src/VBox/Main/src-client/DrvAudioVRDE.cpp
@@ -4,7 +4,7 @@
  */
 
 /*
- * Copyright (C) 2013-2015 Oracle Corporation
+ * Copyright (C) 2013-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;
@@ -211,7 +211,7 @@ static DECLCALLBACK(int) drvAudioVRDEPlayOut(PPDMIHOSTAUDIO pInterface, PPDMAUDI
     PVRDESTREAMOUT pVRDEStrmOut = (PVRDESTREAMOUT)pHstStrmOut;
     AssertPtrReturn(pVRDEStrmOut, VERR_INVALID_POINTER);
 
-    uint32_t live = AudioMixBufAvail(&pHstStrmOut->MixBuf);
+    uint32_t live = AudioMixBufLive(&pHstStrmOut->MixBuf);
     uint64_t now = PDMDrvHlpTMGetVirtualTime(pDrv->pDrvIns);
     uint64_t ticks = now  - pVRDEStrmOut->old_ticks;
     uint64_t ticks_per_second = PDMDrvHlpTMGetVirtualFreq(pDrv->pDrvIns);
@@ -238,30 +238,31 @@ static DECLCALLBACK(int) drvAudioVRDEPlayOut(PPDMIHOSTAUDIO pInterface, PPDMAUDI
                  pHstStrmOut->Props.cBits, pHstStrmOut->Props.fSigned,
                  format, cSamplesToSend));
 
+    int rc = VINF_SUCCESS;
+
     /*
      * Call the VRDP server with the data.
      */
     uint32_t cReadTotal = 0;
 
-    PPDMAUDIOSAMPLE pSamples;
-    uint32_t cRead;
-    int rc = AudioMixBufAcquire(&pHstStrmOut->MixBuf, cSamplesToSend,
-                                &pSamples, &cRead);
-    if (   RT_SUCCESS(rc)
-        && cRead)
+    PDMAUDIOSAMPLE aSamples[64];
+    while (cSamplesPlayed)
     {
-        cReadTotal = cRead;
-        pDrv->pConsoleVRDPServer->SendAudioSamples(pSamples, cRead, format);
-
-        if (rc == VINF_TRY_AGAIN)
+        uint32_t cRead;
+        rc = AudioMixBufPeek(&pHstStrmOut->MixBuf, cSamplesToSend,
+                            aSamples, RT_ELEMENTS(aSamples), &cRead);
+        if (   RT_SUCCESS(rc)
+            && cRead)
         {
-            rc = AudioMixBufAcquire(&pHstStrmOut->MixBuf, cSamplesToSend - cRead,
-                                    &pSamples, &cRead);
-            if (RT_SUCCESS(rc))
-                pDrv->pConsoleVRDPServer->SendAudioSamples(pSamples, cRead, format);
-
+            pDrv->pConsoleVRDPServer->SendAudioSamples(aSamples, cRead, format);
             cReadTotal += cRead;
         }
+
+        if (RT_FAILURE(rc))
+            break;
+
+        Assert(cSamplesPlayed >= cRead);
+        cSamplesPlayed -= cRead;
     }
 
     AudioMixBufFinish(&pHstStrmOut->MixBuf, cSamplesToSend);
diff --git a/src/VBox/Main/src-client/DrvAudioVideoRec.cpp b/src/VBox/Main/src-client/DrvAudioVideoRec.cpp
index 770970c..36c2c7e 100644
--- a/src/VBox/Main/src-client/DrvAudioVideoRec.cpp
+++ b/src/VBox/Main/src-client/DrvAudioVideoRec.cpp
@@ -129,7 +129,7 @@ static DECLCALLBACK(int) drvAudioVideoRecInit(PPDMIHOSTAUDIO pInterface)
 }
 
 /** @todo Replace this with drvAudioHlpPcmPropsFromCfg(). */
-static int drvAudioVideoRecPcmInitInfo(PDMPCMPROPS * pProps, PPDMAUDIOSTREAMCFG as)
+static int drvAudioVideoRecPcmInitInfo(PDMAUDIOPCMPROPS * pProps, PPDMAUDIOSTREAMCFG as)
 {
     int rc = VINF_SUCCESS;
 
diff --git a/src/VBox/Main/src-client/EmulatedUSBImpl.cpp b/src/VBox/Main/src-client/EmulatedUSBImpl.cpp
index 9794228..0b0d5f7 100644
--- a/src/VBox/Main/src-client/EmulatedUSBImpl.cpp
+++ b/src/VBox/Main/src-client/EmulatedUSBImpl.cpp
@@ -391,13 +391,16 @@ void EmulatedUSB::uninit()
     m.pConsole.setNull();
 
     AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
-    WebcamsMap::iterator it = m.webcams.begin();
-    while (it != m.webcams.end())
+    for (WebcamsMap::iterator it = m.webcams.begin(); it != m.webcams.end(); ++it)
     {
         EUSBWEBCAM *p = it->second;
-        m.webcams.erase(it++);
-        p->Release();
+        if (p)
+        {
+            it->second = NULL;
+            p->Release();
+        }
     }
+    m.webcams.clear();
     alock.release();
 
     /* Enclose the state transition Ready->InUninit->NotReady */
diff --git a/src/VBox/Main/src-client/GuestCtrlPrivate.cpp b/src/VBox/Main/src-client/GuestCtrlPrivate.cpp
index 7bbf4b5..a1a4bd2 100644
--- a/src/VBox/Main/src-client/GuestCtrlPrivate.cpp
+++ b/src/VBox/Main/src-client/GuestCtrlPrivate.cpp
@@ -4,7 +4,7 @@
  */
 
 /*
- * Copyright (C) 2011-2016 Oracle Corporation
+ * Copyright (C) 2011-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;
@@ -715,6 +715,21 @@ int GuestBase::registerWaitEvent(uint32_t uSessionID, uint32_t uObjectID,
     return registerWaitEvent(uSessionID, uObjectID, eventTypesEmpty, ppEvent);
 }
 
+/**
+ * Registers (creates) a new wait event based on a given session and object ID.
+ *
+ * From those IDs an unique context ID (CID) will be built, which only can be
+ * around once at a time.
+ *
+ * @returns IPRT status code. VERR_ALREADY_EXISTS if an event with the given session
+ *          and object ID already has been registered.
+ *
+ * @param   uSessionID              Session ID to register wait event for.
+ * @param   uObjectID               Object ID to register wait event for.
+ * @param   lstEvents               List of events to register the wait event for.
+ * @param   ppEvent                 Pointer to registered (created) wait event on success.
+ *                                  Must be destroyed with unregisterWaitEvent().
+ */
 int GuestBase::registerWaitEvent(uint32_t uSessionID, uint32_t uObjectID,
                                  const GuestEventTypes &lstEvents,
                                  GuestWaitEvent **ppEvent)
@@ -741,16 +756,34 @@ int GuestBase::registerWaitEvent(uint32_t uSessionID, uint32_t uObjectID,
             for (GuestEventTypes::const_iterator itEvents = lstEvents.begin();
                  itEvents != lstEvents.end(); ++itEvents)
             {
-                mWaitEventGroups[(*itEvents)].insert(
-                   std::pair<uint32_t, GuestWaitEvent*>(uContextID, pEvent));
-                /** @todo Check for key collision. */
+                /* Check if the event group already has an event with the same
+                 * context ID in it (collision). */
+                GuestWaitEvents eventGroup = mWaitEventGroups[(*itEvents)];
+                if (eventGroup.find(uContextID) == eventGroup.end())
+                {
+                    /* No, insert. */
+                    mWaitEventGroups[(*itEvents)].insert(std::pair<uint32_t, GuestWaitEvent *>(uContextID, pEvent));
+                }
+                else
+                {
+                    rc = VERR_ALREADY_EXISTS;
+                    break;
+                }
             }
 
-            /* Register event in regular event list. */
-            /** @todo Check for key collisions. */
-            mWaitEvents[uContextID] = pEvent;
+            if (RT_SUCCESS(rc))
+            {
+                /* Register event in regular event list. */
+                if (mWaitEvents.find(uContextID) == mWaitEvents.end())
+                {
+                    mWaitEvents[uContextID] = pEvent;
+                }
+                else
+                    rc  = VERR_ALREADY_EXISTS;
+            }
 
-            *ppEvent = pEvent;
+            if (RT_SUCCESS(rc))
+                *ppEvent = pEvent;
         }
         catch(std::bad_alloc &)
         {
@@ -820,7 +853,10 @@ int GuestBase::signalWaitEvent(VBoxEventType_T aType, IEvent *aEvent)
                     }
 
                     /* Remove the event from the passed-in event group. */
-                    itGroup->second.erase(itEvents++);
+                    GuestWaitEvents::iterator itEventsNext = itEvents;
+                    ++itEventsNext;
+                    itGroup->second.erase(itEvents);
+                    itEvents = itEventsNext;
                 }
                 else
                     ++itEvents;
@@ -859,57 +895,91 @@ int GuestBase::signalWaitEventInternalEx(PVBOXGUESTCTRLHOSTCBCTX pCbCtx,
     AssertPtrReturn(pCbCtx, VERR_INVALID_POINTER);
     /* pPayload is optional. */
 
-    int rc2;
-    GuestWaitEvents::iterator itEvent = mWaitEvents.find(pCbCtx->uContextID);
-    if (itEvent != mWaitEvents.end())
+    int rc2 = RTCritSectEnter(&mWaitEventCritSect);
+    if (RT_SUCCESS(rc2))
     {
-        LogFlowThisFunc(("Signalling event=%p (CID %RU32, rc=%Rrc, guestRc=%Rrc, pPayload=%p) ...\n",
-                         itEvent->second, itEvent->first, rc, guestRc, pPayload));
-        GuestWaitEvent *pEvent = itEvent->second;
-        AssertPtr(pEvent);
-        rc2 = pEvent->SignalInternal(rc, guestRc, pPayload);
+        GuestWaitEvents::iterator itEvent = mWaitEvents.find(pCbCtx->uContextID);
+        if (itEvent != mWaitEvents.end())
+        {
+            LogFlowThisFunc(("Signalling event=%p (CID %RU32, rc=%Rrc, guestRc=%Rrc, pPayload=%p) ...\n",
+                             itEvent->second, itEvent->first, rc, guestRc, pPayload));
+            GuestWaitEvent *pEvent = itEvent->second;
+            AssertPtr(pEvent);
+            rc2 = pEvent->SignalInternal(rc, guestRc, pPayload);
+        }
+        else
+            rc2 = VERR_NOT_FOUND;
+
+        int rc3 = RTCritSectLeave(&mWaitEventCritSect);
+        if (RT_SUCCESS(rc2))
+            rc2 = rc3;
     }
-    else
-        rc2 = VERR_NOT_FOUND;
 
     return rc2;
 }
 
-void GuestBase::unregisterWaitEvent(GuestWaitEvent *pEvent)
+/**
+ * Unregisters (deletes) a wait event.
+ *
+ * After successful unregistration the event will not be valid anymore.
+ *
+ * @returns IPRT status code.
+ * @param   pEvent                  Event to unregister (delete).
+ */
+int GuestBase::unregisterWaitEvent(GuestWaitEvent *pEvent)
 {
     if (!pEvent) /* Nothing to unregister. */
-        return;
+        return VINF_SUCCESS;
 
     int rc = RTCritSectEnter(&mWaitEventCritSect);
     if (RT_SUCCESS(rc))
     {
         LogFlowThisFunc(("pEvent=%p\n", pEvent));
 
-        const GuestEventTypes lstTypes = pEvent->Types();
-        for (GuestEventTypes::const_iterator itEvents = lstTypes.begin();
-             itEvents != lstTypes.end(); ++itEvents)
+        try
         {
-            /** @todo Slow O(n) lookup. Optimize this. */
-            GuestWaitEvents::iterator itCurEvent = mWaitEventGroups[(*itEvents)].begin();
-            while (itCurEvent != mWaitEventGroups[(*itEvents)].end())
+            /* Remove the event from all event type groups. */
+            const GuestEventTypes lstTypes = pEvent->Types();
+            for (GuestEventTypes::const_iterator itType = lstTypes.begin();
+                 itType != lstTypes.end(); ++itType)
             {
-                if (itCurEvent->second == pEvent)
+                /** @todo Slow O(n) lookup. Optimize this. */
+                GuestWaitEvents::iterator itCurEvent = mWaitEventGroups[(*itType)].begin();
+                while (itCurEvent != mWaitEventGroups[(*itType)].end())
                 {
-                    mWaitEventGroups[(*itEvents)].erase(itCurEvent++);
-                    break;
+                    if (itCurEvent->second == pEvent)
+                    {
+                        mWaitEventGroups[(*itType)].erase(itCurEvent);
+                        break;
+                    }
+                    else
+                        ++itCurEvent;
                 }
-                else
-                    ++itCurEvent;
             }
-        }
 
-        delete pEvent;
-        pEvent = NULL;
+            /* Remove the event from the general event list as well. */
+            GuestWaitEvents::iterator itEvent = mWaitEvents.find(pEvent->ContextID());
+
+            Assert(itEvent != mWaitEvents.end());
+            Assert(itEvent->second == pEvent);
+
+            mWaitEvents.erase(itEvent);
+
+            delete pEvent;
+            pEvent = NULL;
+        }
+        catch (const std::exception &ex)
+        {
+            NOREF(ex);
+            AssertFailedStmt(rc = VERR_NOT_FOUND);
+        }
 
         int rc2 = RTCritSectLeave(&mWaitEventCritSect);
         if (RT_SUCCESS(rc))
             rc = rc2;
     }
+
+    return rc;
 }
 
 /**
diff --git a/src/VBox/Main/src-client/VideoRec.cpp b/src/VBox/Main/src-client/VideoRec.cpp
index 5271c05..74906fa 100644
--- a/src/VBox/Main/src-client/VideoRec.cpp
+++ b/src/VBox/Main/src-client/VideoRec.cpp
@@ -508,11 +508,9 @@ int VideoRecStrmInit(PVIDEORECCONTEXT pCtx, uint32_t uScreen, const char *pszFil
     com::Utf8Str options(pszOptions);
     size_t pos = 0;
 
-    do {
-
-        com::Utf8Str key, value;
-        pos = options.parseKeyValue(key, value, pos);
-
+    com::Utf8Str key, value;
+    while ((pos = options.parseKeyValue(key, value, pos)) != com::Utf8Str::npos)
+    {
         if (key == "quality")
         {
             if (value == "realtime")
@@ -533,9 +531,9 @@ int VideoRecStrmInit(PVIDEORECCONTEXT pCtx, uint32_t uScreen, const char *pszFil
                 pStrm->uEncoderDeadline = value.toUInt32();
             }
         }
-        else LogRel(("Getting unknown option: %s=%s\n", key.c_str(), value.c_str()));
-
-    } while(pos != com::Utf8Str::npos);
+        else
+            LogRel(("VideoRec: Unknown option '%s' (value '%s'), skipping\n", key.c_str(), value.c_str()));
+    }
 
     /* target bitrate in kilobits per second */
     pStrm->VpxConfig.rc_target_bitrate = uRate;
diff --git a/src/VBox/Main/src-server/HostNetworkInterfaceImpl.cpp b/src/VBox/Main/src-server/HostNetworkInterfaceImpl.cpp
index 120d1df..0d1058f 100644
--- a/src/VBox/Main/src-server/HostNetworkInterfaceImpl.cpp
+++ b/src/VBox/Main/src-server/HostNetworkInterfaceImpl.cpp
@@ -160,11 +160,14 @@ HRESULT HostNetworkInterface::updateConfig()
     int rc = NetIfGetConfig(this, &info);
     if (RT_SUCCESS(rc))
     {
+        int iPrefixIPv6;
+
         m.realIPAddress = m.IPAddress = info.IPAddress.u;
         m.realNetworkMask = m.networkMask = info.IPNetMask.u;
         m.dhcpEnabled = info.bDhcpEnabled;
         m.realIPV6Address = m.IPV6Address = composeIPv6Address(&info.IPv6Address);
-        m.realIPV6PrefixLength = m.IPV6NetworkMaskPrefixLength = composeIPv6PrefixLenghFromAddress(&info.IPv6NetMask);
+        RTNetMaskToPrefixIPv6(&info.IPv6NetMask, &iPrefixIPv6);
+        m.realIPV6PrefixLength = m.IPV6NetworkMaskPrefixLength = iPrefixIPv6;
         m.hardwareAddress = composeHardwareAddress(&info.MACAddress);
 #ifdef RT_OS_WINDOWS
         m.mediumType = (HostNetworkInterfaceMediumType)info.enmMediumType;
@@ -217,10 +220,13 @@ HRESULT HostNetworkInterface::init(Bstr aInterfaceName, HostNetworkInterfaceType
     }
     mIfType = ifType;
 
+    int iPrefixIPv6;
+
     m.realIPAddress = m.IPAddress = pIf->IPAddress.u;
     m.realNetworkMask = m.networkMask = pIf->IPNetMask.u;
     m.realIPV6Address = m.IPV6Address = composeIPv6Address(&pIf->IPv6Address);
-    m.realIPV6PrefixLength = m.IPV6NetworkMaskPrefixLength = composeIPv6PrefixLenghFromAddress(&pIf->IPv6NetMask);
+    RTNetMaskToPrefixIPv6(&pIf->IPv6NetMask, &iPrefixIPv6);
+    m.realIPV6PrefixLength = m.IPV6NetworkMaskPrefixLength = iPrefixIPv6;
     m.dhcpEnabled = pIf->bDhcpEnabled;
     m.hardwareAddress = composeHardwareAddress(&pIf->MACAddress);
 #ifdef RT_OS_WINDOWS
diff --git a/src/VBox/Main/src-server/HostUSBDeviceImpl.cpp b/src/VBox/Main/src-server/HostUSBDeviceImpl.cpp
index 2815ab5..56f827a 100644
--- a/src/VBox/Main/src-server/HostUSBDeviceImpl.cpp
+++ b/src/VBox/Main/src-server/HostUSBDeviceImpl.cpp
@@ -367,7 +367,7 @@ com::Utf8Str HostUSBDevice::i_getName()
                                                    : strProduct.c_str());
         else
         {
-            LogRel(("USB: Unknown USB device detected (idVendor: 0x%04x, idProduct: 0x%04x). Please, report the idVendor and idProduct to virtualbox.org.\n",
+            LogRel(("USB: Unknown USB device detected (idVendor: 0x%04x, idProduct: 0x%04x)\n",
                     mUsb->idVendor, mUsb->idProduct));
             if (strVendor.isNotEmpty())
                 name = strVendor;
@@ -1292,6 +1292,7 @@ bool HostUSBDevice::i_updateState(PCUSBDEVICE aDev, bool *aRunFilters, SessionMa
                     /* Changed! */
                     case kHostUSBDeviceState_UsedByHost:
                         fIsImportant = true;
+                        /* fall thru */
                     case kHostUSBDeviceState_Unused:
                         LogThisFunc(("{%s} %s -> %s\n", mName, i_getStateName(), i_stateName(kHostUSBDeviceState_Capturable)));
                         *aRunFilters = i_setState(kHostUSBDeviceState_Capturable);
diff --git a/src/VBox/Main/src-server/MachineImpl.cpp b/src/VBox/Main/src-server/MachineImpl.cpp
index 320c569..b64d981 100644
--- a/src/VBox/Main/src-server/MachineImpl.cpp
+++ b/src/VBox/Main/src-server/MachineImpl.cpp
@@ -5341,9 +5341,9 @@ void Machine::i_deleteConfigHandler(DeleteConfigTask &task)
                 AutoCaller mac(pMedium);
                 if (FAILED(mac.rc())) throw mac.rc();
                 Utf8Str strLocation = pMedium->i_getLocationFull();
+                LogFunc(("Deleting file %s\n", strLocation.c_str()));
                 rc = task.m_pProgress->SetNextOperation(BstrFmt(tr("Deleting '%s'"), strLocation.c_str()).raw(), 1);
                 if (FAILED(rc)) throw rc;
-                LogFunc(("Deleting file %s\n", strLocation.c_str()));
             }
             if (pMedium->i_isMediumFormatFile())
             {
@@ -5514,8 +5514,8 @@ HRESULT Machine::deleteConfig(const std::vector<ComPtr<IMedium> > &aMedia, ComPt
                          static_cast<IMachine*>(this) /* aInitiator */,
                          Bstr(tr("Deleting files")).raw(),
                          true /* fCancellable */,
-                         (ULONG)(llFilesToDelete.size() + llMediums.size() + 1),   // cOperations
-                         BstrFmt(tr("Deleting '%s'"), llFilesToDelete.front().c_str()).raw());
+                         (ULONG)(1 + llMediums.size() + llFilesToDelete.size() + 1),    // cOperations
+                         Bstr(tr("Collecting file inventory")).raw());
     if (FAILED(rc))
         return rc;
 
@@ -9049,7 +9049,10 @@ HRESULT Machine::i_loadHardware(const Guid *puuidRegistry,
             if (FAILED(rc)) return rc;
         }
 
-        // serial ports
+        // serial ports (establish defaults first, to ensure reading the same
+        // settings as we saved, since the list skips ports having defaults)
+        for (unsigned i = 0; i < RT_ELEMENTS(mSerialPorts); i++)
+            mSerialPorts[i]->i_applyDefaults(NULL);
         for (settings::SerialPortsList::const_iterator it = data.llSerialPorts.begin();
             it != data.llSerialPorts.end();
             ++it)
@@ -9061,7 +9064,10 @@ HRESULT Machine::i_loadHardware(const Guid *puuidRegistry,
             if (FAILED(rc)) return rc;
         }
 
-        // parallel ports (optional)
+        // parallel ports (establish defaults first, to ensure reading the same
+        // settings as we saved, since the list skips ports having defaults)
+        for (unsigned i = 0; i < RT_ELEMENTS(mParallelPorts); i++)
+            mParallelPorts[i]->i_applyDefaults();
         for (settings::ParallelPortsList::const_iterator it = data.llParallelPorts.begin();
             it != data.llParallelPorts.end();
             ++it)
@@ -9849,7 +9855,10 @@ HRESULT Machine::i_prepareSaveSettings(bool *pfNeedsGlobalSaveSettings)
 
             // in the saved state file path, replace the old directory with the new directory
             if (RTPathStartsWith(mSSData->strStateFilePath.c_str(), configDir.c_str()))
-                mSSData->strStateFilePath = newConfigDir.append(mSSData->strStateFilePath.c_str() + configDir.length());
+            {
+                Utf8Str strStateFileName = mSSData->strStateFilePath.c_str() + configDir.length();
+                mSSData->strStateFilePath = newConfigDir + strStateFileName;
+            }
 
             // and do the same thing for the saved state file paths of all the online snapshots
             if (mData->mFirstSnapshot)
diff --git a/src/VBox/Main/src-server/MediumImpl.cpp b/src/VBox/Main/src-server/MediumImpl.cpp
index 9e83858..da454e6 100644
--- a/src/VBox/Main/src-server/MediumImpl.cpp
+++ b/src/VBox/Main/src-server/MediumImpl.cpp
@@ -2984,9 +2984,9 @@ HRESULT Medium::setLocation(const com::Utf8Str &aLocation, ComPtr<IProgress> &aP
 
         /* play with locations */
         {
-            /*get source path and filename */
-            Utf8Str sourceMediumPath = i_getLocationFull();
-            Utf8Str sourceMediumFileName = i_getName();
+            /* get source path and filename */
+            Utf8Str sourcePath = i_getLocationFull();
+            Utf8Str sourceFName = i_getName();
 
             if (aLocation.isEmpty())
             {
@@ -2996,63 +2996,57 @@ HRESULT Medium::setLocation(const com::Utf8Str &aLocation, ComPtr<IProgress> &aP
                 throw rc;
             }
 
-            /*extract destination path and filename */
-            Utf8Str destMediumPath(aLocation);
-            Utf8Str destMediumFileName(destMediumPath);
-            destMediumFileName.stripPath();
+            /* extract destination path and filename */
+            Utf8Str destPath(aLocation);
+            Utf8Str destFName(destPath);
+            destFName.stripPath();
 
-            Utf8Str suffix(destMediumFileName);
-            suffix.stripSuffix();//for small trick, see next condition
+            Utf8Str suffix(destFName);
+            suffix.stripSuffix();
 
-            if(suffix.equals(destMediumFileName) && !destMediumFileName.isEmpty())
+            if (suffix.equals(destFName) && !destFName.isEmpty())
             {
                 /*
-                 * small trick. This case means target path has no filename at the end.
-                 * it will look like "/path/to/new/location" or just "newname"
-                 * there is no backslash in the end
-                 * or there is no filename with extension(suffix) in the end
+                 * The target path has no filename: Either "/path/to/new/location" or
+                 * just "newname" (no trailing backslash or there is no filename with
+                 * extension(suffix)).
                  */
-
-                /* case when new path contains only "newname", no path, no extension */
-                if (destMediumPath.equals(destMediumFileName))
+                if (destPath.equals(destFName))
                 {
-                    Utf8Str localSuffix = RTPathSuffix(sourceMediumFileName.c_str());
-                    destMediumFileName.append(localSuffix);
-                    destMediumPath = destMediumFileName;
+                    /* new path contains only "newname", no path, no extension */
+                    destFName.append(RTPathSuffix(sourceFName.c_str()));
+                    destPath = destFName;
                 }
-                /* case when new path looks like "/path/to/new/location"
-                 * In this case just set destMediumFileName to NULL and
-                 * and add '/' in the end of path.destMediumPath
-                 */
                 else
                 {
-                    destMediumFileName.setNull();
-                    destMediumPath.append(RTPATH_SLASH);
+                    /* new path looks like "/path/to/new/location" */
+                    destFName.setNull();
+                    destPath.append(RTPATH_SLASH);
                 }
             }
 
-            if (destMediumFileName.isEmpty())
+            if (destFName.isEmpty())
             {
-                /* case when a target name is absent */
-                destMediumPath.append(sourceMediumFileName);
+                /* No target name */
+                destPath.append(sourceFName);
             }
             else
             {
-                if (destMediumPath.equals(destMediumFileName))
+                if (destPath.equals(destFName))
                 {
-                    /* the passed target path consist of only a filename without directory
-                     * next move medium within the source directory with the passed new name
+                    /*
+                     * The target path contains of only a filename without a directory.
+                     * Move the medium within the source directory to the new name
+                     * (actually rename operation).
+                     * Scratches sourcePath!
                      */
-                    destMediumPath = sourceMediumPath.stripFilename().append(RTPATH_SLASH).append(destMediumFileName);
+                    destPath = sourcePath.stripFilename().append(RTPATH_SLASH).append(destFName);
                 }
                 suffix = i_getFormat();
-
                 if (suffix.compare("RAW", Utf8Str::CaseInsensitive) == 0)
                 {
-                    if(i_getDeviceType() == DeviceType_DVD)
-                    {
+                    if (i_getDeviceType() == DeviceType_DVD)
                         suffix = "iso";
-                    }
                     else
                     {
                         rc = setError(VERR_NOT_A_FILE,
@@ -3061,28 +3055,33 @@ HRESULT Medium::setLocation(const com::Utf8Str &aLocation, ComPtr<IProgress> &aP
                         throw rc;
                     }
                 }
-                /* set the target extension like on the source. Any conversions are prohibited */
+                /* Set the target extension like on the source. Any conversions are prohibited */
                 suffix.toLower();
-                destMediumPath.stripSuffix().append('.').append(suffix);
+                destPath.stripSuffix().append('.').append(suffix);
             }
 
-            if (i_isMediumFormatFile())
+            if (!i_isMediumFormatFile())
             {
-                /* Check path for a new file object */
-                rc = VirtualBox::i_ensureFilePathExists(destMediumPath, true);
-                if (FAILED(rc))
-                    throw rc;
+                rc = setError(VERR_NOT_A_FILE,
+                              tr("Medium '%s' isn't a file object. \"Move\" operation isn't supported."),
+                              i_getLocationFull().c_str());
+                throw rc;
             }
-            else
+            /* Path must be absolute */
+            if (!RTPathStartsWithRoot(destPath.c_str()))
             {
-                rc = setError(VERR_NOT_A_FILE,
-                           tr("Medium '%s' isn't a file object. \"Move\" operation isn't supported."),
-                           i_getLocationFull().c_str());
+                rc = setError(VBOX_E_FILE_ERROR,
+                              tr("The given path '%s' is not fully qualified"),
+                              destPath.c_str());
                 throw rc;
             }
+            /* Check path for a new file object */
+            rc = VirtualBox::i_ensureFilePathExists(destPath, true);
+            if (FAILED(rc))
+                throw rc;
 
             /* Set needed variables for "moving" procedure. It'll be used later in separate thread task */
-            rc = i_preparationForMoving(destMediumPath);
+            rc = i_preparationForMoving(destPath);
             if (FAILED(rc))
             {
                 rc = setError(VERR_NO_CHANGE,
@@ -3119,8 +3118,7 @@ HRESULT Medium::setLocation(const com::Utf8Str &aLocation, ComPtr<IProgress> &aP
                 if (ses)
                 {
                     rc = setError(VERR_VM_UNEXPECTED_VM_STATE,
-                                  tr("At least VM '%s' to whom this medium '%s' attached has the opened session now. "
-                                     "Stop all needed VM before set a new location."),
+                                  tr("At least the VM '%s' to whom this medium '%s' attached has currently an opened session. Stop all VMs before relocating this medium"),
                                   id.toString().c_str(),
                                   i_getLocationFull().c_str());
                     throw rc;
@@ -3189,7 +3187,7 @@ HRESULT Medium::setLocation(const com::Utf8Str &aLocation, ComPtr<IProgress> &aP
     }
     else
     {
-        if (pTask != NULL)
+        if (pTask)
             delete pTask;
     }
 
@@ -6431,7 +6429,7 @@ bool Medium::i_resetMoveOperationData()
 
 Utf8Str Medium::i_getNewLocationForMoving() const
 {
-    if(m->fMoveThisMedium == true)
+    if (m->fMoveThisMedium == true)
         return m->strNewLocationFull;
     else
         return Utf8Str();
@@ -8046,7 +8044,7 @@ HRESULT Medium::i_taskCreateDiffHandler(Medium::CreateDiffTask &task)
             vrc = VDCreateDiff(hdd,
                                targetFormat.c_str(),
                                targetLocation.c_str(),
-                               (task.mVariant & ~MediumVariant_NoCreateDir) | VD_IMAGE_FLAGS_DIFF,
+                               (task.mVariant & ~(MediumVariant_NoCreateDir | MediumVariant_VmdkESX)) | VD_IMAGE_FLAGS_DIFF,
                                NULL,
                                targetId.raw(),
                                id.raw(),
diff --git a/src/VBox/Main/src-server/MediumLock.cpp b/src/VBox/Main/src-server/MediumLock.cpp
index 2376ade..eff607d 100644
--- a/src/VBox/Main/src-server/MediumLock.cpp
+++ b/src/VBox/Main/src-server/MediumLock.cpp
@@ -323,13 +323,12 @@ HRESULT MediumLockListMap::Clear()
     HRESULT rc = Unlock();
     for (MediumLockListMap::Base::iterator it = mMediumLocks.begin();
          it != mMediumLocks.end();
-         )
+         ++it)
     {
         MediumLockList *pMediumLockList = it->second;
-        // need an incremented iterator as otherwise erasing invalidates it
-        mMediumLocks.erase(it++);
         delete pMediumLockList;
     }
+    mMediumLocks.clear();
     return rc;
 }
 
diff --git a/src/VBox/Main/src-server/NetworkAdapterImpl.cpp b/src/VBox/Main/src-server/NetworkAdapterImpl.cpp
index 0d3b58b..3436b83 100644
--- a/src/VBox/Main/src-server/NetworkAdapterImpl.cpp
+++ b/src/VBox/Main/src-server/NetworkAdapterImpl.cpp
@@ -454,7 +454,7 @@ HRESULT NetworkAdapter::setAttachmentType(NetworkAttachmentType_T aAttachmentTyp
         mlock.release();
 
         if (oldAttachmentType == NetworkAttachmentType_NATNetwork)
-            i_checkAndSwitchFromNatNetworking(mData->strNATNetworkName);
+            i_switchFromNatNetworking(mData->strNATNetworkName);
 
         if (aAttachmentType == NetworkAttachmentType_NATNetwork)
             i_switchToNatNetworking(mData->strNATNetworkName);
@@ -483,11 +483,33 @@ HRESULT NetworkAdapter::setBridgedInterface(const com::Utf8Str &aBridgedInterfac
 
     AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
 
-    if (mData->strBridgedName != aBridgedInterface)
+    Bstr canonicalName = aBridgedInterface;
+#ifdef RT_OS_DARWIN
+    com::SafeIfaceArray<IHostNetworkInterface> hostNetworkInterfaces;
+    ComPtr<IHost> host;
+    HRESULT rc = mParent->i_getVirtualBox()->COMGETTER(Host)(host.asOutParam());
+    if (SUCCEEDED(rc))
+    {
+        host->FindHostNetworkInterfacesOfType(HostNetworkInterfaceType_Bridged,
+                                              ComSafeArrayAsOutParam(hostNetworkInterfaces));
+        for (size_t i = 0; i < hostNetworkInterfaces.size(); ++i)
+        {
+            Bstr shortName;
+            ComPtr<IHostNetworkInterface> ni = hostNetworkInterfaces[i];
+            ni->COMGETTER(ShortName)(shortName.asOutParam());
+            if (shortName == aBridgedInterface)
+            {
+                ni->COMGETTER(Name)(canonicalName.asOutParam());
+                break;
+            }
+        }
+    }
+#endif /* RT_OS_DARWIN */
+    if (Bstr(mData->strBridgedName) != canonicalName)
     {
         /* if an empty/null string is to be set, bridged interface must be
          * turned off */
-        if (aBridgedInterface.isEmpty()
+        if (canonicalName.isEmpty()
             && mData->mode == NetworkAttachmentType_Bridged)
         {
             return setError(E_FAIL,
@@ -495,7 +517,7 @@ HRESULT NetworkAdapter::setBridgedInterface(const com::Utf8Str &aBridgedInterfac
         }
 
         mData.backup();
-        mData->strBridgedName = aBridgedInterface;
+        mData->strBridgedName = canonicalName;
 
         // leave the lock before informing callbacks
         alock.release();
@@ -644,9 +666,13 @@ HRESULT NetworkAdapter::setNATNetwork(const com::Utf8Str &aNATNetwork)
         AutoWriteLock mlock(mParent COMMA_LOCKVAL_SRC_POS);       // mParent is const, no need to lock
         mParent->i_setModified(Machine::IsModified_NetworkAdapters);
         mlock.release();
-        i_checkAndSwitchFromNatNetworking(oldNatNetworkName.raw());
 
-        i_switchToNatNetworking(aNATNetwork);
+        if (mData->mode == NetworkAttachmentType_NATNetwork)
+        {
+            i_switchFromNatNetworking(oldNatNetworkName.raw());
+            i_switchToNatNetworking(aNATNetwork);
+        }
+
         /* When changing the host adapter, adapt the CFGM logic to make this
          * change immediately effect and to notify the guest that the network
          * might have changed, therefore changeAdapter=TRUE. */
@@ -1334,7 +1360,7 @@ void NetworkAdapter::i_updateBandwidthGroup(BandwidthGroup *aBwGroup)
 }
 
 
-HRESULT NetworkAdapter::i_checkAndSwitchFromNatNetworking(com::Utf8Str networkName)
+HRESULT NetworkAdapter::i_switchFromNatNetworking(const com::Utf8Str &networkName)
 {
     HRESULT hrc;
     MachineState_T state;
diff --git a/src/VBox/Main/src-server/ParallelPortImpl.cpp b/src/VBox/Main/src-server/ParallelPortImpl.cpp
index 22d3a9e..0655e56 100644
--- a/src/VBox/Main/src-server/ParallelPortImpl.cpp
+++ b/src/VBox/Main/src-server/ParallelPortImpl.cpp
@@ -488,7 +488,10 @@ void ParallelPort::i_copyFrom(ParallelPort *aThat)
 }
 
 /**
- * Applies the defaults for the given parallel port.
+ * Applies the defaults for this parallel port.
+ *
+ * @note This method currently assumes that the object is in the state after
+ * calling init(), it does not set defaults from an arbitrary state.
  */
 void ParallelPort::i_applyDefaults()
 {
diff --git a/src/VBox/Main/src-server/SerialPortImpl.cpp b/src/VBox/Main/src-server/SerialPortImpl.cpp
index e3d9003..5d39a9e 100644
--- a/src/VBox/Main/src-server/SerialPortImpl.cpp
+++ b/src/VBox/Main/src-server/SerialPortImpl.cpp
@@ -610,10 +610,14 @@ void SerialPort::i_copyFrom(SerialPort *aThat)
     m->bd.assignCopy(aThat->m->bd);
 }
 
+/**
+ * Applies the defaults for this serial port.
+ *
+ * @note This method currently assumes that the object is in the state after
+ * calling init(), it does not set defaults from an arbitrary state.
+ */
 void SerialPort::i_applyDefaults(GuestOSType *aOsType)
 {
-    AssertReturnVoid(aOsType != NULL);
-
     /* sanity */
     AutoCaller autoCaller(this);
     AssertComRCReturnVoid(autoCaller.rc());
@@ -652,7 +656,9 @@ void SerialPort::i_applyDefaults(GuestOSType *aOsType)
             break;
     }
 
-    uint32_t numSerialEnabled = aOsType->i_numSerialEnabled();
+    uint32_t numSerialEnabled = 0;
+    if (aOsType)
+        numSerialEnabled = aOsType->i_numSerialEnabled();
 
     /* Enable port if requested */
     if (m->bd->ulSlot < numSerialEnabled)
diff --git a/src/VBox/Main/src-server/USBIdDatabaseGenerator.cpp b/src/VBox/Main/src-server/USBIdDatabaseGenerator.cpp
index 1767beb..0f8a85a 100644
--- a/src/VBox/Main/src-server/USBIdDatabaseGenerator.cpp
+++ b/src/VBox/Main/src-server/USBIdDatabaseGenerator.cpp
@@ -1,4 +1,4 @@
-/* $Id: USBIdDatabaseGenerator.cpp 105633 2016-02-20 16:51:52Z fmehnert $ */
+/* $Id: USBIdDatabaseGenerator.cpp $ */
 /** @file
  * USB device vendor and product ID database - generator.
  */
diff --git a/src/VBox/Main/src-server/linux/NetIf-linux.cpp b/src/VBox/Main/src-server/linux/NetIf-linux.cpp
index 613a4ca..ed86d4b 100644
--- a/src/VBox/Main/src-server/linux/NetIf-linux.cpp
+++ b/src/VBox/Main/src-server/linux/NetIf-linux.cpp
@@ -193,7 +193,7 @@ static int getInterfaceInfo(int iSocket, const char *pszName, PNETIFINFO pInfo)
                     pInfo->IPv6Address.au32[1] = htonl(IPv6Address.au32[1]);
                     pInfo->IPv6Address.au32[2] = htonl(IPv6Address.au32[2]);
                     pInfo->IPv6Address.au32[3] = htonl(IPv6Address.au32[3]);
-                    ASMBitSetRange(&pInfo->IPv6NetMask, 0, uLength);
+                    RTNetPrefixToMaskIPv6(uLength, &pInfo->IPv6NetMask);
                 }
             }
             fclose(fp);
diff --git a/src/VBox/Main/src-server/win/NetIf-win.cpp b/src/VBox/Main/src-server/win/NetIf-win.cpp
index 8588cc3..b1c594a 100644
--- a/src/VBox/Main/src-server/win/NetIf-win.cpp
+++ b/src/VBox/Main/src-server/win/NetIf-win.cpp
@@ -24,7 +24,6 @@
 
 #define NETIF_WITHOUT_NETCFG
 
-#include <iprt/asm.h>
 #include <iprt/err.h>
 #include <list>
 
@@ -167,11 +166,11 @@ static int collectNetIfInfo(Bstr &strName, Guid &guid, PNETIFINFO pInfo, int iDe
                                     if (pPrefix->PrefixLength <= sizeof(pInfo->IPNetMask) * 8)
                                     {
                                         fIPFound = true;
-                                        ASMBitSetRange(&pInfo->IPNetMask, 0, pPrefix->PrefixLength);
+                                        RTNetPrefixToMaskIPv4(pPrefix->PrefixLength, &pInfo->IPNetMask);
                                     }
                                     else
-                                        Log(("collectNetIfInfo: Unexpected IPv4 prefix length of %d\n",
-                                             pPrefix->PrefixLength));
+                                        LogFunc(("Unexpected IPv4 prefix length of %d\n",
+                                                 pPrefix->PrefixLength));
                                 }
                                 break;
                             case AF_INET6:
@@ -180,17 +179,17 @@ static int collectNetIfInfo(Bstr &strName, Guid &guid, PNETIFINFO pInfo, int iDe
                                     if (pPrefix->PrefixLength <= sizeof(pInfo->IPv6NetMask) * 8)
                                     {
                                         fIPv6Found = true;
-                                        ASMBitSetRange(&pInfo->IPv6NetMask, 0, pPrefix->PrefixLength);
+                                        RTNetPrefixToMaskIPv6(pPrefix->PrefixLength, &pInfo->IPv6NetMask);
                                     }
                                     else
-                                        Log(("collectNetIfInfo: Unexpected IPv6 prefix length of %d\n",
-                                             pPrefix->PrefixLength));
+                                        LogFunc(("Unexpected IPv6 prefix length of %d\n",
+                                                pPrefix->PrefixLength));
                                 }
                                 break;
                         }
                     }
                     if (sizeof(pInfo->MACAddress) != pAdapter->PhysicalAddressLength)
-                        Log(("collectNetIfInfo: Unexpected physical address length: %u\n", pAdapter->PhysicalAddressLength));
+                        LogFunc(("Unexpected physical address length: %u\n", pAdapter->PhysicalAddressLength));
                     else
                         memcpy(pInfo->MACAddress.au8, pAdapter->PhysicalAddress, sizeof(pInfo->MACAddress));
                     pInfo->enmMediumType = NETIF_T_ETHERNET;
@@ -986,8 +985,8 @@ static int vboxNetWinAddComponent(std::list<ComObjPtr<HostNetworkInterface> > *
             Info.Uuid = *guidIfCopy.raw();
             rc = collectNetIfInfo(name, guidIfCopy, &Info, iDefaultInterface);
             if (RT_FAILURE(rc))
-                LogRel(("vboxNetWinAddComponent: collectNetIfInfo() -> %Rrc\n", rc));
-            Log(("vboxNetWinAddComponent: adding %ls\n", lpszName));
+                LogRelFunc(("collectNetIfInfo() -> %Rrc\n", rc));
+            LogFunc(("adding %ls\n", lpszName));
             /* create a new object and add it to the list */
             ComObjPtr<HostNetworkInterface> iface;
             iface.createObject();
@@ -1002,16 +1001,16 @@ static int vboxNetWinAddComponent(std::list<ComObjPtr<HostNetworkInterface> > *
             }
             else
             {
-                LogRel(("vboxNetWinAddComponent: HostNetworkInterface::init() -> %Rrc\n", rc));
-                Assert(0);
+                LogRelFunc(("HostNetworkInterface::init() -> %Rrc\n", rc));
+                AssertComRC(rc);
             }
         }
         else
-            LogRel(("vboxNetWinAddComponent: failed to get device instance GUID (0x%x)\n", hr));
+            LogRelFunc(("failed to get device instance GUID (0x%x)\n", hr));
         CoTaskMemFree(lpszName);
     }
     else
-        LogRel(("vboxNetWinAddComponent: failed to get device display name (0x%x)\n", hr));
+        LogRelFunc(("failed to get device display name (0x%x)\n", hr));
 
     return rc;
 }
@@ -1038,9 +1037,9 @@ static int netIfListHostAdapters(INetCfg *pNc, std::list<ComObjPtr<HostNetworkIn
             ULONG uComponentStatus;
             hr = pMpNcc->GetDisplayName(&pwszName);
             if (hr == S_OK)
-                Log(("netIfListHostAdapters: %ls\n", pwszName));
+                LogFunc(("%ls\n", pwszName));
             else
-                LogRel(("netIfListHostAdapters: failed to get device display name (0x%x)\n", hr));
+                LogRelFunc(("failed to get device display name (0x%x)\n", hr));
             hr = pMpNcc->GetDeviceStatus(&uComponentStatus);
             if (hr == S_OK)
             {
@@ -1051,7 +1050,7 @@ static int netIfListHostAdapters(INetCfg *pNc, std::list<ComObjPtr<HostNetworkIn
                     Assert(hr == S_OK);
                     if (hr == S_OK)
                     {
-                        Log(("netIfListHostAdapters: id = %ls\n", pId));
+                        LogFunc(("id = %ls\n", pId));
                         if (!_wcsnicmp(pId, L"sun_VBoxNetAdp", sizeof(L"sun_VBoxNetAdp")/2))
                         {
                             vboxNetWinAddComponent(&list, pMpNcc, HostNetworkInterfaceType_HostOnly, -1);
@@ -1059,11 +1058,11 @@ static int netIfListHostAdapters(INetCfg *pNc, std::list<ComObjPtr<HostNetworkIn
                         CoTaskMemFree(pId);
                     }
                     else
-                        LogRel(("netIfListHostAdapters: failed to get device id (0x%x)\n", hr));
+                        LogRelFunc(("failed to get device id (0x%x)\n", hr));
                 }
             }
             else
-                LogRel(("netIfListHostAdapters: failed to get device status (0x%x)\n", hr));
+                LogRelFunc(("failed to get device status (0x%x)\n", hr));
             pMpNcc->Release();
         }
         Assert(hr == S_OK || hr == S_FALSE);
@@ -1071,7 +1070,7 @@ static int netIfListHostAdapters(INetCfg *pNc, std::list<ComObjPtr<HostNetworkIn
         pEnumComponent->Release();
     }
     else
-        LogRel(("netIfListHostAdapters: EnumComponents error (0x%x)\n", hr));
+        LogRelFunc(("EnumComponents error (0x%x)\n", hr));
 #endif /* #  if defined VBOX_WITH_NETFLT */
     return VINF_SUCCESS;
 }
@@ -1452,7 +1451,7 @@ int NetIfDhcpRediscover(VirtualBox *vBox, HostNetworkInterface * pIf)
 }
 
 
-#define netIfLog Log
+#define netIfLog LogFunc
 
 struct BoundAdapter
 {
@@ -1469,7 +1468,7 @@ static int netIfGetUnboundHostOnlyAdapters(INetCfg *pNetCfg, std::list<BoundAdap
     IEnumNetCfgComponent  *pEnumComponent;
 
     if ((hr = pNetCfg->EnumComponents(&GUID_DEVCLASS_NET, &pEnumComponent)) != S_OK)
-        LogRel(("netIfGetUnboundHostOnlyAdapters: failed to enumerate network adapter components (0x%x)\n", hr));
+        LogRelFunc(("failed to enumerate network adapter components (0x%x)\n", hr));
     else
     {
         while ((hr = pEnumComponent->Next(1, &pMiniport, NULL)) == S_OK)
@@ -1479,21 +1478,21 @@ static int netIfGetUnboundHostOnlyAdapters(INetCfg *pNetCfg, std::list<BoundAdap
             struct BoundAdapter adapter;
             memset(&adapter, 0, sizeof(adapter));
             if ((hr = pMiniport->GetDisplayName(&adapter.pName)) != S_OK)
-                LogRel(("netIfGetUnboundHostOnlyAdapters: failed to get device display name (0x%x)\n", hr));
+                LogRelFunc(("failed to get device display name (0x%x)\n", hr));
             else if ((hr = pMiniport->GetDeviceStatus(&uComponentStatus)) != S_OK)
-                netIfLog(("netIfGetUnboundHostOnlyAdapters: failed to get device status (0x%x)\n", hr));
+                netIfLog(("failed to get device status (0x%x)\n", hr));
             else if (uComponentStatus != 0)
-                netIfLog(("netIfGetUnboundHostOnlyAdapters: wrong device status (0x%x)\n", uComponentStatus));
+                netIfLog(("wrong device status (0x%x)\n", uComponentStatus));
             else if ((hr = pMiniport->GetId(&adapter.pHwId)) != S_OK)
-                LogRel(("netIfGetUnboundHostOnlyAdapters: failed to get device id (0x%x)\n", hr));
+                LogRelFunc(("failed to get device id (0x%x)\n", hr));
             else if (_wcsnicmp(adapter.pHwId, L"sun_VBoxNetAdp", sizeof(L"sun_VBoxNetAdp")/2))
-                netIfLog(("netIfGetUnboundHostOnlyAdapters: not host-only id = %ls, ignored\n", adapter.pHwId));
+                netIfLog(("not host-only id = %ls, ignored\n", adapter.pHwId));
             else if ((hr = pMiniport->GetInstanceGuid(&guid)) != S_OK)
-                LogRel(("netIfGetUnboundHostOnlyAdapters: failed to get instance id (0x%x)\n", hr));
+                LogRelFunc(("failed to get instance id (0x%x)\n", hr));
             else
             {
                 adapter.guid = *(Guid(guid).raw());
-                netIfLog(("netIfGetUnboundHostOnlyAdapters: guid=%RTuuid, name=%ls id = %ls\n", &adapter.guid, adapter.pName, adapter.pHwId));
+                netIfLog(("guid=%RTuuid, name=%ls id = %ls\n", &adapter.guid, adapter.pName, adapter.pHwId));
                 adapters.push_back(adapter);
                 adapter.pName = adapter.pHwId = NULL; /* do not free, will be done later */
             }
@@ -1507,7 +1506,7 @@ static int netIfGetUnboundHostOnlyAdapters(INetCfg *pNetCfg, std::list<BoundAdap
 
         pEnumComponent->Release();
     }
-    netIfLog(("netIfGetUnboundHostOnlyAdapters: return\n"));
+    netIfLog(("return\n"));
     return VINF_SUCCESS;
 }
 
@@ -1518,7 +1517,7 @@ static HRESULT netIfGetBoundAdapters(std::list<BoundAdapter> &boundAdapters)
     LPWSTR               lpszApp;
     HRESULT              hr;
 
-    netIfLog(("netIfGetBoundAdapters: building the list of interfaces\n"));
+    netIfLog(("building the list of interfaces\n"));
     /* we are using the INetCfg API for getting the list of miniports */
     hr = VBoxNetCfgWinQueryINetCfg(&pNetCfg, FALSE,
                        VBOX_APP_NAME,
@@ -1527,25 +1526,25 @@ static HRESULT netIfGetBoundAdapters(std::list<BoundAdapter> &boundAdapters)
     Assert(hr == S_OK);
     if (hr != S_OK)
     {
-        LogRel(("netIfGetBoundAdapters: failed to query INetCfg (0x%x)\n", hr));
+        LogRelFunc(("failed to query INetCfg (0x%x)\n", hr));
         return hr;
     }
 
     if ((hr = pNetCfg->FindComponent(L"oracle_VBoxNetLwf", &pFilter)) != S_OK
         /* fall back to NDIS5 miniport lookup */
         && (hr = pNetCfg->FindComponent(L"sun_VBoxNetFlt", &pFilter)))
-        LogRel(("netIfGetBoundAdapters: could not find either 'oracle_VBoxNetLwf' or 'sun_VBoxNetFlt' components (0x%x)\n", hr));
+        LogRelFunc(("could not find either 'oracle_VBoxNetLwf' or 'sun_VBoxNetFlt' components (0x%x)\n", hr));
     else
     {
         INetCfgComponentBindings *pFilterBindings;
         if ((pFilter->QueryInterface(IID_INetCfgComponentBindings, (PVOID*)&pFilterBindings)) != S_OK)
-            LogRel(("netIfGetBoundAdapters: failed to query INetCfgComponentBindings (0x%x)\n", hr));
+            LogRelFunc(("failed to query INetCfgComponentBindings (0x%x)\n", hr));
         else
         {
             IEnumNetCfgBindingPath *pEnumBp;
             INetCfgBindingPath     *pBp;
             if ((pFilterBindings->EnumBindingPaths(EBP_BELOW, &pEnumBp)) != S_OK)
-                LogRel(("netIfGetBoundAdapters: failed to enumerate binding paths (0x%x)\n", hr));
+                LogRelFunc(("failed to enumerate binding paths (0x%x)\n", hr));
             else
             {
                 pEnumBp->Reset();
@@ -1556,12 +1555,12 @@ static HRESULT netIfGetBoundAdapters(std::list<BoundAdapter> &boundAdapters)
                     if (pBp->IsEnabled() != S_OK)
                     {
                         /** @todo some id of disabled path could be useful. */
-                        netIfLog(("netIfGetBoundAdapters: INetCfgBindingPath is disabled (0x%x)\n", hr));
+                        netIfLog(("INetCfgBindingPath is disabled (0x%x)\n", hr));
                         pBp->Release();
                         continue;
                     }
                     if ((pBp->EnumBindingInterfaces(&pEnumBi)) != S_OK)
-                        LogRel(("netIfGetBoundAdapters: failed to enumerate binding interfaces (0x%x)\n", hr));
+                        LogRelFunc(("failed to enumerate binding interfaces (0x%x)\n", hr));
                     else
                     {
                         hr = pEnumBi->Reset();
@@ -1569,39 +1568,39 @@ static HRESULT netIfGetBoundAdapters(std::list<BoundAdapter> &boundAdapters)
                         {
                             INetCfgComponent *pAdapter;
                             if ((hr = pBi->GetLowerComponent(&pAdapter)) != S_OK)
-                                LogRel(("netIfGetBoundAdapters: failed to get lower component (0x%x)\n", hr));
+                                LogRelFunc(("failed to get lower component (0x%x)\n", hr));
                             else
                             {
                                 LPWSTR pwszName = NULL;
                                 if ((hr = pAdapter->GetDisplayName(&pwszName)) != S_OK)
-                                    LogRel(("netIfGetBoundAdapters: failed to get display name (0x%x)\n", hr));
+                                    LogRelFunc(("failed to get display name (0x%x)\n", hr));
                                 else
                                 {
                                     ULONG uStatus;
                                     DWORD dwChars;
                                     if ((hr = pAdapter->GetDeviceStatus(&uStatus)) != S_OK)
-                                        netIfLog(("netIfGetBoundAdapters: %ls: failed to get device status (0x%x)\n",
+                                        netIfLog(("%ls: failed to get device status (0x%x)\n",
                                                   pwszName, hr));
                                     else if ((hr = pAdapter->GetCharacteristics(&dwChars)) != S_OK)
-                                        netIfLog(("netIfGetBoundAdapters: %ls: failed to get device characteristics (0x%x)\n",
+                                        netIfLog(("%ls: failed to get device characteristics (0x%x)\n",
                                                   pwszName, hr));
                                     else if (uStatus != 0)
-                                        netIfLog(("netIfGetBoundAdapters: %ls: wrong status 0x%x\n",
+                                        netIfLog(("%ls: wrong status 0x%x\n",
                                                   pwszName, uStatus));
                                     else if (dwChars & NCF_HIDDEN)
-                                        netIfLog(("netIfGetBoundAdapters: %ls: wrong characteristics 0x%x\n",
+                                        netIfLog(("%ls: wrong characteristics 0x%x\n",
                                                   pwszName, dwChars));
                                     else
                                     {
                                         GUID guid;
                                         LPWSTR pwszHwId = NULL;
                                         if ((hr = pAdapter->GetId(&pwszHwId)) != S_OK)
-                                            LogRel(("netIfGetBoundAdapters: %ls: failed to get hardware id (0x%x)\n",
+                                            LogRelFunc(("%ls: failed to get hardware id (0x%x)\n",
                                                       pwszName, hr));
                                         else if (!_wcsnicmp(pwszHwId, L"sun_VBoxNetAdp", sizeof(L"sun_VBoxNetAdp")/2))
-                                            netIfLog(("netIfGetBoundAdapters: host-only adapter %ls, ignored\n", pwszName));
+                                            netIfLog(("host-only adapter %ls, ignored\n", pwszName));
                                         else if ((hr = pAdapter->GetInstanceGuid(&guid)) != S_OK)
-                                            LogRel(("netIfGetBoundAdapters: %ls: failed to get instance GUID (0x%x)\n",
+                                            LogRelFunc(("%ls: failed to get instance GUID (0x%x)\n",
                                                       pwszName, hr));
                                         else
                                         {
@@ -1610,7 +1609,7 @@ static HRESULT netIfGetBoundAdapters(std::list<BoundAdapter> &boundAdapters)
                                             adapter.pHwId    = pwszHwId;
                                             adapter.guid     = *(Guid(guid).raw());
                                             adapter.pAdapter = NULL;
-                                            netIfLog(("netIfGetBoundAdapters: guid=%RTuuid, name=%ls, hwid=%ls, status=%x, chars=%x\n",
+                                            netIfLog(("guid=%RTuuid, name=%ls, hwid=%ls, status=%x, chars=%x\n",
                                                       &adapter.guid, pwszName, pwszHwId, uStatus, dwChars));
                                             boundAdapters.push_back(adapter);
                                             pwszName = pwszHwId = NULL; /* do not free, will be done later */
@@ -1650,6 +1649,10 @@ static HRESULT netIfGetBoundAdaptersFallback(std::list<BoundAdapter> &boundAdapt
 }
 #endif
 
+/**
+ * Walk through the list of adpater addresses and extract the required
+ * information. XP and older don't not have the OnLinkPrefixLength field.
+ */
 static void netIfFillInfoWithAddressesXp(PNETIFINFO pInfo, PIP_ADAPTER_ADDRESSES pAdapter)
 {
     PIP_ADAPTER_UNICAST_ADDRESS pAddr;
@@ -1690,16 +1693,16 @@ static void netIfFillInfoWithAddressesXp(PNETIFINFO pInfo, PIP_ADAPTER_ADDRESSES
                 if (!uPrefixLenV4)
                 {
                     ULONG ip = ((PSOCKADDR_IN)(pPrefix->Address.lpSockaddr))->sin_addr.s_addr;
-                    netIfLog(("netIfFillInfoWithAddressesXp: prefix=%RTnaipv4 len=%u\n", ip, pPrefix->PrefixLength));
+                    netIfLog(("prefix=%RTnaipv4 len=%u\n", ip, pPrefix->PrefixLength));
                     if (   pPrefix->PrefixLength < sizeof(pInfo->IPNetMask) * 8
                         && pPrefix->PrefixLength > 0
                         && (ip & 0xF0) < 224)
                     {
                         uPrefixLenV4 = pPrefix->PrefixLength;
-                        ASMBitSetRange(&pInfo->IPNetMask, 0, pPrefix->PrefixLength);
+                        RTNetPrefixToMaskIPv4(pPrefix->PrefixLength, &pInfo->IPNetMask);
                     }
                     else
-                        netIfLog(("netIfFillInfoWithAddressesXp: Unexpected IPv4 prefix length of %d\n",
+                        netIfLog(("Unexpected IPv4 prefix length of %d\n",
                              pPrefix->PrefixLength));
                 }
                 break;
@@ -1707,34 +1710,34 @@ static void netIfFillInfoWithAddressesXp(PNETIFINFO pInfo, PIP_ADAPTER_ADDRESSES
                 if (!uPrefixLenV6)
                 {
                     PBYTE ipv6 = ((PSOCKADDR_IN6)(pPrefix->Address.lpSockaddr))->sin6_addr.s6_addr;
-                    netIfLog(("netIfFillInfoWithAddressesXp: prefix=%RTnaipv6 len=%u\n",
-                              ipv6, pPrefix->PrefixLength));
+                    netIfLog(("prefix=%RTnaipv6 len=%u\n", ipv6, pPrefix->PrefixLength));
                     if (   pPrefix->PrefixLength < sizeof(pInfo->IPv6NetMask) * 8
                         && pPrefix->PrefixLength > 0
                         && ipv6[0] != 0xFF)
                     {
                         uPrefixLenV6 = pPrefix->PrefixLength;
-                        ASMBitSetRange(&pInfo->IPv6NetMask, 0, pPrefix->PrefixLength);
+                        RTNetPrefixToMaskIPv6(pPrefix->PrefixLength, &pInfo->IPv6NetMask);
                     }
                     else
-                        netIfLog(("netIfFillInfoWithAddressesXp: Unexpected IPv6 prefix length of %d\n",
-                             pPrefix->PrefixLength));
+                        netIfLog(("Unexpected IPv6 prefix length of %d\n", pPrefix->PrefixLength));
                 }
                 break;
         }
     }
-    netIfLog(("netIfFillInfoWithAddressesXp: %RTnaipv4/%u\n",
-              pInfo->IPAddress, uPrefixLenV4));
-    netIfLog(("netIfFillInfoWithAddressesXp: %RTnaipv6/%u\n",
-              &pInfo->IPv6Address, uPrefixLenV6));
+    netIfLog(("%RTnaipv4/%u\n", pInfo->IPAddress, uPrefixLenV4));
+    netIfLog(("%RTnaipv6/%u\n", &pInfo->IPv6Address, uPrefixLenV6));
 }
 
-static void netIfFillInfoWithAddresses(PNETIFINFO pInfo, PIP_ADAPTER_ADDRESSES pAdapter)
+/**
+ * Walk through the list of adpater addresses and extract the required
+ * information. XP and older don't not have the OnLinkPrefixLength field.
+ */
+static void netIfFillInfoWithAddressesVista(PNETIFINFO pInfo, PIP_ADAPTER_ADDRESSES pAdapter)
 {
     PIP_ADAPTER_UNICAST_ADDRESS pAddr;
 
     if (sizeof(pInfo->MACAddress) != pAdapter->PhysicalAddressLength)
-        netIfLog(("netIfFillInfoWithAddresses: Unexpected physical address length: %u\n", pAdapter->PhysicalAddressLength));
+        netIfLog(("Unexpected physical address length: %u\n", pAdapter->PhysicalAddressLength));
     else
         memcpy(pInfo->MACAddress.au8, pAdapter->PhysicalAddress, sizeof(pInfo->MACAddress));
 
@@ -1742,12 +1745,6 @@ static void netIfFillInfoWithAddresses(PNETIFINFO pInfo, PIP_ADAPTER_ADDRESSES p
     bool fIPv6Found = false;
     for (pAddr = pAdapter->FirstUnicastAddress; pAddr; pAddr = pAddr->Next)
     {
-        if (pAddr->Length < sizeof(IP_ADAPTER_UNICAST_ADDRESS_LH))
-        {
-            netIfLog(("netIfFillInfoWithAddresses: unicast address is too small (%u < %u), fall back to XP implementation\n",
-                      pAddr->Length, sizeof(IP_ADAPTER_UNICAST_ADDRESS_LH)));
-            return netIfFillInfoWithAddressesXp(pInfo, pAdapter);
-        }
         PIP_ADAPTER_UNICAST_ADDRESS_LH pAddrLh = (PIP_ADAPTER_UNICAST_ADDRESS_LH)pAddr;
         switch (pAddrLh->Address.lpSockaddr->sa_family)
         {
@@ -1759,9 +1756,9 @@ static void netIfFillInfoWithAddresses(PNETIFINFO pInfo, PIP_ADAPTER_ADDRESSES p
                            &((struct sockaddr_in *)pAddrLh->Address.lpSockaddr)->sin_addr.s_addr,
                            sizeof(pInfo->IPAddress));
                     if (pAddrLh->OnLinkPrefixLength > 32)
-                        netIfLog(("netIfFillInfoWithAddresses: Invalid IPv4 prefix length of %d\n", pAddrLh->OnLinkPrefixLength));
+                        netIfLog(("Invalid IPv4 prefix length of %d\n", pAddrLh->OnLinkPrefixLength));
                     else
-                        ASMBitSetRange(&pInfo->IPNetMask, 0, pAddrLh->OnLinkPrefixLength);
+                        RTNetPrefixToMaskIPv4(pAddrLh->OnLinkPrefixLength, &pInfo->IPNetMask);
                 }
                 break;
             case AF_INET6:
@@ -1772,17 +1769,26 @@ static void netIfFillInfoWithAddresses(PNETIFINFO pInfo, PIP_ADAPTER_ADDRESSES p
                            ((struct sockaddr_in6 *)pAddrLh->Address.lpSockaddr)->sin6_addr.s6_addr,
                            sizeof(pInfo->IPv6Address));
                     if (pAddrLh->OnLinkPrefixLength > 128)
-                        netIfLog(("netIfFillInfoWithAddresses: Invalid IPv6 prefix length of %d\n", pAddrLh->OnLinkPrefixLength));
+                        netIfLog(("Invalid IPv6 prefix length of %d\n", pAddrLh->OnLinkPrefixLength));
                     else
-                        ASMBitSetRange(&pInfo->IPv6NetMask, 0, pAddrLh->OnLinkPrefixLength);
+                        RTNetPrefixToMaskIPv6(pAddrLh->OnLinkPrefixLength, &pInfo->IPv6NetMask);
                 }
                 break;
         }
     }
-    netIfLog(("netIfFillInfoWithAddresses: %RTnaipv4/%u\n",
-              pInfo->IPAddress, ASMBitFirstClear(&pInfo->IPNetMask, sizeof(RTNETADDRIPV4)*8)));
-    netIfLog(("netIfFillInfoWithAddresses: %RTnaipv6/%u\n",
-              &pInfo->IPv6Address, composeIPv6PrefixLenghFromAddress(&pInfo->IPv6NetMask)));
+
+    if (fIPFound)
+    {
+        int iPrefixIPv4 = -1;
+        RTNetMaskToPrefixIPv4(&pInfo->IPNetMask, &iPrefixIPv4);
+        netIfLog(("%RTnaipv4/%u\n", pInfo->IPAddress, iPrefixIPv4));
+    }
+    if (fIPv6Found)
+    {
+        int iPrefixIPv6 = -1;
+        RTNetMaskToPrefixIPv6(&pInfo->IPv6NetMask, &iPrefixIPv6);
+        netIfLog(("%RTnaipv6/%u\n", &pInfo->IPv6Address, iPrefixIPv6));
+    }
 }
 
 #if (NTDDI_VERSION >= NTDDI_VISTA)
@@ -1812,7 +1818,7 @@ int NetIfList(std::list<ComObjPtr<HostNetworkInterface> > &list)
     }
     if (dwRc != NO_ERROR)
     {
-        LogRel(("NetIfList: GetAdaptersAddresses failed (0x%x)\n", dwRc));
+        LogRelFunc(("GetAdaptersAddresses failed (0x%x)\n", dwRc));
         hr = HRESULT_FROM_WIN32(dwRc);
     }
     else
@@ -1824,7 +1830,7 @@ int NetIfList(std::list<ComObjPtr<HostNetworkInterface> > &list)
             hr = netIfGetBoundAdaptersFallback(boundAdapters);
 #endif
         if (hr != S_OK)
-            LogRel(("NetIfList: netIfGetBoundAdapters failed (0x%x)\n", hr));
+            LogRelFunc(("netIfGetBoundAdapters failed (0x%x)\n", hr));
         else
         {
             PIP_ADAPTER_ADDRESSES pAdapter;
@@ -1834,12 +1840,12 @@ int NetIfList(std::list<ComObjPtr<HostNetworkInterface> > &list)
                 char *pszUuid = RTStrDup(pAdapter->AdapterName);
                 if (!pszUuid)
                 {
-                    LogRel(("NetIfList: out of memory\n"));
+                    LogRelFunc(("out of memory\n"));
                     break;
                 }
                 size_t len = strlen(pszUuid) - 1;
                 if (pszUuid[0] != '{' || pszUuid[len] != '}')
-                    LogRel(("NetIfList: ignoring invalid GUID %s\n", pAdapter->AdapterName));
+                    LogRelFunc(("ignoring invalid GUID %s\n", pAdapter->AdapterName));
                 else
                 {
                     std::list<BoundAdapter>::iterator it;
@@ -1868,7 +1874,14 @@ int NetIfList(std::list<ComObjPtr<HostNetworkInterface> > &list)
                     info.enmStatus = pAdapter->OperStatus == IfOperStatusUp ? NETIF_S_UP : NETIF_S_DOWN;
                     info.bIsDefault = (pAdapter->IfIndex == (DWORD)iDefault);
                     info.bDhcpEnabled = pAdapter->Flags & IP_ADAPTER_DHCP_ENABLED;
-                    netIfFillInfoWithAddresses(&info, pAdapter);
+                    OSVERSIONINFOEX OSInfoEx;
+                    RT_ZERO(OSInfoEx);
+                    OSInfoEx.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
+                    if (   GetVersionEx((LPOSVERSIONINFO)&OSInfoEx)
+                        && OSInfoEx.dwMajorVersion < 6)
+                        netIfFillInfoWithAddressesXp(&info, pAdapter);
+                    else
+                        netIfFillInfoWithAddressesVista(&info, pAdapter);
                 }
                 else
                     info.enmStatus = NETIF_S_DOWN;
@@ -1883,7 +1896,7 @@ int NetIfList(std::list<ComObjPtr<HostNetworkInterface> > &list)
                         enmType == HostNetworkInterfaceType_HostOnly ? "host-only" : "unknown"));
                 int rc = iface->init((*it).pName, enmType, &info);
                 if (FAILED(rc))
-                    LogRel(("NetIfList: HostNetworkInterface::init() -> %Rrc\n", rc));
+                    LogRelFunc(("HostNetworkInterface::init() -> %Rrc\n", rc));
                 else
                 {
                     if (info.bIsDefault)
diff --git a/src/VBox/Main/testcase/tstCollector.cpp b/src/VBox/Main/testcase/tstCollector.cpp
index 7f73b92..23d56c8 100644
--- a/src/VBox/Main/testcase/tstCollector.cpp
+++ b/src/VBox/Main/testcase/tstCollector.cpp
@@ -575,6 +575,6 @@ int main(int argc, char *argv[])
 
     printf ("\ntstCollector FINISHED.\n");
 
-    return rc;
+    return RTEXITCODE_SUCCESS;
 }
 
diff --git a/src/VBox/Main/xml/Settings.cpp b/src/VBox/Main/xml/Settings.cpp
index bab5818..00c728c 100644
--- a/src/VBox/Main/xml/Settings.cpp
+++ b/src/VBox/Main/xml/Settings.cpp
@@ -2320,7 +2320,7 @@ bool NAT::areDefaultSettings() const
 bool NAT::operator==(const NAT &n) const
 {
    return (this == &n)
-        || (   strNetwork           == n.strNetwork
+       || (   strNetwork           == n.strNetwork
             && strBindIP           == n.strBindIP
             && u32Mtu              == n.u32Mtu
             && u32SockRcv          == n.u32SockRcv
@@ -5866,7 +5866,7 @@ void MachineConfigFile::buildHardwareXML(xml::ElementNode &elmParent,
                 case PortMode_TCP:
                 case PortMode_HostPipe:
                     pelmPort->setAttribute("server", port.fServer);
-                    /* no break */
+                    /* fall thru */
                 case PortMode_HostDevice:
                 case PortMode_RawFile:
                     pelmPort->setAttribute("path", port.strPath);
diff --git a/src/VBox/Runtime/Makefile.kmk b/src/VBox/Runtime/Makefile.kmk
index b010045..e9ea0ff 100644
--- a/src/VBox/Runtime/Makefile.kmk
+++ b/src/VBox/Runtime/Makefile.kmk
@@ -1837,6 +1837,7 @@ RuntimeR3NoCRTGCC_SOURCES.x86 = \
 	common/math/gcc/subdi3.c \
 	common/math/gcc/ucmpdi2.c \
 	common/math/gcc/udivdi3.c \
+	common/math/gcc/udivmoddi4.c \
 	common/math/gcc/umoddi3.c \
 	common/math/gcc/xordi3.c
 
@@ -1929,6 +1930,7 @@ RuntimeR0_SOURCES += \
 	common/math/gcc/subdi3.c \
 	common/math/gcc/ucmpdi2.c \
 	common/math/gcc/udivdi3.c \
+	common/math/gcc/udivmoddi4.c \
 	common/math/gcc/umoddi3.c \
 	common/math/gcc/xordi3.c
 endif
@@ -2076,6 +2078,7 @@ RuntimeR0Drv_SOURCES    = \
 	common/string/RTStrNLen.cpp \
 	common/string/RTStrNLenEx.cpp \
 	common/string/RTUtf16ICmpAscii.cpp \
+	common/string/RTUtf16NICmpAscii.cpp \
 	common/string/straprintf.cpp \
 	common/string/strformat.cpp \
 	common/string/strformatnum.cpp \
@@ -2660,6 +2663,7 @@ ifdef VBOX_WITH_RAW_MODE
  	common/math/gcc/subdi3.c \
  	common/math/gcc/ucmpdi2.c \
  	common/math/gcc/udivdi3.c \
+	common/math/gcc/udivmoddi4.c \
  	common/math/gcc/umoddi3.c \
  	common/math/gcc/xordi3.c
  endif
diff --git a/src/VBox/Runtime/VBox/log-vbox.cpp b/src/VBox/Runtime/VBox/log-vbox.cpp
index 99a058c..5537276 100644
--- a/src/VBox/Runtime/VBox/log-vbox.cpp
+++ b/src/VBox/Runtime/VBox/log-vbox.cpp
@@ -732,6 +732,8 @@ RTDECL(PRTLOGGER) RTLogDefaultInit(void)
         RTLogFlags(pLogger, "enabled unbuffered pid tid");
 #  ifndef IN_GUEST
         pLogger->fDestFlags |= RTLOGDEST_DEBUGGER | RTLOGDEST_STDOUT;
+#  else
+        RTLogGroupSettings(pLogger, "all=~0 -default.l6.l5.l4.l3");
 #  endif
 # endif
 # if defined(DEBUG_sandervl) && !defined(IN_GUEST)
diff --git a/src/VBox/Runtime/common/asn1/asn1-ut-integer-decode.cpp b/src/VBox/Runtime/common/asn1/asn1-ut-integer-decode.cpp
index ab5a353..990d7cf 100644
--- a/src/VBox/Runtime/common/asn1/asn1-ut-integer-decode.cpp
+++ b/src/VBox/Runtime/common/asn1/asn1-ut-integer-decode.cpp
@@ -52,13 +52,13 @@ RTDECL(int) RTAsn1Integer_DecodeAsn1(PRTASN1CURSOR pCursor, uint32_t fFlags, PRT
             switch (pThis->Asn1Core.cb)
             {
                 default:
-                case 8: pThis->uValue.u |= (uint64_t)pThis->Asn1Core.uData.pu8[offLast - 7] << 56;
-                case 7: pThis->uValue.u |= (uint64_t)pThis->Asn1Core.uData.pu8[offLast - 6] << 48;
-                case 6: pThis->uValue.u |= (uint64_t)pThis->Asn1Core.uData.pu8[offLast - 5] << 40;
-                case 5: pThis->uValue.u |= (uint64_t)pThis->Asn1Core.uData.pu8[offLast - 4] << 32;
-                case 4: pThis->uValue.u |= (uint32_t)pThis->Asn1Core.uData.pu8[offLast - 3] << 24;
-                case 3: pThis->uValue.u |= (uint32_t)pThis->Asn1Core.uData.pu8[offLast - 2] << 16;
-                case 2: pThis->uValue.u |= (uint16_t)pThis->Asn1Core.uData.pu8[offLast - 1] << 8;
+                case 8: pThis->uValue.u |= (uint64_t)pThis->Asn1Core.uData.pu8[offLast - 7] << 56; /* fall thru */
+                case 7: pThis->uValue.u |= (uint64_t)pThis->Asn1Core.uData.pu8[offLast - 6] << 48; /* fall thru */
+                case 6: pThis->uValue.u |= (uint64_t)pThis->Asn1Core.uData.pu8[offLast - 5] << 40; /* fall thru */
+                case 5: pThis->uValue.u |= (uint64_t)pThis->Asn1Core.uData.pu8[offLast - 4] << 32; /* fall thru */
+                case 4: pThis->uValue.u |= (uint32_t)pThis->Asn1Core.uData.pu8[offLast - 3] << 24; /* fall thru */
+                case 3: pThis->uValue.u |= (uint32_t)pThis->Asn1Core.uData.pu8[offLast - 2] << 16; /* fall thru */
+                case 2: pThis->uValue.u |= (uint16_t)pThis->Asn1Core.uData.pu8[offLast - 1] <<  8; /* fall thru */
                 case 1: pThis->uValue.u |=           pThis->Asn1Core.uData.pu8[offLast];
             }
             RTAsn1CursorSkip(pCursor, pThis->Asn1Core.cb);
diff --git a/src/VBox/Runtime/common/asn1/asn1-ut-integer.cpp b/src/VBox/Runtime/common/asn1/asn1-ut-integer.cpp
index 6d7cb92..bb0b4a8 100644
--- a/src/VBox/Runtime/common/asn1/asn1-ut-integer.cpp
+++ b/src/VBox/Runtime/common/asn1/asn1-ut-integer.cpp
@@ -67,13 +67,13 @@ static void rtAsn1Integer_UpdateNativeValue(PRTASN1INTEGER pThis)
     switch (pThis->Asn1Core.cb)
     {
         default:
-        case 8: pThis->uValue.u |= (uint64_t)pThis->Asn1Core.uData.pu8[offLast - 7] << 56;
-        case 7: pThis->uValue.u |= (uint64_t)pThis->Asn1Core.uData.pu8[offLast - 6] << 48;
-        case 6: pThis->uValue.u |= (uint64_t)pThis->Asn1Core.uData.pu8[offLast - 5] << 40;
-        case 5: pThis->uValue.u |= (uint64_t)pThis->Asn1Core.uData.pu8[offLast - 4] << 32;
-        case 4: pThis->uValue.u |= (uint32_t)pThis->Asn1Core.uData.pu8[offLast - 3] << 24;
-        case 3: pThis->uValue.u |= (uint32_t)pThis->Asn1Core.uData.pu8[offLast - 2] << 16;
-        case 2: pThis->uValue.u |= (uint16_t)pThis->Asn1Core.uData.pu8[offLast - 1] << 8;
+        case 8: pThis->uValue.u |= (uint64_t)pThis->Asn1Core.uData.pu8[offLast - 7] << 56; /* fall thru */
+        case 7: pThis->uValue.u |= (uint64_t)pThis->Asn1Core.uData.pu8[offLast - 6] << 48; /* fall thru */
+        case 6: pThis->uValue.u |= (uint64_t)pThis->Asn1Core.uData.pu8[offLast - 5] << 40; /* fall thru */
+        case 5: pThis->uValue.u |= (uint64_t)pThis->Asn1Core.uData.pu8[offLast - 4] << 32; /* fall thru */
+        case 4: pThis->uValue.u |= (uint32_t)pThis->Asn1Core.uData.pu8[offLast - 3] << 24; /* fall thru */
+        case 3: pThis->uValue.u |= (uint32_t)pThis->Asn1Core.uData.pu8[offLast - 2] << 16; /* fall thru */
+        case 2: pThis->uValue.u |= (uint16_t)pThis->Asn1Core.uData.pu8[offLast - 1] <<  8; /* fall thru */
         case 1: pThis->uValue.u |=           pThis->Asn1Core.uData.pu8[offLast];
     }
 }
diff --git a/src/VBox/Runtime/common/crypto/pkix-util.cpp b/src/VBox/Runtime/common/crypto/pkix-util.cpp
index 449e576..a86c7b9 100644
--- a/src/VBox/Runtime/common/crypto/pkix-util.cpp
+++ b/src/VBox/Runtime/common/crypto/pkix-util.cpp
@@ -62,6 +62,7 @@ RTDECL(const char *) RTCrPkixGetCiperOidFromSignatureAlgorithm(PCRTASN1OBJID pAl
                 case 14:
                     return RTCR_PKCS1_RSA_OID;
                 case 1: AssertFailed();
+                    /* fall thru */
                 default:
                     return NULL;
             }
diff --git a/src/VBox/Runtime/common/ldr/ldrPE.cpp b/src/VBox/Runtime/common/ldr/ldrPE.cpp
index adb1e0f..054caa8 100644
--- a/src/VBox/Runtime/common/ldr/ldrPE.cpp
+++ b/src/VBox/Runtime/common/ldr/ldrPE.cpp
@@ -3038,9 +3038,10 @@ static void rtldrPEConvert32BitLoadConfigTo64Bit(PIMAGE_LOAD_CONFIG_DIRECTORY64
     /*
      * volatile everywhere! Trying to prevent the compiler being a smarta$$ and reorder stuff.
      */
-    IMAGE_LOAD_CONFIG_DIRECTORY32_V8 volatile *pLoadCfg32 = (IMAGE_LOAD_CONFIG_DIRECTORY32_V8 volatile *)pLoadCfg;
-    IMAGE_LOAD_CONFIG_DIRECTORY64_V8 volatile *pLoadCfg64 = pLoadCfg;
+    IMAGE_LOAD_CONFIG_DIRECTORY32_V9 volatile *pLoadCfg32 = (IMAGE_LOAD_CONFIG_DIRECTORY32_V9 volatile *)pLoadCfg;
+    IMAGE_LOAD_CONFIG_DIRECTORY64_V9 volatile *pLoadCfg64 = pLoadCfg;
 
+    pLoadCfg64->AddressOfSomeUnicodeString      = pLoadCfg32->AddressOfSomeUnicodeString;
     pLoadCfg64->HotPatchTableOffset             = pLoadCfg32->HotPatchTableOffset;
     pLoadCfg64->GuardRFVerifyStackPointerFunctionPointer = pLoadCfg32->GuardRFVerifyStackPointerFunctionPointer;
     pLoadCfg64->Reserved2                       = pLoadCfg32->Reserved2;
@@ -3604,6 +3605,9 @@ static int rtldrPEValidateDirectoriesAndRememberStuff(PRTLDRMODPE pModPe, const
     IMAGE_DATA_DIRECTORY Dir = pOptHdr->DataDirectory[IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG];
     if (Dir.Size)
     {
+        const size_t cbExpectV9 = !pModPe->f64Bit
+                                ? sizeof(IMAGE_LOAD_CONFIG_DIRECTORY32_V9)
+                                : sizeof(IMAGE_LOAD_CONFIG_DIRECTORY64_V9);
         const size_t cbExpectV8 = !pModPe->f64Bit
                                 ? sizeof(IMAGE_LOAD_CONFIG_DIRECTORY32_V8)
                                 : sizeof(IMAGE_LOAD_CONFIG_DIRECTORY64_V8);
@@ -3629,10 +3633,11 @@ static int rtldrPEValidateDirectoriesAndRememberStuff(PRTLDRMODPE pModPe, const
                                 ? sizeof(IMAGE_LOAD_CONFIG_DIRECTORY32_V1)
                                 : sizeof(IMAGE_LOAD_CONFIG_DIRECTORY64_V2) /*No V1*/;
         const size_t cbNewHack  = cbExpectV5; /* Playing safe here since there might've been revisions between V5 and V6 we don't know about . */
-        const size_t cbMaxKnown = cbExpectV8;
+        const size_t cbMaxKnown = cbExpectV9;
 
         bool fNewerStructureHack = false;
-        if (   Dir.Size != cbExpectV8
+        if (   Dir.Size != cbExpectV9
+            && Dir.Size != cbExpectV8
             && Dir.Size != cbExpectV7
             && Dir.Size != cbExpectV6
             && Dir.Size != cbExpectV5
@@ -3643,13 +3648,13 @@ static int rtldrPEValidateDirectoriesAndRememberStuff(PRTLDRMODPE pModPe, const
         {
             fNewerStructureHack = Dir.Size > cbNewHack /* These structure changes are slowly getting to us! More futher down. */
                                && Dir.Size <= sizeof(u);
-            Log(("rtldrPEOpen: %s: load cfg dir: unexpected dir size of %u bytes, expected %zu, %zu, %zu, %zu, %zu, %zu, %zu, or %zu.%s\n",
-                 pszLogName, Dir.Size, cbExpectV8, cbExpectV7, cbExpectV6, cbExpectV5, cbExpectV4, cbExpectV3, cbExpectV2, cbExpectV1,
+            Log(("rtldrPEOpen: %s: load cfg dir: unexpected dir size of %u bytes, expected %zu, %zu, %zu, %zu, %zu, %zu, %zu, %zu, or %zu.%s\n",
+                 pszLogName, Dir.Size, cbExpectV9, cbExpectV8, cbExpectV7, cbExpectV6, cbExpectV5, cbExpectV4, cbExpectV3, cbExpectV2, cbExpectV1,
                  fNewerStructureHack ? " Will try ignore extra bytes if all zero." : ""));
             if (!fNewerStructureHack)
                 return RTErrInfoSetF(pErrInfo, VERR_LDRPE_LOAD_CONFIG_SIZE,
-                                     "Unexpected load config dir size of %u bytes; supported sized: %zu, %zu, %zu, %zu, %zu, %zu, %zu, or %zu",
-                                     Dir.Size, cbExpectV8, cbExpectV7, cbExpectV6, cbExpectV5, cbExpectV4, cbExpectV3, cbExpectV2, cbExpectV1);
+                                     "Unexpected load config dir size of %u bytes; supported sized: %zu, %zu, %zu, %zu, %zu, %zu, %zu, %zu, or %zu",
+                                     Dir.Size, cbExpectV9, cbExpectV8, cbExpectV7, cbExpectV6, cbExpectV5, cbExpectV4, cbExpectV3, cbExpectV2, cbExpectV1);
         }
 
         /*
@@ -3687,7 +3692,8 @@ static int rtldrPEValidateDirectoriesAndRememberStuff(PRTLDRMODPE pModPe, const
             }
             /* Kludge #2: This happens a lot. Structure changes, but the linker doesn't get
                updated and stores some old size in the directory.  Use the header size. */
-            else if (   u.Cfg64.Size == cbExpectV8
+            else if (   u.Cfg64.Size == cbExpectV9
+                     || u.Cfg64.Size == cbExpectV8
                      || u.Cfg64.Size == cbExpectV7
                      || u.Cfg64.Size == cbExpectV6
                      || u.Cfg64.Size == cbExpectV5
@@ -3723,11 +3729,11 @@ static int rtldrPEValidateDirectoriesAndRememberStuff(PRTLDRMODPE pModPe, const
             }
             else
             {
-                Log(("rtldrPEOpen: %s: load cfg hdr: unexpected hdr size of %u bytes (dir %u), expected %zu, %zu, %zu, %zu, %zu, %zu, %zu, or %zu.\n",
-                     pszLogName, u.Cfg64.Size, Dir.Size, cbExpectV8, cbExpectV7, cbExpectV6, cbExpectV5, cbExpectV4, cbExpectV3, cbExpectV2, cbExpectV1));
+                Log(("rtldrPEOpen: %s: load cfg hdr: unexpected hdr size of %u bytes (dir %u), expected %zu, %zu, %zu, %zu, %zu, %zu, %zu, %zu, or %zu.\n",
+                     pszLogName, u.Cfg64.Size, Dir.Size, cbExpectV9, cbExpectV8, cbExpectV7, cbExpectV6, cbExpectV5, cbExpectV4, cbExpectV3, cbExpectV2, cbExpectV1));
                 return RTErrInfoSetF(pErrInfo, VERR_LDRPE_LOAD_CONFIG_SIZE,
-                                     "Unexpected load config header size of %u bytes (dir %u); supported sized: %zu, %zu, %zu, %zu, %zu, %zu, %zu, or %zu",
-                                     u.Cfg64.Size, Dir.Size, cbExpectV8, cbExpectV7, cbExpectV6, cbExpectV5, cbExpectV4, cbExpectV3, cbExpectV2, cbExpectV1);
+                                     "Unexpected load config header size of %u bytes (dir %u); supported sized: %zu, %zu, %zu, %zu, %zu, %zu, %zu, %zu, or %zu",
+                                     u.Cfg64.Size, Dir.Size, cbExpectV9, cbExpectV8, cbExpectV7, cbExpectV6, cbExpectV5, cbExpectV4, cbExpectV3, cbExpectV2, cbExpectV1);
             }
         }
         if (u.Cfg64.LockPrefixTable && !(fFlags & (RTLDR_O_FOR_DEBUG | RTLDR_O_FOR_VALIDATION)))
diff --git a/src/VBox/Runtime/common/ldr/ldrkStuff.cpp b/src/VBox/Runtime/common/ldr/ldrkStuff.cpp
index d3f8c47..b351a6d 100644
--- a/src/VBox/Runtime/common/ldr/ldrkStuff.cpp
+++ b/src/VBox/Runtime/common/ldr/ldrkStuff.cpp
@@ -710,6 +710,7 @@ static DECLCALLBACK(int) rtkldr_EnumSegments(PRTLDRMODINTERNAL pMod, PFNRTLDRENU
         {
             default:
                 AssertMsgFailed(("%d\n", paSegments[iSeg].enmProt));
+                /* fall thru */
             case KPROT_NOACCESS:
                 Seg.fProt = 0;
                 break;
diff --git a/src/VBox/Runtime/common/math/bignum.cpp b/src/VBox/Runtime/common/math/bignum.cpp
index 5ac74fb..65e9906 100644
--- a/src/VBox/Runtime/common/math/bignum.cpp
+++ b/src/VBox/Runtime/common/math/bignum.cpp
@@ -676,13 +676,15 @@ RTDECL(int) RTBigNumInit(PRTBIGNUM pBigNum, uint32_t fFlags, void const *pvRaw,
                 {
                     default: AssertFailed();
 #if RTBIGNUM_ELEMENT_SIZE == 8
-                    case 7: uLast = (uLast << 8) | pb[6];
-                    case 6: uLast = (uLast << 8) | pb[5];
-                    case 5: uLast = (uLast << 8) | pb[4];
+                                                          /* fall thru */
+                    case 7: uLast = (uLast << 8) | pb[6]; /* fall thru */
+                    case 6: uLast = (uLast << 8) | pb[5]; /* fall thru */
+                    case 5: uLast = (uLast << 8) | pb[4]; /* fall thru */
                     case 4: uLast = (uLast << 8) | pb[3];
 #endif
-                    case 3: uLast = (uLast << 8) | pb[2];
-                    case 2: uLast = (uLast << 8) | pb[1];
+                                                          /* fall thru */
+                    case 3: uLast = (uLast << 8) | pb[2]; /* fall thru */
+                    case 2: uLast = (uLast << 8) | pb[1]; /* fall thru */
                     case 1: uLast = (uLast << 8) | pb[0];
                 }
                 pBigNum->pauElements[i] = uLast;
@@ -713,13 +715,15 @@ RTDECL(int) RTBigNumInit(PRTBIGNUM pBigNum, uint32_t fFlags, void const *pvRaw,
                 {
                     default: AssertFailed();
 #if RTBIGNUM_ELEMENT_SIZE == 8
-                    case 7: uLast = (uLast << 8) | *pb++;
-                    case 6: uLast = (uLast << 8) | *pb++;
-                    case 5: uLast = (uLast << 8) | *pb++;
+                                                          /* fall thru */
+                    case 7: uLast = (uLast << 8) | *pb++; /* fall thru */
+                    case 6: uLast = (uLast << 8) | *pb++; /* fall thru */
+                    case 5: uLast = (uLast << 8) | *pb++; /* fall thru */
                     case 4: uLast = (uLast << 8) | *pb++;
 #endif
-                    case 3: uLast = (uLast << 8) | *pb++;
-                    case 2: uLast = (uLast << 8) | *pb++;
+                                                          /* fall thru */
+                    case 3: uLast = (uLast << 8) | *pb++; /* fall thru */
+                    case 2: uLast = (uLast << 8) | *pb++; /* fall thru */
                     case 1: uLast = (uLast << 8) | *pb++;
                 }
                 pBigNum->pauElements[i] = uLast;
@@ -745,9 +749,9 @@ RTDECL(int) RTBigNumInit(PRTBIGNUM pBigNum, uint32_t fFlags, void const *pvRaw,
             AssertCompile(RTBIGNUM_ALIGNMENT <= 4);
             switch (pBigNum->cAllocated - pBigNum->cUsed)
             {
-                default: AssertFailed();
-                case 3: *puUnused++ = 0;
-                case 2: *puUnused++ = 0;
+                default: AssertFailed(); /* fall thru */
+                case 3: *puUnused++ = 0; /* fall thru */
+                case 2: *puUnused++ = 0; /* fall thru */
                 case 1: *puUnused++ = 0;
             }
         }
diff --git a/src/VBox/Runtime/common/math/gcc/udivmoddi4.c b/src/VBox/Runtime/common/math/gcc/udivmoddi4.c
new file mode 100644
index 0000000..09b3f2b
--- /dev/null
+++ b/src/VBox/Runtime/common/math/gcc/udivmoddi4.c
@@ -0,0 +1,53 @@
+/* $Id: udivmoddi4.c $ */
+/** @file
+ * IPRT - __udivmoddi4 implementation
+ */
+
+/*
+ * Copyright (C) 2006-2016 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 <iprt/stdint.h>
+#include <iprt/uint64.h>
+
+uint64_t __udivmoddi4(uint64_t u64A, uint64_t u64B, uint64_t *pu64R);
+
+/**
+ * __udivmoddi4() implementation to satisfy external references from 32-bit
+ * code generated by gcc-7 or later.
+ *
+ * @param   u64A        The divident value.
+ * @param   u64B        The divisor value.
+ * @param   pu64R       A pointer to the reminder. May be NULL.
+ * @returns u64A / u64B
+ */
+uint64_t __udivmoddi4(uint64_t u64A, uint64_t u64B, uint64_t *pu64R)
+{
+    RTUINT64U Divident;
+    RTUINT64U Divisor;
+    RTUINT64U Quotient;
+    RTUINT64U Reminder;
+    Divident.u = u64A;
+    Divisor.u  = u64B;
+    RTUInt64DivRem(&Quotient, &Reminder, &Divident, &Divisor);
+    if (pu64R)
+        *pu64R = Reminder.u;
+    return Quotient.u;
+}
diff --git a/src/VBox/Runtime/common/misc/getoptargv.cpp b/src/VBox/Runtime/common/misc/getoptargv.cpp
index 8c7ab4a..f484927 100644
--- a/src/VBox/Runtime/common/misc/getoptargv.cpp
+++ b/src/VBox/Runtime/common/misc/getoptargv.cpp
@@ -157,13 +157,13 @@ DECLINLINE(bool) rtGetOptIsAsciiInSet(char ch, const char *pszSeparators, size_t
 {
     switch (cchSeparators)
     {
-        case 8: if (ch == pszSeparators[7]) return true;
-        case 7: if (ch == pszSeparators[6]) return true;
-        case 6: if (ch == pszSeparators[5]) return true;
-        case 5: if (ch == pszSeparators[4]) return true;
-        case 4: if (ch == pszSeparators[3]) return true;
-        case 3: if (ch == pszSeparators[2]) return true;
-        case 2: if (ch == pszSeparators[1]) return true;
+        case 8: if (ch == pszSeparators[7]) return true; /* fall thru */
+        case 7: if (ch == pszSeparators[6]) return true; /* fall thru */
+        case 6: if (ch == pszSeparators[5]) return true; /* fall thru */
+        case 5: if (ch == pszSeparators[4]) return true; /* fall thru */
+        case 4: if (ch == pszSeparators[3]) return true; /* fall thru */
+        case 3: if (ch == pszSeparators[2]) return true; /* fall thru */
+        case 2: if (ch == pszSeparators[1]) return true; /* fall thru */
         case 1: if (ch == pszSeparators[0]) return true;
             return false;
         default:
@@ -275,50 +275,56 @@ RTDECL(int) RTGetOptArgvFromString(char ***ppapszArgv, int *pcArgs, const char *
         /*
          * Parse and copy the string over.
          */
-        RTUNICP Cp;
+        RTUNICP uc;
         if ((fFlags & RTGETOPTARGV_CNV_QUOTE_MASK) == RTGETOPTARGV_CNV_QUOTE_BOURNE_SH)
         {
             /*
              * Bourne shell style.
              */
-            RTUNICP CpQuote = 0;
+            RTUNICP ucQuote = 0;
             for (;;)
             {
-                rc = RTStrGetCpEx(&pszSrc, &Cp);
-                if (RT_FAILURE(rc) || !Cp)
+                rc = RTStrGetCpEx(&pszSrc, &uc);
+                if (RT_FAILURE(rc) || !uc)
                     break;
-                if (!CpQuote)
+                if (!ucQuote)
                 {
-                    if (Cp == '"' || Cp == '\'')
-                        CpQuote = Cp;
-                    else if (rtGetOptIsCpInSet(Cp, pszSeparators, cchSeparators))
+                    if (uc == '"' || uc == '\'')
+                        ucQuote = uc;
+                    else if (rtGetOptIsCpInSet(uc, pszSeparators, cchSeparators))
                         break;
-                    else if (Cp != '\\')
-                        pszDst = RTStrPutCp(pszDst, Cp);
+                    else if (uc != '\\')
+                        pszDst = RTStrPutCp(pszDst, uc);
                     else
                     {
                         /* escaped char */
-                        rc = RTStrGetCpEx(&pszSrc, &Cp);
-                        if (RT_FAILURE(rc) || !Cp)
+                        rc = RTStrGetCpEx(&pszSrc, &uc);
+                        if (RT_FAILURE(rc) || !uc)
                             break;
-                        pszDst = RTStrPutCp(pszDst, Cp);
+                        pszDst = RTStrPutCp(pszDst, uc);
                     }
                 }
-                else if (CpQuote != Cp)
+                else if (ucQuote != uc)
                 {
-                    if (Cp != '\\' || CpQuote == '\'')
-                        pszDst = RTStrPutCp(pszDst, Cp);
+                    if (uc != '\\' || ucQuote == '\'')
+                        pszDst = RTStrPutCp(pszDst, uc);
                     else
                     {
                         /* escaped char */
-                        rc = RTStrGetCpEx(&pszSrc, &Cp);
-                        if (RT_FAILURE(rc) || !Cp)
+                        rc = RTStrGetCpEx(&pszSrc, &uc);
+                        if (RT_FAILURE(rc) || !uc)
                             break;
-                        pszDst = RTStrPutCp(pszDst, Cp);
+                        if (   uc != '"'
+                            && uc != '\\'
+                            && uc != '`'
+                            && uc != '$'
+                            && uc != '\n')
+                            pszDst = RTStrPutCp(pszDst, ucQuote);
+                        pszDst = RTStrPutCp(pszDst, uc);
                     }
                 }
                 else
-                    CpQuote = 0;
+                    ucQuote = 0;
             }
         }
         else
@@ -330,10 +336,10 @@ RTDECL(int) RTGetOptArgvFromString(char ***ppapszArgv, int *pcArgs, const char *
             bool fInQuote = false;
             for (;;)
             {
-                rc = RTStrGetCpEx(&pszSrc, &Cp);
-                if (RT_FAILURE(rc) || !Cp)
+                rc = RTStrGetCpEx(&pszSrc, &uc);
+                if (RT_FAILURE(rc) || !uc)
                     break;
-                if (Cp == '"')
+                if (uc == '"')
                 {
                     /* Two double quotes insides a quoted string in an escape
                        sequence and we output one double quote char.
@@ -348,10 +354,10 @@ RTDECL(int) RTGetOptArgvFromString(char ***ppapszArgv, int *pcArgs, const char *
                         pszSrc++;
                     }
                 }
-                else if (!fInQuote && rtGetOptIsCpInSet(Cp, pszSeparators, cchSeparators))
+                else if (!fInQuote && rtGetOptIsCpInSet(uc, pszSeparators, cchSeparators))
                     break;
-                else if (Cp != '\\')
-                    pszDst = RTStrPutCp(pszDst, Cp);
+                else if (uc != '\\')
+                    pszDst = RTStrPutCp(pszDst, uc);
                 else
                 {
                     /* A backslash sequence is only relevant if followed by
@@ -386,7 +392,7 @@ RTDECL(int) RTGetOptArgvFromString(char ***ppapszArgv, int *pcArgs, const char *
         }
 
         *pszDst++ = '\0';
-        if (RT_FAILURE(rc) || !Cp)
+        if (RT_FAILURE(rc) || !uc)
             break;
     }
 
diff --git a/src/VBox/Runtime/common/misc/lockvalidator.cpp b/src/VBox/Runtime/common/misc/lockvalidator.cpp
index 22ef076..886a112 100644
--- a/src/VBox/Runtime/common/misc/lockvalidator.cpp
+++ b/src/VBox/Runtime/common/misc/lockvalidator.cpp
@@ -4283,6 +4283,7 @@ RTDECL(void *) RTLockValidatorQueryBlocking(RTTHREAD hThread)
                             pRec = (PRTLOCKVALRECUNION)pRec->ShrdOwner.pSharedRec;
                             if (!pRec || pRec->Core.u32Magic != RTLOCKVALRECSHRD_MAGIC)
                                 break;
+                            /* fall thru */
                         case RTLOCKVALRECSHRD_MAGIC:
                             pvLock = pRec->Shared.hLock;
                             break;
diff --git a/src/VBox/Runtime/common/net/netaddrstr2.cpp b/src/VBox/Runtime/common/net/netaddrstr2.cpp
index e3051d0..703aee2 100644
--- a/src/VBox/Runtime/common/net/netaddrstr2.cpp
+++ b/src/VBox/Runtime/common/net/netaddrstr2.cpp
@@ -158,9 +158,9 @@ RTDECL(int) RTNetMaskToPrefixIPv4(PCRTNETADDRIPV4 pMask, int *piPrefix)
 
     if (pMask->u == 0)
     {
-	if (piPrefix != NULL)
-	    *piPrefix = 0;
-	return VINF_SUCCESS;
+        if (piPrefix != NULL)
+            *piPrefix = 0;
+        return VINF_SUCCESS;
     }
 
     const uint32_t uMask = RT_N2H_U32(pMask->u);
@@ -168,16 +168,17 @@ RTDECL(int) RTNetMaskToPrefixIPv4(PCRTNETADDRIPV4 pMask, int *piPrefix)
     uint32_t uPrefixMask = UINT32_C(0xffffffff);
     int iPrefixLen = 32;
 
-    while (iPrefixLen > 0) { 
-	if (uMask == uPrefixMask)
-	{
-	    if (piPrefix != NULL)
-		*piPrefix = iPrefixLen;
-	    return VINF_SUCCESS;
-	}
+    while (iPrefixLen > 0)
+    {
+        if (uMask == uPrefixMask)
+        {
+            if (piPrefix != NULL)
+                *piPrefix = iPrefixLen;
+            return VINF_SUCCESS;
+        }
 
-	--iPrefixLen;
-	uPrefixMask <<= 1;
+        --iPrefixLen;
+        uPrefixMask <<= 1;
     }
 
     return VERR_INVALID_PARAMETER;
@@ -190,12 +191,12 @@ RTDECL(int) RTNetPrefixToMaskIPv4(int iPrefix, PRTNETADDRIPV4 pMask)
     AssertReturn(pMask != NULL, VERR_INVALID_PARAMETER);
 
     if (RT_UNLIKELY(iPrefix < 0 || 32 < iPrefix))
-	return VERR_INVALID_PARAMETER;
+        return VERR_INVALID_PARAMETER;
 
     if (RT_LIKELY(iPrefix != 0))
-	pMask->u = RT_H2N_U32(UINT32_C(0xffffffff) << (32 - iPrefix));
+        pMask->u = RT_H2N_U32(UINT32_C(0xffffffff) << (32 - iPrefix));
     else /* avoid UB in the shift */
-	pMask->u = 0;
+        pMask->u = 0;
 
     return VINF_SUCCESS;
 }
@@ -254,7 +255,7 @@ DECLHIDDEN(int) rtNetStrToIPv6AddrBase(const char *pcszAddr, PRTNETADDRIPV6 pAdd
     uint16_t u16;
     int rc;
 
-    memset(&ipv6, 0, sizeof(ipv6));
+    RT_ZERO(ipv6);
 
     pcszPos = pcszAddr;
 
@@ -325,7 +326,7 @@ DECLHIDDEN(int) rtNetStrToIPv6AddrBase(const char *pcszAddr, PRTNETADDRIPV6 pAdd
         const int iMaybeStart = iGroup;
         int j;
 
-        memset(&ipv6Tail, 0, sizeof(ipv6Tail));
+        RT_ZERO(ipv6Tail);
 
         /*
          * We try to accept longest match; we'll shift if necessary.
@@ -509,3 +510,74 @@ RTDECL(bool) RTNetStrIsIPv6AddrAny(const char *pcszAddr)
     return true;
 }
 RT_EXPORT_SYMBOL(RTNetStrIsIPv6AddrAny);
+
+
+RTDECL(int) RTNetMaskToPrefixIPv6(PCRTNETADDRIPV6 pMask, int *piPrefix)
+{
+    AssertReturn(pMask != NULL, VERR_INVALID_PARAMETER);
+
+    int iPrefix = 0;
+    unsigned int i;
+
+    for (i = 0; i < RT_ELEMENTS(pMask->au8); ++i)
+    {
+        int iBits;
+        switch (pMask->au8[i])
+        {
+            case 0x00: iBits = 0; break;
+            case 0x80: iBits = 1; break;
+            case 0xc0: iBits = 2; break;
+            case 0xe0: iBits = 3; break;
+            case 0xf0: iBits = 4; break;
+            case 0xf8: iBits = 5; break;
+            case 0xfc: iBits = 6; break;
+            case 0xfe: iBits = 7; break;
+            case 0xff: iBits = 8; break;
+            default:                /* non-contiguous mask */
+                return VERR_INVALID_PARAMETER;
+        }
+
+        iPrefix += iBits;
+        if (iBits != 8)
+            break;
+    }
+
+    for (++i; i < RT_ELEMENTS(pMask->au8); ++i)
+        if (pMask->au8[i] != 0)
+            return VERR_INVALID_PARAMETER;
+
+    if (piPrefix != NULL)
+        *piPrefix = iPrefix;
+    return VINF_SUCCESS;
+}
+RT_EXPORT_SYMBOL(RTNetMaskToPrefixIPv6);
+
+
+RTDECL(int) RTNetPrefixToMaskIPv6(int iPrefix, PRTNETADDRIPV6 pMask)
+{
+    AssertReturn(pMask != NULL, VERR_INVALID_PARAMETER);
+
+    if (RT_UNLIKELY(iPrefix < 0 || 128 < iPrefix))
+        return VERR_INVALID_PARAMETER;
+
+    for (unsigned int i = 0; i < RT_ELEMENTS(pMask->au32); ++i)
+    {
+        if (iPrefix == 0)
+        {
+            pMask->au32[i] = 0;
+        }
+        else if (iPrefix >= 32)
+        {
+            pMask->au32[i] = UINT32_C(0xffffffff);
+            iPrefix -= 32;
+        }
+        else
+        {
+            pMask->au32[i] = RT_H2N_U32(UINT32_C(0xffffffff) << (32 - iPrefix));
+            iPrefix = 0;
+        }
+    }
+
+    return VINF_SUCCESS;
+}
+RT_EXPORT_SYMBOL(RTNetPrefixToMaskIPv6);
diff --git a/src/VBox/Runtime/common/rand/randadv.cpp b/src/VBox/Runtime/common/rand/randadv.cpp
index f3be18b..227ce76 100644
--- a/src/VBox/Runtime/common/rand/randadv.cpp
+++ b/src/VBox/Runtime/common/rand/randadv.cpp
@@ -221,11 +221,11 @@ DECLHIDDEN(DECLCALLBACK(void))  rtRandAdvSynthesizeBytesFromU32(PRTRANDINT pThis
         switch (cb)
         {
             case 4:
-                pb[3] = (uint8_t)(u32 >> 24);
+                pb[3] = (uint8_t)(u32 >> 24); /* fall thru */
             case 3:
-                pb[2] = (uint8_t)(u32 >> 16);
+                pb[2] = (uint8_t)(u32 >> 16); /* fall thru */
             case 2:
-                pb[1] = (uint8_t)(u32 >> 8);
+                pb[1] = (uint8_t)(u32 >> 8);  /* fall thru */
             case 1:
                 pb[0] = (uint8_t)u32;
             return; /* done */
@@ -253,19 +253,19 @@ DECLHIDDEN(DECLCALLBACK(void))  rtRandAdvSynthesizeBytesFromU64(PRTRANDINT pThis
         switch (cb)
         {
             case 8:
-                pb[7] = (uint8_t)(u64 >> 56);
+                pb[7] = (uint8_t)(u64 >> 56); /* fall thru */
             case 7:
-                pb[6] = (uint8_t)(u64 >> 48);
+                pb[6] = (uint8_t)(u64 >> 48); /* fall thru */
             case 6:
-                pb[5] = (uint8_t)(u64 >> 40);
+                pb[5] = (uint8_t)(u64 >> 40); /* fall thru */
             case 5:
-                pb[4] = (uint8_t)(u64 >> 32);
+                pb[4] = (uint8_t)(u64 >> 32); /* fall thru */
             case 4:
-                pb[3] = (uint8_t)(u64 >> 24);
+                pb[3] = (uint8_t)(u64 >> 24); /* fall thru */
             case 3:
-                pb[2] = (uint8_t)(u64 >> 16);
+                pb[2] = (uint8_t)(u64 >> 16); /* fall thru */
             case 2:
-                pb[1] = (uint8_t)(u64 >> 8);
+                pb[1] = (uint8_t)(u64 >> 8);  /* fall thru */
             case 1:
                 pb[0] = (uint8_t)u64;
             return; /* done */
diff --git a/src/VBox/Runtime/common/string/RTUtf16NICmpAscii.cpp b/src/VBox/Runtime/common/string/RTUtf16NICmpAscii.cpp
new file mode 100644
index 0000000..692b31c
--- /dev/null
+++ b/src/VBox/Runtime/common/string/RTUtf16NICmpAscii.cpp
@@ -0,0 +1,61 @@
+/* $Id: RTUtf16NICmpAscii.cpp $ */
+/** @file
+ * IPRT - RTUtf16ICmpAscii.
+ */
+
+/*
+ * Copyright (C) 2010-2016 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.
+ */
+
+
+/*********************************************************************************************************************************
+*   Header Files                                                                                                                 *
+*********************************************************************************************************************************/
+#include <iprt/string.h>
+#include "internal/iprt.h"
+
+#include <iprt/assert.h>
+#include <iprt/ctype.h>
+
+
+RTDECL(int) RTUtf16NICmpAscii(PCRTUTF16 pwsz1, const char *psz2, size_t cwcMax)
+{
+    for (;;)
+    {
+        if (cwcMax == 0)
+            return 0;
+
+        RTUTF16         wc1  = *pwsz1++;
+        unsigned char   uch2 = *psz2++; Assert(uch2 < 0x80);
+        if (wc1 != uch2)
+        {
+            if (wc1 >= 0x80)
+                return 1;
+            if (RT_C_TO_LOWER(wc1) != RT_C_TO_LOWER(uch2))
+                return wc1 < uch2 ? -1 : 1;
+        }
+
+        if (!uch2)
+            return 0;
+        cwcMax--;
+    }
+}
+RT_EXPORT_SYMBOL(RTUtf16NICmpAscii);
+
diff --git a/src/VBox/Runtime/common/string/strformat.cpp b/src/VBox/Runtime/common/string/strformat.cpp
index 99dd9a2..a09ed6a 100644
--- a/src/VBox/Runtime/common/string/strformat.cpp
+++ b/src/VBox/Runtime/common/string/strformat.cpp
@@ -658,6 +658,7 @@ RTDECL(size_t) RTStrFormatV(PFNRTSTROUTPUT pfnOutput, void *pvArgOutput, PFNSTRF
 
                             case 'X':
                                 fFlags |= RTSTR_F_CAPITAL;
+                                /* fall thru */
                             case 'x':
                                 uBase = 16;
                                 break;
diff --git a/src/VBox/Runtime/common/string/strformatnum.cpp b/src/VBox/Runtime/common/string/strformatnum.cpp
index 15d2e70..bc95db7 100644
--- a/src/VBox/Runtime/common/string/strformatnum.cpp
+++ b/src/VBox/Runtime/common/string/strformatnum.cpp
@@ -160,14 +160,77 @@ RTDECL(ssize_t) RTStrFormatU128(char *pszBuf, size_t cbBuf, PCRTUINT128U pu128,
         fFlags |= RTSTR_F_SPECIAL;
     fFlags &= ~RTSTR_F_BIT_MASK;
 
-    char szTmp[64+32];
-    size_t cchFirst  = RTStrFormatNumber(szTmp, pu128->s.Hi, 16, 0, 0, fFlags | RTSTR_F_64BIT);
-    size_t cchSecond = RTStrFormatNumber(&szTmp[cchFirst], pu128->s.Lo, 16, 8, 0,
-                                         (fFlags | RTSTR_F_64BIT | RTSTR_F_ZEROPAD) & ~RTSTR_F_SPECIAL);
-    int rc = RTStrCopy(pszBuf, cbBuf, szTmp);
-    if (RT_FAILURE(rc))
-        return rc;
-    return cchFirst + cchSecond;
+    char szTmp[64+32+32+32];
+    char *pszTmp = cbBuf >= sizeof(szTmp) ? pszBuf : szTmp;
+    size_t cchResult = RTStrFormatNumber(pszTmp, pu128->QWords.qw1, 16, 0, 0, fFlags | RTSTR_F_64BIT);
+    cchResult += RTStrFormatNumber(&pszTmp[cchResult], pu128->QWords.qw0, 16, 8, 0,
+                                   (fFlags | RTSTR_F_64BIT | RTSTR_F_ZEROPAD) & ~RTSTR_F_SPECIAL);
+    if (pszTmp == pszBuf)
+        return cchResult;
+    int rc = RTStrCopy(pszBuf, cbBuf, pszTmp);
+    if (RT_SUCCESS(rc))
+        return cchResult;
+    return rc;
+}
+
+
+RTDECL(ssize_t) RTStrFormatU256(char *pszBuf, size_t cbBuf, PCRTUINT256U pu256, unsigned int uiBase,
+                                signed int cchWidth, signed int cchPrecision, uint32_t fFlags)
+{
+    NOREF(cchWidth); NOREF(cchPrecision);
+    if (uiBase != 16)
+        fFlags |= RTSTR_F_SPECIAL;
+    fFlags &= ~RTSTR_F_BIT_MASK;
+
+    char szTmp[64+32+32+32];
+    char *pszTmp = cbBuf >= sizeof(szTmp) ? pszBuf : szTmp;
+    size_t cchResult = RTStrFormatNumber(pszTmp, pu256->QWords.qw3, 16, 0, 0, fFlags | RTSTR_F_64BIT);
+    cchResult += RTStrFormatNumber(&pszTmp[cchResult], pu256->QWords.qw2, 16, 8, 0,
+                                   (fFlags | RTSTR_F_64BIT | RTSTR_F_ZEROPAD) & ~RTSTR_F_SPECIAL);
+    cchResult += RTStrFormatNumber(&pszTmp[cchResult], pu256->QWords.qw1, 16, 8, 0,
+                                   (fFlags | RTSTR_F_64BIT | RTSTR_F_ZEROPAD) & ~RTSTR_F_SPECIAL);
+    cchResult += RTStrFormatNumber(&pszTmp[cchResult], pu256->QWords.qw0, 16, 8, 0,
+                                   (fFlags | RTSTR_F_64BIT | RTSTR_F_ZEROPAD) & ~RTSTR_F_SPECIAL);
+    if (pszTmp == pszBuf)
+        return cchResult;
+    int rc = RTStrCopy(pszBuf, cbBuf, pszTmp);
+    if (RT_SUCCESS(rc))
+        return cchResult;
+    return rc;
+}
+
+
+RTDECL(ssize_t) RTStrFormatU512(char *pszBuf, size_t cbBuf, PCRTUINT512U pu512, unsigned int uiBase,
+                                signed int cchWidth, signed int cchPrecision, uint32_t fFlags)
+{
+    NOREF(cchWidth); NOREF(cchPrecision);
+    if (uiBase != 16)
+        fFlags |= RTSTR_F_SPECIAL;
+    fFlags &= ~RTSTR_F_BIT_MASK;
+
+    char szTmp[64+32+32+32 + 32+32+32+32];
+    char *pszTmp = cbBuf >= sizeof(szTmp) ? pszBuf : szTmp;
+    size_t cchResult = RTStrFormatNumber(pszTmp, pu512->QWords.qw7, 16, 0, 0, fFlags | RTSTR_F_64BIT);
+    cchResult += RTStrFormatNumber(&pszTmp[cchResult], pu512->QWords.qw6, 16, 8, 0,
+                                   (fFlags | RTSTR_F_64BIT | RTSTR_F_ZEROPAD) & ~RTSTR_F_SPECIAL);
+    cchResult += RTStrFormatNumber(&pszTmp[cchResult], pu512->QWords.qw5, 16, 8, 0,
+                                   (fFlags | RTSTR_F_64BIT | RTSTR_F_ZEROPAD) & ~RTSTR_F_SPECIAL);
+    cchResult += RTStrFormatNumber(&pszTmp[cchResult], pu512->QWords.qw4, 16, 8, 0,
+                                   (fFlags | RTSTR_F_64BIT | RTSTR_F_ZEROPAD) & ~RTSTR_F_SPECIAL);
+    cchResult += RTStrFormatNumber(&pszTmp[cchResult], pu512->QWords.qw3, 16, 8, 0,
+                                   (fFlags | RTSTR_F_64BIT | RTSTR_F_ZEROPAD) & ~RTSTR_F_SPECIAL);
+    cchResult += RTStrFormatNumber(&pszTmp[cchResult], pu512->QWords.qw2, 16, 8, 0,
+                                   (fFlags | RTSTR_F_64BIT | RTSTR_F_ZEROPAD) & ~RTSTR_F_SPECIAL);
+    cchResult += RTStrFormatNumber(&pszTmp[cchResult], pu512->QWords.qw1, 16, 8, 0,
+                                   (fFlags | RTSTR_F_64BIT | RTSTR_F_ZEROPAD) & ~RTSTR_F_SPECIAL);
+    cchResult += RTStrFormatNumber(&pszTmp[cchResult], pu512->QWords.qw0, 16, 8, 0,
+                                   (fFlags | RTSTR_F_64BIT | RTSTR_F_ZEROPAD) & ~RTSTR_F_SPECIAL);
+    if (pszTmp == pszBuf)
+        return cchResult;
+    int rc = RTStrCopy(pszBuf, cbBuf, pszTmp);
+    if (RT_SUCCESS(rc))
+        return cchResult;
+    return rc;
 }
 
 
diff --git a/src/VBox/Runtime/common/string/strformatrt.cpp b/src/VBox/Runtime/common/string/strformatrt.cpp
index 9837c1c..fdc48bb 100644
--- a/src/VBox/Runtime/common/string/strformatrt.cpp
+++ b/src/VBox/Runtime/common/string/strformatrt.cpp
@@ -82,9 +82,9 @@ static size_t rtstrFormatIPv6HexWord(char *pszDst, uint16_t uWord)
     off = 0;
     switch (cDigits)
     {
-        case 4: pszDst[off++] = g_szHexDigits[(uWord >> 12) & 0xf];
-        case 3: pszDst[off++] = g_szHexDigits[(uWord >>  8) & 0xf];
-        case 2: pszDst[off++] = g_szHexDigits[(uWord >>  4) & 0xf];
+        case 4: pszDst[off++] = g_szHexDigits[(uWord >> 12) & 0xf]; /* fall thru */
+        case 3: pszDst[off++] = g_szHexDigits[(uWord >>  8) & 0xf]; /* fall thru */
+        case 2: pszDst[off++] = g_szHexDigits[(uWord >>  4) & 0xf]; /* fall thru */
         case 1: pszDst[off++] = g_szHexDigits[(uWord >>  0) & 0xf];
             break;
     }
diff --git a/src/VBox/Runtime/common/string/strprintf.cpp b/src/VBox/Runtime/common/string/strprintf.cpp
index bf11477..741b7ba 100644
--- a/src/VBox/Runtime/common/string/strprintf.cpp
+++ b/src/VBox/Runtime/common/string/strprintf.cpp
@@ -66,30 +66,62 @@ static DECLCALLBACK(size_t) strbufoutput(void *pvArg, const char *pachChars, siz
 static DECLCALLBACK(size_t) strbufoutput(void *pvArg, const char *pachChars, size_t cbChars)
 {
     PSTRBUFARG  pArg = (PSTRBUFARG)pvArg;
+    char *pszCur = pArg->psz; /* We actually have to spell this out for VS2010, or it will load for each case. */
 
     cbChars = RT_MIN(pArg->cch, cbChars);
     if (cbChars)
     {
-        memcpy(pArg->psz, pachChars, cbChars);
         pArg->cch -= cbChars;
-        pArg->psz += cbChars;
+
+        /* Note! For VS2010/64 we need at least 7 case statements before it generates a jump table. */
+        switch (cbChars)
+        {
+            default:
+                memcpy(pszCur, pachChars, cbChars);
+                break;
+            case 8: pszCur[7] = pachChars[7]; /* fall thru */
+            case 7: pszCur[6] = pachChars[6]; /* fall thru */
+            case 6: pszCur[5] = pachChars[5]; /* fall thru */
+            case 5: pszCur[4] = pachChars[4]; /* fall thru */
+            case 4: pszCur[3] = pachChars[3]; /* fall thru */
+            case 3: pszCur[2] = pachChars[2]; /* fall thru */
+            case 2: pszCur[1] = pachChars[1]; /* fall thru */
+            case 1: pszCur[0] = pachChars[0]; /* fall thru */
+            case 0:
+                break;
+        }
+        pArg->psz = pszCur += cbChars;
     }
-    *pArg->psz = '\0';
+    *pszCur = '\0';
 
     return cbChars;
 }
 
 
-RTDECL(size_t) RTStrPrintfExV(PFNSTRFORMAT pfnFormat, void *pvArg, char *pszBuffer, size_t cchBuffer, const char *pszFormat, va_list args)
+RTDECL(size_t) RTStrPrintf(char *pszBuffer, size_t cchBuffer, const char *pszFormat, ...)
 {
+    /* Explicitly inline RTStrPrintfV + RTStrPrintfExV here because this is a frequently use API. */
     STRBUFARG Arg;
+    va_list args;
+    size_t cbRet;
 
-    if (!cchBuffer)
-    {
-        AssertMsgFailed(("Excellent idea! Format a string with no space for the output!\n"));
-        return 0;
-    }
+    AssertMsgReturn(cchBuffer, ("Excellent idea! Format a string with no space for the output!\n"), 0);
+    Arg.psz = pszBuffer;
+    Arg.cch = cchBuffer - 1;
+
+    va_start(args, pszFormat);
+    cbRet = RTStrFormatV(strbufoutput, &Arg, NULL, NULL, pszFormat, args);
+    va_end(args);
+
+    return cbRet;
+}
+RT_EXPORT_SYMBOL(RTStrPrintf);
 
+
+RTDECL(size_t) RTStrPrintfExV(PFNSTRFORMAT pfnFormat, void *pvArg, char *pszBuffer, size_t cchBuffer, const char *pszFormat, va_list args)
+{
+    STRBUFARG Arg;
+    AssertMsgReturn(cchBuffer, ("Excellent idea! Format a string with no space for the output!\n"), 0);
     Arg.psz = pszBuffer;
     Arg.cch = cchBuffer - 1;
     return RTStrFormatV(strbufoutput, &Arg, pfnFormat, pvArg, pszFormat, args);
@@ -115,15 +147,3 @@ RTDECL(size_t) RTStrPrintfEx(PFNSTRFORMAT pfnFormat, void *pvArg, char *pszBuffe
 }
 RT_EXPORT_SYMBOL(RTStrPrintfEx);
 
-
-RTDECL(size_t) RTStrPrintf(char *pszBuffer, size_t cchBuffer, const char *pszFormat, ...)
-{
-    va_list args;
-    size_t cbRet;
-    va_start(args, pszFormat);
-    cbRet = RTStrPrintfV(pszBuffer, cchBuffer, pszFormat, args);
-    va_end(args);
-    return cbRet;
-}
-RT_EXPORT_SYMBOL(RTStrPrintf);
-
diff --git a/src/VBox/Runtime/common/string/utf-8.cpp b/src/VBox/Runtime/common/string/utf-8.cpp
index cf8fd2c..a7efe7a 100644
--- a/src/VBox/Runtime/common/string/utf-8.cpp
+++ b/src/VBox/Runtime/common/string/utf-8.cpp
@@ -93,12 +93,16 @@ DECLHIDDEN(int) rtUtf8Length(const char *psz, size_t cch, size_t *pcuc, size_t *
             {
                 case 6:
                     RTStrAssertMsgReturn((puch[5] & (RT_BIT(7) | RT_BIT(6))) == RT_BIT(7), ("6/%u: %.*Rhxs\n", cb, RT_MIN(cb + 10, cch), puch), VERR_INVALID_UTF8_ENCODING);
+                    /* fall thru */
                 case 5:
                     RTStrAssertMsgReturn((puch[4] & (RT_BIT(7) | RT_BIT(6))) == RT_BIT(7), ("5/%u: %.*Rhxs\n", cb, RT_MIN(cb + 10, cch), puch), VERR_INVALID_UTF8_ENCODING);
+                    /* fall thru */
                 case 4:
                     RTStrAssertMsgReturn((puch[3] & (RT_BIT(7) | RT_BIT(6))) == RT_BIT(7), ("4/%u: %.*Rhxs\n", cb, RT_MIN(cb + 10, cch), puch), VERR_INVALID_UTF8_ENCODING);
+                    /* fall thru */
                 case 3:
                     RTStrAssertMsgReturn((puch[2] & (RT_BIT(7) | RT_BIT(6))) == RT_BIT(7), ("3/%u: %.*Rhxs\n", cb, RT_MIN(cb + 10, cch), puch), VERR_INVALID_UTF8_ENCODING);
+                    /* fall thru */
                 case 2:
                     RTStrAssertMsgReturn((puch[1] & (RT_BIT(7) | RT_BIT(6))) == RT_BIT(7), ("2/%u: %.*Rhxs\n", cb, RT_MIN(cb + 10, cch), puch), VERR_INVALID_UTF8_ENCODING);
                    break;
@@ -589,12 +593,16 @@ static int rtUtf8CalcUtf16Length(const char *psz, size_t cch, size_t *pcwc)
             {
                 case 6:
                     RTStrAssertMsgReturn((puch[5] & (RT_BIT(7) | RT_BIT(6))) == RT_BIT(7), ("6/%u: %.*Rhxs\n", cb, RT_MIN(cb + 10, cch), puch), VERR_INVALID_UTF8_ENCODING);
+                    /* fall thru */
                 case 5:
                     RTStrAssertMsgReturn((puch[4] & (RT_BIT(7) | RT_BIT(6))) == RT_BIT(7), ("5/%u: %.*Rhxs\n", cb, RT_MIN(cb + 10, cch), puch), VERR_INVALID_UTF8_ENCODING);
+                    /* fall thru */
                 case 4:
                     RTStrAssertMsgReturn((puch[3] & (RT_BIT(7) | RT_BIT(6))) == RT_BIT(7), ("4/%u: %.*Rhxs\n", cb, RT_MIN(cb + 10, cch), puch), VERR_INVALID_UTF8_ENCODING);
+                    /* fall thru */
                 case 3:
                     RTStrAssertMsgReturn((puch[2] & (RT_BIT(7) | RT_BIT(6))) == RT_BIT(7), ("3/%u: %.*Rhxs\n", cb, RT_MIN(cb + 10, cch), puch), VERR_INVALID_UTF8_ENCODING);
+                    /* fall thru */
                 case 2:
                     RTStrAssertMsgReturn((puch[1] & (RT_BIT(7) | RT_BIT(6))) == RT_BIT(7), ("2/%u: %.*Rhxs\n", cb, RT_MIN(cb + 10, cch), puch), VERR_INVALID_UTF8_ENCODING);
                    break;
@@ -1323,15 +1331,19 @@ RTDECL(int) RTStrGetCpExInternal(const char **ppsz, PRTUNICP pCp)
             case 6:
                 RTStrAssertMsgReturn((puch[5] & 0xc0) == 0x80, ("6/%u: %.*Rhxs\n", cb, RT_MIN(cb + 10, strlen((char *)puch)), puch),
                                      rtStrGetCpExFailure(ppsz, pCp, VERR_INVALID_UTF8_ENCODING));
+                /* fall thru */
             case 5:
                 RTStrAssertMsgReturn((puch[4] & 0xc0) == 0x80, ("5/%u: %.*Rhxs\n", cb, RT_MIN(cb + 10, strlen((char *)puch)), puch),
                                      rtStrGetCpExFailure(ppsz, pCp, VERR_INVALID_UTF8_ENCODING));
+                /* fall thru */
             case 4:
                 RTStrAssertMsgReturn((puch[3] & 0xc0) == 0x80, ("4/%u: %.*Rhxs\n", cb, RT_MIN(cb + 10, strlen((char *)puch)), puch),
                                      rtStrGetCpExFailure(ppsz, pCp, VERR_INVALID_UTF8_ENCODING));
+                /* fall thru */
             case 3:
                 RTStrAssertMsgReturn((puch[2] & 0xc0) == 0x80, ("3/%u: %.*Rhxs\n", cb, RT_MIN(cb + 10, strlen((char *)puch)), puch),
                                      rtStrGetCpExFailure(ppsz, pCp, VERR_INVALID_UTF8_ENCODING));
+                /* fall thru */
             case 2:
                 RTStrAssertMsgReturn((puch[1] & 0xc0) == 0x80, ("2/%u: %.*Rhxs\n", cb, RT_MIN(cb + 10, strlen((char *)puch)), puch),
                                      rtStrGetCpExFailure(ppsz, pCp, VERR_INVALID_UTF8_ENCODING));
@@ -1478,15 +1490,19 @@ RTDECL(int) RTStrGetCpNExInternal(const char **ppsz, size_t *pcch, PRTUNICP pCp)
             case 6:
                 RTStrAssertMsgReturn((puch[5] & 0xc0) == 0x80, ("6/%u: %.*Rhxs\n", cb, RT_MIN(cb + 10, strlen((char *)puch)), puch),
                                      rtStrGetCpNExFailure(ppsz, pcch, pCp, VERR_INVALID_UTF8_ENCODING));
+                /* fall thru */
             case 5:
                 RTStrAssertMsgReturn((puch[4] & 0xc0) == 0x80, ("5/%u: %.*Rhxs\n", cb, RT_MIN(cb + 10, strlen((char *)puch)), puch),
                                      rtStrGetCpNExFailure(ppsz, pcch, pCp, VERR_INVALID_UTF8_ENCODING));
+                /* fall thru */
             case 4:
                 RTStrAssertMsgReturn((puch[3] & 0xc0) == 0x80, ("4/%u: %.*Rhxs\n", cb, RT_MIN(cb + 10, strlen((char *)puch)), puch),
                                      rtStrGetCpNExFailure(ppsz, pcch, pCp, VERR_INVALID_UTF8_ENCODING));
+                /* fall thru */
             case 3:
                 RTStrAssertMsgReturn((puch[2] & 0xc0) == 0x80, ("3/%u: %.*Rhxs\n", cb, RT_MIN(cb + 10, strlen((char *)puch)), puch),
                                      rtStrGetCpNExFailure(ppsz, pcch, pCp, VERR_INVALID_UTF8_ENCODING));
+                /* fall thru */
             case 2:
                 RTStrAssertMsgReturn((puch[1] & 0xc0) == 0x80, ("2/%u: %.*Rhxs\n", cb, RT_MIN(cb + 10, strlen((char *)puch)), puch),
                                      rtStrGetCpNExFailure(ppsz, pcch, pCp, VERR_INVALID_UTF8_ENCODING));
diff --git a/src/VBox/Runtime/common/zip/tarvfs.cpp b/src/VBox/Runtime/common/zip/tarvfs.cpp
index c2a75a6..e5f4230 100644
--- a/src/VBox/Runtime/common/zip/tarvfs.cpp
+++ b/src/VBox/Runtime/common/zip/tarvfs.cpp
@@ -870,15 +870,18 @@ static bool rtZipTarReaderExpectingMoreHeaders(PRTZIPTARREADER pThis)
  */
 static bool rtZipTarReaderIsAtEnd(PRTZIPTARREADER pThis)
 {
-    /* Turns out our own tar writer code doesn't get this crap right.
-       Kludge our way around it. */
-    if (!pThis->cZeroHdrs)
-        return pThis->enmPrevType == RTZIPTARTYPE_GNU ? true /* IPRT tar.cpp */ : false;
-
-    /* Here is a kludge to try deal with archivers not putting at least two
-       zero headers at the end.  Afraid it may require further relaxing
-       later on, but let's try be strict about things for now. */
-    return pThis->cZeroHdrs >= (pThis->enmPrevType == RTZIPTARTYPE_POSIX ? 2U : 1U);
+    /*
+     * In theory there shall always be two zero headers at the end of the
+     * archive, but life isn't that simple.   We've been creating archives
+     * without any zero headers at the end ourselves for a long long time
+     * (old tar.cpp).
+     *
+     * So, we're fine if the state is 'FIRST' or 'ZERO' here, but we'll barf
+     * if we're in the middle of a multi-header stream (long GNU names, sparse
+     * files, PAX, etc).
+     */
+    return pThis->enmState == RTZIPTARREADERSTATE_FIRST
+        || pThis->enmState == RTZIPTARREADERSTATE_ZERO;
 }
 
 
diff --git a/src/VBox/Runtime/nt/RTErrConvertFromNtStatus.cpp b/src/VBox/Runtime/nt/RTErrConvertFromNtStatus.cpp
index 5a7ba47..6a765f5 100644
--- a/src/VBox/Runtime/nt/RTErrConvertFromNtStatus.cpp
+++ b/src/VBox/Runtime/nt/RTErrConvertFromNtStatus.cpp
@@ -32,6 +32,10 @@
 typedef long NTSTATUS;                  /** @todo figure out which headers to include to get this one typedef... */
 
 #include <iprt/err.h>
+#ifdef VBOX
+# include <VBox/err.h>
+#endif
+#include <iprt/log.h>
 #include <iprt/assert.h>
 
 
@@ -67,6 +71,10 @@ RTDECL(int)  RTErrConvertFromNtStatus(long lNativeCode)
 
         case STATUS_UNEXPECTED_NETWORK_ERROR:
                                             return VERR_NET_IO_ERROR;
+        case STATUS_INVALID_IMAGE_HASH:     return VERR_LDR_IMAGE_HASH;
+#ifdef VBOX
+        case STATUS_TRUST_FAILURE:          return VERR_SUPLIB_NT_PROCESS_UNTRUSTED_5;
+#endif
     }
 
     /* unknown error. */
diff --git a/src/VBox/Runtime/r0drv/linux/memobj-r0drv-linux.c b/src/VBox/Runtime/r0drv/linux/memobj-r0drv-linux.c
index 4bc2a9b..bcdfb00 100644
--- a/src/VBox/Runtime/r0drv/linux/memobj-r0drv-linux.c
+++ b/src/VBox/Runtime/r0drv/linux/memobj-r0drv-linux.c
@@ -902,6 +902,9 @@ static struct page *rtR0MemObjLinuxVirtToPage(void *pv)
     union
     {
         pgd_t       Global;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)
+        p4d_t       Four;
+#endif
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 11)
         pud_t       Upper;
 #endif
@@ -917,9 +920,24 @@ static struct page *rtR0MemObjLinuxVirtToPage(void *pv)
     u.Global = *pgd_offset(current->active_mm, ulAddr);
     if (RT_UNLIKELY(pgd_none(u.Global)))
         return NULL;
-
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 11)
+# if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)
+    u.Four  = *p4d_offset(&u.Global, ulAddr);
+    if (RT_UNLIKELY(p4d_none(u.Four)))
+        return NULL;
+    if (p4d_large(u.Four))
+    {
+        pPage = p4d_page(u.Four);
+        AssertReturn(pPage, NULL);
+        pfn   = page_to_pfn(pPage);      /* doing the safe way... */
+        AssertCompile(P4D_SHIFT - PAGE_SHIFT < 31);
+        pfn  += (ulAddr >> PAGE_SHIFT) & ((UINT32_C(1) << (P4D_SHIFT - PAGE_SHIFT)) - 1);
+        return pfn_to_page(pfn);
+    }
+    u.Upper = *pud_offset(&u.Four, ulAddr);
+# else /* < 4.12 */
     u.Upper = *pud_offset(&u.Global, ulAddr);
+# endif /* < 4.12 */
     if (RT_UNLIKELY(pud_none(u.Upper)))
         return NULL;
 # if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)
@@ -932,7 +950,6 @@ static struct page *rtR0MemObjLinuxVirtToPage(void *pv)
         return pfn_to_page(pfn);
     }
 # endif
-
     u.Middle = *pmd_offset(&u.Upper, ulAddr);
 #else  /* < 2.6.11 */
     u.Middle = *pmd_offset(&u.Global, ulAddr);
diff --git a/src/VBox/Runtime/r0drv/linux/mp-r0drv-linux.c b/src/VBox/Runtime/r0drv/linux/mp-r0drv-linux.c
index c873e4a..3a7acba 100644
--- a/src/VBox/Runtime/r0drv/linux/mp-r0drv-linux.c
+++ b/src/VBox/Runtime/r0drv/linux/mp-r0drv-linux.c
@@ -384,7 +384,10 @@ RTDECL(int) RTMpOnPair(RTCPUID idCpu1, RTCPUID idCpu2, uint32_t fFlags, PFNRTMPW
          * CPUs is the one we're running on, we must do the call and the post
          * call wait ourselves.
          */
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28)
+        /* 2.6.28 introduces CONFIG_CPUMASK_OFFSTACK */
+        cpumask_var_t DstCpuMask;
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
         cpumask_t   DstCpuMask;
 #endif
         RTCPUID     idCpuSelf = RTMpCpuId();
@@ -397,10 +400,17 @@ RTDECL(int) RTMpOnPair(RTCPUID idCpu1, RTCPUID idCpu2, uint32_t fFlags, PFNRTMPW
         Args.idCpu2  = idCpu2;
         Args.cHits   = 0;
 
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28)
-        cpumask_clear(&DstCpuMask);
-        cpumask_set_cpu(idCpu1, &DstCpuMask);
-        cpumask_set_cpu(idCpu2, &DstCpuMask);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 30)
+        if (!zalloc_cpumask_var(&DstCpuMask, GFP_KERNEL))
+            return VERR_NO_MEMORY;
+        cpumask_set_cpu(idCpu1, DstCpuMask);
+        cpumask_set_cpu(idCpu2, DstCpuMask);
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28)
+        if (!alloc_cpumask_var(&DstCpuMask, GFP_KERNEL))
+            return VERR_NO_MEMORY;
+        cpumask_clear(DstCpuMask);
+        cpumask_set_cpu(idCpu1, DstCpuMask);
+        cpumask_set_cpu(idCpu2, DstCpuMask);
 #elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
         cpus_clear(DstCpuMask);
         cpu_set(idCpu1, DstCpuMask);
@@ -408,7 +418,7 @@ RTDECL(int) RTMpOnPair(RTCPUID idCpu1, RTCPUID idCpu2, uint32_t fFlags, PFNRTMPW
 #endif
 
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28)
-        smp_call_function_many(&DstCpuMask, rtmpLinuxWrapperPostInc, &Args, !fCallSelf /* wait */);
+        smp_call_function_many(DstCpuMask, rtmpLinuxWrapperPostInc, &Args, !fCallSelf /* wait */);
         rc = 0;
 #elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
         rc = smp_call_function_mask(DstCpuMask, rtmpLinuxWrapperPostInc, &Args, !fCallSelf /* wait */);
@@ -440,6 +450,10 @@ RTDECL(int) RTMpOnPair(RTCPUID idCpu1, RTCPUID idCpu2, uint32_t fFlags, PFNRTMPW
             rc = VERR_CPU_OFFLINE;
         else
             rc = VERR_CPU_IPE_1;
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28)
+        free_cpumask_var(DstCpuMask);
+#endif
     }
     /*
      * A CPU must be present to be considered just offline.
diff --git a/src/VBox/Runtime/r0drv/linux/the-linux-kernel.h b/src/VBox/Runtime/r0drv/linux/the-linux-kernel.h
index 5a7ccb2..3a17bd1 100644
--- a/src/VBox/Runtime/r0drv/linux/the-linux-kernel.h
+++ b/src/VBox/Runtime/r0drv/linux/the-linux-kernel.h
@@ -159,6 +159,11 @@
 # include <asm/tlbflush.h>
 #endif
 
+/* for set_pages_x() */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)
+# include <asm/set_memory.h>
+#endif
+
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 7, 0)
 # include <asm/smap.h>
 #else
diff --git a/src/VBox/Runtime/r0drv/linux/waitqueue-r0drv-linux.h b/src/VBox/Runtime/r0drv/linux/waitqueue-r0drv-linux.h
index 09df351..cfa4d36 100644
--- a/src/VBox/Runtime/r0drv/linux/waitqueue-r0drv-linux.h
+++ b/src/VBox/Runtime/r0drv/linux/waitqueue-r0drv-linux.h
@@ -46,7 +46,11 @@
 typedef struct RTR0SEMLNXWAIT
 {
     /** The wait queue entry. */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 13, 0)
+    wait_queue_entry_t WaitQE;
+#else
     wait_queue_t    WaitQE;
+#endif
     /** The absolute timeout given as nano seconds since the start of the
      *  monotonic clock. */
     uint64_t        uNsAbsTimeout;
diff --git a/src/VBox/Runtime/r0drv/nt/alloc-r0drv-nt.cpp b/src/VBox/Runtime/r0drv/nt/alloc-r0drv-nt.cpp
index 5f22329..13ac189 100644
--- a/src/VBox/Runtime/r0drv/nt/alloc-r0drv-nt.cpp
+++ b/src/VBox/Runtime/r0drv/nt/alloc-r0drv-nt.cpp
@@ -35,6 +35,7 @@
 #include <iprt/assert.h>
 #include <iprt/err.h>
 #include "r0drv/alloc-r0drv.h"
+#include "internal-r0drv-nt.h"
 
 
 /**
@@ -42,19 +43,28 @@
  */
 DECLHIDDEN(int) rtR0MemAllocEx(size_t cb, uint32_t fFlags, PRTMEMHDR *ppHdr)
 {
-    if (fFlags & RTMEMHDR_FLAG_ANY_CTX)
-        return VERR_NOT_SUPPORTED;
-
-    PRTMEMHDR pHdr = (PRTMEMHDR)ExAllocatePoolWithTag(NonPagedPool, cb + sizeof(*pHdr), IPRT_NT_POOL_TAG);
-    if (RT_UNLIKELY(!pHdr))
+    if (!(fFlags & RTMEMHDR_FLAG_ANY_CTX))
+    {
+#if 1 /* This allegedly makes the driver verifier happier... */
+        POOL_TYPE enmPoolType = NonPagedPool;
+        if (!(fFlags & RTMEMHDR_FLAG_EXEC) && g_uRtNtVersion >= RTNT_MAKE_VERSION(8,0))
+            enmPoolType = NonPagedPoolNx;
+        PRTMEMHDR pHdr = (PRTMEMHDR)ExAllocatePoolWithTag(enmPoolType, cb + sizeof(*pHdr), IPRT_NT_POOL_TAG);
+#else
+        PRTMEMHDR pHdr = (PRTMEMHDR)ExAllocatePoolWithTag(NonPagedPool, cb + sizeof(*pHdr), IPRT_NT_POOL_TAG);
+#endif
+        if (pHdr)
+        {
+            pHdr->u32Magic  = RTMEMHDR_MAGIC;
+            pHdr->fFlags    = fFlags;
+            pHdr->cb        = (uint32_t)cb; Assert(pHdr->cb == cb);
+            pHdr->cbReq     = (uint32_t)cb;
+            *ppHdr = pHdr;
+            return VINF_SUCCESS;
+        }
         return VERR_NO_MEMORY;
-
-    pHdr->u32Magic  = RTMEMHDR_MAGIC;
-    pHdr->fFlags    = fFlags;
-    pHdr->cb        = (uint32_t)cb; Assert(pHdr->cb == cb);
-    pHdr->cbReq     = (uint32_t)cb;
-    *ppHdr = pHdr;
-    return VINF_SUCCESS;
+    }
+    return VERR_NOT_SUPPORTED;
 }
 
 
diff --git a/src/VBox/Runtime/r0drv/nt/initterm-r0drv-nt.cpp b/src/VBox/Runtime/r0drv/nt/initterm-r0drv-nt.cpp
index 494d94b..62f393a 100644
--- a/src/VBox/Runtime/r0drv/nt/initterm-r0drv-nt.cpp
+++ b/src/VBox/Runtime/r0drv/nt/initterm-r0drv-nt.cpp
@@ -103,6 +103,15 @@ uint32_t                                g_cbrtNtPbQuantumEnd;
 /** Offset of the _KPRCB::DpcQueueDepth field. 0 if not found. */
 uint32_t                                g_offrtNtPbDpcQueueDepth;
 
+/** The combined NT version, see RTNT_MAKE_VERSION. */
+uint32_t                                g_uRtNtVersion;
+/** The major version number. */
+uint8_t                                 g_uRtNtMajorVer;
+/** The minor version number. */
+uint8_t                                 g_uRtNtMinorVer;
+/** The build number. */
+uint32_t                                g_uRtNtBuildNo;
+
 
 /**
  * Determines the NT kernel verison information.
@@ -306,6 +315,12 @@ DECLHIDDEN(int) rtR0InitNative(void)
     RTNTSDBOSVER OsVerInfo;
     rtR0NtGetOsVersionInfo(&OsVerInfo);
 
+    /* Publish the version info in globals. */
+    g_uRtNtVersion  = RTNT_MAKE_VERSION(OsVerInfo.uMajorVer, OsVerInfo.uMinorVer);
+    g_uRtNtMinorVer = OsVerInfo.uMinorVer;
+    g_uRtNtMajorVer = OsVerInfo.uMajorVer;
+    g_uRtNtBuildNo  = OsVerInfo.uBuildNo;
+
     /*
      * Gather consistent CPU vendor string and PRCB pointers.
      */
diff --git a/src/VBox/Runtime/r0drv/nt/internal-r0drv-nt.h b/src/VBox/Runtime/r0drv/nt/internal-r0drv-nt.h
index 9e058cd..e0f7c9d 100644
--- a/src/VBox/Runtime/r0drv/nt/internal-r0drv-nt.h
+++ b/src/VBox/Runtime/r0drv/nt/internal-r0drv-nt.h
@@ -91,6 +91,14 @@ extern uint32_t                                g_offrtNtPbQuantumEnd;
 extern uint32_t                                g_cbrtNtPbQuantumEnd;
 extern uint32_t                                g_offrtNtPbDpcQueueDepth;
 
+/** Makes an NT version for checking against g_uRtNtVersion. */
+#define RTNT_MAKE_VERSION(uMajor, uMinor)       RT_MAKE_U32(uMinor, uMajor)
+
+extern uint32_t                                g_uRtNtVersion;
+extern uint8_t                                 g_uRtNtMajorVer;
+extern uint8_t                                 g_uRtNtMinorVer;
+extern uint32_t                                g_uRtNtBuildNo;
+
 
 int __stdcall rtMpPokeCpuUsingDpc(RTCPUID idCpu);
 int __stdcall rtMpPokeCpuUsingBroadcastIpi(RTCPUID idCpu);
diff --git a/src/VBox/Runtime/r0drv/nt/the-nt-kernel.h b/src/VBox/Runtime/r0drv/nt/the-nt-kernel.h
index b171981..4dde623 100644
--- a/src/VBox/Runtime/r0drv/nt/the-nt-kernel.h
+++ b/src/VBox/Runtime/r0drv/nt/the-nt-kernel.h
@@ -63,6 +63,11 @@ RT_C_DECLS_END
 # define PAGE_OFFSET_MASK (PAGE_SIZE - 1)
 #endif
 
+/* Missing if we're compiling against older WDKs. */
+#ifndef NonPagedPoolNx
+# define NonPagedPoolNx     ((POOL_TYPE)512)
+#endif
+
 /*
  * When targeting NT4 we have to undo some of the nice macros
  * installed by the later DDKs.
@@ -76,6 +81,8 @@ RT_C_DECLS_END
   NTKERNELAPI PVOID NTAPI ExAllocatePool(IN POOL_TYPE PoolType, IN SIZE_T NumberOfBytes);
 # undef ExFreePool
   NTKERNELAPI VOID NTAPI ExFreePool(IN PVOID P);
+# undef NonPagedPoolNx
+# define NonPagedPoolNx NonPagedPool
 #endif /* IPRT_TARGET_NT4 */
 
 /** @def IPRT_NT_POOL_TAG
diff --git a/src/VBox/Runtime/r3/linux/RTSystemQueryDmiString-linux.cpp b/src/VBox/Runtime/r3/linux/RTSystemQueryDmiString-linux.cpp
index 38080df..bd98127 100644
--- a/src/VBox/Runtime/r3/linux/RTSystemQueryDmiString-linux.cpp
+++ b/src/VBox/Runtime/r3/linux/RTSystemQueryDmiString-linux.cpp
@@ -67,6 +67,7 @@ RTDECL(int) RTSystemQueryDmiString(RTSYSDMISTR enmString, char *pszBuf, size_t c
         {
             case VINF_SUCCESS:
                 AssertFailed();
+                break;
             case VERR_FILE_NOT_FOUND:
             case VERR_PATH_NOT_FOUND:
             case VERR_IS_A_DIRECTORY:
diff --git a/src/VBox/Runtime/r3/nt/pathint-nt.cpp b/src/VBox/Runtime/r3/nt/pathint-nt.cpp
index 23c490a..0a1e08c 100644
--- a/src/VBox/Runtime/r3/nt/pathint-nt.cpp
+++ b/src/VBox/Runtime/r3/nt/pathint-nt.cpp
@@ -346,9 +346,28 @@ RTDECL(int) RTNtPathFromWinUtf16Ex(struct _UNICODE_STRING *pNtName, HANDLE *phRo
     if (RT_SUCCESS(rc))
     {
         /*
-         * Add prefix and convert it to UTF16.
+         * Add prefix
          */
         memcpy(szAbsPath, pszPrefix, cchPrefix);
+
+        /*
+         * Remove trailing '.' that is used to specify no extension in the Win32/DOS world.
+         */
+        size_t cchAbsPath = strlen(szAbsPath);
+        if (   cchAbsPath > 2
+            && szAbsPath[cchAbsPath - 1] == '.')
+        {
+            char const ch = szAbsPath[cchAbsPath - 2];
+            if (   ch != '/'
+                && ch != '\\'
+                && ch != ':'
+                && ch != '.')
+                szAbsPath[--cchAbsPath] = '\0';
+        }
+
+        /*
+         * Finally convert to UNICODE_STRING.
+         */
         return rtNtPathUtf8ToUniStr(pNtName, phRootDir, szAbsPath);
     }
     return rc;
diff --git a/src/VBox/Runtime/testcase/Makefile.kmk b/src/VBox/Runtime/testcase/Makefile.kmk
index f65b9ef..3d31357 100644
--- a/src/VBox/Runtime/testcase/Makefile.kmk
+++ b/src/VBox/Runtime/testcase/Makefile.kmk
@@ -87,6 +87,7 @@ PROGRAMS += \
 	tstRTList \
 	tstRTLockValidator \
 	tstLog \
+	tstRTMath \
 	tstRTMemEf \
 	tstRTMemCache \
 	tstRTMemPool \
@@ -689,6 +690,11 @@ tstRTCircBuf_SOURCES = tstRTCircBuf.cpp
 tstRTManifest_TEMPLATE = VBOXR3TSTEXE
 tstRTManifest_SOURCES = tstRTManifest.cpp
 
+tstRTMath_TEMPLATE = VBOXR3TSTEXE
+tstRTMath_SOURCES  = \
+	tstRTMath.cpp \
+	../common/math/gcc/udivmoddi4.c
+
 tstRTUri_TEMPLATE = VBOXR3TSTEXE
 tstRTUri_SOURCES = tstRTUri.cpp
 
diff --git a/src/VBox/Runtime/testcase/tstRTMath.cpp b/src/VBox/Runtime/testcase/tstRTMath.cpp
new file mode 100644
index 0000000..ae5ec76
--- /dev/null
+++ b/src/VBox/Runtime/testcase/tstRTMath.cpp
@@ -0,0 +1,71 @@
+/* $Id: tstRTMath.cpp $ */
+/** @file
+ * IPRT Testcase - base mathematics.
+ */
+
+/*
+ * 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 <iprt/test.h>
+
+RT_C_DECLS_BEGIN
+extern uint64_t __udivmoddi4(uint64_t u64A, uint64_t u64B, uint64_t *pu64R);
+RT_C_DECLS_END
+
+static struct {
+    uint64_t u64A;
+    uint64_t u64B;
+    uint64_t u64Div;
+    uint64_t u64Rem;
+} gUDivMod[]
+=
+{
+    {                           10,                            5,                            2,                            0 },
+    {                (uint64_t)-10,                 (uint64_t)-5,                            0,                (uint64_t)-10 },
+    { UINT64_C(0x7FFFFFFFFFFFFFFF),                            1, UINT64_C(0x7FFFFFFFFFFFFFFF),                            0 },
+    { UINT64_C(0x7FFFFFFFFFFFFFFF), UINT64_C(0x7FFFFFFFFFFFFFFF),                            1,                            0 },
+    { UINT64_C(0xFFFFFFFFFFFFFFFF),                            2, UINT64_C(0x7FFFFFFFFFFFFFFF),                            1 },
+    {                            1,                            2,                            0,                            1 },
+    { UINT64_C(0xFFFFFFFFFFFFFFFE), UINT64_C(0xFFFFFFFFFFFFFFFF),                            0, UINT64_C(0xFFFFFFFFFFFFFFFE) },
+    { UINT64_C(0xEEEEEEEE12345678), UINT64_C(0x00000000EEEEEEEE),                  0x100000000,                   0x12345678 },
+};
+
+static void tstCorrectness(RTTEST hTest)
+{
+    RTTestSub(hTest, "Correctness");
+
+    uint64_t u64Rem;
+    for (unsigned i = 0; i < RT_ELEMENTS(gUDivMod); i++)
+        RTTEST_CHECK(hTest, __udivmoddi4(gUDivMod[i].u64A, gUDivMod[i].u64B, &u64Rem) == gUDivMod[i].u64Div && u64Rem == gUDivMod[i].u64Rem);
+}
+
+int main()
+{
+    RTTEST hTest;
+    int rc = RTTestInitAndCreate("tstRTMath", &hTest);
+    if (rc)
+        return rc;
+    RTTestBanner(hTest);
+    
+    tstCorrectness(hTest);
+
+    return RTTestSummaryAndDestroy(hTest);
+}
diff --git a/src/VBox/Runtime/testcase/tstRTR0Timer.cpp b/src/VBox/Runtime/testcase/tstRTR0Timer.cpp
index ad8ce6c..91dd461 100644
--- a/src/VBox/Runtime/testcase/tstRTR0Timer.cpp
+++ b/src/VBox/Runtime/testcase/tstRTR0Timer.cpp
@@ -860,8 +860,9 @@ DECLEXPORT(int) TSTRTR0TimerSrvReqHandler(PSUPDRVSESSION pSession, uint32_t uOpe
                     {
                         RTR0TESTR0_CHECK_MSG(RTCpuSetIsMemberByIndex(&OnlineSet, iCpu), ("%d\n", iCpu));
                         RTR0TESTR0_CHECK_MSG(paStates[iCpu].cTicks <= cMaxTicks && paStates[iCpu].cTicks >= cMinTicks,
-                                             ("min=%u, ticks=%u, avg=%u max=%u, iCpu=%u, interval=%'u, elapsed=%'llu/%'llu\n",
+                                             ("min=%u, ticks=%u, avg=%u max=%u, iCpu=%u, iCpuCurr=%u, interval=%'u, elapsed=%'llu/%'llu\n",
                                               cMinTicks, paStates[iCpu].cTicks, cAvgTicks, cMaxTicks, iCpu,
+                                              RTMpCpuIdToSetIndex(RTMpCpuId()),
                                               cNsInterval, cNsElapsed, cNsElapsedX));
                     }
                     else
diff --git a/src/VBox/Runtime/testcase/tstRTR0TimerDriver.cpp b/src/VBox/Runtime/testcase/tstRTR0TimerDriver.cpp
index e860fbd..fb0782e 100644
--- a/src/VBox/Runtime/testcase/tstRTR0TimerDriver.cpp
+++ b/src/VBox/Runtime/testcase/tstRTR0TimerDriver.cpp
@@ -109,7 +109,7 @@ extern "C" DECLEXPORT(int) TrustedMain(int argc, char **argv, char **envp)
 #  endif
             RTR3TestR0SimpleTest(TSTRTR0TIMER_ONE_SHOT_SPECIFIC_HIRES, "One shot hires cpu specific");
             RTR3TestR0SimpleTest(TSTRTR0TIMER_PERIODIC_SPECIFIC_HIRES, "Periodic hires cpu specific");
-            RTR3TestR0SimpleTest(TSTRTR0TIMER_PERIODIC_OMNI, "Periodic omni hires timer");
+            RTR3TestR0SimpleTest(TSTRTR0TIMER_PERIODIC_OMNI_HIRES, "Periodic omni hires timer");
         }
 # endif
     }
diff --git a/src/VBox/Runtime/win/RTErrConvertFromWin32.cpp b/src/VBox/Runtime/win/RTErrConvertFromWin32.cpp
index c8ed995..024d11f 100644
--- a/src/VBox/Runtime/win/RTErrConvertFromWin32.cpp
+++ b/src/VBox/Runtime/win/RTErrConvertFromWin32.cpp
@@ -203,6 +203,8 @@ RTR3DECL(int)  RTErrConvertFromWin32(unsigned uNativeCode)
         case ERROR_PASSWORD_RESTRICTION:
         case ERROR_ACCOUNT_DISABLED:        return VERR_ACCOUNT_RESTRICTED;
 
+        case ERROR_INVALID_IMAGE_HASH:      return VERR_LDR_IMAGE_HASH;
+
 
         /*
          * Winsocket errors are mostly BSD errno.h wrappers.
diff --git a/src/VBox/Storage/QCOW.cpp b/src/VBox/Storage/QCOW.cpp
index 53e7d2c..d785db2 100644
--- a/src/VBox/Storage/QCOW.cpp
+++ b/src/VBox/Storage/QCOW.cpp
@@ -1380,6 +1380,7 @@ static DECLCALLBACK(int) qcowAsyncClusterAllocUpdate(void *pBackendData, PVDIOCT
             }
             /* Success, fall through. */
         }
+        /* fall thru */
         case QCOWCLUSTERASYNCALLOCSTATE_L2_LINK:
         {
             /* L2 link updated in L1 , save L2 entry in cache and allocate new user data cluster. */
@@ -1406,6 +1407,7 @@ static DECLCALLBACK(int) qcowAsyncClusterAllocUpdate(void *pBackendData, PVDIOCT
                 break;
             }
         }
+        /* fall thru */
         case QCOWCLUSTERASYNCALLOCSTATE_USER_ALLOC:
         {
             uint64_t offUpdateLe = RT_H2BE_U64(pClusterAlloc->offClusterNew);
@@ -1426,6 +1428,7 @@ static DECLCALLBACK(int) qcowAsyncClusterAllocUpdate(void *pBackendData, PVDIOCT
                 break;
             }
         }
+        /* fall thru */
         case QCOWCLUSTERASYNCALLOCSTATE_USER_LINK:
         {
             /* Everything done without errors, signal completion. */
diff --git a/src/VBox/Storage/QED.cpp b/src/VBox/Storage/QED.cpp
index 3e85f65..56942ff 100644
--- a/src/VBox/Storage/QED.cpp
+++ b/src/VBox/Storage/QED.cpp
@@ -1472,8 +1472,8 @@ static DECLCALLBACK(int) qedAsyncClusterAllocUpdate(void *pBackendData, PVDIOCTX
                 qedAsyncClusterAllocRollback(pImage, pIoCtx, pClusterAlloc);
                 break;
             }
-            /* Success, fall through. */
         }
+        /* fall thru */
         case QEDCLUSTERASYNCALLOCSTATE_L2_LINK:
         {
             /* L2 link updated in L1 , save L2 entry in cache and allocate new user data cluster. */
@@ -1500,6 +1500,7 @@ static DECLCALLBACK(int) qedAsyncClusterAllocUpdate(void *pBackendData, PVDIOCTX
                 break;
             }
         }
+        /* fall thru */
         case QEDCLUSTERASYNCALLOCSTATE_USER_ALLOC:
         {
             uint64_t offUpdateLe = RT_H2LE_U64(pClusterAlloc->offClusterNew);
@@ -1520,6 +1521,7 @@ static DECLCALLBACK(int) qedAsyncClusterAllocUpdate(void *pBackendData, PVDIOCTX
                 break;
             }
         }
+        /* fall thru */
         case QEDCLUSTERASYNCALLOCSTATE_USER_LINK:
         {
             /* Everything done without errors, signal completion. */
diff --git a/src/VBox/Storage/VDI.cpp b/src/VBox/Storage/VDI.cpp
index 2713995..7844b07 100644
--- a/src/VBox/Storage/VDI.cpp
+++ b/src/VBox/Storage/VDI.cpp
@@ -1097,6 +1097,7 @@ static DECLCALLBACK(int) vdiDiscardBlockAsyncUpdate(void *pBackendData, PVDIOCTX
             vdIfIoIntMetaXferRelease(pImage->pIfIo, pMetaXfer);
             pDiscardAsync->enmState = VDIBLOCKDISCARDSTATE_WRITE_BLOCK;
         }
+        /* fall thru */
         case VDIBLOCKDISCARDSTATE_WRITE_BLOCK:
         {
             /* Block read complete. Write to the new location (discarded block). */
@@ -1109,6 +1110,7 @@ static DECLCALLBACK(int) vdiDiscardBlockAsyncUpdate(void *pBackendData, PVDIOCTX
             if (RT_FAILURE(rc))
                 break;
         }
+        /* fall thru */
         case VDIBLOCKDISCARDSTATE_UPDATE_METADATA:
         {
             int rc2;
diff --git a/src/VBox/Storage/testcase/tstVDIo.cpp b/src/VBox/Storage/testcase/tstVDIo.cpp
index d435056..59a1311 100644
--- a/src/VBox/Storage/testcase/tstVDIo.cpp
+++ b/src/VBox/Storage/testcase/tstVDIo.cpp
@@ -2552,6 +2552,7 @@ static DECLCALLBACK(void) tstVDIoTestReqComplete(void *pvUser1, void *pvUser2, i
                                  &pIoReq->SgBuf))
                     RTTestFailed(pDisk->pTestGlob->hTest, "Corrupted disk at offset %llu!\n", pIoReq->off);
                 RTCritSectLeave(&pDisk->CritSectVerify);
+                break;
             }
             case VDIOREQTXDIR_WRITE:
             {
diff --git a/src/VBox/VMM/Makefile.kmk b/src/VBox/VMM/Makefile.kmk
index d3b00ff..d7e24a8 100644
--- a/src/VBox/VMM/Makefile.kmk
+++ b/src/VBox/VMM/Makefile.kmk
@@ -54,9 +54,10 @@ endif
 #ifdef VBOX_WITH_IEM
 # VMM_COMMON_DEFS += VBOX_WITH_IEM
 #endif
-ifdef VBOX_WITH_REM
- VMM_COMMON_DEFS += VBOX_WITH_REM
-endif
+# part of global DEFS
+#ifdef VBOX_WITH_REM
+# VMM_COMMON_DEFS += VBOX_WITH_REM
+#endif
 ifdef VBOX_WITH_MULTI_CORE
  VMM_COMMON_DEFS += VBOX_WITH_MULTI_CORE
 endif
@@ -359,7 +360,12 @@ $$(VBoxVMM_0_OUTDIR)/CommonGenIncs/IEMInstructionStatisticsTmpl.h.ts \
 		$(PATH_SUB_CURRENT)/VMMAll/IEMAllInstructions.cpp.h \
 		$(PATH_SUB_CURRENT)/VMMAll/IEMAllInstructionsOneByte.cpp.h \
 		$(PATH_SUB_CURRENT)/VMMAll/IEMAllInstructionsTwoByte0f.cpp.h \
-		$(PATH_SUB_CURRENT)/VMMAll/IEMAllInstructionsVexMap1.cpp.h
+		$(PATH_SUB_CURRENT)/VMMAll/IEMAllInstructionsThree0f38.cpp.h \
+		$(PATH_SUB_CURRENT)/VMMAll/IEMAllInstructionsThree0f3a.cpp.h \
+		$(PATH_SUB_CURRENT)/VMMAll/IEMAllInstructionsVexMap1.cpp.h \
+		$(PATH_SUB_CURRENT)/VMMAll/IEMAllInstructionsVexMap2.cpp.h \
+		$(PATH_SUB_CURRENT)/VMMAll/IEMAllInstructionsVexMap3.cpp.h \
+		$(PATH_SUB_CURRENT)/VMMAll/IEMAllInstructions3DNow.cpp.h
 	$(QUIET)$(call MSG_GENERATE,VBoxVMM,$@,$<)
 	$(QUIET)$(RM) -f -- "$@.tmp" "$@.tmp" "$@.sorted"
 	$(QUIET)$(MKDIR) -p -- "$(dir $@)"
diff --git a/src/VBox/VMM/VMMAll/EMAll.cpp b/src/VBox/VMM/VMMAll/EMAll.cpp
index 155bef8..fc5de6d 100644
--- a/src/VBox/VMM/VMMAll/EMAll.cpp
+++ b/src/VBox/VMM/VMMAll/EMAll.cpp
@@ -1316,8 +1316,8 @@ VMM_INT_DECL(int) EMInterpretRdtsc(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame
     uint64_t uTicks = TMCpuTickGet(pVCpu);
 
     /* Same behaviour in 32 & 64 bits mode */
-    pRegFrame->rax = (uint32_t)uTicks;
-    pRegFrame->rdx = (uTicks >> 32ULL);
+    pRegFrame->rax = RT_LO_U32(uTicks);
+    pRegFrame->rdx = RT_HI_U32(uTicks);
 #ifdef VBOX_COMPARE_IEM_AND_EM
     g_fIgnoreRaxRdx = true;
 #endif
@@ -1352,8 +1352,8 @@ VMM_INT_DECL(int) EMInterpretRdtscp(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx)
     uint64_t uTicks = TMCpuTickGet(pVCpu);
 
     /* Same behaviour in 32 & 64 bits mode */
-    pCtx->rax = (uint32_t)uTicks;
-    pCtx->rdx = (uTicks >> 32ULL);
+    pCtx->rax = RT_LO_U32(uTicks);
+    pCtx->rdx = RT_HI_U32(uTicks);
 #ifdef VBOX_COMPARE_IEM_AND_EM
     g_fIgnoreRaxRdx = true;
 #endif
@@ -1579,8 +1579,8 @@ VMM_INT_DECL(int) EMInterpretRdmsr(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame
         Assert(rcStrict == VERR_CPUM_RAISE_GP_0 || rcStrict == VERR_EM_INTERPRETER || rcStrict == VINF_CPUM_R3_MSR_READ);
         return VERR_EM_INTERPRETER;
     }
-    pRegFrame->rax = (uint32_t) uValue;
-    pRegFrame->rdx = (uint32_t)(uValue >> 32);
+    pRegFrame->rax = RT_LO_U32(uValue);
+    pRegFrame->rdx = RT_HI_U32(uValue);
     LogFlow(("EMInterpretRdmsr %s (%x) -> %RX64\n", emMSRtoString(pRegFrame->ecx), pRegFrame->ecx, uValue));
     return VINF_SUCCESS;
 }
diff --git a/src/VBox/VMM/VMMAll/IEMAll.cpp b/src/VBox/VMM/VMMAll/IEMAll.cpp
index 7372774..782779e 100644
--- a/src/VBox/VMM/VMMAll/IEMAll.cpp
+++ b/src/VBox/VMM/VMMAll/IEMAll.cpp
@@ -216,6 +216,16 @@ typedef union IEMSELDESC
 /** Pointer to a selector descriptor table entry. */
 typedef IEMSELDESC *PIEMSELDESC;
 
+/**
+ * CPU exception classes.
+ */
+typedef enum IEMXCPTCLASS
+{
+    IEMXCPTCLASS_BENIGN,
+    IEMXCPTCLASS_CONTRIBUTORY,
+    IEMXCPTCLASS_PAGE_FAULT
+} IEMXCPTCLASS;
+
 
 /*********************************************************************************************************************************
 *   Defined Constants And Macros                                                                                                 *
@@ -360,6 +370,16 @@ typedef IEMSELDESC *PIEMSELDESC;
  */
 #define IEM_IS_CANONICAL(a_u64Addr)         X86_IS_CANONICAL(a_u64Addr)
 
+/**
+ * Gets the effective VEX.VVVV value.
+ *
+ * The 4th bit is ignored if not 64-bit code.
+ * @returns effective V-register value.
+ * @param   a_pVCpu         The cross context virtual CPU structure of the calling thread.
+ */
+#define IEM_GET_EFFECTIVE_VVVV(a_pVCpu) \
+    ((a_pVCpu)->iem.s.enmCpuMode == IEMMODE_64BIT ? (a_pVCpu)->iem.s.uVex3rdReg : (a_pVCpu)->iem.s.uVex3rdReg & 7)
+
 /** @def IEM_USE_UNALIGNED_DATA_ACCESS
  * Use unaligned accesses instead of elaborate byte assembly. */
 #if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86) || defined(DOXYGEN_RUNNING)
@@ -3212,10 +3232,130 @@ DECLINLINE(uint64_t) iemOpcodeGetNextU64Jmp(PVMCPU pVCpu)
  * @{
  */
 
-/* Currently used only with nested hw.virt. */
-#ifdef VBOX_WITH_NESTED_HWVIRT
 /**
- * Initiates a CPU shutdown sequence.
+ * Gets the exception class for the specified exception vector.
+ *  
+ * @returns The class of the specified exception.
+ * @param   uVector       The exception vector. 
+ */
+IEM_STATIC IEMXCPTCLASS iemGetXcptClass(uint8_t uVector)
+{
+    Assert(uVector <= X86_XCPT_LAST);
+    switch (uVector)
+    {
+        case X86_XCPT_DE:
+        case X86_XCPT_TS:
+        case X86_XCPT_NP:
+        case X86_XCPT_SS:
+        case X86_XCPT_GP:
+        case X86_XCPT_SX:   /* AMD only */
+            return IEMXCPTCLASS_CONTRIBUTORY;
+
+        case X86_XCPT_PF:
+        case X86_XCPT_VE:   /* Intel only */
+            return IEMXCPTCLASS_PAGE_FAULT;
+    }
+    return IEMXCPTCLASS_BENIGN;
+}
+
+
+/**
+ * Evaluates how to handle an exception caused during delivery of another event
+ * (exception / interrupt).
+ *  
+ * @returns How to handle the recursive exception. 
+ * @param   pVCpu               The cross context virtual CPU structure of the
+ *                              calling thread.
+ * @param   fPrevFlags          The flags of the previous event.
+ * @param   uPrevVector         The vector of the previous event.
+ * @param   fCurFlags           The flags of the current exception.
+ * @param   uCurVector          The vector of the current exception.
+ * @param   pfXcptRaiseInfo     Where to store additional information about the
+ *                              exception condition. Optional.
+ */
+VMM_INT_DECL(IEMXCPTRAISE) IEMEvaluateRecursiveXcpt(PVMCPU pVCpu, uint32_t fPrevFlags, uint8_t uPrevVector, uint32_t fCurFlags,
+                                                    uint8_t uCurVector, PIEMXCPTRAISEINFO pfXcptRaiseInfo)
+{
+    /*
+     * Only CPU exceptions can be raised while delivering other events, software interrupt
+     * (INTn/INT3/INTO/ICEBP) generated exceptions cannot occur as the current (second) exception.
+     */
+    AssertReturn(fCurFlags & IEM_XCPT_FLAGS_T_CPU_XCPT, IEMXCPTRAISE_INVALID);
+    Assert(pVCpu); RT_NOREF(pVCpu);
+
+    IEMXCPTRAISE     enmRaise   = IEMXCPTRAISE_CURRENT_XCPT;
+    IEMXCPTRAISEINFO fRaiseInfo = IEMXCPTRAISEINFO_NONE;
+    if (fPrevFlags & IEM_XCPT_FLAGS_T_CPU_XCPT)
+    {
+        IEMXCPTCLASS enmPrevXcptClass = iemGetXcptClass(uPrevVector);
+        if (enmPrevXcptClass != IEMXCPTCLASS_BENIGN)
+        {
+            IEMXCPTCLASS enmCurXcptClass  = iemGetXcptClass(uCurVector);
+            if (   enmPrevXcptClass == IEMXCPTCLASS_PAGE_FAULT
+                && (   enmCurXcptClass == IEMXCPTCLASS_PAGE_FAULT
+                    || enmCurXcptClass == IEMXCPTCLASS_CONTRIBUTORY))
+            {
+                enmRaise = IEMXCPTRAISE_DOUBLE_FAULT;
+                fRaiseInfo = enmCurXcptClass == IEMXCPTCLASS_PAGE_FAULT ? IEMXCPTRAISEINFO_PF_PF
+                                                                        : IEMXCPTRAISEINFO_PF_CONTRIBUTORY_XCPT;
+                Log2(("IEMEvaluateRecursiveXcpt: Vectoring page fault. uPrevVector=%#x uCurVector=%#x uCr2=%#RX64\n", uPrevVector,
+                      uCurVector, IEM_GET_CTX(pVCpu)->cr2));
+            }
+            else if (   enmPrevXcptClass == IEMXCPTCLASS_CONTRIBUTORY
+                     && enmCurXcptClass  == IEMXCPTCLASS_CONTRIBUTORY)
+            {
+                enmRaise = IEMXCPTRAISE_DOUBLE_FAULT;
+                Log2(("IEMEvaluateRecursiveXcpt: uPrevVector=%u uCurVector=%u -> #DF\n", uPrevVector, uCurVector));
+            }
+            else if (   uPrevVector == X86_XCPT_DF
+                     && (   enmCurXcptClass == IEMXCPTCLASS_CONTRIBUTORY
+                         || enmCurXcptClass == IEMXCPTCLASS_PAGE_FAULT))
+            {
+                enmRaise = IEMXCPTRAISE_TRIPLE_FAULT;
+                Log2(("IEMEvaluateRecursiveXcpt: #DF handler raised a %#x exception -> triple fault\n", uCurVector));
+            }
+        }
+        else
+        {
+            if (uPrevVector == X86_XCPT_NMI)
+            {
+                fRaiseInfo = IEMXCPTRAISEINFO_NMI_XCPT;
+                if (uCurVector == X86_XCPT_PF)
+                {
+                    fRaiseInfo |= IEMXCPTRAISEINFO_NMI_PF;
+                    Log2(("IEMEvaluateRecursiveXcpt: NMI delivery caused a page fault\n"));
+                }
+            }
+            else if (   uPrevVector == X86_XCPT_AC
+                     && uCurVector  == X86_XCPT_AC)
+            {
+                enmRaise   = IEMXCPTRAISE_CPU_HANG;
+                fRaiseInfo = IEMXCPTRAISEINFO_AC_AC;
+                Log2(("IEMEvaluateRecursiveXcpt: Recursive #AC - Bad guest\n"));
+            }
+        }
+    }
+    else if (fPrevFlags & IEM_XCPT_FLAGS_T_EXT_INT)
+    {
+        fRaiseInfo = IEMXCPTRAISEINFO_EXT_INT_XCPT;
+        if (uCurVector == X86_XCPT_PF)
+            fRaiseInfo |= IEMXCPTRAISEINFO_EXT_INT_PF;
+    }
+    else
+    {
+        Assert(fPrevFlags & IEM_XCPT_FLAGS_T_SOFT_INT);
+        fRaiseInfo = IEMXCPTRAISEINFO_SOFT_INT_XCPT;
+    }
+
+    if (pfXcptRaiseInfo)
+        *pfXcptRaiseInfo = fRaiseInfo;
+    return enmRaise; 
+}
+
+
+/**
+ * Enters the CPU shutdown state initiated by a triple fault or other
+ * unrecoverable conditions.
  *
  * @returns Strict VBox status code.
  * @param   pVCpu           The cross context virtual CPU structure of the
@@ -3229,11 +3369,88 @@ IEM_STATIC VBOXSTRICTRC iemInitiateCpuShutdown(PVMCPU pVCpu)
         IEM_RETURN_SVM_NST_GST_VMEXIT(pVCpu, SVM_EXIT_SHUTDOWN, 0 /* uExitInfo1 */, 0 /* uExitInfo2 */);
     }
 
-    RT_NOREF_PV(pVCpu);
-    /** @todo Probably need a separate error code and handling for this to
-     *        distinguish it from the regular triple fault. */
+    RT_NOREF(pVCpu);
     return VINF_EM_TRIPLE_FAULT;
 }
+
+
+#ifdef VBOX_WITH_NESTED_HWVIRT
+IEM_STATIC VBOXSTRICTRC iemHandleSvmNstGstEventIntercept(PVMCPU pVCpu, PCPUMCTX pCtx, uint8_t u8Vector, uint32_t fFlags,
+                                                         uint32_t uErr, uint64_t uCr2)
+{
+    Assert(IEM_IS_SVM_ENABLED(pVCpu));
+
+    /*
+     * Handle nested-guest SVM exception and software interrupt intercepts,
+     * see AMD spec. 15.12 "Exception Intercepts".
+     *
+     *   - NMI intercepts have their own exit code and do not cause SVM_EXIT_EXCEPTION_2 #VMEXITs.
+     *   - External interrupts and software interrupts (INTn instruction) do not check the exception intercepts
+     *     even when they use a vector in the range 0 to 31.
+     *   - ICEBP should not trigger #DB intercept, but its own intercept.
+     *   - For #PF exceptions, its intercept is checked before CR2 is written by the exception.
+     */
+    /* Check NMI intercept */
+    if (   u8Vector == X86_XCPT_NMI
+        && (fFlags & IEM_XCPT_FLAGS_T_CPU_XCPT)
+        && IEM_IS_SVM_CTRL_INTERCEPT_SET(pVCpu, SVM_CTRL_INTERCEPT_NMI))
+    {
+        Log2(("iemHandleSvmNstGstEventIntercept: NMI intercept -> #VMEXIT\n"));
+        IEM_RETURN_SVM_NST_GST_VMEXIT(pVCpu, SVM_EXIT_NMI, 0 /* uExitInfo1 */, 0 /* uExitInfo2 */);
+    }
+
+    /* Check ICEBP intercept. */
+    if (   (fFlags & IEM_XCPT_FLAGS_ICEBP_INSTR)
+        && IEM_IS_SVM_CTRL_INTERCEPT_SET(pVCpu, SVM_CTRL_INTERCEPT_ICEBP))
+    {
+        Log2(("iemHandleSvmNstGstEventIntercept: ICEBP intercept -> #VMEXIT\n"));
+        IEM_RETURN_SVM_NST_GST_VMEXIT(pVCpu, SVM_EXIT_ICEBP, 0 /* uExitInfo1 */, 0 /* uExitInfo2 */);
+    }
+
+    /* Check CPU exception intercepts. */
+    if (   (fFlags & IEM_XCPT_FLAGS_T_CPU_XCPT)
+        && IEM_IS_SVM_XCPT_INTERCEPT_SET(pVCpu, u8Vector))
+    {
+        Assert(u8Vector <= X86_XCPT_LAST);
+        uint64_t const uExitInfo1 = fFlags & IEM_XCPT_FLAGS_ERR ? uErr : 0;
+        uint64_t const uExitInfo2 = fFlags & IEM_XCPT_FLAGS_CR2 ? uCr2 : 0;
+        if (   IEM_GET_GUEST_CPU_FEATURES(pVCpu)->fSvmDecodeAssist
+            && u8Vector == X86_XCPT_PF
+            && !(uErr & X86_TRAP_PF_ID))
+        {
+            /** @todo Nested-guest SVM - figure out fetching op-code bytes from IEM. */
+#ifdef IEM_WITH_CODE_TLB
+            AssertReleaseFailedReturn(VERR_IEM_IPE_5);
+#else
+            uint8_t const offOpCode = pVCpu->iem.s.offOpcode;
+            uint8_t const cbCurrent = pVCpu->iem.s.cbOpcode - pVCpu->iem.s.offOpcode;
+            if (   cbCurrent > 0
+                && cbCurrent < sizeof(pCtx->hwvirt.svm.VmcbCtrl.abInstr))
+            {
+                Assert(cbCurrent <= sizeof(pVCpu->iem.s.abOpcode));
+                memcpy(&pCtx->hwvirt.svm.VmcbCtrl.abInstr[0], &pVCpu->iem.s.abOpcode[offOpCode], cbCurrent);
+            }
+#endif
+        }
+        Log2(("iemHandleSvmNstGstEventIntercept: Xcpt intercept. u8Vector=%#x uExitInfo1=%#RX64, uExitInfo2=%#RX64 -> #VMEXIT\n",
+             u8Vector, uExitInfo1, uExitInfo2));
+        IEM_RETURN_SVM_NST_GST_VMEXIT(pVCpu, SVM_EXIT_EXCEPTION_0 + u8Vector, uExitInfo1, uExitInfo2);
+    }
+
+    /* Check software interrupt (INTn) intercepts. */
+    if (   (fFlags & (  IEM_XCPT_FLAGS_T_SOFT_INT
+                      | IEM_XCPT_FLAGS_BP_INSTR
+                      | IEM_XCPT_FLAGS_ICEBP_INSTR
+                      | IEM_XCPT_FLAGS_OF_INSTR)) == IEM_XCPT_FLAGS_T_SOFT_INT
+        && IEM_IS_SVM_CTRL_INTERCEPT_SET(pVCpu, SVM_CTRL_INTERCEPT_INTN))
+    {
+        uint64_t const uExitInfo1 = IEM_GET_GUEST_CPU_FEATURES(pVCpu)->fSvmDecodeAssist ? u8Vector : 0;
+        Log2(("iemHandleSvmNstGstEventIntercept: Software INT intercept (u8Vector=%#x) -> #VMEXIT\n", u8Vector));
+        IEM_RETURN_SVM_NST_GST_VMEXIT(pVCpu, SVM_EXIT_SWINT, uExitInfo1, 0 /* uExitInfo2 */);
+    }
+
+    return VINF_HM_INTERCEPT_NOT_ACTIVE;
+}
 #endif
 
 /**
@@ -3559,7 +3776,7 @@ iemRaiseXcptOrIntInRealMode(PVMCPU      pVCpu,
     pCtx->cs.u64Base       = (uint32_t)Idte.sel << 4;
     /** @todo do we load attribs and limit as well? Should we check against limit like far jump? */
     pCtx->rip              = Idte.off;
-    fEfl &= ~X86_EFL_IF;
+    fEfl &= ~(X86_EFL_IF | X86_EFL_TF | X86_EFL_AC);
     IEMMISC_SET_EFL(pVCpu, pCtx, fEfl);
 
     /** @todo do we actually do this in real mode? */
@@ -5254,59 +5471,21 @@ iemRaiseXcptOrInt(PVMCPU      pVCpu,
     if (IEM_IS_SVM_ENABLED(pVCpu))
     {
         /*
-         * Handle nested-guest SVM exception and software interrupt intercepts,
-         * see AMD spec. 15.12 "Exception Intercepts".
-         *
-         *   - NMI intercepts have their own exit code and do not cause SVM_EXIT_EXCEPTION_2 #VMEXITs.
-         *   - External interrupts and software interrupts (INTn instruction) do not check the exception intercepts
-         *     even when they use a vector in the range 0 to 31.
-         *   - ICEBP should not trigger #DB intercept, but its own intercept, so we catch it early in iemOp_int1.
-         *   - For #PF exceptions, its intercept is checked before CR2 is written by the exception.
+         * If the event is being injected as part of VMRUN, it isn't subject to event
+         * intercepts in the nested-guest. However, secondary exceptions that occur
+         * during injection of any event -are- subject to exception intercepts.
+         * See AMD spec. 15.20 "Event Injection".
          */
-        /* Check NMI intercept */
-        if (   u8Vector == X86_XCPT_NMI
-            && IEM_IS_SVM_CTRL_INTERCEPT_SET(pVCpu, SVM_CTRL_INTERCEPT_NMI))
-        {
-            Log(("iemRaiseXcptOrInt: NMI intercept -> #VMEXIT\n"));
-            IEM_RETURN_SVM_NST_GST_VMEXIT(pVCpu, SVM_EXIT_NMI, 0 /* uExitInfo1 */, 0 /* uExitInfo2 */);
-        }
-
-        /* Check CPU exception intercepts. */
-        if (   IEM_IS_SVM_XCPT_INTERCEPT_SET(pVCpu, u8Vector)
-            && (fFlags & IEM_XCPT_FLAGS_T_CPU_XCPT))
-        {
-            Assert(u8Vector <= X86_XCPT_LAST);
-            uint64_t const uExitInfo1 = fFlags & IEM_XCPT_FLAGS_ERR ? uErr : 0;
-            uint64_t const uExitInfo2 = fFlags & IEM_XCPT_FLAGS_CR2 ? uCr2 : 0;
-            if (   IEM_GET_GUEST_CPU_FEATURES(pVCpu)->fSvmDecodeAssist
-                && u8Vector == X86_XCPT_PF
-                && !(uErr & X86_TRAP_PF_ID))
-            {
-                /** @todo Nested-guest SVM - figure out fetching op-code bytes from IEM. */
-#ifdef IEM_WITH_CODE_TLB
-#else
-                uint8_t const offOpCode = pVCpu->iem.s.offOpcode;
-                uint8_t const cbCurrent = pVCpu->iem.s.cbOpcode - pVCpu->iem.s.offOpcode;
-                if (   cbCurrent > 0
-                    && cbCurrent < sizeof(pCtx->hwvirt.svm.VmcbCtrl.abInstr))
-                {
-                    Assert(cbCurrent <= sizeof(pVCpu->iem.s.abOpcode));
-                    memcpy(&pCtx->hwvirt.svm.VmcbCtrl.abInstr[0], &pVCpu->iem.s.abOpcode[offOpCode], cbCurrent);
-                }
-#endif
-            }
-            Log(("iemRaiseXcptOrInt: Xcpt intercept (u8Vector=%#x uExitInfo1=%#RX64, uExitInfo2=%#RX64 -> #VMEXIT\n", u8Vector,
-                 uExitInfo1, uExitInfo2));
-            IEM_RETURN_SVM_NST_GST_VMEXIT(pVCpu, SVM_EXIT_EXCEPTION_0 + u8Vector, uExitInfo1, uExitInfo2);
-        }
-
-        /* Check software interrupt (INTn) intercepts. */
-        if (   IEM_IS_SVM_CTRL_INTERCEPT_SET(pVCpu, SVM_CTRL_INTERCEPT_INTN)
-            && (fFlags & IEM_XCPT_FLAGS_T_SOFT_INT))
+        if (!pCtx->hwvirt.svm.fInterceptEvents)
+            pCtx->hwvirt.svm.fInterceptEvents = 1;
+        else
         {
-            uint64_t const uExitInfo1 = IEM_GET_GUEST_CPU_FEATURES(pVCpu)->fSvmDecodeAssist ? u8Vector : 0;
-            Log(("iemRaiseXcptOrInt: Software INT intercept (u8Vector=%#x) -> #VMEXIT\n", u8Vector));
-            IEM_RETURN_SVM_NST_GST_VMEXIT(pVCpu, SVM_EXIT_SWINT, uExitInfo1, 0 /* uExitInfo2 */);
+            /*
+             * Check and handle if the event being raised is intercepted.
+             */
+            VBOXSTRICTRC rcStrict0 = iemHandleSvmNstGstEventIntercept(pVCpu, pCtx, u8Vector, fFlags, uErr, uCr2);
+            if (rcStrict0 != VINF_HM_INTERCEPT_NOT_ACTIVE)
+                return rcStrict0;
         }
     }
 #endif /* VBOX_WITH_NESTED_HWVIRT */
@@ -5322,11 +5501,9 @@ iemRaiseXcptOrInt(PVMCPU      pVCpu,
     else
     {
         Log(("iemRaiseXcptOrInt: %#x at %04x:%RGv cbInstr=%#x fFlags=%#x uErr=%#x uCr2=%llx; prev=%#x depth=%d flags=%#x\n",
-             u8Vector, pCtx->cs.Sel, pCtx->rip, cbInstr, fFlags, uErr, uCr2, pVCpu->iem.s.uCurXcpt, pVCpu->iem.s.cXcptRecursions + 1, fPrevXcpt));
+             u8Vector, pCtx->cs.Sel, pCtx->rip, cbInstr, fFlags, uErr, uCr2, pVCpu->iem.s.uCurXcpt,
+             pVCpu->iem.s.cXcptRecursions + 1, fPrevXcpt));
 
-        /** @todo double and tripple faults. */
-        /** @todo When implementing \#DF, the SVM nested-guest \#DF intercepts needs
-         *        some care. See AMD spec. 15.12 "Exception Intercepts". */
         if (pVCpu->iem.s.cXcptRecursions >= 3)
         {
 #ifdef DEBUG_bird
@@ -5335,12 +5512,62 @@ iemRaiseXcptOrInt(PVMCPU      pVCpu,
             IEM_RETURN_ASPECT_NOT_IMPLEMENTED_LOG(("Too many fault nestings.\n"));
         }
 
-        /** @todo set X86_TRAP_ERR_EXTERNAL when appropriate.
-        if (fPrevXcpt & IEM_XCPT_FLAGS_T_EXT_INT)
+        /*
+         * Evaluate the sequence of recurring events.
+         */
+        IEMXCPTRAISE enmRaise = IEMEvaluateRecursiveXcpt(pVCpu, fPrevXcpt, uPrevXcpt, fFlags, u8Vector,
+                                                         NULL /* pXcptRaiseInfo */);
+        if (enmRaise == IEMXCPTRAISE_CURRENT_XCPT)
+        { /* likely */ }
+        else if (enmRaise == IEMXCPTRAISE_DOUBLE_FAULT)
+        {
+            fFlags   = IEM_XCPT_FLAGS_T_CPU_XCPT | IEM_XCPT_FLAGS_ERR;
+            u8Vector = X86_XCPT_DF;
+            uErr     = 0;
+            /* SVM nested-guest #DF intercepts need to be checked now. See AMD spec. 15.12 "Exception Intercepts". */
+            if (IEM_IS_SVM_XCPT_INTERCEPT_SET(pVCpu, X86_XCPT_DF))
+                IEM_RETURN_SVM_NST_GST_VMEXIT(pVCpu, SVM_EXIT_EXCEPTION_0 + X86_XCPT_DF, 0 /* uExitInfo1 */, 0 /* uExitInfo2 */);
+        }
+        else if (enmRaise == IEMXCPTRAISE_TRIPLE_FAULT)
+        {
+            Log2(("iemRaiseXcptOrInt: raising triple fault. uPrevXcpt=%#x\n", uPrevXcpt));
+            return iemInitiateCpuShutdown(pVCpu);
+        }
+        else if (enmRaise == IEMXCPTRAISE_CPU_HANG)
+        {
+            /* If a nested-guest enters an endless CPU loop condition, we'll emulate it; otherwise guru. */
+            Log2(("iemRaiseXcptOrInt: CPU hang condition detected\n"));
+#ifdef VBOX_WITH_NESTED_HWVIRT
+            if (!CPUMIsGuestInNestedHwVirtMode(pCtx))
+#endif
+                return VERR_EM_GUEST_CPU_HANG;
+        }
+        else
+        {
+            AssertMsgFailed(("Unexpected condition! enmRaise=%#x uPrevXcpt=%#x fPrevXcpt=%#x, u8Vector=%#x fFlags=%#x\n",
+                             enmRaise, uPrevXcpt, fPrevXcpt, u8Vector, fFlags));
+            return VERR_IEM_IPE_9;
+        }
+
+        /*
+         * The 'EXT' bit is set when an exception occurs during deliver of an external
+         * event (such as an interrupt or earlier exception)[1]. Privileged software
+         * exception (INT1) also sets the EXT bit[2]. Exceptions generated by software
+         * interrupts and INTO, INT3 instructions, the 'EXT' bit will not be set.
+         *
+         * [1] - Intel spec. 6.13 "Error Code"
+         * [2] - Intel spec. 26.5.1.1 "Details of Vectored-Event Injection".
+         * [3] - Intel Instruction reference for INT n.
+         */
+        if (   (fPrevXcpt & (IEM_XCPT_FLAGS_T_CPU_XCPT | IEM_XCPT_FLAGS_T_EXT_INT | IEM_XCPT_FLAGS_ICEBP_INSTR))
+            && (fFlags & IEM_XCPT_FLAGS_ERR)
+            && u8Vector != X86_XCPT_PF
+            && u8Vector != X86_XCPT_DF)
         {
-        ....
-        } */
+            uErr |= X86_TRAP_ERR_EXTERNAL;
+        }
     }
+
     pVCpu->iem.s.cXcptRecursions++;
     pVCpu->iem.s.uCurXcpt    = u8Vector;
     pVCpu->iem.s.fCurXcpt    = fFlags;
@@ -6667,7 +6894,7 @@ DECLINLINE(void) iemFpuPrepareUsage(PVMCPU pVCpu)
 
 
 /**
- * Hook for preparing to use the host FPU for SSE
+ * Hook for preparing to use the host FPU for SSE.
  *
  * This is necessary in ring-0 and raw-mode context (nop in ring-3).
  *
@@ -6680,6 +6907,19 @@ DECLINLINE(void) iemFpuPrepareUsageSse(PVMCPU pVCpu)
 
 
 /**
+ * Hook for preparing to use the host FPU for AVX.
+ *
+ * This is necessary in ring-0 and raw-mode context (nop in ring-3).
+ *
+ * @param   pVCpu               The cross context virtual CPU structure of the calling thread.
+ */
+DECLINLINE(void) iemFpuPrepareUsageAvx(PVMCPU pVCpu)
+{
+    iemFpuPrepareUsage(pVCpu);
+}
+
+
+/**
  * Hook for actualizing the guest FPU state before the interpreter reads it.
  *
  * This is necessary in ring-0 and raw-mode context (nop in ring-3).
@@ -6750,6 +6990,42 @@ DECLINLINE(void) iemFpuActualizeSseStateForChange(PVMCPU pVCpu)
 
 
 /**
+ * Hook for actualizing the guest YMM0..15 and MXCSR register state for read
+ * only.
+ *
+ * This is necessary in ring-0 and raw-mode context (nop in ring-3).
+ *
+ * @param   pVCpu               The cross context virtual CPU structure of the calling thread.
+ */
+DECLINLINE(void) iemFpuActualizeAvxStateForRead(PVMCPU pVCpu)
+{
+#ifdef IN_RING3
+    NOREF(pVCpu);
+#else
+    CPUMRZFpuStateActualizeAvxForRead(pVCpu);
+#endif
+}
+
+
+/**
+ * Hook for actualizing the guest YMM0..15 and MXCSR register state for
+ * read+write.
+ *
+ * This is necessary in ring-0 and raw-mode context (nop in ring-3).
+ *
+ * @param   pVCpu               The cross context virtual CPU structure of the calling thread.
+ */
+DECLINLINE(void) iemFpuActualizeAvxStateForChange(PVMCPU pVCpu)
+{
+#ifdef IN_RING3
+    CPUMSetChangedFlags(pVCpu, CPUM_CHANGED_FPU_REM);
+#else
+    CPUMRZFpuStateActualizeForChange(pVCpu);
+#endif
+}
+
+
+/**
  * Stores a QNaN value into a FPU register.
  *
  * @param   pReg                Pointer to the register.
@@ -9449,6 +9725,124 @@ DECL_NO_INLINE(IEM_STATIC, void) iemMemFetchDataU128AlignedSseJmp(PVMCPU pVCpu,
 #endif
 
 
+/**
+ * Fetches a data oword (octo word), generally AVX related.
+ *
+ * @returns Strict VBox status code.
+ * @param   pVCpu               The cross context virtual CPU structure of the calling thread.
+ * @param   pu256Dst            Where to return the qword.
+ * @param   iSegReg             The index of the segment register to use for
+ *                              this access.  The base and limits are checked.
+ * @param   GCPtrMem            The address of the guest memory.
+ */
+IEM_STATIC VBOXSTRICTRC iemMemFetchDataU256(PVMCPU pVCpu, PRTUINT256U pu256Dst, uint8_t iSegReg, RTGCPTR GCPtrMem)
+{
+    /* The lazy approach for now... */
+    PCRTUINT256U pu256Src;
+    VBOXSTRICTRC rc = iemMemMap(pVCpu, (void **)&pu256Src, sizeof(*pu256Src), iSegReg, GCPtrMem, IEM_ACCESS_DATA_R);
+    if (rc == VINF_SUCCESS)
+    {
+        pu256Dst->au64[0] = pu256Src->au64[0];
+        pu256Dst->au64[1] = pu256Src->au64[1];
+        pu256Dst->au64[2] = pu256Src->au64[2];
+        pu256Dst->au64[3] = pu256Src->au64[3];
+        rc = iemMemCommitAndUnmap(pVCpu, (void *)pu256Src, IEM_ACCESS_DATA_R);
+    }
+    return rc;
+}
+
+
+#ifdef IEM_WITH_SETJMP
+/**
+ * Fetches a data oword (octo word), generally AVX related.
+ *
+ * @param   pVCpu               The cross context virtual CPU structure of the calling thread.
+ * @param   pu256Dst            Where to return the qword.
+ * @param   iSegReg             The index of the segment register to use for
+ *                              this access.  The base and limits are checked.
+ * @param   GCPtrMem            The address of the guest memory.
+ */
+IEM_STATIC void iemMemFetchDataU256Jmp(PVMCPU pVCpu, PRTUINT256U pu256Dst, uint8_t iSegReg, RTGCPTR GCPtrMem)
+{
+    /* The lazy approach for now... */
+    PCRTUINT256U pu256Src = (PCRTUINT256U)iemMemMapJmp(pVCpu, sizeof(*pu256Src), iSegReg, GCPtrMem, IEM_ACCESS_DATA_R);
+    pu256Dst->au64[0] = pu256Src->au64[0];
+    pu256Dst->au64[1] = pu256Src->au64[1];
+    pu256Dst->au64[2] = pu256Src->au64[2];
+    pu256Dst->au64[3] = pu256Src->au64[3];
+    iemMemCommitAndUnmapJmp(pVCpu, (void *)pu256Src, IEM_ACCESS_DATA_R);
+}
+#endif
+
+
+/**
+ * Fetches a data oword (octo word) at an aligned address, generally AVX
+ * related.
+ *
+ * Raises \#GP(0) if not aligned.
+ *
+ * @returns Strict VBox status code.
+ * @param   pVCpu               The cross context virtual CPU structure of the calling thread.
+ * @param   pu256Dst            Where to return the qword.
+ * @param   iSegReg             The index of the segment register to use for
+ *                              this access.  The base and limits are checked.
+ * @param   GCPtrMem            The address of the guest memory.
+ */
+IEM_STATIC VBOXSTRICTRC iemMemFetchDataU256AlignedSse(PVMCPU pVCpu, PRTUINT256U pu256Dst, uint8_t iSegReg, RTGCPTR GCPtrMem)
+{
+    /* The lazy approach for now... */
+    /** @todo testcase: Ordering of \#SS(0) vs \#GP() vs \#PF on AVX stuff. */
+    if (GCPtrMem & 31)
+        return iemRaiseGeneralProtectionFault0(pVCpu);
+
+    PCRTUINT256U pu256Src;
+    VBOXSTRICTRC rc = iemMemMap(pVCpu, (void **)&pu256Src, sizeof(*pu256Src), iSegReg, GCPtrMem, IEM_ACCESS_DATA_R);
+    if (rc == VINF_SUCCESS)
+    {
+        pu256Dst->au64[0] = pu256Src->au64[0];
+        pu256Dst->au64[1] = pu256Src->au64[1];
+        pu256Dst->au64[2] = pu256Src->au64[2];
+        pu256Dst->au64[3] = pu256Src->au64[3];
+        rc = iemMemCommitAndUnmap(pVCpu, (void *)pu256Src, IEM_ACCESS_DATA_R);
+    }
+    return rc;
+}
+
+
+#ifdef IEM_WITH_SETJMP
+/**
+ * Fetches a data oword (octo word) at an aligned address, generally AVX
+ * related, longjmp on error.
+ *
+ * Raises \#GP(0) if not aligned.
+ *
+ * @param   pVCpu               The cross context virtual CPU structure of the calling thread.
+ * @param   pu256Dst            Where to return the qword.
+ * @param   iSegReg             The index of the segment register to use for
+ *                              this access.  The base and limits are checked.
+ * @param   GCPtrMem            The address of the guest memory.
+ */
+DECL_NO_INLINE(IEM_STATIC, void) iemMemFetchDataU256AlignedSseJmp(PVMCPU pVCpu, PRTUINT256U pu256Dst, uint8_t iSegReg, RTGCPTR GCPtrMem)
+{
+    /* The lazy approach for now... */
+    /** @todo testcase: Ordering of \#SS(0) vs \#GP() vs \#PF on AVX stuff. */
+    if ((GCPtrMem & 31) == 0)
+    {
+        PCRTUINT256U pu256Src = (PCRTUINT256U)iemMemMapJmp(pVCpu, sizeof(*pu256Src), iSegReg, GCPtrMem, IEM_ACCESS_DATA_R);
+        pu256Dst->au64[0] = pu256Src->au64[0];
+        pu256Dst->au64[1] = pu256Src->au64[1];
+        pu256Dst->au64[2] = pu256Src->au64[2];
+        pu256Dst->au64[3] = pu256Src->au64[3];
+        iemMemCommitAndUnmapJmp(pVCpu, (void *)pu256Src, IEM_ACCESS_DATA_R);
+        return;
+    }
+
+    VBOXSTRICTRC rcStrict = iemRaiseGeneralProtectionFault0(pVCpu);
+    longjmp(*pVCpu->iem.s.CTX_SUFF(pJmpBuf), VBOXSTRICTRC_VAL(rcStrict));
+}
+#endif
+
+
 
 /**
  * Fetches a descriptor register (lgdt, lidt).
@@ -9806,6 +10200,118 @@ iemMemStoreDataU128AlignedSseJmp(PVMCPU pVCpu, uint8_t iSegReg, RTGCPTR GCPtrMem
 
 
 /**
+ * Stores a data dqword.
+ *
+ * @returns Strict VBox status code.
+ * @param   pVCpu               The cross context virtual CPU structure of the calling thread.
+ * @param   iSegReg             The index of the segment register to use for
+ *                              this access.  The base and limits are checked.
+ * @param   GCPtrMem            The address of the guest memory.
+ * @param   pu256Value          Pointer to the value to store.
+ */
+IEM_STATIC VBOXSTRICTRC iemMemStoreDataU256(PVMCPU pVCpu, uint8_t iSegReg, RTGCPTR GCPtrMem, PCRTUINT256U pu256Value)
+{
+    /* The lazy approach for now... */
+    PRTUINT256U pu256Dst;
+    VBOXSTRICTRC rc = iemMemMap(pVCpu, (void **)&pu256Dst, sizeof(*pu256Dst), iSegReg, GCPtrMem, IEM_ACCESS_DATA_W);
+    if (rc == VINF_SUCCESS)
+    {
+        pu256Dst->au64[0] = pu256Value->au64[0];
+        pu256Dst->au64[1] = pu256Value->au64[1];
+        pu256Dst->au64[2] = pu256Value->au64[2];
+        pu256Dst->au64[3] = pu256Value->au64[3];
+        rc = iemMemCommitAndUnmap(pVCpu, pu256Dst, IEM_ACCESS_DATA_W);
+    }
+    return rc;
+}
+
+
+#ifdef IEM_WITH_SETJMP
+/**
+ * Stores a data dqword, longjmp on error.
+ *
+ * @param   pVCpu               The cross context virtual CPU structure of the calling thread.
+ * @param   iSegReg             The index of the segment register to use for
+ *                              this access.  The base and limits are checked.
+ * @param   GCPtrMem            The address of the guest memory.
+ * @param   pu256Value          Pointer to the value to store.
+ */
+IEM_STATIC void iemMemStoreDataU256Jmp(PVMCPU pVCpu, uint8_t iSegReg, RTGCPTR GCPtrMem, PCRTUINT256U pu256Value)
+{
+    /* The lazy approach for now... */
+    PRTUINT256U pu256Dst = (PRTUINT256U)iemMemMapJmp(pVCpu, sizeof(*pu256Dst), iSegReg, GCPtrMem, IEM_ACCESS_DATA_W);
+    pu256Dst->au64[0] = pu256Value->au64[0];
+    pu256Dst->au64[1] = pu256Value->au64[1];
+    pu256Dst->au64[2] = pu256Value->au64[2];
+    pu256Dst->au64[3] = pu256Value->au64[3];
+    iemMemCommitAndUnmapJmp(pVCpu, pu256Dst, IEM_ACCESS_DATA_W);
+}
+#endif
+
+
+/**
+ * Stores a data dqword, AVX aligned.
+ *
+ * @returns Strict VBox status code.
+ * @param   pVCpu               The cross context virtual CPU structure of the calling thread.
+ * @param   iSegReg             The index of the segment register to use for
+ *                              this access.  The base and limits are checked.
+ * @param   GCPtrMem            The address of the guest memory.
+ * @param   pu256Value          Pointer to the value to store.
+ */
+IEM_STATIC VBOXSTRICTRC iemMemStoreDataU256AlignedAvx(PVMCPU pVCpu, uint8_t iSegReg, RTGCPTR GCPtrMem, PCRTUINT256U pu256Value)
+{
+    /* The lazy approach for now... */
+    if (GCPtrMem & 31)
+        return iemRaiseGeneralProtectionFault0(pVCpu);
+
+    PRTUINT256U pu256Dst;
+    VBOXSTRICTRC rc = iemMemMap(pVCpu, (void **)&pu256Dst, sizeof(*pu256Dst), iSegReg, GCPtrMem, IEM_ACCESS_DATA_W);
+    if (rc == VINF_SUCCESS)
+    {
+        pu256Dst->au64[0] = pu256Value->au64[0];
+        pu256Dst->au64[1] = pu256Value->au64[1];
+        pu256Dst->au64[2] = pu256Value->au64[2];
+        pu256Dst->au64[3] = pu256Value->au64[3];
+        rc = iemMemCommitAndUnmap(pVCpu, pu256Dst, IEM_ACCESS_DATA_W);
+    }
+    return rc;
+}
+
+
+#ifdef IEM_WITH_SETJMP
+/**
+ * Stores a data dqword, AVX aligned.
+ *
+ * @returns Strict VBox status code.
+ * @param   pVCpu               The cross context virtual CPU structure of the calling thread.
+ * @param   iSegReg             The index of the segment register to use for
+ *                              this access.  The base and limits are checked.
+ * @param   GCPtrMem            The address of the guest memory.
+ * @param   pu256Value          Pointer to the value to store.
+ */
+DECL_NO_INLINE(IEM_STATIC, void)
+iemMemStoreDataU256AlignedAvxJmp(PVMCPU pVCpu, uint8_t iSegReg, RTGCPTR GCPtrMem, PCRTUINT256U pu256Value)
+{
+    /* The lazy approach for now... */
+    if ((GCPtrMem & 31) == 0)
+    {
+        PRTUINT256U pu256Dst = (PRTUINT256U)iemMemMapJmp(pVCpu, sizeof(*pu256Dst), iSegReg, GCPtrMem, IEM_ACCESS_DATA_W);
+        pu256Dst->au64[0] = pu256Value->au64[0];
+        pu256Dst->au64[1] = pu256Value->au64[1];
+        pu256Dst->au64[2] = pu256Value->au64[2];
+        pu256Dst->au64[3] = pu256Value->au64[3];
+        iemMemCommitAndUnmapJmp(pVCpu, pu256Dst, IEM_ACCESS_DATA_W);
+        return;
+    }
+
+    VBOXSTRICTRC rcStrict = iemRaiseGeneralProtectionFault0(pVCpu);
+    longjmp(*pVCpu->iem.s.CTX_SUFF(pJmpBuf), VBOXSTRICTRC_VAL(rcStrict));
+}
+#endif
+
+
+/**
  * Stores a descriptor register (sgdt, sidt).
  *
  * @returns Strict VBox status code.
@@ -10717,6 +11223,33 @@ IEM_STATIC VBOXSTRICTRC iemMemMarkSelDescAccessed(PVMCPU pVCpu, uint16_t uSel)
         if ((pVCpu)->iem.s.CTX_SUFF(pCtx)->CTX_SUFF(pXState)->x87.FSW & X86_FSW_ES) \
             return iemRaiseMathFault(pVCpu); \
     } while (0)
+#define IEM_MC_MAYBE_RAISE_AVX2_RELATED_XCPT() \
+    do { \
+        if (   (IEM_GET_CTX(pVCpu)->aXcr[0] & (XSAVE_C_YMM | XSAVE_C_SSE)) != (XSAVE_C_YMM | XSAVE_C_SSE) \
+            || !(IEM_GET_CTX(pVCpu)->cr4 & X86_CR4_OSXSAVE) \
+            || !IEM_GET_GUEST_CPU_FEATURES(pVCpu)->fAvx2) \
+            return iemRaiseUndefinedOpcode(pVCpu); \
+        if (IEM_GET_CTX(pVCpu)->cr0 & X86_CR0_TS) \
+            return iemRaiseDeviceNotAvailable(pVCpu); \
+    } while (0)
+#define IEM_MC_MAYBE_RAISE_AVX_RELATED_XCPT() \
+    do { \
+        if (   (IEM_GET_CTX(pVCpu)->aXcr[0] & (XSAVE_C_YMM | XSAVE_C_SSE)) != (XSAVE_C_YMM | XSAVE_C_SSE) \
+            || !(IEM_GET_CTX(pVCpu)->cr4 & X86_CR4_OSXSAVE) \
+            || !IEM_GET_GUEST_CPU_FEATURES(pVCpu)->fAvx) \
+            return iemRaiseUndefinedOpcode(pVCpu); \
+        if (IEM_GET_CTX(pVCpu)->cr0 & X86_CR0_TS) \
+            return iemRaiseDeviceNotAvailable(pVCpu); \
+    } while (0)
+#define IEM_MC_MAYBE_RAISE_SSE41_RELATED_XCPT() \
+    do { \
+        if (   (IEM_GET_CTX(pVCpu)->cr0 & X86_CR0_EM) \
+            || !(IEM_GET_CTX(pVCpu)->cr4 & X86_CR4_OSFXSR) \
+            || !IEM_GET_GUEST_CPU_FEATURES(pVCpu)->fSse41) \
+            return iemRaiseUndefinedOpcode(pVCpu); \
+        if (IEM_GET_CTX(pVCpu)->cr0 & X86_CR0_TS) \
+            return iemRaiseDeviceNotAvailable(pVCpu); \
+    } while (0)
 #define IEM_MC_MAYBE_RAISE_SSE3_RELATED_XCPT() \
     do { \
         if (   (IEM_GET_CTX(pVCpu)->cr0 & X86_CR0_EM) \
@@ -10929,16 +11462,25 @@ IEM_STATIC VBOXSTRICTRC iemMemMarkSelDescAccessed(PVMCPU pVCpu, uint16_t uSel)
 
 #define IEM_MC_CLEAR_FSW_EX()   do { (pVCpu)->iem.s.CTX_SUFF(pCtx)->CTX_SUFF(pXState)->x87.FSW &= X86_FSW_C_MASK | X86_FSW_TOP_MASK; } while (0)
 
+/** Switches the FPU state to MMX mode (FSW.TOS=0, FTW=0) if necessary. */
+#define IEM_MC_FPU_TO_MMX_MODE() do { \
+        IEM_GET_CTX(pVCpu)->CTX_SUFF(pXState)->x87.FSW &= ~X86_FSW_TOP_MASK; \
+        IEM_GET_CTX(pVCpu)->CTX_SUFF(pXState)->x87.FTW  = 0xff; \
+    } while (0)
 
 #define IEM_MC_FETCH_MREG_U64(a_u64Value, a_iMReg) \
     do { (a_u64Value) = IEM_GET_CTX(pVCpu)->CTX_SUFF(pXState)->x87.aRegs[(a_iMReg)].mmx; } while (0)
 #define IEM_MC_FETCH_MREG_U32(a_u32Value, a_iMReg) \
     do { (a_u32Value) = IEM_GET_CTX(pVCpu)->CTX_SUFF(pXState)->x87.aRegs[(a_iMReg)].au32[0]; } while (0)
-#define IEM_MC_STORE_MREG_U64(a_iMReg, a_u64Value) \
-    do { IEM_GET_CTX(pVCpu)->CTX_SUFF(pXState)->x87.aRegs[(a_iMReg)].mmx = (a_u64Value); } while (0)
-#define IEM_MC_STORE_MREG_U32_ZX_U64(a_iMReg, a_u32Value) \
-    do { IEM_GET_CTX(pVCpu)->CTX_SUFF(pXState)->x87.aRegs[(a_iMReg)].mmx = (uint32_t)(a_u32Value); } while (0)
-#define IEM_MC_REF_MREG_U64(a_pu64Dst, a_iMReg)         \
+#define IEM_MC_STORE_MREG_U64(a_iMReg, a_u64Value) do { \
+        IEM_GET_CTX(pVCpu)->CTX_SUFF(pXState)->x87.aRegs[(a_iMReg)].mmx = (a_u64Value); \
+        IEM_GET_CTX(pVCpu)->CTX_SUFF(pXState)->x87.aRegs[(a_iMReg)].au32[2] = 0xffff; \
+    } while (0)
+#define IEM_MC_STORE_MREG_U32_ZX_U64(a_iMReg, a_u32Value) do { \
+        IEM_GET_CTX(pVCpu)->CTX_SUFF(pXState)->x87.aRegs[(a_iMReg)].mmx = (uint32_t)(a_u32Value); \
+        IEM_GET_CTX(pVCpu)->CTX_SUFF(pXState)->x87.aRegs[(a_iMReg)].au32[2] = 0xffff; \
+    } while (0)
+#define IEM_MC_REF_MREG_U64(a_pu64Dst, a_iMReg) /** @todo need to set high word to 0xffff on commit (see IEM_MC_STORE_MREG_U64) */ \
         (a_pu64Dst) = (&IEM_GET_CTX(pVCpu)->CTX_SUFF(pXState)->x87.aRegs[(a_iMReg)].mmx)
 #define IEM_MC_REF_MREG_U64_CONST(a_pu64Dst, a_iMReg) \
         (a_pu64Dst) = ((uint64_t const *)&IEM_GET_CTX(pVCpu)->CTX_SUFF(pXState)->x87.aRegs[(a_iMReg)].mmx)
@@ -10971,6 +11513,8 @@ IEM_STATIC VBOXSTRICTRC iemMemMarkSelDescAccessed(PVMCPU pVCpu, uint16_t uSel)
     do { IEM_GET_CTX(pVCpu)->CTX_SUFF(pXState)->x87.aXMM[(a_iXReg)].au64[0] = (uint32_t)(a_u32Value); \
          IEM_GET_CTX(pVCpu)->CTX_SUFF(pXState)->x87.aXMM[(a_iXReg)].au64[1] = 0; \
     } while (0)
+#define IEM_MC_STORE_XREG_HI_U64(a_iXReg, a_u64Value) \
+    do { IEM_GET_CTX(pVCpu)->CTX_SUFF(pXState)->x87.aXMM[(a_iXReg)].au64[1] = (a_u64Value); } while (0)
 #define IEM_MC_REF_XREG_U128(a_pu128Dst, a_iXReg)       \
     (a_pu128Dst) = (&IEM_GET_CTX(pVCpu)->CTX_SUFF(pXState)->x87.aXMM[(a_iXReg)].uXmm)
 #define IEM_MC_REF_XREG_U128_CONST(a_pu128Dst, a_iXReg) \
@@ -10984,6 +11528,160 @@ IEM_STATIC VBOXSTRICTRC iemMemMarkSelDescAccessed(PVMCPU pVCpu, uint16_t uSel)
             = IEM_GET_CTX(pVCpu)->CTX_SUFF(pXState)->x87.aXMM[(a_iXRegSrc)].au64[1]; \
     } while (0)
 
+#define IEM_MC_FETCH_YREG_U32(a_u32Dst, a_iYRegSrc) \
+    do { PX86XSAVEAREA   pXStateTmp     = IEM_GET_CTX(pVCpu)->CTX_SUFF(pXState); \
+         uintptr_t const iYRegSrcTmp    = (a_iYRegSrc); \
+         (a_u32Dst) = pXStateTmp->x87.aXMM[iYRegSrcTmp].au32[0]; \
+    } while (0)
+#define IEM_MC_FETCH_YREG_U64(a_u64Dst, a_iYRegSrc) \
+    do { PX86XSAVEAREA   pXStateTmp     = IEM_GET_CTX(pVCpu)->CTX_SUFF(pXState); \
+         uintptr_t const iYRegSrcTmp    = (a_iYRegSrc); \
+         (a_u64Dst) = pXStateTmp->x87.aXMM[iYRegSrcTmp].au64[0]; \
+    } while (0)
+#define IEM_MC_FETCH_YREG_U128(a_u128Dst, a_iYRegSrc) \
+    do { PX86XSAVEAREA   pXStateTmp     = IEM_GET_CTX(pVCpu)->CTX_SUFF(pXState); \
+         uintptr_t const iYRegSrcTmp    = (a_iYRegSrc); \
+         (a_u128Dst).au64[0] = pXStateTmp->x87.aXMM[iYRegSrcTmp].au64[0]; \
+         (a_u128Dst).au64[1] = pXStateTmp->x87.aXMM[iYRegSrcTmp].au64[1]; \
+    } while (0)
+#define IEM_MC_FETCH_YREG_U256(a_u256Dst, a_iYRegSrc) \
+    do { PX86XSAVEAREA   pXStateTmp     = IEM_GET_CTX(pVCpu)->CTX_SUFF(pXState); \
+         uintptr_t const iYRegSrcTmp    = (a_iYRegSrc); \
+         (a_u256Dst).au64[0] = pXStateTmp->x87.aXMM[iYRegSrcTmp].au64[0]; \
+         (a_u256Dst).au64[1] = pXStateTmp->x87.aXMM[iYRegSrcTmp].au64[1]; \
+         (a_u256Dst).au64[2] = pXStateTmp->u.YmmHi.aYmmHi[iYRegSrcTmp].au64[0]; \
+         (a_u256Dst).au64[3] = pXStateTmp->u.YmmHi.aYmmHi[iYRegSrcTmp].au64[1]; \
+    } while (0)
+
+#define IEM_MC_INT_CLEAR_ZMM_256_UP(a_pXState, a_iXRegDst) do { /* For AVX512 and AVX1024 support. */ } while (0)
+#define IEM_MC_STORE_YREG_U32_ZX_VLMAX(a_iYRegDst, a_u32Src) \
+    do { PX86XSAVEAREA   pXStateTmp     = IEM_GET_CTX(pVCpu)->CTX_SUFF(pXState); \
+         uintptr_t const iYRegDstTmp    = (a_iYRegDst); \
+         pXStateTmp->x87.aXMM[iYRegDstTmp].au32[0]       = (a_u32Src); \
+         pXStateTmp->x87.aXMM[iYRegDstTmp].au32[1]       = 0; \
+         pXStateTmp->x87.aXMM[iYRegDstTmp].au64[1]       = 0; \
+         pXStateTmp->u.YmmHi.aYmmHi[iYRegDstTmp].au64[0] = 0; \
+         pXStateTmp->u.YmmHi.aYmmHi[iYRegDstTmp].au64[1] = 0; \
+         IEM_MC_INT_CLEAR_ZMM_256_UP(pXStateTmp, iYRegDstTmp); \
+    } while (0)
+#define IEM_MC_STORE_YREG_U64_ZX_VLMAX(a_iYRegDst, a_u64Src) \
+    do { PX86XSAVEAREA   pXStateTmp     = IEM_GET_CTX(pVCpu)->CTX_SUFF(pXState); \
+         uintptr_t const iYRegDstTmp    = (a_iYRegDst); \
+         pXStateTmp->x87.aXMM[iYRegDstTmp].au64[0]       = (a_u64Src); \
+         pXStateTmp->x87.aXMM[iYRegDstTmp].au64[1]       = 0; \
+         pXStateTmp->u.YmmHi.aYmmHi[iYRegDstTmp].au64[0] = 0; \
+         pXStateTmp->u.YmmHi.aYmmHi[iYRegDstTmp].au64[1] = 0; \
+         IEM_MC_INT_CLEAR_ZMM_256_UP(pXStateTmp, iYRegDstTmp); \
+    } while (0)
+#define IEM_MC_STORE_YREG_U128_ZX_VLMAX(a_iYRegDst, a_u128Src) \
+    do { PX86XSAVEAREA   pXStateTmp     = IEM_GET_CTX(pVCpu)->CTX_SUFF(pXState); \
+         uintptr_t const iYRegDstTmp    = (a_iYRegDst); \
+         pXStateTmp->x87.aXMM[iYRegDstTmp].au64[0]       = (a_u128Src).au64[0]; \
+         pXStateTmp->x87.aXMM[iYRegDstTmp].au64[1]       = (a_u128Src).au64[1]; \
+         pXStateTmp->u.YmmHi.aYmmHi[iYRegDstTmp].au64[0] = 0; \
+         pXStateTmp->u.YmmHi.aYmmHi[iYRegDstTmp].au64[1] = 0; \
+         IEM_MC_INT_CLEAR_ZMM_256_UP(pXStateTmp, iYRegDstTmp); \
+    } while (0)
+#define IEM_MC_STORE_YREG_U256_ZX_VLMAX(a_iYRegDst, a_u256Src) \
+    do { PX86XSAVEAREA   pXStateTmp     = IEM_GET_CTX(pVCpu)->CTX_SUFF(pXState); \
+         uintptr_t const iYRegDstTmp    = (a_iYRegDst); \
+         pXStateTmp->x87.aXMM[iYRegDstTmp].au64[0]       = (a_u256Src).au64[0]; \
+         pXStateTmp->x87.aXMM[iYRegDstTmp].au64[1]       = (a_u256Src).au64[1]; \
+         pXStateTmp->u.YmmHi.aYmmHi[iYRegDstTmp].au64[0] = (a_u256Src).au64[2]; \
+         pXStateTmp->u.YmmHi.aYmmHi[iYRegDstTmp].au64[1] = (a_u256Src).au64[3]; \
+         IEM_MC_INT_CLEAR_ZMM_256_UP(pXStateTmp, iYRegDstTmp); \
+    } while (0)
+
+#define IEM_MC_REF_YREG_U128(a_pu128Dst, a_iYReg)       \
+    (a_pu128Dst) = (&IEM_GET_CTX(pVCpu)->CTX_SUFF(pXState)->x87.aYMM[(a_iYReg)].uXmm)
+#define IEM_MC_REF_YREG_U128_CONST(a_pu128Dst, a_iYReg) \
+    (a_pu128Dst) = ((PCRTUINT128U)&IEM_GET_CTX(pVCpu)->CTX_SUFF(pXState)->x87.aYMM[(a_iYReg)].uXmm)
+#define IEM_MC_REF_YREG_U64_CONST(a_pu64Dst, a_iYReg) \
+    (a_pu64Dst) = ((uint64_t const *)&IEM_GET_CTX(pVCpu)->CTX_SUFF(pXState)->x87.aYMM[(a_iYReg)].au64[0])
+#define IEM_MC_CLEAR_YREG_128_UP(a_iYReg) \
+    do { PX86XSAVEAREA   pXStateTmp = IEM_GET_CTX(pVCpu)->CTX_SUFF(pXState); \
+         uintptr_t const iYRegTmp   = (a_iYReg); \
+         pXStateTmp->u.YmmHi.aYmmHi[iYRegTmp].au64[0] = 0; \
+         pXStateTmp->u.YmmHi.aYmmHi[iYRegTmp].au64[1] = 0; \
+         IEM_MC_INT_CLEAR_ZMM_256_UP(pXStateTmp, iYRegTmp); \
+    } while (0)
+
+#define IEM_MC_COPY_YREG_U256_ZX_VLMAX(a_iYRegDst, a_iYRegSrc) \
+    do { PX86XSAVEAREA   pXStateTmp     = IEM_GET_CTX(pVCpu)->CTX_SUFF(pXState); \
+         uintptr_t const iYRegDstTmp    = (a_iYRegDst); \
+         uintptr_t const iYRegSrcTmp    = (a_iYRegSrc); \
+         pXStateTmp->x87.aXMM[iYRegDstTmp].au64[0]       = pXStateTmp->x87.aXMM[iYRegSrcTmp].au64[0]; \
+         pXStateTmp->x87.aXMM[iYRegDstTmp].au64[1]       = pXStateTmp->x87.aXMM[iYRegSrcTmp].au64[1]; \
+         pXStateTmp->u.YmmHi.aYmmHi[iYRegDstTmp].au64[0] = pXStateTmp->u.YmmHi.aYmmHi[iYRegSrcTmp].au64[0]; \
+         pXStateTmp->u.YmmHi.aYmmHi[iYRegDstTmp].au64[1] = pXStateTmp->u.YmmHi.aYmmHi[iYRegSrcTmp].au64[1]; \
+         IEM_MC_INT_CLEAR_ZMM_256_UP(pXStateTmp, iYRegDstTmp); \
+    } while (0)
+#define IEM_MC_COPY_YREG_U128_ZX_VLMAX(a_iYRegDst, a_iYRegSrc) \
+    do { PX86XSAVEAREA   pXStateTmp     = IEM_GET_CTX(pVCpu)->CTX_SUFF(pXState); \
+         uintptr_t const iYRegDstTmp    = (a_iYRegDst); \
+         uintptr_t const iYRegSrcTmp    = (a_iYRegSrc); \
+         pXStateTmp->x87.aXMM[iYRegDstTmp].au64[0]       = pXStateTmp->x87.aXMM[iYRegSrcTmp].au64[0]; \
+         pXStateTmp->x87.aXMM[iYRegDstTmp].au64[1]       = pXStateTmp->x87.aXMM[iYRegSrcTmp].au64[1]; \
+         pXStateTmp->u.YmmHi.aYmmHi[iYRegDstTmp].au64[0] = 0; \
+         pXStateTmp->u.YmmHi.aYmmHi[iYRegDstTmp].au64[1] = 0; \
+         IEM_MC_INT_CLEAR_ZMM_256_UP(pXStateTmp, iYRegDstTmp); \
+    } while (0)
+#define IEM_MC_COPY_YREG_U64_ZX_VLMAX(a_iYRegDst, a_iYRegSrc) \
+    do { PX86XSAVEAREA   pXStateTmp     = IEM_GET_CTX(pVCpu)->CTX_SUFF(pXState); \
+         uintptr_t const iYRegDstTmp    = (a_iYRegDst); \
+         uintptr_t const iYRegSrcTmp    = (a_iYRegSrc); \
+         pXStateTmp->x87.aXMM[iYRegDstTmp].au64[0]       = pXStateTmp->x87.aXMM[iYRegSrcTmp].au64[0]; \
+         pXStateTmp->x87.aXMM[iYRegDstTmp].au64[1]       = 0; \
+         pXStateTmp->u.YmmHi.aYmmHi[iYRegDstTmp].au64[0] = 0; \
+         pXStateTmp->u.YmmHi.aYmmHi[iYRegDstTmp].au64[1] = 0; \
+         IEM_MC_INT_CLEAR_ZMM_256_UP(pXStateTmp, iYRegDstTmp); \
+    } while (0)
+
+#define IEM_MC_MERGE_YREG_U32_U96_ZX_VLMAX(a_iYRegDst, a_iYRegSrc32, a_iYRegSrcHx) \
+    do { PX86XSAVEAREA   pXStateTmp     = IEM_GET_CTX(pVCpu)->CTX_SUFF(pXState); \
+         uintptr_t const iYRegDstTmp    = (a_iYRegDst); \
+         uintptr_t const iYRegSrc32Tmp  = (a_iYRegSrc32); \
+         uintptr_t const iYRegSrcHxTmp  = (a_iYRegSrcHx); \
+         pXStateTmp->x87.aXMM[iYRegDstTmp].au32[0]       = pXStateTmp->x87.aXMM[iYRegSrc32Tmp].au32[0]; \
+         pXStateTmp->x87.aXMM[iYRegDstTmp].au32[1]       = pXStateTmp->x87.aXMM[iYRegSrcHxTmp].au32[1]; \
+         pXStateTmp->x87.aXMM[iYRegDstTmp].au64[1]       = pXStateTmp->x87.aXMM[iYRegSrcHxTmp].au64[1]; \
+         pXStateTmp->u.YmmHi.aYmmHi[iYRegDstTmp].au64[0] = 0; \
+         pXStateTmp->u.YmmHi.aYmmHi[iYRegDstTmp].au64[1] = 0; \
+         IEM_MC_INT_CLEAR_ZMM_256_UP(pXStateTmp, iYRegDstTmp); \
+    } while (0)
+#define IEM_MC_MERGE_YREG_U64_U64_ZX_VLMAX(a_iYRegDst, a_iYRegSrc64, a_iYRegSrcHx) \
+    do { PX86XSAVEAREA   pXStateTmp     = IEM_GET_CTX(pVCpu)->CTX_SUFF(pXState); \
+         uintptr_t const iYRegDstTmp    = (a_iYRegDst); \
+         uintptr_t const iYRegSrc64Tmp  = (a_iYRegSrc64); \
+         uintptr_t const iYRegSrcHxTmp  = (a_iYRegSrcHx); \
+         pXStateTmp->x87.aXMM[iYRegDstTmp].au64[0]       = pXStateTmp->x87.aXMM[iYRegSrc64Tmp].au64[0]; \
+         pXStateTmp->x87.aXMM[iYRegDstTmp].au64[1]       = pXStateTmp->x87.aXMM[iYRegSrcHxTmp].au64[1]; \
+         pXStateTmp->u.YmmHi.aYmmHi[iYRegDstTmp].au64[0] = 0; \
+         pXStateTmp->u.YmmHi.aYmmHi[iYRegDstTmp].au64[1] = 0; \
+         IEM_MC_INT_CLEAR_ZMM_256_UP(pXStateTmp, iYRegDstTmp); \
+    } while (0)
+#define IEM_MC_MERGE_YREG_U64HI_U64_ZX_VLMAX(a_iYRegDst, a_iYRegSrc64, a_iYRegSrcHx) /* for vmovhlps */ \
+    do { PX86XSAVEAREA   pXStateTmp     = IEM_GET_CTX(pVCpu)->CTX_SUFF(pXState); \
+         uintptr_t const iYRegDstTmp    = (a_iYRegDst); \
+         uintptr_t const iYRegSrc64Tmp  = (a_iYRegSrc64); \
+         uintptr_t const iYRegSrcHxTmp  = (a_iYRegSrcHx); \
+         pXStateTmp->x87.aXMM[iYRegDstTmp].au64[0]       = pXStateTmp->x87.aXMM[iYRegSrc64Tmp].au64[1]; \
+         pXStateTmp->x87.aXMM[iYRegDstTmp].au64[1]       = pXStateTmp->x87.aXMM[iYRegSrcHxTmp].au64[1]; \
+         pXStateTmp->u.YmmHi.aYmmHi[iYRegDstTmp].au64[0] = 0; \
+         pXStateTmp->u.YmmHi.aYmmHi[iYRegDstTmp].au64[1] = 0; \
+         IEM_MC_INT_CLEAR_ZMM_256_UP(pXStateTmp, iYRegDstTmp); \
+    } while (0)
+#define IEM_MC_MERGE_YREG_U64LOCAL_U64_ZX_VLMAX(a_iYRegDst, a_u64Local, a_iYRegSrcHx) \
+    do { PX86XSAVEAREA   pXStateTmp     = IEM_GET_CTX(pVCpu)->CTX_SUFF(pXState); \
+         uintptr_t const iYRegDstTmp    = (a_iYRegDst); \
+         uintptr_t const iYRegSrcHxTmp  = (a_iYRegSrcHx); \
+         pXStateTmp->x87.aXMM[iYRegDstTmp].au64[0]       = (a_u64Local); \
+         pXStateTmp->x87.aXMM[iYRegDstTmp].au64[1]       = pXStateTmp->x87.aXMM[iYRegSrcHxTmp].au64[1]; \
+         pXStateTmp->u.YmmHi.aYmmHi[iYRegDstTmp].au64[0] = 0; \
+         pXStateTmp->u.YmmHi.aYmmHi[iYRegDstTmp].au64[1] = 0; \
+         IEM_MC_INT_CLEAR_ZMM_256_UP(pXStateTmp, iYRegDstTmp); \
+    } while (0)
+
 #ifndef IEM_WITH_SETJMP
 # define IEM_MC_FETCH_MEM_U8(a_u8Dst, a_iSeg, a_GCPtrMem) \
     IEM_MC_RETURN_ON_FAILURE(iemMemFetchDataU8(pVCpu, &(a_u8Dst), (a_iSeg), (a_GCPtrMem)))
@@ -11085,6 +11783,18 @@ IEM_STATIC VBOXSTRICTRC iemMemMarkSelDescAccessed(PVMCPU pVCpu, uint16_t uSel)
     iemMemFetchDataU128AlignedSseJmp(pVCpu, &(a_u128Dst), (a_iSeg), (a_GCPtrMem))
 #endif
 
+#ifndef IEM_WITH_SETJMP
+# define IEM_MC_FETCH_MEM_U256(a_u256Dst, a_iSeg, a_GCPtrMem) \
+    IEM_MC_RETURN_ON_FAILURE(iemMemFetchDataU256(pVCpu, &(a_u256Dst), (a_iSeg), (a_GCPtrMem)))
+# define IEM_MC_FETCH_MEM_U256_ALIGN_AVX(a_u256Dst, a_iSeg, a_GCPtrMem) \
+    IEM_MC_RETURN_ON_FAILURE(iemMemFetchDataU256AlignedSse(pVCpu, &(a_u256Dst), (a_iSeg), (a_GCPtrMem)))
+#else
+# define IEM_MC_FETCH_MEM_U256(a_u256Dst, a_iSeg, a_GCPtrMem) \
+    iemMemFetchDataU256Jmp(pVCpu, &(a_u256Dst), (a_iSeg), (a_GCPtrMem))
+# define IEM_MC_FETCH_MEM_U256_ALIGN_AVX(a_u256Dst, a_iSeg, a_GCPtrMem) \
+    iemMemFetchDataU256AlignedSseJmp(pVCpu, &(a_u256Dst), (a_iSeg), (a_GCPtrMem))
+#endif
+
 
 
 #ifndef IEM_WITH_SETJMP
@@ -11255,6 +11965,18 @@ IEM_STATIC VBOXSTRICTRC iemMemMarkSelDescAccessed(PVMCPU pVCpu, uint16_t uSel)
     iemMemStoreDataU128AlignedSseJmp(pVCpu, (a_iSeg), (a_GCPtrMem), (a_u128Value))
 #endif
 
+#ifndef IEM_WITH_SETJMP
+# define IEM_MC_STORE_MEM_U256(a_iSeg, a_GCPtrMem, a_u256Value) \
+    IEM_MC_RETURN_ON_FAILURE(iemMemStoreDataU256(pVCpu, (a_iSeg), (a_GCPtrMem), &(a_u256Value)))
+# define IEM_MC_STORE_MEM_U256_ALIGN_AVX(a_iSeg, a_GCPtrMem, a_u256Value) \
+    IEM_MC_RETURN_ON_FAILURE(iemMemStoreDataU256AlignedAvx(pVCpu, (a_iSeg), (a_GCPtrMem), &(a_u256Value)))
+#else
+# define IEM_MC_STORE_MEM_U256(a_iSeg, a_GCPtrMem, a_u256Value) \
+    iemMemStoreDataU256Jmp(pVCpu, (a_iSeg), (a_GCPtrMem), &(a_u256Value))
+# define IEM_MC_STORE_MEM_U256_ALIGN_AVX(a_iSeg, a_GCPtrMem, a_u256Value) \
+    iemMemStoreDataU256AlignedAvxJmp(pVCpu, (a_iSeg), (a_GCPtrMem), &(a_u256Value))
+#endif
+
 
 #define IEM_MC_PUSH_U16(a_u16Value) \
     IEM_MC_RETURN_ON_FAILURE(iemMemStackPushU16(pVCpu, (a_u16Value)))
@@ -11591,6 +12313,17 @@ IEM_STATIC VBOXSTRICTRC iemMemMarkSelDescAccessed(PVMCPU pVCpu, uint16_t uSel)
 /** Actualizes the guest XMM0..15 and MXCSR register state for read-write access. */
 #define IEM_MC_ACTUALIZE_SSE_STATE_FOR_CHANGE() iemFpuActualizeSseStateForChange(pVCpu)
 
+/** Prepares for using the AVX state.
+ * Ensures that we can use the host AVX/FPU in the current context (RC+R0.
+ * Ensures the guest AVX state in the CPUMCTX is up to date.
+ * @note This will include the AVX512 state too when support for it is added
+ *       due to the zero extending feature of VEX instruction. */
+#define IEM_MC_PREPARE_AVX_USAGE()              iemFpuPrepareUsageAvx(pVCpu)
+/** Actualizes the guest XMM0..15 and MXCSR register state for read-only access. */
+#define IEM_MC_ACTUALIZE_AVX_STATE_FOR_READ()   iemFpuActualizeAvxStateForRead(pVCpu)
+/** Actualizes the guest YMM0..15 and MXCSR register state for read-write access. */
+#define IEM_MC_ACTUALIZE_AVX_STATE_FOR_CHANGE() iemFpuActualizeAvxStateForChange(pVCpu)
+
 /**
  * Calls a MMX assembly implementation taking two visible arguments.
  *
@@ -11622,7 +12355,7 @@ IEM_STATIC VBOXSTRICTRC iemMemMarkSelDescAccessed(PVMCPU pVCpu, uint16_t uSel)
 /**
  * Calls a SSE assembly implementation taking two visible arguments.
  *
- * @param   a_pfnAImpl      Pointer to the assembly MMX routine.
+ * @param   a_pfnAImpl      Pointer to the assembly SSE routine.
  * @param   a0              The first extra argument.
  * @param   a1              The second extra argument.
  */
@@ -11635,7 +12368,7 @@ IEM_STATIC VBOXSTRICTRC iemMemMarkSelDescAccessed(PVMCPU pVCpu, uint16_t uSel)
 /**
  * Calls a SSE assembly implementation taking three visible arguments.
  *
- * @param   a_pfnAImpl      Pointer to the assembly MMX routine.
+ * @param   a_pfnAImpl      Pointer to the assembly SSE routine.
  * @param   a0              The first extra argument.
  * @param   a1              The second extra argument.
  * @param   a2              The third extra argument.
@@ -11646,6 +12379,43 @@ IEM_STATIC VBOXSTRICTRC iemMemMarkSelDescAccessed(PVMCPU pVCpu, uint16_t uSel)
         a_pfnAImpl(&IEM_GET_CTX(pVCpu)->CTX_SUFF(pXState)->x87, (a0), (a1), (a2)); \
     } while (0)
 
+
+/** Declares implicit arguments for IEM_MC_CALL_AVX_AIMPL_2,
+ *  IEM_MC_CALL_AVX_AIMPL_3, IEM_MC_CALL_AVX_AIMPL_4, ... */
+#define IEM_MC_IMPLICIT_AVX_AIMPL_ARGS() \
+    IEM_MC_ARG_CONST(PX86XSAVEAREA, pXState, (pVCpu)->iem.s.CTX_SUFF(pCtx)->CTX_SUFF(pXState), 0)
+
+/**
+ * Calls a AVX assembly implementation taking two visible arguments.
+ *
+ * There is one implicit zero'th argument, a pointer to the extended state.
+ *
+ * @param   a_pfnAImpl      Pointer to the assembly AVX routine.
+ * @param   a1              The first extra argument.
+ * @param   a2              The second extra argument.
+ */
+#define IEM_MC_CALL_AVX_AIMPL_2(a_pfnAImpl, a1, a2) \
+    do { \
+        IEM_MC_PREPARE_AVX_USAGE(); \
+        a_pfnAImpl(pXState, (a1), (a2)); \
+    } while (0)
+
+/**
+ * Calls a AVX assembly implementation taking three visible arguments.
+ *
+ * There is one implicit zero'th argument, a pointer to the extended state.
+ *
+ * @param   a_pfnAImpl      Pointer to the assembly AVX routine.
+ * @param   a1              The first extra argument.
+ * @param   a2              The second extra argument.
+ * @param   a3              The third extra argument.
+ */
+#define IEM_MC_CALL_AVX_AIMPL_3(a_pfnAImpl, a1, a2, a3) \
+    do { \
+        IEM_MC_PREPARE_AVX_USAGE(); \
+        a_pfnAImpl(pXState, (a1), (a2), (a3)); \
+    } while (0)
+
 /** @note Not for IOPL or IF testing. */
 #define IEM_MC_IF_EFL_BIT_SET(a_fBit)                   if (IEM_GET_CTX(pVCpu)->eflags.u & (a_fBit)) {
 /** @note Not for IOPL or IF testing. */
@@ -11985,65 +12755,62 @@ IEM_STATIC VBOXSTRICTRC iemMemMarkSelDescAccessed(PVMCPU pVCpu, uint16_t uSel)
             return IEMOP_RAISE_INVALID_LOCK_PREFIX(); \
     } while (0)
 
-#define IEMOP_HLP_DECODED_NL_1(a_uDisOpNo, a_fIemOpFlags, a_uDisParam0, a_fDisOpType) \
-    do \
-    { \
-        if (RT_LIKELY(!(pVCpu->iem.s.fPrefixes & IEM_OP_PRF_LOCK))) \
-        { /* likely */ } \
-        else \
-        { \
-            NOREF(a_uDisOpNo); NOREF(a_fIemOpFlags); NOREF(a_uDisParam0); NOREF(a_fDisOpType); \
-            return IEMOP_RAISE_INVALID_LOCK_PREFIX(); \
-        } \
-    } while (0)
-#define IEMOP_HLP_DECODED_NL_2(a_uDisOpNo, a_fIemOpFlags, a_uDisParam0, a_uDisParam1, a_fDisOpType) \
+
+/**
+ * Done decoding VEX instruction, raise \#UD exception if any lock, rex, repz,
+ * repnz or size prefixes are present, or if in real or v8086 mode.
+ */
+#define IEMOP_HLP_DONE_VEX_DECODING() \
     do \
     { \
-        if (RT_LIKELY(!(pVCpu->iem.s.fPrefixes & IEM_OP_PRF_LOCK))) \
+        if (RT_LIKELY(   !(  pVCpu->iem.s.fPrefixes \
+                           & (IEM_OP_PRF_LOCK | IEM_OP_PRF_REPZ | IEM_OP_PRF_REPNZ | IEM_OP_PRF_SIZE_OP | IEM_OP_PRF_REX)) \
+                      && !IEM_IS_REAL_OR_V86_MODE(pVCpu) )) \
         { /* likely */ } \
         else \
-        { \
-            NOREF(a_uDisOpNo); NOREF(a_fIemOpFlags); NOREF(a_uDisParam0); NOREF(a_uDisParam1); NOREF(a_fDisOpType); \
             return IEMOP_RAISE_INVALID_LOCK_PREFIX(); \
-        } \
     } while (0)
 
 /**
- * Done decoding, raise \#UD exception if any lock, repz or repnz prefixes
- * are present.
+ * Done decoding VEX instruction, raise \#UD exception if any lock, rex, repz,
+ * repnz or size prefixes are present, or if in real or v8086 mode.
  */
-#define IEMOP_HLP_DONE_DECODING_NO_LOCK_REPZ_OR_REPNZ_PREFIXES() \
+#define IEMOP_HLP_DONE_VEX_DECODING_L0() \
     do \
     { \
-        if (RT_LIKELY(!(pVCpu->iem.s.fPrefixes & (IEM_OP_PRF_LOCK | IEM_OP_PRF_REPNZ | IEM_OP_PRF_REPZ)))) \
+        if (RT_LIKELY(   !(  pVCpu->iem.s.fPrefixes \
+                           & (IEM_OP_PRF_LOCK | IEM_OP_PRF_REPZ | IEM_OP_PRF_REPNZ | IEM_OP_PRF_SIZE_OP | IEM_OP_PRF_REX)) \
+                      && !IEM_IS_REAL_OR_V86_MODE(pVCpu) \
+                      && pVCpu->iem.s.uVexLength == 0)) \
         { /* likely */ } \
         else \
-            return IEMOP_RAISE_INVALID_OPCODE(); \
+            return IEMOP_RAISE_INVALID_LOCK_PREFIX(); \
     } while (0)
 
 
 /**
- * Done decoding VEX.
- * Raises \#UD exception if rex, rep, opsize or lock prefixes are present, or if
- * we're in real or v8086 mode.
+ * Done decoding VEX instruction, raise \#UD exception if any lock, rex, repz,
+ * repnz or size prefixes are present, or if the VEX.VVVV field doesn't indicate
+ * register 0, or if in real or v8086 mode.
  */
-#define IEMOP_HLP_DONE_VEX_DECODING() \
+#define IEMOP_HLP_DONE_VEX_DECODING_NO_VVVV() \
     do \
     { \
         if (RT_LIKELY(   !(  pVCpu->iem.s.fPrefixes \
-                           & (IEM_OP_PRF_LOCK | IEM_OP_PRF_SIZE_OP | IEM_OP_PRF_REPZ | IEM_OP_PRF_REPNZ | IEM_OP_PRF_REX)) \
+                           & (IEM_OP_PRF_LOCK | IEM_OP_PRF_REPZ | IEM_OP_PRF_REPNZ | IEM_OP_PRF_SIZE_OP | IEM_OP_PRF_REX)) \
+                      && !pVCpu->iem.s.uVex3rdReg \
                       && !IEM_IS_REAL_OR_V86_MODE(pVCpu) )) \
         { /* likely */ } \
         else \
-            return IEMOP_RAISE_INVALID_OPCODE(); \
+            return IEMOP_RAISE_INVALID_LOCK_PREFIX(); \
     } while (0)
 
 /**
- * Done decoding VEX, no V, no L.
+ * Done decoding VEX, no V, L=0.
  * Raises \#UD exception if rex, rep, opsize or lock prefixes are present, if
  * we're in real or v8086 mode, if VEX.V!=0xf, or if VEX.L!=0.
  */
-#define IEMOP_HLP_DONE_VEX_DECODING_L_ZERO_NO_VVV() \
+#define IEMOP_HLP_DONE_VEX_DECODING_L0_AND_NO_VVVV() \
     do \
     { \
         if (RT_LIKELY(   !(  pVCpu->iem.s.fPrefixes \
@@ -12056,6 +12823,43 @@ IEM_STATIC VBOXSTRICTRC iemMemMarkSelDescAccessed(PVMCPU pVCpu, uint16_t uSel)
             return IEMOP_RAISE_INVALID_OPCODE(); \
     } while (0)
 
+#define IEMOP_HLP_DECODED_NL_1(a_uDisOpNo, a_fIemOpFlags, a_uDisParam0, a_fDisOpType) \
+    do \
+    { \
+        if (RT_LIKELY(!(pVCpu->iem.s.fPrefixes & IEM_OP_PRF_LOCK))) \
+        { /* likely */ } \
+        else \
+        { \
+            NOREF(a_uDisOpNo); NOREF(a_fIemOpFlags); NOREF(a_uDisParam0); NOREF(a_fDisOpType); \
+            return IEMOP_RAISE_INVALID_LOCK_PREFIX(); \
+        } \
+    } while (0)
+#define IEMOP_HLP_DECODED_NL_2(a_uDisOpNo, a_fIemOpFlags, a_uDisParam0, a_uDisParam1, a_fDisOpType) \
+    do \
+    { \
+        if (RT_LIKELY(!(pVCpu->iem.s.fPrefixes & IEM_OP_PRF_LOCK))) \
+        { /* likely */ } \
+        else \
+        { \
+            NOREF(a_uDisOpNo); NOREF(a_fIemOpFlags); NOREF(a_uDisParam0); NOREF(a_uDisParam1); NOREF(a_fDisOpType); \
+            return IEMOP_RAISE_INVALID_LOCK_PREFIX(); \
+        } \
+    } while (0)
+
+/**
+ * Done decoding, raise \#UD exception if any lock, repz or repnz prefixes
+ * are present.
+ */
+#define IEMOP_HLP_DONE_DECODING_NO_LOCK_REPZ_OR_REPNZ_PREFIXES() \
+    do \
+    { \
+        if (RT_LIKELY(!(pVCpu->iem.s.fPrefixes & (IEM_OP_PRF_LOCK | IEM_OP_PRF_REPNZ | IEM_OP_PRF_REPZ)))) \
+        { /* likely */ } \
+        else \
+            return IEMOP_RAISE_INVALID_OPCODE(); \
+    } while (0)
+
+
 #ifdef VBOX_WITH_NESTED_HWVIRT
 /** Check and handles SVM nested-guest control & instruction intercept. */
 # define IEMOP_HLP_SVM_CTRL_INTERCEPT(a_pVCpu, a_Intercept, a_uExitCode, a_uExitInfo1, a_uExitInfo2) \
@@ -12073,11 +12877,10 @@ IEM_STATIC VBOXSTRICTRC iemMemMarkSelDescAccessed(PVMCPU pVCpu, uint16_t uSel)
             IEM_RETURN_SVM_NST_GST_VMEXIT(a_pVCpu, SVM_EXIT_READ_CR0 + (a_uCr), a_uExitInfo1, a_uExitInfo2); \
     } while (0)
 
-#else
+#else  /* !VBOX_WITH_NESTED_HWVIRT */
 # define IEMOP_HLP_SVM_CTRL_INTERCEPT(a_pVCpu, a_Intercept, a_uExitCode, a_uExitInfo1, a_uExitInfo2)    do { } while (0)
 # define IEMOP_HLP_SVM_READ_CR_INTERCEPT(a_pVCpu, a_uCr, a_uExitInfo1, a_uExitInfo2)                    do { } while (0)
-
-#endif /* VBOX_WITH_NESTED_HWVIRT */
+#endif /* !VBOX_WITH_NESTED_HWVIRT */
 
 
 /**
@@ -15224,6 +16027,8 @@ VMM_INT_DECL(VBOXSTRICTRC) IEMExecDecodedXsetbv(PVMCPU pVCpu, uint8_t cbInstr)
  *                          event, optional.
  * @param   puCr2           Where to store the CR2 associated with the event,
  *                          optional.
+ * @remarks The caller should check the flags to determine if the error code and
+ *          CR2 are valid for the event.
  */
 VMM_INT_DECL(bool) IEMGetCurrentXcpt(PVMCPU pVCpu, uint8_t *puVector, uint32_t *pfFlags, uint32_t *puErr, uint64_t *puCr2)
 {
@@ -15234,7 +16039,6 @@ VMM_INT_DECL(bool) IEMGetCurrentXcpt(PVMCPU pVCpu, uint8_t *puVector, uint32_t *
             *puVector = pVCpu->iem.s.uCurXcpt;
         if (pfFlags)
             *pfFlags = pVCpu->iem.s.fCurXcpt;
-        /* The caller should check the flags to determine if the error code & CR2 are valid for the event. */
         if (puErr)
             *puErr = pVCpu->iem.s.uCurXcptErr;
         if (puCr2)
diff --git a/src/VBox/VMM/VMMAll/IEMAllAImplC.cpp b/src/VBox/VMM/VMMAll/IEMAllAImplC.cpp
index c086364..77bae96 100644
--- a/src/VBox/VMM/VMMAll/IEMAllAImplC.cpp
+++ b/src/VBox/VMM/VMMAll/IEMAllAImplC.cpp
@@ -1380,6 +1380,46 @@ IEM_DECL_IMPL_DEF(void, iemAImpl_movsldup,(PCX86FXSTATE pFpuState, PRTUINT128U p
     puDst->au32[3] = puSrc->au32[2];
 }
 
+#ifdef IEM_WITH_VEX
+
+IEM_DECL_IMPL_DEF(void, iemAImpl_vmovsldup_256_rr,(PX86XSAVEAREA pXState, uint8_t iYRegDst, uint8_t iYRegSrc))
+{
+    pXState->x87.aXMM[iYRegDst].au32[0] = pXState->x87.aXMM[iYRegSrc].au32[0];
+    pXState->x87.aXMM[iYRegDst].au32[1] = pXState->x87.aXMM[iYRegSrc].au32[0];
+    pXState->x87.aXMM[iYRegDst].au32[2] = pXState->x87.aXMM[iYRegSrc].au32[2];
+    pXState->x87.aXMM[iYRegDst].au32[3] = pXState->x87.aXMM[iYRegSrc].au32[2];
+    pXState->u.YmmHi.aYmmHi[iYRegDst].au32[0] = pXState->u.YmmHi.aYmmHi[iYRegSrc].au32[0];
+    pXState->u.YmmHi.aYmmHi[iYRegDst].au32[1] = pXState->u.YmmHi.aYmmHi[iYRegSrc].au32[0];
+    pXState->u.YmmHi.aYmmHi[iYRegDst].au32[2] = pXState->u.YmmHi.aYmmHi[iYRegSrc].au32[2];
+    pXState->u.YmmHi.aYmmHi[iYRegDst].au32[3] = pXState->u.YmmHi.aYmmHi[iYRegSrc].au32[2];
+}
+
+
+IEM_DECL_IMPL_DEF(void, iemAImpl_vmovsldup_256_rm,(PX86XSAVEAREA pXState, uint8_t iYRegDst, PCRTUINT256U pSrc))
+{
+    pXState->x87.aXMM[iYRegDst].au32[0]       = pSrc->au32[0];
+    pXState->x87.aXMM[iYRegDst].au32[1]       = pSrc->au32[0];
+    pXState->x87.aXMM[iYRegDst].au32[2]       = pSrc->au32[2];
+    pXState->x87.aXMM[iYRegDst].au32[3]       = pSrc->au32[2];
+    pXState->u.YmmHi.aYmmHi[iYRegDst].au32[0] = pSrc->au32[4];
+    pXState->u.YmmHi.aYmmHi[iYRegDst].au32[1] = pSrc->au32[4];
+    pXState->u.YmmHi.aYmmHi[iYRegDst].au32[2] = pSrc->au32[6];
+    pXState->u.YmmHi.aYmmHi[iYRegDst].au32[3] = pSrc->au32[6];
+}
+
+#endif /* IEM_WITH_VEX */
+
+
+IEM_DECL_IMPL_DEF(void, iemAImpl_movshdup,(PCX86FXSTATE pFpuState, PRTUINT128U puDst, PCRTUINT128U puSrc))
+{
+    RT_NOREF(pFpuState);
+    puDst->au32[0] = puSrc->au32[1];
+    puDst->au32[1] = puSrc->au32[1];
+    puDst->au32[2] = puSrc->au32[3];
+    puDst->au32[3] = puSrc->au32[3];
+}
+
+
 IEM_DECL_IMPL_DEF(void, iemAImpl_movddup,(PCX86FXSTATE pFpuState, PRTUINT128U puDst, uint64_t uSrc))
 {
     RT_NOREF(pFpuState);
@@ -1387,3 +1427,23 @@ IEM_DECL_IMPL_DEF(void, iemAImpl_movddup,(PCX86FXSTATE pFpuState, PRTUINT128U pu
     puDst->au64[1] = uSrc;
 }
 
+#ifdef IEM_WITH_VEX
+
+IEM_DECL_IMPL_DEF(void, iemAImpl_vmovddup_256_rr,(PX86XSAVEAREA pXState, uint8_t iYRegDst, uint8_t iYRegSrc))
+{
+    pXState->x87.aXMM[iYRegDst].au64[0] = pXState->x87.aXMM[iYRegSrc].au64[0];
+    pXState->x87.aXMM[iYRegDst].au64[1] = pXState->x87.aXMM[iYRegSrc].au64[0];
+    pXState->u.YmmHi.aYmmHi[iYRegDst].au64[0] = pXState->u.YmmHi.aYmmHi[iYRegSrc].au64[0];
+    pXState->u.YmmHi.aYmmHi[iYRegDst].au64[1] = pXState->u.YmmHi.aYmmHi[iYRegSrc].au64[0];
+}
+
+IEM_DECL_IMPL_DEF(void, iemAImpl_vmovddup_256_rm,(PX86XSAVEAREA pXState, uint8_t iYRegDst, PCRTUINT256U pSrc))
+{
+    pXState->x87.aXMM[iYRegDst].au64[0]       = pSrc->au64[0];
+    pXState->x87.aXMM[iYRegDst].au64[1]       = pSrc->au64[0];
+    pXState->u.YmmHi.aYmmHi[iYRegDst].au64[0] = pSrc->au64[2];
+    pXState->u.YmmHi.aYmmHi[iYRegDst].au64[1] = pSrc->au64[2];
+}
+
+#endif /* IEM_WITH_VEX */
+
diff --git a/src/VBox/VMM/VMMAll/IEMAllCImpl.cpp.h b/src/VBox/VMM/VMMAll/IEMAllCImpl.cpp.h
index e771ec7..41f13a5 100644
--- a/src/VBox/VMM/VMMAll/IEMAllCImpl.cpp.h
+++ b/src/VBox/VMM/VMMAll/IEMAllCImpl.cpp.h
@@ -2861,15 +2861,15 @@ IEM_CIMPL_DEF_1(iemCImpl_leave, IEMMODE, enmEffOpSize)
  * Implements int3 and int XX.
  *
  * @param   u8Int       The interrupt vector number.
- * @param   fIsBpInstr  Is it the breakpoint instruction.
+ * @param   enmInt      The int instruction type.
  */
-IEM_CIMPL_DEF_2(iemCImpl_int, uint8_t, u8Int, bool, fIsBpInstr)
+IEM_CIMPL_DEF_2(iemCImpl_int, uint8_t, u8Int, IEMINT, enmInt)
 {
     Assert(pVCpu->iem.s.cXcptRecursions == 0);
     return iemRaiseXcptOrInt(pVCpu,
                              cbInstr,
                              u8Int,
-                             (fIsBpInstr ? IEM_XCPT_FLAGS_BP_INSTR : 0) | IEM_XCPT_FLAGS_T_SOFT_INT,
+                             IEM_XCPT_FLAGS_T_SOFT_INT | enmInt,
                              0,
                              0);
 }
@@ -5778,8 +5778,8 @@ IEM_CIMPL_DEF_0(iemCImpl_rdtsc)
      * Do the job.
      */
     uint64_t uTicks = TMCpuTickGet(pVCpu);
-    pCtx->rax = (uint32_t)uTicks;
-    pCtx->rdx = uTicks >> 32;
+    pCtx->rax = RT_LO_U32(uTicks);
+    pCtx->rdx = RT_HI_U32(uTicks);
 #ifdef IEM_VERIFICATION_MODE_FULL
     pVCpu->iem.s.fIgnoreRaxRdx = true;
 #endif
@@ -5826,8 +5826,8 @@ IEM_CIMPL_DEF_0(iemCImpl_rdtscp)
         pCtx->rcx &= UINT32_C(0xffffffff);
 
         uint64_t uTicks = TMCpuTickGet(pVCpu);
-        pCtx->rax = (uint32_t)uTicks;
-        pCtx->rdx = uTicks >> 32;
+        pCtx->rax = RT_LO_U32(uTicks);
+        pCtx->rdx = RT_HI_U32(uTicks);
 #ifdef IEM_VERIFICATION_MODE_FULL
         pVCpu->iem.s.fIgnoreRaxRdx = true;
 #endif
diff --git a/src/VBox/VMM/VMMAll/IEMAllInstructions.cpp.h b/src/VBox/VMM/VMMAll/IEMAllInstructions.cpp.h
index c93edfe..50a36ea 100644
--- a/src/VBox/VMM/VMMAll/IEMAllInstructions.cpp.h
+++ b/src/VBox/VMM/VMMAll/IEMAllInstructions.cpp.h
@@ -548,6 +548,28 @@ FNIEMOPRM_DEF(iemOp_InvalidWithRM)
 }
 
 
+/** Invalid with RM byte where intel decodes any additional address encoding
+ *  bytes. */
+FNIEMOPRM_DEF(iemOp_InvalidWithRMNeedDecode)
+{
+    IEMOP_MNEMONIC(InvalidWithRMNeedDecode, "InvalidWithRMNeedDecode");
+    if (pVCpu->iem.s.enmCpuVendor == CPUMCPUVENDOR_INTEL)
+    {
+#ifndef TST_IEM_CHECK_MC
+        if ((bRm & X86_MODRM_MOD_MASK) != (3 << X86_MODRM_MOD_SHIFT))
+        {
+            RTGCPTR      GCPtrEff;
+            VBOXSTRICTRC rcStrict = iemOpHlpCalcRmEffAddr(pVCpu, bRm, 0, &GCPtrEff);
+            if (rcStrict != VINF_SUCCESS)
+                return rcStrict;
+        }
+#endif
+    }
+    IEMOP_HLP_DONE_DECODING();
+    return IEMOP_RAISE_INVALID_OPCODE();
+}
+
+
 /** Invalid with RM byte where both AMD and Intel decodes any additional
  *  address encoding bytes. */
 FNIEMOPRM_DEF(iemOp_InvalidWithRMAllNeeded)
diff --git a/src/VBox/VMM/VMMAll/IEMAllInstructionsOneByte.cpp.h b/src/VBox/VMM/VMMAll/IEMAllInstructionsOneByte.cpp.h
index 8c0fe32..fa0741e 100644
--- a/src/VBox/VMM/VMMAll/IEMAllInstructionsOneByte.cpp.h
+++ b/src/VBox/VMM/VMMAll/IEMAllInstructionsOneByte.cpp.h
@@ -56,7 +56,7 @@ extern const PFNIEMOP g_apfnOneByteMap[256]; /* not static since we need to forw
  * @opmaps      one
  * @openc       ModR/M
  * @opflmodify  cf,pf,af,zf,sf,of
- * @ophints     harmless ignores_op_size
+ * @ophints     harmless ignores_op_sizes
  * @opstats     add_Eb_Gb
  * @opgroup     og_gen_arith_bin
  * @optest              op1=1   op2=1   -> op1=2   efl&|=nc,pe,na,nz,pl,nv
@@ -66,7 +66,7 @@ extern const PFNIEMOP g_apfnOneByteMap[256]; /* not static since we need to forw
  */
 FNIEMOP_DEF(iemOp_add_Eb_Gb)
 {
-    IEMOP_MNEMONIC2(MR, ADD, add, Eb, Gb, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZE | IEMOPHINT_LOCK_ALLOWED);
+    IEMOP_MNEMONIC2(MR, ADD, add, Eb, Gb, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZES | IEMOPHINT_LOCK_ALLOWED);
     return FNIEMOP_CALL_1(iemOpHlpBinaryOperator_rm_r8, &g_iemAImpl_add);
 }
 
@@ -95,7 +95,7 @@ FNIEMOP_DEF(iemOp_add_Ev_Gv)
  */
 FNIEMOP_DEF(iemOp_add_Gb_Eb)
 {
-    IEMOP_MNEMONIC2(RM, ADD, add, Gb, Eb, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZE);
+    IEMOP_MNEMONIC2(RM, ADD, add, Gb, Eb, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZES);
     return FNIEMOP_CALL_1(iemOpHlpBinaryOperator_r8_rm, &g_iemAImpl_add);
 }
 
@@ -121,7 +121,7 @@ FNIEMOP_DEF(iemOp_add_Gv_Ev)
  */
 FNIEMOP_DEF(iemOp_add_Al_Ib)
 {
-    IEMOP_MNEMONIC2(FIXED, ADD, add, AL, Ib, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZE);
+    IEMOP_MNEMONIC2(FIXED, ADD, add, AL, Ib, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZES);
     return FNIEMOP_CALL_1(iemOpHlpBinaryOperator_AL_Ib, &g_iemAImpl_add);
 }
 
@@ -180,7 +180,7 @@ FNIEMOP_DEF(iemOp_pop_ES)
  */
 FNIEMOP_DEF(iemOp_or_Eb_Gb)
 {
-    IEMOP_MNEMONIC2(MR, OR, or, Eb, Gb, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZE | IEMOPHINT_LOCK_ALLOWED);
+    IEMOP_MNEMONIC2(MR, OR, or, Eb, Gb, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZES | IEMOPHINT_LOCK_ALLOWED);
     IEMOP_VERIFICATION_UNDEFINED_EFLAGS(X86_EFL_AF);
     return FNIEMOP_CALL_1(iemOpHlpBinaryOperator_rm_r8, &g_iemAImpl_or);
 }
@@ -217,7 +217,7 @@ FNIEMOP_DEF(iemOp_or_Ev_Gv)
  */
 FNIEMOP_DEF(iemOp_or_Gb_Eb)
 {
-    IEMOP_MNEMONIC2(RM, OR, or, Gb, Eb, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZE | IEMOPHINT_LOCK_ALLOWED);
+    IEMOP_MNEMONIC2(RM, OR, or, Gb, Eb, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZES | IEMOPHINT_LOCK_ALLOWED);
     IEMOP_VERIFICATION_UNDEFINED_EFLAGS(X86_EFL_AF);
     return FNIEMOP_CALL_1(iemOpHlpBinaryOperator_r8_rm, &g_iemAImpl_or);
 }
@@ -249,7 +249,7 @@ FNIEMOP_DEF(iemOp_or_Gv_Ev)
  */
 FNIEMOP_DEF(iemOp_or_Al_Ib)
 {
-    IEMOP_MNEMONIC2(FIXED, OR, or, AL, Ib, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZE);
+    IEMOP_MNEMONIC2(FIXED, OR, or, AL, Ib, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZES);
     IEMOP_VERIFICATION_UNDEFINED_EFLAGS(X86_EFL_AF);
     return FNIEMOP_CALL_1(iemOpHlpBinaryOperator_AL_Ib, &g_iemAImpl_or);
 }
@@ -344,7 +344,7 @@ FNIEMOP_DEF(iemOp_2byteEscape)
  */
 FNIEMOP_DEF(iemOp_adc_Eb_Gb)
 {
-    IEMOP_MNEMONIC2(MR, ADC, adc, Eb, Gb, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZE | IEMOPHINT_LOCK_ALLOWED);
+    IEMOP_MNEMONIC2(MR, ADC, adc, Eb, Gb, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZES | IEMOPHINT_LOCK_ALLOWED);
     return FNIEMOP_CALL_1(iemOpHlpBinaryOperator_rm_r8, &g_iemAImpl_adc);
 }
 
@@ -376,7 +376,7 @@ FNIEMOP_DEF(iemOp_adc_Ev_Gv)
  */
 FNIEMOP_DEF(iemOp_adc_Gb_Eb)
 {
-    IEMOP_MNEMONIC2(RM, ADC, adc, Gb, Eb, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZE);
+    IEMOP_MNEMONIC2(RM, ADC, adc, Gb, Eb, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZES);
     return FNIEMOP_CALL_1(iemOpHlpBinaryOperator_r8_rm, &g_iemAImpl_adc);
 }
 
@@ -404,7 +404,7 @@ FNIEMOP_DEF(iemOp_adc_Gv_Ev)
  */
 FNIEMOP_DEF(iemOp_adc_Al_Ib)
 {
-    IEMOP_MNEMONIC2(FIXED, ADC, adc, AL, Ib, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZE);
+    IEMOP_MNEMONIC2(FIXED, ADC, adc, AL, Ib, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZES);
     return FNIEMOP_CALL_1(iemOpHlpBinaryOperator_AL_Ib, &g_iemAImpl_adc);
 }
 
@@ -457,7 +457,7 @@ FNIEMOP_DEF(iemOp_pop_SS)
  */
 FNIEMOP_DEF(iemOp_sbb_Eb_Gb)
 {
-    IEMOP_MNEMONIC2(MR, SBB, sbb, Eb, Gb, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZE | IEMOPHINT_LOCK_ALLOWED);
+    IEMOP_MNEMONIC2(MR, SBB, sbb, Eb, Gb, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZES | IEMOPHINT_LOCK_ALLOWED);
     return FNIEMOP_CALL_1(iemOpHlpBinaryOperator_rm_r8, &g_iemAImpl_sbb);
 }
 
@@ -483,7 +483,7 @@ FNIEMOP_DEF(iemOp_sbb_Ev_Gv)
  */
 FNIEMOP_DEF(iemOp_sbb_Gb_Eb)
 {
-    IEMOP_MNEMONIC2(RM, SBB, sbb, Gb, Eb, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZE);
+    IEMOP_MNEMONIC2(RM, SBB, sbb, Gb, Eb, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZES);
     return FNIEMOP_CALL_1(iemOpHlpBinaryOperator_r8_rm, &g_iemAImpl_sbb);
 }
 
@@ -509,7 +509,7 @@ FNIEMOP_DEF(iemOp_sbb_Gv_Ev)
  */
 FNIEMOP_DEF(iemOp_sbb_Al_Ib)
 {
-    IEMOP_MNEMONIC2(FIXED, SBB, sbb, AL, Ib, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZE);
+    IEMOP_MNEMONIC2(FIXED, SBB, sbb, AL, Ib, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZES);
     return FNIEMOP_CALL_1(iemOpHlpBinaryOperator_AL_Ib, &g_iemAImpl_sbb);
 }
 
@@ -561,7 +561,7 @@ FNIEMOP_DEF(iemOp_pop_DS)
  */
 FNIEMOP_DEF(iemOp_and_Eb_Gb)
 {
-    IEMOP_MNEMONIC2(MR, AND, and, Eb, Gb, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZE | IEMOPHINT_LOCK_ALLOWED);
+    IEMOP_MNEMONIC2(MR, AND, and, Eb, Gb, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZES | IEMOPHINT_LOCK_ALLOWED);
     IEMOP_VERIFICATION_UNDEFINED_EFLAGS(X86_EFL_AF);
     return FNIEMOP_CALL_1(iemOpHlpBinaryOperator_rm_r8, &g_iemAImpl_and);
 }
@@ -591,7 +591,7 @@ FNIEMOP_DEF(iemOp_and_Ev_Gv)
  */
 FNIEMOP_DEF(iemOp_and_Gb_Eb)
 {
-    IEMOP_MNEMONIC2(RM, AND, and, Gb, Eb, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZE);
+    IEMOP_MNEMONIC2(RM, AND, and, Gb, Eb, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZES);
     IEMOP_VERIFICATION_UNDEFINED_EFLAGS(X86_EFL_AF);
     return FNIEMOP_CALL_1(iemOpHlpBinaryOperator_r8_rm, &g_iemAImpl_and);
 }
@@ -685,7 +685,7 @@ FNIEMOP_DEF(iemOp_daa)
  */
 FNIEMOP_DEF(iemOp_sub_Eb_Gb)
 {
-    IEMOP_MNEMONIC2(MR, SUB, sub, Eb, Gb, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZE | IEMOPHINT_LOCK_ALLOWED);
+    IEMOP_MNEMONIC2(MR, SUB, sub, Eb, Gb, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZES | IEMOPHINT_LOCK_ALLOWED);
     return FNIEMOP_CALL_1(iemOpHlpBinaryOperator_rm_r8, &g_iemAImpl_sub);
 }
 
@@ -709,7 +709,7 @@ FNIEMOP_DEF(iemOp_sub_Ev_Gv)
  */
 FNIEMOP_DEF(iemOp_sub_Gb_Eb)
 {
-    IEMOP_MNEMONIC2(RM, SUB, sub, Gb, Eb, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZE);
+    IEMOP_MNEMONIC2(RM, SUB, sub, Gb, Eb, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZES);
     return FNIEMOP_CALL_1(iemOpHlpBinaryOperator_r8_rm, &g_iemAImpl_sub);
 }
 
@@ -733,7 +733,7 @@ FNIEMOP_DEF(iemOp_sub_Gv_Ev)
  */
 FNIEMOP_DEF(iemOp_sub_Al_Ib)
 {
-    IEMOP_MNEMONIC2(FIXED, SUB, sub, AL, Ib, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZE);
+    IEMOP_MNEMONIC2(FIXED, SUB, sub, AL, Ib, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZES);
     return FNIEMOP_CALL_1(iemOpHlpBinaryOperator_AL_Ib, &g_iemAImpl_sub);
 }
 
@@ -795,7 +795,7 @@ FNIEMOP_DEF(iemOp_das)
  */
 FNIEMOP_DEF(iemOp_xor_Eb_Gb)
 {
-    IEMOP_MNEMONIC2(MR, XOR, xor, Eb, Gb, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZE | IEMOPHINT_LOCK_ALLOWED);
+    IEMOP_MNEMONIC2(MR, XOR, xor, Eb, Gb, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZES | IEMOPHINT_LOCK_ALLOWED);
     IEMOP_VERIFICATION_UNDEFINED_EFLAGS(X86_EFL_AF);
     return FNIEMOP_CALL_1(iemOpHlpBinaryOperator_rm_r8, &g_iemAImpl_xor);
 }
@@ -825,7 +825,7 @@ FNIEMOP_DEF(iemOp_xor_Ev_Gv)
  */
 FNIEMOP_DEF(iemOp_xor_Gb_Eb)
 {
-    IEMOP_MNEMONIC2(RM, XOR, xor, Gb, Eb, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZE);
+    IEMOP_MNEMONIC2(RM, XOR, xor, Gb, Eb, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZES);
     IEMOP_VERIFICATION_UNDEFINED_EFLAGS(X86_EFL_AF);
     return FNIEMOP_CALL_1(iemOpHlpBinaryOperator_r8_rm, &g_iemAImpl_xor);
 }
@@ -855,7 +855,7 @@ FNIEMOP_DEF(iemOp_xor_Gv_Ev)
  */
 FNIEMOP_DEF(iemOp_xor_Al_Ib)
 {
-    IEMOP_MNEMONIC2(FIXED, XOR, xor, AL, Ib, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZE);
+    IEMOP_MNEMONIC2(FIXED, XOR, xor, AL, Ib, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZES);
     IEMOP_VERIFICATION_UNDEFINED_EFLAGS(X86_EFL_AF);
     return FNIEMOP_CALL_1(iemOpHlpBinaryOperator_AL_Ib, &g_iemAImpl_xor);
 }
@@ -870,7 +870,7 @@ FNIEMOP_DEF(iemOp_xor_Al_Ib)
  */
 FNIEMOP_DEF(iemOp_xor_eAX_Iz)
 {
-    IEMOP_MNEMONIC2(FIXED, XOR, xor, rAX, Iz, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZE);
+    IEMOP_MNEMONIC2(FIXED, XOR, xor, rAX, Iz, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZES);
     IEMOP_VERIFICATION_UNDEFINED_EFLAGS(X86_EFL_AF);
     return FNIEMOP_CALL_1(iemOpHlpBinaryOperator_rAX_Iz, &g_iemAImpl_xor);
 }
@@ -1848,7 +1848,7 @@ FNIEMOP_DEF(iemOp_popa__mvex)
 /**
  * @opcode      0x62
  * @opmnemonic  bound
- * @op1         Gv
+ * @op1         Gv_RO
  * @op2         Ma
  * @opmincpu    80186
  * @ophints     harmless invalid_64
@@ -1910,7 +1910,7 @@ FNIEMOP_DEF(iemOp_bound_Gv_Ma__evex)
     uint8_t bRm;
     if (pVCpu->iem.s.enmCpuMode != IEMMODE_64BIT)
     {
-        IEMOP_MNEMONIC2(RM_MEM, BOUND, bound, Gv, Ma, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZE);
+        IEMOP_MNEMONIC2(RM_MEM, BOUND, bound, Gv_RO, Ma, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZES);
         IEMOP_HLP_MIN_186();
         IEM_OPCODE_GET_NEXT_U8(&bRm);
         if ((bRm & X86_MODRM_MOD_MASK) != (3 << X86_MODRM_MOD_SHIFT))
@@ -4351,11 +4351,11 @@ FNIEMOP_DEF(iemOp_Grp1A__xop)
             == 0)
         {
             pVCpu->iem.s.fPrefixes |= IEM_OP_PRF_XOP;
-            if (bXop2 & 0x80 /* XOP.W */)
+            if ((bXop2 & 0x80 /* XOP.W */) && pVCpu->iem.s.enmCpuMode == IEMMODE_64BIT)
                 pVCpu->iem.s.fPrefixes |= IEM_OP_PRF_SIZE_REX_W;
-            pVCpu->iem.s.uRexReg    = ~bRm >> (7 - 3);
-            pVCpu->iem.s.uRexIndex  = ~bRm >> (6 - 3);
-            pVCpu->iem.s.uRexB      = ~bRm >> (5 - 3);
+            pVCpu->iem.s.uRexReg    = (~bRm >> (7 - 3)) & 0x8;
+            pVCpu->iem.s.uRexIndex  = (~bRm >> (6 - 3)) & 0x8;
+            pVCpu->iem.s.uRexB      = (~bRm >> (5 - 3)) & 0x8;
             pVCpu->iem.s.uVex3rdReg = (~bXop2 >> 3) & 0xf;
             pVCpu->iem.s.uVexLength = (bXop2 >> 2) & 1;
             pVCpu->iem.s.idxPrefix  = bXop2 & 0x3;
@@ -6221,16 +6221,16 @@ FNIEMOP_DEF(iemOp_les_Gv_Mp__vex3)
         IEMOP_MNEMONIC(vex3_prefix, "vex3");
         if (IEM_GET_GUEST_CPU_FEATURES(pVCpu)->fAvx)
         {
-            /* Note! The real mode, v8086 mode and invalid prefix checks are
-                     done once the instruction is fully decoded. */
+            /* Note! The real mode, v8086 mode and invalid prefix checks are done once
+                     the instruction is fully decoded.  Even when XCR0=3 and CR4.OSXSAVE=0. */
             uint8_t bVex2;   IEM_OPCODE_GET_NEXT_U8(&bVex2);
             uint8_t bOpcode; IEM_OPCODE_GET_NEXT_U8(&bOpcode);
             pVCpu->iem.s.fPrefixes |= IEM_OP_PRF_VEX;
-            if (bVex2 & 0x80 /* VEX.W */)
+            if ((bVex2 & 0x80 /* VEX.W */) && pVCpu->iem.s.enmCpuMode == IEMMODE_64BIT)
                 pVCpu->iem.s.fPrefixes |= IEM_OP_PRF_SIZE_REX_W;
-            pVCpu->iem.s.uRexReg    = ~bRm >> (7 - 3);
-            pVCpu->iem.s.uRexIndex  = ~bRm >> (6 - 3);
-            pVCpu->iem.s.uRexB      = ~bRm >> (5 - 3);
+            pVCpu->iem.s.uRexReg    = (~bRm >> (7 - 3)) & 0x8;
+            pVCpu->iem.s.uRexIndex  = (~bRm >> (6 - 3)) & 0x8;
+            pVCpu->iem.s.uRexB      = (~bRm >> (5 - 3)) & 0x8;
             pVCpu->iem.s.uVex3rdReg = (~bVex2 >> 3) & 0xf;
             pVCpu->iem.s.uVexLength = (bVex2 >> 2) & 1;
             pVCpu->iem.s.idxPrefix  = bVex2 & 0x3;
@@ -6293,11 +6293,11 @@ FNIEMOP_DEF(iemOp_lds_Gv_Mp__vex2)
         IEMOP_MNEMONIC(vex2_prefix, "vex2");
         if (IEM_GET_GUEST_CPU_FEATURES(pVCpu)->fAvx)
         {
-            /* Note! The real mode, v8086 mode and invalid prefix checks are
-                     done once the instruction is fully decoded. */
+            /* Note! The real mode, v8086 mode and invalid prefix checks are done once
+                     the instruction is fully decoded.  Even when XCR0=3 and CR4.OSXSAVE=0. */
             uint8_t bOpcode; IEM_OPCODE_GET_NEXT_U8(&bOpcode);
             pVCpu->iem.s.fPrefixes |= IEM_OP_PRF_VEX;
-            pVCpu->iem.s.uRexReg    = ~bRm >> (7 - 3);
+            pVCpu->iem.s.uRexReg    = (~bRm >> (7 - 3)) & 0x8;
             pVCpu->iem.s.uVex3rdReg = (~bRm >> 3) & 0xf;
             pVCpu->iem.s.uVexLength = (bRm >> 2) & 1;
             pVCpu->iem.s.idxPrefix  = bRm & 0x3;
@@ -6506,7 +6506,7 @@ FNIEMOP_DEF(iemOp_retf)
 FNIEMOP_DEF(iemOp_int3)
 {
     IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
-    return IEM_MC_DEFER_TO_CIMPL_2(iemCImpl_int, X86_XCPT_BP, true /*fIsBpInstr*/);
+    return IEM_MC_DEFER_TO_CIMPL_2(iemCImpl_int, X86_XCPT_BP, IEMINT_INT3);
 }
 
 
@@ -6517,7 +6517,7 @@ FNIEMOP_DEF(iemOp_int_Ib)
 {
     uint8_t u8Int; IEM_OPCODE_GET_NEXT_U8(&u8Int);
     IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
-    return IEM_MC_DEFER_TO_CIMPL_2(iemCImpl_int, u8Int, false /*fIsBpInstr*/);
+    return IEM_MC_DEFER_TO_CIMPL_2(iemCImpl_int, u8Int, IEMINT_INTN);
 }
 
 
@@ -6530,9 +6530,9 @@ FNIEMOP_DEF(iemOp_into)
     IEMOP_HLP_NO_64BIT();
 
     IEM_MC_BEGIN(2, 0);
-    IEM_MC_ARG_CONST(uint8_t,   u8Int,      /*=*/ X86_XCPT_OF, 0);
-    IEM_MC_ARG_CONST(bool,      fIsBpInstr, /*=*/ false, 1);
-    IEM_MC_CALL_CIMPL_2(iemCImpl_int, u8Int, fIsBpInstr);
+    IEM_MC_ARG_CONST(uint8_t,   u8Int,  /*=*/ X86_XCPT_OF, 0);
+    IEM_MC_ARG_CONST(IEMINT,    enmInt, /*=*/ IEMINT_INTO, 1);
+    IEM_MC_CALL_CIMPL_2(iemCImpl_int, u8Int, enmInt);
     IEM_MC_END();
     return VINF_SUCCESS;
 }
@@ -10589,8 +10589,7 @@ FNIEMOP_DEF(iemOp_int1)
     IEMOP_MNEMONIC(int1, "int1"); /* icebp */
     IEMOP_HLP_MIN_386(); /** @todo does not generate #UD on 286, or so they say... */
     /** @todo testcase! */
-    IEMOP_HLP_SVM_CTRL_INTERCEPT(pVCpu, SVM_CTRL_INTERCEPT_ICEBP, SVM_EXIT_ICEBP, 0, 0);
-    return IEM_MC_DEFER_TO_CIMPL_2(iemCImpl_int, X86_XCPT_DB, false /*fIsBpInstr*/);
+    return IEM_MC_DEFER_TO_CIMPL_2(iemCImpl_int, X86_XCPT_DB, IEMINT_INT1);
 }
 
 
diff --git a/src/VBox/VMM/VMMAll/IEMAllInstructionsPython.py b/src/VBox/VMM/VMMAll/IEMAllInstructionsPython.py
index 6908587..03e1f6d 100755
--- a/src/VBox/VMM/VMMAll/IEMAllInstructionsPython.py
+++ b/src/VBox/VMM/VMMAll/IEMAllInstructionsPython.py
@@ -31,7 +31,7 @@ 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: 115000 $"
+__version__ = "$Revision: 115694 $"
 
 # pylint: disable=anomalous-backslash-in-string
 
@@ -209,78 +209,131 @@ g_kdOpLocations = {
 ## Note! See the A.2.1 in SDM vol 2 for the type names.
 g_kdOpTypes = {
     # Fixed addresses
-    'Ap':   ( 'IDX_ParseImmAddrF',  'imm',    '%Ap',  'Ap',      ),
+    'Ap':           ( 'IDX_ParseImmAddrF',  'imm',    '%Ap',  'Ap',      ),
 
     # ModR/M.rm
-    'Eb':   ( 'IDX_UseModRM',       'rm',     '%Eb',  'Eb',      ),
-    'Ew':   ( 'IDX_UseModRM',       'rm',     '%Ew',  'Ew',      ),
-    'Ev':   ( 'IDX_UseModRM',       'rm',     '%Ev',  'Ev',      ),
-    'Wss':  ( 'IDX_UseModRM',       'rm',     '%Wss', 'Wss',     ),
-    'Wsd':  ( 'IDX_UseModRM',       'rm',     '%Wsd', 'Wsd',     ),
-    'Wps':  ( 'IDX_UseModRM',       'rm',     '%Wps', 'Wps',     ),
-    'Wpd':  ( 'IDX_UseModRM',       'rm',     '%Wpd', 'Wpd',     ),
-    'Wdq':  ( 'IDX_UseModRM',       'rm',     '%Wdq', 'Wdq',     ),
-    'WqZxReg': ( 'IDX_UseModRM',    'rm',     '%Wq',  'Wq',      ),
+    'Eb':           ( 'IDX_UseModRM',       'rm',     '%Eb',  'Eb',      ),
+    'Ed':           ( 'IDX_UseModRM',       'rm',     '%Ed',  'Ed',      ),
+    'Ed_WO':        ( 'IDX_UseModRM',       'rm',     '%Ed',  'Ed',      ),
+    'Eq':           ( 'IDX_UseModRM',       'rm',     '%Eq',  'Eq',      ),
+    'Eq_WO':        ( 'IDX_UseModRM',       'rm',     '%Eq',  'Eq',      ),
+    'Ew':           ( 'IDX_UseModRM',       'rm',     '%Ew',  'Ew',      ),
+    'Ev':           ( 'IDX_UseModRM',       'rm',     '%Ev',  'Ev',      ),
+    'Qq':           ( 'IDX_UseModRM',       'rm',     '%Qq',  'Qq',      ),
+    'Qq_WO':        ( 'IDX_UseModRM',       'rm',     '%Qq',  'Qq',      ),
+    'Wss':          ( 'IDX_UseModRM',       'rm',     '%Wss', 'Wss',     ),
+    'Wss_WO':       ( 'IDX_UseModRM',       'rm',     '%Wss', 'Wss',     ),
+    'Wsd':          ( 'IDX_UseModRM',       'rm',     '%Wsd', 'Wsd',     ),
+    'Wsd_WO':       ( 'IDX_UseModRM',       'rm',     '%Wsd', 'Wsd',     ),
+    'Wps':          ( 'IDX_UseModRM',       'rm',     '%Wps', 'Wps',     ),
+    'Wps_WO':       ( 'IDX_UseModRM',       'rm',     '%Wps', 'Wps',     ),
+    'Wpd':          ( 'IDX_UseModRM',       'rm',     '%Wpd', 'Wpd',     ),
+    'Wpd_WO':       ( 'IDX_UseModRM',       'rm',     '%Wpd', 'Wpd',     ),
+    'Wdq':          ( 'IDX_UseModRM',       'rm',     '%Wdq', 'Wdq',     ),
+    'Wdq_WO':       ( 'IDX_UseModRM',       'rm',     '%Wdq', 'Wdq',     ),
+    'Wq':           ( 'IDX_UseModRM',       'rm',     '%Wq',  'Wq',      ),
+    'Wq_WO':        ( 'IDX_UseModRM',       'rm',     '%Wq',  'Wq',      ),
+    'WqZxReg_WO':   ( 'IDX_UseModRM',       'rm',     '%Wq',  'Wq',      ),
+    'Wx':           ( 'IDX_UseModRM',       'rm',     '%Wx',  'Wx',      ),
+    'Wx_WO':        ( 'IDX_UseModRM',       'rm',     '%Wx',  'Wx',      ),
 
     # ModR/M.rm - register only.
-    'Uq':   ( 'IDX_UseModRM',       'rm',     '%Uq',  'Uq',      ),
-    'UqHi': ( 'IDX_UseModRM',       'rm',     '%Uq',  'UqHi',    ),
+    'Uq':           ( 'IDX_UseModRM',       'rm',     '%Uq',  'Uq',      ),
+    'UqHi':         ( 'IDX_UseModRM',       'rm',     '%Uq',  'UqHi',    ),
+    'Uss':          ( 'IDX_UseModRM',       'rm',     '%Uss', 'Uss',     ),
+    'Uss_WO':       ( 'IDX_UseModRM',       'rm',     '%Uss', 'Uss',     ),
+    'Usd':          ( 'IDX_UseModRM',       'rm',     '%Usd', 'Usd',     ),
+    'Usd_WO':       ( 'IDX_UseModRM',       'rm',     '%Usd', 'Usd',     ),
+    'Nq':           ( 'IDX_UseModRM',       'rm',     '%Qq',  'Nq',      ),
 
     # ModR/M.rm - memory only.
-    'Ma':   ( 'IDX_UseModRM',       'rm',     '%Ma',  'Ma',      ), ##< Only used by BOUND.
-    'MbRO': ( 'IDX_UseModRM',       'rm',     '%Mb',  'Mb',      ),
-    'MdRO': ( 'IDX_UseModRM',       'rm',     '%Md',  'Md',      ),
-    'MdWO': ( 'IDX_UseModRM',       'rm',     '%Md',  'Md',      ),
-    'Mq':   ( 'IDX_UseModRM',       'rm',     '%Mq',  'Mq',      ),
-    'MRO':  ( 'IDX_UseModRM',       'rm',     '%M',   'M',      ),
-    'MRW':  ( 'IDX_UseModRM',       'rm',     '%M',   'M',      ),
+    'Ma':           ( 'IDX_UseModRM',       'rm',     '%Ma',  'Ma',      ), ##< Only used by BOUND.
+    'Mb_RO':        ( 'IDX_UseModRM',       'rm',     '%Mb',  'Mb',      ),
+    'Md':           ( 'IDX_UseModRM',       'rm',     '%Md',  'Md',      ),
+    'Md_RO':        ( 'IDX_UseModRM',       'rm',     '%Md',  'Md',      ),
+    'Md_WO':        ( 'IDX_UseModRM',       'rm',     '%Md',  'Md',      ),
+    'Mdq':          ( 'IDX_UseModRM',       'rm',     '%Mdq', 'Mdq',     ),
+    'Mdq_WO':       ( 'IDX_UseModRM',       'rm',     '%Mdq', 'Mdq',     ),
+    'Mq':           ( 'IDX_UseModRM',       'rm',     '%Mq',  'Mq',      ),
+    'Mq_WO':        ( 'IDX_UseModRM',       'rm',     '%Mq',  'Mq',      ),
+    'Mps_WO':       ( 'IDX_UseModRM',       'rm',     '%Mps', 'Mps',     ),
+    'Mpd_WO':       ( 'IDX_UseModRM',       'rm',     '%Mpd', 'Mpd',     ),
+    'Mx':           ( 'IDX_UseModRM',       'rm',     '%Mx',  'Mx',      ),
+    'Mx_WO':        ( 'IDX_UseModRM',       'rm',     '%Mx',  'Mx',      ),
+    'M_RO':         ( 'IDX_UseModRM',       'rm',     '%M',   'M',       ),
+    'M_RW':         ( 'IDX_UseModRM',       'rm',     '%M',   'M',       ),
 
     # ModR/M.reg
-    'Gb':   ( 'IDX_UseModRM',       'reg',    '%Gb',  'Gb',      ),
-    'Gw':   ( 'IDX_UseModRM',       'reg',    '%Gw',  'Gw',      ),
-    'Gv':   ( 'IDX_UseModRM',       'reg',    '%Gv',  'Gv',      ),
-    'Vss':  ( 'IDX_UseModRM',       'reg',    '%Vss', 'Vss',     ),
-    'VssZxReg': ( 'IDX_UseModRM',   'reg',    '%Vss', 'Vss',     ),
-    'Vsd':  ( 'IDX_UseModRM',       'reg',    '%Vsd', 'Vsd',     ),
-    'Vps':  ( 'IDX_UseModRM',       'reg',    '%Vps', 'Vps',     ),
-    'Vpd':  ( 'IDX_UseModRM',       'reg',    '%Vpd', 'Vpd',     ),
-    'Vq':   ( 'IDX_UseModRM',       'reg',    '%Vq',  'Vq',      ),
-    'Vdq':  ( 'IDX_UseModRM',       'reg',    '%Vpd', 'Vpd',     ),
+    'Gb':           ( 'IDX_UseModRM',       'reg',    '%Gb',  'Gb',      ),
+    'Gw':           ( 'IDX_UseModRM',       'reg',    '%Gw',  'Gw',      ),
+    'Gv':           ( 'IDX_UseModRM',       'reg',    '%Gv',  'Gv',      ),
+    'Gv_RO':        ( 'IDX_UseModRM',       'reg',    '%Gv',  'Gv',      ),
+    'Pd':           ( 'IDX_UseModRM',       'reg',    '%Pd',  'Pd',      ),
+    'PdZx_WO':      ( 'IDX_UseModRM',       'reg',    '%Pd',  'PdZx',    ),
+    'Pq':           ( 'IDX_UseModRM',       'reg',    '%Pq',  'Pq',      ),
+    'Pq_WO':        ( 'IDX_UseModRM',       'reg',    '%Pq',  'Pq',      ),
+    'Vd':           ( 'IDX_UseModRM',       'reg',    '%Vd',  'Vd',      ),
+    'Vd_WO':        ( 'IDX_UseModRM',       'reg',    '%Vd',  'Vd',      ),
+    'VdZx_WO':      ( 'IDX_UseModRM',       'reg',    '%Vd',  'Vd',      ),
+    'Vdq':          ( 'IDX_UseModRM',       'reg',    '%Vdq', 'Vdq',     ),
+    'Vss':          ( 'IDX_UseModRM',       'reg',    '%Vss', 'Vss',     ),
+    'Vss_WO':       ( 'IDX_UseModRM',       'reg',    '%Vss', 'Vss',     ),
+    'VssZx_WO':     ( 'IDX_UseModRM',       'reg',    '%Vss', 'Vss',     ),
+    'Vsd':          ( 'IDX_UseModRM',       'reg',    '%Vsd', 'Vsd',     ),
+    'Vsd_WO':       ( 'IDX_UseModRM',       'reg',    '%Vsd', 'Vsd',     ),
+    'VsdZx_WO':     ( 'IDX_UseModRM',       'reg',    '%Vsd', 'Vsd',     ),
+    'Vps':          ( 'IDX_UseModRM',       'reg',    '%Vps', 'Vps',     ),
+    'Vps_WO':       ( 'IDX_UseModRM',       'reg',    '%Vps', 'Vps',     ),
+    'Vpd':          ( 'IDX_UseModRM',       'reg',    '%Vpd', 'Vpd',     ),
+    'Vpd_WO':       ( 'IDX_UseModRM',       'reg',    '%Vpd', 'Vpd',     ),
+    'Vq':           ( 'IDX_UseModRM',       'reg',    '%Vq',  'Vq',      ),
+    'Vq_WO':        ( 'IDX_UseModRM',       'reg',    '%Vq',  'Vq',      ),
+    'Vdq_WO':       ( 'IDX_UseModRM',       'reg',    '%Vdq', 'Vdq',     ),
+    'VqHi':         ( 'IDX_UseModRM',       'reg',    '%Vdq', 'VdqHi',   ),
+    'VqHi_WO':      ( 'IDX_UseModRM',       'reg',    '%Vdq', 'VdqHi',   ),
+    'VqZx_WO':      ( 'IDX_UseModRM',       'reg',    '%Vq',  'VqZx',    ),
+    'Vx':           ( 'IDX_UseModRM',       'reg',    '%Vx',  'Vx',      ),
+    'Vx_WO':        ( 'IDX_UseModRM',       'reg',    '%Vx',  'Vx',      ),
+
+    # VEX.vvvv
+    'HssHi':        ( 'IDX_UseModRM',       'vvvv',   '%Hx',  'HssHi',   ),
+    'HsdHi':        ( 'IDX_UseModRM',       'vvvv',   '%Hx',  'HsdHi',   ),
+    'HqHi':         ( 'IDX_UseModRM',       'vvvv',   '%Hq',  'HqHi',    ),
 
     # Immediate values.
-    'Ib':   ( 'IDX_ParseImmByte',   'imm',    '%Ib',  'Ib',      ), ##< NB! Could be IDX_ParseImmByteSX for some instructions.
-    'Iw':   ( 'IDX_ParseImmUshort', 'imm',    '%Iw',  'Iw',      ),
-    'Id':   ( 'IDX_ParseImmUlong',  'imm',    '%Id',  'Id',      ),
-    'Iq':   ( 'IDX_ParseImmQword',  'imm',    '%Iq',  'Iq',      ),
-    'Iv':   ( 'IDX_ParseImmV',      'imm',    '%Iv',  'Iv',      ), ##< o16: word, o32: dword, o64: qword
-    'Iz':   ( 'IDX_ParseImmZ',      'imm',    '%Iz',  'Iz',      ), ##< o16: word, o32|o64:dword
+    'Ib':           ( 'IDX_ParseImmByte',   'imm',    '%Ib',  'Ib',      ), ##< NB! Could be IDX_ParseImmByteSX for some instrs.
+    'Iw':           ( 'IDX_ParseImmUshort', 'imm',    '%Iw',  'Iw',      ),
+    'Id':           ( 'IDX_ParseImmUlong',  'imm',    '%Id',  'Id',      ),
+    'Iq':           ( 'IDX_ParseImmQword',  'imm',    '%Iq',  'Iq',      ),
+    'Iv':           ( 'IDX_ParseImmV',      'imm',    '%Iv',  'Iv',      ), ##< o16: word, o32: dword, o64: qword
+    'Iz':           ( 'IDX_ParseImmZ',      'imm',    '%Iz',  'Iz',      ), ##< o16: word, o32|o64:dword
 
     # Address operands (no ModR/M).
-    'Ob':   ( 'IDX_ParseImmAddr',   'imm',    '%Ob',  'Ob',      ),
-    'Ov':   ( 'IDX_ParseImmAddr',   'imm',    '%Ov',  'Ov',      ),
+    'Ob':           ( 'IDX_ParseImmAddr',   'imm',    '%Ob',  'Ob',      ),
+    'Ov':           ( 'IDX_ParseImmAddr',   'imm',    '%Ov',  'Ov',      ),
 
     # Relative jump targets
-    'Jb':   ( 'IDX_ParseImmBRel',   'imm',    '%Jb',  'Jb',      ),
-    'Jv':   ( 'IDX_ParseImmVRel',   'imm',    '%Jv',  'Jv',      ),
+    'Jb':           ( 'IDX_ParseImmBRel',   'imm',    '%Jb',  'Jb',      ),
+    'Jv':           ( 'IDX_ParseImmVRel',   'imm',    '%Jv',  'Jv',      ),
 
     # DS:rSI
-    'Xb':   ( 'IDX_ParseXb',        'rSI',    '%eSI', 'Xb',      ),
-    'Xv':   ( 'IDX_ParseXv',        'rSI',    '%eSI', 'Xv',      ),
+    'Xb':           ( 'IDX_ParseXb',        'rSI',    '%eSI', 'Xb',      ),
+    'Xv':           ( 'IDX_ParseXv',        'rSI',    '%eSI', 'Xv',      ),
     # ES:rDI
-    'Yb':   ( 'IDX_ParseYb',        'rDI',    '%eDI', 'Yb',      ),
-    'Yv':   ( 'IDX_ParseYv',        'rDI',    '%eDI', 'Yv',      ),
+    'Yb':           ( 'IDX_ParseYb',        'rDI',    '%eDI', 'Yb',      ),
+    'Yv':           ( 'IDX_ParseYv',        'rDI',    '%eDI', 'Yv',      ),
 
-    'Fv':   ( 'IDX_ParseFixedReg',  'rFLAGS', '%Fv',  'Fv',      ),
+    'Fv':           ( 'IDX_ParseFixedReg',  'rFLAGS', '%Fv',  'Fv',      ),
 
     # Fixed registers.
-    'AL':   ( 'IDX_ParseFixedReg',  'AL',     'al',   'REG_AL',  ),
-    'rAX':  ( 'IDX_ParseFixedReg',  'rAX',    '%eAX', 'REG_EAX', ),
-    'CS':   ( 'IDX_ParseFixedReg',  'CS',     'cs',   'REG_CS',  ), # 8086: push CS
-    'DS':   ( 'IDX_ParseFixedReg',  'DS',     'ds',   'REG_DS',  ),
-    'ES':   ( 'IDX_ParseFixedReg',  'ES',     'es',   'REG_ES',  ),
-    'FS':   ( 'IDX_ParseFixedReg',  'FS',     'fs',   'REG_FS',  ),
-    'GS':   ( 'IDX_ParseFixedReg',  'GS',     'gs',   'REG_GS',  ),
-    'SS':   ( 'IDX_ParseFixedReg',  'SS',     'ss',   'REG_SS',  ),
+    'AL':           ( 'IDX_ParseFixedReg',  'AL',     'al',   'REG_AL',  ),
+    'rAX':          ( 'IDX_ParseFixedReg',  'rAX',    '%eAX', 'REG_EAX', ),
+    'CS':           ( 'IDX_ParseFixedReg',  'CS',     'cs',   'REG_CS',  ), # 8086: push CS
+    'DS':           ( 'IDX_ParseFixedReg',  'DS',     'ds',   'REG_DS',  ),
+    'ES':           ( 'IDX_ParseFixedReg',  'ES',     'es',   'REG_ES',  ),
+    'FS':           ( 'IDX_ParseFixedReg',  'FS',     'fs',   'REG_FS',  ),
+    'GS':           ( 'IDX_ParseFixedReg',  'GS',     'gs',   'REG_GS',  ),
+    'SS':           ( 'IDX_ParseFixedReg',  'SS',     'ss',   'REG_SS',  ),
 };
 
 # IDX_ParseFixedReg
@@ -303,6 +356,7 @@ g_kdIemForms = {     # sEncoding,   [ sWhere1, ... ]
     'VEX_RM':       ( 'VEX.ModR/M', [ 'reg', 'rm' ], ),
     'VEX_RM_REG':   ( 'VEX.ModR/M', [ 'reg', 'rm' ], ),
     'VEX_RM_MEM':   ( 'VEX.ModR/M', [ 'reg', 'rm' ], ),
+    'VEX_XM':       ( 'VEX.ModR/M', [ 'reg', 'rm' ], ), # same as VEX_RM_MEM, typo?
     'VEX_MR':       ( 'VEX.ModR/M', [ 'rm', 'reg' ], ),
     'VEX_MR_REG':   ( 'VEX.ModR/M', [ 'rm', 'reg' ], ),
     'VEX_MR_MEM':   ( 'VEX.ModR/M', [ 'rm', 'reg' ], ),
@@ -311,7 +365,11 @@ g_kdIemForms = {     # sEncoding,   [ sWhere1, ... ]
     'VEX_M_MEM':    ( 'VEX.ModR/M', [ 'rm', ], ),
     'VEX_R':        ( 'VEX.ModR/M', [ 'reg', ], ),
     'VEX_RVM':      ( 'VEX.ModR/M', [ 'reg', 'vvvv', 'rm'], ),
+    'VEX_RVM_REG':  ( 'VEX.ModR/M', [ 'reg', 'vvvv', 'rm'], ),
+    'VEX_RVM_MEM':  ( 'VEX.ModR/M', [ 'reg', 'vvvv', 'rm'], ),
     'VEX_MVR':      ( 'VEX.ModR/M', [ 'rm', 'vvvv', 'reg'], ),
+    'VEX_MVR_REG':  ( 'VEX.ModR/M', [ 'rm', 'vvvv', 'reg'], ),
+    'VEX_MVR_MEM':  ( 'VEX.ModR/M', [ 'rm', 'vvvv', 'reg'], ),
 
     'FIXED':        ( 'fixed',      None, )
 };
@@ -341,19 +399,25 @@ g_kdSubOpcodes = {
     '11':           [ '11 mr/reg',  ],      ##< alias
     '!11 mr/reg':   [ '!11 mr/reg', ],
     '!11':          [ '!11 mr/reg', ],      ##< alias
+    'rex.w=0':      [ 'rex.w=0',    ],
+    'w=0':          [ 'rex.w=0',    ],      ##< alias
+    'rex.w=1':      [ 'rex.w=1',    ],
+    'w=1':          [ 'rex.w=1',    ],      ##< alias
 };
 
 ## Valid values for \@openc
 g_kdEncodings = {
     'ModR/M':       [ 'BS3CG1ENC_MODRM', ],     ##< ModR/M
     'VEX.ModR/M':   [ 'BS3CG1ENC_VEX_MODRM', ], ##< VEX...ModR/M
-    'fixed':        [ 'BS3CG1ENC_FIXED', ],     ##< Fixed encoding (address, registers, etc).
+    'fixed':        [ 'BS3CG1ENC_FIXED', ],     ##< Fixed encoding (address, registers, unused, etc).
+    'VEX.fixed':    [ 'BS3CG1ENC_VEX_FIXED', ], ##< VEX + fixed encoding (address, registers, unused, etc).
     'prefix':       [ None, ],                  ##< Prefix
 };
 
 ## \@opunused, \@opinvalid, \@opinvlstyle
 g_kdInvalidStyles = {
     'immediate':                [], ##< CPU stops decoding immediately after the opcode.
+    'vex.modrm':                [], ##< VEX+ModR/M, everyone.
     'intel-modrm':              [], ##< Intel decodes ModR/M.
     'intel-modrm-imm8':         [], ##< Intel decodes ModR/M and an 8-byte immediate.
     'intel-opcode-modrm':       [], ##< Intel decodes another opcode byte followed by ModR/M. (Unused extension tables.)
@@ -391,8 +455,8 @@ g_kdCpuIdFlags = {
     'fma':          'X86_CPUID_FEATURE_ECX_FMA',
     'cx16':         'X86_CPUID_FEATURE_ECX_CX16',
     'pcid':         'X86_CPUID_FEATURE_ECX_PCID',
-    'sse41':        'X86_CPUID_FEATURE_ECX_SSE4_1',
-    'sse42':        'X86_CPUID_FEATURE_ECX_SSE4_2',
+    'sse4.1':       'X86_CPUID_FEATURE_ECX_SSE4_1',
+    'sse4.2':       'X86_CPUID_FEATURE_ECX_SSE4_2',
     'movbe':        'X86_CPUID_FEATURE_ECX_MOVBE',
     'popcnt':       'X86_CPUID_FEATURE_ECX_POPCNT',
     'aes':          'X86_CPUID_FEATURE_ECX_AES',
@@ -444,7 +508,11 @@ g_kdHints = {
     'sse':                   'DISOPTYPE_SSE',                   ##< SSE,SSE2,SSE3,AVX,++ instruction. Not implemented yet!
     'mmx':                   'DISOPTYPE_MMX',                   ##< MMX,MMXExt,3DNow,++ instruction. Not implemented yet!
     'fpu':                   'DISOPTYPE_FPU',                   ##< FPU instruction. Not implemented yet!
-    'ignores_op_size':       '',                                ##< Ignores both operand size prefixes.
+    'ignores_oz_pfx':        '',                                ##< Ignores operand size prefix 66h.
+    'ignores_rexw':          '',                                ##< Ignores REX.W.
+    'ignores_op_sizes':      '',                                ##< Shorthand for "ignores_oz_pfx | ignores_op_sizes".
+    'ignores_vex_l':         '',                                ##< Ignores VEX.L.
+    'vex_l_zero':            '',                                ##< VEX.L must be 0.
     'lock_allowed':          '',                                ##< Lock prefix allowed.
 };
 
@@ -457,8 +525,10 @@ g_kdXcptTypes = {
     '4':        [],
     '4UA':      [],
     '5':        [],
+    '5LZ':      [], # LZ = VEX.L must be zero.
     '6':        [],
     '7':        [],
+    '7LZ':      [],
     '8':        [],
     '11':       [],
     '12':       [],
@@ -638,6 +708,11 @@ class InstructionMap(object):
         return sName;
 
 
+    def isVexMap(self):
+        """ Returns True if a VEX map. """
+        return self.sEncoding.startswith('vex');
+
+
 class TestType(object):
     """
     Test value type.
@@ -1103,6 +1178,11 @@ class TestSelector(object):
             'o32':  'size_o32',
             'o64':  'size_o64',
         },
+        # VEX.L value.
+        'vex.l': {
+            '0':    'vexl_0',
+            '1':    'vexl_1',
+        },
         # Execution ring.
         'ring': {
             '0':    'ring_0',
@@ -1153,6 +1233,9 @@ class TestSelector(object):
         'ring3':        'ring==3',
         'user':         'ring==3',
         'supervisor':   'ring==0..2',
+        '16-bit':       'codebits==16',
+        '32-bit':       'codebits==32',
+        '64-bit':       'codebits==64',
         'real':         'mode==real',
         'prot':         'mode==prot',
         'long':         'mode==long',
@@ -1411,6 +1494,16 @@ class Instruction(object): # pylint: disable=too-many-instance-attributes
         """ Returns asFlClear into a integer mask value """
         return self._flagsToIntegerMask(self.asFlClear);
 
+    def onlyInVexMaps(self):
+        """ Returns True if only in VEX maps, otherwise False.  (No maps -> False) """
+        if not self.aoMaps:
+            return False;
+        for oMap in self.aoMaps:
+            if not oMap.isVexMap():
+                return False;
+        return True;
+
+
 
 ## All the instructions.
 g_aoAllInstructions = []; # type: list(Instruction)
@@ -1701,19 +1794,6 @@ class SimpleParser(object):
             elif oInstr.sStats:
                 oInstr.sFunction = 'iemOp_' + oInstr.sStats;
 
-        # Derive encoding from operands.
-        if oInstr.sEncoding is None:
-            if not oInstr.aoOperands:
-                if oInstr.fUnused and oInstr.sSubOpcode:
-                    oInstr.sEncoding = 'ModR/M';
-                else:
-                    oInstr.sEncoding = 'fixed';
-            elif oInstr.aoOperands[0].usesModRM():
-                if len(oInstr.aoOperands) >= 2 and oInstr.aoOperands[1].sWhere == 'vvvv':
-                    oInstr.sEncoding = 'ModR/M+VEX';
-                else:
-                    oInstr.sEncoding = 'ModR/M';
-
         #
         # Apply default map and then add the instruction to all it's groups.
         #
@@ -1723,6 +1803,22 @@ class SimpleParser(object):
             oMap.aoInstructions.append(oInstr);
 
         #
+        # Derive encoding from operands and maps.
+        #
+        if oInstr.sEncoding is None:
+            if not oInstr.aoOperands:
+                if oInstr.fUnused and oInstr.sSubOpcode:
+                    oInstr.sEncoding = 'VEX.ModR/M' if oInstr.onlyInVexMaps() else 'ModR/M';
+                else:
+                    oInstr.sEncoding = 'VEX.fixed' if oInstr.onlyInVexMaps() else 'fixed';
+            elif oInstr.aoOperands[0].usesModRM():
+                if     (len(oInstr.aoOperands) >= 2 and oInstr.aoOperands[1].sWhere == 'vvvv') \
+                    or oInstr.onlyInVexMaps():
+                    oInstr.sEncoding = 'VEX.ModR/M';
+                else:
+                    oInstr.sEncoding = 'ModR/M';
+
+        #
         # Check the opstat value and add it to the opstat indexed dictionary.
         #
         if oInstr.sStats:
@@ -3129,7 +3225,8 @@ class SimpleParser(object):
                 self.doneInstructions();
 
         self.doneInstructions();
-        self.debug('%3s stubs out of %3s instructions in %s' % (self.cTotalStubs, self.cTotalInstr, os.path.basename(self.sSrcFile),));
+        self.debug('%3s stubs out of %3s instructions in %s'
+                   % (self.cTotalStubs, self.cTotalInstr, os.path.basename(self.sSrcFile),));
         return self.printErrors();
 
 
diff --git a/src/VBox/VMM/VMMAll/IEMAllInstructionsThree0f38.cpp.h b/src/VBox/VMM/VMMAll/IEMAllInstructionsThree0f38.cpp.h
index 2d6d3a7..e6aaa28 100644
--- a/src/VBox/VMM/VMMAll/IEMAllInstructionsThree0f38.cpp.h
+++ b/src/VBox/VMM/VMMAll/IEMAllInstructionsThree0f38.cpp.h
@@ -143,8 +143,54 @@ FNIEMOP_STUB(iemOp_pmovsxdq_Vx_UxMq);
 FNIEMOP_STUB(iemOp_pmuldq_Vx_Wx);
 /** Opcode 0x66 0x0f 0x38 0x29. */
 FNIEMOP_STUB(iemOp_pcmpeqq_Vx_Wx);
-/** Opcode 0x66 0x0f 0x38 0x2a. */
-FNIEMOP_STUB(iemOp_movntdqa_Vx_Mx);
+
+/**
+ * @opcode      0x2a
+ * @opcodesub   !11 mr/reg
+ * @oppfx       0x66
+ * @opcpuid     sse4.1
+ * @opgroup     og_sse41_cachect
+ * @opxcpttype  1
+ * @optest      op1=-1 op2=2  -> op1=2
+ * @optest      op1=0 op2=-42 -> op1=-42
+ */
+FNIEMOP_DEF(iemOp_movntdqa_Vdq_Mdq)
+{
+    IEMOP_MNEMONIC2(RM_MEM, MOVNTDQA, movntdqa, Vdq_WO, Mdq, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZES);
+    uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
+    if ((bRm & X86_MODRM_MOD_MASK) != (3 << X86_MODRM_MOD_SHIFT))
+    {
+        /* Register, memory. */
+        IEM_MC_BEGIN(0, 2);
+        IEM_MC_LOCAL(RTUINT128U,                uSrc);
+        IEM_MC_LOCAL(RTGCPTR,                   GCPtrEffSrc);
+
+        IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, bRm, 0);
+        IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
+        IEM_MC_MAYBE_RAISE_SSE41_RELATED_XCPT();
+        IEM_MC_ACTUALIZE_SSE_STATE_FOR_CHANGE();
+
+        IEM_MC_FETCH_MEM_U128_ALIGN_SSE(uSrc, pVCpu->iem.s.iEffSeg, GCPtrEffSrc);
+        IEM_MC_STORE_XREG_U128(((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg, uSrc);
+
+        IEM_MC_ADVANCE_RIP();
+        IEM_MC_END();
+        return VINF_SUCCESS;
+    }
+
+    /**
+     * @opdone
+     * @opmnemonic  ud660f382areg
+     * @opcode      0x2a
+     * @opcodesub   11 mr/reg
+     * @oppfx       0x66
+     * @opunused    immediate
+     * @opcpuid     sse
+     * @optest      ->
+     */
+    return IEMOP_RAISE_INVALID_OPCODE();
+}
+
 /** Opcode 0x66 0x0f 0x38 0x2b. */
 FNIEMOP_STUB(iemOp_packusdw_Vx_Wx);
 /*  Opcode 0x66 0x0f 0x38 0x2c - invalid (vex only). */
@@ -545,7 +591,7 @@ IEM_STATIC const PFNIEMOP g_apfnThreeByte0f38[] =
     /* 0x27 */  IEMOP_X4(iemOp_InvalidNeedRM),
     /* 0x28 */  iemOp_InvalidNeedRM,        iemOp_pmuldq_Vx_Wx,         iemOp_InvalidNeedRM,        iemOp_InvalidNeedRM,
     /* 0x29 */  iemOp_InvalidNeedRM,        iemOp_pcmpeqq_Vx_Wx,        iemOp_InvalidNeedRM,        iemOp_InvalidNeedRM,
-    /* 0x2a */  iemOp_InvalidNeedRM,        iemOp_movntdqa_Vx_Mx,       iemOp_InvalidNeedRM,        iemOp_InvalidNeedRM,
+    /* 0x2a */  iemOp_InvalidNeedRM,        iemOp_movntdqa_Vdq_Mdq,     iemOp_InvalidNeedRM,        iemOp_InvalidNeedRM,
     /* 0x2b */  iemOp_InvalidNeedRM,        iemOp_packusdw_Vx_Wx,       iemOp_InvalidNeedRM,        iemOp_InvalidNeedRM,
     /* 0x2c */  IEMOP_X4(iemOp_InvalidNeedRM),
     /* 0x2d */  IEMOP_X4(iemOp_InvalidNeedRM),
diff --git a/src/VBox/VMM/VMMAll/IEMAllInstructionsTwoByte0f.cpp.h b/src/VBox/VMM/VMMAll/IEMAllInstructionsTwoByte0f.cpp.h
index 0bb58a2..3642af9 100644
--- a/src/VBox/VMM/VMMAll/IEMAllInstructionsTwoByte0f.cpp.h
+++ b/src/VBox/VMM/VMMAll/IEMAllInstructionsTwoByte0f.cpp.h
@@ -989,10 +989,107 @@ FNIEMOP_DEF(iemOp_3Dnow)
 }
 
 
-/** Opcode      0x0f 0x10 - vmovups Vps, Wps */
-FNIEMOP_STUB(iemOp_movups_Vps_Wps);
-/** Opcode 0x66 0x0f 0x10 - vmovupd Vpd, Wpd */
-FNIEMOP_STUB(iemOp_movupd_Vpd_Wpd);
+/**
+ * @opcode      0x10
+ * @oppfx       none
+ * @opcpuid     sse
+ * @opgroup     og_sse_simdfp_datamove
+ * @opxcpttype  4UA
+ * @optest      op1=1 op2=2 -> op1=2
+ * @optest      op1=0 op2=-22 -> op1=-22
+ */
+FNIEMOP_DEF(iemOp_movups_Vps_Wps)
+{
+    IEMOP_MNEMONIC2(RM, MOVUPS, movups, Vps_WO, Wps, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZES);
+    uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
+    if ((bRm & X86_MODRM_MOD_MASK) == (3 << X86_MODRM_MOD_SHIFT))
+    {
+        /*
+         * Register, register.
+         */
+        IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
+        IEM_MC_BEGIN(0, 0);
+        IEM_MC_MAYBE_RAISE_SSE_RELATED_XCPT();
+        IEM_MC_ACTUALIZE_SSE_STATE_FOR_CHANGE();
+        IEM_MC_COPY_XREG_U128(((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg,
+                              (bRm & X86_MODRM_RM_MASK) | pVCpu->iem.s.uRexB);
+        IEM_MC_ADVANCE_RIP();
+        IEM_MC_END();
+    }
+    else
+    {
+        /*
+         * Memory, register.
+         */
+        IEM_MC_BEGIN(0, 2);
+        IEM_MC_LOCAL(RTUINT128U,                uSrc); /** @todo optimize this one day... */
+        IEM_MC_LOCAL(RTGCPTR,                   GCPtrEffSrc);
+
+        IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, bRm, 0);
+        IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
+        IEM_MC_MAYBE_RAISE_SSE_RELATED_XCPT();
+        IEM_MC_ACTUALIZE_SSE_STATE_FOR_CHANGE();
+
+        IEM_MC_FETCH_MEM_U128(uSrc, pVCpu->iem.s.iEffSeg, GCPtrEffSrc);
+        IEM_MC_STORE_XREG_U128(((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg, uSrc);
+
+        IEM_MC_ADVANCE_RIP();
+        IEM_MC_END();
+    }
+    return VINF_SUCCESS;
+
+}
+
+
+/**
+ * @opcode      0x10
+ * @oppfx       0x66
+ * @opcpuid     sse2
+ * @opgroup     og_sse2_pcksclr_datamove
+ * @opxcpttype  4UA
+ * @optest      op1=1 op2=2 -> op1=2
+ * @optest      op1=0 op2=-42 -> op1=-42
+ */
+FNIEMOP_DEF(iemOp_movupd_Vpd_Wpd)
+{
+    IEMOP_MNEMONIC2(RM, MOVUPD, movupd, Vpd_WO, Wpd, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZES);
+    uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
+    if ((bRm & X86_MODRM_MOD_MASK) == (3 << X86_MODRM_MOD_SHIFT))
+    {
+        /*
+         * Register, register.
+         */
+        IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
+        IEM_MC_BEGIN(0, 0);
+        IEM_MC_MAYBE_RAISE_SSE2_RELATED_XCPT();
+        IEM_MC_ACTUALIZE_SSE_STATE_FOR_CHANGE();
+        IEM_MC_COPY_XREG_U128(((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg,
+                              (bRm & X86_MODRM_RM_MASK) | pVCpu->iem.s.uRexB);
+        IEM_MC_ADVANCE_RIP();
+        IEM_MC_END();
+    }
+    else
+    {
+        /*
+         * Memory, register.
+         */
+        IEM_MC_BEGIN(0, 2);
+        IEM_MC_LOCAL(RTUINT128U,                uSrc); /** @todo optimize this one day... */
+        IEM_MC_LOCAL(RTGCPTR,                   GCPtrEffSrc);
+
+        IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, bRm, 0);
+        IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
+        IEM_MC_MAYBE_RAISE_SSE2_RELATED_XCPT();
+        IEM_MC_ACTUALIZE_SSE_STATE_FOR_CHANGE();
+
+        IEM_MC_FETCH_MEM_U128(uSrc, pVCpu->iem.s.iEffSeg, GCPtrEffSrc);
+        IEM_MC_STORE_XREG_U128(((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg, uSrc);
+
+        IEM_MC_ADVANCE_RIP();
+        IEM_MC_END();
+    }
+    return VINF_SUCCESS;
+}
 
 
 /**
@@ -1006,7 +1103,7 @@ FNIEMOP_STUB(iemOp_movupd_Vpd_Wpd);
  */
 FNIEMOP_DEF(iemOp_movss_Vss_Wss)
 {
-    IEMOP_MNEMONIC2(RM, MOVSS, movss, VssZxReg, Wss, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZE);
+    IEMOP_MNEMONIC2(RM, MOVSS, movss, VssZx_WO, Wss, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZES);
     uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
     if ((bRm & X86_MODRM_MOD_MASK) == (3 << X86_MODRM_MOD_SHIFT))
     {
@@ -1049,8 +1146,58 @@ FNIEMOP_DEF(iemOp_movss_Vss_Wss)
 }
 
 
-/** Opcode 0xf2 0x0f 0x10 - movsd Vx, Wsd */
-FNIEMOP_STUB(iemOp_movsd_Vx_Wsd);
+/**
+ * @opcode      0x10
+ * @oppfx       0xf2
+ * @opcpuid     sse2
+ * @opgroup     og_sse2_pcksclr_datamove
+ * @opxcpttype  5
+ * @optest      op1=1 op2=2 -> op1=2
+ * @optest      op1=0 op2=-42 -> op1=-42
+ */
+FNIEMOP_DEF(iemOp_movsd_Vsd_Wsd)
+{
+    IEMOP_MNEMONIC2(RM, MOVSD, movsd, VsdZx_WO, Wsd, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZES);
+    uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
+    if ((bRm & X86_MODRM_MOD_MASK) == (3 << X86_MODRM_MOD_SHIFT))
+    {
+        /*
+         * Register, register.
+         */
+        IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
+        IEM_MC_BEGIN(0, 1);
+        IEM_MC_LOCAL(uint64_t,                  uSrc);
+
+        IEM_MC_MAYBE_RAISE_SSE2_RELATED_XCPT();
+        IEM_MC_ACTUALIZE_SSE_STATE_FOR_CHANGE();
+        IEM_MC_FETCH_XREG_U64(uSrc, (bRm & X86_MODRM_RM_MASK) | pVCpu->iem.s.uRexB);
+        IEM_MC_STORE_XREG_U64_ZX_U128(((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg, uSrc);
+
+        IEM_MC_ADVANCE_RIP();
+        IEM_MC_END();
+    }
+    else
+    {
+        /*
+         * Memory, register.
+         */
+        IEM_MC_BEGIN(0, 2);
+        IEM_MC_LOCAL(uint64_t,                  uSrc);
+        IEM_MC_LOCAL(RTGCPTR,                   GCPtrEffSrc);
+
+        IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, bRm, 0);
+        IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
+        IEM_MC_MAYBE_RAISE_SSE2_RELATED_XCPT();
+        IEM_MC_ACTUALIZE_SSE_STATE_FOR_CHANGE();
+
+        IEM_MC_FETCH_MEM_U64(uSrc, pVCpu->iem.s.iEffSeg, GCPtrEffSrc);
+        IEM_MC_STORE_XREG_U64_ZX_U128(((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg, uSrc);
+
+        IEM_MC_ADVANCE_RIP();
+        IEM_MC_END();
+    }
+    return VINF_SUCCESS;
+}
 
 
 /**
@@ -1064,7 +1211,7 @@ FNIEMOP_STUB(iemOp_movsd_Vx_Wsd);
  */
 FNIEMOP_DEF(iemOp_movups_Wps_Vps)
 {
-    IEMOP_MNEMONIC2(MR, MOVUPS, movups, Wps, Vps, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZE);
+    IEMOP_MNEMONIC2(MR, MOVUPS, movups, Wps_WO, Vps, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZES);
     uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
     if ((bRm & X86_MODRM_MOD_MASK) == (3 << X86_MODRM_MOD_SHIFT))
     {
@@ -1115,7 +1262,7 @@ FNIEMOP_DEF(iemOp_movups_Wps_Vps)
  */
 FNIEMOP_DEF(iemOp_movupd_Wpd_Vpd)
 {
-    IEMOP_MNEMONIC2(MR, MOVUPD, movupd, Wpd, Vpd, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZE);
+    IEMOP_MNEMONIC2(MR, MOVUPD, movupd, Wpd_WO, Vpd, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZES);
     uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
     if ((bRm & X86_MODRM_MOD_MASK) == (3 << X86_MODRM_MOD_SHIFT))
     {
@@ -1166,7 +1313,7 @@ FNIEMOP_DEF(iemOp_movupd_Wpd_Vpd)
  */
 FNIEMOP_DEF(iemOp_movss_Wss_Vss)
 {
-    IEMOP_MNEMONIC2(MR, MOVSS, movss, Wss, Vss, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZE);
+    IEMOP_MNEMONIC2(MR, MOVSS, movss, Wss_WO, Vss, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZES);
     uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
     if ((bRm & X86_MODRM_MOD_MASK) == (3 << X86_MODRM_MOD_SHIFT))
     {
@@ -1220,7 +1367,7 @@ FNIEMOP_DEF(iemOp_movss_Wss_Vss)
  */
 FNIEMOP_DEF(iemOp_movsd_Wsd_Vsd)
 {
-    IEMOP_MNEMONIC2(MR, MOVSD, movsd, Wsd, Vsd, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZE);
+    IEMOP_MNEMONIC2(MR, MOVSD, movsd, Wsd_WO, Vsd, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZES);
     uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
     if ((bRm & X86_MODRM_MOD_MASK) == (3 << X86_MODRM_MOD_SHIFT))
     {
@@ -1278,7 +1425,7 @@ FNIEMOP_DEF(iemOp_movlps_Vq_Mq__movhlps)
          * @optest      op1=1 op2=2 -> op1=2
          * @optest      op1=0 op2=-42 -> op1=-42
          */
-        IEMOP_MNEMONIC2(RM_REG, MOVHLPS, movhlps, Vq, UqHi, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZE);
+        IEMOP_MNEMONIC2(RM_REG, MOVHLPS, movhlps, Vq_WO, UqHi, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZES);
 
         IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
         IEM_MC_BEGIN(0, 1);
@@ -1306,7 +1453,7 @@ FNIEMOP_DEF(iemOp_movlps_Vq_Mq__movhlps)
          * @optest      op1=0 op2=-42 -> op1=-42
          * @opfunction  iemOp_movlps_Vq_Mq__vmovhlps
          */
-        IEMOP_MNEMONIC2(RM_MEM, MOVLPS, movlps, Vq, Mq, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZE);
+        IEMOP_MNEMONIC2(RM_MEM, MOVLPS, movlps, Vq_WO, Mq, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZES);
 
         IEM_MC_BEGIN(0, 2);
         IEM_MC_LOCAL(uint64_t,                  uSrc);
@@ -1342,7 +1489,7 @@ FNIEMOP_DEF(iemOp_movlpd_Vq_Mq)
     uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
     if ((bRm & X86_MODRM_MOD_MASK) != (3 << X86_MODRM_MOD_SHIFT))
     {
-        IEMOP_MNEMONIC2(RM_MEM, MOVLPD, movlpd, Vq, Mq, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZE);
+        IEMOP_MNEMONIC2(RM_MEM, MOVLPD, movlpd, Vq_WO, Mq, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZES);
 
         IEM_MC_BEGIN(0, 2);
         IEM_MC_LOCAL(uint64_t,                  uSrc);
@@ -1386,7 +1533,7 @@ FNIEMOP_DEF(iemOp_movlpd_Vq_Mq)
  */
 FNIEMOP_DEF(iemOp_movsldup_Vdq_Wdq)
 {
-    IEMOP_MNEMONIC2(RM, MOVSLDUP, movsldup, Vdq, Wdq, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZE);
+    IEMOP_MNEMONIC2(RM, MOVSLDUP, movsldup, Vdq_WO, Wdq, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZES);
     uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
     if ((bRm & X86_MODRM_MOD_MASK) == (3 << X86_MODRM_MOD_SHIFT))
     {
@@ -1446,7 +1593,7 @@ FNIEMOP_DEF(iemOp_movsldup_Vdq_Wdq)
  */
 FNIEMOP_DEF(iemOp_movddup_Vdq_Wdq)
 {
-    IEMOP_MNEMONIC2(RM, MOVDDUP, movddup, Vdq, Wdq, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZE);
+    IEMOP_MNEMONIC2(RM, MOVDDUP, movddup, Vdq_WO, Wdq, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZES);
     uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
     if ((bRm & X86_MODRM_MOD_MASK) == (3 << X86_MODRM_MOD_SHIFT))
     {
@@ -1494,38 +1641,70 @@ FNIEMOP_DEF(iemOp_movddup_Vdq_Wdq)
 }
 
 
-/** Opcode      0x0f 0x13 - vmovlps Mq, Vq */
-FNIEMOP_STUB(iemOp_movlps_Mq_Vq);
-
-/** Opcode 0x66 0x0f 0x13 - vmovlpd Mq, Vq */
-FNIEMOP_DEF(iemOp_movlpd_Mq_Vq)
+/**
+ * @opcode      0x13
+ * @opcodesub   !11 mr/reg
+ * @oppfx       none
+ * @opcpuid     sse
+ * @opgroup     og_sse_simdfp_datamove
+ * @opxcpttype  5
+ * @optest      op1=1 op2=2 -> op1=2
+ * @optest      op1=0 op2=-42 -> op1=-42
+ */
+FNIEMOP_DEF(iemOp_movlps_Mq_Vq)
 {
-    IEMOP_MNEMONIC(movlpd_Mq_Vq, "movlpd Mq,Vq");
     uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
-    if ((bRm & X86_MODRM_MOD_MASK) == (3 << X86_MODRM_MOD_SHIFT))
+    if ((bRm & X86_MODRM_MOD_MASK) != (3 << X86_MODRM_MOD_SHIFT))
     {
-#if 0
-        /*
-         * Register, register.
-         */
-        IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
-        IEM_MC_BEGIN(0, 1);
+        IEMOP_MNEMONIC2(MR_MEM, MOVLPS, movlps, Mq_WO, Vq, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZES);
+
+        IEM_MC_BEGIN(0, 2);
         IEM_MC_LOCAL(uint64_t,                  uSrc);
-        IEM_MC_MAYBE_RAISE_SSE2_RELATED_XCPT();
-        IEM_MC_ACTUALIZE_SSE_STATE_FOR_CHANGE();
+        IEM_MC_LOCAL(RTGCPTR,                   GCPtrEffSrc);
+
+        IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, bRm, 0);
+        IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
+        IEM_MC_MAYBE_RAISE_SSE_RELATED_XCPT();
+        IEM_MC_ACTUALIZE_SSE_STATE_FOR_READ();
+
         IEM_MC_FETCH_XREG_U64(uSrc, ((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg);
-        IEM_MC_STORE_XREG_U64((bRm & X86_MODRM_RM_MASK) | pVCpu->iem.s.uRexB, uSrc);
+        IEM_MC_STORE_MEM_U64(pVCpu->iem.s.iEffSeg, GCPtrEffSrc, uSrc);
+
         IEM_MC_ADVANCE_RIP();
         IEM_MC_END();
-#else
-        return IEMOP_RAISE_INVALID_OPCODE();
-#endif
+        return VINF_SUCCESS;
     }
-    else
+
+    /**
+     * @opdone
+     * @opmnemonic  ud0f13m3
+     * @opcode      0x13
+     * @opcodesub   11 mr/reg
+     * @oppfx       none
+     * @opunused    immediate
+     * @opcpuid     sse
+     * @optest      ->
+     */
+    return IEMOP_RAISE_INVALID_OPCODE();
+}
+
+
+/**
+ * @opcode      0x13
+ * @opcodesub   !11 mr/reg
+ * @oppfx       0x66
+ * @opcpuid     sse2
+ * @opgroup     og_sse2_pcksclr_datamove
+ * @opxcpttype  5
+ * @optest      op1=1 op2=2 -> op1=2
+ * @optest      op1=0 op2=-42 -> op1=-42
+ */
+FNIEMOP_DEF(iemOp_movlpd_Mq_Vq)
+{
+    uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
+    if ((bRm & X86_MODRM_MOD_MASK) != (3 << X86_MODRM_MOD_SHIFT))
     {
-        /*
-         * Memory, register.
-         */
+        IEMOP_MNEMONIC2(MR_MEM, MOVLPD, movlpd, Mq_WO, Vq, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZES);
         IEM_MC_BEGIN(0, 2);
         IEM_MC_LOCAL(uint64_t,                  uSrc);
         IEM_MC_LOCAL(RTGCPTR,                   GCPtrEffSrc);
@@ -1540,45 +1719,402 @@ FNIEMOP_DEF(iemOp_movlpd_Mq_Vq)
 
         IEM_MC_ADVANCE_RIP();
         IEM_MC_END();
+        return VINF_SUCCESS;
     }
-    return VINF_SUCCESS;
+
+    /**
+     * @opdone
+     * @opmnemonic  ud660f13m3
+     * @opcode      0x13
+     * @opcodesub   11 mr/reg
+     * @oppfx       0x66
+     * @opunused    immediate
+     * @opcpuid     sse
+     * @optest      ->
+     */
+    return IEMOP_RAISE_INVALID_OPCODE();
 }
 
-/*  Opcode 0xf3 0x0f 0x13 - invalid */
-/*  Opcode 0xf2 0x0f 0x13 - invalid */
+
+/**
+ * @opmnemonic  udf30f13
+ * @opcode      0x13
+ * @oppfx       0xf3
+ * @opunused    intel-modrm
+ * @opcpuid     sse
+ * @optest      ->
+ * @opdone
+ */
+
+/**
+ * @opmnemonic  udf20f13
+ * @opcode      0x13
+ * @oppfx       0xf2
+ * @opunused    intel-modrm
+ * @opcpuid     sse
+ * @optest      ->
+ * @opdone
+ */
 
 /** Opcode      0x0f 0x14 - unpcklps Vx, Wx*/
 FNIEMOP_STUB(iemOp_unpcklps_Vx_Wx);
 /** Opcode 0x66 0x0f 0x14 - unpcklpd Vx, Wx   */
 FNIEMOP_STUB(iemOp_unpcklpd_Vx_Wx);
-/*  Opcode 0xf3 0x0f 0x14 - invalid */
-/*  Opcode 0xf2 0x0f 0x14 - invalid */
+
+/**
+ * @opdone
+ * @opmnemonic  udf30f14
+ * @opcode      0x14
+ * @oppfx       0xf3
+ * @opunused    intel-modrm
+ * @opcpuid     sse
+ * @optest      ->
+ * @opdone
+ */
+
+/**
+ * @opmnemonic  udf20f14
+ * @opcode      0x14
+ * @oppfx       0xf2
+ * @opunused    intel-modrm
+ * @opcpuid     sse
+ * @optest      ->
+ * @opdone
+ */
+
 /** Opcode      0x0f 0x15 - unpckhps Vx, Wx   */
 FNIEMOP_STUB(iemOp_unpckhps_Vx_Wx);
 /** Opcode 0x66 0x0f 0x15 - unpckhpd Vx, Wx   */
 FNIEMOP_STUB(iemOp_unpckhpd_Vx_Wx);
 /*  Opcode 0xf3 0x0f 0x15 - invalid */
 /*  Opcode 0xf2 0x0f 0x15 - invalid */
-/** Opcode      0x0f 0x16 - movhpsv1 Vdq, Mq movlhps Vdq, Uq   */
-FNIEMOP_STUB(iemOp_movhpsv1_Vdq_Mq__movlhps_Vdq_Uq);  //NEXT
-/** Opcode 0x66 0x0f 0x16 - movhpdv1 Vdq, Mq   */
-FNIEMOP_STUB(iemOp_movhpdv1_Vdq_Mq);  //NEXT
-/** Opcode 0xf3 0x0f 0x16 - movshdup Vx, Wx   */
-FNIEMOP_STUB(iemOp_movshdup_Vx_Wx); //NEXT
-/*  Opcode 0xf2 0x0f 0x16 - invalid */
-/** Opcode      0x0f 0x17 - movhpsv1 Mq, Vq   */
-FNIEMOP_STUB(iemOp_movhpsv1_Mq_Vq);  //NEXT
-/** Opcode 0x66 0x0f 0x17 - movhpdv1 Mq, Vq   */
-FNIEMOP_STUB(iemOp_movhpdv1_Mq_Vq);  //NEXT
-/*  Opcode 0xf3 0x0f 0x17 - invalid */
-/*  Opcode 0xf2 0x0f 0x17 - invalid */
 
+/**
+ * @opdone
+ * @opmnemonic  udf30f15
+ * @opcode      0x15
+ * @oppfx       0xf3
+ * @opunused    intel-modrm
+ * @opcpuid     sse
+ * @optest      ->
+ * @opdone
+ */
 
-/** Opcode 0x0f 0x18. */
-FNIEMOP_DEF(iemOp_prefetch_Grp16)
-{
-    uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
-    if ((bRm & X86_MODRM_MOD_MASK) != (3 << X86_MODRM_MOD_SHIFT))
+/**
+ * @opmnemonic  udf20f15
+ * @opcode      0x15
+ * @oppfx       0xf2
+ * @opunused    intel-modrm
+ * @opcpuid     sse
+ * @optest      ->
+ * @opdone
+ */
+
+FNIEMOP_DEF(iemOp_movhps_Vdq_Mq__movlhps_Vdq_Uq)
+{
+    uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
+    if ((bRm & X86_MODRM_MOD_MASK) == (3 << X86_MODRM_MOD_SHIFT))
+    {
+        /**
+         * @opcode      0x16
+         * @opcodesub   11 mr/reg
+         * @oppfx       none
+         * @opcpuid     sse
+         * @opgroup     og_sse_simdfp_datamove
+         * @opxcpttype  5
+         * @optest      op1=1 op2=2 -> op1=2
+         * @optest      op1=0 op2=-42 -> op1=-42
+         */
+        IEMOP_MNEMONIC2(RM_REG, MOVLHPS, movlhps, VqHi_WO, Uq, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZES);
+
+        IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
+        IEM_MC_BEGIN(0, 1);
+        IEM_MC_LOCAL(uint64_t,                  uSrc);
+
+        IEM_MC_MAYBE_RAISE_SSE_RELATED_XCPT();
+        IEM_MC_ACTUALIZE_SSE_STATE_FOR_CHANGE();
+        IEM_MC_FETCH_XREG_U64(uSrc, (bRm & X86_MODRM_RM_MASK) | pVCpu->iem.s.uRexB);
+        IEM_MC_STORE_XREG_HI_U64(((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg, uSrc);
+
+        IEM_MC_ADVANCE_RIP();
+        IEM_MC_END();
+    }
+    else
+    {
+        /**
+         * @opdone
+         * @opcode      0x16
+         * @opcodesub   !11 mr/reg
+         * @oppfx       none
+         * @opcpuid     sse
+         * @opgroup     og_sse_simdfp_datamove
+         * @opxcpttype  5
+         * @optest      op1=1 op2=2 -> op1=2
+         * @optest      op1=0 op2=-42 -> op1=-42
+         * @opfunction  iemOp_movhps_Vdq_Mq__movlhps_Vdq_Uq
+         */
+        IEMOP_MNEMONIC2(RM_MEM, MOVHPS, movhps, VqHi_WO, Mq, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZES);
+
+        IEM_MC_BEGIN(0, 2);
+        IEM_MC_LOCAL(uint64_t,                  uSrc);
+        IEM_MC_LOCAL(RTGCPTR,                   GCPtrEffSrc);
+
+        IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, bRm, 0);
+        IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
+        IEM_MC_MAYBE_RAISE_SSE_RELATED_XCPT();
+        IEM_MC_ACTUALIZE_SSE_STATE_FOR_CHANGE();
+
+        IEM_MC_FETCH_MEM_U64(uSrc, pVCpu->iem.s.iEffSeg, GCPtrEffSrc);
+        IEM_MC_STORE_XREG_HI_U64(((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg, uSrc);
+
+        IEM_MC_ADVANCE_RIP();
+        IEM_MC_END();
+    }
+    return VINF_SUCCESS;
+}
+
+
+/**
+ * @opcode      0x16
+ * @opcodesub   !11 mr/reg
+ * @oppfx       0x66
+ * @opcpuid     sse2
+ * @opgroup     og_sse2_pcksclr_datamove
+ * @opxcpttype  5
+ * @optest      op1=1 op2=2 -> op1=2
+ * @optest      op1=0 op2=-42 -> op1=-42
+ */
+FNIEMOP_DEF(iemOp_movhpd_Vdq_Mq)
+{
+    uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
+    if ((bRm & X86_MODRM_MOD_MASK) != (3 << X86_MODRM_MOD_SHIFT))
+    {
+        IEMOP_MNEMONIC2(RM_MEM, MOVHPD, movhpd, VqHi_WO, Mq, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZES);
+        IEM_MC_BEGIN(0, 2);
+        IEM_MC_LOCAL(uint64_t,                  uSrc);
+        IEM_MC_LOCAL(RTGCPTR,                   GCPtrEffSrc);
+
+        IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, bRm, 0);
+        IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
+        IEM_MC_MAYBE_RAISE_SSE2_RELATED_XCPT();
+        IEM_MC_ACTUALIZE_SSE_STATE_FOR_CHANGE();
+
+        IEM_MC_FETCH_MEM_U64(uSrc, pVCpu->iem.s.iEffSeg, GCPtrEffSrc);
+        IEM_MC_STORE_XREG_HI_U64(((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg, uSrc);
+
+        IEM_MC_ADVANCE_RIP();
+        IEM_MC_END();
+        return VINF_SUCCESS;
+    }
+
+    /**
+     * @opdone
+     * @opmnemonic  ud660f16m3
+     * @opcode      0x16
+     * @opcodesub   11 mr/reg
+     * @oppfx       0x66
+     * @opunused    immediate
+     * @opcpuid     sse
+     * @optest      ->
+     */
+    return IEMOP_RAISE_INVALID_OPCODE();
+}
+
+
+/**
+ * @opcode      0x16
+ * @oppfx       0xf3
+ * @opcpuid     sse3
+ * @opgroup     og_sse3_pcksclr_datamove
+ * @opxcpttype  4
+ * @optest      op1=-1 op2=0x00000002dddddddd00000001eeeeeeee ->
+ *              op1=0x00000002000000020000000100000001
+ */
+FNIEMOP_DEF(iemOp_movshdup_Vdq_Wdq)
+{
+    IEMOP_MNEMONIC2(RM, MOVSHDUP, movshdup, Vdq_WO, Wdq, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZES);
+    uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
+    if ((bRm & X86_MODRM_MOD_MASK) == (3 << X86_MODRM_MOD_SHIFT))
+    {
+        /*
+         * Register, register.
+         */
+        IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
+        IEM_MC_BEGIN(2, 0);
+        IEM_MC_ARG(PRTUINT128U,                 puDst, 0);
+        IEM_MC_ARG(PCRTUINT128U,                puSrc, 1);
+
+        IEM_MC_MAYBE_RAISE_SSE3_RELATED_XCPT();
+        IEM_MC_PREPARE_SSE_USAGE();
+
+        IEM_MC_REF_XREG_U128_CONST(puSrc, (bRm & X86_MODRM_RM_MASK) | pVCpu->iem.s.uRexB);
+        IEM_MC_REF_XREG_U128(puDst, ((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg);
+        IEM_MC_CALL_SSE_AIMPL_2(iemAImpl_movshdup, puDst, puSrc);
+
+        IEM_MC_ADVANCE_RIP();
+        IEM_MC_END();
+    }
+    else
+    {
+        /*
+         * Register, memory.
+         */
+        IEM_MC_BEGIN(2, 2);
+        IEM_MC_LOCAL(RTUINT128U,                uSrc);
+        IEM_MC_LOCAL(RTGCPTR,                   GCPtrEffSrc);
+        IEM_MC_ARG(PRTUINT128U,                 puDst, 0);
+        IEM_MC_ARG_LOCAL_REF(PCRTUINT128U,      puSrc, uSrc, 1);
+
+        IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, bRm, 0);
+        IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
+        IEM_MC_MAYBE_RAISE_SSE3_RELATED_XCPT();
+        IEM_MC_PREPARE_SSE_USAGE();
+
+        IEM_MC_FETCH_MEM_U128_ALIGN_SSE(uSrc, pVCpu->iem.s.iEffSeg, GCPtrEffSrc);
+        IEM_MC_REF_XREG_U128(puDst, ((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg);
+        IEM_MC_CALL_SSE_AIMPL_2(iemAImpl_movshdup, puDst, puSrc);
+
+        IEM_MC_ADVANCE_RIP();
+        IEM_MC_END();
+    }
+    return VINF_SUCCESS;
+}
+
+/**
+ * @opdone
+ * @opmnemonic  udf30f16
+ * @opcode      0x16
+ * @oppfx       0xf2
+ * @opunused    intel-modrm
+ * @opcpuid     sse
+ * @optest      ->
+ * @opdone
+ */
+
+
+/**
+ * @opcode      0x17
+ * @opcodesub   !11 mr/reg
+ * @oppfx       none
+ * @opcpuid     sse
+ * @opgroup     og_sse_simdfp_datamove
+ * @opxcpttype  5
+ * @optest      op1=1 op2=2 -> op1=2
+ * @optest      op1=0 op2=-42 -> op1=-42
+ */
+FNIEMOP_DEF(iemOp_movhps_Mq_Vq)
+{
+    uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
+    if ((bRm & X86_MODRM_MOD_MASK) != (3 << X86_MODRM_MOD_SHIFT))
+    {
+        IEMOP_MNEMONIC2(MR_MEM, MOVHPS, movhps, Mq_WO, VqHi, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZES);
+
+        IEM_MC_BEGIN(0, 2);
+        IEM_MC_LOCAL(uint64_t,                  uSrc);
+        IEM_MC_LOCAL(RTGCPTR,                   GCPtrEffSrc);
+
+        IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, bRm, 0);
+        IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
+        IEM_MC_MAYBE_RAISE_SSE_RELATED_XCPT();
+        IEM_MC_ACTUALIZE_SSE_STATE_FOR_READ();
+
+        IEM_MC_FETCH_XREG_HI_U64(uSrc, ((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg);
+        IEM_MC_STORE_MEM_U64(pVCpu->iem.s.iEffSeg, GCPtrEffSrc, uSrc);
+
+        IEM_MC_ADVANCE_RIP();
+        IEM_MC_END();
+        return VINF_SUCCESS;
+    }
+
+    /**
+     * @opdone
+     * @opmnemonic  ud0f17m3
+     * @opcode      0x17
+     * @opcodesub   11 mr/reg
+     * @oppfx       none
+     * @opunused    immediate
+     * @opcpuid     sse
+     * @optest      ->
+     */
+    return IEMOP_RAISE_INVALID_OPCODE();
+}
+
+
+/**
+ * @opcode      0x17
+ * @opcodesub   !11 mr/reg
+ * @oppfx       0x66
+ * @opcpuid     sse2
+ * @opgroup     og_sse2_pcksclr_datamove
+ * @opxcpttype  5
+ * @optest      op1=1 op2=2 -> op1=2
+ * @optest      op1=0 op2=-42 -> op1=-42
+ */
+FNIEMOP_DEF(iemOp_movhpd_Mq_Vq)
+{
+    uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
+    if ((bRm & X86_MODRM_MOD_MASK) != (3 << X86_MODRM_MOD_SHIFT))
+    {
+        IEMOP_MNEMONIC2(MR_MEM, MOVHPD, movhpd, Mq_WO, VqHi, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZES);
+
+        IEM_MC_BEGIN(0, 2);
+        IEM_MC_LOCAL(uint64_t,                  uSrc);
+        IEM_MC_LOCAL(RTGCPTR,                   GCPtrEffSrc);
+
+        IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, bRm, 0);
+        IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
+        IEM_MC_MAYBE_RAISE_SSE_RELATED_XCPT();
+        IEM_MC_ACTUALIZE_SSE_STATE_FOR_READ();
+
+        IEM_MC_FETCH_XREG_HI_U64(uSrc, ((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg);
+        IEM_MC_STORE_MEM_U64(pVCpu->iem.s.iEffSeg, GCPtrEffSrc, uSrc);
+
+        IEM_MC_ADVANCE_RIP();
+        IEM_MC_END();
+        return VINF_SUCCESS;
+    }
+
+    /**
+     * @opdone
+     * @opmnemonic  ud660f17m3
+     * @opcode      0x17
+     * @opcodesub   11 mr/reg
+     * @oppfx       0x66
+     * @opunused    immediate
+     * @opcpuid     sse
+     * @optest      ->
+     */
+    return IEMOP_RAISE_INVALID_OPCODE();
+}
+
+
+/**
+ * @opdone
+ * @opmnemonic  udf30f17
+ * @opcode      0x17
+ * @oppfx       0xf3
+ * @opunused    intel-modrm
+ * @opcpuid     sse
+ * @optest      ->
+ * @opdone
+ */
+
+/**
+ * @opmnemonic  udf20f17
+ * @opcode      0x17
+ * @oppfx       0xf2
+ * @opunused    intel-modrm
+ * @opcpuid     sse
+ * @optest      ->
+ * @opdone
+ */
+
+
+/** Opcode 0x0f 0x18. */
+FNIEMOP_DEF(iemOp_prefetch_Grp16)
+{
+    uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
+    if ((bRm & X86_MODRM_MOD_MASK) != (3 << X86_MODRM_MOD_SHIFT))
     {
         switch ((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK)
         {
@@ -1751,10 +2287,18 @@ FNIEMOP_DEF(iemOp_mov_Td_Rd)
 }
 
 
-/** Opcode      0x0f 0x28 - movaps Vps, Wps */
+/**
+ * @opcode      0x28
+ * @oppfx       none
+ * @opcpuid     sse
+ * @opgroup     og_sse_simdfp_datamove
+ * @opxcpttype  1
+ * @optest      op1=1 op2=2 -> op1=2
+ * @optest      op1=0 op2=-42 -> op1=-42
+ */
 FNIEMOP_DEF(iemOp_movaps_Vps_Wps)
 {
-    IEMOP_MNEMONIC(movaps_r_mr, "movaps r,mr");
+    IEMOP_MNEMONIC2(RM, MOVAPS, movaps, Vps_WO, Wps, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZES);
     uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
     if ((bRm & X86_MODRM_MOD_MASK) == (3 << X86_MODRM_MOD_SHIFT))
     {
@@ -1793,10 +2337,18 @@ FNIEMOP_DEF(iemOp_movaps_Vps_Wps)
     return VINF_SUCCESS;
 }
 
-/** Opcode 0x66 0x0f 0x28 - movapd Vpd, Wpd */
+/**
+ * @opcode      0x28
+ * @oppfx       66
+ * @opcpuid     sse2
+ * @opgroup     og_sse2_pcksclr_datamove
+ * @opxcpttype  1
+ * @optest      op1=1 op2=2 -> op1=2
+ * @optest      op1=0 op2=-42 -> op1=-42
+ */
 FNIEMOP_DEF(iemOp_movapd_Vpd_Wpd)
 {
-    IEMOP_MNEMONIC(movapd_r_mr, "movapd r,mr");
+    IEMOP_MNEMONIC2(RM, MOVAPD, movapd, Vpd_WO, Wpd, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZES);
     uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
     if ((bRm & X86_MODRM_MOD_MASK) == (3 << X86_MODRM_MOD_SHIFT))
     {
@@ -1838,10 +2390,18 @@ FNIEMOP_DEF(iemOp_movapd_Vpd_Wpd)
 /*  Opcode 0xf3 0x0f 0x28 - invalid */
 /*  Opcode 0xf2 0x0f 0x28 - invalid */
 
-/** Opcode      0x0f 0x29 - movaps Wps, Vps */
+/**
+ * @opcode      0x29
+ * @oppfx       none
+ * @opcpuid     sse
+ * @opgroup     og_sse_simdfp_datamove
+ * @opxcpttype  1
+ * @optest      op1=1 op2=2 -> op1=2
+ * @optest      op1=0 op2=-42 -> op1=-42
+ */
 FNIEMOP_DEF(iemOp_movaps_Wps_Vps)
 {
-    IEMOP_MNEMONIC(movaps_mr_r, "movaps Wps,Vps");
+    IEMOP_MNEMONIC2(MR, MOVAPS, movaps, Wps_WO, Vps, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZES);
     uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
     if ((bRm & X86_MODRM_MOD_MASK) == (3 << X86_MODRM_MOD_SHIFT))
     {
@@ -1880,10 +2440,18 @@ FNIEMOP_DEF(iemOp_movaps_Wps_Vps)
     return VINF_SUCCESS;
 }
 
-/** Opcode 0x66 0x0f 0x29 - movapd Wpd,Vpd */
+/**
+ * @opcode      0x29
+ * @oppfx       66
+ * @opcpuid     sse2
+ * @opgroup     og_sse2_pcksclr_datamove
+ * @opxcpttype  1
+ * @optest      op1=1 op2=2 -> op1=2
+ * @optest      op1=0 op2=-42 -> op1=-42
+ */
 FNIEMOP_DEF(iemOp_movapd_Wpd_Vpd)
 {
-    IEMOP_MNEMONIC(movapd_mr_r, "movapd Wpd,Vpd");
+    IEMOP_MNEMONIC2(MR, MOVAPD, movapd, Wpd_WO, Vpd, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZES);
     uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
     if ((bRm & X86_MODRM_MOD_MASK) == (3 << X86_MODRM_MOD_SHIFT))
     {
@@ -1936,10 +2504,19 @@ FNIEMOP_STUB(iemOp_cvtsi2ss_Vss_Ey); //NEXT
 FNIEMOP_STUB(iemOp_cvtsi2sd_Vsd_Ey); //NEXT
 
 
-/** Opcode      0x0f 0x2b - vmovntps Mps, Vps */
+/**
+ * @opcode      0x2b
+ * @opcodesub   !11 mr/reg
+ * @oppfx       none
+ * @opcpuid     sse
+ * @opgroup     og_sse1_cachect
+ * @opxcpttype  1
+ * @optest      op1=1 op2=2 -> op1=2
+ * @optest      op1=0 op2=-42 -> op1=-42
+ */
 FNIEMOP_DEF(iemOp_movntps_Mps_Vps)
 {
-    IEMOP_MNEMONIC(movntps_mr_r, "movntps Mps,Vps");
+    IEMOP_MNEMONIC2(MR_MEM, MOVNTPS, movntps, Mps_WO, Vps, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZES);
     uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
     if ((bRm & X86_MODRM_MOD_MASK) != (3 << X86_MODRM_MOD_SHIFT))
     {
@@ -1967,10 +2544,19 @@ FNIEMOP_DEF(iemOp_movntps_Mps_Vps)
     return VINF_SUCCESS;
 }
 
-/** Opcode 0x66 0x0f 0x2b - movntpd Mpd, Vpd */
+/**
+ * @opcode      0x2b
+ * @opcodesub   !11 mr/reg
+ * @oppfx       0x66
+ * @opcpuid     sse2
+ * @opgroup     og_sse2_cachect
+ * @opxcpttype  1
+ * @optest      op1=1 op2=2 -> op1=2
+ * @optest      op1=0 op2=-42 -> op1=-42
+ */
 FNIEMOP_DEF(iemOp_movntpd_Mpd_Vpd)
 {
-    IEMOP_MNEMONIC(movntpd_mr_r, "movntpd Mdq,Vpd");
+    IEMOP_MNEMONIC2(MR_MEM, MOVNTPD, movntpd, Mpd_WO, Vpd, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZES);
     uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
     if ((bRm & X86_MODRM_MOD_MASK) != (3 << X86_MODRM_MOD_SHIFT))
     {
@@ -2863,110 +3449,214 @@ FNIEMOP_DEF(iemOp_punpckhqdq_Vx_W)
 /*  Opcode 0xf3 0x0f 0x6d - invalid */
 
 
-/** Opcode      0x0f 0x6e - movd/q Pd, Ey */
 FNIEMOP_DEF(iemOp_movd_q_Pd_Ey)
 {
     uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
     if (pVCpu->iem.s.fPrefixes & IEM_OP_PRF_SIZE_REX_W)
-        IEMOP_MNEMONIC(movq_Pq_Eq, "movq Pq,Eq");
-    else
-        IEMOP_MNEMONIC(movd_Pd_Ed, "movd Pd,Ed");
-    if ((bRm & X86_MODRM_MOD_MASK) == (3 << X86_MODRM_MOD_SHIFT))
     {
-        /* MMX, greg */
-        IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
-        IEM_MC_BEGIN(0, 1);
-        IEM_MC_MAYBE_RAISE_MMX_RELATED_XCPT();
-        IEM_MC_ACTUALIZE_FPU_STATE_FOR_CHANGE();
-        IEM_MC_LOCAL(uint64_t, u64Tmp);
-        if (pVCpu->iem.s.fPrefixes & IEM_OP_PRF_SIZE_REX_W)
+        /**
+         * @opcode      0x6e
+         * @opcodesub   rex.w=1
+         * @oppfx       none
+         * @opcpuid     mmx
+         * @opgroup     og_mmx_datamove
+         * @opxcpttype  5
+         * @optest      64-bit / op1=1 op2=2   -> op1=2   ftw=0xff
+         * @optest      64-bit / op1=0 op2=-42 -> op1=-42 ftw=0xff
+         */
+        IEMOP_MNEMONIC2(RM, MOVQ, movq, Pq_WO, Eq, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OZ_PFX);
+        if ((bRm & X86_MODRM_MOD_MASK) == (3 << X86_MODRM_MOD_SHIFT))
+        {
+            /* MMX, greg64 */
+            IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
+            IEM_MC_BEGIN(0, 1);
+            IEM_MC_LOCAL(uint64_t, u64Tmp);
+
+            IEM_MC_MAYBE_RAISE_MMX_RELATED_XCPT();
+            IEM_MC_ACTUALIZE_FPU_STATE_FOR_CHANGE();
+
             IEM_MC_FETCH_GREG_U64(u64Tmp, (bRm & X86_MODRM_RM_MASK) | pVCpu->iem.s.uRexB);
+            IEM_MC_STORE_MREG_U64((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK, u64Tmp);
+            IEM_MC_FPU_TO_MMX_MODE();
+
+            IEM_MC_ADVANCE_RIP();
+            IEM_MC_END();
+        }
         else
-            IEM_MC_FETCH_GREG_U32_ZX_U64(u64Tmp, (bRm & X86_MODRM_RM_MASK) | pVCpu->iem.s.uRexB);
-        IEM_MC_STORE_MREG_U64((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK, u64Tmp);
-        IEM_MC_ADVANCE_RIP();
-        IEM_MC_END();
+        {
+            /* MMX, [mem64] */
+            IEM_MC_BEGIN(0, 2);
+            IEM_MC_LOCAL(RTGCPTR, GCPtrEffSrc);
+            IEM_MC_LOCAL(uint64_t, u64Tmp);
+
+            IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, bRm, 0);
+            IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
+            IEM_MC_MAYBE_RAISE_MMX_RELATED_XCPT();
+            IEM_MC_ACTUALIZE_FPU_STATE_FOR_CHANGE();
+
+            IEM_MC_FETCH_MEM_U64(u64Tmp, pVCpu->iem.s.iEffSeg, GCPtrEffSrc);
+            IEM_MC_STORE_MREG_U64((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK, u64Tmp);
+            IEM_MC_FPU_TO_MMX_MODE();
+
+            IEM_MC_ADVANCE_RIP();
+            IEM_MC_END();
+        }
     }
     else
     {
-        /* MMX, [mem] */
-        IEM_MC_BEGIN(0, 2);
-        IEM_MC_LOCAL(RTGCPTR, GCPtrEffSrc);
-        IEM_MC_MAYBE_RAISE_MMX_RELATED_XCPT();
-        IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, bRm, 1);
-        IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
-        IEM_MC_ACTUALIZE_FPU_STATE_FOR_CHANGE();
-        if (pVCpu->iem.s.fPrefixes & IEM_OP_PRF_SIZE_REX_W)
+        /**
+         * @opdone
+         * @opcode      0x6e
+         * @opcodesub   rex.w=0
+         * @oppfx       none
+         * @opcpuid     mmx
+         * @opgroup     og_mmx_datamove
+         * @opxcpttype  5
+         * @opfunction  iemOp_movd_q_Pd_Ey
+         * @optest      op1=1 op2=2   -> op1=2   ftw=0xff
+         * @optest      op1=0 op2=-42 -> op1=-42 ftw=0xff
+         */
+        IEMOP_MNEMONIC2(RM, MOVD, movd, PdZx_WO, Ed, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OZ_PFX);
+        if ((bRm & X86_MODRM_MOD_MASK) == (3 << X86_MODRM_MOD_SHIFT))
         {
+            /* MMX, greg */
+            IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
+            IEM_MC_BEGIN(0, 1);
             IEM_MC_LOCAL(uint64_t, u64Tmp);
-            IEM_MC_FETCH_MEM_U64(u64Tmp, pVCpu->iem.s.iEffSeg, GCPtrEffSrc);
+
+            IEM_MC_MAYBE_RAISE_MMX_RELATED_XCPT();
+            IEM_MC_ACTUALIZE_FPU_STATE_FOR_CHANGE();
+
+            IEM_MC_FETCH_GREG_U32_ZX_U64(u64Tmp, (bRm & X86_MODRM_RM_MASK) | pVCpu->iem.s.uRexB);
             IEM_MC_STORE_MREG_U64((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK, u64Tmp);
+            IEM_MC_FPU_TO_MMX_MODE();
+
+            IEM_MC_ADVANCE_RIP();
+            IEM_MC_END();
         }
         else
         {
+            /* MMX, [mem] */
+            IEM_MC_BEGIN(0, 2);
+            IEM_MC_LOCAL(RTGCPTR, GCPtrEffSrc);
             IEM_MC_LOCAL(uint32_t, u32Tmp);
+
+            IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, bRm, 0);
+            IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
+            IEM_MC_MAYBE_RAISE_MMX_RELATED_XCPT();
+            IEM_MC_ACTUALIZE_FPU_STATE_FOR_CHANGE();
+
             IEM_MC_FETCH_MEM_U32(u32Tmp, pVCpu->iem.s.iEffSeg, GCPtrEffSrc);
             IEM_MC_STORE_MREG_U32_ZX_U64((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK, u32Tmp);
+            IEM_MC_FPU_TO_MMX_MODE();
+
+            IEM_MC_ADVANCE_RIP();
+            IEM_MC_END();
         }
-        IEM_MC_ADVANCE_RIP();
-        IEM_MC_END();
     }
     return VINF_SUCCESS;
 }
 
-/** Opcode 0x66 0x0f 0x6e - movd/q Vy, Ey */
 FNIEMOP_DEF(iemOp_movd_q_Vy_Ey)
 {
     uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
     if (pVCpu->iem.s.fPrefixes & IEM_OP_PRF_SIZE_REX_W)
-        IEMOP_MNEMONIC(movdq_Wq_Eq, "movq Wq,Eq");
-    else
-        IEMOP_MNEMONIC(movdq_Wd_Ed, "movd Wd,Ed");
-    if ((bRm & X86_MODRM_MOD_MASK) == (3 << X86_MODRM_MOD_SHIFT))
     {
-        /* XMM, greg*/
-        IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
-        IEM_MC_BEGIN(0, 1);
-        IEM_MC_MAYBE_RAISE_SSE2_RELATED_XCPT();
-        IEM_MC_ACTUALIZE_SSE_STATE_FOR_CHANGE();
-        if (pVCpu->iem.s.fPrefixes & IEM_OP_PRF_SIZE_REX_W)
+        /**
+         * @opcode      0x6e
+         * @opcodesub   rex.w=1
+         * @oppfx       0x66
+         * @opcpuid     sse2
+         * @opgroup     og_sse2_simdint_datamove
+         * @opxcpttype  5
+         * @optest      64-bit / op1=1 op2=2   -> op1=2
+         * @optest      64-bit / op1=0 op2=-42 -> op1=-42
+         */
+        IEMOP_MNEMONIC2(RM, MOVQ, movq, VqZx_WO, Eq, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OZ_PFX);
+        if ((bRm & X86_MODRM_MOD_MASK) == (3 << X86_MODRM_MOD_SHIFT))
         {
+            /* XMM, greg64 */
+            IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
+            IEM_MC_BEGIN(0, 1);
             IEM_MC_LOCAL(uint64_t, u64Tmp);
+
+            IEM_MC_MAYBE_RAISE_SSE2_RELATED_XCPT();
+            IEM_MC_ACTUALIZE_SSE_STATE_FOR_CHANGE();
+
             IEM_MC_FETCH_GREG_U64(u64Tmp, (bRm & X86_MODRM_RM_MASK) | pVCpu->iem.s.uRexB);
             IEM_MC_STORE_XREG_U64_ZX_U128(((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg, u64Tmp);
+
+            IEM_MC_ADVANCE_RIP();
+            IEM_MC_END();
         }
         else
         {
-            IEM_MC_LOCAL(uint32_t, u32Tmp);
-            IEM_MC_FETCH_GREG_U32(u32Tmp, (bRm & X86_MODRM_RM_MASK) | pVCpu->iem.s.uRexB);
-            IEM_MC_STORE_XREG_U32_ZX_U128(((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg, u32Tmp);
+            /* XMM, [mem64] */
+            IEM_MC_BEGIN(0, 2);
+            IEM_MC_LOCAL(RTGCPTR, GCPtrEffSrc);
+            IEM_MC_LOCAL(uint64_t, u64Tmp);
+
+            IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, bRm, 0);
+            IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
+            IEM_MC_MAYBE_RAISE_SSE2_RELATED_XCPT();
+            IEM_MC_ACTUALIZE_SSE_STATE_FOR_CHANGE();
+
+            IEM_MC_FETCH_MEM_U64(u64Tmp, pVCpu->iem.s.iEffSeg, GCPtrEffSrc);
+            IEM_MC_STORE_XREG_U64_ZX_U128(((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg, u64Tmp);
+
+            IEM_MC_ADVANCE_RIP();
+            IEM_MC_END();
         }
-        IEM_MC_ADVANCE_RIP();
-        IEM_MC_END();
     }
     else
     {
-        /* XMM, [mem] */
-        IEM_MC_BEGIN(0, 2);
-        IEM_MC_LOCAL(RTGCPTR, GCPtrEffSrc);
-        IEM_MC_MAYBE_RAISE_SSE2_RELATED_XCPT(); /** @todo order */
-        IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, bRm, 1);
-        IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
-        IEM_MC_ACTUALIZE_SSE_STATE_FOR_CHANGE();
-        if (pVCpu->iem.s.fPrefixes & IEM_OP_PRF_SIZE_REX_W)
+        /**
+         * @opdone
+         * @opcode      0x6e
+         * @opcodesub   rex.w=0
+         * @oppfx       0x66
+         * @opcpuid     sse2
+         * @opgroup     og_sse2_simdint_datamove
+         * @opxcpttype  5
+         * @opfunction  iemOp_movd_q_Vy_Ey
+         * @optest      op1=1 op2=2   -> op1=2
+         * @optest      op1=0 op2=-42 -> op1=-42
+         */
+        IEMOP_MNEMONIC2(RM, MOVD, movd, VdZx_WO, Ed, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OZ_PFX);
+        if ((bRm & X86_MODRM_MOD_MASK) == (3 << X86_MODRM_MOD_SHIFT))
         {
-            IEM_MC_LOCAL(uint64_t, u64Tmp);
-            IEM_MC_FETCH_MEM_U64(u64Tmp, pVCpu->iem.s.iEffSeg, GCPtrEffSrc);
-            IEM_MC_STORE_XREG_U64_ZX_U128(((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg, u64Tmp);
+            /* XMM, greg32 */
+            IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
+            IEM_MC_BEGIN(0, 1);
+            IEM_MC_LOCAL(uint32_t, u32Tmp);
+
+            IEM_MC_MAYBE_RAISE_SSE2_RELATED_XCPT();
+            IEM_MC_ACTUALIZE_SSE_STATE_FOR_CHANGE();
+
+            IEM_MC_FETCH_GREG_U32(u32Tmp, (bRm & X86_MODRM_RM_MASK) | pVCpu->iem.s.uRexB);
+            IEM_MC_STORE_XREG_U32_ZX_U128(((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg, u32Tmp);
+
+            IEM_MC_ADVANCE_RIP();
+            IEM_MC_END();
         }
         else
         {
+            /* XMM, [mem32] */
+            IEM_MC_BEGIN(0, 2);
+            IEM_MC_LOCAL(RTGCPTR, GCPtrEffSrc);
             IEM_MC_LOCAL(uint32_t, u32Tmp);
+
+            IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, bRm, 0);
+            IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
+            IEM_MC_MAYBE_RAISE_SSE2_RELATED_XCPT();
+            IEM_MC_ACTUALIZE_SSE_STATE_FOR_CHANGE();
+
             IEM_MC_FETCH_MEM_U32(u32Tmp, pVCpu->iem.s.iEffSeg, GCPtrEffSrc);
             IEM_MC_STORE_XREG_U32_ZX_U128(((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg, u32Tmp);
+
+            IEM_MC_ADVANCE_RIP();
+            IEM_MC_END();
         }
-        IEM_MC_ADVANCE_RIP();
-        IEM_MC_END();
     }
     return VINF_SUCCESS;
 }
@@ -2974,25 +3664,35 @@ FNIEMOP_DEF(iemOp_movd_q_Vy_Ey)
 /*  Opcode 0xf3 0x0f 0x6e - invalid */
 
 
-/** Opcode      0x0f 0x6f - movq Pq, Qq */
+/**
+ * @opcode      0x6f
+ * @oppfx       none
+ * @opcpuid     mmx
+ * @opgroup     og_mmx_datamove
+ * @opxcpttype  5
+ * @optest      op1=1 op2=2   -> op1=2   ftw=0xff
+ * @optest      op1=0 op2=-42 -> op1=-42 ftw=0xff
+ */
 FNIEMOP_DEF(iemOp_movq_Pq_Qq)
 {
+    IEMOP_MNEMONIC2(RM, MOVD, movd, Pq_WO, Qq, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZES);
     uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
-    IEMOP_MNEMONIC(movq_Pq_Qq, "movq Pq,Qq");
     if ((bRm & X86_MODRM_MOD_MASK) == (3 << X86_MODRM_MOD_SHIFT))
     {
         /*
          * Register, register.
          */
-        /** @todo testcase: REX.B / REX.R and MMX register indexing. Ignored? */
-        /** @todo testcase: REX.B / REX.R and segment register indexing. Ignored? */
         IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
         IEM_MC_BEGIN(0, 1);
         IEM_MC_LOCAL(uint64_t, u64Tmp);
+
         IEM_MC_MAYBE_RAISE_MMX_RELATED_XCPT();
         IEM_MC_ACTUALIZE_FPU_STATE_FOR_CHANGE();
+
         IEM_MC_FETCH_MREG_U64(u64Tmp, bRm & X86_MODRM_RM_MASK);
         IEM_MC_STORE_MREG_U64((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK, u64Tmp);
+        IEM_MC_FPU_TO_MMX_MODE();
+
         IEM_MC_ADVANCE_RIP();
         IEM_MC_END();
     }
@@ -3009,8 +3709,10 @@ FNIEMOP_DEF(iemOp_movq_Pq_Qq)
         IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
         IEM_MC_MAYBE_RAISE_MMX_RELATED_XCPT();
         IEM_MC_ACTUALIZE_FPU_STATE_FOR_CHANGE();
+
         IEM_MC_FETCH_MEM_U64(u64Tmp, pVCpu->iem.s.iEffSeg, GCPtrEffSrc);
         IEM_MC_STORE_MREG_U64((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK, u64Tmp);
+        IEM_MC_FPU_TO_MMX_MODE();
 
         IEM_MC_ADVANCE_RIP();
         IEM_MC_END();
@@ -3018,11 +3720,19 @@ FNIEMOP_DEF(iemOp_movq_Pq_Qq)
     return VINF_SUCCESS;
 }
 
-/** Opcode 0x66 0x0f 0x6f - movdqa Vx, Wx */
-FNIEMOP_DEF(iemOp_movdqa_Vx_Wx)
+/**
+ * @opcode      0x6f
+ * @oppfx       0x66
+ * @opcpuid     sse2
+ * @opgroup     og_sse2_simdint_datamove
+ * @opxcpttype  1
+ * @optest      op1=1 op2=2   -> op1=2
+ * @optest      op1=0 op2=-42 -> op1=-42
+ */
+FNIEMOP_DEF(iemOp_movdqa_Vdq_Wdq)
 {
+    IEMOP_MNEMONIC2(RM, MOVDQA, movdqa, Vdq_WO, Wdq, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZES);
     uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
-    IEMOP_MNEMONIC(movdqa_Vdq_Wdq, "movdqa Vdq,Wdq");
     if ((bRm & X86_MODRM_MOD_MASK) == (3 << X86_MODRM_MOD_SHIFT))
     {
         /*
@@ -3030,8 +3740,10 @@ FNIEMOP_DEF(iemOp_movdqa_Vx_Wx)
          */
         IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
         IEM_MC_BEGIN(0, 0);
+
         IEM_MC_MAYBE_RAISE_SSE2_RELATED_XCPT();
         IEM_MC_ACTUALIZE_SSE_STATE_FOR_CHANGE();
+
         IEM_MC_COPY_XREG_U128(((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg,
                               (bRm & X86_MODRM_RM_MASK) | pVCpu->iem.s.uRexB);
         IEM_MC_ADVANCE_RIP();
@@ -3050,6 +3762,7 @@ FNIEMOP_DEF(iemOp_movdqa_Vx_Wx)
         IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
         IEM_MC_MAYBE_RAISE_SSE2_RELATED_XCPT();
         IEM_MC_ACTUALIZE_SSE_STATE_FOR_CHANGE();
+
         IEM_MC_FETCH_MEM_U128_ALIGN_SSE(u128Tmp, pVCpu->iem.s.iEffSeg, GCPtrEffSrc);
         IEM_MC_STORE_XREG_U128(((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg, u128Tmp);
 
@@ -3059,11 +3772,19 @@ FNIEMOP_DEF(iemOp_movdqa_Vx_Wx)
     return VINF_SUCCESS;
 }
 
-/** Opcode 0xf3 0x0f 0x6f - movdqu Vx, Wx */
-FNIEMOP_DEF(iemOp_movdqu_Vx_Wx)
+/**
+ * @opcode      0x6f
+ * @oppfx       0xf3
+ * @opcpuid     sse2
+ * @opgroup     og_sse2_simdint_datamove
+ * @opxcpttype  4UA
+ * @optest      op1=1 op2=2   -> op1=2
+ * @optest      op1=0 op2=-42 -> op1=-42
+ */
+FNIEMOP_DEF(iemOp_movdqu_Vdq_Wdq)
 {
+    IEMOP_MNEMONIC2(RM, MOVDQU, movdqu, Vdq_WO, Wdq, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZES);
     uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
-    IEMOP_MNEMONIC(movdqu_Vdq_Wdq, "movdqu Vdq,Wdq");
     if ((bRm & X86_MODRM_MOD_MASK) == (3 << X86_MODRM_MOD_SHIFT))
     {
         /*
@@ -3646,137 +4367,291 @@ FNIEMOP_STUB(iemOp_vmwrite_Gy_Ey);
 /*  Opcode 0xf3 0x0f 0x7b - invalid */
 /*  Opcode 0xf2 0x0f 0x7b - invalid */
 
-/*  Opcode      0x0f 0x7c - invalid */
-/** Opcode 0x66 0x0f 0x7c - haddpd Vpd, Wpd */
-FNIEMOP_STUB(iemOp_haddpd_Vpd_Wpd);
-/*  Opcode 0xf3 0x0f 0x7c - invalid */
-/** Opcode 0xf2 0x0f 0x7c - haddps Vps, Wps */
-FNIEMOP_STUB(iemOp_haddps_Vps_Wps);
+/*  Opcode      0x0f 0x7c - invalid */
+/** Opcode 0x66 0x0f 0x7c - haddpd Vpd, Wpd */
+FNIEMOP_STUB(iemOp_haddpd_Vpd_Wpd);
+/*  Opcode 0xf3 0x0f 0x7c - invalid */
+/** Opcode 0xf2 0x0f 0x7c - haddps Vps, Wps */
+FNIEMOP_STUB(iemOp_haddps_Vps_Wps);
+
+/*  Opcode      0x0f 0x7d - invalid */
+/** Opcode 0x66 0x0f 0x7d - hsubpd Vpd, Wpd */
+FNIEMOP_STUB(iemOp_hsubpd_Vpd_Wpd);
+/*  Opcode 0xf3 0x0f 0x7d - invalid */
+/** Opcode 0xf2 0x0f 0x7d - hsubps Vps, Wps */
+FNIEMOP_STUB(iemOp_hsubps_Vps_Wps);
+
+
+/** Opcode      0x0f 0x7e - movd_q Ey, Pd */
+FNIEMOP_DEF(iemOp_movd_q_Ey_Pd)
+{
+    uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
+    if (pVCpu->iem.s.fPrefixes & IEM_OP_PRF_SIZE_REX_W)
+    {
+        /**
+         * @opcode      0x7e
+         * @opcodesub   rex.w=1
+         * @oppfx       none
+         * @opcpuid     mmx
+         * @opgroup     og_mmx_datamove
+         * @opxcpttype  5
+         * @optest      64-bit / op1=1 op2=2   -> op1=2   ftw=0xff
+         * @optest      64-bit / op1=0 op2=-42 -> op1=-42 ftw=0xff
+         */
+        IEMOP_MNEMONIC2(MR, MOVQ, movq, Eq_WO, Pq, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OZ_PFX);
+        if ((bRm & X86_MODRM_MOD_MASK) == (3 << X86_MODRM_MOD_SHIFT))
+        {
+            /* greg64, MMX */
+            IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
+            IEM_MC_BEGIN(0, 1);
+            IEM_MC_LOCAL(uint64_t, u64Tmp);
+
+            IEM_MC_MAYBE_RAISE_MMX_RELATED_XCPT();
+            IEM_MC_ACTUALIZE_FPU_STATE_FOR_CHANGE();
+
+            IEM_MC_FETCH_MREG_U64(u64Tmp, (bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK);
+            IEM_MC_STORE_GREG_U64((bRm & X86_MODRM_RM_MASK) | pVCpu->iem.s.uRexB, u64Tmp);
+            IEM_MC_FPU_TO_MMX_MODE();
+
+            IEM_MC_ADVANCE_RIP();
+            IEM_MC_END();
+        }
+        else
+        {
+            /* [mem64], MMX */
+            IEM_MC_BEGIN(0, 2);
+            IEM_MC_LOCAL(RTGCPTR, GCPtrEffSrc);
+            IEM_MC_LOCAL(uint64_t, u64Tmp);
+
+            IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, bRm, 0);
+            IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
+            IEM_MC_MAYBE_RAISE_MMX_RELATED_XCPT();
+            IEM_MC_ACTUALIZE_FPU_STATE_FOR_CHANGE();
+
+            IEM_MC_FETCH_MREG_U64(u64Tmp, (bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK);
+            IEM_MC_STORE_MEM_U64(pVCpu->iem.s.iEffSeg, GCPtrEffSrc, u64Tmp);
+            IEM_MC_FPU_TO_MMX_MODE();
+
+            IEM_MC_ADVANCE_RIP();
+            IEM_MC_END();
+        }
+    }
+    else
+    {
+        /**
+         * @opdone
+         * @opcode      0x7e
+         * @opcodesub   rex.w=0
+         * @oppfx       none
+         * @opcpuid     mmx
+         * @opgroup     og_mmx_datamove
+         * @opxcpttype  5
+         * @opfunction  iemOp_movd_q_Pd_Ey
+         * @optest      op1=1 op2=2   -> op1=2   ftw=0xff
+         * @optest      op1=0 op2=-42 -> op1=-42 ftw=0xff
+         */
+        IEMOP_MNEMONIC2(MR, MOVD, movd, Ed_WO, Pd, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OZ_PFX);
+        if ((bRm & X86_MODRM_MOD_MASK) == (3 << X86_MODRM_MOD_SHIFT))
+        {
+            /* greg32, MMX */
+            IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
+            IEM_MC_BEGIN(0, 1);
+            IEM_MC_LOCAL(uint32_t, u32Tmp);
+
+            IEM_MC_MAYBE_RAISE_MMX_RELATED_XCPT();
+            IEM_MC_ACTUALIZE_FPU_STATE_FOR_CHANGE();
+
+            IEM_MC_FETCH_MREG_U32(u32Tmp, (bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK);
+            IEM_MC_STORE_GREG_U32((bRm & X86_MODRM_RM_MASK) | pVCpu->iem.s.uRexB, u32Tmp);
+            IEM_MC_FPU_TO_MMX_MODE();
+
+            IEM_MC_ADVANCE_RIP();
+            IEM_MC_END();
+        }
+        else
+        {
+            /* [mem32], MMX */
+            IEM_MC_BEGIN(0, 2);
+            IEM_MC_LOCAL(RTGCPTR, GCPtrEffSrc);
+            IEM_MC_LOCAL(uint32_t, u32Tmp);
+
+            IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, bRm, 0);
+            IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
+            IEM_MC_MAYBE_RAISE_MMX_RELATED_XCPT();
+            IEM_MC_ACTUALIZE_FPU_STATE_FOR_CHANGE();
+
+            IEM_MC_FETCH_MREG_U32(u32Tmp, (bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK);
+            IEM_MC_STORE_MEM_U32(pVCpu->iem.s.iEffSeg, GCPtrEffSrc, u32Tmp);
+            IEM_MC_FPU_TO_MMX_MODE();
 
-/*  Opcode      0x0f 0x7d - invalid */
-/** Opcode 0x66 0x0f 0x7d - hsubpd Vpd, Wpd */
-FNIEMOP_STUB(iemOp_hsubpd_Vpd_Wpd);
-/*  Opcode 0xf3 0x0f 0x7d - invalid */
-/** Opcode 0xf2 0x0f 0x7d - hsubps Vps, Wps */
-FNIEMOP_STUB(iemOp_hsubps_Vps_Wps);
+            IEM_MC_ADVANCE_RIP();
+            IEM_MC_END();
+        }
+    }
+    return VINF_SUCCESS;
 
+}
 
-/** Opcode      0x0f 0x7e - movd_q Ey, Pd */
-FNIEMOP_DEF(iemOp_movd_q_Ey_Pd)
+
+FNIEMOP_DEF(iemOp_movd_q_Ey_Vy)
 {
     uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
     if (pVCpu->iem.s.fPrefixes & IEM_OP_PRF_SIZE_REX_W)
-        IEMOP_MNEMONIC(movq_Eq_Pq, "movq Eq,Pq");
-    else
-        IEMOP_MNEMONIC(movd_Ed_Pd, "movd Ed,Pd");
-    if ((bRm & X86_MODRM_MOD_MASK) == (3 << X86_MODRM_MOD_SHIFT))
     {
-        /* greg, MMX */
-        IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
-        IEM_MC_BEGIN(0, 1);
-        IEM_MC_MAYBE_RAISE_MMX_RELATED_XCPT();
-        IEM_MC_ACTUALIZE_FPU_STATE_FOR_READ();
-        if (pVCpu->iem.s.fPrefixes & IEM_OP_PRF_SIZE_REX_W)
+        /**
+         * @opcode      0x7e
+         * @opcodesub   rex.w=1
+         * @oppfx       0x66
+         * @opcpuid     sse2
+         * @opgroup     og_sse2_simdint_datamove
+         * @opxcpttype  5
+         * @optest      64-bit / op1=1 op2=2   -> op1=2
+         * @optest      64-bit / op1=0 op2=-42 -> op1=-42
+         */
+        IEMOP_MNEMONIC2(MR, MOVQ, movq, Eq_WO, Vq, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OZ_PFX);
+        if ((bRm & X86_MODRM_MOD_MASK) == (3 << X86_MODRM_MOD_SHIFT))
         {
+            /* greg64, XMM */
+            IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
+            IEM_MC_BEGIN(0, 1);
             IEM_MC_LOCAL(uint64_t, u64Tmp);
-            IEM_MC_FETCH_MREG_U64(u64Tmp, (bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK);
+
+            IEM_MC_MAYBE_RAISE_SSE2_RELATED_XCPT();
+            IEM_MC_ACTUALIZE_SSE_STATE_FOR_READ();
+
+            IEM_MC_FETCH_XREG_U64(u64Tmp, ((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg);
             IEM_MC_STORE_GREG_U64((bRm & X86_MODRM_RM_MASK) | pVCpu->iem.s.uRexB, u64Tmp);
+
+            IEM_MC_ADVANCE_RIP();
+            IEM_MC_END();
         }
         else
         {
-            IEM_MC_LOCAL(uint32_t, u32Tmp);
-            IEM_MC_FETCH_MREG_U32(u32Tmp, (bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK);
-            IEM_MC_STORE_GREG_U32((bRm & X86_MODRM_RM_MASK) | pVCpu->iem.s.uRexB, u32Tmp);
+            /* [mem64], XMM */
+            IEM_MC_BEGIN(0, 2);
+            IEM_MC_LOCAL(RTGCPTR, GCPtrEffSrc);
+            IEM_MC_LOCAL(uint64_t, u64Tmp);
+
+            IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, bRm, 0);
+            IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
+            IEM_MC_MAYBE_RAISE_SSE2_RELATED_XCPT();
+            IEM_MC_ACTUALIZE_SSE_STATE_FOR_READ();
+
+            IEM_MC_FETCH_XREG_U64(u64Tmp, ((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg);
+            IEM_MC_STORE_MEM_U64(pVCpu->iem.s.iEffSeg, GCPtrEffSrc, u64Tmp);
+
+            IEM_MC_ADVANCE_RIP();
+            IEM_MC_END();
         }
-        IEM_MC_ADVANCE_RIP();
-        IEM_MC_END();
     }
     else
     {
-        /* [mem], MMX */
-        IEM_MC_BEGIN(0, 2);
-        IEM_MC_LOCAL(RTGCPTR, GCPtrEffSrc);
-        IEM_MC_MAYBE_RAISE_MMX_RELATED_XCPT();
-        IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, bRm, 1);
-        IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
-        IEM_MC_ACTUALIZE_FPU_STATE_FOR_READ();
-        if (pVCpu->iem.s.fPrefixes & IEM_OP_PRF_SIZE_REX_W)
+        /**
+         * @opdone
+         * @opcode      0x7e
+         * @opcodesub   rex.w=0
+         * @oppfx       0x66
+         * @opcpuid     sse2
+         * @opgroup     og_sse2_simdint_datamove
+         * @opxcpttype  5
+         * @opfunction  iemOp_movd_q_Vy_Ey
+         * @optest      op1=1 op2=2   -> op1=2
+         * @optest      op1=0 op2=-42 -> op1=-42
+         */
+        IEMOP_MNEMONIC2(MR, MOVD, movd, Ed_WO, Vd, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OZ_PFX);
+        if ((bRm & X86_MODRM_MOD_MASK) == (3 << X86_MODRM_MOD_SHIFT))
         {
-            IEM_MC_LOCAL(uint64_t, u64Tmp);
-            IEM_MC_FETCH_MREG_U64(u64Tmp, (bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK);
-            IEM_MC_STORE_MEM_U64(pVCpu->iem.s.iEffSeg, GCPtrEffSrc, u64Tmp);
+            /* greg32, XMM */
+            IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
+            IEM_MC_BEGIN(0, 1);
+            IEM_MC_LOCAL(uint32_t, u32Tmp);
+
+            IEM_MC_MAYBE_RAISE_SSE2_RELATED_XCPT();
+            IEM_MC_ACTUALIZE_SSE_STATE_FOR_READ();
+
+            IEM_MC_FETCH_XREG_U32(u32Tmp, ((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg);
+            IEM_MC_STORE_GREG_U32((bRm & X86_MODRM_RM_MASK) | pVCpu->iem.s.uRexB, u32Tmp);
+
+            IEM_MC_ADVANCE_RIP();
+            IEM_MC_END();
         }
         else
         {
+            /* [mem32], XMM */
+            IEM_MC_BEGIN(0, 2);
+            IEM_MC_LOCAL(RTGCPTR, GCPtrEffSrc);
             IEM_MC_LOCAL(uint32_t, u32Tmp);
-            IEM_MC_FETCH_MREG_U32(u32Tmp, (bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK);
+
+            IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, bRm, 0);
+            IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
+            IEM_MC_MAYBE_RAISE_SSE2_RELATED_XCPT();
+            IEM_MC_ACTUALIZE_SSE_STATE_FOR_READ();
+
+            IEM_MC_FETCH_XREG_U32(u32Tmp, ((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg);
             IEM_MC_STORE_MEM_U32(pVCpu->iem.s.iEffSeg, GCPtrEffSrc, u32Tmp);
+
+            IEM_MC_ADVANCE_RIP();
+            IEM_MC_END();
         }
-        IEM_MC_ADVANCE_RIP();
-        IEM_MC_END();
     }
     return VINF_SUCCESS;
+
 }
 
-/** Opcode 0x66 0x0f 0x7e - movd_q Ey, Vy */
-FNIEMOP_DEF(iemOp_movd_q_Ey_Vy)
+/**
+ * @opcode      0x7e
+ * @oppfx       0xf3
+ * @opcpuid     sse2
+ * @opgroup     og_sse2_pcksclr_datamove
+ * @opxcpttype  none
+ * @optest      op1=1 op2=2 -> op1=2
+ * @optest      op1=0 op2=-42 -> op1=-42
+ */
+FNIEMOP_DEF(iemOp_movq_Vq_Wq)
 {
+    IEMOP_MNEMONIC2(RM, MOVQ, movq, VqZx_WO, Wq, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZES);
     uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
-    if (pVCpu->iem.s.fPrefixes & IEM_OP_PRF_SIZE_REX_W)
-        IEMOP_MNEMONIC(movq_Eq_Wq, "movq Eq,Wq");
-    else
-        IEMOP_MNEMONIC(movd_Ed_Wd, "movd Ed,Wd");
     if ((bRm & X86_MODRM_MOD_MASK) == (3 << X86_MODRM_MOD_SHIFT))
     {
-        /* greg, XMM */
+        /*
+         * Register, register.
+         */
         IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
-        IEM_MC_BEGIN(0, 1);
+        IEM_MC_BEGIN(0, 2);
+        IEM_MC_LOCAL(uint64_t,                  uSrc);
+
         IEM_MC_MAYBE_RAISE_SSE2_RELATED_XCPT();
-        IEM_MC_ACTUALIZE_SSE_STATE_FOR_READ();
-        if (pVCpu->iem.s.fPrefixes & IEM_OP_PRF_SIZE_REX_W)
-        {
-            IEM_MC_LOCAL(uint64_t, u64Tmp);
-            IEM_MC_FETCH_XREG_U64(u64Tmp, ((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg);
-            IEM_MC_STORE_GREG_U64((bRm & X86_MODRM_RM_MASK) | pVCpu->iem.s.uRexB, u64Tmp);
-        }
-        else
-        {
-            IEM_MC_LOCAL(uint32_t, u32Tmp);
-            IEM_MC_FETCH_XREG_U32(u32Tmp, ((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg);
-            IEM_MC_STORE_GREG_U32((bRm & X86_MODRM_RM_MASK) | pVCpu->iem.s.uRexB, u32Tmp);
-        }
+        IEM_MC_ACTUALIZE_SSE_STATE_FOR_CHANGE();
+
+        IEM_MC_FETCH_XREG_U64(uSrc, (bRm & X86_MODRM_RM_MASK) | pVCpu->iem.s.uRexB);
+        IEM_MC_STORE_XREG_U64_ZX_U128(((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg, uSrc);
+
         IEM_MC_ADVANCE_RIP();
         IEM_MC_END();
     }
     else
     {
-        /* [mem], XMM */
+        /*
+         * Memory, register.
+         */
         IEM_MC_BEGIN(0, 2);
-        IEM_MC_LOCAL(RTGCPTR, GCPtrEffSrc);
-        IEM_MC_MAYBE_RAISE_SSE2_RELATED_XCPT();
-        IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, bRm, 1);
+        IEM_MC_LOCAL(uint64_t,                  uSrc);
+        IEM_MC_LOCAL(RTGCPTR,                   GCPtrEffSrc);
+
+        IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, bRm, 0);
         IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
-        IEM_MC_ACTUALIZE_SSE_STATE_FOR_READ();
-        if (pVCpu->iem.s.fPrefixes & IEM_OP_PRF_SIZE_REX_W)
-        {
-            IEM_MC_LOCAL(uint64_t, u64Tmp);
-            IEM_MC_FETCH_XREG_U64(u64Tmp, ((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg);
-            IEM_MC_STORE_MEM_U64(pVCpu->iem.s.iEffSeg, GCPtrEffSrc, u64Tmp);
-        }
-        else
-        {
-            IEM_MC_LOCAL(uint32_t, u32Tmp);
-            IEM_MC_FETCH_XREG_U32(u32Tmp, ((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg);
-            IEM_MC_STORE_MEM_U32(pVCpu->iem.s.iEffSeg, GCPtrEffSrc, u32Tmp);
-        }
+        IEM_MC_MAYBE_RAISE_SSE2_RELATED_XCPT();
+        IEM_MC_ACTUALIZE_SSE_STATE_FOR_CHANGE();
+
+        IEM_MC_FETCH_MEM_U64(uSrc, pVCpu->iem.s.iEffSeg, GCPtrEffSrc);
+        IEM_MC_STORE_XREG_U64_ZX_U128(((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg, uSrc);
+
         IEM_MC_ADVANCE_RIP();
         IEM_MC_END();
     }
     return VINF_SUCCESS;
 }
 
-/** Opcode 0xf3 0x0f 0x7e - movq Vq, Wq */
-FNIEMOP_STUB(iemOp_movq_Vq_Wq);
 /*  Opcode 0xf2 0x0f 0x7e - invalid */
 
 
@@ -5862,7 +6737,7 @@ FNIEMOP_DEF_1(iemOp_Grp15_fxrstor,  uint8_t, bRm)
  */
 FNIEMOP_DEF_1(iemOp_Grp15_ldmxcsr, uint8_t, bRm)
 {
-    IEMOP_MNEMONIC1(M_MEM, LDMXCSR, ldmxcsr, MdRO, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZE);
+    IEMOP_MNEMONIC1(M_MEM, LDMXCSR, ldmxcsr, Md_RO, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZES);
     if (!IEM_GET_GUEST_CPU_FEATURES(pVCpu)->fSse)
         return IEMOP_RAISE_INVALID_OPCODE();
 
@@ -5899,7 +6774,7 @@ FNIEMOP_DEF_1(iemOp_Grp15_ldmxcsr, uint8_t, bRm)
  */
 FNIEMOP_DEF_1(iemOp_Grp15_stmxcsr,  uint8_t, bRm)
 {
-    IEMOP_MNEMONIC1(M_MEM, STMXCSR, stmxcsr, MdWO, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZE);
+    IEMOP_MNEMONIC1(M_MEM, STMXCSR, stmxcsr, Md_WO, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZES);
     if (!IEM_GET_GUEST_CPU_FEATURES(pVCpu)->fSse)
         return IEMOP_RAISE_INVALID_OPCODE();
 
@@ -5926,7 +6801,7 @@ FNIEMOP_DEF_1(iemOp_Grp15_stmxcsr,  uint8_t, bRm)
  */
 FNIEMOP_DEF_1(iemOp_Grp15_xsave,    uint8_t, bRm)
 {
-    IEMOP_MNEMONIC1(M_MEM, XSAVE, xsave, MRW, DISOPTYPE_HARMLESS, 0);
+    IEMOP_MNEMONIC1(M_MEM, XSAVE, xsave, M_RW, DISOPTYPE_HARMLESS, 0);
     if (!IEM_GET_GUEST_CPU_FEATURES(pVCpu)->fXSaveRstor)
         return IEMOP_RAISE_INVALID_OPCODE();
 
@@ -5954,7 +6829,7 @@ FNIEMOP_DEF_1(iemOp_Grp15_xsave,    uint8_t, bRm)
  */
 FNIEMOP_DEF_1(iemOp_Grp15_xrstor,   uint8_t, bRm)
 {
-    IEMOP_MNEMONIC1(M_MEM, XRSTOR, xrstor, MRO, DISOPTYPE_HARMLESS, 0);
+    IEMOP_MNEMONIC1(M_MEM, XRSTOR, xrstor, M_RO, DISOPTYPE_HARMLESS, 0);
     if (!IEM_GET_GUEST_CPU_FEATURES(pVCpu)->fXSaveRstor)
         return IEMOP_RAISE_INVALID_OPCODE();
 
@@ -5984,7 +6859,7 @@ FNIEMOP_UD_STUB_1(iemOp_Grp15_xsaveopt, uint8_t, bRm);
  */
 FNIEMOP_DEF_1(iemOp_Grp15_clflush,  uint8_t, bRm)
 {
-    IEMOP_MNEMONIC1(M_MEM, CLFLUSH, clflush, MbRO, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZE);
+    IEMOP_MNEMONIC1(M_MEM, CLFLUSH, clflush, Mb_RO, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZES);
     if (!IEM_GET_GUEST_CPU_FEATURES(pVCpu)->fClFlush)
         return FNIEMOP_CALL_1(iemOp_InvalidWithRMAllNeeded, bRm);
 
@@ -6009,7 +6884,7 @@ FNIEMOP_DEF_1(iemOp_Grp15_clflush,  uint8_t, bRm)
  */
 FNIEMOP_DEF_1(iemOp_Grp15_clflushopt,  uint8_t, bRm)
 {
-    IEMOP_MNEMONIC1(M_MEM, CLFLUSHOPT, clflushopt, MbRO, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZE);
+    IEMOP_MNEMONIC1(M_MEM, CLFLUSHOPT, clflushopt, Mb_RO, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZES);
     if (!IEM_GET_GUEST_CPU_FEATURES(pVCpu)->fClFlushOpt)
         return FNIEMOP_CALL_1(iemOp_InvalidWithRMAllNeeded, bRm);
 
@@ -6702,7 +7577,7 @@ FNIEMOP_DEF(iemOp_Grp10)
      * too. See bs3-cpu-decoder-1.c32.  So, we can forward to iemOp_InvalidNeedRM.
      */
     Log(("iemOp_Grp10 aka UD1 -> #UD\n"));
-    IEMOP_MNEMONIC2EX(ud1, "ud1", RM, UD1, ud1, Gb, Eb, DISOPTYPE_INVALID, IEMOPHINT_IGNORES_OP_SIZE); /* just picked Gb,Eb here. */
+    IEMOP_MNEMONIC2EX(ud1, "ud1", RM, UD1, ud1, Gb, Eb, DISOPTYPE_INVALID, IEMOPHINT_IGNORES_OP_SIZES); /* just picked Gb,Eb here. */
     return FNIEMOP_CALL(iemOp_InvalidNeedRM);
 }
 
@@ -7750,7 +8625,7 @@ FNIEMOP_STUB(iemOp_pmullw_Vx_Wx);
  */
 FNIEMOP_DEF(iemOp_movq_Wq_Vq)
 {
-    IEMOP_MNEMONIC2(MR, MOVQ, movq, WqZxReg, Vq, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZE);
+    IEMOP_MNEMONIC2(MR, MOVQ, movq, WqZxReg_WO, Vq, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZES);
     uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
     if ((bRm & X86_MODRM_MOD_MASK) == (3 << X86_MODRM_MOD_SHIFT))
     {
@@ -7794,55 +8669,105 @@ FNIEMOP_DEF(iemOp_movq_Wq_Vq)
 }
 
 
-/** Opcode 0xf3 0x0f 0xd6 - movq2dq Vdq, Nq */
-FNIEMOP_STUB(iemOp_movq2dq_Vdq_Nq);
-/** Opcode 0xf2 0x0f 0xd6 - movdq2q Pq, Uq */
-FNIEMOP_STUB(iemOp_movdq2q_Pq_Uq);
-#if 0
-FNIEMOP_DEF(iemOp_movq_Wq_Vq__movq2dq_Vdq_Nq__movdq2q_Pq_Uq)
+/**
+ * @opcode      0xd6
+ * @opcodesub   11 mr/reg
+ * @oppfx       f3
+ * @opcpuid     sse2
+ * @opgroup     og_sse2_simdint_datamove
+ * @optest      op1=1 op2=2   -> op1=2   ftw=0xff
+ * @optest      op1=0 op2=-42 -> op1=-42 ftw=0xff
+ */
+FNIEMOP_DEF(iemOp_movq2dq_Vdq_Nq)
 {
-    /* Docs says register only. */
     uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
-
-    switch (pVCpu->iem.s.fPrefixes & (IEM_OP_PRF_SIZE_OP | IEM_OP_PRF_REPNZ | IEM_OP_PRF_REPZ))
+    if ((bRm & X86_MODRM_MOD_MASK) == (3 << X86_MODRM_MOD_SHIFT))
     {
-        case IEM_OP_PRF_SIZE_OP: /* SSE */
-            I E M O P _ M N E M O N I C(movq_Wq_Vq, "movq Wq,Vq");
-            IEMOP_HLP_DECODED_NL_2(OP_PMOVMSKB, IEMOPFORM_RM_REG, OP_PARM_Gd, OP_PARM_Vdq, DISOPTYPE_SSE | DISOPTYPE_HARMLESS);
-            IEM_MC_BEGIN(2, 0);
-            IEM_MC_ARG(uint64_t *,           pDst, 0);
-            IEM_MC_ARG(PCRTUINT128U,         pSrc, 1);
-            IEM_MC_MAYBE_RAISE_SSE2_RELATED_XCPT();
-            IEM_MC_PREPARE_SSE_USAGE();
-            IEM_MC_REF_GREG_U64(pDst, ((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg);
-            IEM_MC_REF_XREG_U128_CONST(pSrc, (bRm & X86_MODRM_RM_MASK) | pVCpu->iem.s.uRexB);
-            IEM_MC_CALL_SSE_AIMPL_2(iemAImpl_pmovmskb_u128, pDst, pSrc);
-            IEM_MC_ADVANCE_RIP();
-            IEM_MC_END();
-            return VINF_SUCCESS;
+        /*
+         * Register, register.
+         */
+        IEMOP_MNEMONIC2(RM_REG, MOVQ2DQ, movq2dq, VqZx_WO, Nq, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZES);
+        IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
+        IEM_MC_BEGIN(0, 1);
+        IEM_MC_LOCAL(uint64_t,                  uSrc);
 
-        case 0: /* MMX */
-            I E M O P _ M N E M O N I C(pmovmskb_Gd_Udq, "pmovmskb Gd,Udq");
-            IEMOP_HLP_DECODED_NL_2(OP_PMOVMSKB, IEMOPFORM_RM_REG, OP_PARM_Gd, OP_PARM_Vdq, DISOPTYPE_MMX | DISOPTYPE_HARMLESS);
-            IEM_MC_BEGIN(2, 0);
-            IEM_MC_ARG(uint64_t *,          pDst, 0);
-            IEM_MC_ARG(uint64_t const *,    pSrc, 1);
-            IEM_MC_MAYBE_RAISE_MMX_RELATED_XCPT_CHECK_SSE_OR_MMXEXT();
-            IEM_MC_PREPARE_FPU_USAGE();
-            IEM_MC_REF_GREG_U64(pDst, (bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK);
-            IEM_MC_REF_MREG_U64_CONST(pSrc, bRm & X86_MODRM_RM_MASK);
-            IEM_MC_CALL_MMX_AIMPL_2(iemAImpl_pmovmskb_u64, pDst, pSrc);
-            IEM_MC_ADVANCE_RIP();
-            IEM_MC_END();
-            return VINF_SUCCESS;
+        IEM_MC_MAYBE_RAISE_SSE2_RELATED_XCPT();
+        IEM_MC_ACTUALIZE_FPU_STATE_FOR_CHANGE();
 
-        default:
-            return IEMOP_RAISE_INVALID_OPCODE();
+        IEM_MC_FETCH_MREG_U64(uSrc, bRm & X86_MODRM_RM_MASK);
+        IEM_MC_STORE_XREG_U64_ZX_U128(((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg, uSrc);
+        IEM_MC_FPU_TO_MMX_MODE();
+
+        IEM_MC_ADVANCE_RIP();
+        IEM_MC_END();
+        return VINF_SUCCESS;
     }
+
+    /**
+     * @opdone
+     * @opmnemonic  udf30fd6mem
+     * @opcode      0xd6
+     * @opcodesub   !11 mr/reg
+     * @oppfx       f3
+     * @opunused    intel-modrm
+     * @opcpuid     sse
+     * @optest      ->
+     */
+    return FNIEMOP_CALL_1(iemOp_InvalidWithRMNeedDecode, bRm);
 }
-#endif
 
 
+/**
+ * @opcode      0xd6
+ * @opcodesub   11 mr/reg
+ * @oppfx       f2
+ * @opcpuid     sse2
+ * @opgroup     og_sse2_simdint_datamove
+ * @optest      op1=1 op2=2   -> op1=2   ftw=0xff
+ * @optest      op1=0 op2=-42 -> op1=-42 ftw=0xff
+ * @optest      op1=0 op2=0x1123456789abcdef -> op1=0x1123456789abcdef ftw=0xff
+ * @optest      op1=0 op2=0xfedcba9876543210 -> op1=0xfedcba9876543210 ftw=0xff
+ * @optest      op1=-42 op2=0xfedcba9876543210
+ *                  ->  op1=0xfedcba9876543210 ftw=0xff
+ */
+FNIEMOP_DEF(iemOp_movdq2q_Pq_Uq)
+{
+    uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
+    if ((bRm & X86_MODRM_MOD_MASK) == (3 << X86_MODRM_MOD_SHIFT))
+    {
+        /*
+         * Register, register.
+         */
+        IEMOP_MNEMONIC2(RM_REG, MOVDQ2Q, movdq2q, Pq_WO, Uq, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZES);
+        IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
+        IEM_MC_BEGIN(0, 1);
+        IEM_MC_LOCAL(uint64_t,                  uSrc);
+
+        IEM_MC_MAYBE_RAISE_SSE2_RELATED_XCPT();
+        IEM_MC_ACTUALIZE_FPU_STATE_FOR_CHANGE();
+
+        IEM_MC_FETCH_XREG_U64(uSrc, (bRm & X86_MODRM_RM_MASK) | pVCpu->iem.s.uRexB);
+        IEM_MC_STORE_MREG_U64((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK, uSrc);
+        IEM_MC_FPU_TO_MMX_MODE();
+
+        IEM_MC_ADVANCE_RIP();
+        IEM_MC_END();
+        return VINF_SUCCESS;
+    }
+
+    /**
+     * @opdone
+     * @opmnemonic  udf20fd6mem
+     * @opcode      0xd6
+     * @opcodesub   !11 mr/reg
+     * @oppfx       f2
+     * @opunused    intel-modrm
+     * @opcpuid     sse
+     * @optest      ->
+     */
+    return FNIEMOP_CALL_1(iemOp_InvalidWithRMNeedDecode, bRm);
+}
+
 /** Opcode      0x0f 0xd7 - pmovmskb Gd, Nq */
 FNIEMOP_DEF(iemOp_pmovmskb_Gd_Nq)
 {
@@ -8012,10 +8937,19 @@ FNIEMOP_STUB(iemOp_cvtdq2pd_Vx_Wpd);
 FNIEMOP_STUB(iemOp_cvtpd2dq_Vx_Wpd);
 
 
-/** Opcode      0x0f 0xe7 - movntq Mq, Pq */
+/**
+ * @opcode      0xe7
+ * @opcodesub   !11 mr/reg
+ * @oppfx       none
+ * @opcpuid     sse
+ * @opgroup     og_sse1_cachect
+ * @opxcpttype  none
+ * @optest      op1=-1 op2=2  -> op1=2   ftw=0xff
+ * @optest      op1=0 op2=-42 -> op1=-42 ftw=0xff
+ */
 FNIEMOP_DEF(iemOp_movntq_Mq_Pq)
 {
-    IEMOP_MNEMONIC(movntq_Mq_Pq, "movntq Mq,Pq");
+    IEMOP_MNEMONIC2(MR_MEM, MOVNTQ, movntq, Mq_WO, Pq, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZES);
     uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
     if ((bRm & X86_MODRM_MOD_MASK) != (3 << X86_MODRM_MOD_SHIFT))
     {
@@ -8027,27 +8961,46 @@ FNIEMOP_DEF(iemOp_movntq_Mq_Pq)
         IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, bRm, 0);
         IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
         IEM_MC_MAYBE_RAISE_MMX_RELATED_XCPT();
-        IEM_MC_ACTUALIZE_FPU_STATE_FOR_READ();
+        IEM_MC_ACTUALIZE_FPU_STATE_FOR_CHANGE();
 
         IEM_MC_FETCH_MREG_U64(uSrc, (bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK);
         IEM_MC_STORE_MEM_U64(pVCpu->iem.s.iEffSeg, GCPtrEffSrc, uSrc);
+        IEM_MC_FPU_TO_MMX_MODE();
 
         IEM_MC_ADVANCE_RIP();
         IEM_MC_END();
         return VINF_SUCCESS;
     }
-    /* The register, register encoding is invalid. */
+    /**
+     * @opdone
+     * @opmnemonic  ud0fe7reg
+     * @opcode      0xe7
+     * @opcodesub   11 mr/reg
+     * @oppfx       none
+     * @opunused    immediate
+     * @opcpuid     sse
+     * @optest      ->
+     */
     return IEMOP_RAISE_INVALID_OPCODE();
 }
 
-/** Opcode 0x66 0x0f 0xe7 - movntdq Mx, Vx */
-FNIEMOP_DEF(iemOp_movntdq_Mx_Vx)
+/**
+ * @opcode      0xe7
+ * @opcodesub   !11 mr/reg
+ * @oppfx       0x66
+ * @opcpuid     sse2
+ * @opgroup     og_sse2_cachect
+ * @opxcpttype  1
+ * @optest      op1=-1 op2=2  -> op1=2
+ * @optest      op1=0 op2=-42 -> op1=-42
+ */
+FNIEMOP_DEF(iemOp_movntdq_Mdq_Vdq)
 {
+    IEMOP_MNEMONIC2(MR_MEM, MOVNTDQ, movntdq, Mdq_WO, Vdq, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZES);
     uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
     if ((bRm & X86_MODRM_MOD_MASK) != (3 << X86_MODRM_MOD_SHIFT))
     {
         /* Register, memory. */
-        IEMOP_MNEMONIC(movntdq_Mx_Vx, "movntdq Mx,Vx");
         IEM_MC_BEGIN(0, 2);
         IEM_MC_LOCAL(RTUINT128U,                uSrc);
         IEM_MC_LOCAL(RTGCPTR,                   GCPtrEffSrc);
@@ -8065,7 +9018,16 @@ FNIEMOP_DEF(iemOp_movntdq_Mx_Vx)
         return VINF_SUCCESS;
     }
 
-    /* The register, register encoding is invalid. */
+    /**
+     * @opdone
+     * @opmnemonic  ud660fe7reg
+     * @opcode      0xe7
+     * @opcodesub   11 mr/reg
+     * @oppfx       0x66
+     * @opunused    immediate
+     * @opcpuid     sse
+     * @optest      ->
+     */
     return IEMOP_RAISE_INVALID_OPCODE();
 }
 
@@ -8276,14 +9238,14 @@ IEM_STATIC const PFNIEMOP g_apfnTwoByteMap[] =
     /* 0x0e */  IEMOP_X4(iemOp_femms),
     /* 0x0f */  IEMOP_X4(iemOp_3Dnow),
 
-    /* 0x10 */  iemOp_movups_Vps_Wps,       iemOp_movupd_Vpd_Wpd,      iemOp_movss_Vss_Wss,        iemOp_movsd_Vx_Wsd,
-    /* 0x11 */  iemOp_movups_Wps_Vps,       iemOp_movupd_Wpd_Vpd,      iemOp_movss_Wss_Vss,        iemOp_movsd_Wsd_Vsd,
-    /* 0x12 */  iemOp_movlps_Vq_Mq__movhlps, iemOp_movlpd_Vq_Mq,       iemOp_movsldup_Vdq_Wdq,     iemOp_movddup_Vdq_Wdq,
-    /* 0x13 */  iemOp_movlps_Mq_Vq,         iemOp_movlpd_Mq_Vq,        iemOp_InvalidNeedRM,        iemOp_InvalidNeedRM,
-    /* 0x14 */  iemOp_unpcklps_Vx_Wx,       iemOp_unpcklpd_Vx_Wx,      iemOp_InvalidNeedRM,        iemOp_InvalidNeedRM,
-    /* 0x15 */  iemOp_unpckhps_Vx_Wx,       iemOp_unpckhpd_Vx_Wx,      iemOp_InvalidNeedRM,        iemOp_InvalidNeedRM,
-    /* 0x16 */  iemOp_movhpsv1_Vdq_Mq__movlhps_Vdq_Uq,  iemOp_movhpdv1_Vdq_Mq, iemOp_movshdup_Vx_Wx, iemOp_InvalidNeedRM,
-    /* 0x17 */  iemOp_movhpsv1_Mq_Vq,       iemOp_movhpdv1_Mq_Vq,      iemOp_InvalidNeedRM,        iemOp_InvalidNeedRM,
+    /* 0x10 */  iemOp_movups_Vps_Wps,       iemOp_movupd_Vpd_Wpd,       iemOp_movss_Vss_Wss,        iemOp_movsd_Vsd_Wsd,
+    /* 0x11 */  iemOp_movups_Wps_Vps,       iemOp_movupd_Wpd_Vpd,       iemOp_movss_Wss_Vss,        iemOp_movsd_Wsd_Vsd,
+    /* 0x12 */  iemOp_movlps_Vq_Mq__movhlps, iemOp_movlpd_Vq_Mq,        iemOp_movsldup_Vdq_Wdq,     iemOp_movddup_Vdq_Wdq,
+    /* 0x13 */  iemOp_movlps_Mq_Vq,         iemOp_movlpd_Mq_Vq,         iemOp_InvalidNeedRM,        iemOp_InvalidNeedRM,
+    /* 0x14 */  iemOp_unpcklps_Vx_Wx,       iemOp_unpcklpd_Vx_Wx,       iemOp_InvalidNeedRM,        iemOp_InvalidNeedRM,
+    /* 0x15 */  iemOp_unpckhps_Vx_Wx,       iemOp_unpckhpd_Vx_Wx,       iemOp_InvalidNeedRM,        iemOp_InvalidNeedRM,
+    /* 0x16 */  iemOp_movhps_Vdq_Mq__movlhps_Vdq_Uq, iemOp_movhpd_Vdq_Mq, iemOp_movshdup_Vdq_Wdq,   iemOp_InvalidNeedRM,
+    /* 0x17 */  iemOp_movhps_Mq_Vq,         iemOp_movhpd_Mq_Vq,         iemOp_InvalidNeedRM,        iemOp_InvalidNeedRM,
     /* 0x18 */  IEMOP_X4(iemOp_prefetch_Grp16),
     /* 0x19 */  IEMOP_X4(iemOp_nop_Ev),
     /* 0x1a */  IEMOP_X4(iemOp_nop_Ev),
@@ -8376,7 +9338,7 @@ IEM_STATIC const PFNIEMOP g_apfnTwoByteMap[] =
     /* 0x6c */  iemOp_InvalidNeedRM,        iemOp_punpcklqdq_Vx_Wx,     iemOp_InvalidNeedRM,        iemOp_InvalidNeedRM,
     /* 0x6d */  iemOp_InvalidNeedRM,        iemOp_punpckhqdq_Vx_W,      iemOp_InvalidNeedRM,        iemOp_InvalidNeedRM,
     /* 0x6e */  iemOp_movd_q_Pd_Ey,         iemOp_movd_q_Vy_Ey,         iemOp_InvalidNeedRM,        iemOp_InvalidNeedRM,
-    /* 0x6f */  iemOp_movq_Pq_Qq,           iemOp_movdqa_Vx_Wx,         iemOp_movdqu_Vx_Wx,         iemOp_InvalidNeedRM,
+    /* 0x6f */  iemOp_movq_Pq_Qq,           iemOp_movdqa_Vdq_Wdq,       iemOp_movdqu_Vdq_Wdq,       iemOp_InvalidNeedRM,
 
     /* 0x70 */  iemOp_pshufw_Pq_Qq_Ib,      iemOp_pshufd_Vx_Wx_Ib,      iemOp_pshufhw_Vx_Wx_Ib,     iemOp_pshuflw_Vx_Wx_Ib,
     /* 0x71 */  IEMOP_X4(iemOp_Grp12),
@@ -8505,7 +9467,7 @@ IEM_STATIC const PFNIEMOP g_apfnTwoByteMap[] =
     /* 0xe4 */  iemOp_pmulhuw_Pq_Qq,        iemOp_pmulhuw_Vx_W,         iemOp_InvalidNeedRM,        iemOp_InvalidNeedRM,
     /* 0xe5 */  iemOp_pmulhw_Pq_Qq,         iemOp_pmulhw_Vx_Wx,         iemOp_InvalidNeedRM,        iemOp_InvalidNeedRM,
     /* 0xe6 */  iemOp_InvalidNeedRM,        iemOp_cvttpd2dq_Vx_Wpd,     iemOp_cvtdq2pd_Vx_Wpd,      iemOp_cvtpd2dq_Vx_Wpd,
-    /* 0xe7 */  iemOp_movntq_Mq_Pq,         iemOp_movntdq_Mx_Vx,        iemOp_InvalidNeedRM,        iemOp_InvalidNeedRM,
+    /* 0xe7 */  iemOp_movntq_Mq_Pq,         iemOp_movntdq_Mdq_Vdq,      iemOp_InvalidNeedRM,        iemOp_InvalidNeedRM,
     /* 0xe8 */  iemOp_psubsb_Pq_Qq,         iemOp_psubsb_Vx_W,          iemOp_InvalidNeedRM,        iemOp_InvalidNeedRM,
     /* 0xe9 */  iemOp_psubsw_Pq_Qq,         iemOp_psubsw_Vx_Wx,         iemOp_InvalidNeedRM,        iemOp_InvalidNeedRM,
     /* 0xea */  iemOp_pminsw_Pq_Qq,         iemOp_pminsw_Vx_Wx,         iemOp_InvalidNeedRM,        iemOp_InvalidNeedRM,
diff --git a/src/VBox/VMM/VMMAll/IEMAllInstructionsVexMap1.cpp.h b/src/VBox/VMM/VMMAll/IEMAllInstructionsVexMap1.cpp.h
index 4bd8e2b..7146ad2 100644
--- a/src/VBox/VMM/VMMAll/IEMAllInstructionsVexMap1.cpp.h
+++ b/src/VBox/VMM/VMMAll/IEMAllInstructionsVexMap1.cpp.h
@@ -49,571 +49,998 @@ FNIEMOP_DEF(iemOp_vud2)
 /*  Opcode VEX.0F 0x0f - invalid */
 
 
-/** Opcode VEX.0F 0x10 - vmovups Vps, Wps */
-FNIEMOP_STUB(iemOp_vmovups_Vps_Wps);
-/** Opcode VEX.66.0F 0x10 - vmovupd Vpd, Wpd */
-FNIEMOP_STUB(iemOp_vmovupd_Vpd_Wpd);
+/**
+ * @opcode      0x10
+ * @oppfx       none
+ * @opcpuid     avx
+ * @opgroup     og_avx_simdfp_datamove
+ * @opxcpttype  4UA
+ * @optest      op1=1 op2=2 -> op1=2
+ * @optest      op1=0 op2=-22 -> op1=-22
+ */
+FNIEMOP_DEF(iemOp_vmovups_Vps_Wps)
+{
+    IEMOP_MNEMONIC2(VEX_RM, VMOVUPS, vmovups, Vps_WO, Wps, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZES);
+    Assert(pVCpu->iem.s.uVexLength <= 1);
+    uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
+    if ((bRm & X86_MODRM_MOD_MASK) == (3 << X86_MODRM_MOD_SHIFT))
+    {
+        /*
+         * Register, register.
+         */
+        IEMOP_HLP_DONE_VEX_DECODING_NO_VVVV();
+        IEM_MC_BEGIN(0, 0);
+        IEM_MC_MAYBE_RAISE_AVX_RELATED_XCPT();
+        IEM_MC_ACTUALIZE_AVX_STATE_FOR_CHANGE();
+        if (pVCpu->iem.s.uVexLength == 0)
+            IEM_MC_COPY_YREG_U128_ZX_VLMAX(((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg,
+                                           (bRm & X86_MODRM_RM_MASK) | pVCpu->iem.s.uRexB);
+        else
+            IEM_MC_COPY_YREG_U256_ZX_VLMAX(((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg,
+                                           (bRm & X86_MODRM_RM_MASK) | pVCpu->iem.s.uRexB);
+        IEM_MC_ADVANCE_RIP();
+        IEM_MC_END();
+    }
+    else if (pVCpu->iem.s.uVexLength == 0)
+    {
+        /*
+         * 128-bit: Register, Memory
+         */
+        IEM_MC_BEGIN(0, 2);
+        IEM_MC_LOCAL(RTUINT128U,                uSrc);
+        IEM_MC_LOCAL(RTGCPTR,                   GCPtrEffSrc);
+
+        IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, bRm, 0);
+        IEMOP_HLP_DONE_VEX_DECODING_NO_VVVV();
+        IEM_MC_MAYBE_RAISE_AVX_RELATED_XCPT();
+        IEM_MC_ACTUALIZE_AVX_STATE_FOR_CHANGE();
+
+        IEM_MC_FETCH_MEM_U128(uSrc, pVCpu->iem.s.iEffSeg, GCPtrEffSrc);
+        IEM_MC_STORE_YREG_U128_ZX_VLMAX(((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg, uSrc);
+
+        IEM_MC_ADVANCE_RIP();
+        IEM_MC_END();
+    }
+    else
+    {
+        /*
+         * 256-bit: Register, Memory
+         */
+        IEM_MC_BEGIN(0, 2);
+        IEM_MC_LOCAL(RTUINT256U,                uSrc);
+        IEM_MC_LOCAL(RTGCPTR,                   GCPtrEffSrc);
+
+        IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, bRm, 0);
+        IEMOP_HLP_DONE_VEX_DECODING_NO_VVVV();
+        IEM_MC_MAYBE_RAISE_AVX_RELATED_XCPT();
+        IEM_MC_ACTUALIZE_AVX_STATE_FOR_CHANGE();
+
+        IEM_MC_FETCH_MEM_U256(uSrc, pVCpu->iem.s.iEffSeg, GCPtrEffSrc);
+        IEM_MC_STORE_YREG_U256_ZX_VLMAX(((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg, uSrc);
+
+        IEM_MC_ADVANCE_RIP();
+        IEM_MC_END();
+    }
+    return VINF_SUCCESS;
+}
 
 
-/** Opcode VEX 0xf3 0x0f 0x10 - vmovsd Vx, Hx, Wsd */
 /**
- * @ opcode      0x10
- * @ oppfx       0xf3
- * @ opcpuid     sse
- * @ opgroup     og_sse_simdfp_datamove
- * @ opxcpttype  5
- * @ optest      op1=1 op2=2 -> op1=2
- * @ optest      op1=0 op2=-22 -> op1=-22
- * @ oponly
+ * @opcode      0x10
+ * @oppfx       0x66
+ * @opcpuid     avx
+ * @opgroup     og_avx_simdfp_datamove
+ * @opxcpttype  4UA
+ * @optest      op1=1 op2=2 -> op1=2
+ * @optest      op1=0 op2=-22 -> op1=-22
  */
-FNIEMOP_STUB(iemOp_vmovss_Vx_Hx_Wss);
-//FNIEMOP_DEF(iemOp_movss_Vss_Wss)
-//{
-//    I E M O P _ M N E M O N I C 2(RM, VMOVSS, vmovss, VssZxReg, Wss, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZE);
-//    uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
-//    if ((bRm & X86_MODRM_MOD_MASK) == (3 << X86_MODRM_MOD_SHIFT))
-//    {
-//        /*
-//         * Register, register.
-//         */
-//        IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
-//        IEM_MC_BEGIN(0, 1);
-//        IEM_MC_LOCAL(uint32_t,                  uSrc);
-//
-//        IEM_MC_MAYBE_RAISE_SSE_RELATED_XCPT();
-//        IEM_MC_ACTUALIZE_SSE_STATE_FOR_CHANGE();
-//        IEM_MC_FETCH_XREG_U32(uSrc, (bRm & X86_MODRM_RM_MASK) | pVCpu->iem.s.uRexB);
-//        IEM_MC_STORE_XREG_U32(((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg, uSrc);
-//
-//        IEM_MC_ADVANCE_RIP();
-//        IEM_MC_END();
-//    }
-//    else
-//    {
-//        /*
-//         * Memory, register.
-//         */
-//        IEM_MC_BEGIN(0, 2);
-//        IEM_MC_LOCAL(uint32_t,                  uSrc);
-//        IEM_MC_LOCAL(RTGCPTR,                   GCPtrEffSrc);
-//
-//        IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, bRm, 0);
-//        IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
-//        IEM_MC_MAYBE_RAISE_SSE_RELATED_XCPT();
-//        IEM_MC_ACTUALIZE_SSE_STATE_FOR_CHANGE();
-//
-//        IEM_MC_FETCH_MEM_U32(uSrc, pVCpu->iem.s.iEffSeg, GCPtrEffSrc);
-//        IEM_MC_STORE_XREG_U32_ZX_U128(((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg, uSrc);
-//
-//        IEM_MC_ADVANCE_RIP();
-//        IEM_MC_END();
-//    }
-//    return VINF_SUCCESS;
-//}
+FNIEMOP_DEF(iemOp_vmovupd_Vpd_Wpd)
+{
+    IEMOP_MNEMONIC2(VEX_RM, VMOVUPD, vmovupd, Vpd_WO, Wpd, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZES);
+    Assert(pVCpu->iem.s.uVexLength <= 1);
+    uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
+    if ((bRm & X86_MODRM_MOD_MASK) == (3 << X86_MODRM_MOD_SHIFT))
+    {
+        /*
+         * Register, register.
+         */
+        IEMOP_HLP_DONE_VEX_DECODING_NO_VVVV();
+        IEM_MC_BEGIN(0, 0);
+        IEM_MC_MAYBE_RAISE_AVX_RELATED_XCPT();
+        IEM_MC_ACTUALIZE_AVX_STATE_FOR_CHANGE();
+        if (pVCpu->iem.s.uVexLength == 0)
+            IEM_MC_COPY_YREG_U128_ZX_VLMAX(((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg,
+                                           (bRm & X86_MODRM_RM_MASK) | pVCpu->iem.s.uRexB);
+        else
+            IEM_MC_COPY_YREG_U256_ZX_VLMAX(((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg,
+                                           (bRm & X86_MODRM_RM_MASK) | pVCpu->iem.s.uRexB);
+        IEM_MC_ADVANCE_RIP();
+        IEM_MC_END();
+    }
+    else if (pVCpu->iem.s.uVexLength == 0)
+    {
+        /*
+         * 128-bit: Memory, register.
+         */
+        IEM_MC_BEGIN(0, 2);
+        IEM_MC_LOCAL(RTUINT128U,                uSrc);
+        IEM_MC_LOCAL(RTGCPTR,                   GCPtrEffSrc);
+
+        IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, bRm, 0);
+        IEMOP_HLP_DONE_VEX_DECODING_NO_VVVV();
+        IEM_MC_MAYBE_RAISE_AVX_RELATED_XCPT();
+        IEM_MC_ACTUALIZE_AVX_STATE_FOR_CHANGE();
+
+        IEM_MC_FETCH_MEM_U128(uSrc, pVCpu->iem.s.iEffSeg, GCPtrEffSrc);
+        IEM_MC_STORE_YREG_U128_ZX_VLMAX(((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg, uSrc);
+
+        IEM_MC_ADVANCE_RIP();
+        IEM_MC_END();
+    }
+    else
+    {
+        /*
+         * 256-bit: Memory, register.
+         */
+        IEM_MC_BEGIN(0, 2);
+        IEM_MC_LOCAL(RTUINT256U,                uSrc);
+        IEM_MC_LOCAL(RTGCPTR,                   GCPtrEffSrc);
+
+        IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, bRm, 0);
+        IEMOP_HLP_DONE_VEX_DECODING_NO_VVVV();
+        IEM_MC_MAYBE_RAISE_AVX_RELATED_XCPT();
+        IEM_MC_ACTUALIZE_AVX_STATE_FOR_CHANGE();
+
+        IEM_MC_FETCH_MEM_U256(uSrc, pVCpu->iem.s.iEffSeg, GCPtrEffSrc);
+        IEM_MC_STORE_YREG_U256_ZX_VLMAX(((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg, uSrc);
+
+        IEM_MC_ADVANCE_RIP();
+        IEM_MC_END();
+    }
+    return VINF_SUCCESS;
+}
 
-/** Opcode VEX.F2.0F 0x10 - vmovsd Vx, Hx, Wsd */
-FNIEMOP_STUB(iemOp_vmovsd_Vx_Hx_Wsd);
 
+FNIEMOP_DEF(iemOp_vmovss_Vss_Hss_Wss)
+{
+    Assert(pVCpu->iem.s.uVexLength <= 1);
+    uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
+    if ((bRm & X86_MODRM_MOD_MASK) == (3 << X86_MODRM_MOD_SHIFT))
+    {
+        /**
+         * @opcode      0x10
+         * @oppfx       0xf3
+         * @opcodesub   11 mr/reg
+         * @opcpuid     avx
+         * @opgroup     og_avx_simdfp_datamerge
+         * @opxcpttype  5
+         * @optest      op1=1 op2=0  op3=2    -> op1=2
+         * @optest      op1=0 op2=0  op3=-22  -> op1=0xffffffea
+         * @optest      op1=3 op2=-1 op3=0x77 -> op1=-4294967177
+         * @optest      op1=3 op2=-2 op3=0x77 -> op1=-8589934473
+         * @note        HssHi refers to bits 127:32.
+         */
+        IEMOP_MNEMONIC3(VEX_RVM, VMOVSS, vmovss, Vss_WO, HssHi, Uss, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZES | IEMOPHINT_IGNORES_VEX_L);
+        IEMOP_HLP_DONE_VEX_DECODING();
+        IEM_MC_BEGIN(0, 0);
+
+        IEM_MC_MAYBE_RAISE_AVX_RELATED_XCPT();
+        IEM_MC_ACTUALIZE_AVX_STATE_FOR_CHANGE();
+        IEM_MC_MERGE_YREG_U32_U96_ZX_VLMAX(((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg,
+                                           (bRm & X86_MODRM_RM_MASK) | pVCpu->iem.s.uRexB /*U32*/,
+                                            IEM_GET_EFFECTIVE_VVVV(pVCpu) /*Hss*/);
+        IEM_MC_ADVANCE_RIP();
+        IEM_MC_END();
+    }
+    else
+    {
+        /**
+         * @opdone
+         * @opcode      0x10
+         * @oppfx       0xf3
+         * @opcodesub   11 mr/reg
+         * @opcpuid     avx
+         * @opgroup     og_avx_simdfp_datamove
+         * @opxcpttype  5
+         * @opfunction  iemOp_vmovss_Vss_Hss_Wss
+         * @optest      op1=1 op2=2 -> op1=2
+         * @optest      op1=0 op2=-22 -> op1=-22
+         */
+        IEMOP_MNEMONIC2(VEX_XM, VMOVSS, vmovss, VssZx_WO, Md, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZES | IEMOPHINT_IGNORES_VEX_L);
+        IEM_MC_BEGIN(0, 2);
+        IEM_MC_LOCAL(uint32_t,                  uSrc);
+        IEM_MC_LOCAL(RTGCPTR,                   GCPtrEffSrc);
+
+        IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, bRm, 0);
+        IEMOP_HLP_DONE_VEX_DECODING_NO_VVVV();
+        IEM_MC_MAYBE_RAISE_AVX_RELATED_XCPT();
+        IEM_MC_ACTUALIZE_AVX_STATE_FOR_CHANGE();
+
+        IEM_MC_FETCH_MEM_U32(uSrc, pVCpu->iem.s.iEffSeg, GCPtrEffSrc);
+        IEM_MC_STORE_YREG_U32_ZX_VLMAX(((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg, uSrc);
+
+        IEM_MC_ADVANCE_RIP();
+        IEM_MC_END();
+    }
 
-/**
- * @ opcode      0x11
- * @ oppfx       none
- * @ opcpuid     sse
- * @ opgroup     og_sse_simdfp_datamove
- * @ opxcpttype  4UA
- * @ optest      op1=1 op2=2 -> op1=2
- * @ optest      op1=0 op2=-42 -> op1=-42
- */
-FNIEMOP_STUB(iemOp_vmovups_Wps_Vps);
-//FNIEMOP_DEF(iemOp_vmovups_Wps_Vps)
-//{
-//    IEMOP_MNEMONIC2(MR, VMOVUPS, vmovups, Wps, Vps, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZE);
-//    uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
-//    if ((bRm & X86_MODRM_MOD_MASK) == (3 << X86_MODRM_MOD_SHIFT))
-//    {
-//        /*
-//         * Register, register.
-//         */
-//        IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
-//        IEM_MC_BEGIN(0, 0);
-//        IEM_MC_MAYBE_RAISE_SSE_RELATED_XCPT();
-//        IEM_MC_ACTUALIZE_SSE_STATE_FOR_CHANGE();
-//        IEM_MC_COPY_XREG_U128((bRm & X86_MODRM_RM_MASK) | pVCpu->iem.s.uRexB,
-//                              ((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg);
-//        IEM_MC_ADVANCE_RIP();
-//        IEM_MC_END();
-//    }
-//    else
-//    {
-//        /*
-//         * Memory, register.
-//         */
-//        IEM_MC_BEGIN(0, 2);
-//        IEM_MC_LOCAL(RTUINT128U,                uSrc); /** @todo optimize this one day... */
-//        IEM_MC_LOCAL(RTGCPTR,                   GCPtrEffSrc);
-//
-//        IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, bRm, 0);
-//        IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
-//        IEM_MC_MAYBE_RAISE_SSE_RELATED_XCPT();
-//        IEM_MC_ACTUALIZE_SSE_STATE_FOR_READ();
-//
-//        IEM_MC_FETCH_XREG_U128(uSrc, ((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg);
-//        IEM_MC_STORE_MEM_U128(pVCpu->iem.s.iEffSeg, GCPtrEffSrc, uSrc);
-//
-//        IEM_MC_ADVANCE_RIP();
-//        IEM_MC_END();
-//    }
-//    return VINF_SUCCESS;
-//}
+    return VINF_SUCCESS;
+}
+
+
+FNIEMOP_DEF(iemOp_vmovsd_Vsd_Hsd_Wsd)
+{
+    Assert(pVCpu->iem.s.uVexLength <= 1);
+    uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
+    if ((bRm & X86_MODRM_MOD_MASK) == (3 << X86_MODRM_MOD_SHIFT))
+    {
+        /**
+         * @opcode      0x10
+         * @oppfx       0xf2
+         * @opcodesub   11 mr/reg
+         * @opcpuid     avx
+         * @opgroup     og_avx_simdfp_datamerge
+         * @opxcpttype  5
+         * @optest      op1=1 op2=0  op3=2    -> op1=2
+         * @optest      op1=0 op2=0  op3=-22  -> op1=0xffffffffffffffea
+         * @optest      op1=3 op2=-1 op3=0x77 ->
+         *              op1=0xffffffffffffffff0000000000000077
+         * @optest      op1=3 op2=0x42 op3=0x77 -> op1=0x420000000000000077
+         */
+        IEMOP_MNEMONIC3(VEX_RVM, VMOVSD, vmovsd, Vsd_WO, HsdHi, Usd, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZES | IEMOPHINT_IGNORES_VEX_L);
+        IEMOP_HLP_DONE_VEX_DECODING();
+        IEM_MC_BEGIN(0, 0);
+
+        IEM_MC_MAYBE_RAISE_AVX_RELATED_XCPT();
+        IEM_MC_ACTUALIZE_AVX_STATE_FOR_CHANGE();
+        IEM_MC_MERGE_YREG_U64_U64_ZX_VLMAX(((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg,
+                                           (bRm & X86_MODRM_RM_MASK) | pVCpu->iem.s.uRexB /*U32*/,
+                                           IEM_GET_EFFECTIVE_VVVV(pVCpu) /*Hss*/);
+        IEM_MC_ADVANCE_RIP();
+        IEM_MC_END();
+    }
+    else
+    {
+        /**
+         * @opdone
+         * @opcode      0x10
+         * @oppfx       0xf2
+         * @opcodesub   11 mr/reg
+         * @opcpuid     avx
+         * @opgroup     og_avx_simdfp_datamove
+         * @opxcpttype  5
+         * @opfunction  iemOp_vmovsd_Vsd_Hsd_Wsd
+         * @optest      op1=1 op2=2 -> op1=2
+         * @optest      op1=0 op2=-22 -> op1=-22
+         */
+        IEMOP_MNEMONIC2(VEX_XM, VMOVSD, vmovsd, VsdZx_WO, Mq, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZES | IEMOPHINT_IGNORES_VEX_L);
+        IEM_MC_BEGIN(0, 2);
+        IEM_MC_LOCAL(uint64_t,                  uSrc);
+        IEM_MC_LOCAL(RTGCPTR,                   GCPtrEffSrc);
+
+        IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, bRm, 0);
+        IEMOP_HLP_DONE_VEX_DECODING_NO_VVVV();
+        IEM_MC_MAYBE_RAISE_AVX_RELATED_XCPT();
+        IEM_MC_ACTUALIZE_AVX_STATE_FOR_CHANGE();
+
+        IEM_MC_FETCH_MEM_U64(uSrc, pVCpu->iem.s.iEffSeg, GCPtrEffSrc);
+        IEM_MC_STORE_YREG_U64_ZX_VLMAX(((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg, uSrc);
+
+        IEM_MC_ADVANCE_RIP();
+        IEM_MC_END();
+    }
+
+    return VINF_SUCCESS;
+}
 
 
 /**
- * @ opcode      0x11
- * @ oppfx       0x66
- * @ opcpuid     sse2
- * @ opgroup     og_sse2_pcksclr_datamove
- * @ opxcpttype  4UA
- * @ optest      op1=1 op2=2 -> op1=2
- * @ optest      op1=0 op2=-42 -> op1=-42
+ * @opcode      0x11
+ * @oppfx       none
+ * @opcpuid     avx
+ * @opgroup     og_avx_simdfp_datamove
+ * @opxcpttype  4UA
+ * @optest      op1=1 op2=2 -> op1=2
+ * @optest      op1=0 op2=-22 -> op1=-22
  */
-FNIEMOP_STUB(iemOp_vmovupd_Wpd_Vpd);
-//FNIEMOP_DEF(iemOp_vmovupd_Wpd_Vpd)
-//{
-//    IEMOP_MNEMONIC2(MR, VMOVUPD, vmovupd, Wpd, Vpd, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZE);
-//    uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
-//    if ((bRm & X86_MODRM_MOD_MASK) == (3 << X86_MODRM_MOD_SHIFT))
-//    {
-//        /*
-//         * Register, register.
-//         */
-//        IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
-//        IEM_MC_BEGIN(0, 0);
-//        IEM_MC_MAYBE_RAISE_SSE2_RELATED_XCPT();
-//        IEM_MC_ACTUALIZE_SSE_STATE_FOR_CHANGE();
-//        IEM_MC_COPY_XREG_U128((bRm & X86_MODRM_RM_MASK) | pVCpu->iem.s.uRexB,
-//                              ((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg);
-//        IEM_MC_ADVANCE_RIP();
-//        IEM_MC_END();
-//    }
-//    else
-//    {
-//        /*
-//         * Memory, register.
-//         */
-//        IEM_MC_BEGIN(0, 2);
-//        IEM_MC_LOCAL(RTUINT128U,                uSrc); /** @todo optimize this one day... */
-//        IEM_MC_LOCAL(RTGCPTR,                   GCPtrEffSrc);
-//
-//        IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, bRm, 0);
-//        IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
-//        IEM_MC_MAYBE_RAISE_SSE2_RELATED_XCPT();
-//        IEM_MC_ACTUALIZE_SSE_STATE_FOR_READ();
-//
-//        IEM_MC_FETCH_XREG_U128(uSrc, ((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg);
-//        IEM_MC_STORE_MEM_U128(pVCpu->iem.s.iEffSeg, GCPtrEffSrc, uSrc);
-//
-//        IEM_MC_ADVANCE_RIP();
-//        IEM_MC_END();
-//    }
-//    return VINF_SUCCESS;
-//}
+FNIEMOP_DEF(iemOp_vmovups_Wps_Vps)
+{
+    IEMOP_MNEMONIC2(VEX_MR, VMOVUPS, vmovups, Wps_WO, Vps, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZES);
+    Assert(pVCpu->iem.s.uVexLength <= 1);
+    uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
+    if ((bRm & X86_MODRM_MOD_MASK) == (3 << X86_MODRM_MOD_SHIFT))
+    {
+        /*
+         * Register, register.
+         */
+        IEMOP_HLP_DONE_VEX_DECODING_NO_VVVV();
+        IEM_MC_BEGIN(0, 0);
+        IEM_MC_MAYBE_RAISE_AVX_RELATED_XCPT();
+        IEM_MC_ACTUALIZE_AVX_STATE_FOR_CHANGE();
+        if (pVCpu->iem.s.uVexLength == 0)
+            IEM_MC_COPY_YREG_U128_ZX_VLMAX((bRm & X86_MODRM_RM_MASK) | pVCpu->iem.s.uRexB,
+                                           ((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg);
+        else
+            IEM_MC_COPY_YREG_U256_ZX_VLMAX((bRm & X86_MODRM_RM_MASK) | pVCpu->iem.s.uRexB,
+                                           ((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg);
+        IEM_MC_ADVANCE_RIP();
+        IEM_MC_END();
+    }
+    else if (pVCpu->iem.s.uVexLength == 0)
+    {
+        /*
+         * 128-bit: Memory, register.
+         */
+        IEM_MC_BEGIN(0, 2);
+        IEM_MC_LOCAL(RTUINT128U,                uSrc);
+        IEM_MC_LOCAL(RTGCPTR,                   GCPtrEffSrc);
+
+        IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, bRm, 0);
+        IEMOP_HLP_DONE_VEX_DECODING_NO_VVVV();
+        IEM_MC_MAYBE_RAISE_AVX_RELATED_XCPT();
+        IEM_MC_ACTUALIZE_AVX_STATE_FOR_READ();
+
+        IEM_MC_FETCH_YREG_U128(uSrc, ((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg);
+        IEM_MC_STORE_MEM_U128(pVCpu->iem.s.iEffSeg, GCPtrEffSrc, uSrc);
+
+        IEM_MC_ADVANCE_RIP();
+        IEM_MC_END();
+    }
+    else
+    {
+        /*
+         * 256-bit: Memory, register.
+         */
+        IEM_MC_BEGIN(0, 2);
+        IEM_MC_LOCAL(RTUINT256U,                uSrc);
+        IEM_MC_LOCAL(RTGCPTR,                   GCPtrEffSrc);
+
+        IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, bRm, 0);
+        IEMOP_HLP_DONE_VEX_DECODING_NO_VVVV();
+        IEM_MC_MAYBE_RAISE_AVX_RELATED_XCPT();
+        IEM_MC_ACTUALIZE_AVX_STATE_FOR_READ();
+
+        IEM_MC_FETCH_YREG_U256(uSrc, ((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg);
+        IEM_MC_STORE_MEM_U256(pVCpu->iem.s.iEffSeg, GCPtrEffSrc, uSrc);
+
+        IEM_MC_ADVANCE_RIP();
+        IEM_MC_END();
+    }
+    return VINF_SUCCESS;
+}
 
 
 /**
- * @ opcode      0x11
- * @ oppfx       0xf3
- * @ opcpuid     sse
- * @ opgroup     og_sse_simdfp_datamove
- * @ opxcpttype  5
- * @ optest      op1=1 op2=2 -> op1=2
- * @ optest      op1=0 op2=-22 -> op1=-22
+ * @opcode      0x11
+ * @oppfx       0x66
+ * @opcpuid     avx
+ * @opgroup     og_avx_simdfp_datamove
+ * @opxcpttype  4UA
+ * @optest      op1=1 op2=2 -> op1=2
+ * @optest      op1=0 op2=-22 -> op1=-22
  */
-FNIEMOP_STUB(iemOp_vmovss_Wss_Hx_Vss);
-//FNIEMOP_DEF(iemOp_vmovss_Wss_Hx_Vss)
-//{
-//    IEMOP_MNEMONIC2(MR, VMOVSS, vmovss, Wss, Vss, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZE);
-//    uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
-//    if ((bRm & X86_MODRM_MOD_MASK) == (3 << X86_MODRM_MOD_SHIFT))
-//    {
-//        /*
-//         * Register, register.
-//         */
-//        IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
-//        IEM_MC_BEGIN(0, 1);
-//        IEM_MC_LOCAL(uint32_t,                  uSrc);
-//
-//        IEM_MC_MAYBE_RAISE_SSE_RELATED_XCPT();
-//        IEM_MC_ACTUALIZE_SSE_STATE_FOR_CHANGE();
-//        IEM_MC_FETCH_XREG_U32(uSrc, ((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg);
-//        IEM_MC_STORE_XREG_U32((bRm & X86_MODRM_RM_MASK) | pVCpu->iem.s.uRexB, uSrc);
-//
-//        IEM_MC_ADVANCE_RIP();
-//        IEM_MC_END();
-//    }
-//    else
-//    {
-//        /*
-//         * Memory, register.
-//         */
-//        IEM_MC_BEGIN(0, 2);
-//        IEM_MC_LOCAL(uint32_t,                  uSrc);
-//        IEM_MC_LOCAL(RTGCPTR,                   GCPtrEffSrc);
-//
-//        IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, bRm, 0);
-//        IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
-//        IEM_MC_MAYBE_RAISE_SSE_RELATED_XCPT();
-//        IEM_MC_ACTUALIZE_SSE_STATE_FOR_READ();
-//
-//        IEM_MC_FETCH_XREG_U32(uSrc, ((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg);
-//        IEM_MC_STORE_MEM_U32(pVCpu->iem.s.iEffSeg, GCPtrEffSrc, uSrc);
-//
-//        IEM_MC_ADVANCE_RIP();
-//        IEM_MC_END();
-//    }
-//    return VINF_SUCCESS;
-//}
+FNIEMOP_DEF(iemOp_vmovupd_Wpd_Vpd)
+{
+    IEMOP_MNEMONIC2(VEX_MR, VMOVUPD, vmovupd, Wpd_WO, Vpd, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZES);
+    Assert(pVCpu->iem.s.uVexLength <= 1);
+    uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
+    if ((bRm & X86_MODRM_MOD_MASK) == (3 << X86_MODRM_MOD_SHIFT))
+    {
+        /*
+         * Register, register.
+         */
+        IEMOP_HLP_DONE_VEX_DECODING_NO_VVVV();
+        IEM_MC_BEGIN(0, 0);
+        IEM_MC_MAYBE_RAISE_AVX_RELATED_XCPT();
+        IEM_MC_ACTUALIZE_AVX_STATE_FOR_CHANGE();
+        if (pVCpu->iem.s.uVexLength == 0)
+            IEM_MC_COPY_YREG_U128_ZX_VLMAX((bRm & X86_MODRM_RM_MASK) | pVCpu->iem.s.uRexB,
+                                           ((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg);
+        else
+            IEM_MC_COPY_YREG_U256_ZX_VLMAX((bRm & X86_MODRM_RM_MASK) | pVCpu->iem.s.uRexB,
+                                           ((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg);
+        IEM_MC_ADVANCE_RIP();
+        IEM_MC_END();
+    }
+    else if (pVCpu->iem.s.uVexLength == 0)
+    {
+        /*
+         * 128-bit: Memory, register.
+         */
+        IEM_MC_BEGIN(0, 2);
+        IEM_MC_LOCAL(RTUINT128U,                uSrc);
+        IEM_MC_LOCAL(RTGCPTR,                   GCPtrEffSrc);
+
+        IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, bRm, 0);
+        IEMOP_HLP_DONE_VEX_DECODING_NO_VVVV();
+        IEM_MC_MAYBE_RAISE_AVX_RELATED_XCPT();
+        IEM_MC_ACTUALIZE_AVX_STATE_FOR_READ();
+
+        IEM_MC_FETCH_YREG_U128(uSrc, ((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg);
+        IEM_MC_STORE_MEM_U128(pVCpu->iem.s.iEffSeg, GCPtrEffSrc, uSrc);
+
+        IEM_MC_ADVANCE_RIP();
+        IEM_MC_END();
+    }
+    else
+    {
+        /*
+         * 256-bit: Memory, register.
+         */
+        IEM_MC_BEGIN(0, 2);
+        IEM_MC_LOCAL(RTUINT256U,                uSrc);
+        IEM_MC_LOCAL(RTGCPTR,                   GCPtrEffSrc);
+
+        IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, bRm, 0);
+        IEMOP_HLP_DONE_VEX_DECODING_NO_VVVV();
+        IEM_MC_MAYBE_RAISE_AVX_RELATED_XCPT();
+        IEM_MC_ACTUALIZE_AVX_STATE_FOR_READ();
+
+        IEM_MC_FETCH_YREG_U256(uSrc, ((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg);
+        IEM_MC_STORE_MEM_U256(pVCpu->iem.s.iEffSeg, GCPtrEffSrc, uSrc);
+
+        IEM_MC_ADVANCE_RIP();
+        IEM_MC_END();
+    }
+    return VINF_SUCCESS;
+}
+
+
+FNIEMOP_DEF(iemOp_vmovss_Wss_Hss_Vss)
+{
+    Assert(pVCpu->iem.s.uVexLength <= 1);
+    uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
+    if ((bRm & X86_MODRM_MOD_MASK) == (3 << X86_MODRM_MOD_SHIFT))
+    {
+        /**
+         * @opcode      0x11
+         * @oppfx       0xf3
+         * @opcodesub   11 mr/reg
+         * @opcpuid     avx
+         * @opgroup     og_avx_simdfp_datamerge
+         * @opxcpttype  5
+         * @optest      op1=1 op2=0  op3=2    -> op1=2
+         * @optest      op1=0 op2=0  op3=-22  -> op1=0xffffffea
+         * @optest      op1=3 op2=-1 op3=0x77 -> op1=-4294967177
+         * @optest      op1=3 op2=0x42 op3=0x77 -> op1=0x4200000077
+         */
+        IEMOP_MNEMONIC3(VEX_MVR, VMOVSS, vmovss, Uss_WO, HssHi, Vss, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZES | IEMOPHINT_IGNORES_VEX_L);
+        IEMOP_HLP_DONE_VEX_DECODING();
+        IEM_MC_BEGIN(0, 0);
+
+        IEM_MC_MAYBE_RAISE_AVX_RELATED_XCPT();
+        IEM_MC_ACTUALIZE_AVX_STATE_FOR_CHANGE();
+        IEM_MC_MERGE_YREG_U32_U96_ZX_VLMAX((bRm & X86_MODRM_RM_MASK) | pVCpu->iem.s.uRexB /*U32*/,
+                                           ((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg,
+                                           IEM_GET_EFFECTIVE_VVVV(pVCpu) /*Hss*/);
+        IEM_MC_ADVANCE_RIP();
+        IEM_MC_END();
+    }
+    else
+    {
+        /**
+         * @opdone
+         * @opcode      0x11
+         * @oppfx       0xf3
+         * @opcodesub   11 mr/reg
+         * @opcpuid     avx
+         * @opgroup     og_avx_simdfp_datamove
+         * @opxcpttype  5
+         * @opfunction  iemOp_vmovss_Vss_Hss_Wss
+         * @optest      op1=1 op2=2 -> op1=2
+         * @optest      op1=0 op2=-22 -> op1=-22
+         */
+        IEMOP_MNEMONIC2(VEX_MR, VMOVSS, vmovss, Md_WO, Vss, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZES | IEMOPHINT_IGNORES_VEX_L);
+        IEM_MC_BEGIN(0, 2);
+        IEM_MC_LOCAL(uint32_t,                  uSrc);
+        IEM_MC_LOCAL(RTGCPTR,                   GCPtrEffSrc);
+
+        IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, bRm, 0);
+        IEMOP_HLP_DONE_VEX_DECODING_NO_VVVV();
+        IEM_MC_MAYBE_RAISE_AVX_RELATED_XCPT();
+        IEM_MC_ACTUALIZE_AVX_STATE_FOR_READ();
+
+        IEM_MC_FETCH_YREG_U32(uSrc, ((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg);
+        IEM_MC_STORE_MEM_U32(pVCpu->iem.s.iEffSeg, GCPtrEffSrc, uSrc);
+
+        IEM_MC_ADVANCE_RIP();
+        IEM_MC_END();
+    }
+
+    return VINF_SUCCESS;
+}
+
+
+FNIEMOP_DEF(iemOp_vmovsd_Wsd_Hsd_Vsd)
+{
+    Assert(pVCpu->iem.s.uVexLength <= 1);
+    uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
+    if ((bRm & X86_MODRM_MOD_MASK) == (3 << X86_MODRM_MOD_SHIFT))
+    {
+        /**
+         * @opcode      0x11
+         * @oppfx       0xf2
+         * @opcodesub   11 mr/reg
+         * @opcpuid     avx
+         * @opgroup     og_avx_simdfp_datamerge
+         * @opxcpttype  5
+         * @optest      op1=1 op2=0  op3=2    -> op1=2
+         * @optest      op1=0 op2=0  op3=-22  -> op1=0xffffffffffffffea
+         * @optest      op1=3 op2=-1 op3=0x77 ->
+         *              op1=0xffffffffffffffff0000000000000077
+         * @optest      op2=0x42 op3=0x77 -> op1=0x420000000000000077
+         */
+        IEMOP_MNEMONIC3(VEX_MVR, VMOVSD, vmovsd, Usd_WO, HsdHi, Vsd, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZES | IEMOPHINT_IGNORES_VEX_L);
+        IEMOP_HLP_DONE_VEX_DECODING();
+        IEM_MC_BEGIN(0, 0);
+
+        IEM_MC_MAYBE_RAISE_AVX_RELATED_XCPT();
+        IEM_MC_ACTUALIZE_AVX_STATE_FOR_CHANGE();
+        IEM_MC_MERGE_YREG_U64_U64_ZX_VLMAX((bRm & X86_MODRM_RM_MASK) | pVCpu->iem.s.uRexB,
+                                           ((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg,
+                                           IEM_GET_EFFECTIVE_VVVV(pVCpu) /*Hss*/);
+        IEM_MC_ADVANCE_RIP();
+        IEM_MC_END();
+    }
+    else
+    {
+        /**
+         * @opdone
+         * @opcode      0x11
+         * @oppfx       0xf2
+         * @opcodesub   11 mr/reg
+         * @opcpuid     avx
+         * @opgroup     og_avx_simdfp_datamove
+         * @opxcpttype  5
+         * @opfunction  iemOp_vmovsd_Wsd_Hsd_Vsd
+         * @optest      op1=1 op2=2 -> op1=2
+         * @optest      op1=0 op2=-22 -> op1=-22
+         */
+        IEMOP_MNEMONIC2(VEX_MR, VMOVSD, vmovsd, Mq_WO, Vsd, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZES | IEMOPHINT_IGNORES_VEX_L);
+        IEM_MC_BEGIN(0, 2);
+        IEM_MC_LOCAL(uint64_t,                  uSrc);
+        IEM_MC_LOCAL(RTGCPTR,                   GCPtrEffSrc);
+
+        IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, bRm, 0);
+        IEMOP_HLP_DONE_VEX_DECODING_NO_VVVV();
+        IEM_MC_MAYBE_RAISE_AVX_RELATED_XCPT();
+        IEM_MC_ACTUALIZE_AVX_STATE_FOR_READ();
+
+        IEM_MC_FETCH_YREG_U64(uSrc, ((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg);
+        IEM_MC_STORE_MEM_U64(pVCpu->iem.s.iEffSeg, GCPtrEffSrc, uSrc);
+
+        IEM_MC_ADVANCE_RIP();
+        IEM_MC_END();
+    }
+
+    return VINF_SUCCESS;
+}
+
+
+FNIEMOP_DEF(iemOp_vmovlps_Vq_Hq_Mq__vmovhlps)
+{
+    uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
+    if ((bRm & X86_MODRM_MOD_MASK) == (3 << X86_MODRM_MOD_SHIFT))
+    {
+        /**
+         * @opcode      0x12
+         * @opcodesub   11 mr/reg
+         * @oppfx       none
+         * @opcpuid     avx
+         * @opgroup     og_avx_simdfp_datamerge
+         * @opxcpttype  7LZ
+         * @optest         op2=0x2200220122022203
+         *                 op3=0x3304330533063307
+         *              -> op1=0x22002201220222033304330533063307
+         * @optest      op2=-1  op3=-42 -> op1=-42
+         * @note        op3 and op2 are only the 8-byte high XMM register halfs.
+         */
+        IEMOP_MNEMONIC3(VEX_RVM, VMOVHLPS, vmovhlps, Vq_WO, HqHi, UqHi, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZES | IEMOPHINT_VEX_L_ZERO);
+
+        IEMOP_HLP_DONE_VEX_DECODING_L0();
+        IEM_MC_BEGIN(0, 0);
+
+        IEM_MC_MAYBE_RAISE_AVX_RELATED_XCPT();
+        IEM_MC_ACTUALIZE_AVX_STATE_FOR_CHANGE();
+        IEM_MC_MERGE_YREG_U64HI_U64_ZX_VLMAX(((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg,
+                                             (bRm & X86_MODRM_RM_MASK) | pVCpu->iem.s.uRexB,
+                                             IEM_GET_EFFECTIVE_VVVV(pVCpu) /*Hq*/);
+
+        IEM_MC_ADVANCE_RIP();
+        IEM_MC_END();
+    }
+    else
+    {
+        /**
+         * @opdone
+         * @opcode      0x12
+         * @opcodesub   !11 mr/reg
+         * @oppfx       none
+         * @opcpuid     avx
+         * @opgroup     og_avx_simdfp_datamove
+         * @opxcpttype  5LZ
+         * @opfunction  iemOp_vmovlps_Vq_Hq_Mq__vmovhlps
+         * @optest      op1=1 op2=0 op3=0 -> op1=0
+         * @optest      op1=0 op2=-1 op3=-1 -> op1=-1
+         * @optest      op1=1 op2=2 op3=3 -> op1=0x20000000000000003
+         * @optest      op2=-1 op3=0x42 -> op1=0xffffffffffffffff0000000000000042
+         */
+        IEMOP_MNEMONIC3(VEX_RVM_MEM, VMOVLPS, vmovlps, Vq_WO, HqHi, Mq, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZES | IEMOPHINT_VEX_L_ZERO);
+
+        IEM_MC_BEGIN(0, 2);
+        IEM_MC_LOCAL(uint64_t,                  uSrc);
+        IEM_MC_LOCAL(RTGCPTR,                   GCPtrEffSrc);
+
+        IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, bRm, 0);
+        IEMOP_HLP_DONE_VEX_DECODING_L0();
+        IEM_MC_MAYBE_RAISE_AVX_RELATED_XCPT();
+        IEM_MC_ACTUALIZE_AVX_STATE_FOR_CHANGE();
+
+        IEM_MC_FETCH_MEM_U64(uSrc, pVCpu->iem.s.iEffSeg, GCPtrEffSrc);
+        IEM_MC_MERGE_YREG_U64LOCAL_U64_ZX_VLMAX(((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg,
+                                                uSrc,
+                                                IEM_GET_EFFECTIVE_VVVV(pVCpu) /*Hq*/);
+
+        IEM_MC_ADVANCE_RIP();
+        IEM_MC_END();
+    }
+    return VINF_SUCCESS;
+}
 
 
 /**
- * @ opcode      0x11
- * @ oppfx       0xf2
- * @ opcpuid     sse2
- * @ opgroup     og_sse2_pcksclr_datamove
- * @ opxcpttype  5
- * @ optest      op1=1 op2=2 -> op1=2
- * @ optest      op1=0 op2=-42 -> op1=-42
+ * @opcode      0x12
+ * @opcodesub   !11 mr/reg
+ * @oppfx       0x66
+ * @opcpuid     avx
+ * @opgroup     og_avx_pcksclr_datamerge
+ * @opxcpttype  5LZ
+ * @optest      op2=0 op3=2 -> op1=2
+ * @optest      op2=0x22 op3=0x33 -> op1=0x220000000000000033
+ * @optest      op2=0xfffffff0fffffff1 op3=0xeeeeeee8eeeeeee9
+ *              -> op1=0xfffffff0fffffff1eeeeeee8eeeeeee9
  */
-FNIEMOP_STUB(iemOp_vmovsd_Wsd_Hx_Vsd);
-//FNIEMOP_DEF(iemOp_vmovsd_Wsd_Hx_Vsd)
-//{
-//    IEMOP_MNEMONIC2(MR, VMOVSD, vmovsd, Wsd, Vsd, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZE);
-//    uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
-//    if ((bRm & X86_MODRM_MOD_MASK) == (3 << X86_MODRM_MOD_SHIFT))
-//    {
-//        /*
-//         * Register, register.
-//         */
-//        IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
-//        IEM_MC_BEGIN(0, 1);
-//        IEM_MC_LOCAL(uint64_t,                  uSrc);
-//
-//        IEM_MC_MAYBE_RAISE_SSE2_RELATED_XCPT();
-//        IEM_MC_ACTUALIZE_SSE_STATE_FOR_CHANGE();
-//        IEM_MC_FETCH_XREG_U64(uSrc, ((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg);
-//        IEM_MC_STORE_XREG_U64((bRm & X86_MODRM_RM_MASK) | pVCpu->iem.s.uRexB, uSrc);
-//
-//        IEM_MC_ADVANCE_RIP();
-//        IEM_MC_END();
-//    }
-//    else
-//    {
-//        /*
-//         * Memory, register.
-//         */
-//        IEM_MC_BEGIN(0, 2);
-//        IEM_MC_LOCAL(uint64_t,                  uSrc);
-//        IEM_MC_LOCAL(RTGCPTR,                   GCPtrEffSrc);
-//
-//        IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, bRm, 0);
-//        IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
-//        IEM_MC_MAYBE_RAISE_SSE2_RELATED_XCPT();
-//        IEM_MC_ACTUALIZE_SSE_STATE_FOR_READ();
-//
-//        IEM_MC_FETCH_XREG_U64(uSrc, ((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg);
-//        IEM_MC_STORE_MEM_U64(pVCpu->iem.s.iEffSeg, GCPtrEffSrc, uSrc);
-//
-//        IEM_MC_ADVANCE_RIP();
-//        IEM_MC_END();
-//    }
-//    return VINF_SUCCESS;
-//}
-
+FNIEMOP_DEF(iemOp_vmovlpd_Vq_Hq_Mq)
+{
+    uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
+    if ((bRm & X86_MODRM_MOD_MASK) != (3 << X86_MODRM_MOD_SHIFT))
+    {
+        IEMOP_MNEMONIC3(VEX_RVM_MEM, VMOVLPD, vmovlpd, Vq_WO, HqHi, Mq, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZES | IEMOPHINT_VEX_L_ZERO);
 
-FNIEMOP_STUB(iemOp_vmovlps_Vq_Hq_Mq__vmovhlps);
-//FNIEMOP_DEF(iemOp_vmovlps_Vq_Hq_Mq__vmovhlps)
-//{
-//    uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
-//    if ((bRm & X86_MODRM_MOD_MASK) == (3 << X86_MODRM_MOD_SHIFT))
-//    {
-//        /**
-//         * @ opcode      0x12
-//         * @ opcodesub   11 mr/reg
-//         * @ oppfx       none
-//         * @ opcpuid     sse
-//         * @ opgroup     og_sse_simdfp_datamove
-//         * @ opxcpttype  5
-//         * @ optest      op1=1 op2=2 -> op1=2
-//         * @ optest      op1=0 op2=-42 -> op1=-42
-//         */
-//        IEMOP_MNEMONIC2(RM_REG, VMOVHLPS, vmovhlps, Vq, UqHi, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZE);
-//
-//        IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
-//        IEM_MC_BEGIN(0, 1);
-//        IEM_MC_LOCAL(uint64_t,                  uSrc);
-//
-//        IEM_MC_MAYBE_RAISE_SSE_RELATED_XCPT();
-//        IEM_MC_ACTUALIZE_SSE_STATE_FOR_CHANGE();
-//        IEM_MC_FETCH_XREG_HI_U64(uSrc, (bRm & X86_MODRM_RM_MASK) | pVCpu->iem.s.uRexB);
-//        IEM_MC_STORE_XREG_U64(((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg, uSrc);
-//
-//        IEM_MC_ADVANCE_RIP();
-//        IEM_MC_END();
-//    }
-//    else
-//    {
-//        /**
-//         * @ opdone
-//         * @ opcode      0x12
-//         * @ opcodesub   !11 mr/reg
-//         * @ oppfx       none
-//         * @ opcpuid     sse
-//         * @ opgroup     og_sse_simdfp_datamove
-//         * @ opxcpttype  5
-//         * @ optest      op1=1 op2=2 -> op1=2
-//         * @ optest      op1=0 op2=-42 -> op1=-42
-//         * @ opfunction  iemOp_vmovlps_Vq_Hq_Mq__vmovhlps
-//         */
-//        IEMOP_MNEMONIC2(RM_MEM, VMOVLPS, vmovlps, Vq, Mq, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZE);
-//
-//        IEM_MC_BEGIN(0, 2);
-//        IEM_MC_LOCAL(uint64_t,                  uSrc);
-//        IEM_MC_LOCAL(RTGCPTR,                   GCPtrEffSrc);
-//
-//        IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, bRm, 0);
-//        IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
-//        IEM_MC_MAYBE_RAISE_SSE_RELATED_XCPT();
-//        IEM_MC_ACTUALIZE_SSE_STATE_FOR_CHANGE();
-//
-//        IEM_MC_FETCH_MEM_U64(uSrc, pVCpu->iem.s.iEffSeg, GCPtrEffSrc);
-//        IEM_MC_STORE_XREG_U64(((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg, uSrc);
-//
-//        IEM_MC_ADVANCE_RIP();
-//        IEM_MC_END();
-//    }
-//    return VINF_SUCCESS;
-//}
+        IEM_MC_BEGIN(0, 2);
+        IEM_MC_LOCAL(uint64_t,                  uSrc);
+        IEM_MC_LOCAL(RTGCPTR,                   GCPtrEffSrc);
+
+        IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, bRm, 0);
+        IEMOP_HLP_DONE_VEX_DECODING_L0();
+        IEM_MC_MAYBE_RAISE_AVX_RELATED_XCPT();
+        IEM_MC_ACTUALIZE_AVX_STATE_FOR_CHANGE();
+
+        IEM_MC_FETCH_MEM_U64(uSrc, pVCpu->iem.s.iEffSeg, GCPtrEffSrc);
+        IEM_MC_MERGE_YREG_U64LOCAL_U64_ZX_VLMAX(((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg,
+                                                uSrc,
+                                                IEM_GET_EFFECTIVE_VVVV(pVCpu) /*Hq*/);
+
+        IEM_MC_ADVANCE_RIP();
+        IEM_MC_END();
+        return VINF_SUCCESS;
+    }
+
+    /**
+     * @opdone
+     * @opmnemonic  udvex660f12m3
+     * @opcode      0x12
+     * @opcodesub   11 mr/reg
+     * @oppfx       0x66
+     * @opunused    immediate
+     * @opcpuid     avx
+     * @optest      ->
+     */
+    return IEMOP_RAISE_INVALID_OPCODE();
+}
 
 
 /**
- * @ opcode      0x12
- * @ opcodesub   !11 mr/reg
- * @ oppfx       0x66
- * @ opcpuid     sse2
- * @ opgroup     og_sse2_pcksclr_datamove
- * @ opxcpttype  5
- * @ optest      op1=1 op2=2 -> op1=2
- * @ optest      op1=0 op2=-42 -> op1=-42
+ * @opcode      0x12
+ * @oppfx       0xf3
+ * @opcpuid     avx
+ * @opgroup     og_avx_pcksclr_datamove
+ * @opxcpttype  4
+ * @optest      vex.l==0 / op1=-1 op2=0xdddddddd00000002eeeeeeee00000001
+ *              -> op1=0x00000002000000020000000100000001
+ * @optest      vex.l==1 /
+ *                 op2=0xbbbbbbbb00000004cccccccc00000003dddddddd00000002eeeeeeee00000001
+ *              -> op1=0x0000000400000004000000030000000300000002000000020000000100000001
  */
-FNIEMOP_STUB(iemOp_vmovlpd_Vq_Hq_Mq);
-//FNIEMOP_DEF(iemOp_vmovlpd_Vq_Hq_Mq)
-//{
-//    uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
-//    if ((bRm & X86_MODRM_MOD_MASK) != (3 << X86_MODRM_MOD_SHIFT))
-//    {
-//        IEMOP_MNEMONIC2(RM_MEM, VMOVLPD, vmovlpd, Vq, Mq, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZE);
-//
-//        IEM_MC_BEGIN(0, 2);
-//        IEM_MC_LOCAL(uint64_t,                  uSrc);
-//        IEM_MC_LOCAL(RTGCPTR,                   GCPtrEffSrc);
-//
-//        IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, bRm, 0);
-//        IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
-//        IEM_MC_MAYBE_RAISE_SSE2_RELATED_XCPT();
-//        IEM_MC_ACTUALIZE_SSE_STATE_FOR_CHANGE();
-//
-//        IEM_MC_FETCH_MEM_U64(uSrc, pVCpu->iem.s.iEffSeg, GCPtrEffSrc);
-//        IEM_MC_STORE_XREG_U64(((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg, uSrc);
-//
-//        IEM_MC_ADVANCE_RIP();
-//        IEM_MC_END();
-//        return VINF_SUCCESS;
-//    }
-//
-//    /**
-//     * @ opdone
-//     * @ opmnemonic  ud660f12m3
-//     * @ opcode      0x12
-//     * @ opcodesub   11 mr/reg
-//     * @ oppfx       0x66
-//     * @ opunused    immediate
-//     * @ opcpuid     sse
-//     * @ optest      ->
-//     */
-//    return IEMOP_RAISE_INVALID_OPCODE();
-//}
+FNIEMOP_DEF(iemOp_vmovsldup_Vx_Wx)
+{
+    IEMOP_MNEMONIC2(VEX_RM, VMOVSLDUP, vmovsldup, Vx_WO, Wx, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZES);
+    Assert(pVCpu->iem.s.uVexLength <= 1);
+    uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
+    if ((bRm & X86_MODRM_MOD_MASK) == (3 << X86_MODRM_MOD_SHIFT))
+    {
+        /*
+         * Register, register.
+         */
+        IEMOP_HLP_DONE_VEX_DECODING_NO_VVVV();
+        if (pVCpu->iem.s.uVexLength == 0)
+        {
+            IEM_MC_BEGIN(2, 0);
+            IEM_MC_ARG(PRTUINT128U,                 puDst, 0);
+            IEM_MC_ARG(PCRTUINT128U,                puSrc, 1);
+
+            IEM_MC_MAYBE_RAISE_AVX_RELATED_XCPT();
+            IEM_MC_PREPARE_AVX_USAGE();
+
+            IEM_MC_REF_XREG_U128_CONST(puSrc, (bRm & X86_MODRM_RM_MASK) | pVCpu->iem.s.uRexB);
+            IEM_MC_REF_XREG_U128(puDst, ((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg);
+            IEM_MC_CALL_SSE_AIMPL_2(iemAImpl_movsldup, puDst, puSrc);
+            IEM_MC_CLEAR_YREG_128_UP(((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg);
+
+            IEM_MC_ADVANCE_RIP();
+            IEM_MC_END();
+        }
+        else
+        {
+            IEM_MC_BEGIN(3, 0);
+            IEM_MC_IMPLICIT_AVX_AIMPL_ARGS();
+            IEM_MC_ARG_CONST(uint8_t,   iYRegDst, ((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg, 1);
+            IEM_MC_ARG_CONST(uint8_t,   iYRegSrc, (bRm & X86_MODRM_RM_MASK) | pVCpu->iem.s.uRexB, 2);
+
+            IEM_MC_MAYBE_RAISE_AVX_RELATED_XCPT();
+            IEM_MC_PREPARE_AVX_USAGE();
+            IEM_MC_CALL_AVX_AIMPL_2(iemAImpl_vmovsldup_256_rr, iYRegDst, iYRegSrc);
+
+            IEM_MC_ADVANCE_RIP();
+            IEM_MC_END();
+        }
+    }
+    else
+    {
+        /*
+         * Register, memory.
+         */
+        if (pVCpu->iem.s.uVexLength == 0)
+        {
+            IEM_MC_BEGIN(2, 2);
+            IEM_MC_LOCAL(RTUINT128U,                uSrc);
+            IEM_MC_LOCAL(RTGCPTR,                   GCPtrEffSrc);
+            IEM_MC_ARG(PRTUINT128U,                 puDst, 0);
+            IEM_MC_ARG_LOCAL_REF(PCRTUINT128U,      puSrc, uSrc, 1);
+
+            IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, bRm, 0);
+            IEMOP_HLP_DONE_VEX_DECODING_NO_VVVV();
+            IEM_MC_MAYBE_RAISE_AVX_RELATED_XCPT();
+            IEM_MC_PREPARE_AVX_USAGE();
+
+            IEM_MC_FETCH_MEM_U128(uSrc, pVCpu->iem.s.iEffSeg, GCPtrEffSrc);
+            IEM_MC_REF_XREG_U128(puDst, ((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg);
+            IEM_MC_CALL_SSE_AIMPL_2(iemAImpl_movsldup, puDst, puSrc);
+            IEM_MC_CLEAR_YREG_128_UP(((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg);
+
+            IEM_MC_ADVANCE_RIP();
+            IEM_MC_END();
+        }
+        else
+        {
+            IEM_MC_BEGIN(3, 2);
+            IEM_MC_LOCAL(RTUINT256U,            uSrc);
+            IEM_MC_LOCAL(RTGCPTR,               GCPtrEffSrc);
+            IEM_MC_IMPLICIT_AVX_AIMPL_ARGS();
+            IEM_MC_ARG_CONST(uint8_t,   iYRegDst, ((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg, 1);
+            IEM_MC_ARG_LOCAL_REF(PCRTUINT256U,  puSrc, uSrc, 2);
+
+            IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, bRm, 0);
+            IEMOP_HLP_DONE_VEX_DECODING_NO_VVVV();
+            IEM_MC_MAYBE_RAISE_AVX_RELATED_XCPT();
+            IEM_MC_PREPARE_AVX_USAGE();
+
+            IEM_MC_FETCH_MEM_U256(uSrc, pVCpu->iem.s.iEffSeg, GCPtrEffSrc);
+            IEM_MC_CALL_AVX_AIMPL_2(iemAImpl_vmovsldup_256_rm, iYRegDst, puSrc);
+
+            IEM_MC_ADVANCE_RIP();
+            IEM_MC_END();
+        }
+    }
+    return VINF_SUCCESS;
+}
 
 
 /**
- * @ opcode      0x12
- * @ oppfx       0xf3
- * @ opcpuid     sse3
- * @ opgroup     og_sse3_pcksclr_datamove
- * @ opxcpttype  4
- * @ optest      op1=-1 op2=0xdddddddd00000002eeeeeeee00000001 ->
- *               op1=0x00000002000000020000000100000001
+ * @opcode      0x12
+ * @oppfx       0xf2
+ * @opcpuid     avx
+ * @opgroup     og_avx_pcksclr_datamove
+ * @opxcpttype  5
+ * @optest      vex.l==0 / op2=0xddddddddeeeeeeee2222222211111111
+ *              ->         op1=0x22222222111111112222222211111111
+ * @optest      vex.l==1 / op2=0xbbbbbbbbcccccccc4444444433333333ddddddddeeeeeeee2222222211111111
+ *              ->         op1=0x4444444433333333444444443333333322222222111111112222222211111111
  */
-FNIEMOP_STUB(iemOp_vmovsldup_Vx_Wx);
-//FNIEMOP_DEF(iemOp_vmovsldup_Vx_Wx)
-//{
-//    IEMOP_MNEMONIC2(RM, VMOVSLDUP, vmovsldup, Vdq, Wdq, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZE);
-//    uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
-//    if ((bRm & X86_MODRM_MOD_MASK) == (3 << X86_MODRM_MOD_SHIFT))
-//    {
-//        /*
-//         * Register, register.
-//         */
-//        IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
-//        IEM_MC_BEGIN(2, 0);
-//        IEM_MC_ARG(PRTUINT128U,                 puDst, 0);
-//        IEM_MC_ARG(PCRTUINT128U,                puSrc, 1);
-//
-//        IEM_MC_MAYBE_RAISE_SSE3_RELATED_XCPT();
-//        IEM_MC_PREPARE_SSE_USAGE();
-//
-//        IEM_MC_REF_XREG_U128_CONST(puSrc, (bRm & X86_MODRM_RM_MASK) | pVCpu->iem.s.uRexB);
-//        IEM_MC_REF_XREG_U128(puDst, ((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg);
-//        IEM_MC_CALL_SSE_AIMPL_2(iemAImpl_movsldup, puDst, puSrc);
-//
-//        IEM_MC_ADVANCE_RIP();
-//        IEM_MC_END();
-//    }
-//    else
-//    {
-//        /*
-//         * Register, memory.
-//         */
-//        IEM_MC_BEGIN(2, 2);
-//        IEM_MC_LOCAL(RTUINT128U,                uSrc);
-//        IEM_MC_LOCAL(RTGCPTR,                   GCPtrEffSrc);
-//        IEM_MC_ARG(PRTUINT128U,                 puDst, 0);
-//        IEM_MC_ARG_LOCAL_REF(PCRTUINT128U,      puSrc, uSrc, 1);
-//
-//        IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, bRm, 0);
-//        IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
-//        IEM_MC_MAYBE_RAISE_SSE3_RELATED_XCPT();
-//        IEM_MC_PREPARE_SSE_USAGE();
-//
-//        IEM_MC_FETCH_MEM_U128_ALIGN_SSE(uSrc, pVCpu->iem.s.iEffSeg, GCPtrEffSrc);
-//        IEM_MC_REF_XREG_U128(puDst, ((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg);
-//        IEM_MC_CALL_SSE_AIMPL_2(iemAImpl_movsldup, puDst, puSrc);
-//
-//        IEM_MC_ADVANCE_RIP();
-//        IEM_MC_END();
-//    }
-//    return VINF_SUCCESS;
-//}
+FNIEMOP_DEF(iemOp_vmovddup_Vx_Wx)
+{
+    IEMOP_MNEMONIC2(VEX_RM, VMOVDDUP, vmovddup, Vx_WO, Wx, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZES);
+    uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
+    if ((bRm & X86_MODRM_MOD_MASK) == (3 << X86_MODRM_MOD_SHIFT))
+    {
+        /*
+         * Register, register.
+         */
+        IEMOP_HLP_DONE_VEX_DECODING_NO_VVVV();
+        if (pVCpu->iem.s.uVexLength == 0)
+        {
+            IEM_MC_BEGIN(2, 0);
+            IEM_MC_ARG(PRTUINT128U,                 puDst, 0);
+            IEM_MC_ARG(uint64_t,                    uSrc, 1);
+
+            IEM_MC_MAYBE_RAISE_AVX_RELATED_XCPT();
+            IEM_MC_PREPARE_AVX_USAGE();
+
+            IEM_MC_FETCH_XREG_U64(uSrc, (bRm & X86_MODRM_RM_MASK) | pVCpu->iem.s.uRexB);
+            IEM_MC_REF_XREG_U128(puDst, ((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg);
+            IEM_MC_CALL_SSE_AIMPL_2(iemAImpl_movddup, puDst, uSrc);
+            IEM_MC_CLEAR_YREG_128_UP(((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg);
+
+            IEM_MC_ADVANCE_RIP();
+            IEM_MC_END();
+        }
+        else
+        {
+            IEM_MC_BEGIN(3, 0);
+            IEM_MC_IMPLICIT_AVX_AIMPL_ARGS();
+            IEM_MC_ARG_CONST(uint8_t,   iYRegDst, ((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg, 1);
+            IEM_MC_ARG_CONST(uint8_t,   iYRegSrc, (bRm & X86_MODRM_RM_MASK) | pVCpu->iem.s.uRexB, 2);
+
+            IEM_MC_MAYBE_RAISE_AVX_RELATED_XCPT();
+            IEM_MC_PREPARE_AVX_USAGE();
+            IEM_MC_CALL_AVX_AIMPL_2(iemAImpl_vmovddup_256_rr, iYRegDst, iYRegSrc);
+
+            IEM_MC_ADVANCE_RIP();
+            IEM_MC_END();
+        }
+    }
+    else
+    {
+        /*
+         * Register, memory.
+         */
+        if (pVCpu->iem.s.uVexLength == 0)
+        {
+            IEM_MC_BEGIN(2, 2);
+            IEM_MC_LOCAL(RTGCPTR,                   GCPtrEffSrc);
+            IEM_MC_ARG(PRTUINT128U,                 puDst, 0);
+            IEM_MC_ARG(uint64_t,                    uSrc, 1);
+
+            IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, bRm, 0);
+            IEMOP_HLP_DONE_VEX_DECODING_NO_VVVV();
+            IEM_MC_MAYBE_RAISE_AVX_RELATED_XCPT();
+            IEM_MC_PREPARE_AVX_USAGE();
+
+            IEM_MC_FETCH_MEM_U64(uSrc, pVCpu->iem.s.iEffSeg, GCPtrEffSrc);
+            IEM_MC_REF_XREG_U128(puDst, ((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg);
+            IEM_MC_CALL_SSE_AIMPL_2(iemAImpl_movddup, puDst, uSrc);
+            IEM_MC_CLEAR_YREG_128_UP(((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg);
+
+            IEM_MC_ADVANCE_RIP();
+            IEM_MC_END();
+        }
+        else
+        {
+            IEM_MC_BEGIN(3, 2);
+            IEM_MC_LOCAL(RTUINT256U,            uSrc);
+            IEM_MC_LOCAL(RTGCPTR,               GCPtrEffSrc);
+            IEM_MC_IMPLICIT_AVX_AIMPL_ARGS();
+            IEM_MC_ARG_CONST(uint8_t,   iYRegDst, ((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg, 1);
+            IEM_MC_ARG_LOCAL_REF(PCRTUINT256U,  puSrc, uSrc, 2);
+
+            IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, bRm, 0);
+            IEMOP_HLP_DONE_VEX_DECODING_NO_VVVV();
+            IEM_MC_MAYBE_RAISE_AVX_RELATED_XCPT();
+            IEM_MC_PREPARE_AVX_USAGE();
+
+            IEM_MC_FETCH_MEM_U256(uSrc, pVCpu->iem.s.iEffSeg, GCPtrEffSrc);
+            IEM_MC_CALL_AVX_AIMPL_2(iemAImpl_vmovddup_256_rm, iYRegDst, puSrc);
+
+            IEM_MC_ADVANCE_RIP();
+            IEM_MC_END();
+        }
+    }
+    return VINF_SUCCESS;
+}
 
 
 /**
- * @ opcode      0x12
- * @ oppfx       0xf2
- * @ opcpuid     sse3
- * @ opgroup     og_sse3_pcksclr_datamove
- * @ opxcpttype  5
- * @ optest      op1=-1 op2=0xddddddddeeeeeeee2222222211111111 ->
- *               op1=0x22222222111111112222222211111111
+ * @opcode      0x13
+ * @opcodesub   !11 mr/reg
+ * @oppfx       none
+ * @opcpuid     avx
+ * @opgroup     og_avx_simdfp_datamove
+ * @opxcpttype  5
+ * @optest      op1=1 op2=2 -> op1=2
+ * @optest      op1=0 op2=-42 -> op1=-42
  */
-FNIEMOP_STUB(iemOp_vmovddup_Vx_Wx);
-//FNIEMOP_DEF(iemOp_vmovddup_Vx_Wx)
-//{
-//    IEMOP_MNEMONIC2(RM, VMOVDDUP, vmovddup, Vdq, Wdq, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZE);
-//    uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
-//    if ((bRm & X86_MODRM_MOD_MASK) == (3 << X86_MODRM_MOD_SHIFT))
-//    {
-//        /*
-//         * Register, register.
-//         */
-//        IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
-//        IEM_MC_BEGIN(2, 0);
-//        IEM_MC_ARG(PRTUINT128U,                 puDst, 0);
-//        IEM_MC_ARG(uint64_t,                    uSrc, 1);
-//
-//        IEM_MC_MAYBE_RAISE_SSE3_RELATED_XCPT();
-//        IEM_MC_PREPARE_SSE_USAGE();
-//
-//        IEM_MC_FETCH_XREG_U64(uSrc, (bRm & X86_MODRM_RM_MASK) | pVCpu->iem.s.uRexB);
-//        IEM_MC_REF_XREG_U128(puDst, ((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg);
-//        IEM_MC_CALL_SSE_AIMPL_2(iemAImpl_movddup, puDst, uSrc);
-//
-//        IEM_MC_ADVANCE_RIP();
-//        IEM_MC_END();
-//    }
-//    else
-//    {
-//        /*
-//         * Register, memory.
-//         */
-//        IEM_MC_BEGIN(2, 2);
-//        IEM_MC_LOCAL(RTGCPTR,                   GCPtrEffSrc);
-//        IEM_MC_ARG(PRTUINT128U,                 puDst, 0);
-//        IEM_MC_ARG(uint64_t,                    uSrc, 1);
-//
-//        IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, bRm, 0);
-//        IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
-//        IEM_MC_MAYBE_RAISE_SSE3_RELATED_XCPT();
-//        IEM_MC_PREPARE_SSE_USAGE();
-//
-//        IEM_MC_FETCH_MEM_U64(uSrc, pVCpu->iem.s.iEffSeg, GCPtrEffSrc);
-//        IEM_MC_REF_XREG_U128(puDst, ((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg);
-//        IEM_MC_CALL_SSE_AIMPL_2(iemAImpl_movddup, puDst, uSrc);
-//
-//        IEM_MC_ADVANCE_RIP();
-//        IEM_MC_END();
-//    }
-//    return VINF_SUCCESS;
-//}
+FNIEMOP_DEF(iemOp_vmovlps_Mq_Vq)
+{
+    uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
+    if ((bRm & X86_MODRM_MOD_MASK) != (3 << X86_MODRM_MOD_SHIFT))
+    {
+        IEMOP_MNEMONIC2(VEX_MR_MEM, VMOVLPS, vmovlps, Mq_WO, Vq, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZES | IEMOPHINT_VEX_L_ZERO);
 
+        IEM_MC_BEGIN(0, 2);
+        IEM_MC_LOCAL(uint64_t,                  uSrc);
+        IEM_MC_LOCAL(RTGCPTR,                   GCPtrEffSrc);
 
-/** Opcode VEX.0F 0x13 - vmovlps Mq, Vq */
-FNIEMOP_STUB(iemOp_vmovlps_Mq_Vq);
+        IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, bRm, 0);
+        IEMOP_HLP_DONE_VEX_DECODING_L0_AND_NO_VVVV();
+        IEM_MC_MAYBE_RAISE_AVX_RELATED_XCPT();
+        IEM_MC_ACTUALIZE_AVX_STATE_FOR_READ();
 
-/** Opcode VEX.66.0F 0x13 - vmovlpd Mq, Vq */
-FNIEMOP_STUB(iemOp_vmovlpd_Mq_Vq);
-//FNIEMOP_DEF(iemOp_vmovlpd_Mq_Vq)
-//{
-//    IEMOP_MNEMONIC(vmovlpd_Mq_Vq, "movlpd Mq,Vq");
-//    uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
-//    if ((bRm & X86_MODRM_MOD_MASK) == (3 << X86_MODRM_MOD_SHIFT))
-//    {
-//#if 0
-//        /*
-//         * Register, register.
-//         */
-//        IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
-//        IEM_MC_BEGIN(0, 1);
-//        IEM_MC_LOCAL(uint64_t,                  uSrc);
-//        IEM_MC_MAYBE_RAISE_SSE2_RELATED_XCPT();
-//        IEM_MC_ACTUALIZE_SSE_STATE_FOR_CHANGE();
-//        IEM_MC_FETCH_XREG_U64(uSrc, ((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg);
-//        IEM_MC_STORE_XREG_U64((bRm & X86_MODRM_RM_MASK) | pVCpu->iem.s.uRexB, uSrc);
-//        IEM_MC_ADVANCE_RIP();
-//        IEM_MC_END();
-//#else
-//        return IEMOP_RAISE_INVALID_OPCODE();
-//#endif
-//    }
-//    else
-//    {
-//        /*
-//         * Memory, register.
-//         */
-//        IEM_MC_BEGIN(0, 2);
-//        IEM_MC_LOCAL(uint64_t,                  uSrc);
-//        IEM_MC_LOCAL(RTGCPTR,                   GCPtrEffSrc);
-//
-//        IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, bRm, 0);
-//        IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
-//        IEM_MC_MAYBE_RAISE_SSE2_RELATED_XCPT();
-//        IEM_MC_ACTUALIZE_SSE_STATE_FOR_READ();
-//
-//        IEM_MC_FETCH_XREG_U64(uSrc, ((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg);
-//        IEM_MC_STORE_MEM_U64(pVCpu->iem.s.iEffSeg, GCPtrEffSrc, uSrc);
-//
-//        IEM_MC_ADVANCE_RIP();
-//        IEM_MC_END();
-//    }
-//    return VINF_SUCCESS;
-//}
+        IEM_MC_FETCH_YREG_U64(uSrc, ((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg);
+        IEM_MC_STORE_MEM_U64(pVCpu->iem.s.iEffSeg, GCPtrEffSrc, uSrc);
+
+        IEM_MC_ADVANCE_RIP();
+        IEM_MC_END();
+        return VINF_SUCCESS;
+    }
+
+    /**
+     * @opdone
+     * @opmnemonic  udvex0f13m3
+     * @opcode      0x13
+     * @opcodesub   11 mr/reg
+     * @oppfx       none
+     * @opunused    immediate
+     * @opcpuid     avx
+     * @optest      ->
+     */
+    return IEMOP_RAISE_INVALID_OPCODE();
+}
+
+
+/**
+ * @opcode      0x13
+ * @opcodesub   !11 mr/reg
+ * @oppfx       0x66
+ * @opcpuid     avx
+ * @opgroup     og_avx_pcksclr_datamove
+ * @opxcpttype  5
+ * @optest      op1=1 op2=2 -> op1=2
+ * @optest      op1=0 op2=-42 -> op1=-42
+ */
+FNIEMOP_DEF(iemOp_vmovlpd_Mq_Vq)
+{
+    uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
+    if ((bRm & X86_MODRM_MOD_MASK) != (3 << X86_MODRM_MOD_SHIFT))
+    {
+        IEMOP_MNEMONIC2(VEX_MR_MEM, VMOVLPD, vmovlpd, Mq_WO, Vq, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZES | IEMOPHINT_VEX_L_ZERO);
+        IEM_MC_BEGIN(0, 2);
+        IEM_MC_LOCAL(uint64_t,                  uSrc);
+        IEM_MC_LOCAL(RTGCPTR,                   GCPtrEffSrc);
+
+        IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, bRm, 0);
+        IEMOP_HLP_DONE_VEX_DECODING_L0_AND_NO_VVVV();
+        IEM_MC_MAYBE_RAISE_AVX_RELATED_XCPT();
+        IEM_MC_ACTUALIZE_AVX_STATE_FOR_READ();
+
+        IEM_MC_FETCH_YREG_U64(uSrc, ((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg);
+        IEM_MC_STORE_MEM_U64(pVCpu->iem.s.iEffSeg, GCPtrEffSrc, uSrc);
+
+        IEM_MC_ADVANCE_RIP();
+        IEM_MC_END();
+        return VINF_SUCCESS;
+    }
+
+    /**
+     * @opdone
+     * @opmnemonic  udvex660f13m3
+     * @opcode      0x13
+     * @opcodesub   11 mr/reg
+     * @oppfx       0x66
+     * @opunused    immediate
+     * @opcpuid     avx
+     * @optest      ->
+     */
+    return IEMOP_RAISE_INVALID_OPCODE();
+}
 
 /*  Opcode VEX.F3.0F 0x13 - invalid */
 /*  Opcode VEX.F2.0F 0x13 - invalid */
@@ -663,183 +1090,355 @@ FNIEMOP_STUB(iemOp_vmovhpdv1_Mq_Vq);  //NEXT
 /*  Opcode VEX.0F 0x26 - invalid */
 /*  Opcode VEX.0F 0x27 - invalid */
 
-/** Opcode VEX.0F 0x28 - vmovaps Vps, Wps */
-FNIEMOP_STUB(iemOp_vmovaps_Vps_Wps);
-//FNIEMOP_DEF(iemOp_vmovaps_Vps_Wps)
-//{
-//    IEMOP_MNEMONIC(vmovaps_Vps_Wps, "vmovaps Vps,Wps");
-//    uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
-//    if ((bRm & X86_MODRM_MOD_MASK) == (3 << X86_MODRM_MOD_SHIFT))
-//    {
-//        /*
-//         * Register, register.
-//         */
-//        IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
-//        IEM_MC_BEGIN(0, 0);
-//        IEM_MC_MAYBE_RAISE_SSE_RELATED_XCPT();
-//        IEM_MC_ACTUALIZE_SSE_STATE_FOR_CHANGE();
-//        IEM_MC_COPY_XREG_U128(((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg,
-//                              (bRm & X86_MODRM_RM_MASK) | pVCpu->iem.s.uRexB);
-//        IEM_MC_ADVANCE_RIP();
-//        IEM_MC_END();
-//    }
-//    else
-//    {
-//        /*
-//         * Register, memory.
-//         */
-//        IEM_MC_BEGIN(0, 2);
-//        IEM_MC_LOCAL(RTUINT128U,                uSrc); /** @todo optimize this one day... */
-//        IEM_MC_LOCAL(RTGCPTR,                   GCPtrEffSrc);
-//
-//        IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, bRm, 0);
-//        IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
-//        IEM_MC_MAYBE_RAISE_SSE_RELATED_XCPT();
-//        IEM_MC_ACTUALIZE_SSE_STATE_FOR_CHANGE();
-//
-//        IEM_MC_FETCH_MEM_U128_ALIGN_SSE(uSrc, pVCpu->iem.s.iEffSeg, GCPtrEffSrc);
-//        IEM_MC_STORE_XREG_U128(((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg, uSrc);
-//
-//        IEM_MC_ADVANCE_RIP();
-//        IEM_MC_END();
-//    }
-//    return VINF_SUCCESS;
-//}
+/**
+ * @opcode      0x28
+ * @oppfx       none
+ * @opcpuid     avx
+ * @opgroup     og_avx_pcksclr_datamove
+ * @opxcpttype  1
+ * @optest      op1=1 op2=2 -> op1=2
+ * @optest      op1=0 op2=-42 -> op1=-42
+ * @note        Almost identical to vmovapd.
+ */
+FNIEMOP_DEF(iemOp_vmovaps_Vps_Wps)
+{
+    IEMOP_MNEMONIC2(VEX_RM, VMOVAPS, vmovaps, Vps_WO, Wps, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZES);
+    uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
+    Assert(pVCpu->iem.s.uVexLength <= 1);
+    if ((bRm & X86_MODRM_MOD_MASK) == (3 << X86_MODRM_MOD_SHIFT))
+    {
+        /*
+         * Register, register.
+         */
+        IEMOP_HLP_DONE_VEX_DECODING_NO_VVVV();
+        IEM_MC_BEGIN(1, 0);
+
+        IEM_MC_MAYBE_RAISE_AVX_RELATED_XCPT();
+        IEM_MC_ACTUALIZE_AVX_STATE_FOR_CHANGE();
+        if (pVCpu->iem.s.uVexLength == 0)
+            IEM_MC_COPY_YREG_U128_ZX_VLMAX(((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg,
+                                           (bRm & X86_MODRM_RM_MASK) | pVCpu->iem.s.uRexB);
+        else
+            IEM_MC_COPY_YREG_U256_ZX_VLMAX(((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg,
+                                           (bRm & X86_MODRM_RM_MASK) | pVCpu->iem.s.uRexB);
+        IEM_MC_ADVANCE_RIP();
+        IEM_MC_END();
+    }
+    else
+    {
+        /*
+         * Register, memory.
+         */
+        if (pVCpu->iem.s.uVexLength == 0)
+        {
+            IEM_MC_BEGIN(0, 2);
+            IEM_MC_LOCAL(RTGCPTR,                   GCPtrEffSrc);
+            IEM_MC_LOCAL(RTUINT128U,                uSrc);
+
+            IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, bRm, 0);
+            IEMOP_HLP_DONE_VEX_DECODING_NO_VVVV();
+            IEM_MC_MAYBE_RAISE_AVX_RELATED_XCPT();
+            IEM_MC_ACTUALIZE_AVX_STATE_FOR_CHANGE();
+
+            IEM_MC_FETCH_MEM_U128_ALIGN_SSE(uSrc, pVCpu->iem.s.iEffSeg, GCPtrEffSrc);
+            IEM_MC_STORE_YREG_U128_ZX_VLMAX(((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg, uSrc);
+
+            IEM_MC_ADVANCE_RIP();
+            IEM_MC_END();
+        }
+        else
+        {
+            IEM_MC_BEGIN(0, 2);
+            IEM_MC_LOCAL(RTGCPTR,                   GCPtrEffSrc);
+            IEM_MC_LOCAL(RTUINT256U,                uSrc);
+
+            IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, bRm, 0);
+            IEMOP_HLP_DONE_VEX_DECODING_NO_VVVV();
+            IEM_MC_MAYBE_RAISE_AVX_RELATED_XCPT();
+            IEM_MC_ACTUALIZE_AVX_STATE_FOR_CHANGE();
+
+            IEM_MC_FETCH_MEM_U256_ALIGN_AVX(uSrc, pVCpu->iem.s.iEffSeg, GCPtrEffSrc);
+            IEM_MC_STORE_YREG_U256_ZX_VLMAX(((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg, uSrc);
+
+            IEM_MC_ADVANCE_RIP();
+            IEM_MC_END();
+        }
+    }
+    return VINF_SUCCESS;
+}
 
-/** Opcode VEX.66.0F 0x28 - vmovapd Vpd, Wpd */
-FNIEMOP_STUB(iemOp_vmovapd_Vpd_Wpd);
-//FNIEMOP_DEF(iemOp_vmovapd_Vpd_Wpd)
-//{
-//    IEMOP_MNEMONIC(vmovapd_Wpd_Wpd, "vmovapd Wpd,Wpd");
-//    uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
-//    if ((bRm & X86_MODRM_MOD_MASK) == (3 << X86_MODRM_MOD_SHIFT))
-//    {
-//        /*
-//         * Register, register.
-//         */
-//        IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
-//        IEM_MC_BEGIN(0, 0);
-//        IEM_MC_MAYBE_RAISE_SSE2_RELATED_XCPT();
-//        IEM_MC_ACTUALIZE_SSE_STATE_FOR_CHANGE();
-//        IEM_MC_COPY_XREG_U128(((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg,
-//                              (bRm & X86_MODRM_RM_MASK) | pVCpu->iem.s.uRexB);
-//        IEM_MC_ADVANCE_RIP();
-//        IEM_MC_END();
-//    }
-//    else
-//    {
-//        /*
-//         * Register, memory.
-//         */
-//        IEM_MC_BEGIN(0, 2);
-//        IEM_MC_LOCAL(RTUINT128U,                uSrc); /** @todo optimize this one day... */
-//        IEM_MC_LOCAL(RTGCPTR,                   GCPtrEffSrc);
-//
-//        IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, bRm, 0);
-//        IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
-//        IEM_MC_MAYBE_RAISE_SSE2_RELATED_XCPT();
-//        IEM_MC_ACTUALIZE_SSE_STATE_FOR_CHANGE();
-//
-//        IEM_MC_FETCH_MEM_U128_ALIGN_SSE(uSrc, pVCpu->iem.s.iEffSeg, GCPtrEffSrc);
-//        IEM_MC_STORE_XREG_U128(((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg, uSrc);
-//
-//        IEM_MC_ADVANCE_RIP();
-//        IEM_MC_END();
-//    }
-//    return VINF_SUCCESS;
-//}
 
-/*  Opcode VEX.F3.0F 0x28 - invalid */
-/*  Opcode VEX.F2.0F 0x28 - invalid */
+/**
+ * @opcode      0x28
+ * @oppfx       66
+ * @opcpuid     avx
+ * @opgroup     og_avx_pcksclr_datamove
+ * @opxcpttype  1
+ * @optest      op1=1 op2=2 -> op1=2
+ * @optest      op1=0 op2=-42 -> op1=-42
+ * @note        Almost identical to vmovaps
+ */
+FNIEMOP_DEF(iemOp_vmovapd_Vpd_Wpd)
+{
+    IEMOP_MNEMONIC2(VEX_RM, VMOVAPD, vmovapd, Vpd_WO, Wpd, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZES);
+    uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
+    Assert(pVCpu->iem.s.uVexLength <= 1);
+    if ((bRm & X86_MODRM_MOD_MASK) == (3 << X86_MODRM_MOD_SHIFT))
+    {
+        /*
+         * Register, register.
+         */
+        IEMOP_HLP_DONE_VEX_DECODING_NO_VVVV();
+        IEM_MC_BEGIN(1, 0);
+
+        IEM_MC_MAYBE_RAISE_AVX_RELATED_XCPT();
+        IEM_MC_ACTUALIZE_AVX_STATE_FOR_CHANGE();
+        if (pVCpu->iem.s.uVexLength == 0)
+            IEM_MC_COPY_YREG_U128_ZX_VLMAX(((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg,
+                                           (bRm & X86_MODRM_RM_MASK) | pVCpu->iem.s.uRexB);
+        else
+            IEM_MC_COPY_YREG_U256_ZX_VLMAX(((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg,
+                                           (bRm & X86_MODRM_RM_MASK) | pVCpu->iem.s.uRexB);
+        IEM_MC_ADVANCE_RIP();
+        IEM_MC_END();
+    }
+    else
+    {
+        /*
+         * Register, memory.
+         */
+        if (pVCpu->iem.s.uVexLength == 0)
+        {
+            IEM_MC_BEGIN(0, 2);
+            IEM_MC_LOCAL(RTGCPTR,                   GCPtrEffSrc);
+            IEM_MC_LOCAL(RTUINT128U,                uSrc);
+
+            IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, bRm, 0);
+            IEMOP_HLP_DONE_VEX_DECODING_NO_VVVV();
+            IEM_MC_MAYBE_RAISE_AVX_RELATED_XCPT();
+            IEM_MC_ACTUALIZE_AVX_STATE_FOR_CHANGE();
+
+            IEM_MC_FETCH_MEM_U128_ALIGN_SSE(uSrc, pVCpu->iem.s.iEffSeg, GCPtrEffSrc);
+            IEM_MC_STORE_YREG_U128_ZX_VLMAX(((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg, uSrc);
+
+            IEM_MC_ADVANCE_RIP();
+            IEM_MC_END();
+        }
+        else
+        {
+            IEM_MC_BEGIN(0, 2);
+            IEM_MC_LOCAL(RTGCPTR,                   GCPtrEffSrc);
+            IEM_MC_LOCAL(RTUINT256U,                uSrc);
+
+            IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, bRm, 0);
+            IEMOP_HLP_DONE_VEX_DECODING_NO_VVVV();
+            IEM_MC_MAYBE_RAISE_AVX_RELATED_XCPT();
+            IEM_MC_ACTUALIZE_AVX_STATE_FOR_CHANGE();
+
+            IEM_MC_FETCH_MEM_U256_ALIGN_AVX(uSrc, pVCpu->iem.s.iEffSeg, GCPtrEffSrc);
+            IEM_MC_STORE_YREG_U256_ZX_VLMAX(((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg, uSrc);
+
+            IEM_MC_ADVANCE_RIP();
+            IEM_MC_END();
+        }
+    }
+    return VINF_SUCCESS;
+}
+
+/**
+ * @opmnemonic  udvexf30f28
+ * @opcode      0x28
+ * @oppfx       0xf3
+ * @opunused    vex.modrm
+ * @opcpuid     avx
+ * @optest      ->
+ * @opdone
+ */
+
+/**
+ * @opmnemonic  udvexf20f28
+ * @opcode      0x28
+ * @oppfx       0xf2
+ * @opunused    vex.modrm
+ * @opcpuid     avx
+ * @optest      ->
+ * @opdone
+ */
 
-/** Opcode VEX.0F 0x29 - vmovaps Wps, Vps */
-FNIEMOP_STUB(iemOp_vmovaps_Wps_Vps);
-//FNIEMOP_DEF(iemOp_vmovaps_Wps_Vps)
-//{
-//    IEMOP_MNEMONIC(vmovaps_Wps_Vps, "vmovaps Wps,Vps");
-//    uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
-//    if ((bRm & X86_MODRM_MOD_MASK) == (3 << X86_MODRM_MOD_SHIFT))
-//    {
-//        /*
-//         * Register, register.
-//         */
-//        IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
-//        IEM_MC_BEGIN(0, 0);
-//        IEM_MC_MAYBE_RAISE_SSE_RELATED_XCPT();
-//        IEM_MC_ACTUALIZE_SSE_STATE_FOR_CHANGE();
-//        IEM_MC_COPY_XREG_U128((bRm & X86_MODRM_RM_MASK) | pVCpu->iem.s.uRexB,
-//                              ((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg);
-//        IEM_MC_ADVANCE_RIP();
-//        IEM_MC_END();
-//    }
-//    else
-//    {
-//        /*
-//         * Memory, register.
-//         */
-//        IEM_MC_BEGIN(0, 2);
-//        IEM_MC_LOCAL(RTUINT128U,                uSrc); /** @todo optimize this one day... */
-//        IEM_MC_LOCAL(RTGCPTR,                   GCPtrEffSrc);
-//
-//        IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, bRm, 0);
-//        IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
-//        IEM_MC_MAYBE_RAISE_SSE_RELATED_XCPT();
-//        IEM_MC_ACTUALIZE_SSE_STATE_FOR_READ();
-//
-//        IEM_MC_FETCH_XREG_U128(uSrc, ((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg);
-//        IEM_MC_STORE_MEM_U128_ALIGN_SSE(pVCpu->iem.s.iEffSeg, GCPtrEffSrc, uSrc);
-//
-//        IEM_MC_ADVANCE_RIP();
-//        IEM_MC_END();
-//    }
-//    return VINF_SUCCESS;
-//}
+/**
+ * @opcode      0x29
+ * @oppfx       none
+ * @opcpuid     avx
+ * @opgroup     og_avx_pcksclr_datamove
+ * @opxcpttype  1
+ * @optest      op1=1 op2=2 -> op1=2
+ * @optest      op1=0 op2=-42 -> op1=-42
+ * @note        Almost identical to vmovapd.
+ */
+FNIEMOP_DEF(iemOp_vmovaps_Wps_Vps)
+{
+    IEMOP_MNEMONIC2(VEX_MR, VMOVAPS, vmovaps, Wps_WO, Vps, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZES);
+    uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
+    Assert(pVCpu->iem.s.uVexLength <= 1);
+    if ((bRm & X86_MODRM_MOD_MASK) == (3 << X86_MODRM_MOD_SHIFT))
+    {
+        /*
+         * Register, register.
+         */
+        IEMOP_HLP_DONE_VEX_DECODING_NO_VVVV();
+        IEM_MC_BEGIN(1, 0);
+
+        IEM_MC_MAYBE_RAISE_AVX_RELATED_XCPT();
+        IEM_MC_ACTUALIZE_AVX_STATE_FOR_CHANGE();
+        if (pVCpu->iem.s.uVexLength == 0)
+            IEM_MC_COPY_YREG_U128_ZX_VLMAX((bRm & X86_MODRM_RM_MASK) | pVCpu->iem.s.uRexB,
+                ((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg);
+        else
+            IEM_MC_COPY_YREG_U256_ZX_VLMAX((bRm & X86_MODRM_RM_MASK) | pVCpu->iem.s.uRexB,
+                                           ((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg);
+        IEM_MC_ADVANCE_RIP();
+        IEM_MC_END();
+    }
+    else
+    {
+        /*
+         * Register, memory.
+         */
+        if (pVCpu->iem.s.uVexLength == 0)
+        {
+            IEM_MC_BEGIN(0, 2);
+            IEM_MC_LOCAL(RTGCPTR,                   GCPtrEffSrc);
+            IEM_MC_LOCAL(RTUINT128U,                uSrc);
+
+            IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, bRm, 0);
+            IEMOP_HLP_DONE_VEX_DECODING_NO_VVVV();
+            IEM_MC_MAYBE_RAISE_AVX_RELATED_XCPT();
+            IEM_MC_ACTUALIZE_AVX_STATE_FOR_READ();
+
+            IEM_MC_FETCH_YREG_U128(uSrc, ((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg);
+            IEM_MC_STORE_MEM_U128_ALIGN_SSE(pVCpu->iem.s.iEffSeg, GCPtrEffSrc, uSrc);
+
+            IEM_MC_ADVANCE_RIP();
+            IEM_MC_END();
+        }
+        else
+        {
+            IEM_MC_BEGIN(0, 2);
+            IEM_MC_LOCAL(RTGCPTR,                   GCPtrEffSrc);
+            IEM_MC_LOCAL(RTUINT256U,                uSrc);
+
+            IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, bRm, 0);
+            IEMOP_HLP_DONE_VEX_DECODING_NO_VVVV();
+            IEM_MC_MAYBE_RAISE_AVX_RELATED_XCPT();
+            IEM_MC_ACTUALIZE_AVX_STATE_FOR_READ();
+
+            IEM_MC_FETCH_YREG_U256(uSrc, ((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg);
+            IEM_MC_STORE_MEM_U256_ALIGN_AVX(pVCpu->iem.s.iEffSeg, GCPtrEffSrc, uSrc);
+
+            IEM_MC_ADVANCE_RIP();
+            IEM_MC_END();
+        }
+    }
+    return VINF_SUCCESS;
+}
 
-/** Opcode VEX.66.0F 0x29 - vmovapd Wpd,Vpd */
-FNIEMOP_STUB(iemOp_vmovapd_Wpd_Vpd);
-//FNIEMOP_DEF(iemOp_vmovapd_Wpd_Vpd)
-//{
-//    IEMOP_MNEMONIC(vmovapd_Wpd_Vpd, "movapd Wpd,Vpd");
-//    uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
-//    if ((bRm & X86_MODRM_MOD_MASK) == (3 << X86_MODRM_MOD_SHIFT))
-//    {
-//        /*
-//         * Register, register.
-//         */
-//        IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
-//        IEM_MC_BEGIN(0, 0);
-//        IEM_MC_MAYBE_RAISE_SSE2_RELATED_XCPT();
-//        IEM_MC_ACTUALIZE_SSE_STATE_FOR_CHANGE();
-//        IEM_MC_COPY_XREG_U128((bRm & X86_MODRM_RM_MASK) | pVCpu->iem.s.uRexB,
-//                              ((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg);
-//        IEM_MC_ADVANCE_RIP();
-//        IEM_MC_END();
-//    }
-//    else
-//    {
-//        /*
-//         * Memory, register.
-//         */
-//        IEM_MC_BEGIN(0, 2);
-//        IEM_MC_LOCAL(RTUINT128U,                uSrc); /** @todo optimize this one day... */
-//        IEM_MC_LOCAL(RTGCPTR,                   GCPtrEffSrc);
-//
-//        IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, bRm, 0);
-//        IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
-//        IEM_MC_MAYBE_RAISE_SSE2_RELATED_XCPT();
-//        IEM_MC_ACTUALIZE_SSE_STATE_FOR_READ();
-//
-//        IEM_MC_FETCH_XREG_U128(uSrc, ((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg);
-//        IEM_MC_STORE_MEM_U128_ALIGN_SSE(pVCpu->iem.s.iEffSeg, GCPtrEffSrc, uSrc);
-//
-//        IEM_MC_ADVANCE_RIP();
-//        IEM_MC_END();
-//    }
-//    return VINF_SUCCESS;
-//}
+/**
+ * @opcode      0x29
+ * @oppfx       66
+ * @opcpuid     avx
+ * @opgroup     og_avx_pcksclr_datamove
+ * @opxcpttype  1
+ * @optest      op1=1 op2=2 -> op1=2
+ * @optest      op1=0 op2=-42 -> op1=-42
+ * @note        Almost identical to vmovaps
+ */
+FNIEMOP_DEF(iemOp_vmovapd_Wpd_Vpd)
+{
+    IEMOP_MNEMONIC2(VEX_MR, VMOVAPD, vmovapd, Wpd_WO, Vpd, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZES);
+    Assert(pVCpu->iem.s.uVexLength <= 1);
+    uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
+    if ((bRm & X86_MODRM_MOD_MASK) == (3 << X86_MODRM_MOD_SHIFT))
+    {
+        /*
+         * Register, register.
+         */
+        IEMOP_HLP_DONE_VEX_DECODING_NO_VVVV();
+        IEM_MC_BEGIN(1, 0);
+
+        IEM_MC_MAYBE_RAISE_AVX_RELATED_XCPT();
+        IEM_MC_ACTUALIZE_AVX_STATE_FOR_CHANGE();
+        if (pVCpu->iem.s.uVexLength == 0)
+            IEM_MC_COPY_YREG_U128_ZX_VLMAX((bRm & X86_MODRM_RM_MASK) | pVCpu->iem.s.uRexB,
+                ((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg);
+        else
+            IEM_MC_COPY_YREG_U256_ZX_VLMAX((bRm & X86_MODRM_RM_MASK) | pVCpu->iem.s.uRexB,
+                                           ((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg);
+        IEM_MC_ADVANCE_RIP();
+        IEM_MC_END();
+    }
+    else
+    {
+        /*
+         * Register, memory.
+         */
+        if (pVCpu->iem.s.uVexLength == 0)
+        {
+            IEM_MC_BEGIN(0, 2);
+            IEM_MC_LOCAL(RTGCPTR,                   GCPtrEffSrc);
+            IEM_MC_LOCAL(RTUINT128U,                uSrc);
+
+            IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, bRm, 0);
+            IEMOP_HLP_DONE_VEX_DECODING_NO_VVVV();
+            IEM_MC_MAYBE_RAISE_AVX_RELATED_XCPT();
+            IEM_MC_ACTUALIZE_AVX_STATE_FOR_READ();
+
+            IEM_MC_FETCH_YREG_U128(uSrc, ((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg);
+            IEM_MC_STORE_MEM_U128_ALIGN_SSE(pVCpu->iem.s.iEffSeg, GCPtrEffSrc, uSrc);
+
+            IEM_MC_ADVANCE_RIP();
+            IEM_MC_END();
+        }
+        else
+        {
+            IEM_MC_BEGIN(0, 2);
+            IEM_MC_LOCAL(RTGCPTR,                   GCPtrEffSrc);
+            IEM_MC_LOCAL(RTUINT256U,                uSrc);
+
+            IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, bRm, 0);
+            IEMOP_HLP_DONE_VEX_DECODING_NO_VVVV();
+            IEM_MC_MAYBE_RAISE_AVX_RELATED_XCPT();
+            IEM_MC_ACTUALIZE_AVX_STATE_FOR_READ();
+
+            IEM_MC_FETCH_YREG_U256(uSrc, ((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg);
+            IEM_MC_STORE_MEM_U256_ALIGN_AVX(pVCpu->iem.s.iEffSeg, GCPtrEffSrc, uSrc);
+
+            IEM_MC_ADVANCE_RIP();
+            IEM_MC_END();
+        }
+    }
+    return VINF_SUCCESS;
+}
+
+
+/**
+ * @opmnemonic  udvexf30f29
+ * @opcode      0x29
+ * @oppfx       0xf3
+ * @opunused    vex.modrm
+ * @opcpuid     avx
+ * @optest      ->
+ * @opdone
+ */
 
-/*  Opcode VEX.F3.0F 0x29 - invalid */
-/*  Opcode VEX.F2.0F 0x29 - invalid */
+/**
+ * @opmnemonic  udvexf20f29
+ * @opcode      0x29
+ * @oppfx       0xf2
+ * @opunused    vex.modrm
+ * @opcpuid     avx
+ * @optest      ->
+ * @opdone
+ */
 
 
 /** Opcode VEX.0F 0x2a - invalid */
@@ -850,71 +1449,149 @@ FNIEMOP_STUB(iemOp_vcvtsi2ss_Vss_Hss_Ey);
 FNIEMOP_STUB(iemOp_vcvtsi2sd_Vsd_Hsd_Ey);
 
 
-/** Opcode VEX.0F 0x2b - vmovntps Mps, Vps */
-FNIEMOP_STUB(iemOp_vmovntps_Mps_Vps);
-//FNIEMOP_DEF(iemOp_vmovntps_Mps_Vps)
-//{
-//    IEMOP_MNEMONIC(vmovntps_Mps_Vps, "movntps Mps,Vps");
-//    uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
-//    if ((bRm & X86_MODRM_MOD_MASK) != (3 << X86_MODRM_MOD_SHIFT))
-//    {
-//        /*
-//         * memory, register.
-//         */
-//        IEM_MC_BEGIN(0, 2);
-//        IEM_MC_LOCAL(RTUINT128U,                uSrc); /** @todo optimize this one day... */
-//        IEM_MC_LOCAL(RTGCPTR,                   GCPtrEffSrc);
-//
-//        IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, bRm, 0);
-//        IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
-//        IEM_MC_MAYBE_RAISE_SSE_RELATED_XCPT();
-//        IEM_MC_ACTUALIZE_SSE_STATE_FOR_CHANGE();
-//
-//        IEM_MC_FETCH_XREG_U128(uSrc, ((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg);
-//        IEM_MC_STORE_MEM_U128_ALIGN_SSE(pVCpu->iem.s.iEffSeg, GCPtrEffSrc, uSrc);
-//
-//        IEM_MC_ADVANCE_RIP();
-//        IEM_MC_END();
-//    }
-//    /* The register, register encoding is invalid. */
-//    else
-//        return IEMOP_RAISE_INVALID_OPCODE();
-//    return VINF_SUCCESS;
-//}
+/**
+ * @opcode      0x2b
+ * @opcodesub   !11 mr/reg
+ * @oppfx       none
+ * @opcpuid     avx
+ * @opgroup     og_avx_cachect
+ * @opxcpttype  1
+ * @optest      op1=1 op2=2 -> op1=2
+ * @optest      op1=0 op2=-42 -> op1=-42
+ * @note        Identical implementation to vmovntpd
+ */
+FNIEMOP_DEF(iemOp_vmovntps_Mps_Vps)
+{
+    IEMOP_MNEMONIC2(VEX_MR_MEM, VMOVNTPS, vmovntps, Mps_WO, Vps, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZES);
+    Assert(pVCpu->iem.s.uVexLength <= 1);
+    uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
+    if ((bRm & X86_MODRM_MOD_MASK) != (3 << X86_MODRM_MOD_SHIFT))
+    {
+        /*
+         * memory, register.
+         */
+        if (pVCpu->iem.s.uVexLength == 0)
+        {
+            IEM_MC_BEGIN(0, 2);
+            IEM_MC_LOCAL(RTUINT128U,                uSrc);
+            IEM_MC_LOCAL(RTGCPTR,                   GCPtrEffSrc);
+
+            IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, bRm, 0);
+            IEMOP_HLP_DONE_VEX_DECODING_NO_VVVV();
+            IEM_MC_MAYBE_RAISE_AVX_RELATED_XCPT();
+            IEM_MC_ACTUALIZE_AVX_STATE_FOR_CHANGE();
+
+            IEM_MC_FETCH_XREG_U128(uSrc, ((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg);
+            IEM_MC_STORE_MEM_U128_ALIGN_SSE(pVCpu->iem.s.iEffSeg, GCPtrEffSrc, uSrc);
+
+            IEM_MC_ADVANCE_RIP();
+            IEM_MC_END();
+        }
+        else
+        {
+            IEM_MC_BEGIN(0, 2);
+            IEM_MC_LOCAL(RTUINT256U,                uSrc);
+            IEM_MC_LOCAL(RTGCPTR,                   GCPtrEffSrc);
+
+            IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, bRm, 0);
+            IEMOP_HLP_DONE_VEX_DECODING_NO_VVVV();
+            IEM_MC_MAYBE_RAISE_AVX_RELATED_XCPT();
+            IEM_MC_ACTUALIZE_AVX_STATE_FOR_CHANGE();
+
+            IEM_MC_FETCH_YREG_U256(uSrc, ((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg);
+            IEM_MC_STORE_MEM_U256_ALIGN_AVX(pVCpu->iem.s.iEffSeg, GCPtrEffSrc, uSrc);
+
+            IEM_MC_ADVANCE_RIP();
+            IEM_MC_END();
+        }
+    }
+    /* The register, register encoding is invalid. */
+    else
+        return IEMOP_RAISE_INVALID_OPCODE();
+    return VINF_SUCCESS;
+}
 
-/** Opcode VEX.66.0F 0x2b - vmovntpd Mpd, Vpd */
-FNIEMOP_STUB(iemOp_vmovntpd_Mpd_Vpd);
-//FNIEMOP_DEF(iemOp_vmovntpd_Mpd_Vpd)
-//{
-//    IEMOP_MNEMONIC(vmovntpd_Mpd_Vpd, "movntpd Mdq,Vpd");
-//    uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
-//    if ((bRm & X86_MODRM_MOD_MASK) != (3 << X86_MODRM_MOD_SHIFT))
-//    {
-//        /*
-//         * memory, register.
-//         */
-//        IEM_MC_BEGIN(0, 2);
-//        IEM_MC_LOCAL(RTUINT128U,                uSrc); /** @todo optimize this one day... */
-//        IEM_MC_LOCAL(RTGCPTR,                   GCPtrEffSrc);
-//
-//        IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, bRm, 0);
-//        IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
-//        IEM_MC_MAYBE_RAISE_SSE2_RELATED_XCPT();
-//        IEM_MC_ACTUALIZE_SSE_STATE_FOR_CHANGE();
-//
-//        IEM_MC_FETCH_XREG_U128(uSrc, ((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg);
-//        IEM_MC_STORE_MEM_U128_ALIGN_SSE(pVCpu->iem.s.iEffSeg, GCPtrEffSrc, uSrc);
-//
-//        IEM_MC_ADVANCE_RIP();
-//        IEM_MC_END();
-//    }
-//    /* The register, register encoding is invalid. */
-//    else
-//        return IEMOP_RAISE_INVALID_OPCODE();
-//    return VINF_SUCCESS;
-//}
-/*  Opcode VEX.F3.0F 0x2b - invalid */
-/*  Opcode VEX.F2.0F 0x2b - invalid */
+/**
+ * @opcode      0x2b
+ * @opcodesub   !11 mr/reg
+ * @oppfx       0x66
+ * @opcpuid     avx
+ * @opgroup     og_avx_cachect
+ * @opxcpttype  1
+ * @optest      op1=1 op2=2 -> op1=2
+ * @optest      op1=0 op2=-42 -> op1=-42
+ * @note        Identical implementation to vmovntps
+ */
+FNIEMOP_DEF(iemOp_vmovntpd_Mpd_Vpd)
+{
+    IEMOP_MNEMONIC2(VEX_MR_MEM, VMOVNTPD, vmovntpd, Mpd_WO, Vpd, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZES);
+    Assert(pVCpu->iem.s.uVexLength <= 1);
+    uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
+    if ((bRm & X86_MODRM_MOD_MASK) != (3 << X86_MODRM_MOD_SHIFT))
+    {
+        /*
+         * memory, register.
+         */
+        if (pVCpu->iem.s.uVexLength == 0)
+        {
+            IEM_MC_BEGIN(0, 2);
+            IEM_MC_LOCAL(RTUINT128U,                uSrc);
+            IEM_MC_LOCAL(RTGCPTR,                   GCPtrEffSrc);
+
+            IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, bRm, 0);
+            IEMOP_HLP_DONE_VEX_DECODING_NO_VVVV();
+            IEM_MC_MAYBE_RAISE_AVX_RELATED_XCPT();
+            IEM_MC_ACTUALIZE_AVX_STATE_FOR_CHANGE();
+
+            IEM_MC_FETCH_XREG_U128(uSrc, ((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg);
+            IEM_MC_STORE_MEM_U128_ALIGN_SSE(pVCpu->iem.s.iEffSeg, GCPtrEffSrc, uSrc);
+
+            IEM_MC_ADVANCE_RIP();
+            IEM_MC_END();
+        }
+        else
+        {
+            IEM_MC_BEGIN(0, 2);
+            IEM_MC_LOCAL(RTUINT256U,                uSrc);
+            IEM_MC_LOCAL(RTGCPTR,                   GCPtrEffSrc);
+
+            IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, bRm, 0);
+            IEMOP_HLP_DONE_VEX_DECODING_NO_VVVV();
+            IEM_MC_MAYBE_RAISE_AVX_RELATED_XCPT();
+            IEM_MC_ACTUALIZE_AVX_STATE_FOR_CHANGE();
+
+            IEM_MC_FETCH_YREG_U256(uSrc, ((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg);
+            IEM_MC_STORE_MEM_U256_ALIGN_AVX(pVCpu->iem.s.iEffSeg, GCPtrEffSrc, uSrc);
+
+            IEM_MC_ADVANCE_RIP();
+            IEM_MC_END();
+        }
+    }
+    /* The register, register encoding is invalid. */
+    else
+        return IEMOP_RAISE_INVALID_OPCODE();
+    return VINF_SUCCESS;
+}
+
+/**
+ * @opmnemonic  udvexf30f2b
+ * @opcode      0x2b
+ * @oppfx       0xf3
+ * @opunused    vex.modrm
+ * @opcpuid     avx
+ * @optest      ->
+ * @opdone
+ */
+
+/**
+ * @opmnemonic  udvexf20f2b
+ * @opcode      0x2b
+ * @oppfx       0xf2
+ * @opunused    vex.modrm
+ * @opcpuid     avx
+ * @optest      ->
+ * @opdone
+ */
 
 
 /*  Opcode VEX.0F 0x2c - invalid */
@@ -1345,172 +2022,287 @@ FNIEMOP_STUB(iemOp_vpunpcklqdq_Vx_Hx_Wx);
 //    return FNIEMOP_CALL_1(iemOpCommonSse_LowLow_To_Full, &g_iemAImpl_punpcklqdq);
 //}
 
-/*  Opcode VEX.F3.0F 0x6c - invalid */
-/*  Opcode VEX.F2.0F 0x6c - invalid */
-
-
-/*  Opcode VEX.0F 0x6d - invalid */
-
-/** Opcode VEX.66.0F 0x6d - vpunpckhqdq Vx, Hx, W */
-FNIEMOP_STUB(iemOp_vpunpckhqdq_Vx_Hx_W);
-//FNIEMOP_DEF(iemOp_vpunpckhqdq_Vx_Hx_W)
-//{
-//    IEMOP_MNEMONIC(punpckhqdq, "punpckhqdq");
-//    return FNIEMOP_CALL_1(iemOpCommonSse_HighHigh_To_Full, &g_iemAImpl_punpckhqdq);
-//}
-
-/*  Opcode VEX.F3.0F 0x6d - invalid */
-
-
-/*  Opcode VEX.0F 0x6e - invalid */
-
-/** Opcode VEX.66.0F 0x6e - vmovd/q Vy, Ey */
-FNIEMOP_STUB(iemOp_vmovd_q_Vy_Ey);
-//FNIEMOP_DEF(iemOp_vmovd_q_Vy_Ey)
-//{
-//    uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
-//    if (pVCpu->iem.s.fPrefixes & IEM_OP_PRF_SIZE_REX_W)
-//        IEMOP_MNEMONIC(vmovdq_Wq_Eq, "vmovq Wq,Eq");
-//    else
-//        IEMOP_MNEMONIC(vmovdq_Wd_Ed, "vmovd Wd,Ed");
-//    if ((bRm & X86_MODRM_MOD_MASK) == (3 << X86_MODRM_MOD_SHIFT))
-//    {
-//        /* XMM, greg*/
-//        IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
-//        IEM_MC_BEGIN(0, 1);
-//        IEM_MC_MAYBE_RAISE_SSE2_RELATED_XCPT();
-//        IEM_MC_ACTUALIZE_SSE_STATE_FOR_CHANGE();
-//        if (pVCpu->iem.s.fPrefixes & IEM_OP_PRF_SIZE_REX_W)
-//        {
-//            IEM_MC_LOCAL(uint64_t, u64Tmp);
-//            IEM_MC_FETCH_GREG_U64(u64Tmp, (bRm & X86_MODRM_RM_MASK) | pVCpu->iem.s.uRexB);
-//            IEM_MC_STORE_XREG_U64_ZX_U128(((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg, u64Tmp);
-//        }
-//        else
-//        {
-//            IEM_MC_LOCAL(uint32_t, u32Tmp);
-//            IEM_MC_FETCH_GREG_U32(u32Tmp, (bRm & X86_MODRM_RM_MASK) | pVCpu->iem.s.uRexB);
-//            IEM_MC_STORE_XREG_U32_ZX_U128(((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg, u32Tmp);
-//        }
-//        IEM_MC_ADVANCE_RIP();
-//        IEM_MC_END();
-//    }
-//    else
-//    {
-//        /* XMM, [mem] */
-//        IEM_MC_BEGIN(0, 2);
-//        IEM_MC_LOCAL(RTGCPTR, GCPtrEffSrc);
-//        IEM_MC_MAYBE_RAISE_SSE2_RELATED_XCPT(); /** @todo order */
-//        IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, bRm, 1);
-//        IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
-//        IEM_MC_ACTUALIZE_SSE_STATE_FOR_CHANGE();
-//        if (pVCpu->iem.s.fPrefixes & IEM_OP_PRF_SIZE_REX_W)
-//        {
-//            IEM_MC_LOCAL(uint64_t, u64Tmp);
-//            IEM_MC_FETCH_MEM_U64(u64Tmp, pVCpu->iem.s.iEffSeg, GCPtrEffSrc);
-//            IEM_MC_STORE_XREG_U64_ZX_U128(((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg, u64Tmp);
-//        }
-//        else
-//        {
-//            IEM_MC_LOCAL(uint32_t, u32Tmp);
-//            IEM_MC_FETCH_MEM_U32(u32Tmp, pVCpu->iem.s.iEffSeg, GCPtrEffSrc);
-//            IEM_MC_STORE_XREG_U32_ZX_U128(((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg, u32Tmp);
-//        }
-//        IEM_MC_ADVANCE_RIP();
-//        IEM_MC_END();
-//    }
-//    return VINF_SUCCESS;
-//}
-
-/*  Opcode VEX.F3.0F 0x6e - invalid */
-
-
-/*  Opcode VEX.0F 0x6f - invalid */
-
-/** Opcode VEX.66.0F 0x6f - vmovdqa Vx, Wx */
-FNIEMOP_STUB(iemOp_vmovdqa_Vx_Wx);
-//FNIEMOP_DEF(iemOp_vmovdqa_Vx_Wx)
-//{
-//    uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
-//    IEMOP_MNEMONIC(vmovdqa_Vdq_Wdq, "movdqa Vdq,Wdq");
-//    if ((bRm & X86_MODRM_MOD_MASK) == (3 << X86_MODRM_MOD_SHIFT))
-//    {
-//        /*
-//         * Register, register.
-//         */
-//        IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
-//        IEM_MC_BEGIN(0, 0);
-//        IEM_MC_MAYBE_RAISE_SSE2_RELATED_XCPT();
-//        IEM_MC_ACTUALIZE_SSE_STATE_FOR_CHANGE();
-//        IEM_MC_COPY_XREG_U128(((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg,
-//                              (bRm & X86_MODRM_RM_MASK) | pVCpu->iem.s.uRexB);
-//        IEM_MC_ADVANCE_RIP();
-//        IEM_MC_END();
-//    }
-//    else
-//    {
-//        /*
-//         * Register, memory.
-//         */
-//        IEM_MC_BEGIN(0, 2);
-//        IEM_MC_LOCAL(RTUINT128U, u128Tmp);
-//        IEM_MC_LOCAL(RTGCPTR,    GCPtrEffSrc);
-//
-//        IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, bRm, 0);
-//        IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
-//        IEM_MC_MAYBE_RAISE_SSE2_RELATED_XCPT();
-//        IEM_MC_ACTUALIZE_SSE_STATE_FOR_CHANGE();
-//        IEM_MC_FETCH_MEM_U128_ALIGN_SSE(u128Tmp, pVCpu->iem.s.iEffSeg, GCPtrEffSrc);
-//        IEM_MC_STORE_XREG_U128(((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg, u128Tmp);
-//
-//        IEM_MC_ADVANCE_RIP();
-//        IEM_MC_END();
-//    }
-//    return VINF_SUCCESS;
-//}
-
-/** Opcode VEX.F3.0F 0x6f - vmovdqu Vx, Wx */
-FNIEMOP_STUB(iemOp_vmovdqu_Vx_Wx);
-//FNIEMOP_DEF(iemOp_vmovdqu_Vx_Wx)
-//{
-//    uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
-//    IEMOP_MNEMONIC(vmovdqu_Vdq_Wdq, "movdqu Vdq,Wdq");
-//    if ((bRm & X86_MODRM_MOD_MASK) == (3 << X86_MODRM_MOD_SHIFT))
-//    {
-//        /*
-//         * Register, register.
-//         */
-//        IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
-//        IEM_MC_BEGIN(0, 0);
-//        IEM_MC_MAYBE_RAISE_SSE2_RELATED_XCPT();
-//        IEM_MC_ACTUALIZE_SSE_STATE_FOR_CHANGE();
-//        IEM_MC_COPY_XREG_U128(((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg,
-//                              (bRm & X86_MODRM_RM_MASK) | pVCpu->iem.s.uRexB);
-//        IEM_MC_ADVANCE_RIP();
-//        IEM_MC_END();
-//    }
-//    else
-//    {
-//        /*
-//         * Register, memory.
-//         */
-//        IEM_MC_BEGIN(0, 2);
-//        IEM_MC_LOCAL(RTUINT128U, u128Tmp);
-//        IEM_MC_LOCAL(RTGCPTR,    GCPtrEffSrc);
-//
-//        IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, bRm, 0);
-//        IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
-//        IEM_MC_MAYBE_RAISE_SSE2_RELATED_XCPT();
-//        IEM_MC_ACTUALIZE_SSE_STATE_FOR_CHANGE();
-//        IEM_MC_FETCH_MEM_U128(u128Tmp, pVCpu->iem.s.iEffSeg, GCPtrEffSrc);
-//        IEM_MC_STORE_XREG_U128(((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg, u128Tmp);
-//
-//        IEM_MC_ADVANCE_RIP();
-//        IEM_MC_END();
-//    }
-//    return VINF_SUCCESS;
+/*  Opcode VEX.F3.0F 0x6c - invalid */
+/*  Opcode VEX.F2.0F 0x6c - invalid */
+
+
+/*  Opcode VEX.0F 0x6d - invalid */
+
+/** Opcode VEX.66.0F 0x6d - vpunpckhqdq Vx, Hx, W */
+FNIEMOP_STUB(iemOp_vpunpckhqdq_Vx_Hx_W);
+//FNIEMOP_DEF(iemOp_vpunpckhqdq_Vx_Hx_W)
+//{
+//    IEMOP_MNEMONIC(punpckhqdq, "punpckhqdq");
+//    return FNIEMOP_CALL_1(iemOpCommonSse_HighHigh_To_Full, &g_iemAImpl_punpckhqdq);
 //}
 
+/*  Opcode VEX.F3.0F 0x6d - invalid */
+
+
+/*  Opcode VEX.0F 0x6e - invalid */
+
+FNIEMOP_DEF(iemOp_vmovd_q_Vy_Ey)
+{
+    uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
+    if (pVCpu->iem.s.fPrefixes & IEM_OP_PRF_SIZE_REX_W)
+    {
+        /**
+         * @opcode      0x6e
+         * @opcodesub   rex.w=1
+         * @oppfx       0x66
+         * @opcpuid     avx
+         * @opgroup     og_avx_simdint_datamov
+         * @opxcpttype  5
+         * @optest      64-bit / op1=1 op2=2   -> op1=2
+         * @optest      64-bit / op1=0 op2=-42 -> op1=-42
+         */
+        IEMOP_MNEMONIC2(VEX_RM, VMOVQ, vmovq, Vq_WO, Eq, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OZ_PFX);
+        if ((bRm & X86_MODRM_MOD_MASK) == (3 << X86_MODRM_MOD_SHIFT))
+        {
+            /* XMM, greg64 */
+            IEMOP_HLP_DONE_VEX_DECODING_L0_AND_NO_VVVV();
+            IEM_MC_BEGIN(0, 1);
+            IEM_MC_LOCAL(uint64_t, u64Tmp);
+
+            IEM_MC_MAYBE_RAISE_AVX_RELATED_XCPT();
+            IEM_MC_ACTUALIZE_AVX_STATE_FOR_CHANGE();
+
+            IEM_MC_FETCH_GREG_U64(u64Tmp, (bRm & X86_MODRM_RM_MASK) | pVCpu->iem.s.uRexB);
+            IEM_MC_STORE_YREG_U64_ZX_VLMAX(((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg, u64Tmp);
+
+            IEM_MC_ADVANCE_RIP();
+            IEM_MC_END();
+        }
+        else
+        {
+            /* XMM, [mem64] */
+            IEM_MC_BEGIN(0, 2);
+            IEM_MC_LOCAL(RTGCPTR, GCPtrEffSrc);
+            IEM_MC_LOCAL(uint64_t, u64Tmp);
+
+            IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, bRm, 0);
+            IEMOP_HLP_DONE_VEX_DECODING_L0_AND_NO_VVVV();
+            IEM_MC_MAYBE_RAISE_AVX_RELATED_XCPT();
+            IEM_MC_ACTUALIZE_AVX_STATE_FOR_CHANGE();
+
+            IEM_MC_FETCH_MEM_U64(u64Tmp, pVCpu->iem.s.iEffSeg, GCPtrEffSrc);
+            IEM_MC_STORE_YREG_U64_ZX_VLMAX(((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg, u64Tmp);
+
+            IEM_MC_ADVANCE_RIP();
+            IEM_MC_END();
+        }
+    }
+    else
+    {
+        /**
+         * @opdone
+         * @opcode      0x6e
+         * @opcodesub   rex.w=0
+         * @oppfx       0x66
+         * @opcpuid     avx
+         * @opgroup     og_avx_simdint_datamov
+         * @opxcpttype  5
+         * @opfunction  iemOp_vmovd_q_Vy_Ey
+         * @optest      op1=1 op2=2   -> op1=2
+         * @optest      op1=0 op2=-42 -> op1=-42
+         */
+        IEMOP_MNEMONIC2(VEX_RM, VMOVD, vmovd, Vd_WO, Ed, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OZ_PFX);
+        if ((bRm & X86_MODRM_MOD_MASK) == (3 << X86_MODRM_MOD_SHIFT))
+        {
+            /* XMM, greg32 */
+            IEMOP_HLP_DONE_VEX_DECODING_L0_AND_NO_VVVV();
+            IEM_MC_BEGIN(0, 1);
+            IEM_MC_LOCAL(uint32_t, u32Tmp);
+
+            IEM_MC_MAYBE_RAISE_AVX_RELATED_XCPT();
+            IEM_MC_ACTUALIZE_AVX_STATE_FOR_CHANGE();
+
+            IEM_MC_FETCH_GREG_U32(u32Tmp, (bRm & X86_MODRM_RM_MASK) | pVCpu->iem.s.uRexB);
+            IEM_MC_STORE_YREG_U32_ZX_VLMAX(((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg, u32Tmp);
+
+            IEM_MC_ADVANCE_RIP();
+            IEM_MC_END();
+        }
+        else
+        {
+            /* XMM, [mem32] */
+            IEM_MC_BEGIN(0, 2);
+            IEM_MC_LOCAL(RTGCPTR, GCPtrEffSrc);
+            IEM_MC_LOCAL(uint32_t, u32Tmp);
+
+            IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, bRm, 0);
+            IEMOP_HLP_DONE_VEX_DECODING_L0_AND_NO_VVVV();
+            IEM_MC_MAYBE_RAISE_AVX_RELATED_XCPT();
+            IEM_MC_ACTUALIZE_AVX_STATE_FOR_CHANGE();
+
+            IEM_MC_FETCH_MEM_U32(u32Tmp, pVCpu->iem.s.iEffSeg, GCPtrEffSrc);
+            IEM_MC_STORE_YREG_U32_ZX_VLMAX(((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg, u32Tmp);
+
+            IEM_MC_ADVANCE_RIP();
+            IEM_MC_END();
+        }
+    }
+    return VINF_SUCCESS;
+}
+
+
+/*  Opcode VEX.F3.0F 0x6e - invalid */
+
+
+/*  Opcode VEX.0F 0x6f - invalid */
+
+/**
+ * @opcode      0x6f
+ * @oppfx       0x66
+ * @opcpuid     avx
+ * @opgroup     og_avx_simdint_datamove
+ * @opxcpttype  1
+ * @optest      op1=1 op2=2   -> op1=2
+ * @optest      op1=0 op2=-42 -> op1=-42
+ */
+FNIEMOP_DEF(iemOp_vmovdqa_Vx_Wx)
+{
+    IEMOP_MNEMONIC2(VEX_RM, VMOVDQA, vmovdqa, Vx_WO, Wx, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZES);
+    Assert(pVCpu->iem.s.uVexLength <= 1);
+    uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
+    if ((bRm & X86_MODRM_MOD_MASK) == (3 << X86_MODRM_MOD_SHIFT))
+    {
+        /*
+         * Register, register.
+         */
+        IEMOP_HLP_DONE_VEX_DECODING_NO_VVVV();
+        IEM_MC_BEGIN(0, 0);
+
+        IEM_MC_MAYBE_RAISE_AVX_RELATED_XCPT();
+        IEM_MC_ACTUALIZE_AVX_STATE_FOR_CHANGE();
+        if (pVCpu->iem.s.uVexLength == 0)
+            IEM_MC_COPY_YREG_U128_ZX_VLMAX(((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg,
+                                           (bRm & X86_MODRM_RM_MASK) | pVCpu->iem.s.uRexB);
+        else
+            IEM_MC_COPY_YREG_U256_ZX_VLMAX(((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg,
+                                           (bRm & X86_MODRM_RM_MASK) | pVCpu->iem.s.uRexB);
+        IEM_MC_ADVANCE_RIP();
+        IEM_MC_END();
+    }
+    else if (pVCpu->iem.s.uVexLength == 0)
+    {
+        /*
+         * Register, memory128.
+         */
+        IEM_MC_BEGIN(0, 2);
+        IEM_MC_LOCAL(RTUINT128U, u128Tmp);
+        IEM_MC_LOCAL(RTGCPTR,    GCPtrEffSrc);
+
+        IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, bRm, 0);
+        IEMOP_HLP_DONE_VEX_DECODING_NO_VVVV();
+        IEM_MC_MAYBE_RAISE_AVX_RELATED_XCPT();
+        IEM_MC_ACTUALIZE_AVX_STATE_FOR_CHANGE();
+
+        IEM_MC_FETCH_MEM_U128_ALIGN_SSE(u128Tmp, pVCpu->iem.s.iEffSeg, GCPtrEffSrc);
+        IEM_MC_STORE_YREG_U128_ZX_VLMAX(((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg, u128Tmp);
+
+        IEM_MC_ADVANCE_RIP();
+        IEM_MC_END();
+    }
+    else
+    {
+        /*
+         * Register, memory256.
+         */
+        IEM_MC_BEGIN(0, 2);
+        IEM_MC_LOCAL(RTUINT256U, u256Tmp);
+        IEM_MC_LOCAL(RTGCPTR,    GCPtrEffSrc);
+
+        IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, bRm, 0);
+        IEMOP_HLP_DONE_VEX_DECODING_NO_VVVV();
+        IEM_MC_MAYBE_RAISE_AVX_RELATED_XCPT();
+        IEM_MC_ACTUALIZE_AVX_STATE_FOR_CHANGE();
+
+        IEM_MC_FETCH_MEM_U256_ALIGN_AVX(u256Tmp, pVCpu->iem.s.iEffSeg, GCPtrEffSrc);
+        IEM_MC_STORE_YREG_U256_ZX_VLMAX(((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg, u256Tmp);
+
+        IEM_MC_ADVANCE_RIP();
+        IEM_MC_END();
+    }
+    return VINF_SUCCESS;
+}
+
+/**
+ * @opcode      0x6f
+ * @oppfx       0xf3
+ * @opcpuid     avx
+ * @opgroup     og_avx_simdint_datamove
+ * @opxcpttype  4UA
+ * @optest      op1=1 op2=2   -> op1=2
+ * @optest      op1=0 op2=-42 -> op1=-42
+ */
+FNIEMOP_DEF(iemOp_vmovdqu_Vx_Wx)
+{
+    IEMOP_MNEMONIC2(VEX_RM, VMOVDQU, vmovdqu, Vx_WO, Wx, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZES);
+    Assert(pVCpu->iem.s.uVexLength <= 1);
+    uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
+    if ((bRm & X86_MODRM_MOD_MASK) == (3 << X86_MODRM_MOD_SHIFT))
+    {
+        /*
+         * Register, register.
+         */
+        IEMOP_HLP_DONE_VEX_DECODING_NO_VVVV();
+        IEM_MC_BEGIN(0, 0);
+
+        IEM_MC_MAYBE_RAISE_AVX_RELATED_XCPT();
+        IEM_MC_ACTUALIZE_AVX_STATE_FOR_CHANGE();
+        if (pVCpu->iem.s.uVexLength == 0)
+            IEM_MC_COPY_YREG_U128_ZX_VLMAX(((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg,
+                                           (bRm & X86_MODRM_RM_MASK) | pVCpu->iem.s.uRexB);
+        else
+            IEM_MC_COPY_YREG_U256_ZX_VLMAX(((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg,
+                                           (bRm & X86_MODRM_RM_MASK) | pVCpu->iem.s.uRexB);
+        IEM_MC_ADVANCE_RIP();
+        IEM_MC_END();
+    }
+    else if (pVCpu->iem.s.uVexLength == 0)
+    {
+        /*
+         * Register, memory128.
+         */
+        IEM_MC_BEGIN(0, 2);
+        IEM_MC_LOCAL(RTUINT128U, u128Tmp);
+        IEM_MC_LOCAL(RTGCPTR,    GCPtrEffSrc);
+
+        IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, bRm, 0);
+        IEMOP_HLP_DONE_VEX_DECODING_NO_VVVV();
+        IEM_MC_MAYBE_RAISE_AVX_RELATED_XCPT();
+        IEM_MC_ACTUALIZE_AVX_STATE_FOR_CHANGE();
+
+        IEM_MC_FETCH_MEM_U128(u128Tmp, pVCpu->iem.s.iEffSeg, GCPtrEffSrc);
+        IEM_MC_STORE_YREG_U128_ZX_VLMAX(((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg, u128Tmp);
+
+        IEM_MC_ADVANCE_RIP();
+        IEM_MC_END();
+    }
+    else
+    {
+        /*
+         * Register, memory256.
+         */
+        IEM_MC_BEGIN(0, 2);
+        IEM_MC_LOCAL(RTUINT256U, u256Tmp);
+        IEM_MC_LOCAL(RTGCPTR,    GCPtrEffSrc);
+
+        IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, bRm, 0);
+        IEMOP_HLP_DONE_VEX_DECODING_NO_VVVV();
+        IEM_MC_MAYBE_RAISE_AVX_RELATED_XCPT();
+        IEM_MC_ACTUALIZE_AVX_STATE_FOR_CHANGE();
+
+        IEM_MC_FETCH_MEM_U256(u256Tmp, pVCpu->iem.s.iEffSeg, GCPtrEffSrc);
+        IEM_MC_STORE_YREG_U256_ZX_VLMAX(((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg, u256Tmp);
+
+        IEM_MC_ADVANCE_RIP();
+        IEM_MC_END();
+    }
+    return VINF_SUCCESS;
+}
+
 
 /*  Opcode VEX.0F 0x70 - invalid */
 
@@ -1942,156 +2734,318 @@ FNIEMOP_STUB(iemOp_vhsubps_Vps_Hps_Wps);
 
 /*  Opcode VEX.0F 0x7e - invalid */
 
-/** Opcode VEX.66.0F 0x7e - vmovd_q Ey, Vy */
-FNIEMOP_STUB(iemOp_vmovd_q_Ey_Vy);
-//FNIEMOP_DEF(iemOp_vmovd_q_Ey_Vy)
-//{
-//    uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
-//    if (pVCpu->iem.s.fPrefixes & IEM_OP_PRF_SIZE_REX_W)
-//        IEMOP_MNEMONIC(vmovq_Eq_Wq, "vmovq Eq,Wq");
-//    else
-//        IEMOP_MNEMONIC(vmovd_Ed_Wd, "vmovd Ed,Wd");
-//    if ((bRm & X86_MODRM_MOD_MASK) == (3 << X86_MODRM_MOD_SHIFT))
-//    {
-//        /* greg, XMM */
-//        IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
-//        IEM_MC_BEGIN(0, 1);
-//        IEM_MC_MAYBE_RAISE_SSE2_RELATED_XCPT();
-//        IEM_MC_ACTUALIZE_SSE_STATE_FOR_READ();
-//        if (pVCpu->iem.s.fPrefixes & IEM_OP_PRF_SIZE_REX_W)
-//        {
-//            IEM_MC_LOCAL(uint64_t, u64Tmp);
-//            IEM_MC_FETCH_XREG_U64(u64Tmp, ((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg);
-//            IEM_MC_STORE_GREG_U64((bRm & X86_MODRM_RM_MASK) | pVCpu->iem.s.uRexB, u64Tmp);
-//        }
-//        else
-//        {
-//            IEM_MC_LOCAL(uint32_t, u32Tmp);
-//            IEM_MC_FETCH_XREG_U32(u32Tmp, ((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg);
-//            IEM_MC_STORE_GREG_U32((bRm & X86_MODRM_RM_MASK) | pVCpu->iem.s.uRexB, u32Tmp);
-//        }
-//        IEM_MC_ADVANCE_RIP();
-//        IEM_MC_END();
-//    }
-//    else
-//    {
-//        /* [mem], XMM */
-//        IEM_MC_BEGIN(0, 2);
-//        IEM_MC_LOCAL(RTGCPTR, GCPtrEffSrc);
-//        IEM_MC_MAYBE_RAISE_SSE2_RELATED_XCPT();
-//        IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, bRm, 1);
-//        IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
-//        IEM_MC_ACTUALIZE_SSE_STATE_FOR_READ();
-//        if (pVCpu->iem.s.fPrefixes & IEM_OP_PRF_SIZE_REX_W)
-//        {
-//            IEM_MC_LOCAL(uint64_t, u64Tmp);
-//            IEM_MC_FETCH_XREG_U64(u64Tmp, ((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg);
-//            IEM_MC_STORE_MEM_U64(pVCpu->iem.s.iEffSeg, GCPtrEffSrc, u64Tmp);
-//        }
-//        else
-//        {
-//            IEM_MC_LOCAL(uint32_t, u32Tmp);
-//            IEM_MC_FETCH_XREG_U32(u32Tmp, ((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg);
-//            IEM_MC_STORE_MEM_U32(pVCpu->iem.s.iEffSeg, GCPtrEffSrc, u32Tmp);
-//        }
-//        IEM_MC_ADVANCE_RIP();
-//        IEM_MC_END();
-//    }
-//    return VINF_SUCCESS;
-//}
+FNIEMOP_DEF(iemOp_vmovd_q_Ey_Vy)
+{
+    uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
+    if (pVCpu->iem.s.fPrefixes & IEM_OP_PRF_SIZE_REX_W)
+    {
+        /**
+         * @opcode      0x7e
+         * @opcodesub   rex.w=1
+         * @oppfx       0x66
+         * @opcpuid     avx
+         * @opgroup     og_avx_simdint_datamov
+         * @opxcpttype  5
+         * @optest      64-bit / op1=1 op2=2   -> op1=2
+         * @optest      64-bit / op1=0 op2=-42 -> op1=-42
+         */
+        IEMOP_MNEMONIC2(VEX_MR, VMOVQ, vmovq, Eq_WO, Vq, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OZ_PFX);
+        if ((bRm & X86_MODRM_MOD_MASK) == (3 << X86_MODRM_MOD_SHIFT))
+        {
+            /* greg64, XMM */
+            IEMOP_HLP_DONE_VEX_DECODING_L0_AND_NO_VVVV();
+            IEM_MC_BEGIN(0, 1);
+            IEM_MC_LOCAL(uint64_t, u64Tmp);
+
+            IEM_MC_MAYBE_RAISE_AVX_RELATED_XCPT();
+            IEM_MC_ACTUALIZE_AVX_STATE_FOR_READ();
+
+            IEM_MC_FETCH_YREG_U64(u64Tmp, ((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg);
+            IEM_MC_STORE_GREG_U64((bRm & X86_MODRM_RM_MASK) | pVCpu->iem.s.uRexB, u64Tmp);
+
+            IEM_MC_ADVANCE_RIP();
+            IEM_MC_END();
+        }
+        else
+        {
+            /* [mem64], XMM */
+            IEM_MC_BEGIN(0, 2);
+            IEM_MC_LOCAL(RTGCPTR, GCPtrEffSrc);
+            IEM_MC_LOCAL(uint64_t, u64Tmp);
+
+            IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, bRm, 0);
+            IEMOP_HLP_DONE_VEX_DECODING_L0_AND_NO_VVVV();
+            IEM_MC_MAYBE_RAISE_AVX_RELATED_XCPT();
+            IEM_MC_ACTUALIZE_AVX_STATE_FOR_READ();
+
+            IEM_MC_FETCH_YREG_U64(u64Tmp, ((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg);
+            IEM_MC_STORE_MEM_U64(pVCpu->iem.s.iEffSeg, GCPtrEffSrc, u64Tmp);
+
+            IEM_MC_ADVANCE_RIP();
+            IEM_MC_END();
+        }
+    }
+    else
+    {
+        /**
+         * @opdone
+         * @opcode      0x7e
+         * @opcodesub   rex.w=0
+         * @oppfx       0x66
+         * @opcpuid     avx
+         * @opgroup     og_avx_simdint_datamov
+         * @opxcpttype  5
+         * @opfunction  iemOp_vmovd_q_Vy_Ey
+         * @optest      op1=1 op2=2   -> op1=2
+         * @optest      op1=0 op2=-42 -> op1=-42
+         */
+        IEMOP_MNEMONIC2(VEX_MR, VMOVD, vmovd, Ed_WO, Vd, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OZ_PFX);
+        if ((bRm & X86_MODRM_MOD_MASK) == (3 << X86_MODRM_MOD_SHIFT))
+        {
+            /* greg32, XMM */
+            IEMOP_HLP_DONE_VEX_DECODING_L0_AND_NO_VVVV();
+            IEM_MC_BEGIN(0, 1);
+            IEM_MC_LOCAL(uint32_t, u32Tmp);
+
+            IEM_MC_MAYBE_RAISE_AVX_RELATED_XCPT();
+            IEM_MC_ACTUALIZE_AVX_STATE_FOR_READ();
+
+            IEM_MC_FETCH_YREG_U32(u32Tmp, ((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg);
+            IEM_MC_STORE_GREG_U32((bRm & X86_MODRM_RM_MASK) | pVCpu->iem.s.uRexB, u32Tmp);
+
+            IEM_MC_ADVANCE_RIP();
+            IEM_MC_END();
+        }
+        else
+        {
+            /* [mem32], XMM */
+            IEM_MC_BEGIN(0, 2);
+            IEM_MC_LOCAL(RTGCPTR, GCPtrEffSrc);
+            IEM_MC_LOCAL(uint32_t, u32Tmp);
+
+            IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, bRm, 0);
+            IEMOP_HLP_DONE_VEX_DECODING_L0_AND_NO_VVVV();
+            IEM_MC_MAYBE_RAISE_AVX_RELATED_XCPT();
+            IEM_MC_ACTUALIZE_AVX_STATE_FOR_READ();
+
+            IEM_MC_FETCH_YREG_U32(u32Tmp, ((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg);
+            IEM_MC_STORE_MEM_U32(pVCpu->iem.s.iEffSeg, GCPtrEffSrc, u32Tmp);
+
+            IEM_MC_ADVANCE_RIP();
+            IEM_MC_END();
+        }
+    }
+    return VINF_SUCCESS;
+}
+
+/**
+ * @opcode      0x7e
+ * @oppfx       0xf3
+ * @opcpuid     avx
+ * @opgroup     og_avx_pcksclr_datamove
+ * @opxcpttype  none
+ * @optest      op1=1 op2=2 -> op1=2
+ * @optest      op1=0 op2=-42 -> op1=-42
+ */
+FNIEMOP_DEF(iemOp_vmovq_Vq_Wq)
+{
+    IEMOP_MNEMONIC2(VEX_RM, VMOVQ, vmovq, Vq_WO, Wq, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZES);
+    uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
+    if ((bRm & X86_MODRM_MOD_MASK) == (3 << X86_MODRM_MOD_SHIFT))
+    {
+        /*
+         * Register, register.
+         */
+        IEMOP_HLP_DONE_VEX_DECODING_L0_AND_NO_VVVV();
+        IEM_MC_BEGIN(0, 0);
+
+        IEM_MC_MAYBE_RAISE_AVX_RELATED_XCPT();
+        IEM_MC_ACTUALIZE_AVX_STATE_FOR_CHANGE();
+
+        IEM_MC_COPY_YREG_U64_ZX_VLMAX(((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg,
+                                      (bRm & X86_MODRM_RM_MASK) | pVCpu->iem.s.uRexB);
+        IEM_MC_ADVANCE_RIP();
+        IEM_MC_END();
+    }
+    else
+    {
+        /*
+         * Memory, register.
+         */
+        IEM_MC_BEGIN(0, 2);
+        IEM_MC_LOCAL(uint64_t,                  uSrc);
+        IEM_MC_LOCAL(RTGCPTR,                   GCPtrEffSrc);
+
+        IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, bRm, 0);
+        IEMOP_HLP_DONE_VEX_DECODING_L0_AND_NO_VVVV();
+        IEM_MC_MAYBE_RAISE_AVX_RELATED_XCPT();
+        IEM_MC_ACTUALIZE_AVX_STATE_FOR_CHANGE();
+
+        IEM_MC_FETCH_MEM_U64(uSrc, pVCpu->iem.s.iEffSeg, GCPtrEffSrc);
+        IEM_MC_STORE_YREG_U64_ZX_VLMAX(((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg, uSrc);
+
+        IEM_MC_ADVANCE_RIP();
+        IEM_MC_END();
+    }
+    return VINF_SUCCESS;
 
-/** Opcode VEX.F3.0F 0x7e - vmovq Vq, Wq */
-FNIEMOP_STUB(iemOp_vmovq_Vq_Wq);
+}
 /*  Opcode VEX.F2.0F 0x7e - invalid */
 
 
 /*  Opcode VEX.0F 0x7f - invalid */
 
-/** Opcode VEX.66.0F 0x7f - vmovdqa Wx,Vx */
-FNIEMOP_STUB(iemOp_vmovdqa_Wx_Vx);
-//FNIEMOP_DEF(iemOp_vmovdqa_Wx_Vx)
-//{
-//    IEMOP_MNEMONIC(vmovdqa_Wdq_Vdq, "vmovdqa Wx,Vx");
-//    uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
-//    if ((bRm & X86_MODRM_MOD_MASK) == (3 << X86_MODRM_MOD_SHIFT))
-//    {
-//        /*
-//         * Register, register.
-//         */
-//        IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
-//        IEM_MC_BEGIN(0, 0);
-//        IEM_MC_MAYBE_RAISE_SSE2_RELATED_XCPT();
-//        IEM_MC_ACTUALIZE_SSE_STATE_FOR_CHANGE();
-//        IEM_MC_COPY_XREG_U128((bRm & X86_MODRM_RM_MASK) | pVCpu->iem.s.uRexB,
-//                              ((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg);
-//        IEM_MC_ADVANCE_RIP();
-//        IEM_MC_END();
-//    }
-//    else
-//    {
-//        /*
-//         * Register, memory.
-//         */
-//        IEM_MC_BEGIN(0, 2);
-//        IEM_MC_LOCAL(RTUINT128U, u128Tmp);
-//        IEM_MC_LOCAL(RTGCPTR,    GCPtrEffSrc);
-//
-//        IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, bRm, 0);
-//        IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
-//        IEM_MC_MAYBE_RAISE_SSE2_RELATED_XCPT();
-//        IEM_MC_ACTUALIZE_SSE_STATE_FOR_READ();
-//
-//        IEM_MC_FETCH_XREG_U128(u128Tmp, ((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg);
-//        IEM_MC_STORE_MEM_U128_ALIGN_SSE(pVCpu->iem.s.iEffSeg, GCPtrEffSrc, u128Tmp);
-//
-//        IEM_MC_ADVANCE_RIP();
-//        IEM_MC_END();
-//    }
-//    return VINF_SUCCESS;
-//}
+/**
+ * @opcode      0x7f
+ * @oppfx       0x66
+ * @opcpuid     avx
+ * @opgroup     og_avx_simdint_datamove
+ * @opxcpttype  1
+ * @optest      op1=1 op2=2   -> op1=2
+ * @optest      op1=0 op2=-42 -> op1=-42
+ */
+FNIEMOP_DEF(iemOp_vmovdqa_Wx_Vx)
+{
+    IEMOP_MNEMONIC2(VEX_MR, VMOVDQA, vmovdqa, Wx_WO, Vx, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZES);
+    Assert(pVCpu->iem.s.uVexLength <= 1);
+    uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
+    if ((bRm & X86_MODRM_MOD_MASK) == (3 << X86_MODRM_MOD_SHIFT))
+    {
+        /*
+         * Register, register.
+         */
+        IEMOP_HLP_DONE_VEX_DECODING_NO_VVVV();
+        IEM_MC_BEGIN(0, 0);
+
+        IEM_MC_MAYBE_RAISE_AVX_RELATED_XCPT();
+        IEM_MC_ACTUALIZE_AVX_STATE_FOR_CHANGE();
+        if (pVCpu->iem.s.uVexLength == 0)
+            IEM_MC_COPY_YREG_U128_ZX_VLMAX((bRm & X86_MODRM_RM_MASK) | pVCpu->iem.s.uRexB,
+                                           ((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg);
+        else
+            IEM_MC_COPY_YREG_U256_ZX_VLMAX((bRm & X86_MODRM_RM_MASK) | pVCpu->iem.s.uRexB,
+                                           ((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg);
+        IEM_MC_ADVANCE_RIP();
+        IEM_MC_END();
+    }
+    else if (pVCpu->iem.s.uVexLength == 0)
+    {
+        /*
+         * Register, memory128.
+         */
+        IEM_MC_BEGIN(0, 2);
+        IEM_MC_LOCAL(RTUINT128U, u128Tmp);
+        IEM_MC_LOCAL(RTGCPTR,    GCPtrEffSrc);
+
+        IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, bRm, 0);
+        IEMOP_HLP_DONE_VEX_DECODING_NO_VVVV();
+        IEM_MC_MAYBE_RAISE_AVX_RELATED_XCPT();
+        IEM_MC_ACTUALIZE_AVX_STATE_FOR_READ();
+
+        IEM_MC_FETCH_YREG_U128(u128Tmp, ((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg);
+        IEM_MC_STORE_MEM_U128_ALIGN_SSE(pVCpu->iem.s.iEffSeg, GCPtrEffSrc, u128Tmp);
+
+        IEM_MC_ADVANCE_RIP();
+        IEM_MC_END();
+    }
+    else
+    {
+        /*
+         * Register, memory256.
+         */
+        IEM_MC_BEGIN(0, 2);
+        IEM_MC_LOCAL(RTUINT256U, u256Tmp);
+        IEM_MC_LOCAL(RTGCPTR,    GCPtrEffSrc);
+
+        IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, bRm, 0);
+        IEMOP_HLP_DONE_VEX_DECODING_NO_VVVV();
+        IEM_MC_MAYBE_RAISE_AVX_RELATED_XCPT();
+        IEM_MC_ACTUALIZE_AVX_STATE_FOR_READ();
+
+        IEM_MC_FETCH_YREG_U256(u256Tmp, ((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg);
+        IEM_MC_STORE_MEM_U256_ALIGN_AVX(pVCpu->iem.s.iEffSeg, GCPtrEffSrc, u256Tmp);
+
+        IEM_MC_ADVANCE_RIP();
+        IEM_MC_END();
+    }
+    return VINF_SUCCESS;
+}
 
-/** Opcode VEX.F3.0F 0x7f - vmovdqu Wx,Vx */
-FNIEMOP_STUB(iemOp_vmovdqu_Wx_Vx);
-//FNIEMOP_DEF(iemOp_vmovdqu_Wx_Vx)
-//{
-//    uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
-//    IEMOP_MNEMONIC(vmovdqu_Wdq_Vdq, "vmovdqu Wx,Vx");
-//    if ((bRm & X86_MODRM_MOD_MASK) == (3 << X86_MODRM_MOD_SHIFT))
-//    {
-//        /*
-//         * Register, register.
-//         */
-//        IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
-//        IEM_MC_BEGIN(0, 0);
-//        IEM_MC_MAYBE_RAISE_SSE2_RELATED_XCPT();
-//        IEM_MC_ACTUALIZE_SSE_STATE_FOR_CHANGE();
-//        IEM_MC_COPY_XREG_U128((bRm & X86_MODRM_RM_MASK) | pVCpu->iem.s.uRexB,
-//                              ((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg);
-//        IEM_MC_ADVANCE_RIP();
-//        IEM_MC_END();
-//    }
-//    else
-//    {
-//        /*
-//         * Register, memory.
-//         */
-//        IEM_MC_BEGIN(0, 2);
-//        IEM_MC_LOCAL(RTUINT128U, u128Tmp);
-//        IEM_MC_LOCAL(RTGCPTR,    GCPtrEffSrc);
-//
-//        IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, bRm, 0);
-//        IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
-//        IEM_MC_MAYBE_RAISE_SSE2_RELATED_XCPT();
-//        IEM_MC_ACTUALIZE_SSE_STATE_FOR_READ();
-//
-//        IEM_MC_FETCH_XREG_U128(u128Tmp, ((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg);
-//        IEM_MC_STORE_MEM_U128(pVCpu->iem.s.iEffSeg, GCPtrEffSrc, u128Tmp);
-//
-//        IEM_MC_ADVANCE_RIP();
-//        IEM_MC_END();
-//    }
-//    return VINF_SUCCESS;
-//}
+/**
+ * @opcode      0x7f
+ * @oppfx       0xf3
+ * @opcpuid     avx
+ * @opgroup     og_avx_simdint_datamove
+ * @opxcpttype  4UA
+ * @optest      op1=1 op2=2   -> op1=2
+ * @optest      op1=0 op2=-42 -> op1=-42
+ */
+FNIEMOP_DEF(iemOp_vmovdqu_Wx_Vx)
+{
+    IEMOP_MNEMONIC2(VEX_MR, VMOVDQU, vmovdqu, Wx_WO, Vx, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZES);
+    Assert(pVCpu->iem.s.uVexLength <= 1);
+    uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
+    if ((bRm & X86_MODRM_MOD_MASK) == (3 << X86_MODRM_MOD_SHIFT))
+    {
+        /*
+         * Register, register.
+         */
+        IEMOP_HLP_DONE_VEX_DECODING_NO_VVVV();
+        IEM_MC_BEGIN(0, 0);
+
+        IEM_MC_MAYBE_RAISE_AVX_RELATED_XCPT();
+        IEM_MC_ACTUALIZE_AVX_STATE_FOR_CHANGE();
+        if (pVCpu->iem.s.uVexLength == 0)
+            IEM_MC_COPY_YREG_U128_ZX_VLMAX((bRm & X86_MODRM_RM_MASK) | pVCpu->iem.s.uRexB,
+                                           ((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg);
+        else
+            IEM_MC_COPY_YREG_U256_ZX_VLMAX((bRm & X86_MODRM_RM_MASK) | pVCpu->iem.s.uRexB,
+                                           ((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg);
+        IEM_MC_ADVANCE_RIP();
+        IEM_MC_END();
+    }
+    else if (pVCpu->iem.s.uVexLength == 0)
+    {
+        /*
+         * Register, memory128.
+         */
+        IEM_MC_BEGIN(0, 2);
+        IEM_MC_LOCAL(RTUINT128U, u128Tmp);
+        IEM_MC_LOCAL(RTGCPTR,    GCPtrEffSrc);
+
+        IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, bRm, 0);
+        IEMOP_HLP_DONE_VEX_DECODING_NO_VVVV();
+        IEM_MC_MAYBE_RAISE_AVX_RELATED_XCPT();
+        IEM_MC_ACTUALIZE_AVX_STATE_FOR_READ();
+
+        IEM_MC_FETCH_YREG_U128(u128Tmp, ((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg);
+        IEM_MC_STORE_MEM_U128(pVCpu->iem.s.iEffSeg, GCPtrEffSrc, u128Tmp);
+
+        IEM_MC_ADVANCE_RIP();
+        IEM_MC_END();
+    }
+    else
+    {
+        /*
+         * Register, memory256.
+         */
+        IEM_MC_BEGIN(0, 2);
+        IEM_MC_LOCAL(RTUINT256U, u256Tmp);
+        IEM_MC_LOCAL(RTGCPTR,    GCPtrEffSrc);
+
+        IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, bRm, 0);
+        IEMOP_HLP_DONE_VEX_DECODING_NO_VVVV();
+        IEM_MC_MAYBE_RAISE_AVX_RELATED_XCPT();
+        IEM_MC_ACTUALIZE_AVX_STATE_FOR_READ();
+
+        IEM_MC_FETCH_YREG_U256(u256Tmp, ((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg);
+        IEM_MC_STORE_MEM_U256(pVCpu->iem.s.iEffSeg, GCPtrEffSrc, u256Tmp);
+
+        IEM_MC_ADVANCE_RIP();
+        IEM_MC_END();
+    }
+    return VINF_SUCCESS;
+}
 
 /*  Opcode VEX.F2.0F 0x7f - invalid */
 
@@ -2169,7 +3123,7 @@ FNIEMOP_STUB(iemOp_vmovdqu_Wx_Vx);
 FNIEMOP_STUB_1(iemOp_VGrp15_vldmxcsr, uint8_t, bRm);
 //FNIEMOP_DEF_1(iemOp_VGrp15_vldmxcsr, uint8_t, bRm)
 //{
-//    IEMOP_MNEMONIC1(M_MEM, VLDMXCSR, vldmxcsr, MdRO, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZE);
+//    IEMOP_MNEMONIC1(M_MEM, VLDMXCSR, vldmxcsr, MdRO, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZES);
 //    if (!IEM_GET_GUEST_CPU_FEATURES(pVCpu)->fSse)
 //        return IEMOP_RAISE_INVALID_OPCODE();
 //
@@ -2226,15 +3180,12 @@ FNIEMOP_STUB_1(iemOp_VGrp15_vldmxcsr, uint8_t, bRm);
  */
 FNIEMOP_DEF_1(iemOp_VGrp15_vstmxcsr,  uint8_t, bRm)
 {
-    IEMOP_MNEMONIC1(VEX_M_MEM, VSTMXCSR, vstmxcsr, MdWO, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZE);
-    if (!IEM_GET_GUEST_CPU_FEATURES(pVCpu)->fAvx)
-        return IEMOP_RAISE_INVALID_OPCODE();
-
+    IEMOP_MNEMONIC1(VEX_M_MEM, VSTMXCSR, vstmxcsr, Md_WO, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZES);
     IEM_MC_BEGIN(2, 0);
     IEM_MC_ARG(uint8_t,         iEffSeg,                                 0);
     IEM_MC_ARG(RTGCPTR,         GCPtrEff,                                1);
     IEM_MC_CALC_RM_EFF_ADDR(GCPtrEff, bRm, 0);
-    IEMOP_HLP_DONE_VEX_DECODING_L_ZERO_NO_VVV();
+    IEMOP_HLP_DONE_VEX_DECODING_L0_AND_NO_VVVV();
     IEM_MC_ACTUALIZE_SSE_STATE_FOR_READ();
     IEM_MC_ASSIGN(iEffSeg, pVCpu->iem.s.iEffSeg);
     IEM_MC_CALL_CIMPL_2(iemCImpl_vstmxcsr, iEffSeg, GCPtrEff);
@@ -2405,59 +3356,56 @@ FNIEMOP_STUB(iemOp_vpmullw_Vx_Hx_Wx);
 /*  Opcode VEX.0F 0xd6 - invalid */
 
 /**
- * @ opcode      0xd6
- * @ oppfx       0x66
- * @ opcpuid     sse2
- * @ opgroup     og_sse2_pcksclr_datamove
- * @ opxcpttype  none
- * @ optest      op1=-1 op2=2 -> op1=2
- * @ optest      op1=0 op2=-42 -> op1=-42
+ * @opcode      0xd6
+ * @oppfx       0x66
+ * @opcpuid     avx
+ * @opgroup     og_avx_pcksclr_datamove
+ * @opxcpttype  none
+ * @optest      op1=-1 op2=2 -> op1=2
+ * @optest      op1=0 op2=-42 -> op1=-42
  */
-FNIEMOP_STUB(iemOp_vmovq_Wq_Vq);
-//FNIEMOP_DEF(iemOp_vmovq_Wq_Vq)
-//{
-//    IEMOP_MNEMONIC2(MR, VMOVQ, vmovq, WqZxReg, Vq, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZE);
-//    uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
-//    if ((bRm & X86_MODRM_MOD_MASK) == (3 << X86_MODRM_MOD_SHIFT))
-//    {
-//        /*
-//         * Register, register.
-//         */
-//        IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
-//        IEM_MC_BEGIN(0, 2);
-//        IEM_MC_LOCAL(uint64_t,                  uSrc);
-//
-//        IEM_MC_MAYBE_RAISE_SSE2_RELATED_XCPT();
-//        IEM_MC_ACTUALIZE_SSE_STATE_FOR_CHANGE();
-//
-//        IEM_MC_FETCH_XREG_U64(uSrc, ((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg);
-//        IEM_MC_STORE_XREG_U64_ZX_U128((bRm & X86_MODRM_RM_MASK) | pVCpu->iem.s.uRexB, uSrc);
-//
-//        IEM_MC_ADVANCE_RIP();
-//        IEM_MC_END();
-//    }
-//    else
-//    {
-//        /*
-//         * Memory, register.
-//         */
-//        IEM_MC_BEGIN(0, 2);
-//        IEM_MC_LOCAL(uint64_t,                  uSrc);
-//        IEM_MC_LOCAL(RTGCPTR,                   GCPtrEffSrc);
-//
-//        IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, bRm, 0);
-//        IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
-//        IEM_MC_MAYBE_RAISE_SSE2_RELATED_XCPT();
-//        IEM_MC_ACTUALIZE_SSE_STATE_FOR_READ();
-//
-//        IEM_MC_FETCH_XREG_U64(uSrc, ((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg);
-//        IEM_MC_STORE_MEM_U64(pVCpu->iem.s.iEffSeg, GCPtrEffSrc, uSrc);
-//
-//        IEM_MC_ADVANCE_RIP();
-//        IEM_MC_END();
-//    }
-//    return VINF_SUCCESS;
-//}
+FNIEMOP_DEF(iemOp_vmovq_Wq_Vq)
+{
+    IEMOP_MNEMONIC2(VEX_MR, VMOVQ, vmovq, Wq_WO, Vq, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZES);
+    uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
+    if ((bRm & X86_MODRM_MOD_MASK) == (3 << X86_MODRM_MOD_SHIFT))
+    {
+        /*
+         * Register, register.
+         */
+        IEMOP_HLP_DONE_VEX_DECODING_L0_AND_NO_VVVV();
+        IEM_MC_BEGIN(0, 0);
+
+        IEM_MC_MAYBE_RAISE_AVX_RELATED_XCPT();
+        IEM_MC_ACTUALIZE_AVX_STATE_FOR_CHANGE();
+
+        IEM_MC_COPY_YREG_U64_ZX_VLMAX((bRm & X86_MODRM_RM_MASK) | pVCpu->iem.s.uRexB,
+                                      ((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg);
+        IEM_MC_ADVANCE_RIP();
+        IEM_MC_END();
+    }
+    else
+    {
+        /*
+         * Memory, register.
+         */
+        IEM_MC_BEGIN(0, 2);
+        IEM_MC_LOCAL(uint64_t,                  uSrc);
+        IEM_MC_LOCAL(RTGCPTR,                   GCPtrEffSrc);
+
+        IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, bRm, 0);
+        IEMOP_HLP_DONE_VEX_DECODING_L0_AND_NO_VVVV();
+        IEM_MC_MAYBE_RAISE_AVX_RELATED_XCPT();
+        IEM_MC_ACTUALIZE_AVX_STATE_FOR_READ();
+
+        IEM_MC_FETCH_YREG_U64(uSrc, ((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg);
+        IEM_MC_STORE_MEM_U64(pVCpu->iem.s.iEffSeg, GCPtrEffSrc, uSrc);
+
+        IEM_MC_ADVANCE_RIP();
+        IEM_MC_END();
+    }
+    return VINF_SUCCESS;
+}
 
 /*  Opcode VEX.F3.0F 0xd6 - invalid */
 /*  Opcode VEX.F2.0F 0xd6 - invalid */
@@ -2594,35 +3542,77 @@ FNIEMOP_STUB(iemOp_vcvtpd2dq_Vx_Wpd);
 
 /* Opcode VEX.0F 0xe7 - invalid */
 
-/** Opcode VEX.66.0F 0xe7 - vmovntdq Mx, Vx */
-FNIEMOP_STUB(iemOp_vmovntdq_Mx_Vx);
-//FNIEMOP_DEF(iemOp_vmovntdq_Mx_Vx)
-//{
-//    uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
-//    if ((bRm & X86_MODRM_MOD_MASK) != (3 << X86_MODRM_MOD_SHIFT))
-//    {
-//        /* Register, memory. */
-//        IEMOP_MNEMONIC(vmovntdq_Mx_Vx, "vmovntdq Mx,Vx");
-//        IEM_MC_BEGIN(0, 2);
-//        IEM_MC_LOCAL(RTUINT128U,                uSrc);
-//        IEM_MC_LOCAL(RTGCPTR,                   GCPtrEffSrc);
-//
-//        IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, bRm, 0);
-//        IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
-//        IEM_MC_MAYBE_RAISE_SSE2_RELATED_XCPT();
-//        IEM_MC_ACTUALIZE_SSE_STATE_FOR_READ();
-//
-//        IEM_MC_FETCH_XREG_U128(uSrc, ((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg);
-//        IEM_MC_STORE_MEM_U128_ALIGN_SSE(pVCpu->iem.s.iEffSeg, GCPtrEffSrc, uSrc);
-//
-//        IEM_MC_ADVANCE_RIP();
-//        IEM_MC_END();
-//        return VINF_SUCCESS;
-//    }
-//
-//    /* The register, register encoding is invalid. */
-//    return IEMOP_RAISE_INVALID_OPCODE();
-//}
+/**
+ * @opcode      0xe7
+ * @opcodesub   !11 mr/reg
+ * @oppfx       0x66
+ * @opcpuid     avx
+ * @opgroup     og_avx_cachect
+ * @opxcpttype  1
+ * @optest      op1=-1 op2=2  -> op1=2
+ * @optest      op1=0 op2=-42 -> op1=-42
+ */
+FNIEMOP_DEF(iemOp_vmovntdq_Mx_Vx)
+{
+    IEMOP_MNEMONIC2(VEX_MR, VMOVNTDQ, vmovntdq, Mx_WO, Vx, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZES);
+    Assert(pVCpu->iem.s.uVexLength <= 1);
+    uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
+    if ((bRm & X86_MODRM_MOD_MASK) != (3 << X86_MODRM_MOD_SHIFT))
+    {
+        if (pVCpu->iem.s.uVexLength == 0)
+        {
+            /*
+             * 128-bit: Memory, register.
+             */
+            IEM_MC_BEGIN(0, 2);
+            IEM_MC_LOCAL(RTUINT128U,                uSrc);
+            IEM_MC_LOCAL(RTGCPTR,                   GCPtrEffSrc);
+
+            IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, bRm, 0);
+            IEMOP_HLP_DONE_VEX_DECODING_NO_VVVV();
+            IEM_MC_MAYBE_RAISE_AVX_RELATED_XCPT();
+            IEM_MC_ACTUALIZE_AVX_STATE_FOR_READ();
+
+            IEM_MC_FETCH_YREG_U128(uSrc, ((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg);
+            IEM_MC_STORE_MEM_U128_ALIGN_SSE(pVCpu->iem.s.iEffSeg, GCPtrEffSrc, uSrc);
+
+            IEM_MC_ADVANCE_RIP();
+            IEM_MC_END();
+        }
+        else
+        {
+            /*
+             * 256-bit: Memory, register.
+             */
+            IEM_MC_BEGIN(0, 2);
+            IEM_MC_LOCAL(RTUINT256U,                uSrc);
+            IEM_MC_LOCAL(RTGCPTR,                   GCPtrEffSrc);
+
+            IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, bRm, 0);
+            IEMOP_HLP_DONE_VEX_DECODING_NO_VVVV();
+            IEM_MC_MAYBE_RAISE_AVX_RELATED_XCPT();
+            IEM_MC_ACTUALIZE_AVX_STATE_FOR_READ();
+
+            IEM_MC_FETCH_YREG_U256(uSrc, ((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg);
+            IEM_MC_STORE_MEM_U256_ALIGN_AVX(pVCpu->iem.s.iEffSeg, GCPtrEffSrc, uSrc);
+
+            IEM_MC_ADVANCE_RIP();
+            IEM_MC_END();
+        }
+        return VINF_SUCCESS;
+    }
+    /**
+     * @opdone
+     * @opmnemonic  udvex660fe7reg
+     * @opcode      0xe7
+     * @opcodesub   11 mr/reg
+     * @oppfx       0x66
+     * @opunused    immediate
+     * @opcpuid     avx
+     * @optest      ->
+     */
+    return IEMOP_RAISE_INVALID_OPCODE();
+}
 
 /*  Opcode VEX.F3.0F 0xe7 - invalid */
 /*  Opcode VEX.F2.0F 0xe7 - invalid */
@@ -2804,8 +3794,8 @@ IEM_STATIC const PFNIEMOP g_apfnVexMap1[] =
     /* 0x0e */  IEMOP_X4(iemOp_InvalidNeedRM),
     /* 0x0f */  IEMOP_X4(iemOp_InvalidNeedRM),
 
-    /* 0x10 */  iemOp_vmovups_Vps_Wps,      iemOp_vmovupd_Vpd_Wpd,      iemOp_vmovss_Vx_Hx_Wss,     iemOp_vmovsd_Vx_Hx_Wsd,
-    /* 0x11 */  iemOp_vmovups_Wps_Vps,      iemOp_vmovupd_Wpd_Vpd,      iemOp_vmovss_Wss_Hx_Vss,    iemOp_vmovsd_Wsd_Hx_Vsd,
+    /* 0x10 */  iemOp_vmovups_Vps_Wps,      iemOp_vmovupd_Vpd_Wpd,      iemOp_vmovss_Vss_Hss_Wss,   iemOp_vmovsd_Vsd_Hsd_Wsd,
+    /* 0x11 */  iemOp_vmovups_Wps_Vps,      iemOp_vmovupd_Wpd_Vpd,      iemOp_vmovss_Wss_Hss_Vss,   iemOp_vmovsd_Wsd_Hsd_Vsd,
     /* 0x12 */  iemOp_vmovlps_Vq_Hq_Mq__vmovhlps, iemOp_vmovlpd_Vq_Hq_Mq, iemOp_vmovsldup_Vx_Wx,    iemOp_vmovddup_Vx_Wx,
     /* 0x13 */  iemOp_vmovlps_Mq_Vq,        iemOp_vmovlpd_Mq_Vq,        iemOp_InvalidNeedRM,        iemOp_InvalidNeedRM,
     /* 0x14 */  iemOp_vunpcklps_Vx_Hx_Wx,   iemOp_vunpcklpd_Vx_Hx_Wx,   iemOp_InvalidNeedRM,        iemOp_InvalidNeedRM,
diff --git a/src/VBox/VMM/VMMAll/IEMAllInstructionsVexMap2.cpp.h b/src/VBox/VMM/VMMAll/IEMAllInstructionsVexMap2.cpp.h
index 958295a..5bf5fc3 100644
--- a/src/VBox/VMM/VMMAll/IEMAllInstructionsVexMap2.cpp.h
+++ b/src/VBox/VMM/VMMAll/IEMAllInstructionsVexMap2.cpp.h
@@ -133,8 +133,93 @@ FNIEMOP_STUB(iemOp_vpmovsxdq_Vx_UxMq);
 FNIEMOP_STUB(iemOp_vpmuldq_Vx_Hx_Wx);
 /** Opcode VEX.66.0F38 0x29. */
 FNIEMOP_STUB(iemOp_vpcmpeqq_Vx_Hx_Wx);
+
 /** Opcode VEX.66.0F38 0x2a. */
-FNIEMOP_STUB(iemOp_vmovntdqa_Vx_Hx_Mx);
+/*
+ * @ opcode      0x2a
+ * @ opcodesub   !11 mr/reg vex.l=0
+ * @ oppfx       0x66
+ * @ opcpuid     avx
+ * @ opgroup     og_avx_cachect
+ * @ opxcpttype  1
+ * @ optest      op1=-1 op2=2  -> op1=2
+ * @ optest      op1=0 op2=-42 -> op1=-42
+ */
+FNIEMOP_DEF(iemOp_vmovntdqa_Vx_Mx)
+{
+    Assert(pVCpu->iem.s.uVexLength <= 1);
+    IEMOP_MNEMONIC2(VEX_RM, VMOVNTDQA, vmovntdqa, Vx_WO, Mx, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZES);
+    uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
+    if ((bRm & X86_MODRM_MOD_MASK) != (3 << X86_MODRM_MOD_SHIFT))
+    {
+        if (pVCpu->iem.s.uVexLength == 0)
+        {
+            /*
+             * 128-bit: Memory, register.
+             */
+            IEM_MC_BEGIN(0, 2);
+            IEM_MC_LOCAL(RTUINT128U,                uSrc);
+            IEM_MC_LOCAL(RTGCPTR,                   GCPtrEffSrc);
+
+            IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, bRm, 0);
+            IEMOP_HLP_DONE_VEX_DECODING_NO_VVVV();
+            IEM_MC_MAYBE_RAISE_AVX_RELATED_XCPT();
+            IEM_MC_ACTUALIZE_AVX_STATE_FOR_CHANGE();
+
+            IEM_MC_FETCH_MEM_U128_ALIGN_SSE(uSrc, pVCpu->iem.s.iEffSeg, GCPtrEffSrc);
+            IEM_MC_STORE_YREG_U128_ZX_VLMAX(((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg, uSrc);
+
+            IEM_MC_ADVANCE_RIP();
+            IEM_MC_END();
+        }
+        else
+        {
+/*
+ * @ opdone
+ * @ opcode      0x2a
+ * @ opcodesub   !11 mr/reg vex.l=1
+ * @ oppfx       0x66
+ * @ opcpuid     avx2
+ * @ opgroup     og_avx2_cachect
+ * @ opxcpttype  1
+ * @ optest      op1=-1 op2=2  -> op1=2
+ * @ optest      op1=0 op2=-42 -> op1=-42
+ */
+            /*
+             * 256-bit: Memory, register.
+             */
+            IEM_MC_BEGIN(0, 2);
+            IEM_MC_LOCAL(RTUINT256U,                uSrc);
+            IEM_MC_LOCAL(RTGCPTR,                   GCPtrEffSrc);
+
+            IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, bRm, 0);
+            IEMOP_HLP_DONE_VEX_DECODING_NO_VVVV();
+            IEM_MC_MAYBE_RAISE_AVX2_RELATED_XCPT();
+            IEM_MC_ACTUALIZE_AVX_STATE_FOR_READ();
+
+            IEM_MC_FETCH_YREG_U256(uSrc, ((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg);
+            IEM_MC_STORE_MEM_U256_ALIGN_AVX(pVCpu->iem.s.iEffSeg, GCPtrEffSrc, uSrc);
+
+            IEM_MC_ADVANCE_RIP();
+            IEM_MC_END();
+        }
+        return VINF_SUCCESS;
+    }
+    /**
+     * @opdone
+     * @opmnemonic  udvex660f382areg
+     * @opcode      0x2a
+     * @opcodesub   11 mr/reg
+     * @oppfx       0x66
+     * @opunused    immediate
+     * @opcpuid     avx
+     * @optest      ->
+     * @oponly
+     */
+    return IEMOP_RAISE_INVALID_OPCODE();
+
+}
+
 /** Opcode VEX.66.0F38 0x2b. */
 FNIEMOP_STUB(iemOp_vpackusdw_Vx_Hx_Wx);
 /** Opcode VEX.66.0F38 0x2c. */
@@ -621,7 +706,7 @@ IEM_STATIC const PFNIEMOP g_apfnVexMap2[] =
     /* 0x27 */  IEMOP_X4(iemOp_InvalidNeedRM),
     /* 0x28 */  iemOp_InvalidNeedRM,        iemOp_vpmuldq_Vx_Hx_Wx,     iemOp_InvalidNeedRM,        iemOp_InvalidNeedRM,
     /* 0x29 */  iemOp_InvalidNeedRM,        iemOp_vpcmpeqq_Vx_Hx_Wx,    iemOp_InvalidNeedRM,        iemOp_InvalidNeedRM,
-    /* 0x2a */  iemOp_InvalidNeedRM,        iemOp_vmovntdqa_Vx_Hx_Mx,   iemOp_InvalidNeedRM,        iemOp_InvalidNeedRM,
+    /* 0x2a */  iemOp_InvalidNeedRM,        iemOp_vmovntdqa_Vx_Mx,      iemOp_InvalidNeedRM,        iemOp_InvalidNeedRM,
     /* 0x2b */  iemOp_InvalidNeedRM,        iemOp_vpackusdw_Vx_Hx_Wx,   iemOp_InvalidNeedRM,        iemOp_InvalidNeedRM,
     /* 0x2c */  iemOp_InvalidNeedRM,        iemOp_vmaskmovps_Vx_Hx_Mx,  iemOp_InvalidNeedRM,        iemOp_InvalidNeedRM,
     /* 0x2d */  iemOp_InvalidNeedRM,        iemOp_vmaskmovpd_Vx_Hx_Mx,  iemOp_InvalidNeedRM,        iemOp_InvalidNeedRM,
diff --git a/src/VBox/VMM/VMMR0/CPUMR0A.asm b/src/VBox/VMM/VMMR0/CPUMR0A.asm
index ecc5472..7d2911c 100644
--- a/src/VBox/VMM/VMMR0/CPUMR0A.asm
+++ b/src/VBox/VMM/VMMR0/CPUMR0A.asm
@@ -65,7 +65,9 @@ ENDPROC   CPUMR0RegisterVCpuThread
 ;
 ; @uses nothing (well, maybe cr0)
 ;
+ %ifndef RT_ASM_WITH_SEH64 ; workaround for yasm 1.3.0 bug (error: prologue -1 bytes, must be <256)
 ALIGNCODE(16)
+ %endif
 BEGINPROC CPUMR0TouchHostFpu
         push    xBP
         SEH64_PUSH_xBP
@@ -87,7 +89,15 @@ ENDPROC   CPUMR0TouchHostFpu
 ; @returns  VINF_SUCCESS (0) or VINF_CPUM_HOST_CR0_MODIFIED. (EAX)
 ; @param    pCpumCpu  x86:[ebp+8] gcc:rdi msc:rcx     CPUMCPU pointer
 ;
+; @remarks  64-bit Windows drivers shouldn't use AVX registers without saving+loading:
+;               https://msdn.microsoft.com/en-us/library/windows/hardware/ff545910%28v=vs.85%29.aspx?f=255&MSPPError=-2147217396
+;           However the compiler docs have different idea:
+;               https://msdn.microsoft.com/en-us/library/9z1stfyw.aspx
+;           We'll go with the former for now.
+;
+%ifndef RT_ASM_WITH_SEH64 ; workaround for yasm 1.3.0 bug (error: prologue -1 bytes, must be <256)
 ALIGNCODE(16)
+%endif
 BEGINPROC cpumR0SaveHostRestoreGuestFPUState
         push    xBP
         SEH64_PUSH_xBP
@@ -134,6 +144,7 @@ SEH64_END_PROLOGUE
 %ifdef VBOX_WITH_KERNEL_USING_XMM
         ; If we didn't save the host state, we must save the non-volatile XMM registers.
         mov     pXState, [pCpumCpu + CPUMCPU.Host.pXStateR0]
+        stmxcsr [pXState + X86FXSTATE.MXCSR]
         movdqa  [pXState + X86FXSTATE.xmm6 ], xmm6
         movdqa  [pXState + X86FXSTATE.xmm7 ], xmm7
         movdqa  [pXState + X86FXSTATE.xmm8 ], xmm8
@@ -165,6 +176,7 @@ SEH64_END_PROLOGUE
         movdqa  xmm13, [pXState + X86FXSTATE.xmm13]
         movdqa  xmm14, [pXState + X86FXSTATE.xmm14]
         movdqa  xmm15, [pXState + X86FXSTATE.xmm15]
+        ldmxcsr        [pXState + X86FXSTATE.MXCSR]
 %endif
 
         or      dword [pCpumCpu + CPUMCPU.fUseFlags], (CPUM_USED_FPU_GUEST | CPUM_USED_FPU_SINCE_REM | CPUM_USED_FPU_HOST)
@@ -186,7 +198,15 @@ ENDPROC   cpumR0SaveHostRestoreGuestFPUState
 ;
 ; @param    pCpumCpu  x86:[ebp+8] gcc:rdi msc:rcx     CPUMCPU pointer
 ;
+; @remarks  64-bit Windows drivers shouldn't use AVX registers without saving+loading:
+;               https://msdn.microsoft.com/en-us/library/windows/hardware/ff545910%28v=vs.85%29.aspx?f=255&MSPPError=-2147217396
+;           However the compiler docs have different idea:
+;               https://msdn.microsoft.com/en-us/library/9z1stfyw.aspx
+;           We'll go with the former for now.
+;
+%ifndef RT_ASM_WITH_SEH64 ; workaround for yasm 1.3.0 bug (error: prologue -1 bytes, must be <256)
 ALIGNCODE(16)
+%endif
 BEGINPROC cpumR0SaveGuestRestoreHostFPUState
         push    xBP
         SEH64_PUSH_xBP
@@ -221,6 +241,7 @@ SEH64_END_PROLOGUE
         ; them while saving the guest state (we've gotta do this anyway).
         ;
         mov     pXState, [pCpumCpu + CPUMCPU.Host.pXStateR0]
+        stmxcsr [pXState + X86FXSTATE.MXCSR]
         movdqa  [pXState + X86FXSTATE.xmm6], xmm6
         movdqa  [pXState + X86FXSTATE.xmm7], xmm7
         movdqa  [pXState + X86FXSTATE.xmm8], xmm8
@@ -258,6 +279,7 @@ SEH64_END_PROLOGUE
         movdqa  xmm13, [pXState + X86FXSTATE.xmm13]
         movdqa  xmm14, [pXState + X86FXSTATE.xmm14]
         movdqa  xmm15, [pXState + X86FXSTATE.xmm15]
+        ldmxcsr        [pXState + X86FXSTATE.MXCSR]
  %endif
         CPUMR0_SAVE_GUEST
 
@@ -292,7 +314,9 @@ ENDPROC   cpumR0SaveGuestRestoreHostFPUState
 ;
 ; @param    pCpumCpu  x86:[ebp+8] gcc:rdi msc:rcx     CPUMCPU pointer
 ;
+  %ifndef RT_ASM_WITH_SEH64 ; workaround for yasm 1.3.0 bug (error: prologue -1 bytes, must be <256)
 ALIGNCODE(16)
+  %endif
 BEGINPROC cpumR0RestoreHostFPUState
         ;
         ; Prologue - xAX+xDX must be free for XSAVE/XRSTOR input.
diff --git a/src/VBox/VMM/VMMR0/GVMMR0.cpp b/src/VBox/VMM/VMMR0/GVMMR0.cpp
index 9260993..4acf9b9 100644
--- a/src/VBox/VMM/VMMR0/GVMMR0.cpp
+++ b/src/VBox/VMM/VMMR0/GVMMR0.cpp
@@ -360,6 +360,8 @@ static void gvmmR0InitPerVMData(PGVM pGVM);
 static DECLCALLBACK(void) gvmmR0HandleObjDestructor(void *pvObj, void *pvGVMM, void *pvHandle);
 static int gvmmR0ByVM(PVM pVM, PGVM *ppGVM, PGVMM *ppGVMM, bool fTakeUsedLock);
 static int gvmmR0ByVMAndEMT(PVM pVM, VMCPUID idCpu, PGVM *ppGVM, PGVMM *ppGVMM);
+static int gvmmR0ByGVMandVM(PGVM pGVM, PVM pVM, PGVMM *ppGVMM, bool fTakeUsedLock);
+
 #ifdef GVMM_SCHED_WITH_PPT
 static DECLCALLBACK(void) gvmmR0SchedPeriodicPreemptionTimerCallback(PRTTIMER pTimer, void *pvUser, uint64_t iTick);
 #endif
@@ -768,8 +770,9 @@ DECLINLINE(int) gvmmR0CreateDestroyUnlock(PGVMM pGVMM)
  *
  * @returns VBox status code.
  * @param   pReq        The request buffer.
+ * @param   pSession    The session handle. The VM will be associated with this.
  */
-GVMMR0DECL(int) GVMMR0CreateVMReq(PGVMMCREATEVMREQ pReq)
+GVMMR0DECL(int) GVMMR0CreateVMReq(PGVMMCREATEVMREQ pReq, PSUPDRVSESSION pSession)
 {
     /*
      * Validate the request.
@@ -778,7 +781,7 @@ GVMMR0DECL(int) GVMMR0CreateVMReq(PGVMMCREATEVMREQ pReq)
         return VERR_INVALID_POINTER;
     if (pReq->Hdr.cbReq != sizeof(*pReq))
         return VERR_INVALID_PARAMETER;
-    if (!VALID_PTR(pReq->pSession))
+    if (pReq->pSession != pSession)
         return VERR_INVALID_POINTER;
 
     /*
@@ -787,7 +790,7 @@ GVMMR0DECL(int) GVMMR0CreateVMReq(PGVMMCREATEVMREQ pReq)
     PVM pVM;
     pReq->pVMR0 = NULL;
     pReq->pVMR3 = NIL_RTR3PTR;
-    int rc = GVMMR0CreateVM(pReq->pSession, pReq->cCpus, &pVM);
+    int rc = GVMMR0CreateVM(pSession, pReq->cCpus, &pVM);
     if (RT_SUCCESS(rc))
     {
         pReq->pVMR0 = pVM;
@@ -834,6 +837,16 @@ GVMMR0DECL(int) GVMMR0CreateVM(PSUPDRVSESSION pSession, uint32_t cCpus, PVM *ppV
     AssertRCReturn(rc, rc);
 
     /*
+     * Only one VM per session.
+     */
+    if (SUPR0GetSessionVM(pSession) != NULL)
+    {
+        gvmmR0CreateDestroyUnlock(pGVMM);
+        SUPR0Printf("GVMMR0CreateVM: The session %p already got a VM: %p\n", pSession, SUPR0GetSessionVM(pSession));
+        return VERR_ALREADY_EXISTS;
+    }
+
+    /*
      * Allocate a handle first so we don't waste resources unnecessarily.
      */
     uint16_t iHandle = pGVMM->iFreeHead;
@@ -882,6 +895,7 @@ GVMMR0DECL(int) GVMMR0CreateVM(PSUPDRVSESSION pSession, uint32_t cCpus, PVM *ppV
                         pGVM->hSelf     = iHandle;
                         pGVM->pVM       = NULL;
                         pGVM->cCpus     = cCpus;
+                        pGVM->pSession  = pSession;
 
                         gvmmR0InitPerVMData(pGVM);
                         GMMR0InitPerVMData(pGVM);
@@ -959,21 +973,30 @@ GVMMR0DECL(int) GVMMR0CreateVM(PSUPDRVSESSION pSession, uint32_t cCpus, PVM *ppV
                                         pVM->aCpus[0].hNativeThreadR0 = hEMT0;
                                         pGVMM->cEMTs += cCpus;
 
-                                        rc = VMMR0ThreadCtxHookCreateForEmt(&pVM->aCpus[0]);
+                                        /* Associate it with the session and create the context hook for EMT0. */
+                                        rc = SUPR0SetSessionVM(pSession, pGVM, pVM);
                                         if (RT_SUCCESS(rc))
                                         {
-                                            VBOXVMM_R0_GVMM_VM_CREATED(pGVM, pVM, ProcId, (void *)hEMT0, cCpus);
+                                            rc = VMMR0ThreadCtxHookCreateForEmt(&pVM->aCpus[0]);
+                                            if (RT_SUCCESS(rc))
+                                            {
+                                                /*
+                                                 * Done!
+                                                 */
+                                                VBOXVMM_R0_GVMM_VM_CREATED(pGVM, pVM, ProcId, (void *)hEMT0, cCpus);
 
-                                            GVMMR0_USED_EXCLUSIVE_UNLOCK(pGVMM);
-                                            gvmmR0CreateDestroyUnlock(pGVMM);
+                                                GVMMR0_USED_EXCLUSIVE_UNLOCK(pGVMM);
+                                                gvmmR0CreateDestroyUnlock(pGVMM);
 
-                                            CPUMR0RegisterVCpuThread(&pVM->aCpus[0]);
+                                                CPUMR0RegisterVCpuThread(&pVM->aCpus[0]);
 
-                                            *ppVM = pVM;
-                                            Log(("GVMMR0CreateVM: pVM=%p pVMR3=%p pGVM=%p hGVM=%d\n", pVM, pVM->pVMR3, pGVM, iHandle));
-                                            return VINF_SUCCESS;
-                                        }
+                                                *ppVM = pVM;
+                                                Log(("GVMMR0CreateVM: pVM=%p pVMR3=%p pGVM=%p hGVM=%d\n", pVM, pVM->pVMR3, pGVM, iHandle));
+                                                return VINF_SUCCESS;
+                                            }
 
+                                            SUPR0SetSessionVM(pSession, NULL, NULL);
+                                        }
                                         GVMMR0_USED_EXCLUSIVE_UNLOCK(pGVMM);
                                     }
 
@@ -1138,33 +1161,36 @@ GVMMR0DECL(bool) GVMMR0DoingTermVM(PVM pVM, PGVM pGVM)
  * could've associated the calling thread with the VM up front.
  *
  * @returns VBox status code.
+ * @param   pGVM        The global (ring-0) VM structure.
  * @param   pVM         The cross context VM structure.
  *
  * @thread  EMT(0) if it's associated with the VM, otherwise any thread.
  */
-GVMMR0DECL(int) GVMMR0DestroyVM(PVM pVM)
+GVMMR0DECL(int) GVMMR0DestroyVM(PGVM pGVM, PVM pVM)
 {
-    LogFlow(("GVMMR0DestroyVM: pVM=%p\n", pVM));
+    LogFlow(("GVMMR0DestroyVM: pGVM=%p pVM=%p\n", pGVM, pVM));
     PGVMM pGVMM;
     GVMM_GET_VALID_INSTANCE(pGVMM, VERR_GVMM_INSTANCE);
 
     /*
      * Validate the VM structure, state and caller.
      */
+    AssertPtrReturn(pGVM, VERR_INVALID_POINTER);
     AssertPtrReturn(pVM, VERR_INVALID_POINTER);
     AssertReturn(!((uintptr_t)pVM & PAGE_OFFSET_MASK), VERR_INVALID_POINTER);
+    AssertReturn(pGVM->pVM == pVM, VERR_INVALID_POINTER);
     AssertMsgReturn(pVM->enmVMState >= VMSTATE_CREATING && pVM->enmVMState <= VMSTATE_TERMINATED, ("%d\n", pVM->enmVMState),
                     VERR_WRONG_ORDER);
 
-    uint32_t hGVM = pVM->hSelf;
+    uint32_t        hGVM = pGVM->hSelf;
     AssertReturn(hGVM != NIL_GVM_HANDLE, VERR_INVALID_HANDLE);
     AssertReturn(hGVM < RT_ELEMENTS(pGVMM->aHandles), VERR_INVALID_HANDLE);
 
-    PGVMHANDLE pHandle = &pGVMM->aHandles[hGVM];
+    PGVMHANDLE      pHandle = &pGVMM->aHandles[hGVM];
     AssertReturn(pHandle->pVM == pVM, VERR_NOT_OWNER);
 
-    RTPROCESS      ProcId = RTProcSelf();
-    RTNATIVETHREAD hSelf  = RTThreadNativeSelf();
+    RTPROCESS       ProcId = RTProcSelf();
+    RTNATIVETHREAD  hSelf  = RTThreadNativeSelf();
     AssertReturn(   (   pHandle->hEMT0  == hSelf
                      && pHandle->ProcId == ProcId)
                  || pHandle->hEMT0 == NIL_RTNATIVETHREAD, VERR_NOT_OWNER);
@@ -1177,6 +1203,9 @@ GVMMR0DECL(int) GVMMR0DestroyVM(PVM pVM)
     int rc = gvmmR0CreateDestroyLock(pGVMM);
     AssertRC(rc);
 
+/** @todo Check that all other EMTs have said bye-bye. */
+
+
     /* Be careful here because we might theoretically be racing someone else cleaning up. */
     if (    pHandle->pVM == pVM
         &&  (   (   pHandle->hEMT0  == hSelf
@@ -1329,6 +1358,10 @@ static DECLCALLBACK(void) gvmmR0HandleObjDestructor(void *pvObj, void *pvUser1,
         &&  pGVM->u32Magic == GVM_MAGIC)
     {
         pGVMM->cEMTs -= pGVM->cCpus;
+
+        if (pGVM->pSession)
+            SUPR0SetSessionVM(pGVM->pSession, NULL, NULL);
+
         GVMMR0_USED_EXCLUSIVE_UNLOCK(pGVMM);
 
         gvmmR0CleanupVM(pGVM);
@@ -1404,32 +1437,52 @@ static DECLCALLBACK(void) gvmmR0HandleObjDestructor(void *pvObj, void *pvUser1,
  * Note that VCPU 0 is automatically registered during VM creation.
  *
  * @returns VBox status code
- * @param   pVM             The cross context VM structure.
- * @param   idCpu           VCPU id.
+ * @param   pGVM        The global (ring-0) VM structure.
+ * @param   pVM         The cross context VM structure.
+ * @param   idCpu       VCPU id to register the current thread as.
  */
-GVMMR0DECL(int) GVMMR0RegisterVCpu(PVM pVM, VMCPUID idCpu)
+GVMMR0DECL(int) GVMMR0RegisterVCpu(PGVM pGVM, PVM pVM, VMCPUID idCpu)
 {
     AssertReturn(idCpu != 0, VERR_NOT_OWNER);
 
     /*
      * Validate the VM structure, state and handle.
      */
-    PGVM pGVM;
     PGVMM pGVMM;
-    int rc = gvmmR0ByVM(pVM, &pGVM, &pGVMM, false /* fTakeUsedLock */); /** @todo take lock here. */
-    if (RT_FAILURE(rc))
-        return rc;
-
-    AssertReturn(idCpu < pGVM->cCpus, VERR_INVALID_CPU_ID);
-    AssertReturn(pGVM->aCpus[idCpu].hEMT == NIL_RTNATIVETHREAD, VERR_ACCESS_DENIED);
-    Assert(pGVM->cCpus == pVM->cCpus);
-    Assert(pVM->aCpus[idCpu].hNativeThreadR0 == NIL_RTNATIVETHREAD);
+    int rc = gvmmR0ByGVMandVM(pGVM, pVM, &pGVMM, false /* fTakeUsedLock */); /** @todo take lock here. */
+    if (RT_SUCCESS(rc))
+    {
+        if (idCpu < pGVM->cCpus)
+        {
+            /* Check that the EMT isn't already assigned to a thread. */
+            if (pGVM->aCpus[idCpu].hEMT == NIL_RTNATIVETHREAD)
+            {
+                Assert(pVM->aCpus[idCpu].hNativeThreadR0 == NIL_RTNATIVETHREAD);
 
-    pVM->aCpus[idCpu].hNativeThreadR0 = pGVM->aCpus[idCpu].hEMT = RTThreadNativeSelf();
+                /* A thread may only be one EMT. */
+                RTNATIVETHREAD const hNativeSelf = RTThreadNativeSelf();
+                for (VMCPUID iCpu = 0; iCpu < pGVM->cCpus; iCpu++)
+                    AssertBreakStmt(pGVM->aCpus[iCpu].hEMT != hNativeSelf, rc = VERR_INVALID_PARAMETER);
+                if (RT_SUCCESS(rc))
+                {
+                    /*
+                     * Do the assignment, then try setup the hook. Undo if that fails.
+                     */
+                    pVM->aCpus[idCpu].hNativeThreadR0 = pGVM->aCpus[idCpu].hEMT = RTThreadNativeSelf();
 
-    rc = VMMR0ThreadCtxHookCreateForEmt(&pVM->aCpus[idCpu]);
-    if (RT_SUCCESS(rc))
-        CPUMR0RegisterVCpuThread(&pVM->aCpus[idCpu]);
+                    rc = VMMR0ThreadCtxHookCreateForEmt(&pVM->aCpus[idCpu]);
+                    if (RT_SUCCESS(rc))
+                        CPUMR0RegisterVCpuThread(&pVM->aCpus[idCpu]);
+                    else
+                        pVM->aCpus[idCpu].hNativeThreadR0 = pGVM->aCpus[idCpu].hEMT = NIL_RTNATIVETHREAD;
+                }
+            }
+            else
+                rc = VERR_ACCESS_DENIED;
+        }
+        else
+            rc = VERR_INVALID_CPU_ID;
+    }
     return rc;
 }
 
@@ -1548,6 +1601,89 @@ static int gvmmR0ByVM(PVM pVM, PGVM *ppGVM, PGVMM *ppGVMM, bool fTakeUsedLock)
 
 
 /**
+ * Check that the given GVM and VM structures match up.
+ *
+ * The calling thread must be in the same process as the VM. All current lookups
+ * are by threads inside the same process, so this will not be an issue.
+ *
+ * @returns VBox status code.
+ * @param   pGVM            The global (ring-0) VM structure.
+ * @param   pVM             The cross context VM structure.
+ * @param   ppGVMM          Where to store the pointer to the GVMM instance data.
+ * @param   fTakeUsedLock   Whether to take the used lock or not.  We take it in
+ *                          shared mode when requested.
+ *
+ *                          Be very careful if not taking the lock as it's
+ *                          possible that the VM will disappear then!
+ *
+ * @remark  This will not assert on an invalid pVM but try return silently.
+ */
+static int gvmmR0ByGVMandVM(PGVM pGVM, PVM pVM, PGVMM *ppGVMM, bool fTakeUsedLock)
+{
+    /*
+     * Check the pointers.
+     */
+    int rc;
+    if (RT_LIKELY(RT_VALID_PTR(pGVM)))
+    {
+        if (RT_LIKELY(   RT_VALID_PTR(pVM)
+                      && ((uintptr_t)pVM & PAGE_OFFSET_MASK) == 0))
+        {
+            if (RT_LIKELY(pGVM->pVM == pVM))
+            {
+                /*
+                 * Get the pGVMM instance and check the VM handle.
+                 */
+                PGVMM pGVMM;
+                GVMM_GET_VALID_INSTANCE(pGVMM, VERR_GVMM_INSTANCE);
+
+                uint16_t hGVM = pGVM->hSelf;
+                if (RT_LIKELY(   hGVM != NIL_GVM_HANDLE
+                              && hGVM < RT_ELEMENTS(pGVMM->aHandles)))
+                {
+                    RTPROCESS const pidSelf = RTProcSelf();
+                    PGVMHANDLE      pHandle = &pGVMM->aHandles[hGVM];
+                    if (fTakeUsedLock)
+                    {
+                        rc = GVMMR0_USED_SHARED_LOCK(pGVMM);
+                        AssertRCReturn(rc, rc);
+                    }
+
+                    if (RT_LIKELY(   pHandle->pGVM   == pGVM
+                                  && pHandle->pVM    == pVM
+                                  && pHandle->ProcId == pidSelf
+                                  && RT_VALID_PTR(pHandle->pvObj)))
+                    {
+                        /*
+                         * Some more VM data consistency checks.
+                         */
+                        if (RT_LIKELY(   pVM->cCpus == pGVM->cCpus
+                                      && pVM->hSelf == hGVM
+                                      && pVM->enmVMState >= VMSTATE_CREATING
+                                      && pVM->enmVMState <= VMSTATE_TERMINATED
+                                      && pVM->pVMR0 == pVM))
+                        {
+                            *ppGVMM = pGVMM;
+                            return VINF_SUCCESS;
+                        }
+                    }
+
+                    if (fTakeUsedLock)
+                        GVMMR0_USED_SHARED_UNLOCK(pGVMM);
+                }
+            }
+            rc = VERR_INVALID_HANDLE;
+        }
+        else
+            rc = VERR_INVALID_POINTER;
+    }
+    else
+        rc = VERR_INVALID_POINTER;
+    return rc;
+}
+
+
+/**
  * Lookup a GVM structure by the shared VM structure.
  *
  * @returns VBox status code.
@@ -2589,16 +2725,18 @@ GVMMR0DECL(int) GVMMR0QueryStatistics(PGVMMSTATS pStats, PSUPDRVSESSION pSession
  * @returns see GVMMR0QueryStatistics.
  * @param   pVM             The cross context VM structure. Optional.
  * @param   pReq            Pointer to the request packet.
+ * @param   pSession        The current session.
  */
-GVMMR0DECL(int) GVMMR0QueryStatisticsReq(PVM pVM, PGVMMQUERYSTATISTICSSREQ pReq)
+GVMMR0DECL(int) GVMMR0QueryStatisticsReq(PVM pVM, PGVMMQUERYSTATISTICSSREQ pReq, PSUPDRVSESSION pSession)
 {
     /*
      * Validate input and pass it on.
      */
     AssertPtrReturn(pReq, VERR_INVALID_POINTER);
     AssertMsgReturn(pReq->Hdr.cbReq == sizeof(*pReq), ("%#x != %#x\n", pReq->Hdr.cbReq, sizeof(*pReq)), VERR_INVALID_PARAMETER);
+    AssertReturn(pReq->pSession == pSession, VERR_INVALID_PARAMETER);
 
-    return GVMMR0QueryStatistics(&pReq->Stats, pReq->pSession, pVM);
+    return GVMMR0QueryStatistics(&pReq->Stats, pSession, pVM);
 }
 
 
@@ -2704,15 +2842,17 @@ GVMMR0DECL(int) GVMMR0ResetStatistics(PCGVMMSTATS pStats, PSUPDRVSESSION pSessio
  * @returns see GVMMR0ResetStatistics.
  * @param   pVM             The cross context VM structure. Optional.
  * @param   pReq            Pointer to the request packet.
+ * @param   pSession        The current session.
  */
-GVMMR0DECL(int) GVMMR0ResetStatisticsReq(PVM pVM, PGVMMRESETSTATISTICSSREQ pReq)
+GVMMR0DECL(int) GVMMR0ResetStatisticsReq(PVM pVM, PGVMMRESETSTATISTICSSREQ pReq, PSUPDRVSESSION pSession)
 {
     /*
      * Validate input and pass it on.
      */
     AssertPtrReturn(pReq, VERR_INVALID_POINTER);
     AssertMsgReturn(pReq->Hdr.cbReq == sizeof(*pReq), ("%#x != %#x\n", pReq->Hdr.cbReq, sizeof(*pReq)), VERR_INVALID_PARAMETER);
+    AssertReturn(pReq->pSession == pSession, VERR_INVALID_PARAMETER);
 
-    return GVMMR0ResetStatistics(&pReq->Stats, pReq->pSession, pVM);
+    return GVMMR0ResetStatistics(&pReq->Stats, pSession, pVM);
 }
 
diff --git a/src/VBox/VMM/VMMR0/HMR0A.asm b/src/VBox/VMM/VMMR0/HMR0A.asm
index 2525e9d..887ffa4 100644
--- a/src/VBox/VMM/VMMR0/HMR0A.asm
+++ b/src/VBox/VMM/VMMR0/HMR0A.asm
@@ -284,20 +284,30 @@ BEGINPROC VMXRestoreHostState
     mov         dx, [rsi + VMXRESTOREHOST.uHostSelTR]
     mov         ax, dx
     and         eax, X86_SEL_MASK_OFF_RPL                       ; Mask away TI and RPL bits leaving only the descriptor offset.
-    add         rax, qword [rsi + VMXRESTOREHOST.HostGdtr + 2]  ; xAX <- descriptor offset + GDTR.pGdt.
-    test        edi, VMX_RESTORE_HOST_GDT_READ_ONLY
+    test        edi, VMX_RESTORE_HOST_GDT_READ_ONLY | VMX_RESTORE_HOST_GDT_NEED_WRITABLE
     jnz         .gdt_readonly
+    add         rax, qword [rsi + VMXRESTOREHOST.HostGdtr + 2]  ; xAX <- descriptor offset + GDTR.pGdt.
     and         dword [rax + 4], ~RT_BIT(9)                     ; Clear the busy flag in TSS desc (bits 0-7=base, bit 9=busy bit).
     ltr         dx
     jmp short   .test_fs
 .gdt_readonly:
+    test        edi, VMX_RESTORE_HOST_GDT_NEED_WRITABLE
+    jnz         .gdt_readonly_need_writable
     mov         rcx, cr0
     mov         r9, rcx
+    add         rax, qword [rsi + VMXRESTOREHOST.HostGdtr + 2]  ; xAX <- descriptor offset + GDTR.pGdt.
     and         rcx, ~X86_CR0_WP
     mov         cr0, rcx
     and         dword [rax + 4], ~RT_BIT(9)                     ; Clear the busy flag in TSS desc (bits 0-7=base, bit 9=busy bit).
     ltr         dx
     mov         cr0, r9
+    jmp short   .test_fs
+.gdt_readonly_need_writable:
+    add         rax, qword [rsi + VMXRESTOREHOST.HostGdtrRw + 2]  ; xAX <- descriptor offset + GDTR.pGdtRw.
+    and         dword [rax + 4], ~RT_BIT(9)                     ; Clear the busy flag in TSS desc (bits 0-7=base, bit 9=busy bit).
+    lgdt        [rsi + VMXRESTOREHOST.HostGdtrRw]
+    ltr         dx
+    lgdt        [rsi + VMXRESTOREHOST.HostGdtr]                 ; Load the original GDT
 
 .test_fs:
     ;
@@ -807,12 +817,19 @@ ENDPROC SVMR0InvlpgA
 ;
 ; @remarks      This is essentially the same code as HMR0SVMRunWrapXMM, only the parameters differ a little bit.
 ;
+; @remarks      Drivers shouldn't use AVX registers without saving+loading:
+;                   https://msdn.microsoft.com/en-us/library/windows/hardware/ff545910%28v=vs.85%29.aspx?f=255&MSPPError=-2147217396
+;               However the compiler docs have different idea:
+;                   https://msdn.microsoft.com/en-us/library/9z1stfyw.aspx
+;               We'll go with the former for now.
+;
 ; ASSUMING 64-bit and windows for now.
+;
 ALIGNCODE(16)
 BEGINPROC HMR0VMXStartVMWrapXMM
         push    xBP
         mov     xBP, xSP
-        sub     xSP, 0a0h + 040h        ; Don't bother optimizing the frame size.
+        sub     xSP, 0b0h + 040h ; Don't bother optimizing the frame size.
 
         ; spill input parameters.
         mov     [xBP + 010h], rcx       ; fResumeVM
@@ -852,6 +869,7 @@ ALIGNCODE(8)
         movdqa  [rsp + 040h + 070h], xmm13
         movdqa  [rsp + 040h + 080h], xmm14
         movdqa  [rsp + 040h + 090h], xmm15
+        stmxcsr [rsp + 040h + 0a0h]
 
         mov     r10, [xBP + 018h]       ; pCtx
         mov     eax, [r10 + CPUMCTX.fXStateMask]
@@ -900,6 +918,7 @@ ALIGNCODE(8)
         movdqa  xmm13, [rsp + 040h + 070h]
         movdqa  xmm14, [rsp + 040h + 080h]
         movdqa  xmm15, [rsp + 040h + 090h]
+        ldmxcsr        [rsp + 040h + 0a0h]
         leave
         ret
 
@@ -925,6 +944,7 @@ ALIGNCODE(8)
         movdqa  xmm13, [r10 + XMM_OFF_IN_X86FXSTATE + 0d0h]
         movdqa  xmm14, [r10 + XMM_OFF_IN_X86FXSTATE + 0e0h]
         movdqa  xmm15, [r10 + XMM_OFF_IN_X86FXSTATE + 0f0h]
+        ldmxcsr        [r10 + X86FXSTATE.MXCSR]
 
         ; Make the call (same as in the other case ).
         mov     r11, [xBP + 38h]        ; pfnStartVM
@@ -939,6 +959,7 @@ ALIGNCODE(8)
         ; Save the guest XMM registers.
         mov     r10, [xBP + 018h]       ; pCtx
         mov     r10, [r10 + CPUMCTX.pXStateR0]
+        stmxcsr [r10 + X86FXSTATE.MXCSR]
         movdqa  [r10 + XMM_OFF_IN_X86FXSTATE + 000h], xmm0
         movdqa  [r10 + XMM_OFF_IN_X86FXSTATE + 010h], xmm1
         movdqa  [r10 + XMM_OFF_IN_X86FXSTATE + 020h], xmm2
@@ -975,12 +996,18 @@ ENDPROC   HMR0VMXStartVMWrapXMM
 ;
 ; @remarks      This is essentially the same code as HMR0VMXStartVMWrapXMM, only the parameters differ a little bit.
 ;
+; @remarks      Drivers shouldn't use AVX registers without saving+loading:
+;                   https://msdn.microsoft.com/en-us/library/windows/hardware/ff545910%28v=vs.85%29.aspx?f=255&MSPPError=-2147217396
+;               However the compiler docs have different idea:
+;                   https://msdn.microsoft.com/en-us/library/9z1stfyw.aspx
+;               We'll go with the former for now.
+;
 ; ASSUMING 64-bit and windows for now.
 ALIGNCODE(16)
 BEGINPROC HMR0SVMRunWrapXMM
         push    xBP
         mov     xBP, xSP
-        sub     xSP, 0a0h + 040h        ; Don't bother optimizing the frame size.
+        sub     xSP, 0b0h + 040h        ; Don't bother optimizing the frame size.
 
         ; spill input parameters.
         mov     [xBP + 010h], rcx       ; pVMCBHostPhys
@@ -1020,6 +1047,7 @@ ALIGNCODE(8)
         movdqa  [rsp + 040h + 070h], xmm13
         movdqa  [rsp + 040h + 080h], xmm14
         movdqa  [rsp + 040h + 090h], xmm15
+        stmxcsr [rsp + 040h + 0a0h]
 
         mov     r10, [xBP + 020h]       ; pCtx
         mov     eax, [r10 + CPUMCTX.fXStateMask]
@@ -1068,6 +1096,7 @@ ALIGNCODE(8)
         movdqa  xmm13, [rsp + 040h + 070h]
         movdqa  xmm14, [rsp + 040h + 080h]
         movdqa  xmm15, [rsp + 040h + 090h]
+        ldmxcsr [rsp + 040h + 0a0h]
         leave
         ret
 
@@ -1093,6 +1122,7 @@ ALIGNCODE(8)
         movdqa  xmm13, [r10 + XMM_OFF_IN_X86FXSTATE + 0d0h]
         movdqa  xmm14, [r10 + XMM_OFF_IN_X86FXSTATE + 0e0h]
         movdqa  xmm15, [r10 + XMM_OFF_IN_X86FXSTATE + 0f0h]
+        ldmxcsr        [r10 + X86FXSTATE.MXCSR]
 
         ; Make the call (same as in the other case ).
         mov     r11, [xBP + 38h]        ; pfnVMRun
@@ -1107,6 +1137,7 @@ ALIGNCODE(8)
         ; Save the guest XMM registers.
         mov     r10, [xBP + 020h]       ; pCtx
         mov     r10, [r10 + CPUMCTX.pXStateR0]
+        stmxcsr [r10 + X86FXSTATE.MXCSR]
         movdqa  [r10 + XMM_OFF_IN_X86FXSTATE + 000h], xmm0
         movdqa  [r10 + XMM_OFF_IN_X86FXSTATE + 010h], xmm1
         movdqa  [r10 + XMM_OFF_IN_X86FXSTATE + 020h], xmm2
diff --git a/src/VBox/VMM/VMMR0/HMSVMR0.cpp b/src/VBox/VMM/VMMR0/HMSVMR0.cpp
index c09b126..667fac6 100644
--- a/src/VBox/VMM/VMMR0/HMSVMR0.cpp
+++ b/src/VBox/VMM/VMMR0/HMSVMR0.cpp
@@ -1040,10 +1040,10 @@ static void hmR0SvmFlushTaggedTlb(PVMCPU pVCpu)
 DECLASM(int) SVMR0VMSwitcherRun64(RTHCPHYS HCPhysVmcbHost, RTHCPHYS HCPhysVmcb, PCPUMCTX pCtx, PVM pVM, PVMCPU pVCpu)
 {
     uint32_t aParam[8];
-    aParam[0] = (uint32_t)(HCPhysVmcbHost);             /* Param 1: HCPhysVmcbHost - Lo. */
-    aParam[1] = (uint32_t)(HCPhysVmcbHost >> 32);       /* Param 1: HCPhysVmcbHost - Hi. */
-    aParam[2] = (uint32_t)(HCPhysVmcb);                 /* Param 2: HCPhysVmcb - Lo. */
-    aParam[3] = (uint32_t)(HCPhysVmcb >> 32);           /* Param 2: HCPhysVmcb - Hi. */
+    aParam[0] = RT_LO_U32(HCPhysVmcbHost);              /* Param 1: HCPhysVmcbHost - Lo. */
+    aParam[1] = RT_HI_U32(HCPhysVmcbHost);              /* Param 1: HCPhysVmcbHost - Hi. */
+    aParam[2] = RT_LO_U32(HCPhysVmcb);                  /* Param 2: HCPhysVmcb - Lo. */
+    aParam[3] = RT_HI_U32(HCPhysVmcb);                  /* Param 2: HCPhysVmcb - Hi. */
     aParam[4] = VM_RC_ADDR(pVM, pVM);
     aParam[5] = 0;
     aParam[6] = VM_RC_ADDR(pVM, pVCpu);
diff --git a/src/VBox/VMM/VMMR0/HMVMXR0.cpp b/src/VBox/VMM/VMMR0/HMVMXR0.cpp
index 85cf0d4..0432b2d 100644
--- a/src/VBox/VMM/VMMR0/HMVMXR0.cpp
+++ b/src/VBox/VMM/VMMR0/HMVMXR0.cpp
@@ -3038,11 +3038,7 @@ DECLINLINE(int) hmR0VmxSaveHostSegmentRegs(PVM pVM, PVMCPU pVCpu)
      * maximum limit (0xffff) on every VM-exit.
      */
     if (Gdtr.cbGdt != 0xffff)
-    {
         pVCpu->hm.s.vmx.fRestoreHostFlags |= VMX_RESTORE_HOST_GDTR;
-        AssertCompile(sizeof(Gdtr) == sizeof(X86XDTR64));
-        memcpy(&pVCpu->hm.s.vmx.RestoreHost.HostGdtr, &Gdtr, sizeof(X86XDTR64));
-    }
 
     /*
      * IDT limit is effectively capped at 0xfff. (See Intel spec. 6.14.1 "64-Bit Mode IDT"
@@ -3094,9 +3090,23 @@ DECLINLINE(int) hmR0VmxSaveHostSegmentRegs(PVM pVM, PVMCPU pVCpu)
         if (pVM->hm.s.fHostKernelFeatures & SUPKERNELFEATURES_GDT_READ_ONLY)
             pVCpu->hm.s.vmx.fRestoreHostFlags |= VMX_RESTORE_HOST_GDT_READ_ONLY;
         pVCpu->hm.s.vmx.RestoreHost.uHostSelTR = uSelTR;
+    }
 
-        /* Store the GDTR here as we need it while restoring TR. */
+    /*
+     * Store the GDTR as we need it when restoring the GDT and while restoring the TR.
+     */
+    if (pVCpu->hm.s.vmx.fRestoreHostFlags & (VMX_RESTORE_HOST_GDTR | VMX_RESTORE_HOST_SEL_TR))
+    {
+        AssertCompile(sizeof(Gdtr) == sizeof(X86XDTR64));
         memcpy(&pVCpu->hm.s.vmx.RestoreHost.HostGdtr, &Gdtr, sizeof(X86XDTR64));
+        if (pVM->hm.s.fHostKernelFeatures & SUPKERNELFEATURES_GDT_NEED_WRITABLE)
+        {
+            /* The GDT is read-only but the writable GDT is available. */
+            pVCpu->hm.s.vmx.fRestoreHostFlags |= VMX_RESTORE_HOST_GDT_NEED_WRITABLE;
+            pVCpu->hm.s.vmx.RestoreHost.HostGdtrRw.cb = Gdtr.cbGdt;
+            rc = SUPR0GetCurrentGdtRw(&pVCpu->hm.s.vmx.RestoreHost.HostGdtrRw.uAddr);
+            AssertRCReturn(rc, rc);
+        }
     }
 #else
     NOREF(pVM);
@@ -5396,10 +5406,10 @@ DECLASM(int) VMXR0SwitcherStartVM64(RTHCUINT fResume, PCPUMCTX pCtx, PVMCSCACHE
 #endif
 
     uint32_t aParam[10];
-    aParam[0] = (uint32_t)(HCPhysCpuPage);                              /* Param 1: VMXON physical address - Lo. */
-    aParam[1] = (uint32_t)(HCPhysCpuPage >> 32);                        /* Param 1: VMXON physical address - Hi. */
-    aParam[2] = (uint32_t)(pVCpu->hm.s.vmx.HCPhysVmcs);                 /* Param 2: VMCS physical address - Lo. */
-    aParam[3] = (uint32_t)(pVCpu->hm.s.vmx.HCPhysVmcs >> 32);           /* Param 2: VMCS physical address - Hi. */
+    aParam[0] = RT_LO_U32(HCPhysCpuPage);                               /* Param 1: VMXON physical address - Lo. */
+    aParam[1] = RT_HI_U32(HCPhysCpuPage);                               /* Param 1: VMXON physical address - Hi. */
+    aParam[2] = RT_LO_U32(pVCpu->hm.s.vmx.HCPhysVmcs);                  /* Param 2: VMCS physical address - Lo. */
+    aParam[3] = RT_HI_U32(pVCpu->hm.s.vmx.HCPhysVmcs);                  /* Param 2: VMCS physical address - Hi. */
     aParam[4] = VM_RC_ADDR(pVM, &pVM->aCpus[pVCpu->idCpu].hm.s.vmx.VMCSCache);
     aParam[5] = 0;
     aParam[6] = VM_RC_ADDR(pVM, pVM);
@@ -5580,8 +5590,8 @@ VMMR0DECL(int) VMXWriteVmcs64Ex(PVMCPU pVCpu, uint32_t idxField, uint64_t u64Val
         case VMX_VMCS64_HOST_EFER_FULL:
         case VMX_VMCS64_HOST_PERF_GLOBAL_CTRL_FULL:
         {
-            rc  = VMXWriteVmcs32(idxField, u64Val);
-            rc |= VMXWriteVmcs32(idxField + 1, (uint32_t)(u64Val >> 32));
+            rc  = VMXWriteVmcs32(idxField,     RT_LO_U32(u64Val));
+            rc |= VMXWriteVmcs32(idxField + 1, RT_HI_U32(u64Val));
             break;
         }
 
@@ -5606,10 +5616,10 @@ VMMR0DECL(int) VMXWriteVmcs64Ex(PVMCPU pVCpu, uint32_t idxField, uint64_t u64Val
         case VMX_VMCS_GUEST_SYSENTER_ESP:
         case VMX_VMCS_GUEST_SYSENTER_EIP:
         {
-            if (!(u64Val >> 32))
+            if (!(RT_HI_U32(u64Val)))
             {
                 /* If this field is 64-bit, VT-x will zero out the top bits. */
-                rc = VMXWriteVmcs32(idxField, (uint32_t)u64Val);
+                rc = VMXWriteVmcs32(idxField, RT_LO_U32(u64Val));
             }
             else
             {
@@ -7982,8 +7992,12 @@ static VBOXSTRICTRC hmR0VmxInjectEventVmcs(PVMCPU pVCpu, PCPUMCTX pMixedCtx, uin
     uint32_t const uIntType = VMX_EXIT_INTERRUPTION_INFO_TYPE(u32IntInfo);
 
 #ifdef VBOX_STRICT
-    /* Validate the error-code-valid bit for hardware exceptions. */
-    if (uIntType == VMX_EXIT_INTERRUPTION_INFO_TYPE_HW_XCPT)
+    /*
+     * Validate the error-code-valid bit for hardware exceptions.
+     * No error codes for exceptions in real-mode. See Intel spec. 20.1.4 "Interrupt and Exception Handling"
+     */
+    if (   uIntType == VMX_EXIT_INTERRUPTION_INFO_TYPE_HW_XCPT
+        && !CPUMIsGuestInRealModeEx(pMixedCtx))
     {
         switch (uVector)
         {
@@ -7996,7 +8010,7 @@ static VBOXSTRICTRC hmR0VmxInjectEventVmcs(PVMCPU pVCpu, PCPUMCTX pMixedCtx, uin
             case X86_XCPT_AC:
                 AssertMsg(VMX_EXIT_INTERRUPTION_INFO_ERROR_CODE_IS_VALID(u32IntInfo),
                           ("Error-code-valid bit not set for exception that has an error code uVector=%#x\n", uVector));
-                /* fallthru */
+                /* fall thru */
             default:
                 break;
         }
@@ -11306,10 +11320,10 @@ HMVMX_EXIT_DECL hmR0VmxExitXcptOrNmi(PVMCPU pVCpu, PCPUMCTX pMixedCtx, PVMXTRANS
     {
         case VMX_EXIT_INTERRUPTION_INFO_TYPE_PRIV_SW_XCPT:  /* Privileged software exception. (#DB from ICEBP) */
             Assert(uVector == X86_XCPT_DB);
-            /* no break */
+            /* fall thru */
         case VMX_EXIT_INTERRUPTION_INFO_TYPE_SW_XCPT:       /* Software exception. (#BP or #OF) */
             Assert(uVector == X86_XCPT_BP || uVector == X86_XCPT_OF || uIntType == VMX_EXIT_INTERRUPTION_INFO_TYPE_PRIV_SW_XCPT);
-            /* no break */
+            /* fall thru */
         case VMX_EXIT_INTERRUPTION_INFO_TYPE_HW_XCPT:
         {
             /*
@@ -12157,7 +12171,7 @@ HMVMX_EXIT_DECL hmR0VmxExitWrmsr(PVMCPU pVCpu, PCPUMCTX pMixedCtx, PVMXTRANSIENT
                     HMCPU_CF_SET(pVCpu, HM_CHANGED_GUEST_SYSENTER_ESP_MSR);
                     HMVMXCPU_GST_SET_UPDATED(pVCpu, HMVMX_UPDATED_GUEST_SYSENTER_ESP_MSR);
                     break;
-                case MSR_K8_FS_BASE:        /* no break */
+                case MSR_K8_FS_BASE:        /* fall thru */
                 case MSR_K8_GS_BASE:        HMCPU_CF_SET(pVCpu, HM_CHANGED_GUEST_SEGMENT_REGS);     break;
                 case MSR_K6_EFER:           /* already handled above */                             break;
                 default:
diff --git a/src/VBox/VMM/VMMR0/VMMR0.cpp b/src/VBox/VMM/VMMR0/VMMR0.cpp
index 00089f7..043e2b5 100644
--- a/src/VBox/VMM/VMMR0/VMMR0.cpp
+++ b/src/VBox/VMM/VMMR0/VMMR0.cpp
@@ -30,6 +30,7 @@
 #include <VBox/vmm/tm.h>
 #include "VMMInternal.h"
 #include <VBox/vmm/vm.h>
+#include <VBox/vmm/gvm.h>
 #ifdef VBOX_WITH_PCI_PASSTHROUGH
 # include <VBox/vmm/pdmpci.h>
 #endif
@@ -926,22 +927,43 @@ static void vmmR0RecordRC(PVM pVM, PVMCPU pVCpu, int rc)
 /**
  * The Ring 0 entry point, called by the fast-ioctl path.
  *
+ * @param   pGVM            The global (ring-0) VM structure.
  * @param   pVM             The cross context VM structure.
  *                          The return code is stored in pVM->vmm.s.iLastGZRc.
  * @param   idCpu           The Virtual CPU ID of the calling EMT.
  * @param   enmOperation    Which operation to execute.
  * @remarks Assume called with interrupts _enabled_.
  */
-VMMR0DECL(void) VMMR0EntryFast(PVM pVM, VMCPUID idCpu, VMMR0OPERATION enmOperation)
+VMMR0DECL(void) VMMR0EntryFast(PGVM pGVM, PVM pVM, VMCPUID idCpu, VMMR0OPERATION enmOperation)
 {
     /*
      * Validation.
      */
-    if (RT_UNLIKELY(idCpu >= pVM->cCpus))
+    if (   idCpu < pGVM->cCpus
+        && pGVM->cCpus == pVM->cCpus)
+    { /*likely*/ }
+    else
+    {
+        SUPR0Printf("VMMR0EntryFast: Bad idCpu=%#x cCpus=%#x/%#x\n", idCpu, pGVM->cCpus, pVM->cCpus);
         return;
-    PVMCPU pVCpu = &pVM->aCpus[idCpu];
-    if (RT_UNLIKELY(pVCpu->hNativeThreadR0 != RTThreadNativeSelf()))
+    }
+
+    PGVMCPU pGVCpu = &pGVM->aCpus[idCpu];
+    PVMCPU  pVCpu  = &pVM->aCpus[idCpu];
+    RTNATIVETHREAD const hNativeThread = RTThreadNativeSelf();
+    if (RT_LIKELY(   pGVCpu->hEMT           == hNativeThread
+                  && pVCpu->hNativeThreadR0 == hNativeThread))
+    { /* likely */ }
+    else
+    {
+        SUPR0Printf("VMMR0EntryFast: Bad thread idCpu=%#x hNativeSelf=%p pGVCpu->hEmt=%p pVCpu->hNativeThreadR0=%p\n",
+                    idCpu, hNativeThread, pGVCpu->hEMT, pVCpu->hNativeThreadR0);
         return;
+    }
+
+    /*
+     * SMAP fun.
+     */
     VMM_CHECK_SMAP_SETUP();
     VMM_CHECK_SMAP_CHECK2(pVM, RT_NOTHING);
 
@@ -1310,6 +1332,7 @@ DECLINLINE(bool) vmmR0IsValidSession(PVM pVM, PSUPDRVSESSION pClaimedSession, PS
  * called thru a longjmp so we can exit safely on failure.
  *
  * @returns VBox status code.
+ * @param   pGVM            The global (ring-0) VM structure.
  * @param   pVM             The cross context VM structure.
  * @param   idCpu           Virtual CPU ID argument. Must be NIL_VMCPUID if pVM
  *                          is NIL_RTR0PTR, and may be NIL_VMCPUID if it isn't
@@ -1318,72 +1341,103 @@ DECLINLINE(bool) vmmR0IsValidSession(PVM pVM, PSUPDRVSESSION pClaimedSession, PS
  *                          The support driver validates this if it's present.
  * @param   u64Arg          Some simple constant argument.
  * @param   pSession        The session of the caller.
+ *
  * @remarks Assume called with interrupts _enabled_.
  */
-static int vmmR0EntryExWorker(PVM pVM, VMCPUID idCpu, VMMR0OPERATION enmOperation, PSUPVMMR0REQHDR pReqHdr, uint64_t u64Arg, PSUPDRVSESSION pSession)
+static int vmmR0EntryExWorker(PGVM pGVM, PVM pVM, VMCPUID idCpu, VMMR0OPERATION enmOperation,
+                              PSUPVMMR0REQHDR pReqHdr, uint64_t u64Arg, PSUPDRVSESSION pSession)
 {
     /*
-     * Common VM pointer validation.
+     * Validate pGVM, pVM and idCpu for consistency and validity.
      */
-    if (pVM)
+    if (   pGVM != NULL
+        || pVM  != NULL)
     {
-        if (RT_UNLIKELY(    !VALID_PTR(pVM)
-                        ||  ((uintptr_t)pVM & PAGE_OFFSET_MASK)))
+        if (RT_LIKELY(   RT_VALID_PTR(pGVM)
+                      && RT_VALID_PTR(pVM)
+                      && ((uintptr_t)pVM & PAGE_OFFSET_MASK) == 0))
+        { /* likely */ }
+        else
         {
-            SUPR0Printf("vmmR0EntryExWorker: Invalid pVM=%p! (op=%d)\n", pVM, enmOperation);
+            SUPR0Printf("vmmR0EntryExWorker: Invalid pGVM=%p and/or pVM=%p! (op=%d)\n", pGVM, pVM, enmOperation);
             return VERR_INVALID_POINTER;
         }
-        if (RT_UNLIKELY(    pVM->enmVMState < VMSTATE_CREATING
-                        ||  pVM->enmVMState > VMSTATE_TERMINATED
-                        ||  pVM->pVMR0 != pVM))
+
+        if (RT_LIKELY(pGVM->pVM == pVM))
+        { /* likely */ }
+        else
         {
-            SUPR0Printf("vmmR0EntryExWorker: Invalid pVM=%p:{enmVMState=%d, .pVMR0=%p}! (op=%d)\n",
-                        pVM, pVM->enmVMState, pVM->pVMR0, enmOperation);
-            return VERR_INVALID_POINTER;
+            SUPR0Printf("vmmR0EntryExWorker: pVM mismatch: got %p, pGVM->pVM=%p\n", pVM, pGVM->pVM);
+            return VERR_INVALID_PARAMETER;
         }
 
-        if (RT_UNLIKELY(idCpu >= pVM->cCpus && idCpu != NIL_VMCPUID))
+        if (RT_LIKELY(idCpu == NIL_VMCPUID || idCpu < pGVM->cCpus))
+        { /* likely */ }
+        else
         {
-            SUPR0Printf("vmmR0EntryExWorker: Invalid idCpu (%u vs cCpus=%u)\n", idCpu, pVM->cCpus);
+            SUPR0Printf("vmmR0EntryExWorker: Invalid idCpu %#x (cCpus=%#x)\n", idCpu, pGVM->cCpus);
             return VERR_INVALID_PARAMETER;
         }
+
+        if (RT_LIKELY(   pVM->enmVMState >= VMSTATE_CREATING
+                      && pVM->enmVMState <= VMSTATE_TERMINATED
+                      && pVM->cCpus      == pGVM->cCpus
+                      && pVM->pSession   == pSession
+                      && pVM->pVMR0      == pVM))
+        { /* likely */ }
+        else
+        {
+            SUPR0Printf("vmmR0EntryExWorker: Invalid pVM=%p:{.enmVMState=%d, .cCpus=%#x(==%#x), .pSession=%p(==%p), .pVMR0=%p(==%p)}! (op=%d)\n",
+                        pVM, pVM->enmVMState, pVM->cCpus, pGVM->cCpus, pVM->pSession, pSession, pVM->pVMR0, pVM, enmOperation);
+            return VERR_INVALID_POINTER;
+        }
     }
-    else if (RT_UNLIKELY(idCpu != NIL_VMCPUID))
+    else if (RT_LIKELY(idCpu == NIL_VMCPUID))
+    { /* likely */ }
+    else
     {
         SUPR0Printf("vmmR0EntryExWorker: Invalid idCpu=%u\n", idCpu);
         return VERR_INVALID_PARAMETER;
     }
+
+    /*
+     * SMAP fun.
+     */
     VMM_CHECK_SMAP_SETUP();
     VMM_CHECK_SMAP_CHECK(RT_NOTHING);
-    int rc;
 
+    /*
+     * Process the request.
+     */
+    int rc;
     switch (enmOperation)
     {
         /*
          * GVM requests
          */
         case VMMR0_DO_GVMM_CREATE_VM:
-            if (pVM || u64Arg || idCpu != NIL_VMCPUID)
-                return VERR_INVALID_PARAMETER;
-            rc = GVMMR0CreateVMReq((PGVMMCREATEVMREQ)pReqHdr);
+            if (pGVM == NULL && pVM == NULL && u64Arg == 0 && idCpu == NIL_VMCPUID)
+                rc = GVMMR0CreateVMReq((PGVMMCREATEVMREQ)pReqHdr, pSession);
+            else
+                rc = VERR_INVALID_PARAMETER;
             VMM_CHECK_SMAP_CHECK(RT_NOTHING);
             break;
 
         case VMMR0_DO_GVMM_DESTROY_VM:
-            if (pReqHdr || u64Arg)
-                return VERR_INVALID_PARAMETER;
-            rc = GVMMR0DestroyVM(pVM);
+            if (pReqHdr == NULL && u64Arg == 0)
+                rc = GVMMR0DestroyVM(pGVM, pVM);
+            else
+                rc = VERR_INVALID_PARAMETER;
             VMM_CHECK_SMAP_CHECK(RT_NOTHING);
             break;
 
         case VMMR0_DO_GVMM_REGISTER_VMCPU:
-        {
-            if (!pVM)
-                return VERR_INVALID_PARAMETER;
-            rc = GVMMR0RegisterVCpu(pVM, idCpu);
+            if (pGVM != NULL && pVM != NULL )
+                rc = GVMMR0RegisterVCpu(pGVM, pVM, idCpu);
+            else
+                rc = VERR_INVALID_PARAMETER;
             VMM_CHECK_SMAP_CHECK2(pVM, RT_NOTHING);
             break;
-        }
 
         case VMMR0_DO_GVMM_SCHED_HALT:
             if (pReqHdr)
@@ -1425,14 +1479,14 @@ static int vmmR0EntryExWorker(PVM pVM, VMCPUID idCpu, VMMR0OPERATION enmOperatio
         case VMMR0_DO_GVMM_QUERY_STATISTICS:
             if (u64Arg)
                 return VERR_INVALID_PARAMETER;
-            rc = GVMMR0QueryStatisticsReq(pVM, (PGVMMQUERYSTATISTICSSREQ)pReqHdr);
+            rc = GVMMR0QueryStatisticsReq(pVM, (PGVMMQUERYSTATISTICSSREQ)pReqHdr, pSession);
             VMM_CHECK_SMAP_CHECK2(pVM, RT_NOTHING);
             break;
 
         case VMMR0_DO_GVMM_RESET_STATISTICS:
             if (u64Arg)
                 return VERR_INVALID_PARAMETER;
-            rc = GVMMR0ResetStatisticsReq(pVM, (PGVMMRESETSTATISTICSSREQ)pReqHdr);
+            rc = GVMMR0ResetStatisticsReq(pVM, (PGVMMRESETSTATISTICSSREQ)pReqHdr, pSession);
             VMM_CHECK_SMAP_CHECK2(pVM, RT_NOTHING);
             break;
 
@@ -1919,6 +1973,7 @@ static int vmmR0EntryExWorker(PVM pVM, VMCPUID idCpu, VMMR0OPERATION enmOperatio
  */
 typedef struct VMMR0ENTRYEXARGS
 {
+    PGVM                pGVM;
     PVM                 pVM;
     VMCPUID             idCpu;
     VMMR0OPERATION      enmOperation;
@@ -1937,7 +1992,8 @@ typedef VMMR0ENTRYEXARGS *PVMMR0ENTRYEXARGS;
  */
 static DECLCALLBACK(int) vmmR0EntryExWrapper(void *pvArgs)
 {
-    return vmmR0EntryExWorker(((PVMMR0ENTRYEXARGS)pvArgs)->pVM,
+    return vmmR0EntryExWorker(((PVMMR0ENTRYEXARGS)pvArgs)->pGVM,
+                              ((PVMMR0ENTRYEXARGS)pvArgs)->pVM,
                               ((PVMMR0ENTRYEXARGS)pvArgs)->idCpu,
                               ((PVMMR0ENTRYEXARGS)pvArgs)->enmOperation,
                               ((PVMMR0ENTRYEXARGS)pvArgs)->pReq,
@@ -1950,6 +2006,7 @@ static DECLCALLBACK(int) vmmR0EntryExWrapper(void *pvArgs)
  * The Ring 0 entry point, called by the support library (SUP).
  *
  * @returns VBox status code.
+ * @param   pGVM            The global (ring-0) VM structure.
  * @param   pVM             The cross context VM structure.
  * @param   idCpu           Virtual CPU ID argument. Must be NIL_VMCPUID if pVM
  *                          is NIL_RTR0PTR, and may be NIL_VMCPUID if it isn't
@@ -1959,15 +2016,17 @@ static DECLCALLBACK(int) vmmR0EntryExWrapper(void *pvArgs)
  * @param   pSession        The session of the caller.
  * @remarks Assume called with interrupts _enabled_.
  */
-VMMR0DECL(int) VMMR0EntryEx(PVM pVM, VMCPUID idCpu, VMMR0OPERATION enmOperation, PSUPVMMR0REQHDR pReq, uint64_t u64Arg, PSUPDRVSESSION pSession)
+VMMR0DECL(int) VMMR0EntryEx(PGVM pGVM, PVM pVM, VMCPUID idCpu, VMMR0OPERATION enmOperation,
+                            PSUPVMMR0REQHDR pReq, uint64_t u64Arg, PSUPDRVSESSION pSession)
 {
     /*
      * Requests that should only happen on the EMT thread will be
      * wrapped in a setjmp so we can assert without causing trouble.
      */
-    if (    VALID_PTR(pVM)
-        &&  pVM->pVMR0
-        &&  idCpu < pVM->cCpus)
+    if (   pVM  != NULL
+        && pGVM != NULL
+        && idCpu < pGVM->cCpus
+        && pVM->pVMR0 != NULL)
     {
         switch (enmOperation)
         {
@@ -1981,27 +2040,34 @@ VMMR0DECL(int) VMMR0EntryEx(PVM pVM, VMCPUID idCpu, VMMR0OPERATION enmOperation,
             case VMMR0_DO_VMMR0_INIT:
             case VMMR0_DO_VMMR0_TERM:
             {
-                PVMCPU pVCpu = &pVM->aCpus[idCpu];
-
-                if (!pVCpu->vmm.s.CallRing3JmpBufR0.pvSavedStack)
-                    break;
-
-                /** @todo validate this EMT claim... GVM knows. */
-                VMMR0ENTRYEXARGS Args;
-                Args.pVM = pVM;
-                Args.idCpu = idCpu;
-                Args.enmOperation = enmOperation;
-                Args.pReq = pReq;
-                Args.u64Arg = u64Arg;
-                Args.pSession = pSession;
-                return vmmR0CallRing3SetJmpEx(&pVCpu->vmm.s.CallRing3JmpBufR0, vmmR0EntryExWrapper, &Args);
+                PGVMCPU pGVCpu = &pGVM->aCpus[idCpu];
+                PVMCPU  pVCpu  = &pVM->aCpus[idCpu];
+                RTNATIVETHREAD hNativeThread = RTThreadNativeSelf();
+                if (RT_LIKELY(   pGVCpu->hEMT           == hNativeThread
+                              && pVCpu->hNativeThreadR0 == hNativeThread))
+                {
+                    if (!pVCpu->vmm.s.CallRing3JmpBufR0.pvSavedStack)
+                        break;
+
+                    /** @todo validate this EMT claim... GVM knows. */
+                    VMMR0ENTRYEXARGS Args;
+                    Args.pGVM = pGVM;
+                    Args.pVM = pVM;
+                    Args.idCpu = idCpu;
+                    Args.enmOperation = enmOperation;
+                    Args.pReq = pReq;
+                    Args.u64Arg = u64Arg;
+                    Args.pSession = pSession;
+                    return vmmR0CallRing3SetJmpEx(&pVCpu->vmm.s.CallRing3JmpBufR0, vmmR0EntryExWrapper, &Args);
+                }
+                return VERR_VM_THREAD_NOT_EMT;
             }
 
             default:
                 break;
         }
     }
-    return vmmR0EntryExWorker(pVM, idCpu, enmOperation, pReq, u64Arg, pSession);
+    return vmmR0EntryExWorker(pGVM, pVM, idCpu, enmOperation, pReq, u64Arg, pSession);
 }
 
 
diff --git a/src/VBox/VMM/VMMR3/CPUMDbg.cpp b/src/VBox/VMM/VMMR3/CPUMDbg.cpp
index 8afc27e..1e5d292 100644
--- a/src/VBox/VMM/VMMR3/CPUMDbg.cpp
+++ b/src/VBox/VMM/VMMR3/CPUMDbg.cpp
@@ -50,6 +50,8 @@ static DECLCALLBACK(int) cpumR3RegGet_Generic(void *pvUser, PCDBGFREGDESC pDesc,
         case DBGFREGVALTYPE_U32:       pValue->u32  = *(uint32_t const *)pv; return VINF_SUCCESS;
         case DBGFREGVALTYPE_U64:       pValue->u64  = *(uint64_t const *)pv; return VINF_SUCCESS;
         case DBGFREGVALTYPE_U128:      pValue->u128 = *(PCRTUINT128U    )pv; return VINF_SUCCESS;
+        case DBGFREGVALTYPE_U256:      pValue->u256 = *(PCRTUINT256U    )pv; return VINF_SUCCESS;
+        case DBGFREGVALTYPE_U512:      pValue->u512 = *(PCRTUINT512U    )pv; return VINF_SUCCESS;
         default:
             AssertMsgFailedReturn(("%d %s\n", pDesc->enmType, pDesc->pszName), VERR_IPE_NOT_REACHED_DEFAULT_CASE);
     }
@@ -342,6 +344,50 @@ static DECLCALLBACK(int) cpumR3RegSet_Dummy(void *pvUser, PCDBGFREGDESC pDesc, P
 }
 
 
+/**
+ * @interface_method_impl{DBGFREGDESC,pfnGet}
+ */
+static DECLCALLBACK(int) cpumR3RegGet_ymm(void *pvUser, PCDBGFREGDESC pDesc, PDBGFREGVAL pValue)
+{
+    PVMCPU      pVCpu   = (PVMCPU)pvUser;
+    uint32_t    iReg    = pDesc->offRegister;
+
+    Assert(pDesc->enmType == DBGFREGVALTYPE_U256);
+    VMCPU_ASSERT_EMT(pVCpu);
+
+    if (iReg < 16)
+    {
+        pValue->u256.DQWords.dqw0 = pVCpu->cpum.s.Guest.pXStateR3->x87.aXMM[iReg].uXmm;
+        pValue->u256.DQWords.dqw1 = pVCpu->cpum.s.Guest.pXStateR3->u.YmmHi.aYmmHi[iReg].uXmm;
+        return VINF_SUCCESS;
+    }
+    return VERR_NOT_IMPLEMENTED;
+}
+
+
+/**
+ * @interface_method_impl{DBGFREGDESC,pfnSet}
+ */
+static DECLCALLBACK(int) cpumR3RegSet_ymm(void *pvUser, PCDBGFREGDESC pDesc, PCDBGFREGVAL pValue, PCDBGFREGVAL pfMask)
+{
+    PVMCPU      pVCpu = (PVMCPU)pvUser;
+    uint32_t    iReg  = pDesc->offRegister;
+
+    Assert(pDesc->enmType == DBGFREGVALTYPE_U256);
+    VMCPU_ASSERT_EMT(pVCpu);
+
+    if (iReg < 16)
+    {
+        RTUINT128U Val;
+        RTUInt128AssignAnd(&pVCpu->cpum.s.Guest.pXStateR3->x87.aXMM[iReg].uXmm,
+                           RTUInt128AssignBitwiseNot(RTUInt128Assign(&Val, &pfMask->u256.DQWords.dqw0)));
+        RTUInt128AssignOr(&pVCpu->cpum.s.Guest.pXStateR3->u.YmmHi.aYmmHi[iReg].uXmm,
+                          RTUInt128AssignAnd(RTUInt128Assign(&Val, &pValue->u128), &pfMask->u128));
+
+    }
+    return VERR_NOT_IMPLEMENTED;
+}
+
 
 /*
  *
@@ -948,6 +994,46 @@ static DBGFREGSUBFIELD const g_aCpumRegFields_xmmN[] =
     DBGFREGSUBFIELD_TERMINATOR()
 };
 
+#if 0 /* needs special accessor, too lazy for that now. */
+/** Sub-fields for the YMM registers. */
+static DBGFREGSUBFIELD const g_aCpumRegFields_ymmN[] =
+{
+    DBGFREGSUBFIELD_RW("r0",       0,     32,  0),
+    DBGFREGSUBFIELD_RW("r0.man",   0+ 0,  23,  0),
+    DBGFREGSUBFIELD_RW("r0.exp",   0+23,   8,  0),
+    DBGFREGSUBFIELD_RW("r0.sig",   0+31,   1,  0),
+    DBGFREGSUBFIELD_RW("r1",      32,     32,  0),
+    DBGFREGSUBFIELD_RW("r1.man",  32+ 0,  23,  0),
+    DBGFREGSUBFIELD_RW("r1.exp",  32+23,   8,  0),
+    DBGFREGSUBFIELD_RW("r1.sig",  32+31,   1,  0),
+    DBGFREGSUBFIELD_RW("r2",      64,     32,  0),
+    DBGFREGSUBFIELD_RW("r2.man",  64+ 0,  23,  0),
+    DBGFREGSUBFIELD_RW("r2.exp",  64+23,   8,  0),
+    DBGFREGSUBFIELD_RW("r2.sig",  64+31,   1,  0),
+    DBGFREGSUBFIELD_RW("r3",      96,     32,  0),
+    DBGFREGSUBFIELD_RW("r3.man",  96+ 0,  23,  0),
+    DBGFREGSUBFIELD_RW("r3.exp",  96+23,   8,  0),
+    DBGFREGSUBFIELD_RW("r3.sig",  96+31,   1,  0),
+    DBGFREGSUBFIELD_RW("r4",     128,     32,  0),
+    DBGFREGSUBFIELD_RW("r4.man", 128+ 0,  23,  0),
+    DBGFREGSUBFIELD_RW("r4.exp", 128+23,   8,  0),
+    DBGFREGSUBFIELD_RW("r4.sig", 128+31,   1,  0),
+    DBGFREGSUBFIELD_RW("r5",     160,     32,  0),
+    DBGFREGSUBFIELD_RW("r5.man", 160+ 0,  23,  0),
+    DBGFREGSUBFIELD_RW("r5.exp", 160+23,   8,  0),
+    DBGFREGSUBFIELD_RW("r5.sig", 160+31,   1,  0),
+    DBGFREGSUBFIELD_RW("r6",     192,     32,  0),
+    DBGFREGSUBFIELD_RW("r6.man", 192+ 0,  23,  0),
+    DBGFREGSUBFIELD_RW("r6.exp", 192+23,   8,  0),
+    DBGFREGSUBFIELD_RW("r6.sig", 192+31,   1,  0),
+    DBGFREGSUBFIELD_RW("r7",     224,     32,  0),
+    DBGFREGSUBFIELD_RW("r7.man", 224+ 0,  23,  0),
+    DBGFREGSUBFIELD_RW("r7.exp", 224+23,   8,  0),
+    DBGFREGSUBFIELD_RW("r7.sig", 224+31,   1,  0),
+    DBGFREGSUBFIELD_TERMINATOR()
+};
+#endif
+
 /** Sub-fields for the CR0 register. */
 static DBGFREGSUBFIELD const g_aCpumRegFields_cr0[] =
 {
@@ -1110,10 +1196,14 @@ static DBGFREGSUBFIELD const g_aCpumRegFields_sf_mask[] =
     CPU_REG_RW_AS(#LName "_lim",    UName##_LIMIT,  U32, LName.u32Limit,        cpumR3RegGet_Generic, cpumR3RegSet_Generic, NULL,                       NULL                )
 
 #define CPU_REG_MM(n) \
-    CPU_REG_XS_RW_AS("mm" #n,       MM##n,          U64, x87.aRegs[n].mmx, cpumR3RegGet_XStateGeneric, cpumR3RegSet_XStateGeneric, NULL,                       g_aCpumRegFields_mmN)
+    CPU_REG_XS_RW_AS("mm" #n,       MM##n,          U64, x87.aRegs[n].mmx, cpumR3RegGet_XStateGeneric, cpumR3RegSet_XStateGeneric, NULL,                g_aCpumRegFields_mmN)
 
 #define CPU_REG_XMM(n) \
-    CPU_REG_XS_RW_AS("xmm" #n,      XMM##n,         U128, x87.aXMM[n].xmm, cpumR3RegGet_XStateGeneric, cpumR3RegSet_XStateGeneric, NULL,                       g_aCpumRegFields_xmmN)
+    CPU_REG_XS_RW_AS("xmm" #n,      XMM##n,         U128, x87.aXMM[n].xmm, cpumR3RegGet_XStateGeneric, cpumR3RegSet_XStateGeneric, NULL,                g_aCpumRegFields_xmmN)
+
+#define CPU_REG_YMM(n) \
+    { "ymm" #n, DBGFREG_YMM##n, DBGFREGVALTYPE_U256, 0 /*fFlags*/, n,   cpumR3RegGet_ymm, cpumR3RegSet_ymm, NULL /*paAliases*/, NULL /*paSubFields*/ }
+
 /** @} */
 
 
@@ -1201,6 +1291,22 @@ static DBGFREGDESC const g_aCpumRegGstDescs[] =
     CPU_REG_XMM(13),
     CPU_REG_XMM(14),
     CPU_REG_XMM(15),
+    CPU_REG_YMM(0),
+    CPU_REG_YMM(1),
+    CPU_REG_YMM(2),
+    CPU_REG_YMM(3),
+    CPU_REG_YMM(4),
+    CPU_REG_YMM(5),
+    CPU_REG_YMM(6),
+    CPU_REG_YMM(7),
+    CPU_REG_YMM(8),
+    CPU_REG_YMM(9),
+    CPU_REG_YMM(10),
+    CPU_REG_YMM(11),
+    CPU_REG_YMM(12),
+    CPU_REG_YMM(13),
+    CPU_REG_YMM(14),
+    CPU_REG_YMM(15),
     CPU_REG_RW_AS("gdtr_base",      GDTR_BASE,      U64, gdtr.pGdt,             cpumR3RegGet_Generic,   cpumR3RegSet_Generic,   NULL,                       NULL                    ),
     CPU_REG_RW_AS("gdtr_lim",       GDTR_LIMIT,     U16, gdtr.cbGdt,            cpumR3RegGet_Generic,   cpumR3RegSet_Generic,   NULL,                       NULL                    ),
     CPU_REG_RW_AS("idtr_base",      IDTR_BASE,      U64, idtr.pIdt,             cpumR3RegGet_Generic,   cpumR3RegSet_Generic,   NULL,                       NULL                    ),
@@ -1329,6 +1435,22 @@ static DBGFREGDESC const g_aCpumRegHyperDescs[] =
     CPU_REG_DUMMY("xmm13",          XMM13,          U128),
     CPU_REG_DUMMY("xmm14",          XMM14,          U128),
     CPU_REG_DUMMY("xmm15",          XMM15,          U128),
+    CPU_REG_DUMMY("ymm0",           YMM0,           U256),
+    CPU_REG_DUMMY("ymm1",           YMM1,           U256),
+    CPU_REG_DUMMY("ymm2",           YMM2,           U256),
+    CPU_REG_DUMMY("ymm3",           YMM3,           U256),
+    CPU_REG_DUMMY("ymm4",           YMM4,           U256),
+    CPU_REG_DUMMY("ymm5",           YMM5,           U256),
+    CPU_REG_DUMMY("ymm6",           YMM6,           U256),
+    CPU_REG_DUMMY("ymm7",           YMM7,           U256),
+    CPU_REG_DUMMY("ymm8",           YMM8,           U256),
+    CPU_REG_DUMMY("ymm9",           YMM9,           U256),
+    CPU_REG_DUMMY("ymm10",          YMM10,          U256),
+    CPU_REG_DUMMY("ymm11",          YMM11,          U256),
+    CPU_REG_DUMMY("ymm12",          YMM12,          U256),
+    CPU_REG_DUMMY("ymm13",          YMM13,          U256),
+    CPU_REG_DUMMY("ymm14",          YMM14,          U256),
+    CPU_REG_DUMMY("ymm15",          YMM15,          U256),
     CPU_REG_RW_AS("gdtr_base",      GDTR_BASE,      U64, gdtr.pGdt,             cpumR3RegGet_Generic,   cpumR3RegSet_Generic,   NULL,                       NULL                    ),
     CPU_REG_RW_AS("gdtr_lim",       GDTR_LIMIT,     U16, gdtr.cbGdt,            cpumR3RegGet_Generic,   cpumR3RegSet_Generic,   NULL,                       NULL                    ),
     CPU_REG_RW_AS("idtr_base",      IDTR_BASE,      U64, idtr.pIdt,             cpumR3RegGet_Generic,   cpumR3RegSet_Generic,   NULL,                       NULL                    ),
diff --git a/src/VBox/VMM/VMMR3/CPUMR3CpuId.cpp b/src/VBox/VMM/VMMR3/CPUMR3CpuId.cpp
index 4f25351..093b064 100644
--- a/src/VBox/VMM/VMMR3/CPUMR3CpuId.cpp
+++ b/src/VBox/VMM/VMMR3/CPUMR3CpuId.cpp
@@ -27,6 +27,7 @@
 #include "CPUMInternal.h"
 #include <VBox/vmm/vm.h>
 #include <VBox/vmm/mm.h>
+#include <VBox/sup.h>
 
 #include <VBox/err.h>
 #include <iprt/asm-amd64-x86.h>
@@ -207,10 +208,10 @@ VMMR3DECL(CPUMMICROARCH) CPUMR3CpuIdDetermineMicroarchEx(CPUMCPUVENDOR enmVendor
                  *  - 130nm:
                  *     - ClawHammer:    F7A/SH-CG, F5A/-CG, F4A/-CG, F50/-B0, F48/-C0, F58/-C0,
                  *     - SledgeHammer:  F50/SH-B0, F48/-C0, F58/-C0, F4A/-CG, F5A/-CG, F7A/-CG, F51/-B3
-                 *     - Newcastle:     FC0/DH-CG (errum #180: FE0/DH-CG), FF0/DH-CG
+                 *     - Newcastle:     FC0/DH-CG (erratum #180: FE0/DH-CG), FF0/DH-CG
                  *     - Dublin:        FC0/-CG, FF0/-CG, F82/CH-CG, F4A/-CG, F48/SH-C0,
-                 *     - Odessa:        FC0/DH-CG (errum #180: FE0/DH-CG)
-                 *     - Paris:         FF0/DH-CG, FC0/DH-CG (errum #180: FE0/DH-CG),
+                 *     - Odessa:        FC0/DH-CG (erratum #180: FE0/DH-CG)
+                 *     - Paris:         FF0/DH-CG, FC0/DH-CG (erratum #180: FE0/DH-CG),
                  *  - 90nm:
                  *     - Winchester:    10FF0/DH-D0, 20FF0/DH-E3.
                  *     - Oakville:      10FC0/DH-D0.
@@ -2236,6 +2237,7 @@ typedef struct CPUMCPUIDCONFIG
 {
     bool            fNt4LeafLimit;
     bool            fInvariantTsc;
+    bool            fForceVme;
 
     CPUMISAEXTCFG   enmCmpXchg16b;
     CPUMISAEXTCFG   enmMonitor;
@@ -2659,6 +2661,30 @@ static int cpumR3CpuIdSanitize(PVM pVM, PCPUM pCpum, PCPUMCPUIDCONFIG pConfig)
     }
 #endif
 
+    uint32_t uMicrocodeRev;
+    int rc = SUPR3QueryMicrocodeRev(&uMicrocodeRev);
+    if (RT_SUCCESS(rc))
+    {
+        LogRel(("CPUM: Microcode revision 0x%08X\n", uMicrocodeRev));
+    }
+    else
+    {
+        uMicrocodeRev = 0;
+        LogRel(("CPUM: Failed to query microcode revision. rc=%Rrc\n", rc));
+    }
+
+    /* Mask out the VME capability on certain CPUs, unless overridden by fForceVme. 
+     * VME bug was fixed in AGESA 1.0.0.6, microcode patch level 8001126.
+     */
+    if ( (pVM->cpum.s.GuestFeatures.enmMicroarch == kCpumMicroarch_AMD_Zen_Ryzen)
+        && uMicrocodeRev < 0x8001126
+        && !pConfig->fForceVme)
+    {
+        /** @todo The above is a very coarse test but at the moment we don't know any better (see @bugref{8852}). */
+        LogRel(("CPUM: Zen VME workaround engaged\n"));
+        pStdFeatureLeaf->uEdx &= ~X86_CPUID_FEATURE_EDX_VME;
+    }
+
     /* Force standard feature bits. */
     if (pConfig->enmPClMul == CPUMISAEXTCFG_ENABLED_ALWAYS)
         pStdFeatureLeaf->uEcx |= X86_CPUID_FEATURE_ECX_PCLMUL;
@@ -3721,6 +3747,15 @@ static int cpumR3CpuIdReadConfig(PVM pVM, PCPUMCPUIDCONFIG pConfig, PCFGMNODE pC
     rc = CFGMR3QueryBoolDef(pCpumCfg, "InvariantTsc", &pConfig->fInvariantTsc, false);
     AssertLogRelRCReturn(rc, rc);
 
+    /** @cfgm{/CPUM/ForceVme, boolean, false}
+     * Always expose the VME (Virtual-8086 Mode Extensions) capability if true.
+     * By default the flag is passed thru as is from the host CPU, except
+     * on AMD Ryzen CPUs where it's masked to avoid trouble with XP/Server 2003
+     * guests and DOS boxes in general.
+     */
+    rc = CFGMR3QueryBoolDef(pCpumCfg, "ForceVme", &pConfig->fForceVme, false);
+    AssertLogRelRCReturn(rc, rc);
+
     /** @cfgm{/CPUM/MaxIntelFamilyModelStep, uint32_t, UINT32_MAX}
      * Restrict the reported CPU family+model+stepping of intel CPUs.  This is
      * probably going to be a temporary hack, so don't depend on this.
diff --git a/src/VBox/VMM/VMMR3/DBGFReg.cpp b/src/VBox/VMM/VMMR3/DBGFReg.cpp
index ffbefb3..0bec1a8 100644
--- a/src/VBox/VMM/VMMR3/DBGFReg.cpp
+++ b/src/VBox/VMM/VMMR3/DBGFReg.cpp
@@ -551,6 +551,12 @@ DECLINLINE(void) dbgfR3RegValClear(PDBGFREGVAL pValue)
 {
     pValue->au64[0] = 0;
     pValue->au64[1] = 0;
+    pValue->au64[2] = 0;
+    pValue->au64[3] = 0;
+    pValue->au64[4] = 0;
+    pValue->au64[5] = 0;
+    pValue->au64[6] = 0;
+    pValue->au64[7] = 0;
 }
 
 
@@ -647,6 +653,8 @@ static int dbgfR3RegValCast(PDBGFREGVAL pValue, DBGFREGVALTYPE enmFromType, DBGF
                 case DBGFREGVALTYPE_U32:    pValue->u32       = InVal.u8; return VINF_DBGF_ZERO_EXTENDED_REGISTER;
                 case DBGFREGVALTYPE_U64:    pValue->u64       = InVal.u8; return VINF_DBGF_ZERO_EXTENDED_REGISTER;
                 case DBGFREGVALTYPE_U128:   pValue->u128.s.Lo = InVal.u8; return VINF_DBGF_ZERO_EXTENDED_REGISTER;
+                case DBGFREGVALTYPE_U256:   pValue->u256.Words.w0 = InVal.u8; return VINF_DBGF_ZERO_EXTENDED_REGISTER;
+                case DBGFREGVALTYPE_U512:   pValue->u512.Words.w0 = InVal.u8; return VINF_DBGF_ZERO_EXTENDED_REGISTER;
                 case DBGFREGVALTYPE_R80:    dbgfR3RegValR80SetU64(pValue, InVal.u8); return VINF_DBGF_ZERO_EXTENDED_REGISTER;
                 case DBGFREGVALTYPE_DTR:                                  return VERR_DBGF_UNSUPPORTED_CAST;
 
@@ -665,6 +673,8 @@ static int dbgfR3RegValCast(PDBGFREGVAL pValue, DBGFREGVALTYPE enmFromType, DBGF
                 case DBGFREGVALTYPE_U32:    pValue->u32       = InVal.u16;  return VINF_DBGF_ZERO_EXTENDED_REGISTER;
                 case DBGFREGVALTYPE_U64:    pValue->u64       = InVal.u16;  return VINF_DBGF_ZERO_EXTENDED_REGISTER;
                 case DBGFREGVALTYPE_U128:   pValue->u128.s.Lo = InVal.u16;  return VINF_DBGF_ZERO_EXTENDED_REGISTER;
+                case DBGFREGVALTYPE_U256:   pValue->u256.Words.w0 = InVal.u16;  return VINF_DBGF_ZERO_EXTENDED_REGISTER;
+                case DBGFREGVALTYPE_U512:   pValue->u512.Words.w0 = InVal.u16;  return VINF_DBGF_ZERO_EXTENDED_REGISTER;
                 case DBGFREGVALTYPE_R80:    dbgfR3RegValR80SetU64(pValue, InVal.u16); return VINF_DBGF_ZERO_EXTENDED_REGISTER;
                 case DBGFREGVALTYPE_DTR:                                    return VERR_DBGF_UNSUPPORTED_CAST;
 
@@ -683,6 +693,8 @@ static int dbgfR3RegValCast(PDBGFREGVAL pValue, DBGFREGVALTYPE enmFromType, DBGF
                 case DBGFREGVALTYPE_U32:    pValue->u32       = InVal.u32;  return VINF_SUCCESS;
                 case DBGFREGVALTYPE_U64:    pValue->u64       = InVal.u32;  return VINF_DBGF_ZERO_EXTENDED_REGISTER;
                 case DBGFREGVALTYPE_U128:   pValue->u128.s.Lo = InVal.u32;  return VINF_DBGF_ZERO_EXTENDED_REGISTER;
+                case DBGFREGVALTYPE_U256:   pValue->u256.DWords.dw0 = InVal.u32;  return VINF_DBGF_ZERO_EXTENDED_REGISTER;
+                case DBGFREGVALTYPE_U512:   pValue->u512.DWords.dw0 = InVal.u32;  return VINF_DBGF_ZERO_EXTENDED_REGISTER;
                 case DBGFREGVALTYPE_R80:    dbgfR3RegValR80SetU64(pValue, InVal.u32); return VINF_DBGF_ZERO_EXTENDED_REGISTER;
                 case DBGFREGVALTYPE_DTR:                                    return VERR_DBGF_UNSUPPORTED_CAST;
 
@@ -701,6 +713,8 @@ static int dbgfR3RegValCast(PDBGFREGVAL pValue, DBGFREGVALTYPE enmFromType, DBGF
                 case DBGFREGVALTYPE_U32:    pValue->u32       = InVal.u64;  return VINF_DBGF_TRUNCATED_REGISTER;
                 case DBGFREGVALTYPE_U64:    pValue->u64       = InVal.u64;  return VINF_SUCCESS;
                 case DBGFREGVALTYPE_U128:   pValue->u128.s.Lo = InVal.u64;  return VINF_DBGF_TRUNCATED_REGISTER;
+                case DBGFREGVALTYPE_U256:   pValue->u256.QWords.qw0 = InVal.u64;  return VINF_DBGF_TRUNCATED_REGISTER;
+                case DBGFREGVALTYPE_U512:   pValue->u512.QWords.qw0 = InVal.u64;  return VINF_DBGF_TRUNCATED_REGISTER;
                 case DBGFREGVALTYPE_R80:    dbgfR3RegValR80SetU64(pValue, InVal.u64); return VINF_DBGF_TRUNCATED_REGISTER;
                 case DBGFREGVALTYPE_DTR:                                    return VERR_DBGF_UNSUPPORTED_CAST;
 
@@ -719,6 +733,8 @@ static int dbgfR3RegValCast(PDBGFREGVAL pValue, DBGFREGVALTYPE enmFromType, DBGF
                 case DBGFREGVALTYPE_U32:    pValue->u32       = InVal.u128.s.Lo;  return VINF_DBGF_TRUNCATED_REGISTER;
                 case DBGFREGVALTYPE_U64:    pValue->u64       = InVal.u128.s.Lo;  return VINF_DBGF_TRUNCATED_REGISTER;
                 case DBGFREGVALTYPE_U128:   pValue->u128      = InVal.u128;       return VINF_SUCCESS;
+                case DBGFREGVALTYPE_U256:   pValue->u256.DQWords.dqw0 = InVal.u128; return VINF_SUCCESS;
+                case DBGFREGVALTYPE_U512:   pValue->u512.DQWords.dqw0 = InVal.u128; return VINF_SUCCESS;
                 case DBGFREGVALTYPE_R80:    dbgfR3RegValR80SetU128(pValue, InVal.u128); return VINF_DBGF_TRUNCATED_REGISTER;
                 case DBGFREGVALTYPE_DTR:                                          return VERR_DBGF_UNSUPPORTED_CAST;
 
@@ -729,6 +745,46 @@ static int dbgfR3RegValCast(PDBGFREGVAL pValue, DBGFREGVALTYPE enmFromType, DBGF
             }
             break;
 
+        case DBGFREGVALTYPE_U256:
+            switch (enmToType)
+            {
+                case DBGFREGVALTYPE_U8:     pValue->u8        = InVal.u256.Words.w0;        return VINF_DBGF_TRUNCATED_REGISTER;
+                case DBGFREGVALTYPE_U16:    pValue->u16       = InVal.u256.Words.w0;        return VINF_DBGF_TRUNCATED_REGISTER;
+                case DBGFREGVALTYPE_U32:    pValue->u32       = InVal.u256.DWords.dw0;      return VINF_DBGF_TRUNCATED_REGISTER;
+                case DBGFREGVALTYPE_U64:    pValue->u64       = InVal.u256.QWords.qw0;      return VINF_DBGF_TRUNCATED_REGISTER;
+                case DBGFREGVALTYPE_U128:   pValue->u128      = InVal.u256.DQWords.dqw0;    return VINF_DBGF_TRUNCATED_REGISTER;
+                case DBGFREGVALTYPE_U256:   pValue->u256      = InVal.u256;                 return VINF_SUCCESS;
+                case DBGFREGVALTYPE_U512:   pValue->u512.OWords.ow0 = InVal.u256;           return VINF_SUCCESS;
+                case DBGFREGVALTYPE_R80:    dbgfR3RegValR80SetU128(pValue, InVal.u256.DQWords.dqw0); return VINF_DBGF_TRUNCATED_REGISTER;
+                case DBGFREGVALTYPE_DTR:                                                    return VERR_DBGF_UNSUPPORTED_CAST;
+
+                case DBGFREGVALTYPE_32BIT_HACK:
+                case DBGFREGVALTYPE_END:
+                case DBGFREGVALTYPE_INVALID:
+                    break;
+            }
+            break;
+
+        case DBGFREGVALTYPE_U512:
+            switch (enmToType)
+            {
+                case DBGFREGVALTYPE_U8:     pValue->u8        = InVal.u512.Words.w0;        return VINF_DBGF_TRUNCATED_REGISTER;
+                case DBGFREGVALTYPE_U16:    pValue->u16       = InVal.u512.Words.w0;        return VINF_DBGF_TRUNCATED_REGISTER;
+                case DBGFREGVALTYPE_U32:    pValue->u32       = InVal.u512.DWords.dw0;      return VINF_DBGF_TRUNCATED_REGISTER;
+                case DBGFREGVALTYPE_U64:    pValue->u64       = InVal.u512.QWords.qw0;      return VINF_DBGF_TRUNCATED_REGISTER;
+                case DBGFREGVALTYPE_U128:   pValue->u128      = InVal.u512.DQWords.dqw0;    return VINF_DBGF_TRUNCATED_REGISTER;
+                case DBGFREGVALTYPE_U256:   pValue->u256      = InVal.u512.OWords.ow0;      return VINF_DBGF_TRUNCATED_REGISTER;
+                case DBGFREGVALTYPE_U512:   pValue->u512      = InVal.u512;                 return VINF_SUCCESS;
+                case DBGFREGVALTYPE_R80:    dbgfR3RegValR80SetU128(pValue, InVal.u512.DQWords.dqw0); return VINF_DBGF_TRUNCATED_REGISTER;
+                case DBGFREGVALTYPE_DTR:                                                    return VERR_DBGF_UNSUPPORTED_CAST;
+
+                case DBGFREGVALTYPE_32BIT_HACK:
+                case DBGFREGVALTYPE_END:
+                case DBGFREGVALTYPE_INVALID:
+                    break;
+            }
+            break;
+
         case DBGFREGVALTYPE_R80:
             switch (enmToType)
             {
@@ -737,6 +793,8 @@ static int dbgfR3RegValCast(PDBGFREGVAL pValue, DBGFREGVALTYPE enmFromType, DBGF
                 case DBGFREGVALTYPE_U32:    pValue->u32       = (uint32_t)dbgfR3RegValR80GetU64(&InVal);  return VINF_DBGF_TRUNCATED_REGISTER;
                 case DBGFREGVALTYPE_U64:    pValue->u64       = (uint64_t)dbgfR3RegValR80GetU64(&InVal);  return VINF_DBGF_TRUNCATED_REGISTER;
                 case DBGFREGVALTYPE_U128:   pValue->u128      = dbgfR3RegValR80GetU128(&InVal);           return VINF_DBGF_TRUNCATED_REGISTER;
+                case DBGFREGVALTYPE_U256:   pValue->u256.DQWords.dqw0 = dbgfR3RegValR80GetU128(&InVal);   return VINF_DBGF_TRUNCATED_REGISTER;
+                case DBGFREGVALTYPE_U512:   pValue->u512.DQWords.dqw0 = dbgfR3RegValR80GetU128(&InVal);   return VINF_DBGF_TRUNCATED_REGISTER;
                 case DBGFREGVALTYPE_R80:    pValue->r80       = InVal.r80;          return VINF_SUCCESS;
                 case DBGFREGVALTYPE_DTR:                                            return VERR_DBGF_UNSUPPORTED_CAST;
 
@@ -755,6 +813,8 @@ static int dbgfR3RegValCast(PDBGFREGVAL pValue, DBGFREGVALTYPE enmFromType, DBGF
                 case DBGFREGVALTYPE_U32:    pValue->u32       = InVal.dtr.u64Base;  return VINF_DBGF_TRUNCATED_REGISTER;
                 case DBGFREGVALTYPE_U64:    pValue->u64       = InVal.dtr.u64Base;  return VINF_DBGF_TRUNCATED_REGISTER;
                 case DBGFREGVALTYPE_U128:   pValue->u128.s.Lo = InVal.dtr.u64Base;  return VINF_DBGF_TRUNCATED_REGISTER;
+                case DBGFREGVALTYPE_U256:   pValue->u256.QWords.qw0 = InVal.dtr.u64Base;  return VINF_DBGF_TRUNCATED_REGISTER;
+                case DBGFREGVALTYPE_U512:   pValue->u512.QWords.qw0 = InVal.dtr.u64Base;  return VINF_DBGF_TRUNCATED_REGISTER;
                 case DBGFREGVALTYPE_R80:    dbgfR3RegValR80SetU64(pValue, InVal.dtr.u64Base);  return VINF_DBGF_TRUNCATED_REGISTER;
                 case DBGFREGVALTYPE_DTR:    pValue->dtr       = InVal.dtr;          return VINF_SUCCESS;
 
@@ -2004,6 +2064,24 @@ VMMR3DECL(int) DBGFR3RegNmSet(PUVM pUVM, VMCPUID idDefCpu, const char *pszReg, P
                     Mask.u128.s.Lo = UINT64_MAX;
                     Mask.u128.s.Hi = UINT64_MAX;
                     break;
+                case DBGFREGVALTYPE_U256:
+                    Value.u256 = pValue->u256;
+                    Mask.u256.QWords.qw0 = UINT64_MAX;
+                    Mask.u256.QWords.qw1 = UINT64_MAX;
+                    Mask.u256.QWords.qw2 = UINT64_MAX;
+                    Mask.u256.QWords.qw3 = UINT64_MAX;
+                    break;
+                case DBGFREGVALTYPE_U512:
+                    Value.u512 = pValue->u512;
+                    Mask.u512.QWords.qw0 = UINT64_MAX;
+                    Mask.u512.QWords.qw1 = UINT64_MAX;
+                    Mask.u512.QWords.qw2 = UINT64_MAX;
+                    Mask.u512.QWords.qw3 = UINT64_MAX;
+                    Mask.u512.QWords.qw4 = UINT64_MAX;
+                    Mask.u512.QWords.qw5 = UINT64_MAX;
+                    Mask.u512.QWords.qw6 = UINT64_MAX;
+                    Mask.u512.QWords.qw7 = UINT64_MAX;
+                    break;
                 case DBGFREGVALTYPE_R80:
 #ifdef RT_COMPILER_WITH_80BIT_LONG_DOUBLE
                     Value.r80Ex.lrd = pValue->r80Ex.lrd;
@@ -2039,8 +2117,12 @@ VMMR3DECL(int) DBGFR3RegNmSet(PUVM pUVM, VMCPUID idDefCpu, const char *pszReg, P
                     enmRegType = DBGFREGVALTYPE_U32;
                 else if (cBits <= 64)
                     enmRegType = DBGFREGVALTYPE_U64;
-                else
+                else if (cBits <= 128)
                     enmRegType = DBGFREGVALTYPE_U128;
+                else if (cBits <= 256)
+                    enmRegType = DBGFREGVALTYPE_U256;
+                else
+                    enmRegType = DBGFREGVALTYPE_U512;
             }
             else if (pLookupRec->pAlias)
             {
@@ -2141,6 +2223,10 @@ DECLINLINE(ssize_t) dbgfR3RegFormatValueInt(char *pszBuf, size_t cbBuf, PCDBGFRE
             return RTStrFormatU64(pszBuf, cbBuf, pValue->u64, uBase, cchWidth, cchPrecision, fFlags);
         case DBGFREGVALTYPE_U128:
             return RTStrFormatU128(pszBuf, cbBuf, &pValue->u128, uBase, cchWidth, cchPrecision, fFlags);
+        case DBGFREGVALTYPE_U256:
+            return RTStrFormatU256(pszBuf, cbBuf, &pValue->u256, uBase, cchWidth, cchPrecision, fFlags);
+        case DBGFREGVALTYPE_U512:
+            return RTStrFormatU512(pszBuf, cbBuf, &pValue->u512, uBase, cchWidth, cchPrecision, fFlags);
         case DBGFREGVALTYPE_R80:
             return RTStrFormatR80u2(pszBuf, cbBuf, &pValue->r80Ex, cchWidth, cchPrecision, fFlags);
         case DBGFREGVALTYPE_DTR:
@@ -2223,11 +2309,13 @@ VMMR3DECL(ssize_t) DBGFR3RegFormatValue(char *pszBuf, size_t cbBuf, PCDBGFREGVAL
     int cchWidth = 0;
     switch (enmType)
     {
-        case DBGFREGVALTYPE_U8:     cchWidth = 2  + fSpecial*2; break;
-        case DBGFREGVALTYPE_U16:    cchWidth = 4  + fSpecial*2; break;
-        case DBGFREGVALTYPE_U32:    cchWidth = 8  + fSpecial*2; break;
-        case DBGFREGVALTYPE_U64:    cchWidth = 16 + fSpecial*2; break;
-        case DBGFREGVALTYPE_U128:   cchWidth = 32 + fSpecial*2; break;
+        case DBGFREGVALTYPE_U8:     cchWidth = 2   + fSpecial*2; break;
+        case DBGFREGVALTYPE_U16:    cchWidth = 4   + fSpecial*2; break;
+        case DBGFREGVALTYPE_U32:    cchWidth = 8   + fSpecial*2; break;
+        case DBGFREGVALTYPE_U64:    cchWidth = 16  + fSpecial*2; break;
+        case DBGFREGVALTYPE_U128:   cchWidth = 32  + fSpecial*2; break;
+        case DBGFREGVALTYPE_U256:   cchWidth = 64  + fSpecial*2; break;
+        case DBGFREGVALTYPE_U512:   cchWidth = 128 + fSpecial*2; break;
         case DBGFREGVALTYPE_R80:    cchWidth = 0; break;
         case DBGFREGVALTYPE_DTR:    cchWidth = 16+1+4 + fSpecial*2; break;
 
diff --git a/src/VBox/VMM/VMMR3/PDM.cpp b/src/VBox/VMM/VMMR3/PDM.cpp
index 95a95b5..1c444b6 100644
--- a/src/VBox/VMM/VMMR3/PDM.cpp
+++ b/src/VBox/VMM/VMMR3/PDM.cpp
@@ -1657,6 +1657,19 @@ VMMR3_INT_DECL(void) PDMR3MemSetup(PVM pVM, bool fAtReset)
             PDMCritSectLeave(pDevIns->pCritSectRoR3);
         }
 
+    /*
+     * Run Fake PCI BIOS after reset.
+     */
+    if (fAtReset && pVM->pdm.s.aPciBuses[0].pDevInsR3)
+    {
+        pdmLock(pVM);
+        int rc = pVM->pdm.s.aPciBuses[0].pfnFakePCIBIOSR3(pVM->pdm.s.aPciBuses[0].pDevInsR3);
+        pdmUnlock(pVM);
+        if (RT_FAILURE(rc))
+            AssertMsgFailed(("PCI BIOS fake failed rc=%Rrc\n", rc));
+    }
+
+
     LogFlow(("PDMR3MemSetup: returns void\n"));
 }
 
diff --git a/src/VBox/VMM/VMMR3/VMM.cpp b/src/VBox/VMM/VMMR3/VMM.cpp
index b86500c..2b1d34a 100644
--- a/src/VBox/VMM/VMMR3/VMM.cpp
+++ b/src/VBox/VMM/VMMR3/VMM.cpp
@@ -627,8 +627,8 @@ VMMR3_INT_DECL(int) VMMR3InitRC(PVM pVM)
     {
         CPUMSetHyperESP(pVCpu, pVCpu->vmm.s.pbEMTStackBottomRC); /* Clear the stack. */
         uint64_t u64TS = RTTimeProgramStartNanoTS();
-        CPUMPushHyper(pVCpu, (uint32_t)(u64TS >> 32));    /* Param 4: The program startup TS - Hi. */
-        CPUMPushHyper(pVCpu, (uint32_t)u64TS);            /* Param 4: The program startup TS - Lo. */
+        CPUMPushHyper(pVCpu, RT_HI_U32(u64TS));           /* Param 4: The program startup TS - Hi. */
+        CPUMPushHyper(pVCpu, RT_LO_U32(u64TS));           /* Param 4: The program startup TS - Lo. */
         CPUMPushHyper(pVCpu, vmmGetBuildType());          /* Param 3: Version argument. */
         CPUMPushHyper(pVCpu, VMMGetSvnRev());             /* Param 2: Version argument. */
         CPUMPushHyper(pVCpu, VMMRC_DO_VMMRC_INIT);        /* Param 1: Operation. */
diff --git a/src/VBox/VMM/VMMR3/VMMTests.cpp b/src/VBox/VMM/VMMR3/VMMTests.cpp
index a018861..043ab07 100644
--- a/src/VBox/VMM/VMMR3/VMMTests.cpp
+++ b/src/VBox/VMM/VMMR3/VMMTests.cpp
@@ -112,7 +112,7 @@ static int vmmR3ReportMsrRange(PVM pVM, uint32_t uMsr, uint64_t cMsrs, PRTSTREAM
                         RTStrmPrintf(pReportStrm,
                                      "    MVO(%#010llx, \"MSR\", UINT64_C(%#018llx)),\n", paResults[i].uMsr, paResults[i].uValue);
                     RTPrintf("%#010llx = %#010x`%08x\n", paResults[i].uMsr,
-                             (uint32_t)(paResults[i].uValue >> 32), (uint32_t)paResults[i].uValue);
+                             RT_HI_U32(paResults[i].uValue), RT_LO_U32(paResults[i].uValue));
                 }
                 cMsrsFound++;
                 uLastMsr = paResults[i].uMsr;
diff --git a/src/VBox/VMM/VMMRC/PATMRC.cpp b/src/VBox/VMM/VMMRC/PATMRC.cpp
index be58f4a..647978a 100644
--- a/src/VBox/VMM/VMMRC/PATMRC.cpp
+++ b/src/VBox/VMM/VMMRC/PATMRC.cpp
@@ -210,6 +210,7 @@ VMMRC_INT_DECL(int) PATMRCHandleIllegalInstrTrap(PVM pVM, PCPUMCTXCORE pCtxCore)
                             return VINF_SUCCESS;
                         }
                         AssertFailed();
+                        return rc;
                     }
                     else
                     {
diff --git a/src/VBox/VMM/VMMRC/TRPMRCHandlers.cpp b/src/VBox/VMM/VMMRC/TRPMRCHandlers.cpp
index 345df77..0f31b8a 100644
--- a/src/VBox/VMM/VMMRC/TRPMRCHandlers.cpp
+++ b/src/VBox/VMM/VMMRC/TRPMRCHandlers.cpp
@@ -1055,8 +1055,8 @@ DECLINLINE(int) trpmGCTrap0dHandlerRdTsc(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRe
     }
 
     uint64_t uTicks = TMCpuTickGet(pVCpu);
-    pRegFrame->eax = uTicks;
-    pRegFrame->edx = uTicks >> 32;
+    pRegFrame->eax = RT_LO_U32(uTicks);
+    pRegFrame->edx = RT_HI_U32(uTicks);
     pRegFrame->eip += 2;
     TRPM_EXIT_DBG_HOOK(0xd);
     return trpmGCExitTrap(pVM, pVCpu, VINF_SUCCESS, pRegFrame);
diff --git a/src/VBox/VMM/VMMRZ/CPUMRZ.cpp b/src/VBox/VMM/VMMRZ/CPUMRZ.cpp
index 885b3af..6bf1067 100644
--- a/src/VBox/VMM/VMMRZ/CPUMRZ.cpp
+++ b/src/VBox/VMM/VMMRZ/CPUMRZ.cpp
@@ -133,7 +133,7 @@ VMMRZ_INT_DECL(void)    CPUMRZFpuStateActualizeForRead(PVMCPU pVCpu)
 
 
 /**
- * Makes sure the XMM0..XMM15 state in CPUMCPU::Guest is up to date.
+ * Makes sure the XMM0..XMM15 and MXCSR state in CPUMCPU::Guest is up to date.
  *
  * This will not cause CPUM_USED_FPU_GUEST to change.
  *
@@ -161,3 +161,29 @@ VMMRZ_INT_DECL(void)    CPUMRZFpuStateActualizeSseForRead(PVMCPU pVCpu)
 #endif
 }
 
+
+/**
+ * Makes sure the YMM0..YMM15 and MXCSR state in CPUMCPU::Guest is up to date.
+ *
+ * This will not cause CPUM_USED_FPU_GUEST to change.
+ *
+ * @param   pVCpu       The cross context virtual CPU structure.
+ */
+VMMRZ_INT_DECL(void)    CPUMRZFpuStateActualizeAvxForRead(PVMCPU pVCpu)
+{
+    if (pVCpu->cpum.s.fUseFlags & CPUM_USED_FPU_GUEST)
+    {
+#if defined(IN_RING0) && ARCH_BITS == 32 && defined(VBOX_WITH_64_BITS_GUESTS)
+        if (CPUMIsGuestInLongModeEx(&pVCpu->cpum.s.Guest))
+        {
+            Assert(!(pVCpu->cpum.s.fUseFlags & CPUM_SYNC_FPU_STATE));
+            HMR0SaveFPUState(pVCpu->CTX_SUFF(pVM), pVCpu, &pVCpu->cpum.s.Guest);
+            pVCpu->cpum.s.fUseFlags |= CPUM_USED_FPU_GUEST;
+        }
+        else
+#endif
+            cpumRZSaveGuestAvxRegisters(&pVCpu->cpum.s);
+        Log7(("CPUMRZFpuStateActualizeAvxForRead\n"));
+    }
+}
+
diff --git a/src/VBox/VMM/VMMRZ/CPUMRZA.asm b/src/VBox/VMM/VMMRZ/CPUMRZA.asm
index 949ff2e..e5ea312 100644
--- a/src/VBox/VMM/VMMRZ/CPUMRZA.asm
+++ b/src/VBox/VMM/VMMRZ/CPUMRZA.asm
@@ -105,6 +105,12 @@ ENDPROC   cpumRZSaveHostFPUState
 ; @param    fLeaveFpuAccessible  x86:[ebp+c] gcc:sil msc:dl      Whether to restore CR0 and XCR0 on
 ;                                                                the way out. Only really applicable to RC.
 ;
+; @remarks  64-bit Windows drivers shouldn't use AVX registers without saving+loading:
+;               https://msdn.microsoft.com/en-us/library/windows/hardware/ff545910%28v=vs.85%29.aspx?f=255&MSPPError=-2147217396
+;           However the compiler docs have different idea:
+;               https://msdn.microsoft.com/en-us/library/9z1stfyw.aspx
+;           We'll go with the former for now.
+;
 align 16
 BEGINPROC cpumRZSaveGuestFpuState
         push    xBP
@@ -165,6 +171,7 @@ SEH64_END_PROLOGUE
         movdqa  [pXState + X86FXSTATE.xmm13], xmm13
         movdqa  [pXState + X86FXSTATE.xmm14], xmm14
         movdqa  [pXState + X86FXSTATE.xmm15], xmm15
+        stmxcsr [pXState + X86FXSTATE.MXCSR]
 
         ; Load the guest XMM register values we already saved in HMR0VMXStartVMWrapXMM.
         mov     pXState, [pCpumCpu + CPUMCPU.Guest.pXStateR0]
@@ -184,6 +191,7 @@ SEH64_END_PROLOGUE
         movdqa  xmm13, [pXState + X86FXSTATE.xmm13]
         movdqa  xmm14, [pXState + X86FXSTATE.xmm14]
         movdqa  xmm15, [pXState + X86FXSTATE.xmm15]
+        ldmxcsr        [pXState + X86FXSTATE.MXCSR]
 
         CPUMR0_SAVE_GUEST
 
@@ -199,6 +207,7 @@ SEH64_END_PROLOGUE
         movdqa  xmm13, [pXState + X86FXSTATE.xmm13]
         movdqa  xmm14, [pXState + X86FXSTATE.xmm14]
         movdqa  xmm15, [pXState + X86FXSTATE.xmm15]
+        ldmxcsr        [pXState + X86FXSTATE.MXCSR]
 
  %endif
 
@@ -222,7 +231,7 @@ ENDPROC   cpumRZSaveGuestFpuState
 
 
 ;;
-; Saves the guest XMM0..15 registers.
+; Saves the guest XMM0..15 registers and MXCSR.
 ;
 ; The purpose is to actualize the register state for read-only use, so CR0 is
 ; restored in raw-mode context (so, the FPU/SSE/AVX CPU features can be
@@ -269,6 +278,7 @@ SEH64_END_PROLOGUE
         ;
         ; Do the job.
         ;
+        stmxcsr [xCX + X86FXSTATE.MXCSR]
         movdqa  [xCX + X86FXSTATE.xmm0 ], xmm0
         movdqa  [xCX + X86FXSTATE.xmm1 ], xmm1
         movdqa  [xCX + X86FXSTATE.xmm2 ], xmm2
@@ -298,3 +308,79 @@ SEH64_END_PROLOGUE
         ret
 ENDPROC   cpumRZSaveGuestSseRegisters
 
+;;
+; Saves the guest YMM0..15 registers.
+;
+; The purpose is to actualize the register state for read-only use, so CR0 is
+; restored in raw-mode context (so, the FPU/SSE/AVX CPU features can be
+; inaccessible upon return).
+;
+; @param    pCpumCpu  x86:[ebp+8] gcc:rdi msc:rcx     CPUMCPU pointer
+;
+align 16
+BEGINPROC cpumRZSaveGuestAvxRegisters
+        push    xBP
+        SEH64_PUSH_xBP
+        mov     xBP, xSP
+        SEH64_SET_FRAME_xBP 0
+%ifdef IN_RC
+        push    xBX
+%endif
+SEH64_END_PROLOGUE
+
+        ;
+        ; Load xCX with the guest pXStateR0.
+        ;
+%ifdef ASM_CALL64_GCC
+        mov     xCX, rdi
+%elifdef RT_ARCH_X86
+        mov     xCX, dword [ebp + 8]
+%endif
+%ifdef IN_RING0
+        mov     xCX, [xCX + CPUMCPU.Guest.pXStateR0]
+%elifdef IN_RC
+        mov     xCX, [xCX + CPUMCPU.Guest.pXStateRC]
+%else
+ %error "Invalid context!"
+%endif
+
+%ifdef IN_RC
+        ; Temporarily grant access to the SSE state. xBX must be preserved until CR0 is restored!
+        mov     ebx, cr0
+        test    ebx, X86_CR0_TS | X86_CR0_EM
+        jz      .skip_cr0_write
+        mov     eax, ebx
+        and     eax, ~(X86_CR0_TS | X86_CR0_EM)
+        mov     cr0, eax
+.skip_cr0_write:
+%endif
+
+        ;
+        ; Use XSAVE to do the job.
+        ;
+        ; Drivers shouldn't use AVX registers without saving+loading:
+        ;     https://msdn.microsoft.com/en-us/library/windows/hardware/ff545910%28v=vs.85%29.aspx?f=255&MSPPError=-2147217396
+        ; However the compiler docs have different idea:
+        ;     https://msdn.microsoft.com/en-us/library/9z1stfyw.aspx
+        ; We'll go with the former for now.
+        ;
+%ifdef VBOX_WITH_KERNEL_USING_XMM
+        mov     eax, XSAVE_C_YMM
+%else
+        mov     eax, XSAVE_C_YMM | XSAVE_C_SSE ; The SSE component includes MXCSR.
+%endif
+        xor     edx, edx
+%if ARCH_BITS == 64
+        o64 xsave [xCX]
+%else
+        xsave   [xCX]
+%endif
+
+%ifdef IN_RC
+        CPUMRZ_RESTORE_CR0_IF_TS_OR_EM_SET ebx  ; Restore CR0 if we changed it above.
+        pop     xBX
+%endif
+        leave
+        ret
+ENDPROC   cpumRZSaveGuestAvxRegisters
+
diff --git a/src/VBox/VMM/include/CPUMInternal.h b/src/VBox/VMM/include/CPUMInternal.h
index e3b22e2..f608b41 100644
--- a/src/VBox/VMM/include/CPUMInternal.h
+++ b/src/VBox/VMM/include/CPUMInternal.h
@@ -558,6 +558,7 @@ DECLASM(void)       cpumR0RestoreHostFPUState(PCPUMCPU pCPUM);
 DECLASM(int)        cpumRZSaveHostFPUState(PCPUMCPU pCPUM);
 DECLASM(void)       cpumRZSaveGuestFpuState(PCPUMCPU pCPUM, bool fLeaveFpuAccessible);
 DECLASM(void)       cpumRZSaveGuestSseRegisters(PCPUMCPU pCPUM);
+DECLASM(void)       cpumRZSaveGuestAvxRegisters(PCPUMCPU pCPUM);
 # endif
 
 RT_C_DECLS_END
diff --git a/src/VBox/VMM/include/IEMInternal.h b/src/VBox/VMM/include/IEMInternal.h
index af0115c..9def50a 100644
--- a/src/VBox/VMM/include/IEMInternal.h
+++ b/src/VBox/VMM/include/IEMInternal.h
@@ -139,6 +139,23 @@ AssertCompileSize(IEMBRANCH, 4);
 
 
 /**
+ * INT instruction types.
+ */
+typedef enum IEMINT
+{
+    /** INT n instruction (opcode 0xcd imm). */
+    IEMINT_INTN  = 0,
+    /** Single byte INT3 instruction (opcode 0xcc). */
+    IEMINT_INT3  = IEM_XCPT_FLAGS_BP_INSTR,
+    /** Single byte INTO instruction (opcode 0xce). */
+    IEMINT_INTO  = IEM_XCPT_FLAGS_OF_INSTR,
+    /** Single byte INT1 (ICEBP) instruction (opcode 0xf1). */
+    IEMINT_INT1 = IEM_XCPT_FLAGS_ICEBP_INSTR
+} IEMINT;
+AssertCompileSize(IEMINT, 4);
+
+
+/**
  * A FPU result.
  */
 typedef struct IEMFPURESULT
@@ -532,7 +549,8 @@ typedef struct IEMCPU
 
     /** Prefix index (VEX.pp) for two byte and three byte tables. */
     uint8_t                 idxPrefix;                                                                      /* 0x30, 0x16 */
-    /** 3rd VEX/EVEX/XOP register. */
+    /** 3rd VEX/EVEX/XOP register.
+     * Please use IEM_GET_EFFECTIVE_VVVV to access.  */
     uint8_t                 uVex3rdReg;                                                                     /* 0x31, 0x17 */
     /** The VEX/EVEX/XOP length field. */
     uint8_t                 uVexLength;                                                                     /* 0x32, 0x18 */
@@ -892,27 +910,36 @@ typedef IEMCPU const *PCIEMCPU;
 /** VEX+ModR/M: reg, r/m */
 #define IEMOPFORM_VEX_RM        4
 /** VEX+ModR/M: reg, r/m (register) */
-#define IEMOPFORM_VEX_RM_REG        (IEMOPFORM_VEX_RM | IEMOPFORM_MOD3)
+#define IEMOPFORM_VEX_RM_REG    (IEMOPFORM_VEX_RM | IEMOPFORM_MOD3)
 /** VEX+ModR/M: reg, r/m (memory)   */
-#define IEMOPFORM_VEX_RM_MEM        (IEMOPFORM_VEX_RM | IEMOPFORM_NOT_MOD3)
+#define IEMOPFORM_VEX_RM_MEM    (IEMOPFORM_VEX_RM | IEMOPFORM_NOT_MOD3)
+#define IEMOPFORM_VEX_XM        IEMOPFORM_VEX_RM_MEM
 /** VEX+ModR/M: r/m, reg */
 #define IEMOPFORM_VEX_MR        5
 /** VEX+ModR/M: r/m (register), reg */
-#define IEMOPFORM_VEX_MR_REG        (IEMOPFORM_VEX_MR | IEMOPFORM_MOD3)
+#define IEMOPFORM_VEX_MR_REG    (IEMOPFORM_VEX_MR | IEMOPFORM_MOD3)
 /** VEX+ModR/M: r/m (memory), reg */
-#define IEMOPFORM_VEX_MR_MEM        (IEMOPFORM_VEX_MR | IEMOPFORM_NOT_MOD3)
+#define IEMOPFORM_VEX_MR_MEM    (IEMOPFORM_VEX_MR | IEMOPFORM_NOT_MOD3)
 /** VEX+ModR/M: r/m only */
 #define IEMOPFORM_VEX_M         6
 /** VEX+ModR/M: r/m only (register). */
-#define IEMOPFORM_VEX_M_REG         (IEMOPFORM_VEX_M | IEMOPFORM_MOD3)
+#define IEMOPFORM_VEX_M_REG     (IEMOPFORM_VEX_M | IEMOPFORM_MOD3)
 /** VEX+ModR/M: r/m only (memory). */
-#define IEMOPFORM_VEX_M_MEM         (IEMOPFORM_VEX_M | IEMOPFORM_NOT_MOD3)
+#define IEMOPFORM_VEX_M_MEM     (IEMOPFORM_VEX_M | IEMOPFORM_NOT_MOD3)
 /** VEX+ModR/M: reg only */
 #define IEMOPFORM_VEX_R         7
 /** VEX+ModR/M: reg, vvvv, r/m */
 #define IEMOPFORM_VEX_RVM       8
+/** VEX+ModR/M: reg, vvvv, r/m (register). */
+#define IEMOPFORM_VEX_RVM_REG   (IEMOPFORM_VEX_RVM | IEMOPFORM_MOD3)
+/** VEX+ModR/M: reg, vvvv, r/m (memory). */
+#define IEMOPFORM_VEX_RVM_MEM   (IEMOPFORM_VEX_RVM | IEMOPFORM_NOT_MOD3)
 /** VEX+ModR/M: r/m, vvvv, reg */
 #define IEMOPFORM_VEX_MVR       9
+/** VEX+ModR/M: r/m, vvvv, reg (register) */
+#define IEMOPFORM_VEX_MVR_REG   (IEMOPFORM_VEX_MVR | IEMOPFORM_MOD3)
+/** VEX+ModR/M: r/m, vvvv, reg (memory) */
+#define IEMOPFORM_VEX_MVR_MEM   (IEMOPFORM_VEX_MVR | IEMOPFORM_NOT_MOD3)
 
 /** Fixed register instruction, no R/M. */
 #define IEMOPFORM_FIXED         16
@@ -926,10 +953,19 @@ typedef IEMCPU const *PCIEMCPU;
 /** @name IEMOPHINT_XXX - Additional Opcode Hints
  * @note These are ORed together with IEMOPFORM_XXX.
  * @{ */
-/** Both the operand size prefixes are ignored. */
-#define IEMOPHINT_IGNORES_OP_SIZE   RT_BIT_32(10)
+/** Ignores the operand size prefix (66h). */
+#define IEMOPHINT_IGNORES_OZ_PFX    RT_BIT_32(10)
+/** Ignores REX.W. */
+#define IEMOPHINT_IGNORES_REXW      RT_BIT_32(11)
+/** Both the operand size prefixes (66h + REX.W) are ignored. */
+#define IEMOPHINT_IGNORES_OP_SIZES  (IEMOPHINT_IGNORES_OZ_PFX | IEMOPHINT_IGNORES_REXW)
 /** Allowed with the lock prefix. */
 #define IEMOPHINT_LOCK_ALLOWED      RT_BIT_32(11)
+/** The VEX.L value is ignored (aka LIG). */
+#define IEMOPHINT_IGNORES_VEX_L     RT_BIT_32(12)
+/** The VEX.L value must be zero (i.e. 128-bit width). */
+#define IEMOPHINT_VEX_L_ZERO        RT_BIT_32(13)
+
 /** Hint to IEMAllInstructionPython.py that this macro should be skipped.  */
 #define IEMOPHINT_SKIP_PYTHON       RT_BIT_32(31)
 /** @} */
@@ -1607,7 +1643,14 @@ IEM_DECL_IMPL_DEF(void, iemAImpl_pmovmskb_u128,(PCX86FXSTATE pFpuState, uint64_t
 /** @name Media (SSE/MMX/AVX) operation: Sort this later
  * @{ */
 IEM_DECL_IMPL_DEF(void, iemAImpl_movsldup,(PCX86FXSTATE pFpuState, PRTUINT128U puDst, PCRTUINT128U puSrc));
+IEM_DECL_IMPL_DEF(void, iemAImpl_movshdup,(PCX86FXSTATE pFpuState, PRTUINT128U puDst, PCRTUINT128U puSrc));
 IEM_DECL_IMPL_DEF(void, iemAImpl_movddup,(PCX86FXSTATE pFpuState, PRTUINT128U puDst, uint64_t uSrc));
+
+IEM_DECL_IMPL_DEF(void, iemAImpl_vmovsldup_256_rr,(PX86XSAVEAREA pXState, uint8_t iYRegDst, uint8_t iYRegSrc));
+IEM_DECL_IMPL_DEF(void, iemAImpl_vmovsldup_256_rm,(PX86XSAVEAREA pXState, uint8_t iYRegDst, PCRTUINT256U pSrc));
+IEM_DECL_IMPL_DEF(void, iemAImpl_vmovddup_256_rr,(PX86XSAVEAREA pXState, uint8_t iYRegDst, uint8_t iYRegSrc));
+IEM_DECL_IMPL_DEF(void, iemAImpl_vmovddup_256_rm,(PX86XSAVEAREA pXState, uint8_t iYRegDst, PCRTUINT256U pSrc));
+
 /** @} */
 
 
diff --git a/src/VBox/VMM/testcase/tstIEMCheckMc.cpp b/src/VBox/VMM/testcase/tstIEMCheckMc.cpp
index 56f8e37..1b75035 100644
--- a/src/VBox/VMM/testcase/tstIEMCheckMc.cpp
+++ b/src/VBox/VMM/testcase/tstIEMCheckMc.cpp
@@ -118,11 +118,15 @@ typedef VBOXSTRICTRC (* PFNIEMOPRM)(PVMCPU pVCpu, uint8_t bRm);
 #define IEMOP_HLP_64BIT_OP_SIZE()                           do { } while (0)
 #define IEMOP_HLP_DEFAULT_64BIT_OP_SIZE()                   do { } while (0)
 #define IEMOP_HLP_CLEAR_REX_NOT_BEFORE_OPCODE(a_szPrf)      do { } while (0)
-#define IEMOP_HLP_DONE_VEX_DECODING_L_ZERO_NO_VVV()         do { } while (0)
+#define IEMOP_HLP_DONE_VEX_DECODING_L0_AND_NO_VVVV()         do { } while (0)
 #define IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX()            do { } while (0)
+#define IEMOP_HLP_DONE_VEX_DECODING()             do { } while (0)
+#define IEMOP_HLP_DONE_VEX_DECODING_L0()      do { } while (0)
+#define IEMOP_HLP_DONE_VEX_DECODING_NO_VVVV() do { } while (0)
 #define IEMOP_HLP_DONE_DECODING_NO_LOCK_REPZ_OR_REPNZ_PREFIXES()                                    do { } while (0)
+
+
 #define IEMOP_HLP_DONE_DECODING()                           do { } while (0)
-#define IEMOP_HLP_DONE_VEX_DECODING()                       do { } while (0)
 
 #define IEMOP_HLP_SVM_CTRL_INTERCEPT(a_pVCpu, a_Intercept, a_uExitCode, a_uExitInfo1, a_uExitInfo2) do { } while (0)
 #define IEMOP_HLP_SVM_READ_CR_INTERCEPT(a_pVCpu, a_uCr, a_uExitInfo1, a_uExitInfo2)                 do { } while (0)
@@ -351,6 +355,9 @@ IEMOPMEDIAF2 g_iemAImpl_pcmpeqd;
 #define IEM_MC_MAYBE_RAISE_SSE_RELATED_XCPT()           do {} while (0)
 #define IEM_MC_MAYBE_RAISE_SSE2_RELATED_XCPT()          do {} while (0)
 #define IEM_MC_MAYBE_RAISE_SSE3_RELATED_XCPT()          do {} while (0)
+#define IEM_MC_MAYBE_RAISE_SSE41_RELATED_XCPT()         do {} while (0)
+#define IEM_MC_MAYBE_RAISE_AVX_RELATED_XCPT()           do {} while (0)
+#define IEM_MC_MAYBE_RAISE_AVX2_RELATED_XCPT()          do {} while (0)
 #define IEM_MC_RAISE_GP0_IF_CPL_NOT_ZERO()              do {} while (0)
 #define IEM_MC_RAISE_GP0_IF_EFF_ADDR_UNALIGNED(a_EffAddr, a_cbAlign) \
     do { AssertCompile(RT_IS_POWER_OF_TWO(a_cbAlign)); CHK_TYPE(RTGCPTR,  a_EffAddr); } while (0)
@@ -375,6 +382,9 @@ IEMOPMEDIAF2 g_iemAImpl_pcmpeqd;
     AssertCompile((a_iArg) < cArgs); \
     a_Type const a_Name = (a_Value); \
     NOREF(a_Name)
+#define IEM_MC_ARG_XSTATE(a_Name, a_iArg) \
+    IEM_MC_ARG_CONST(PX86XSAVEAREA, a_Name, NULL, a_iArg)
+
 #define IEM_MC_ARG_LOCAL_REF(a_Type, a_Name, a_Local, a_iArg) \
     RT_CONCAT(iArgCheck_, a_iArg) = 1; NOREF(RT_CONCAT(iArgCheck_,a_iArg)); \
     int RT_CONCAT3(iArgCheck_,a_iArg,a_Name); NOREF(RT_CONCAT3(iArgCheck_,a_iArg,a_Name)); \
@@ -491,7 +501,7 @@ IEMOPMEDIAF2 g_iemAImpl_pcmpeqd;
 #define IEM_MC_CLEAR_EFL_BIT(a_fBit)                    do { CHK_SINGLE_BIT(uint32_t, a_fBit); } while (0)
 #define IEM_MC_FLIP_EFL_BIT(a_fBit)                     do { CHK_SINGLE_BIT(uint32_t, a_fBit); } while (0)
 #define IEM_MC_CLEAR_FSW_EX()                           do { } while (0)
-
+#define IEM_MC_FPU_TO_MMX_MODE()                        do { (void)fFpuWrite; } while (0)
 
 #define IEM_MC_FETCH_MREG_U64(a_u64Value, a_iMReg)          do { (a_u64Value) = 0; CHK_TYPE(uint64_t, a_u64Value); (void)fFpuRead; } while (0)
 #define IEM_MC_FETCH_MREG_U32(a_u32Value, a_iMReg)          do { (a_u32Value) = 0; CHK_TYPE(uint32_t, a_u32Value); (void)fFpuRead; } while (0)
@@ -510,11 +520,32 @@ IEMOPMEDIAF2 g_iemAImpl_pcmpeqd;
 #define IEM_MC_STORE_XREG_U64_ZX_U128(a_iXReg, a_u64Value)  do { CHK_TYPE(uint64_t,  a_u64Value);  (void)fSseWrite; } while (0)
 #define IEM_MC_STORE_XREG_U32(a_iXReg, a_u32Value)          do { CHK_TYPE(uint32_t,  a_u32Value);  (void)fSseWrite; } while (0)
 #define IEM_MC_STORE_XREG_U32_ZX_U128(a_iXReg, a_u32Value)  do { CHK_TYPE(uint32_t,  a_u32Value);  (void)fSseWrite; } while (0)
+#define IEM_MC_STORE_XREG_HI_U64(a_iXReg, a_u64Value)       do { CHK_TYPE(uint64_t,  a_u64Value);  (void)fSseWrite; } while (0)
 #define IEM_MC_REF_XREG_U128(a_pu128Dst, a_iXReg)           do { (a_pu128Dst) = (PRTUINT128U)((uintptr_t)0);        CHK_PTYPE(PRTUINT128U, a_pu128Dst);       (void)fSseWrite; } while (0)
 #define IEM_MC_REF_XREG_U128_CONST(a_pu128Dst, a_iXReg)     do { (a_pu128Dst) = (PCRTUINT128U)((uintptr_t)0);  CHK_PTYPE(PCRTUINT128U, a_pu128Dst); (void)fSseWrite; } while (0)
 #define IEM_MC_REF_XREG_U64_CONST(a_pu64Dst, a_iXReg)       do { (a_pu64Dst)  = (uint64_t const *)((uintptr_t)0);   CHK_PTYPE(uint64_t const *, a_pu64Dst);   (void)fSseWrite; } while (0)
 #define IEM_MC_COPY_XREG_U128(a_iXRegDst, a_iXRegSrc)       do { (void)fSseWrite; } while (0)
 
+#define IEM_MC_FETCH_YREG_U256(a_u256Value, a_iYRegSrc)           do { (a_u256Value).au64[0] = (a_u256Value).au64[1] = (a_u256Value).au64[2] = (a_u256Value).au64[3] = 0; CHK_TYPE(RTUINT256U, a_u256Value); (void)fAvxRead; } while (0)
+#define IEM_MC_FETCH_YREG_U128(a_u128Value, a_iYRegSrc)           do { (a_u128Value).au64[0] = (a_u128Value).au64[1] = 0; CHK_TYPE(RTUINT128U, a_u128Value); (void)fAvxRead; } while (0)
+#define IEM_MC_FETCH_YREG_U64(a_u64Value, a_iYRegSrc)             do { (a_u64Value) = UINT64_MAX; CHK_TYPE(uint64_t, a_u64Value); (void)fAvxRead; } while (0)
+#define IEM_MC_FETCH_YREG_U32(a_u32Value, a_iYRegSrc)             do { (a_u32Value) = UINT32_MAX; CHK_TYPE(uint32_t, a_u32Value); (void)fAvxRead; } while (0)
+#define IEM_MC_STORE_YREG_U32_ZX_VLMAX(a_iYRegDst, a_u32Value)    do { CHK_TYPE(uint32_t, a_u32Value); (void)fAvxWrite; } while (0)
+#define IEM_MC_STORE_YREG_U64_ZX_VLMAX(a_iYRegDst, a_u64Value)    do { CHK_TYPE(uint64_t, a_u64Value); (void)fAvxWrite; } while (0)
+#define IEM_MC_STORE_YREG_U128_ZX_VLMAX(a_iYRegDst, a_u128Value)  do { CHK_TYPE(RTUINT128U, a_u128Value); (void)fAvxWrite; } while (0)
+#define IEM_MC_STORE_YREG_U256_ZX_VLMAX(a_iYRegDst, a_u256Value)  do { CHK_TYPE(RTUINT256U, a_u256Value); (void)fAvxWrite; } while (0)
+#define IEM_MC_REF_YREG_U128(a_pu128Dst, a_iYReg)                 do { (a_pu128Dst) = (PRTUINT128U)((uintptr_t)0);      CHK_PTYPE(PRTUINT128U, a_pu128Dst);       (void)fAvxWrite; } while (0)
+#define IEM_MC_REF_YREG_U128_CONST(a_pu128Dst, a_iYReg)           do { (a_pu128Dst) = (PCRTUINT128U)((uintptr_t)0);     CHK_PTYPE(PCRTUINT128U, a_pu128Dst);      (void)fAvxWrite; } while (0)
+#define IEM_MC_REF_YREG_U64_CONST(a_pu64Dst, a_iYReg)             do { (a_pu64Dst)  = (uint64_t const *)((uintptr_t)0); CHK_PTYPE(uint64_t const *, a_pu64Dst);   (void)fAvxWrite; } while (0)
+#define IEM_MC_CLEAR_YREG_128_UP(a_iYReg)                         do { (void)fAvxWrite; } while (0)
+#define IEM_MC_COPY_YREG_U256_ZX_VLMAX(a_iYRegDst, a_iYRegSrc)    do { (void)fAvxWrite; } while (0)
+#define IEM_MC_COPY_YREG_U128_ZX_VLMAX(a_iYRegDst, a_iYRegSrc)    do { (void)fAvxWrite; } while (0)
+#define IEM_MC_COPY_YREG_U64_ZX_VLMAX(a_iYRegDst, a_iYRegSrc)     do { (void)fAvxWrite; } while (0)
+#define IEM_MC_MERGE_YREG_U32_U96_ZX_VLMAX(a_iYRegDst, a_iYRegSrc32, a_iYRegSrcHx)      do { (void)fAvxWrite; (void)fAvxRead; } while (0)
+#define IEM_MC_MERGE_YREG_U64_U64_ZX_VLMAX(a_iYRegDst, a_iYRegSrc64, a_iYRegSrcHx)      do { (void)fAvxWrite; (void)fAvxRead; } while (0)
+#define IEM_MC_MERGE_YREG_U64HI_U64_ZX_VLMAX(a_iYRegDst, a_iYRegSrc64, a_iYRegSrcHx)    do { (void)fAvxWrite; (void)fAvxRead; } while (0)
+#define IEM_MC_MERGE_YREG_U64LOCAL_U64_ZX_VLMAX(a_iYRegDst, a_u64Local, a_iYRegSrcHx)   do { (void)fAvxWrite; (void)fAvxRead; } while (0)
+
 #define IEM_MC_FETCH_MEM_U8(a_u8Dst, a_iSeg, a_GCPtrMem)                do { CHK_GCPTR(a_GCPtrMem); } while (0)
 #define IEM_MC_FETCH_MEM16_U8(a_u8Dst, a_iSeg, a_GCPtrMem16)            do { CHK_TYPE(uint16_t, a_GCPtrMem16); } while (0)
 #define IEM_MC_FETCH_MEM32_U8(a_u8Dst, a_iSeg, a_GCPtrMem32)            do { CHK_TYPE(uint32_t, a_GCPtrMem32); } while (0)
@@ -553,6 +584,8 @@ IEMOPMEDIAF2 g_iemAImpl_pcmpeqd;
 #define IEM_MC_FETCH_MEM_R80(a_r80Dst, a_iSeg, a_GCPtrMem)              do { CHK_GCPTR(a_GCPtrMem); CHK_TYPE(RTFLOAT80U, a_r80Dst);} while (0)
 #define IEM_MC_FETCH_MEM_U128(a_u128Dst, a_iSeg, a_GCPtrMem)            do { CHK_GCPTR(a_GCPtrMem); CHK_TYPE(RTUINT128U, a_u128Dst);} while (0)
 #define IEM_MC_FETCH_MEM_U128_ALIGN_SSE(a_u128Dst, a_iSeg, a_GCPtrMem)  do { CHK_GCPTR(a_GCPtrMem); CHK_TYPE(RTUINT128U, a_u128Dst);} while (0)
+#define IEM_MC_FETCH_MEM_U256(a_u256Dst, a_iSeg, a_GCPtrMem)            do { CHK_GCPTR(a_GCPtrMem); CHK_TYPE(RTUINT256U, a_u256Dst);} while (0)
+#define IEM_MC_FETCH_MEM_U256_ALIGN_AVX(a_u256Dst, a_iSeg, a_GCPtrMem)  do { CHK_GCPTR(a_GCPtrMem); CHK_TYPE(RTUINT256U, a_u256Dst);} while (0)
 
 #define IEM_MC_STORE_MEM_U8(a_iSeg, a_GCPtrMem, a_u8Value)              do { CHK_GCPTR(a_GCPtrMem); CHK_TYPE(uint8_t,  a_u8Value); CHK_SEG_IDX(a_iSeg); } while (0)
 #define IEM_MC_STORE_MEM_U16(a_iSeg, a_GCPtrMem, a_u16Value)            do { CHK_GCPTR(a_GCPtrMem); CHK_TYPE(uint16_t, a_u16Value);      } while (0)
@@ -569,8 +602,10 @@ IEMOPMEDIAF2 g_iemAImpl_pcmpeqd;
 #define IEM_MC_STORE_MEM_NEG_QNAN_R32_BY_REF(a_pr32Dst)                 do { CHK_TYPE(PRTFLOAT32U, a_pr32Dst); } while (0)
 #define IEM_MC_STORE_MEM_NEG_QNAN_R64_BY_REF(a_pr64Dst)                 do { CHK_TYPE(PRTFLOAT64U, a_pr64Dst); } while (0)
 #define IEM_MC_STORE_MEM_NEG_QNAN_R80_BY_REF(a_pr80Dst)                 do { CHK_TYPE(PRTFLOAT80U, a_pr80Dst); } while (0)
-#define IEM_MC_STORE_MEM_U128(a_iSeg, a_GCPtrMem, a_u128Dst)            do { CHK_GCPTR(a_GCPtrMem); CHK_TYPE(RTUINT128U, a_u128Dst); CHK_SEG_IDX(a_iSeg);} while (0)
-#define IEM_MC_STORE_MEM_U128_ALIGN_SSE(a_iSeg, a_GCPtrMem, a_u128Dst)  do { CHK_GCPTR(a_GCPtrMem); CHK_TYPE(RTUINT128U, a_u128Dst); CHK_SEG_IDX(a_iSeg);} while (0)
+#define IEM_MC_STORE_MEM_U128(a_iSeg, a_GCPtrMem, a_u128Src)            do { CHK_GCPTR(a_GCPtrMem); CHK_TYPE(RTUINT128U, a_u128Src); CHK_SEG_IDX(a_iSeg);} while (0)
+#define IEM_MC_STORE_MEM_U128_ALIGN_SSE(a_iSeg, a_GCPtrMem, a_u128Src)  do { CHK_GCPTR(a_GCPtrMem); CHK_TYPE(RTUINT128U, a_u128Src); CHK_SEG_IDX(a_iSeg);} while (0)
+#define IEM_MC_STORE_MEM_U256(a_iSeg, a_GCPtrMem, a_u256Src)            do { CHK_GCPTR(a_GCPtrMem); CHK_TYPE(RTUINT256U, a_u256Src); CHK_SEG_IDX(a_iSeg);} while (0)
+#define IEM_MC_STORE_MEM_U256_ALIGN_AVX(a_iSeg, a_GCPtrMem, a_u256Src)  do { CHK_GCPTR(a_GCPtrMem); CHK_TYPE(RTUINT256U, a_u256Src); CHK_SEG_IDX(a_iSeg);} while (0)
 
 #define IEM_MC_PUSH_U16(a_u16Value)                                     do {} while (0)
 #define IEM_MC_PUSH_U32(a_u32Value)                                     do {} while (0)
@@ -647,12 +682,15 @@ IEMOPMEDIAF2 g_iemAImpl_pcmpeqd;
 #define IEM_MC_UPDATE_FSW_WITH_MEM_OP_THEN_POP(a_u16FSW, a_iEffSeg, a_GCPtrEff)                 do { (void)fFpuWrite; } while (0)
 #define IEM_MC_UPDATE_FSW_THEN_POP_POP(a_u16FSW)                                                do { (void)fFpuWrite; } while (0)
 #define IEM_MC_PREPARE_FPU_USAGE() \
-    const int fFpuRead = 1, fFpuWrite = 1, fFpuHost = 1, fSseRead = 1, fSseWrite = 1, fSseHost = 1
+    const int fFpuRead = 1, fFpuWrite = 1, fFpuHost = 1, fSseRead = 1, fSseWrite = 1, fSseHost = 1, fAvxRead = 1, fAvxWrite = 1, fAvxHost = 1
 #define IEM_MC_ACTUALIZE_FPU_STATE_FOR_READ()   const int fFpuRead = 1, fSseRead = 1
 #define IEM_MC_ACTUALIZE_FPU_STATE_FOR_CHANGE() const int fFpuRead = 1, fFpuWrite = 1, fSseRead = 1, fSseWrite = 1
 #define IEM_MC_PREPARE_SSE_USAGE()              const int fSseRead = 1, fSseWrite = 1, fSseHost = 1
 #define IEM_MC_ACTUALIZE_SSE_STATE_FOR_READ()   const int fSseRead = 1
 #define IEM_MC_ACTUALIZE_SSE_STATE_FOR_CHANGE() const int fSseRead = 1, fSseWrite = 1
+#define IEM_MC_PREPARE_AVX_USAGE()              const int fAvxRead = 1, fAvxWrite = 1, fAvxHost = 1, fSseRead = 1, fSseWrite = 1, fSseHost = 1
+#define IEM_MC_ACTUALIZE_AVX_STATE_FOR_READ()   const int fAvxRead = 1, fSseRead = 1
+#define IEM_MC_ACTUALIZE_AVX_STATE_FOR_CHANGE() const int fAvxRead = 1, fAvxWrite = 1, fSseRead = 1, fSseWrite = 1
 
 #define IEM_MC_CALL_MMX_AIMPL_2(a_pfnAImpl, a0, a1) \
     do { (void)fFpuHost; (void)fFpuWrite; CHK_CALL_ARG(a0, 0); CHK_CALL_ARG(a1, 1); } while (0)
@@ -662,6 +700,13 @@ IEMOPMEDIAF2 g_iemAImpl_pcmpeqd;
     do { (void)fSseHost; (void)fSseWrite; CHK_CALL_ARG(a0, 0); CHK_CALL_ARG(a1, 1); } while (0)
 #define IEM_MC_CALL_SSE_AIMPL_3(a_pfnAImpl, a0, a1, a2) \
     do { (void)fSseHost; (void)fSseWrite; CHK_CALL_ARG(a0, 0); CHK_CALL_ARG(a1, 1); CHK_CALL_ARG(a2, 2);} while (0)
+#define IEM_MC_IMPLICIT_AVX_AIMPL_ARGS() IEM_MC_ARG_CONST(PX86XSAVEAREA, pXState, (pVCpu)->iem.s.CTX_SUFF(pCtx)->CTX_SUFF(pXState), 0)
+#define IEM_MC_CALL_AVX_AIMPL_2(a_pfnAImpl, a1, a2) \
+    do { (void)fAvxHost; (void)fAvxWrite; CHK_CALL_ARG(a1, 1); CHK_CALL_ARG(a2, 2); } while (0)
+#define IEM_MC_CALL_AVX_AIMPL_3(a_pfnAImpl, a1, a2, a3) \
+    do { (void)fAvxHost; (void)fAvxWrite; CHK_CALL_ARG(a1, 1); CHK_CALL_ARG(a2, 2); CHK_CALL_ARG(a3, 3);} while (0)
+#define IEM_MC_CALL_AVX_AIMPL_4(a_pfnAImpl, a1, a2, a3, a4) \
+    do { (void)fAvxHost; (void)fAvxWrite; CHK_CALL_ARG(a1, 1); CHK_CALL_ARG(a2, 2); CHK_CALL_ARG(a3, 3); CHK_CALL_ARG(a4, 4);} while (0)
 
 #define IEM_MC_IF_EFL_BIT_SET(a_fBit)                                   if (g_fRandom) {
 #define IEM_MC_IF_EFL_BIT_NOT_SET(a_fBit)                               if (g_fRandom) {
diff --git a/src/VBox/ValidationKit/Makefile.kmk b/src/VBox/ValidationKit/Makefile.kmk
index 34b50bd..74d7c7a 100644
--- a/src/VBox/ValidationKit/Makefile.kmk
+++ b/src/VBox/ValidationKit/Makefile.kmk
@@ -102,7 +102,7 @@ ifndef VBOX_WITHOUT_VALIDATIONKIT_ZIP
 	$(foreach os, darwin freebsd linux os2 solaris win,$(foreach arch, x86 amd64 \
 	,$(if-expr defined(VBOX_WITH_VALIDATIONKIT_PACKING.$(os).$(arch))\
 		,$(NLTAB)$(QUIET)$(REDIRECT) -C $(PATH_OUT_BASE)/$(os).$(arch)/$(KBUILD_TYPE)/ \
-			-- zip$(HOSTSUFF_EXE) -r9 $@ $(INST_VALIDATIONKIT) -x '*.pyc',)))
+			-- $(VBOX_ZIP) -r9 $@ $(INST_VALIDATIONKIT) -x '*.pyc',)))
 
  #
  # VBoxTestBoxScript.zip - For setting up the testboxes.
@@ -117,7 +117,7 @@ ifndef VBOX_WITHOUT_VALIDATIONKIT_ZIP
 	$(foreach os, darwin freebsd linux os2 solaris win,$(foreach arch, x86 amd64 \
 	,$(if-expr defined(VBOX_WITH_VALIDATIONKIT_PACKING.$(os).$(arch))\
 		,$(NLTAB)$(QUIET)$(REDIRECT) -C $(PATH_OUT_BASE)/$(os).$(arch)/$(KBUILD_TYPE)/ \
-			-- zip$(HOSTSUFF_EXE) -r9 $@ $(INST_TESTBOXSCRIPT) -x '*.pyc',)))
+			-- $(VBOX_ZIP) -r9 $@ $(INST_TESTBOXSCRIPT) -x '*.pyc',)))
 
 endif # !VBOX_WITHOUT_VALIDATIONKIT_ZIP
 
diff --git a/src/VBox/ValidationKit/bootsectors/Config.kmk b/src/VBox/ValidationKit/bootsectors/Config.kmk
index 50c8ef3..6d5ef30 100644
--- a/src/VBox/ValidationKit/bootsectors/Config.kmk
+++ b/src/VBox/ValidationKit/bootsectors/Config.kmk
@@ -554,6 +554,7 @@ endef
 #       -q                     Quiet, no logos or stuff.
 #       -0                     Use 8086 instruction set (16-bit only).
 #       -3                     Use 386 instruction set (16-bit only).
+#       -e<num>                Stop after <num> errors.
 #       -wx                    Maxium warning level.
 #       -zl                    Don't emit default library information.
 #       -zdp                   DS pegged to BS3DATA16_GROUP/DGROUP.
@@ -597,9 +598,9 @@ TEMPLATE_VBoxBS3KitImg_ARTOOL       = OPENWATCOM-16
 TEMPLATE_VBoxBS3KitImg_CTOOL        = Bs3Ow16
 TEMPLATE_VBoxBS3KitImg_CXXTOOL      = Bs3Ow16
 TEMPLATE_VBoxBS3KitImg_CFLAGS       = $(if $(BS3KIT_SEGNM_DATA16),-nd=$(BS3KIT_SEGNM_DATA16),) \
-	-nt=BS3TEXT16 -nc=$(BS3KIT_CLASS_CODE16) -ecc -q -0 -wx -zl -zdp -zu -ml $(BS3_OW_DBG_OPT) -s -oa -ob -of -oi -ol -or -os -oh -d+
+	-nt=BS3TEXT16 -nc=$(BS3KIT_CLASS_CODE16) -ecc -q -0 -e125 -wx -zl -zdp -zu -ml $(BS3_OW_DBG_OPT) -s -oa -ob -of -oi -ol -or -os -oh -d+
 TEMPLATE_VBoxBS3KitImg_CXXFLAGS     = $(if $(BS3KIT_SEGNM_DATA16),-nd=$(BS3KIT_SEGNM_DATA16),) \
-	-nt=BS3TEXT16 -nc=$(BS3KIT_CLASS_CODE16) -ecc -q -0 -wx -zl -zdp -zu -ml $(BS3_OW_DBG_OPT) -s -oa -ob -of -oi -ol -or -os -oh -d+
+	-nt=BS3TEXT16 -nc=$(BS3KIT_CLASS_CODE16) -ecc -q -0 -e125 -wx -zl -zdp -zu -ml $(BS3_OW_DBG_OPT) -s -oa -ob -of -oi -ol -or -os -oh -d+
 TEMPLATE_VBoxBS3KitImg_CDEFS        = ARCH_BITS=16 RT_ARCH_X86
 
 TEMPLATE_VBoxBS3KitImg_TOOL         = $(NO_SUCH_VARIABLE)
@@ -766,9 +767,9 @@ TEMPLATE_VBoxBS3KitImg32_ARTOOL       = OPENWATCOM
 TEMPLATE_VBoxBS3KitImg32_CTOOL        = Bs3Ow32
 TEMPLATE_VBoxBS3KitImg32_CXXTOOL      = Bs3Ow32
 TEMPLATE_VBoxBS3KitImg32_CFLAGS       = \
-	-nt=BS3TEXT32 -nd=BS3DATA32 -nc=BS3CLASS32CODE -ecc -q -wx -zl -mf $(BS3_OW_DBG_OPT) -s -oa -ob -of -oi -ol -or -os -d+
+	-nt=BS3TEXT32 -nd=BS3DATA32 -nc=BS3CLASS32CODE -ecc -q -e125 -wx -zl -mf $(BS3_OW_DBG_OPT) -s -oa -ob -of -oi -ol -or -os -d+
 TEMPLATE_VBoxBS3KitImg32_CXXFLAGS     = \
-	-nt=BS3TEXT32 -nd=BS3DATA32 -nc=BS3CLASS32CODE -ecc -q -wx -zl -mf $(BS3_OW_DBG_OPT) -s -oa -ob -of -oi -ol -or -os -d+
+	-nt=BS3TEXT32 -nd=BS3DATA32 -nc=BS3CLASS32CODE -ecc -q -e125 -wx -zl -mf $(BS3_OW_DBG_OPT) -s -oa -ob -of -oi -ol -or -os -d+
 TEMPLATE_VBoxBS3KitImg32_INCS         = $(VBOX_PATH_BS3KIT_SRC) .
 TEMPLATE_VBoxBS3KitImg32_LDTOOL       = VBoxBsUnusedLd
 
diff --git a/src/VBox/ValidationKit/bootsectors/bs3-cpu-generated-1-data.py b/src/VBox/ValidationKit/bootsectors/bs3-cpu-generated-1-data.py
index 617c62d..be65421 100755
--- a/src/VBox/ValidationKit/bootsectors/bs3-cpu-generated-1-data.py
+++ b/src/VBox/ValidationKit/bootsectors/bs3-cpu-generated-1-data.py
@@ -30,7 +30,7 @@ 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: 114989 $"
+__version__ = "$Revision: 115692 $"
 
 # Standard python imports.
 import os;
@@ -301,11 +301,26 @@ class Bs3Cg1Instruction(object):
 
         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;
+        if oInstr.sSubOpcode == 'rex.w=1':      self.sEncoding += '_WNZ';
+        elif oInstr.sSubOpcode == 'rex.w=0':    self.sEncoding += '_WZ';
+
         if oInstr.fUnused:
             if oInstr.sInvalidStyle == 'immediate' and oInstr.sSubOpcode:
                 self.sEncoding += '_MOD_EQ_3' if oInstr.sSubOpcode == '11 mr/reg' else '_MOD_NE_3';
+            elif oInstr.sInvalidStyle == 'intel-modrm':
+                if oInstr.sSubOpcode is None:
+                    self.sEncoding = 'BS3CG1ENC_MODRM_Gv_Ev';
+                elif oInstr.sSubOpcode == '11 mr/reg':
+                    self.sEncoding = 'BS3CG1ENC_MODRM_MOD_EQ_3';
+                elif oInstr.sSubOpcode == '!11 mr/reg':
+                    self.sEncoding = 'BS3CG1ENC_MODRM_MOD_NE_3';
+                else:
+                    raise Exception('Unhandled sSubOpcode=%s for sInvalidStyle=%s' % (oInstr.sSubOpcode, oInstr.sInvalidStyle));
+            elif oInstr.sInvalidStyle == 'vex.modrm':
+                self.sEncoding = 'BS3CG1ENC_VEX_MODRM';
 
         self.asFlags            = [];
         if 'invalid_64' in oInstr.dHints:
@@ -316,6 +331,8 @@ class Bs3Cg1Instruction(object):
             self.asFlags.append('BS3CG1INSTR_F_INVALID');
         if oInstr.sInvalidStyle and oInstr.sInvalidStyle.startswith('intel-'):
             self.asFlags.append('BS3CG1INSTR_F_INTEL_DECODES_INVALID');
+        if 'vex_l_zero' in oInstr.dHints:
+            self.asFlags.append('BS3CG1INSTR_F_VEX_L_ZERO');
 
         self.fAdvanceMnemonic   = True; ##< Set by the caller.
         if oInstr.sPrefix:
@@ -334,7 +351,7 @@ class Bs3Cg1Instruction(object):
         self.sCpu = 'BS3CG1CPU_';
         assert len(oInstr.asCpuIds) in [0, 1], str(oInstr);
         if oInstr.asCpuIds:
-            self.sCpu += oInstr.asCpuIds[0].upper();
+            self.sCpu += oInstr.asCpuIds[0].upper().replace('.', '_');
         elif oInstr.sMinCpu:
             self.sCpu += 'GE_' + oInstr.sMinCpu;
         else:
diff --git a/src/VBox/ValidationKit/bootsectors/bs3-cpu-generated-1-template.c b/src/VBox/ValidationKit/bootsectors/bs3-cpu-generated-1-template.c
index e94f4ba..ccdb52e 100644
--- a/src/VBox/ValidationKit/bootsectors/bs3-cpu-generated-1-template.c
+++ b/src/VBox/ValidationKit/bootsectors/bs3-cpu-generated-1-template.c
@@ -41,6 +41,8 @@
 /*********************************************************************************************************************************
 *   Defined Constants And Macros                                                                                                 *
 *********************************************************************************************************************************/
+#define BS3CG1_WITH_VEX
+
 #define P_CS        X86_OP_PRF_CS
 #define P_SS        X86_OP_PRF_SS
 #define P_DS        X86_OP_PRF_DS
@@ -81,6 +83,15 @@
 # define BS3CG1_DPRINTF(a_ArgList) do { } while (0)
 #endif
 
+/**
+ * Checks if this is a 64-bit test target or not.
+ * Helps avoid ifdefs or code bloat.
+ */
+#if ARCH_BITS == 64
+# define BS3CG1_IS_64BIT_TARGET(a_pThis)    BS3_MODE_IS_64BIT_CODE((a_pThis)->bMode)
+#else
+# define BS3CG1_IS_64BIT_TARGET(a_pThis)    (false)
+#endif
 
 
 /*********************************************************************************************************************************
@@ -91,11 +102,29 @@ typedef enum BS3CG1OPLOC
 {
     BS3CG1OPLOC_INVALID = 0,
     BS3CG1OPLOC_CTX,
+    BS3CG1OPLOC_CTX_ZX_VLMAX,
     BS3CG1OPLOC_IMM,
     BS3CG1OPLOC_MEM,
     BS3CG1OPLOC_MEM_RW,
+    BS3CG1OPLOC_MEM_WO,
     BS3CG1OPLOC_END
 } BS3CG1OPLOC;
+AssertCompile(BS3CG1OPLOC_END <= 16);
+
+
+/** Pointer to the generated test state. */
+typedef struct BS3CG1STATE *PBS3CG1STATE;
+
+/**
+ * Encoder callback.
+ * @returns Next encoding.  If equal or less to @a iEncoding, no
+ *          further encodings are available for testing.
+ * @param   pThis       The state.
+ * @param   iEncoding   The encoding.
+ */
+typedef unsigned BS3_NEAR_CODE FNBS3CG1ENCODER(PBS3CG1STATE pThis, unsigned iEncoding);
+/** Pointer to a encoder callback. */
+typedef FNBS3CG1ENCODER *PFNBS3CG1ENCODER;
 
 
 /**
@@ -133,6 +162,8 @@ typedef struct BS3CG1STATE
     BS3CG1OP                aenmOperands[4];
     /** Opcode bytes. */
     uint8_t                 abOpcodes[4];
+    /** The instruction encoder. */
+    PFNBS3CG1ENCODER        pfnEncoder;
 
     /** The length of the mnemonic. */
     uint8_t                 cchMnemonic;
@@ -146,6 +177,8 @@ typedef struct BS3CG1STATE
 
     /** Operand size in bytes (0 if not applicable). */
     uint8_t                 cbOperand;
+    /** Current VEX.L value (UINT8_MAX if not applicable). */
+    uint8_t                 uVexL;
     /** Current target ring (0..3). */
     uint8_t                 uCpl;
 
@@ -189,13 +222,21 @@ typedef struct BS3CG1STATE
         uint8_t             cbOp;
         /** BS3CG1OPLOC_XXX. */
         uint8_t             enmLocation;
+        /** BS3CG1OPLOC_XXX for memory encodings (MODRM.rm field). */
+        uint8_t             enmLocationMem : 4;
+        /** BS3CG1OPLOC_XXX for register encodings (MODRM.rm field). */
+        uint8_t             enmLocationReg : 4;
         /** The BS3CG1DST value for this field.
          * Set to BS3CG1DST_INVALID if memory or immediate.  */
         uint8_t             idxField;
+        /** The base BS3CG1DST value for this field.
+         * Used only by some generalized encoders when dealing with registers. */
+        uint8_t             idxFieldBase;
         /** Depends on enmLocation.
          * - BS3CG1OPLOC_IMM:       offset relative to start of the instruction.
          * - BS3CG1OPLOC_MEM:       offset should be subtracted from &pbDataPg[_4K].
          * - BS3CG1OPLOC_MEM_RW:    offset should be subtracted from &pbDataPg[_4K].
+         * - BS3CG1OPLOC_MEM_RO:    offset should be subtracted from &pbDataPg[_4K].
          * - BS3CG1OPLOC_CTX:       not used (use idxField instead).
          */
         uint8_t             off;
@@ -267,8 +308,6 @@ typedef struct BS3CG1STATE
     } aSavedSegRegs[4];
 
 } BS3CG1STATE;
-/** Pointer to the generated test state. */
-typedef BS3CG1STATE *PBS3CG1STATE;
 
 
 #define BS3CG1_PF_OZ  UINT16_C(0x0001)
@@ -432,6 +471,14 @@ static const uint8_t g_acbBs3Cg1DstFields[] =
     /* [BS3CG1DST_MM5] = */         8,
     /* [BS3CG1DST_MM6] = */         8,
     /* [BS3CG1DST_MM7] = */         8,
+    /* [BS3CG1DST_MM0_LO_ZX] = */   4,
+    /* [BS3CG1DST_MM1_LO_ZX] = */   4,
+    /* [BS3CG1DST_MM2_LO_ZX] = */   4,
+    /* [BS3CG1DST_MM3_LO_ZX] = */   4,
+    /* [BS3CG1DST_MM4_LO_ZX] = */   4,
+    /* [BS3CG1DST_MM5_LO_ZX] = */   4,
+    /* [BS3CG1DST_MM6_LO_ZX] = */   4,
+    /* [BS3CG1DST_MM7_LO_ZX] = */   4,
     /* [BS3CG1DST_XMM0] = */        16,
     /* [BS3CG1DST_XMM1] = */        16,
     /* [BS3CG1DST_XMM2] = */        16,
@@ -528,6 +575,22 @@ static const uint8_t g_acbBs3Cg1DstFields[] =
     /* [BS3CG1DST_XMM13_DW0_ZX] =*/ 4,
     /* [BS3CG1DST_XMM14_DW0_ZX] =*/ 4,
     /* [BS3CG1DST_XMM15_DW0_ZX] =*/ 4,
+    /* [BS3CG1DST_XMM0_HI96] = */   12,
+    /* [BS3CG1DST_XMM1_HI96] = */   12,
+    /* [BS3CG1DST_XMM2_HI96] = */   12,
+    /* [BS3CG1DST_XMM3_HI96] = */   12,
+    /* [BS3CG1DST_XMM4_HI96] = */   12,
+    /* [BS3CG1DST_XMM5_HI96] = */   12,
+    /* [BS3CG1DST_XMM6_HI96] = */   12,
+    /* [BS3CG1DST_XMM7_HI96] = */   12,
+    /* [BS3CG1DST_XMM8_HI96] = */   12,
+    /* [BS3CG1DST_XMM9_HI96] = */   12,
+    /* [BS3CG1DST_XMM10_HI96] =*/   12,
+    /* [BS3CG1DST_XMM11_HI96] =*/   12,
+    /* [BS3CG1DST_XMM12_HI96] =*/   12,
+    /* [BS3CG1DST_XMM13_HI96] =*/   12,
+    /* [BS3CG1DST_XMM14_HI96] =*/   12,
+    /* [BS3CG1DST_XMM15_HI96] =*/   12,
     /* [BS3CG1DST_YMM0] = */        32,
     /* [BS3CG1DST_YMM1] = */        32,
     /* [BS3CG1DST_YMM2] = */        32,
@@ -679,6 +742,14 @@ static const unsigned g_aoffBs3Cg1DstFields[] =
     /* [BS3CG1DST_MM5] = */         sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aRegs[5]),
     /* [BS3CG1DST_MM6] = */         sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aRegs[6]),
     /* [BS3CG1DST_MM7] = */         sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aRegs[7]),
+    /* [BS3CG1DST_MM0_LO_ZX] = */   sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aRegs[0]),
+    /* [BS3CG1DST_MM1_LO_ZX] = */   sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aRegs[1]),
+    /* [BS3CG1DST_MM2_LO_ZX] = */   sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aRegs[2]),
+    /* [BS3CG1DST_MM3_LO_ZX] = */   sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aRegs[3]),
+    /* [BS3CG1DST_MM4_LO_ZX] = */   sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aRegs[4]),
+    /* [BS3CG1DST_MM5_LO_ZX] = */   sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aRegs[5]),
+    /* [BS3CG1DST_MM6_LO_ZX] = */   sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aRegs[6]),
+    /* [BS3CG1DST_MM7_LO_ZX] = */   sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aRegs[7]),
 
     /* [BS3CG1DST_XMM0] = */        sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[0]),
     /* [BS3CG1DST_XMM1] = */        sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[1]),
@@ -776,6 +847,22 @@ static const unsigned g_aoffBs3Cg1DstFields[] =
     /* [BS3CG1DST_XMM13_DW0_ZX] =*/ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[13]),
     /* [BS3CG1DST_XMM14_DW0_ZX] =*/ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[14]),
     /* [BS3CG1DST_XMM15_DW0_ZX] =*/ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[15]),
+    /* [BS3CG1DST_XMM0_HI96] = */   sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[0].au32[1]),
+    /* [BS3CG1DST_XMM1_HI96] = */   sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[1].au32[1]),
+    /* [BS3CG1DST_XMM2_HI96] = */   sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[2].au32[1]),
+    /* [BS3CG1DST_XMM3_HI96] = */   sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[3].au32[1]),
+    /* [BS3CG1DST_XMM4_HI96] = */   sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[4].au32[1]),
+    /* [BS3CG1DST_XMM5_HI96] = */   sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[5].au32[1]),
+    /* [BS3CG1DST_XMM6_HI96] = */   sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[6].au32[1]),
+    /* [BS3CG1DST_XMM7_HI96] = */   sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[7].au32[1]),
+    /* [BS3CG1DST_XMM8_HI96] = */   sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[8].au32[1]),
+    /* [BS3CG1DST_XMM9_HI96] = */   sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[9].au32[1]),
+    /* [BS3CG1DST_XMM10_HI96] =*/   sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[10].au32[1]),
+    /* [BS3CG1DST_XMM11_HI96] =*/   sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[11].au32[1]),
+    /* [BS3CG1DST_XMM12_HI96] =*/   sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[12].au32[1]),
+    /* [BS3CG1DST_XMM13_HI96] =*/   sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[13].au32[1]),
+    /* [BS3CG1DST_XMM14_HI96] =*/   sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[14].au32[1]),
+    /* [BS3CG1DST_XMM15_HI96] =*/   sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[15].au32[1]),
 
     /* [BS3CG1DST_YMM0] = */        ~0U,
     /* [BS3CG1DST_YMM1] = */        ~0U,
@@ -928,6 +1015,14 @@ static const struct { char sz[12]; } g_aszBs3Cg1DstFields[] =
     { "MM5" },
     { "MM6" },
     { "MM7" },
+    { "MM0_LO_ZX" },
+    { "MM1_LO_ZX" },
+    { "MM2_LO_ZX" },
+    { "MM3_LO_ZX" },
+    { "MM4_LO_ZX" },
+    { "MM5_LO_ZX" },
+    { "MM6_LO_ZX" },
+    { "MM7_LO_ZX" },
     { "XMM0" },
     { "XMM1" },
     { "XMM2" },
@@ -1024,6 +1119,22 @@ static const struct { char sz[12]; } g_aszBs3Cg1DstFields[] =
     { "XMM13_DW0_ZX" },
     { "XMM14_DW0_ZX" },
     { "XMM15_DW0_ZX" },
+    { "XMM0_HI96" },
+    { "XMM1_HI96" },
+    { "XMM2_HI96" },
+    { "XMM3_HI96" },
+    { "XMM4_HI96" },
+    { "XMM5_HI96" },
+    { "XMM6_HI96" },
+    { "XMM7_HI96" },
+    { "XMM8_HI96" },
+    { "XMM9_HI96" },
+    { "XMM10_HI96" },
+    { "XMM11_HI96" },
+    { "XMM12_HI96" },
+    { "XMM13_HI96" },
+    { "XMM14_HI96" },
+    { "XMM15_HI96" },
     { "YMM0" },
     { "YMM1" },
     { "YMM2" },
@@ -1095,7 +1206,7 @@ static const uint16_t g_afPfxKindToIgnoredFlags[BS3CG1PFXKIND_END] =
 
 
 /**
- * Checks if >= 16 byte SSE/AVX alignment are exempted for the exception type.
+ * Checks if >= 16 byte SSE alignment are exempted for the exception type.
  *
  * @returns true / false.
  * @param   enmXcptType         The type to check.
@@ -1104,6 +1215,12 @@ static bool BS3_NEAR_CODE Bs3Cg1XcptTypeIsUnaligned(BS3CG1XCPTTYPE enmXcptType)
 {
     switch (enmXcptType)
     {
+        case BS3CG1XCPTTYPE_1:
+        case BS3CG1XCPTTYPE_2:
+        case BS3CG1XCPTTYPE_4:
+            return false;
+        case BS3CG1XCPTTYPE_NONE:
+        case BS3CG1XCPTTYPE_3:
         case BS3CG1XCPTTYPE_4UA:
         case BS3CG1XCPTTYPE_5:
             return true;
@@ -1114,78 +1231,32 @@ static bool BS3_NEAR_CODE Bs3Cg1XcptTypeIsUnaligned(BS3CG1XCPTTYPE enmXcptType)
 
 
 /**
- * Inserts a 2-byte VEX prefix.
+ * Checks if >= 16 byte AVX alignment are exempted for the exception type.
  *
- * @returns New offDst value.
- * @param   pThis       The state.
- * @param   offDst      The current instruction offset.
- * @param   uVexL       The VEX.L value.
- * @param   uVexV       The VEX.V value (caller inverted it already).
- * @param   uVexR       The VEX.R value (caller inverted it already).
+ * @returns true / false.
+ * @param   enmXcptType         The type to check.
  */
-DECLINLINE(unsigned) BS3_NEAR_CODE Bs3Cg1InsertVex2bPrefix(PBS3CG1STATE pThis, unsigned offDst,
-                                                           uint8_t uVexV, uint8_t uVexL, uint8_t uVexR)
+static bool BS3_NEAR_CODE Bs3Cg1XcptTypeIsVexUnaligned(BS3CG1XCPTTYPE enmXcptType)
 {
-    uint8_t b = uVexR << 7;
-    b        |= uVexV << 3;
-    b        |= uVexL << 2;
-    switch (pThis->enmPrefixKind)
+    switch (enmXcptType)
     {
-        case BS3CG1PFXKIND_NO_F2_F3_66:     b |= 0; break;
-        case BS3CG1PFXKIND_REQ_66:          b |= 1; break;
-        case BS3CG1PFXKIND_REQ_F3:          b |= 2; break;
-        case BS3CG1PFXKIND_REQ_F2:          b |= 3; break;
-        default:
-            Bs3TestFailedF("enmPrefixKind=%d not supported for VEX!\n");
-            break;
-    }
-
-    pThis->abCurInstr[offDst]     = 0xc5; /* vex2 */
-    pThis->abCurInstr[offDst + 1] = b;
-    return offDst + 2;
-}
+        case BS3CG1XCPTTYPE_1:
+            return false;
 
+        case BS3CG1XCPTTYPE_NONE:
+        case BS3CG1XCPTTYPE_2:
+        case BS3CG1XCPTTYPE_3:
+        case BS3CG1XCPTTYPE_4:
+        case BS3CG1XCPTTYPE_4UA:
+        case BS3CG1XCPTTYPE_5:
+        case BS3CG1XCPTTYPE_6:
+        case BS3CG1XCPTTYPE_11:
+        case BS3CG1XCPTTYPE_12:
+            return true;
 
-/**
- * Inserts a 3-byte VEX prefix.
- *
- * @returns New offDst value.
- * @param   pThis       The state.
- * @param   offDst      The current instruction offset.
- * @param   uVexL       The VEX.L value.
- * @param   uVexV       The VEX.V value (caller inverted it already).
- * @param   uVexR       The VEX.R value (caller inverted it already).
- * @param   uVexR       The VEX.X value (caller inverted it already).
- * @param   uVexR       The VEX.B value (caller inverted it already).
- * @param   uVexR       The VEX.W value (straight).
- */
-DECLINLINE(unsigned) BS3_NEAR_CODE Bs3Cg1InsertVex3bPrefix(PBS3CG1STATE pThis, unsigned offDst, uint8_t uVexV, uint8_t uVexL,
-                                                           uint8_t uVexR, uint8_t uVexX, uint8_t uVexB, uint8_t uVexW)
-{
-    uint8_t b1;
-    uint8_t b2;
-    b1        = uVexR << 7;
-    b1       |= uVexX << 6;
-    b1       |= uVexB << 5;
-    b1       |= 1; /* VEX.mmmmm = 1*/ /** @todo three byte opcode tables */
-    b2        = uVexV << 3;
-    b2       |= uVexW << 7;
-    b2       |= uVexL << 2;
-    switch (pThis->enmPrefixKind)
-    {
-        case BS3CG1PFXKIND_NO_F2_F3_66:     b2 |= 0; break;
-        case BS3CG1PFXKIND_REQ_66:          b2 |= 1; break;
-        case BS3CG1PFXKIND_REQ_F3:          b2 |= 2; break;
-        case BS3CG1PFXKIND_REQ_F2:          b2 |= 3; break;
         default:
-            Bs3TestFailedF("enmPrefixKind=%d not supported for VEX!\n", pThis->enmPrefixKind);
-            break;
+            return false;
     }
-
-    pThis->abCurInstr[offDst]     = 0xc4; /* vex3 */
-    pThis->abCurInstr[offDst + 1] = b1;
-    pThis->abCurInstr[offDst + 2] = b2;
-    return offDst + 3;
 }
 
 
@@ -1248,12 +1319,12 @@ static void BS3_NEAR_CODE Bs3Cg1EncodeCleanup(PBS3CG1STATE pThis)
 
 
 static unsigned BS3_NEAR_CODE Bs3Cfg1EncodeMemMod0Disp(PBS3CG1STATE pThis, bool fAddrOverride, unsigned off, uint8_t iReg,
-                                                       uint8_t cbOp, uint8_t cbMissalign, BS3CG1OPLOC enmLocation)
+                                                       uint8_t cbOp, uint8_t cbMisalign, BS3CG1OPLOC enmLocation)
 {
     pThis->aOperands[pThis->iRmOp].idxField     = BS3CG1DST_INVALID;
     pThis->aOperands[pThis->iRmOp].enmLocation  = enmLocation;
     pThis->aOperands[pThis->iRmOp].cbOp         = cbOp;
-    pThis->aOperands[pThis->iRmOp].off          = cbOp + cbMissalign;
+    pThis->aOperands[pThis->iRmOp].off          = cbOp + cbMisalign;
 
     if (   BS3_MODE_IS_16BIT_CODE(pThis->bMode)
         || (fAddrOverride && BS3_MODE_IS_32BIT_CODE(pThis->bMode)) )
@@ -1272,13 +1343,13 @@ static unsigned BS3_NEAR_CODE Bs3Cfg1EncodeMemMod0Disp(PBS3CG1STATE pThis, bool
         if (!fAddrOverride || BS3_MODE_IS_32BIT_CODE(pThis->bMode))
         {
             pThis->abCurInstr[off++] = X86_MODRM_MAKE(0, iReg, 6 /*disp16*/);
-            *(uint16_t *)&pThis->abCurInstr[off] = pThis->DataPgFar.off + X86_PAGE_SIZE - cbOp - cbMissalign;
+            *(uint16_t *)&pThis->abCurInstr[off] = pThis->DataPgFar.off + X86_PAGE_SIZE - cbOp - cbMisalign;
             off += 2;
         }
         else
         {
             pThis->abCurInstr[off++] = X86_MODRM_MAKE(0, iReg, 5 /*disp32*/);
-            *(uint32_t *)&pThis->abCurInstr[off] = pThis->DataPgFar.off + X86_PAGE_SIZE - cbOp - cbMissalign;
+            *(uint32_t *)&pThis->abCurInstr[off] = pThis->DataPgFar.off + X86_PAGE_SIZE - cbOp - cbMisalign;
             off += 4;
         }
     }
@@ -1289,18 +1360,20 @@ static unsigned BS3_NEAR_CODE Bs3Cfg1EncodeMemMod0Disp(PBS3CG1STATE pThis, bool
          * or 64-bit code doing either 64-bit or 32-bit addressing.
          */
         pThis->abCurInstr[off++] = X86_MODRM_MAKE(0, iReg, 5 /*disp32*/);
-        *(uint32_t *)&pThis->abCurInstr[off] = BS3_FP_OFF(pThis->pbDataPg) + X86_PAGE_SIZE - cbOp - cbMissalign;
+        *(uint32_t *)&pThis->abCurInstr[off] = BS3_FP_OFF(pThis->pbDataPg) + X86_PAGE_SIZE - cbOp - cbMisalign;
 
+#if ARCH_BITS == 64
         /* In 64-bit mode we always have a rip relative encoding regardless of fAddrOverride. */
-        if (BS3_MODE_IS_64BIT_CODE(pThis->bMode))
+        if (BS3CG1_IS_64BIT_TARGET(pThis))
             *(uint32_t *)&pThis->abCurInstr[off] -= BS3_FP_OFF(&pThis->pbCodePg[X86_PAGE_SIZE]);
+#endif
         off += 4;
     }
 
     /*
      * Fill the memory with 0xcc.
      */
-    switch (cbOp + cbMissalign)
+    switch (cbOp + cbMisalign)
     {
         case 8: pThis->pbDataPg[X86_PAGE_SIZE - 8] = 0xcc;  /* fall thru */
         case 7: pThis->pbDataPg[X86_PAGE_SIZE - 7] = 0xcc;  /* fall thru */
@@ -1313,8 +1386,8 @@ static unsigned BS3_NEAR_CODE Bs3Cfg1EncodeMemMod0Disp(PBS3CG1STATE pThis, bool
         case 0: break;
         default:
         {
-            BS3CG1_DPRINTF(("Bs3MemSet(%p,%#x,%#x)\n", &pThis->pbDataPg[X86_PAGE_SIZE - cbOp - cbMissalign], 0xcc, cbOp - cbMissalign));
-            Bs3MemSet(&pThis->pbDataPg[X86_PAGE_SIZE - cbOp - cbMissalign], 0xcc, cbOp - cbMissalign);
+            BS3CG1_DPRINTF(("Bs3MemSet(%p,%#x,%#x)\n", &pThis->pbDataPg[X86_PAGE_SIZE - cbOp - cbMisalign], 0xcc, cbOp - cbMisalign));
+            Bs3MemSet(&pThis->pbDataPg[X86_PAGE_SIZE - cbOp - cbMisalign], 0xcc, cbOp - cbMisalign);
             break;
         }
     }
@@ -1323,7 +1396,30 @@ static unsigned BS3_NEAR_CODE Bs3Cfg1EncodeMemMod0Disp(PBS3CG1STATE pThis, bool
 }
 
 
-static unsigned BS3_NEAR_CODE Bs3Cg1EncodeNext_BS3CG1ENC_MODRM_Eb_Gb(PBS3CG1STATE pThis, unsigned iEncoding)
+#if 0 /* unused */
+/** Also encodes idxField of the register operand using idxFieldBase.   */
+static unsigned BS3_NEAR_CODE
+Bs3Cfg1EncodeMemMod0DispWithRegField(PBS3CG1STATE pThis, bool fAddrOverride, unsigned off, uint8_t iReg,
+                                     uint8_t cbOp, uint8_t cbMisalign, BS3CG1OPLOC enmLocation)
+{
+    pThis->aOperands[pThis->iRegOp].idxField = pThis->aOperands[pThis->iRegOp].idxFieldBase + iReg;
+    return Bs3Cfg1EncodeMemMod0Disp(pThis, fAddrOverride, off, iReg & 7, cbOp, cbMisalign, enmLocation);
+}
+#endif
+
+/** Also encodes idxField of the register operand using idxFieldBase.   */
+static unsigned BS3_NEAR_CODE
+Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(PBS3CG1STATE pThis, bool fAddrOverride, unsigned off,
+                                                uint8_t iReg, uint8_t cbMisalign)
+{
+    pThis->aOperands[pThis->iRegOp].idxField = pThis->aOperands[pThis->iRegOp].idxFieldBase + iReg;
+    return Bs3Cfg1EncodeMemMod0Disp(pThis, fAddrOverride, off, iReg & 7, pThis->aOperands[pThis->iRmOp].cbOp, cbMisalign,
+                                    pThis->aOperands[pThis->iRmOp].enmLocation);
+}
+
+
+
+static unsigned BS3_NEAR_CODE Bs3Cg1EncodeNext_MODRM_Eb_Gb(PBS3CG1STATE pThis, unsigned iEncoding)
 {
     unsigned off;
     /* Start by reg,reg encoding. */
@@ -1354,7 +1450,7 @@ static unsigned BS3_NEAR_CODE Bs3Cg1EncodeNext_BS3CG1ENC_MODRM_Eb_Gb(PBS3CG1STAT
 }
 
 
-static unsigned BS3_NEAR_CODE Bs3Cg1EncodeNext_BS3CG1ENC_MODRM_Gb_Eb(PBS3CG1STATE pThis, unsigned iEncoding)
+static unsigned BS3_NEAR_CODE Bs3Cg1EncodeNext_MODRM_Gb_Eb(PBS3CG1STATE pThis, unsigned iEncoding)
 {
     unsigned off;
     /* Start by reg,reg encoding. */
@@ -1385,7 +1481,8 @@ static unsigned BS3_NEAR_CODE Bs3Cg1EncodeNext_BS3CG1ENC_MODRM_Gb_Eb(PBS3CG1STAT
 }
 
 
-static unsigned BS3_NEAR_CODE Bs3Cg1EncodeNext_BS3CG1ENC_MODRM_Gv_Ev__OR__BS3CG1ENC_MODRM_Ev_Gv(PBS3CG1STATE pThis, unsigned iEncoding)
+static unsigned BS3_NEAR_CODE Bs3Cg1EncodeNext_MODRM_Gv_Ev__OR__MODRM_Ev_Gv(PBS3CG1STATE pThis,
+                                                                                                unsigned iEncoding)
 {
     unsigned off;
     unsigned cbOp;
@@ -1403,7 +1500,7 @@ static unsigned BS3_NEAR_CODE Bs3Cg1EncodeNext_BS3CG1ENC_MODRM_Gv_Ev__OR__BS3CG1
         pThis->aOperands[pThis->iRegOp].idxField    = BS3CG1DST_OZ_RBP;
         off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 0));
         off = Bs3Cfg1EncodeMemMod0Disp(pThis, false, off, X86_GREG_xBP, cbOp, 0,
-                                       pThis->enmEncoding == BS3CG1ENC_MODRM_Gv_Ev ? BS3CG1OPLOC_MEM : BS3CG1OPLOC_MEM_RW);
+                                       pThis->enmEncoding == BS3CG1ENC_MODRM_Gv_Ev ? BS3CG1OPLOC_MEM : BS3CG1OPLOC_MEM_WO);
     }
     else if (iEncoding == 2 && (g_uBs3CpuDetected & BS3CPU_TYPE_MASK) >= BS3CPU_80386)
     {
@@ -1422,7 +1519,7 @@ static unsigned BS3_NEAR_CODE Bs3Cg1EncodeNext_BS3CG1ENC_MODRM_Gv_Ev__OR__BS3CG1
         pThis->abCurInstr[0] = P_OZ;
         off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 1));
         off = Bs3Cfg1EncodeMemMod0Disp(pThis, false, off, X86_GREG_xSI, cbOp, 0,
-                                       pThis->enmEncoding == BS3CG1ENC_MODRM_Gv_Ev ? BS3CG1OPLOC_MEM : BS3CG1OPLOC_MEM_RW);
+                                       pThis->enmEncoding == BS3CG1ENC_MODRM_Gv_Ev ? BS3CG1OPLOC_MEM : BS3CG1OPLOC_MEM_WO);
     }
     else if (iEncoding == 4)
     {
@@ -1431,7 +1528,7 @@ static unsigned BS3_NEAR_CODE Bs3Cg1EncodeNext_BS3CG1ENC_MODRM_Gv_Ev__OR__BS3CG1
         pThis->abCurInstr[0] = P_AZ;
         off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 1));
         off = Bs3Cfg1EncodeMemMod0Disp(pThis, true, off, X86_GREG_xDI, cbOp, 0,
-                                       pThis->enmEncoding == BS3CG1ENC_MODRM_Gv_Ev ? BS3CG1OPLOC_MEM : BS3CG1OPLOC_MEM_RW);
+                                       pThis->enmEncoding == BS3CG1ENC_MODRM_Gv_Ev ? BS3CG1OPLOC_MEM : BS3CG1OPLOC_MEM_WO);
     }
     else if (iEncoding == 5)
     {
@@ -1441,9 +1538,9 @@ static unsigned BS3_NEAR_CODE Bs3Cg1EncodeNext_BS3CG1ENC_MODRM_Gv_Ev__OR__BS3CG1
         pThis->abCurInstr[1] = P_AZ;
         off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 2));
         off = Bs3Cfg1EncodeMemMod0Disp(pThis, true, off, X86_GREG_xSI, cbOp, 0,
-                                       pThis->enmEncoding == BS3CG1ENC_MODRM_Gv_Ev ? BS3CG1OPLOC_MEM : BS3CG1OPLOC_MEM_RW);
+                                       pThis->enmEncoding == BS3CG1ENC_MODRM_Gv_Ev ? BS3CG1OPLOC_MEM : BS3CG1OPLOC_MEM_WO);
     }
-    else if (iEncoding == 6 && BS3_MODE_IS_64BIT_CODE(pThis->bMode))
+    else if (iEncoding == 6 && BS3CG1_IS_64BIT_TARGET(pThis))
     {
         cbOp = 8;
         off = Bs3Cg1InsertReqPrefix(pThis, 0);
@@ -1464,7 +1561,7 @@ static unsigned BS3_NEAR_CODE Bs3Cg1EncodeNext_BS3CG1ENC_MODRM_Gv_Ev__OR__BS3CG1
 }
 
 
-static unsigned BS3_NEAR_CODE Bs3Cg1EncodeNext_BS3CG1ENC_MODRM_Wss_Vss(PBS3CG1STATE pThis, unsigned iEncoding)
+static unsigned BS3_NEAR_CODE Bs3Cg1EncodeNext_MODRM_Wss_WO_Vss(PBS3CG1STATE pThis, unsigned iEncoding)
 {
     unsigned off;
     if (iEncoding == 0)
@@ -1478,13 +1575,13 @@ static unsigned BS3_NEAR_CODE Bs3Cg1EncodeNext_BS3CG1ENC_MODRM_Wss_Vss(PBS3CG1ST
     {
         pThis->aOperands[pThis->iRegOp].idxField = BS3CG1DST_XMM2_DW0;
         off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 0));
-        off = Bs3Cfg1EncodeMemMod0Disp(pThis, false, off, 2 /*iReg*/, 4, 0, BS3CG1OPLOC_MEM_RW);
+        off = Bs3Cfg1EncodeMemMod0Disp(pThis, false, off, 2 /*iReg*/, 4, 0, BS3CG1OPLOC_MEM_WO);
     }
     else if (iEncoding == 2)
     {
         pThis->aOperands[pThis->iRegOp].idxField = BS3CG1DST_XMM3_DW0;
         off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 0));
-        off = Bs3Cfg1EncodeMemMod0Disp(pThis, false, off, 3 /*iReg*/, 4, 1 /*cbMissalign*/, BS3CG1OPLOC_MEM_RW);
+        off = Bs3Cfg1EncodeMemMod0Disp(pThis, false, off, 3 /*iReg*/, 4, 1 /*cbMisalign*/, BS3CG1OPLOC_MEM_WO);
     }
     else
         return 0;
@@ -1493,7 +1590,7 @@ static unsigned BS3_NEAR_CODE Bs3Cg1EncodeNext_BS3CG1ENC_MODRM_Wss_Vss(PBS3CG1ST
 }
 
 
-static unsigned BS3_NEAR_CODE Bs3Cg1EncodeNext_BS3CG1ENC_MODRM_Wsd_Vsd(PBS3CG1STATE pThis, unsigned iEncoding)
+static unsigned BS3_NEAR_CODE Bs3Cg1EncodeNext_MODRM_Wsd_WO_Vsd(PBS3CG1STATE pThis, unsigned iEncoding)
 {
     unsigned off;
     if (iEncoding == 0)
@@ -1507,13 +1604,13 @@ static unsigned BS3_NEAR_CODE Bs3Cg1EncodeNext_BS3CG1ENC_MODRM_Wsd_Vsd(PBS3CG1ST
     {
         pThis->aOperands[pThis->iRegOp].idxField = BS3CG1DST_XMM2_LO;
         off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 0));
-        off = Bs3Cfg1EncodeMemMod0Disp(pThis, false, off, 2 /*iReg*/, 8, 0, BS3CG1OPLOC_MEM_RW);
+        off = Bs3Cfg1EncodeMemMod0Disp(pThis, false, off, 2 /*iReg*/, 8, 0, BS3CG1OPLOC_MEM_WO);
     }
     else if (iEncoding == 2)
     {
         pThis->aOperands[pThis->iRegOp].idxField = BS3CG1DST_XMM3_LO;
         off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 0));
-        off = Bs3Cfg1EncodeMemMod0Disp(pThis, false, off, 3 /*iReg*/, 8, 1 /*cbMissalign*/, BS3CG1OPLOC_MEM_RW);
+        off = Bs3Cfg1EncodeMemMod0Disp(pThis, false, off, 3 /*iReg*/, 8, 1 /*cbMisalign*/, BS3CG1OPLOC_MEM_WO);
     }
     else
         return 0;
@@ -1522,7 +1619,7 @@ static unsigned BS3_NEAR_CODE Bs3Cg1EncodeNext_BS3CG1ENC_MODRM_Wsd_Vsd(PBS3CG1ST
 }
 
 
-static unsigned BS3_NEAR_CODE Bs3Cg1EncodeNext_BS3CG1ENC_MODRM_Wps_Vps__OR__BS3CG1ENC_MODRM_Wpd_Vpd(PBS3CG1STATE pThis, unsigned iEncoding)
+static unsigned BS3_NEAR_CODE Bs3Cg1EncodeNext_MODRM_Wps_WO_Vps__OR__MODRM_Wpd_WO_Vpd(PBS3CG1STATE pThis, unsigned iEncoding)
 {
     unsigned off;
     if (iEncoding == 0)
@@ -1536,13 +1633,13 @@ static unsigned BS3_NEAR_CODE Bs3Cg1EncodeNext_BS3CG1ENC_MODRM_Wps_Vps__OR__BS3C
     {
         pThis->aOperands[pThis->iRegOp].idxField = BS3CG1DST_XMM2;
         off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 0));
-        off = Bs3Cfg1EncodeMemMod0Disp(pThis, false, off, 2 /*iReg*/, 16, 0, BS3CG1OPLOC_MEM_RW);
+        off = Bs3Cfg1EncodeMemMod0Disp(pThis, false, off, 2 /*iReg*/, 16, 0, BS3CG1OPLOC_MEM_WO);
     }
     else if (iEncoding == 2)
     {
         pThis->aOperands[pThis->iRegOp].idxField = BS3CG1DST_XMM3;
         off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 0));
-        off = Bs3Cfg1EncodeMemMod0Disp(pThis, false, off, 3 /*iReg*/, 16, 1 /*cbMissalign*/, BS3CG1OPLOC_MEM_RW);
+        off = Bs3Cfg1EncodeMemMod0Disp(pThis, false, off, 3 /*iReg*/, 16, 1 /*cbMisalign*/, BS3CG1OPLOC_MEM_WO);
         if (!Bs3Cg1XcptTypeIsUnaligned(pThis->enmXcptType))
             pThis->bAlignmentXcpt = X86_XCPT_GP;
     }
@@ -1553,7 +1650,7 @@ static unsigned BS3_NEAR_CODE Bs3Cg1EncodeNext_BS3CG1ENC_MODRM_Wps_Vps__OR__BS3C
 }
 
 
-static unsigned BS3_NEAR_CODE Bs3Cg1EncodeNext_BS3CG1ENC_MODRM_WqZxReg_Vq(PBS3CG1STATE pThis, unsigned iEncoding)
+static unsigned BS3_NEAR_CODE Bs3Cg1EncodeNext_MODRM_WqZxReg_WO_Vq(PBS3CG1STATE pThis, unsigned iEncoding)
 {
     unsigned off;
     if (iEncoding == 0)
@@ -1567,13 +1664,95 @@ static unsigned BS3_NEAR_CODE Bs3Cg1EncodeNext_BS3CG1ENC_MODRM_WqZxReg_Vq(PBS3CG
     {
         pThis->aOperands[pThis->iRegOp].idxField = BS3CG1DST_XMM2_LO;
         off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 0));
-        off = Bs3Cfg1EncodeMemMod0Disp(pThis, false, off, 2 /*iReg*/, 8, 0, BS3CG1OPLOC_MEM_RW);
+        off = Bs3Cfg1EncodeMemMod0Disp(pThis, false, off, 2 /*iReg*/, 8, 0, BS3CG1OPLOC_MEM_WO);
     }
     else if (iEncoding == 2)
     {
         pThis->aOperands[pThis->iRegOp].idxField = BS3CG1DST_XMM3_LO;
         off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 0));
-        off = Bs3Cfg1EncodeMemMod0Disp(pThis, false, off, 3 /*iReg*/, 8, 1 /*cbMissalign*/, BS3CG1OPLOC_MEM_RW);
+        off = Bs3Cfg1EncodeMemMod0Disp(pThis, false, off, 3 /*iReg*/, 8, 1 /*cbMisalign*/, BS3CG1OPLOC_MEM_WO);
+    }
+    else
+        return 0;
+    pThis->cbCurInstr = off;
+    return iEncoding + 1;
+}
+
+
+static unsigned BS3_NEAR_CODE Bs3Cg1EncodeNext_MODRM_Pq_WO_Qq(PBS3CG1STATE pThis, unsigned iEncoding)
+{
+    unsigned off;
+    switch (iEncoding)
+    {
+        case 0:
+            pThis->aOperands[pThis->iRmOp ].enmLocation = pThis->aOperands[pThis->iRmOp].enmLocationReg;
+            off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 0));
+            pThis->abCurInstr[off++] = X86_MODRM_MAKE(3, 1, 0);
+            pThis->aOperands[pThis->iRmOp ].idxField = pThis->aOperands[pThis->iRmOp ].idxFieldBase + 0;
+            pThis->aOperands[pThis->iRegOp].idxField = pThis->aOperands[pThis->iRegOp].idxFieldBase + 1;
+            break;
+        case 1:
+            pThis->aOperands[pThis->iRmOp ].enmLocation = pThis->aOperands[pThis->iRmOp].enmLocationReg;
+            off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 0));
+            pThis->abCurInstr[off++] = X86_MODRM_MAKE(3, 4, 7);
+            pThis->aOperands[pThis->iRmOp ].idxField = pThis->aOperands[pThis->iRmOp ].idxFieldBase + 7;
+            pThis->aOperands[pThis->iRegOp].idxField = pThis->aOperands[pThis->iRegOp].idxFieldBase + 4;
+            iEncoding += !BS3CG1_IS_64BIT_TARGET(pThis) ? 1 : 0;
+            break;
+#if ARCH_BITS == 64
+        case 2:
+            off = Bs3Cg1InsertReqPrefix(pThis, 0);
+            pThis->abCurInstr[off++] = REX__RBX;
+            off = Bs3Cg1InsertOpcodes(pThis, off);
+            pThis->abCurInstr[off++] = X86_MODRM_MAKE(3, 6, 2);
+            pThis->aOperands[pThis->iRmOp ].idxField = pThis->aOperands[pThis->iRmOp ].idxFieldBase + 2; /* no +8*/
+            pThis->aOperands[pThis->iRegOp].idxField = pThis->aOperands[pThis->iRegOp].idxFieldBase + 6; /* no +8*/
+            break;
+#endif
+        case 3:
+            pThis->aOperands[pThis->iRmOp ].enmLocation = pThis->aOperands[pThis->iRmOp].enmLocationMem;
+            off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 0));
+            off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, false, off, 4 /*iReg*/, 0 /*cbMisalign*/);
+            break;
+        case 4:
+            off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 0));
+            off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, false, off, 7 /*iReg*/, 1 /*cbMisalign*/);
+            iEncoding += !BS3CG1_IS_64BIT_TARGET(pThis) ? 1 : 0;
+            break;
+#if ARCH_BITS == 64
+        case 5:
+            off = Bs3Cg1InsertReqPrefix(pThis, 0);
+            pThis->abCurInstr[off++] = REX__RBX;
+            off = Bs3Cg1InsertOpcodes(pThis, off);
+            off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, false, off, 7 /*iReg - no +8*/, 0 /*cbMisalign*/);
+            break;
+#endif
+
+        default:
+            return 0;
+    }
+
+    pThis->cbCurInstr = off;
+    return iEncoding + 1;
+}
+
+
+static unsigned BS3_NEAR_CODE Bs3Cg1EncodeNext_MODRM_Pq_WO_Uq(PBS3CG1STATE pThis, unsigned iEncoding)
+{
+    unsigned off;
+    if (iEncoding == 0)
+    {
+        off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 0));
+        pThis->abCurInstr[off++] = X86_MODRM_MAKE(3, 1, 0);
+        pThis->aOperands[pThis->iRmOp ].idxField = BS3CG1DST_XMM0_LO;
+        pThis->aOperands[pThis->iRegOp].idxField = BS3CG1DST_MM1;
+    }
+    else if (iEncoding == 1)
+    {
+        off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 0));
+        pThis->abCurInstr[off++] = X86_MODRM_MAKE(3, 6, 2);
+        pThis->aOperands[pThis->iRmOp ].idxField = BS3CG1DST_XMM2_LO;
+        pThis->aOperands[pThis->iRegOp].idxField = BS3CG1DST_MM6;
     }
     else
         return 0;
@@ -1582,7 +1761,249 @@ static unsigned BS3_NEAR_CODE Bs3Cg1EncodeNext_BS3CG1ENC_MODRM_WqZxReg_Vq(PBS3CG
 }
 
 
-static unsigned BS3_NEAR_CODE Bs3Cg1EncodeNext_BS3CG1ENC_MODRM_Vq_UqHi(PBS3CG1STATE pThis, unsigned iEncoding)
+static unsigned BS3_NEAR_CODE Bs3Cg1EncodeNext_MODRM_PdZx_WO_Ed_WZ(PBS3CG1STATE pThis, unsigned iEncoding)
+{
+    unsigned off;
+    switch (iEncoding)
+    {
+        case 0:
+            pThis->aOperands[pThis->iRmOp ].enmLocation = pThis->aOperands[pThis->iRmOp].enmLocationReg;
+            off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 0));
+            pThis->abCurInstr[off++] = X86_MODRM_MAKE(3, 1, 0);
+            pThis->aOperands[pThis->iRmOp ].idxField = pThis->aOperands[pThis->iRmOp ].idxFieldBase + 0;
+            pThis->aOperands[pThis->iRegOp].idxField = pThis->aOperands[pThis->iRegOp].idxFieldBase + 1;
+            break;
+        case 1:
+            off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 0));
+            pThis->abCurInstr[off++] = X86_MODRM_MAKE(3, 6, 2);
+            pThis->aOperands[pThis->iRmOp ].idxField = pThis->aOperands[pThis->iRmOp ].idxFieldBase + 2;
+            pThis->aOperands[pThis->iRegOp].idxField = pThis->aOperands[pThis->iRegOp].idxFieldBase + 6;
+            iEncoding += !BS3CG1_IS_64BIT_TARGET(pThis) ? 1 : 0;
+            break;
+#if ARCH_BITS == 64
+        case 2:
+            off = Bs3Cg1InsertReqPrefix(pThis, 0);
+            pThis->abCurInstr[off++] = REX__RBX;
+            off = Bs3Cg1InsertOpcodes(pThis, off);
+            pThis->abCurInstr[off++] = X86_MODRM_MAKE(3, 6, 2);
+            pThis->aOperands[pThis->iRmOp ].idxField = pThis->aOperands[pThis->iRmOp ].idxFieldBase + 2 + 8;
+            pThis->aOperands[pThis->iRegOp].idxField = pThis->aOperands[pThis->iRegOp].idxFieldBase + 6; /* no +8*/
+            break;
+#endif
+        case 3:
+            pThis->aOperands[pThis->iRmOp ].enmLocation = pThis->aOperands[pThis->iRmOp].enmLocationMem;
+            off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 0));
+            off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, false, off, 4 /*iReg*/, 0 /*cbMisalign*/);
+            break;
+        case 4:
+            off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 0));
+            off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, false, off, 7 /*iReg*/, 1 /*cbMisalign*/);
+            iEncoding += !BS3CG1_IS_64BIT_TARGET(pThis) ? 1 : 0;
+            break;
+#if ARCH_BITS == 64
+        case 5:
+            off = Bs3Cg1InsertReqPrefix(pThis, 0);
+            pThis->abCurInstr[off++] = REX__RBX;
+            off = Bs3Cg1InsertOpcodes(pThis, off);
+            off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, false, off, 7 /*iReg*/, 0 /*cbMisalign*/);
+            break;
+#endif
+
+        default:
+            return 0;
+    }
+    pThis->cbCurInstr = off;
+    return iEncoding + 1;
+}
+
+
+static unsigned BS3_NEAR_CODE Bs3Cg1EncodeNext_MODRM_Pq_WO_Eq_WNZ(PBS3CG1STATE pThis, unsigned iEncoding)
+{
+#if ARCH_BITS == 64
+    if (BS3CG1_IS_64BIT_TARGET(pThis))
+    {
+        unsigned off;
+        switch (iEncoding)
+        {
+            case 0:
+                pThis->aOperands[pThis->iRmOp ].enmLocation = pThis->aOperands[pThis->iRmOp].enmLocationReg;
+                off = Bs3Cg1InsertReqPrefix(pThis, 0);
+                pThis->abCurInstr[off++] = REX_W___;
+                off = Bs3Cg1InsertOpcodes(pThis, off);
+                pThis->abCurInstr[off++] = X86_MODRM_MAKE(3, 1, 0);
+                pThis->aOperands[pThis->iRmOp ].idxField = pThis->aOperands[pThis->iRmOp ].idxFieldBase + 0;
+                pThis->aOperands[pThis->iRegOp].idxField = pThis->aOperands[pThis->iRegOp].idxFieldBase + 1;
+                break;
+            case 1:
+                off = Bs3Cg1InsertReqPrefix(pThis, 0);
+                pThis->abCurInstr[off++] = REX_W___;
+                off = Bs3Cg1InsertOpcodes(pThis, off);
+                pThis->abCurInstr[off++] = X86_MODRM_MAKE(3, 6, 2);
+                pThis->aOperands[pThis->iRmOp ].idxField = pThis->aOperands[pThis->iRmOp ].idxFieldBase + 2;
+                pThis->aOperands[pThis->iRegOp].idxField = pThis->aOperands[pThis->iRegOp].idxFieldBase + 6;
+                break;
+            case 2:
+                off = Bs3Cg1InsertReqPrefix(pThis, 0);
+                pThis->abCurInstr[off++] = REX_WRBX;
+                off = Bs3Cg1InsertOpcodes(pThis, off);
+                pThis->abCurInstr[off++] = X86_MODRM_MAKE(3, 6, 2);
+                pThis->aOperands[pThis->iRmOp ].idxField = pThis->aOperands[pThis->iRmOp ].idxFieldBase + 2 + 8;
+                pThis->aOperands[pThis->iRegOp].idxField = pThis->aOperands[pThis->iRegOp].idxFieldBase + 6; /* no +8*/
+                break;
+            case 3:
+                pThis->aOperands[pThis->iRmOp ].enmLocation = pThis->aOperands[pThis->iRmOp].enmLocationMem;
+                off = Bs3Cg1InsertReqPrefix(pThis, 0);
+                pThis->abCurInstr[off++] = REX_W___;
+                off = Bs3Cg1InsertOpcodes(pThis, off);
+                off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, false, off, 4 /*iReg*/, 0 /*cbMisalign*/);
+                break;
+            case 4:
+                off = Bs3Cg1InsertReqPrefix(pThis, 0);
+                pThis->abCurInstr[off++] = REX_W___;
+                off = Bs3Cg1InsertOpcodes(pThis, off);
+                off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, false, off, 7 /*iReg*/, 1 /*cbMisalign*/);
+                break;
+            case 5:
+                off = Bs3Cg1InsertReqPrefix(pThis, 0);
+                pThis->abCurInstr[off++] = REX_WRBX;
+                off = Bs3Cg1InsertOpcodes(pThis, off);
+                off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, false, off, 7 /*iReg*/, 0 /*cbMisalign*/);
+                break;
+
+            default:
+                return 0;
+        }
+        pThis->cbCurInstr = off;
+        return iEncoding + 1;
+    }
+#endif
+    return 0;
+}
+
+
+/* Differs from Bs3Cg1EncodeNext_MODRM_PdZx_WO_Ed_WZ in that REX.R isn't ignored. */
+static unsigned BS3_NEAR_CODE Bs3Cg1EncodeNext_MODRM_Vd_WO_Ed_WZ(PBS3CG1STATE pThis, unsigned iEncoding)
+{
+    unsigned off;
+    switch (iEncoding)
+    {
+        case 0:
+            pThis->aOperands[pThis->iRmOp ].enmLocation = pThis->aOperands[pThis->iRmOp].enmLocationReg;
+            off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 0));
+            pThis->abCurInstr[off++] = X86_MODRM_MAKE(3, 1, 0);
+            pThis->aOperands[pThis->iRmOp ].idxField = pThis->aOperands[pThis->iRmOp ].idxFieldBase + 0;
+            pThis->aOperands[pThis->iRegOp].idxField = pThis->aOperands[pThis->iRegOp].idxFieldBase + 1;
+            break;
+        case 1:
+            off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 0));
+            pThis->abCurInstr[off++] = X86_MODRM_MAKE(3, 6, 2);
+            pThis->aOperands[pThis->iRmOp ].idxField = pThis->aOperands[pThis->iRmOp ].idxFieldBase + 2;
+            pThis->aOperands[pThis->iRegOp].idxField = pThis->aOperands[pThis->iRegOp].idxFieldBase + 6;
+            iEncoding += !BS3CG1_IS_64BIT_TARGET(pThis) ? 1 : 0;
+            break;
+#if ARCH_BITS == 64
+        case 2:
+            off = Bs3Cg1InsertReqPrefix(pThis, 0);
+            pThis->abCurInstr[off++] = REX__RBX;
+            off = Bs3Cg1InsertOpcodes(pThis, off);
+            pThis->abCurInstr[off++] = X86_MODRM_MAKE(3, 6, 2);
+            pThis->aOperands[pThis->iRmOp ].idxField = pThis->aOperands[pThis->iRmOp ].idxFieldBase + 2 + 8;
+            pThis->aOperands[pThis->iRegOp].idxField = pThis->aOperands[pThis->iRegOp].idxFieldBase + 6 + 8;
+            break;
+#endif
+        case 3:
+            pThis->aOperands[pThis->iRmOp ].enmLocation = pThis->aOperands[pThis->iRmOp].enmLocationMem;
+            off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 0));
+            off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, false, off, 4 /*iReg*/, 0 /*cbMisalign*/);
+            break;
+        case 4:
+            off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 0));
+            off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, false, off, 7 /*iReg*/, 1 /*cbMisalign*/);
+            iEncoding += !BS3CG1_IS_64BIT_TARGET(pThis) ? 1 : 0;
+            break;
+#if ARCH_BITS == 64
+        case 5:
+            off = Bs3Cg1InsertReqPrefix(pThis, 0);
+            pThis->abCurInstr[off++] = REX__RBX;
+            off = Bs3Cg1InsertOpcodes(pThis, off);
+            off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, false, off, 7+8 /*iReg*/, 0 /*cbMisalign*/);
+            break;
+#endif
+
+        default:
+            return 0;
+    }
+    pThis->cbCurInstr = off;
+    return iEncoding + 1;
+}
+
+
+/* Differs from Bs3Cg1EncodeNext_MODRM_Pq_WO_Eq_WNZ in that REX.R isn't ignored. */
+static unsigned BS3_NEAR_CODE Bs3Cg1EncodeNext_MODRM_Vq_WO_Eq_WNZ(PBS3CG1STATE pThis, unsigned iEncoding)
+{
+#if ARCH_BITS == 64
+    if (BS3CG1_IS_64BIT_TARGET(pThis))
+    {
+        unsigned off;
+        switch (iEncoding)
+        {
+            case 0:
+                pThis->aOperands[pThis->iRmOp ].enmLocation = pThis->aOperands[pThis->iRmOp].enmLocationReg;
+                off = Bs3Cg1InsertReqPrefix(pThis, 0);
+                pThis->abCurInstr[off++] = REX_W___;
+                off = Bs3Cg1InsertOpcodes(pThis, off);
+                pThis->abCurInstr[off++] = X86_MODRM_MAKE(3, 1, 0);
+                pThis->aOperands[pThis->iRmOp ].idxField = pThis->aOperands[pThis->iRmOp ].idxFieldBase + 0;
+                pThis->aOperands[pThis->iRegOp].idxField = pThis->aOperands[pThis->iRegOp].idxFieldBase + 1;
+                break;
+            case 1:
+                off = Bs3Cg1InsertReqPrefix(pThis, 0);
+                pThis->abCurInstr[off++] = REX_W___;
+                off = Bs3Cg1InsertOpcodes(pThis, off);
+                pThis->abCurInstr[off++] = X86_MODRM_MAKE(3, 6, 2);
+                pThis->aOperands[pThis->iRmOp ].idxField = pThis->aOperands[pThis->iRmOp ].idxFieldBase + 2;
+                pThis->aOperands[pThis->iRegOp].idxField = pThis->aOperands[pThis->iRegOp].idxFieldBase + 6;
+                break;
+            case 2:
+                off = Bs3Cg1InsertReqPrefix(pThis, 0);
+                pThis->abCurInstr[off++] = REX_WRBX;
+                off = Bs3Cg1InsertOpcodes(pThis, off);
+                pThis->abCurInstr[off++] = X86_MODRM_MAKE(3, 6, 2);
+                pThis->aOperands[pThis->iRmOp ].idxField = pThis->aOperands[pThis->iRmOp ].idxFieldBase + 2 + 8;
+                pThis->aOperands[pThis->iRegOp].idxField = pThis->aOperands[pThis->iRegOp].idxFieldBase + 6 + 8;
+                break;
+            case 4:
+                pThis->aOperands[pThis->iRmOp ].enmLocation = pThis->aOperands[pThis->iRmOp].enmLocationMem;
+                off = Bs3Cg1InsertReqPrefix(pThis, 0);
+                pThis->abCurInstr[off++] = REX_W___;
+                off = Bs3Cg1InsertOpcodes(pThis, off);
+                off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, false, off, 4 /*iReg*/, 0 /*cbMisalign*/);
+                break;
+            case 5:
+                off = Bs3Cg1InsertReqPrefix(pThis, 0);
+                pThis->abCurInstr[off++] = REX_W___;
+                off = Bs3Cg1InsertOpcodes(pThis, off);
+                off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, false, off, 7 /*iReg*/, 1 /*cbMisalign*/);
+                break;
+            case 6:
+                off = Bs3Cg1InsertReqPrefix(pThis, 0);
+                pThis->abCurInstr[off++] = REX_WRBX;
+                off = Bs3Cg1InsertOpcodes(pThis, off);
+                off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, false, off, 7+8 /*iReg*/, 0 /*cbMisalign*/);
+                break;
+
+            default:
+                return 0;
+        }
+        pThis->cbCurInstr = off;
+        return iEncoding + 1;
+    }
+#endif
+    return 0;
+}
+
+
+static unsigned BS3_NEAR_CODE Bs3Cg1EncodeNext_MODRM_Vq_WO_UqHi(PBS3CG1STATE pThis, unsigned iEncoding)
 {
     unsigned off;
     if (iEncoding == 0)
@@ -1606,7 +2027,7 @@ static unsigned BS3_NEAR_CODE Bs3Cg1EncodeNext_BS3CG1ENC_MODRM_Vq_UqHi(PBS3CG1ST
 }
 
 
-static unsigned BS3_NEAR_CODE Bs3Cg1EncodeNext_BS3CG1ENC_MODRM_Vq_Mq(PBS3CG1STATE pThis, unsigned iEncoding)
+static unsigned BS3_NEAR_CODE Bs3Cg1EncodeNext_MODRM_Vq_WO_Mq(PBS3CG1STATE pThis, unsigned iEncoding)
 {
     unsigned off;
     if (iEncoding == 0)
@@ -1619,7 +2040,7 @@ static unsigned BS3_NEAR_CODE Bs3Cg1EncodeNext_BS3CG1ENC_MODRM_Vq_Mq(PBS3CG1STAT
     {
         pThis->aOperands[pThis->iRegOp].idxField = BS3CG1DST_XMM3_LO;
         off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 0));
-        off = Bs3Cfg1EncodeMemMod0Disp(pThis, false, off, 3 /*iReg*/, 8, 1 /*cbMissalign*/, BS3CG1OPLOC_MEM);
+        off = Bs3Cfg1EncodeMemMod0Disp(pThis, false, off, 3 /*iReg*/, 8, 1 /*cbMisalign*/, BS3CG1OPLOC_MEM);
     }
     else
         return 0;
@@ -1628,29 +2049,22 @@ static unsigned BS3_NEAR_CODE Bs3Cg1EncodeNext_BS3CG1ENC_MODRM_Vq_Mq(PBS3CG1STAT
 }
 
 
-static unsigned BS3_NEAR_CODE Bs3Cg1EncodeNext_BS3CG1ENC_MODRM_Vdq_Wdq(PBS3CG1STATE pThis, unsigned iEncoding)
+static unsigned BS3_NEAR_CODE Bs3Cg1EncodeNext_MODRM_VqHi_WO_Uq(PBS3CG1STATE pThis, unsigned iEncoding)
 {
     unsigned off;
     if (iEncoding == 0)
     {
         off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 0));
         pThis->abCurInstr[off++] = X86_MODRM_MAKE(3, 1, 0);
-        pThis->aOperands[pThis->iRmOp ].idxField = BS3CG1DST_XMM0;
-        pThis->aOperands[pThis->iRegOp].idxField = BS3CG1DST_XMM1;
+        pThis->aOperands[pThis->iRmOp ].idxField = BS3CG1DST_XMM0_LO;
+        pThis->aOperands[pThis->iRegOp].idxField = BS3CG1DST_XMM1_HI;
     }
     else if (iEncoding == 1)
     {
-        pThis->aOperands[pThis->iRegOp].idxField = BS3CG1DST_XMM2;
-        off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 0));
-        off = Bs3Cfg1EncodeMemMod0Disp(pThis, false, off, 2 /*iReg*/, 16, 0, BS3CG1OPLOC_MEM);
-    }
-    else if (iEncoding == 2)
-    {
-        pThis->aOperands[pThis->iRegOp].idxField = BS3CG1DST_XMM3;
         off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 0));
-        off = Bs3Cfg1EncodeMemMod0Disp(pThis, false, off, 3 /*iReg*/, 16, 1 /*cbMissalign*/, BS3CG1OPLOC_MEM);
-        if (!Bs3Cg1XcptTypeIsUnaligned(pThis->enmXcptType))
-            pThis->bAlignmentXcpt = X86_XCPT_GP;
+        pThis->abCurInstr[off++] = X86_MODRM_MAKE(3, 2, 2);
+        pThis->aOperands[pThis->iRmOp ].idxField = BS3CG1DST_XMM2_LO;
+        pThis->aOperands[pThis->iRegOp].idxField = BS3CG1DST_XMM2_HI;
     }
     else
         return 0;
@@ -1659,27 +2073,20 @@ static unsigned BS3_NEAR_CODE Bs3Cg1EncodeNext_BS3CG1ENC_MODRM_Vdq_Wdq(PBS3CG1ST
 }
 
 
-static unsigned BS3_NEAR_CODE Bs3Cg1EncodeNext_BS3CG1ENC_MODRM_VssZxReg_Wss(PBS3CG1STATE pThis, unsigned iEncoding)
+static unsigned BS3_NEAR_CODE Bs3Cg1EncodeNext_MODRM_VqHi_WO_Mq(PBS3CG1STATE pThis, unsigned iEncoding)
 {
     unsigned off;
     if (iEncoding == 0)
     {
+        pThis->aOperands[pThis->iRegOp].idxField = BS3CG1DST_XMM2_HI;
         off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 0));
-        pThis->abCurInstr[off++] = X86_MODRM_MAKE(3, 1, 0);
-        pThis->aOperands[pThis->iRmOp ].idxField = BS3CG1DST_XMM0_LO;
-        pThis->aOperands[pThis->iRegOp].idxField = BS3CG1DST_XMM1_DW0_ZX;
+        off = Bs3Cfg1EncodeMemMod0Disp(pThis, false, off, 2 /*iReg*/, 8, 0, BS3CG1OPLOC_MEM);
     }
     else if (iEncoding == 1)
     {
-        pThis->aOperands[pThis->iRegOp].idxField = BS3CG1DST_XMM2_DW0_ZX;
-        off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 0));
-        off = Bs3Cfg1EncodeMemMod0Disp(pThis, false, off, 2 /*iReg*/, 4, 0, BS3CG1OPLOC_MEM);
-    }
-    else if (iEncoding == 2)
-    {
-        pThis->aOperands[pThis->iRegOp].idxField = BS3CG1DST_XMM3_DW0_ZX;
+        pThis->aOperands[pThis->iRegOp].idxField = BS3CG1DST_XMM3_HI;
         off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 0));
-        off = Bs3Cfg1EncodeMemMod0Disp(pThis, false, off, 3 /*iReg*/, 4, 1 /*cbMissalign*/, BS3CG1OPLOC_MEM);
+        off = Bs3Cfg1EncodeMemMod0Disp(pThis, false, off, 3 /*iReg*/, 8, 1 /*cbMisalign*/, BS3CG1OPLOC_MEM);
     }
     else
         return 0;
@@ -1688,17 +2095,163 @@ static unsigned BS3_NEAR_CODE Bs3Cg1EncodeNext_BS3CG1ENC_MODRM_VssZxReg_Wss(PBS3
 }
 
 
-static unsigned BS3_NEAR_CODE Bs3Cg1EncodeNext_BS3CG1ENC_MODRM_Gv_Ma(PBS3CG1STATE pThis, unsigned iEncoding)
+static unsigned BS3_NEAR_CODE Bs3Cg1EncodeNext_MODRM_Vdq_WO_Wdq(PBS3CG1STATE pThis, unsigned iEncoding)
 {
     unsigned off;
-    unsigned cbOp = BS3_MODE_IS_16BIT_CODE(pThis->bMode) ? 2 : 4;
     if (iEncoding == 0)
     {
-        pThis->aOperands[pThis->iRegOp].idxField = BS3CG1DST_OZ_RBP;
         off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 0));
-        off = Bs3Cfg1EncodeMemMod0Disp(pThis, false, off, X86_GREG_xBP, cbOp * 2, 0, BS3CG1OPLOC_MEM);
+        pThis->abCurInstr[off++] = X86_MODRM_MAKE(3, 1, 0);
+        pThis->aOperands[pThis->iRmOp ].idxField = BS3CG1DST_XMM0;
+        pThis->aOperands[pThis->iRegOp].idxField = BS3CG1DST_XMM1;
     }
-    else if (iEncoding == 1 && (g_uBs3CpuDetected & BS3CPU_TYPE_MASK) >= BS3CPU_80386)
+    else if (iEncoding == 1)
+    {
+        pThis->aOperands[pThis->iRegOp].idxField = BS3CG1DST_XMM2;
+        off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 0));
+        off = Bs3Cfg1EncodeMemMod0Disp(pThis, false, off, 2 /*iReg*/, 16, 0, BS3CG1OPLOC_MEM);
+    }
+    else if (iEncoding == 2)
+    {
+        pThis->aOperands[pThis->iRegOp].idxField = BS3CG1DST_XMM3;
+        off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 0));
+        off = Bs3Cfg1EncodeMemMod0Disp(pThis, false, off, 3 /*iReg*/, 16, 1 /*cbMisalign*/, BS3CG1OPLOC_MEM);
+        if (!Bs3Cg1XcptTypeIsUnaligned(pThis->enmXcptType))
+            pThis->bAlignmentXcpt = X86_XCPT_GP;
+    }
+    else
+        return 0;
+    pThis->cbCurInstr = off;
+    return iEncoding + 1;
+}
+
+
+static unsigned BS3_NEAR_CODE Bs3Cg1EncodeNext_MODRM_Vps_WO_Wps__OR__MODRM_Vpd_WO_Wpd(PBS3CG1STATE pThis,
+                                                                                                          unsigned iEncoding)
+{
+    unsigned off;
+    if (iEncoding == 0)
+    {
+        off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 0));
+        pThis->abCurInstr[off++] = X86_MODRM_MAKE(3, 1, 0);
+        pThis->aOperands[pThis->iRmOp ].idxField = BS3CG1DST_XMM0;
+        pThis->aOperands[pThis->iRegOp].idxField = BS3CG1DST_XMM1;
+    }
+    else if (iEncoding == 1)
+    {
+        pThis->aOperands[pThis->iRegOp].idxField = BS3CG1DST_XMM2;
+        off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 0));
+        off = Bs3Cfg1EncodeMemMod0Disp(pThis, false, off, 2 /*iReg*/, 16, 0, BS3CG1OPLOC_MEM);
+    }
+    else if (iEncoding == 2)
+    {
+        pThis->aOperands[pThis->iRegOp].idxField = BS3CG1DST_XMM3;
+        off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 0));
+        off = Bs3Cfg1EncodeMemMod0Disp(pThis, false, off, 3 /*iReg*/, 16, 1 /*cbMisalign*/, BS3CG1OPLOC_MEM);
+        if (!Bs3Cg1XcptTypeIsUnaligned(pThis->enmXcptType))
+            pThis->bAlignmentXcpt = X86_XCPT_GP;
+    }
+    else
+        return 0;
+    pThis->cbCurInstr = off;
+    return iEncoding + 1;
+}
+
+
+static unsigned BS3_NEAR_CODE Bs3Cg1EncodeNext_MODRM_VssZx_WO_Wss(PBS3CG1STATE pThis, unsigned iEncoding)
+{
+    unsigned off;
+    if (iEncoding == 0)
+    {
+        off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 0));
+        pThis->abCurInstr[off++] = X86_MODRM_MAKE(3, 1, 0);
+        pThis->aOperands[pThis->iRmOp ].idxField = BS3CG1DST_XMM0_LO;
+        pThis->aOperands[pThis->iRegOp].idxField = BS3CG1DST_XMM1_DW0_ZX;
+    }
+    else if (iEncoding == 1)
+    {
+        pThis->aOperands[pThis->iRegOp].idxField = BS3CG1DST_XMM2_DW0_ZX;
+        off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 0));
+        off = Bs3Cfg1EncodeMemMod0Disp(pThis, false, off, 2 /*iReg*/, 4, 0, BS3CG1OPLOC_MEM);
+    }
+    else if (iEncoding == 2)
+    {
+        pThis->aOperands[pThis->iRegOp].idxField = BS3CG1DST_XMM3_DW0_ZX;
+        off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 0));
+        off = Bs3Cfg1EncodeMemMod0Disp(pThis, false, off, 3 /*iReg*/, 4, 1 /*cbMisalign*/, BS3CG1OPLOC_MEM);
+    }
+    else
+        return 0;
+    pThis->cbCurInstr = off;
+    return iEncoding + 1;
+}
+
+
+static unsigned BS3_NEAR_CODE Bs3Cg1EncodeNext_MODRM_VsdZx_WO_Wsd__OR__MODRM_VqZx_WO_Wq(PBS3CG1STATE pThis,
+                                                                                                  unsigned iEncoding)
+{
+    unsigned off;
+    if (iEncoding == 0)
+    {
+        off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 0));
+        pThis->abCurInstr[off++] = X86_MODRM_MAKE(3, 1, 0);
+        pThis->aOperands[pThis->iRmOp ].idxField = BS3CG1DST_XMM0_LO;
+        pThis->aOperands[pThis->iRegOp].idxField = BS3CG1DST_XMM1_LO_ZX;
+    }
+    else if (iEncoding == 1)
+    {
+        pThis->aOperands[pThis->iRegOp].idxField = BS3CG1DST_XMM2_LO_ZX;
+        off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 0));
+        off = Bs3Cfg1EncodeMemMod0Disp(pThis, false, off, 2 /*iReg*/, 8, 0, BS3CG1OPLOC_MEM);
+    }
+    else if (iEncoding == 2)
+    {
+        pThis->aOperands[pThis->iRegOp].idxField = BS3CG1DST_XMM3_LO_ZX;
+        off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 0));
+        off = Bs3Cfg1EncodeMemMod0Disp(pThis, false, off, 3 /*iReg*/, 8, 1 /*cbMisalign*/, BS3CG1OPLOC_MEM);
+    }
+    else
+        return 0;
+    pThis->cbCurInstr = off;
+    return iEncoding + 1;
+}
+
+
+static unsigned BS3_NEAR_CODE Bs3Cg1EncodeNext_MODRM_VqZx_WO_Nq(PBS3CG1STATE pThis, unsigned iEncoding)
+{
+    unsigned off;
+    if (iEncoding == 0)
+    {
+        off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 0));
+        pThis->abCurInstr[off++] = X86_MODRM_MAKE(3, 1, 0);
+        pThis->aOperands[pThis->iRmOp ].idxField = BS3CG1DST_MM0;
+        pThis->aOperands[pThis->iRegOp].idxField = BS3CG1DST_XMM1_LO_ZX;
+    }
+    else if (iEncoding == 1)
+    {
+        off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 0));
+        pThis->abCurInstr[off++] = X86_MODRM_MAKE(3, 6, 7);
+        pThis->aOperands[pThis->iRmOp ].idxField = BS3CG1DST_MM7;
+        pThis->aOperands[pThis->iRegOp].idxField = BS3CG1DST_XMM6_LO_ZX;
+    }
+    else
+        return 0;
+    pThis->cbCurInstr = off;
+    return iEncoding + 1;
+}
+
+
+static unsigned BS3_NEAR_CODE Bs3Cg1EncodeNext_MODRM_Gv_RO_Ma(PBS3CG1STATE pThis, unsigned iEncoding)
+{
+    unsigned off;
+    unsigned cbOp = BS3_MODE_IS_16BIT_CODE(pThis->bMode) ? 2 : 4;
+    if (iEncoding == 0)
+    {
+        pThis->aOperands[pThis->iRegOp].idxField = BS3CG1DST_OZ_RBP;
+        off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 0));
+        off = Bs3Cfg1EncodeMemMod0Disp(pThis, false, off, X86_GREG_xBP, cbOp * 2, 0, BS3CG1OPLOC_MEM);
+    }
+    else if (iEncoding == 1 && (g_uBs3CpuDetected & BS3CPU_TYPE_MASK) >= BS3CPU_80386)
     {
         cbOp = cbOp == 2 ? 4 : 2;
         pThis->aOperands[pThis->iRegOp].idxField = BS3CG1DST_OZ_RBP;
@@ -1731,7 +2284,7 @@ static unsigned BS3_NEAR_CODE Bs3Cg1EncodeNext_BS3CG1ENC_MODRM_Gv_Ma(PBS3CG1STAT
 }
 
 
-static unsigned BS3_NEAR_CODE Bs3Cg1EncodeNext_BS3CG1ENC_MODRM_MbRO(PBS3CG1STATE pThis, unsigned iEncoding)
+static unsigned BS3_NEAR_CODE Bs3Cg1EncodeNext_MODRM_Mb_RO(PBS3CG1STATE pThis, unsigned iEncoding)
 {
     unsigned off;
     if (iEncoding == 0)
@@ -1748,7 +2301,7 @@ static unsigned BS3_NEAR_CODE Bs3Cg1EncodeNext_BS3CG1ENC_MODRM_MbRO(PBS3CG1STATE
 }
 
 
-static unsigned BS3_NEAR_CODE Bs3Cg1EncodeNext_BS3CG1ENC_MODRM_MdRO(PBS3CG1STATE pThis, unsigned iEncoding)
+static unsigned BS3_NEAR_CODE Bs3Cg1EncodeNext_MODRM_Md_RO(PBS3CG1STATE pThis, unsigned iEncoding)
 {
     unsigned off;
     if (iEncoding == 0)
@@ -1765,7 +2318,7 @@ static unsigned BS3_NEAR_CODE Bs3Cg1EncodeNext_BS3CG1ENC_MODRM_MdRO(PBS3CG1STATE
 }
 
 
-static unsigned BS3_NEAR_CODE Bs3Cg1EncodeNext_BS3CG1ENC_MODRM_MdWO(PBS3CG1STATE pThis, unsigned iEncoding)
+static unsigned BS3_NEAR_CODE Bs3Cg1EncodeNext_MODRM_Md_WO(PBS3CG1STATE pThis, unsigned iEncoding)
 {
     unsigned off;
     if (iEncoding == 0)
@@ -1773,7 +2326,7 @@ static unsigned BS3_NEAR_CODE Bs3Cg1EncodeNext_BS3CG1ENC_MODRM_MdWO(PBS3CG1STATE
         off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 0)) - 1;
         off = Bs3Cfg1EncodeMemMod0Disp(pThis, false, off,
                                        (pThis->abCurInstr[off] & X86_MODRM_REG_MASK) >> X86_MODRM_REG_SHIFT,
-                                       4, 0, BS3CG1OPLOC_MEM_RW);
+                                       4, 0, BS3CG1OPLOC_MEM_WO);
     }
     else
         return 0;
@@ -1782,114 +2335,119 @@ static unsigned BS3_NEAR_CODE Bs3Cg1EncodeNext_BS3CG1ENC_MODRM_MdWO(PBS3CG1STATE
 }
 
 
-static unsigned BS3_NEAR_CODE Bs3Cg1EncodeNext_BS3CG1ENC_VEX_MODRM_MdWO(PBS3CG1STATE pThis, unsigned iEncoding)
+static unsigned BS3_NEAR_CODE Bs3Cg1EncodeNext_MODRM_Mq_WO_Pq(PBS3CG1STATE pThis, unsigned iEncoding)
 {
     unsigned off;
-    if (iEncoding == 0)
+    switch (iEncoding)
     {
-        /** @todo three by opcode needs some tweaking. */
-        off = Bs3Cg1InsertVex2bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 0 /*L*/, 1 /*~R*/);
-        off = Bs3Cg1InsertOpcodes(pThis, off) - 1;
-        off = Bs3Cfg1EncodeMemMod0Disp(pThis, false, off,
-                                       (pThis->abCurInstr[off] & X86_MODRM_REG_MASK) >> X86_MODRM_REG_SHIFT,
-                                       4, 0, BS3CG1OPLOC_MEM_RW);
-    }
-    else if (iEncoding == 1)
-    {
-        off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 0 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 0 /*W*/);
-        off = Bs3Cg1InsertOpcodes(pThis, off) - 1;
-        off = Bs3Cfg1EncodeMemMod0Disp(pThis, false, off,
-                                       (pThis->abCurInstr[off] & X86_MODRM_REG_MASK) >> X86_MODRM_REG_SHIFT,
-                                       4, 0, BS3CG1OPLOC_MEM_RW);
-    }
-    else if (iEncoding == 2)
-    {
-        off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0x7 /*~V*/, 0 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 0 /*W*/);
-        off = Bs3Cg1InsertOpcodes(pThis, off) - 1;
-        off = Bs3Cfg1EncodeMemMod0Disp(pThis, false, off,
-                                       (pThis->abCurInstr[off] & X86_MODRM_REG_MASK) >> X86_MODRM_REG_SHIFT,
-                                       4, 0, BS3CG1OPLOC_MEM_RW);
-        pThis->fInvalidEncoding = true;
-    }
-    else if (iEncoding == 3)
-    {
-        off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 1 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 0 /*W*/);
-        off = Bs3Cg1InsertOpcodes(pThis, off) - 1;
-        off = Bs3Cfg1EncodeMemMod0Disp(pThis, false, off,
-                                       (pThis->abCurInstr[off] & X86_MODRM_REG_MASK) >> X86_MODRM_REG_SHIFT,
-                                       4, 0, BS3CG1OPLOC_MEM_RW);
-        pThis->fInvalidEncoding = true;
+        case 0:
+            off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 0));
+            off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, false, off, 4 /*iReg*/, 0 /*cbMisalign*/);
+            break;
+        case 1:
+            off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 0));
+            off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, false, off, 7 /*iReg*/, 1 /*cbMisalign*/);
+            iEncoding += !BS3CG1_IS_64BIT_TARGET(pThis) ? 1 : 0;
+            break;
+#if ARCH_BITS == 64
+        case 2:
+            off = Bs3Cg1InsertReqPrefix(pThis, 0);
+            pThis->abCurInstr[off++] = REX__RBX;
+            off = Bs3Cg1InsertOpcodes(pThis, off);
+            off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, false, off, 7 /*iReg - no +8*/, 0 /*cbMisalign*/);
+            break;
+#endif
+
+        default:
+            return 0;
     }
-    else if (iEncoding == 4)
+
+    pThis->cbCurInstr = off;
+    return iEncoding + 1;
+}
+
+
+static unsigned BS3_NEAR_CODE Bs3Cg1EncodeNext_MODRM_Mq_WO_Vq(PBS3CG1STATE pThis, unsigned iEncoding)
+{
+    unsigned off;
+    if (iEncoding == 0)
     {
-        pThis->abCurInstr[0] = P_OZ;
-        off = Bs3Cg1InsertVex3bPrefix(pThis, 1 /*offDst*/, 0xf /*~V*/, 0 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 0 /*W*/);
-        off = Bs3Cg1InsertOpcodes(pThis, off) - 1;
-        off = Bs3Cfg1EncodeMemMod0Disp(pThis, false, off,
-                                       (pThis->abCurInstr[off] & X86_MODRM_REG_MASK) >> X86_MODRM_REG_SHIFT,
-                                       4, 0, BS3CG1OPLOC_MEM_RW);
-        pThis->fInvalidEncoding = true;
+        pThis->aOperands[pThis->iRegOp].idxField = BS3CG1DST_XMM2_LO;
+        off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 0));
+        off = Bs3Cfg1EncodeMemMod0Disp(pThis, false, off, 2 /*iReg*/, 8, 0, BS3CG1OPLOC_MEM_WO);
     }
-    else if (iEncoding == 5)
+    else if (iEncoding == 1)
     {
-        pThis->abCurInstr[0] = P_RZ;
-        off = Bs3Cg1InsertVex3bPrefix(pThis, 1 /*offDst*/, 0xf /*~V*/, 0 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 0 /*W*/);
-        off = Bs3Cg1InsertOpcodes(pThis, off) - 1;
-        off = Bs3Cfg1EncodeMemMod0Disp(pThis, false, off,
-                                       (pThis->abCurInstr[off] & X86_MODRM_REG_MASK) >> X86_MODRM_REG_SHIFT,
-                                       4, 0, BS3CG1OPLOC_MEM_RW);
-        pThis->fInvalidEncoding = true;
+        pThis->aOperands[pThis->iRegOp].idxField = BS3CG1DST_XMM3_LO;
+        off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 0));
+        off = Bs3Cfg1EncodeMemMod0Disp(pThis, false, off, 3 /*iReg*/, 8, 1 /*cbMisalign*/, BS3CG1OPLOC_MEM_WO);
     }
-    else if (iEncoding == 6)
+    else
+        return 0;
+    pThis->cbCurInstr = off;
+    return iEncoding + 1;
+}
+
+
+static unsigned BS3_NEAR_CODE Bs3Cg1EncodeNext_MODRM_Mq_WO_VqHi(PBS3CG1STATE pThis, unsigned iEncoding)
+{
+    unsigned off;
+    if (iEncoding == 0)
     {
-        pThis->abCurInstr[0] = P_RN;
-        off = Bs3Cg1InsertVex3bPrefix(pThis, 1 /*offDst*/, 0xf /*~V*/, 0 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 0 /*W*/);
-        off = Bs3Cg1InsertOpcodes(pThis, off) - 1;
-        off = Bs3Cfg1EncodeMemMod0Disp(pThis, false, off,
-                                       (pThis->abCurInstr[off] & X86_MODRM_REG_MASK) >> X86_MODRM_REG_SHIFT,
-                                       4, 0, BS3CG1OPLOC_MEM_RW);
-        pThis->fInvalidEncoding = true;
+        pThis->aOperands[pThis->iRegOp].idxField = BS3CG1DST_XMM2_HI;
+        off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 0));
+        off = Bs3Cfg1EncodeMemMod0Disp(pThis, false, off, 2 /*iReg*/, 8, 0, BS3CG1OPLOC_MEM_WO);
     }
-    else if (iEncoding == 7)
+    else if (iEncoding == 1)
     {
-        off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 0 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 1 /*W*/);
-        off = Bs3Cg1InsertOpcodes(pThis, off) - 1;
-        off = Bs3Cfg1EncodeMemMod0Disp(pThis, false, off,
-                                       (pThis->abCurInstr[off] & X86_MODRM_REG_MASK) >> X86_MODRM_REG_SHIFT,
-                                       4, 0, BS3CG1OPLOC_MEM_RW);
+        pThis->aOperands[pThis->iRegOp].idxField = BS3CG1DST_XMM3_HI;
+        off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 0));
+        off = Bs3Cfg1EncodeMemMod0Disp(pThis, false, off, 3 /*iReg*/, 8, 1 /*cbMisalign*/, BS3CG1OPLOC_MEM_WO);
     }
-#if ARCH_BITS == 64
-    else if (BS3_MODE_IS_64BIT_CODE(pThis->bMode))
+    else
+        return 0;
+    pThis->cbCurInstr = off;
+    return iEncoding + 1;
+}
+
+
+static unsigned BS3_NEAR_CODE Bs3Cg1EncodeNext_MODRM_MsomethingWO_Vsomething_OR_ViceVersa(PBS3CG1STATE pThis, unsigned iEncoding)
+{
+    unsigned off;
+    switch (iEncoding)
     {
-        if (iEncoding == 8)
-        {
-            pThis->abCurInstr[0] = REX_____;
-            off = Bs3Cg1InsertVex3bPrefix(pThis, 1 /*offDst*/, 0xf /*~V*/, 0 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 0 /*W*/);
-            off = Bs3Cg1InsertOpcodes(pThis, off) - 1;
-            off = Bs3Cfg1EncodeMemMod0Disp(pThis, false, off,
-                                           (pThis->abCurInstr[off] & X86_MODRM_REG_MASK) >> X86_MODRM_REG_SHIFT,
-                                           4, 0, BS3CG1OPLOC_MEM_RW);
-            pThis->fInvalidEncoding = true;
-        }
-        else
+        case 0:
+            off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 0));
+            off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, false, off, 2 /*iReg*/, 0);
+            break;
+        case 1:
+            off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 0));
+            off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, false, off, 2 /*iReg*/, 1 /*cbMisalign*/ );
+            if (!Bs3Cg1XcptTypeIsUnaligned(pThis->enmXcptType))
+                pThis->bAlignmentXcpt = X86_XCPT_GP;
+            iEncoding += !BS3CG1_IS_64BIT_TARGET(pThis) ? 1 : 0;
+            break;
+        case 2:
+            off = Bs3Cg1InsertReqPrefix(pThis, 0);
+            pThis->abCurInstr[off++] = REX__R__;
+            off = Bs3Cg1InsertOpcodes(pThis, off);
+            off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, false, off, 2+8 /*iReg*/, 0);
+            break;
+        default:
             return 0;
     }
-#endif
-    else
-        return 0;
     pThis->cbCurInstr = off;
     return iEncoding + 1;
 }
 
 
-static unsigned BS3_NEAR_CODE Bs3Cg1EncodeNext_BS3CG1ENC_FIXED(PBS3CG1STATE pThis, unsigned iEncoding)
+static unsigned BS3_NEAR_CODE Bs3Cg1EncodeNext_FIXED(PBS3CG1STATE pThis, unsigned iEncoding)
 {
     unsigned off;
     if (iEncoding == 0)
     {
         off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 0));
         pThis->cbCurInstr = off;
-        iEncoding++;
     }
     else
         return 0;
@@ -1897,7 +2455,7 @@ static unsigned BS3_NEAR_CODE Bs3Cg1EncodeNext_BS3CG1ENC_FIXED(PBS3CG1STATE pThi
 }
 
 
-static unsigned BS3_NEAR_CODE Bs3Cg1EncodeNext_BS3CG1ENC_FIXED_AL_Ib(PBS3CG1STATE pThis, unsigned iEncoding)
+static unsigned BS3_NEAR_CODE Bs3Cg1EncodeNext_FIXED_AL_Ib(PBS3CG1STATE pThis, unsigned iEncoding)
 {
     unsigned off;
     if (iEncoding == 0)
@@ -1913,7 +2471,7 @@ static unsigned BS3_NEAR_CODE Bs3Cg1EncodeNext_BS3CG1ENC_FIXED_AL_Ib(PBS3CG1STAT
 }
 
 
-static unsigned BS3_NEAR_CODE Bs3Cg1EncodeNext_BS3CG1ENC_FIXED_rAX_Iz(PBS3CG1STATE pThis, unsigned iEncoding)
+static unsigned BS3_NEAR_CODE Bs3Cg1EncodeNext_FIXED_rAX_Iz(PBS3CG1STATE pThis, unsigned iEncoding)
 {
     unsigned off;
     if (iEncoding == 0)
@@ -1959,7 +2517,7 @@ static unsigned BS3_NEAR_CODE Bs3Cg1EncodeNext_BS3CG1ENC_FIXED_rAX_Iz(PBS3CG1STA
             pThis->cbOperand         = 4;
         }
     }
-    else if (iEncoding == 2 && BS3_MODE_IS_64BIT_CODE(pThis->bMode))
+    else if (iEncoding == 2 && BS3CG1_IS_64BIT_TARGET(pThis))
     {
         off = Bs3Cg1InsertReqPrefix(pThis, 0);
         pThis->abCurInstr[off++] = REX_W___;
@@ -1978,7 +2536,7 @@ static unsigned BS3_NEAR_CODE Bs3Cg1EncodeNext_BS3CG1ENC_FIXED_rAX_Iz(PBS3CG1STA
 }
 
 
-static unsigned BS3_NEAR_CODE Bs3Cg1EncodeNext_BS3CG1ENC_MODRM_MOD_EQ_3(PBS3CG1STATE pThis, unsigned iEncoding)
+static unsigned BS3_NEAR_CODE Bs3Cg1EncodeNext_MODRM_MOD_EQ_3(PBS3CG1STATE pThis, unsigned iEncoding)
 {
     unsigned off;
     if (iEncoding < 8)
@@ -1991,7 +2549,7 @@ static unsigned BS3_NEAR_CODE Bs3Cg1EncodeNext_BS3CG1ENC_MODRM_MOD_EQ_3(PBS3CG1S
     {
         off = Bs3Cg1InsertReqPrefix(pThis, 0);
         off = Bs3Cg1InsertOpcodes(pThis, off);
-        pThis->abCurInstr[off++] = X86_MODRM_MAKE(3, 0, iEncoding);
+        pThis->abCurInstr[off++] = X86_MODRM_MAKE(3, 0, iEncoding & 7);
     }
     else
         return 0;
@@ -2001,7 +2559,7 @@ static unsigned BS3_NEAR_CODE Bs3Cg1EncodeNext_BS3CG1ENC_MODRM_MOD_EQ_3(PBS3CG1S
 }
 
 
-static unsigned BS3_NEAR_CODE Bs3Cg1EncodeNext_BS3CG1ENC_MODRM_MOD_NE_3(PBS3CG1STATE pThis, unsigned iEncoding)
+static unsigned BS3_NEAR_CODE Bs3Cg1EncodeNext_MODRM_MOD_NE_3(PBS3CG1STATE pThis, unsigned iEncoding)
 {
     unsigned off;
     if (iEncoding < 3)
@@ -2028,72 +2586,1648 @@ static unsigned BS3_NEAR_CODE Bs3Cg1EncodeNext_BS3CG1ENC_MODRM_MOD_NE_3(PBS3CG1S
 }
 
 
-/**
- * Encodes the next instruction.
+/*
+ *
+ * VEX
+ * VEX
+ * VEX
  *
- * @returns Next iEncoding value.  Returns @a iEncoding unchanged to indicate
- *          that there are no more encodings to test.
- * @param   pThis           The state.
- * @param   iEncoding       The encoding to produce.  Meaning is specific to
- *                          each BS3CG1ENC_XXX value and should be considered
- *                          internal.
  */
-static unsigned BS3_NEAR_CODE Bs3Cg1EncodeNext(PBS3CG1STATE pThis, unsigned iEncoding)
-{
-    pThis->bAlignmentXcpt = UINT8_MAX;
+#ifdef BS3CG1_WITH_VEX
+
+/**
+ * Inserts a 2-byte VEX prefix.
+ *
+ * @returns New offDst value.
+ * @param   pThis       The state.
+ * @param   offDst      The current instruction offset.
+ * @param   uVexL       The VEX.L value.
+ * @param   uVexV       The VEX.V value (caller inverted it already).
+ * @param   uVexR       The VEX.R value (caller inverted it already).
+ */
+DECLINLINE(unsigned) BS3_NEAR_CODE Bs3Cg1InsertVex2bPrefix(PBS3CG1STATE pThis, unsigned offDst,
+                                                           uint8_t uVexV, uint8_t uVexL, uint8_t uVexR)
+{
+    uint8_t b = uVexR << 7;
+    b        |= uVexV << 3;
+    b        |= uVexL << 2;
+    switch (pThis->enmPrefixKind)
+    {
+        case BS3CG1PFXKIND_NO_F2_F3_66:     b |= 0; break;
+        case BS3CG1PFXKIND_REQ_66:          b |= 1; break;
+        case BS3CG1PFXKIND_REQ_F3:          b |= 2; break;
+        case BS3CG1PFXKIND_REQ_F2:          b |= 3; break;
+        default:
+            Bs3TestFailedF("enmPrefixKind=%d not supported for VEX!\n");
+            break;
+    }
+
+    pThis->abCurInstr[offDst]     = 0xc5; /* vex2 */
+    pThis->abCurInstr[offDst + 1] = b;
+    pThis->uVexL                  = uVexL;
+    return offDst + 2;
+}
+
+
+/**
+ * Inserts a 3-byte VEX prefix.
+ *
+ * @returns New offDst value.
+ * @param   pThis       The state.
+ * @param   offDst      The current instruction offset.
+ * @param   uVexL       The VEX.L value.
+ * @param   uVexV       The VEX.V value (caller inverted it already).
+ * @param   uVexR       The VEX.R value (caller inverted it already).
+ * @param   uVexR       The VEX.X value (caller inverted it already).
+ * @param   uVexR       The VEX.B value (caller inverted it already).
+ * @param   uVexR       The VEX.W value (straight).
+ */
+DECLINLINE(unsigned) BS3_NEAR_CODE Bs3Cg1InsertVex3bPrefix(PBS3CG1STATE pThis, unsigned offDst, uint8_t uVexV, uint8_t uVexL,
+                                                           uint8_t uVexR, uint8_t uVexX, uint8_t uVexB, uint8_t uVexW)
+{
+    uint8_t b1;
+    uint8_t b2;
+    b1        = uVexR << 7;
+    b1       |= uVexX << 6;
+    b1       |= uVexB << 5;
+    b1       |= 1; /* VEX.mmmmm = 1*/ /** @todo three byte opcode tables */
+    b2        = uVexV << 3;
+    b2       |= uVexW << 7;
+    b2       |= uVexL << 2;
+    switch (pThis->enmPrefixKind)
+    {
+        case BS3CG1PFXKIND_NO_F2_F3_66:     b2 |= 0; break;
+        case BS3CG1PFXKIND_REQ_66:          b2 |= 1; break;
+        case BS3CG1PFXKIND_REQ_F3:          b2 |= 2; break;
+        case BS3CG1PFXKIND_REQ_F2:          b2 |= 3; break;
+        default:
+            Bs3TestFailedF("enmPrefixKind=%d not supported for VEX!\n", pThis->enmPrefixKind);
+            break;
+    }
+
+    pThis->abCurInstr[offDst]     = 0xc4; /* vex3 */
+    pThis->abCurInstr[offDst + 1] = b1;
+    pThis->abCurInstr[offDst + 2] = b2;
+    pThis->uVexL                  = uVexL;
+    return offDst + 3;
+}
+
+
+static unsigned BS3_NEAR_CODE Bs3Cg1EncodeNext_VEX_MODRM_Vd_WO_Ed_WZ(PBS3CG1STATE pThis, unsigned iEncoding)
+{
+    unsigned off;
+    switch (iEncoding)
+    {
+        case 0:
+            pThis->aOperands[pThis->iRmOp ].enmLocation = pThis->aOperands[pThis->iRmOp].enmLocationReg;
+            off = Bs3Cg1InsertVex2bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 0 /*L*/, 1 /*~R*/);
+            off = Bs3Cg1InsertOpcodes(pThis, off);
+            pThis->abCurInstr[off++] = X86_MODRM_MAKE(3, 1, 0);
+            pThis->aOperands[pThis->iRmOp ].idxField = pThis->aOperands[pThis->iRmOp ].idxFieldBase + 0;
+            pThis->aOperands[pThis->iRegOp].idxField = pThis->aOperands[pThis->iRegOp].idxFieldBase + 1;
+            break;
+        case 1:
+            off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 0 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 0 /*W*/);
+            off = Bs3Cg1InsertOpcodes(pThis, off);
+            pThis->abCurInstr[off++] = X86_MODRM_MAKE(3, 6, 2);
+            pThis->aOperands[pThis->iRmOp ].idxField = pThis->aOperands[pThis->iRmOp ].idxFieldBase + 2;
+            pThis->aOperands[pThis->iRegOp].idxField = pThis->aOperands[pThis->iRegOp].idxFieldBase + 6;
+            break;
+        case 2:
+            off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 1 /*L-invalid*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 0 /*W*/);
+            off = Bs3Cg1InsertOpcodes(pThis, off);
+            pThis->abCurInstr[off++] = X86_MODRM_MAKE(3, 6, 2);
+            pThis->aOperands[pThis->iRmOp ].idxField = pThis->aOperands[pThis->iRmOp ].idxFieldBase + 2;
+            pThis->aOperands[pThis->iRegOp].idxField = pThis->aOperands[pThis->iRegOp].idxFieldBase + 6;
+            pThis->fInvalidEncoding = true;
+            break;
+        case 3:
+            off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xe /*~V-invalid*/, 0 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 0 /*W*/);
+            off = Bs3Cg1InsertOpcodes(pThis, off);
+            pThis->abCurInstr[off++] = X86_MODRM_MAKE(3, 6, 2);
+            pThis->aOperands[pThis->iRmOp ].idxField = pThis->aOperands[pThis->iRmOp ].idxFieldBase + 2;
+            pThis->aOperands[pThis->iRegOp].idxField = pThis->aOperands[pThis->iRegOp].idxFieldBase + 6;
+            pThis->fInvalidEncoding = true;
+            iEncoding += !BS3CG1_IS_64BIT_TARGET(pThis) ? 1 : 0;
+            break;
+#if ARCH_BITS == 64
+        case 4:
+            off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 0 /*L*/, 0 /*~R*/, 1 /*~X*/, 0 /*~B*/, 0 /*W*/);
+            off = Bs3Cg1InsertOpcodes(pThis, off);
+            pThis->abCurInstr[off++] = X86_MODRM_MAKE(3, 6, 2);
+            pThis->aOperands[pThis->iRmOp ].idxField = pThis->aOperands[pThis->iRmOp ].idxFieldBase + 2 + 8;
+            pThis->aOperands[pThis->iRegOp].idxField = pThis->aOperands[pThis->iRegOp].idxFieldBase + 6 + 8;
+            break;
+#endif
+        case 5:
+            pThis->aOperands[pThis->iRmOp ].enmLocation = pThis->aOperands[pThis->iRmOp].enmLocationMem;
+            off = Bs3Cg1InsertVex2bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 0 /*L*/, 1 /*~R*/);
+            off = Bs3Cg1InsertOpcodes(pThis, off);
+            off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, false, off, 4 /*iReg*/, 0 /*cbMisalign*/);
+            break;
+        case 6:
+            off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 0 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 0 /*W*/);
+            off = Bs3Cg1InsertOpcodes(pThis, off);
+            off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, false, off, 4 /*iReg*/, 0 /*cbMisalign*/);
+            break;
+        case 7:
+            off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 0 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 0 /*W*/);
+            off = Bs3Cg1InsertOpcodes(pThis, off);
+            off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, false, off, 4 /*iReg*/, 1 /*cbMisalign*/);
+            iEncoding += !BS3CG1_IS_64BIT_TARGET(pThis) ? 2 : 0;
+            break;
+#if ARCH_BITS == 64
+        case 8:
+            off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 0 /*L*/, 0 /*~R*/, 1 /*~X*/, 1 /*~B*/, 0 /*W*/);
+            off = Bs3Cg1InsertOpcodes(pThis, off);
+            off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, false, off, 4+8 /*iReg*/, 0 /*cbMisalign*/);
+            break;
+        case 9:
+            off = Bs3Cg1InsertVex2bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 0 /*L*/, 0 /*~R*/);
+            off = Bs3Cg1InsertOpcodes(pThis, off);
+            off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, false, off, 5+8 /*iReg*/, 0 /*cbMisalign*/);
+            iEncoding += 2;
+            break;
+#endif
+        case 10: /* VEX.W is ignored in 32-bit mode. flag? */
+            BS3_ASSERT(!BS3CG1_IS_64BIT_TARGET(pThis));
+            off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 0 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 1 /*W*/);
+            off = Bs3Cg1InsertOpcodes(pThis, off);
+            off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, false, off, 4 /*iReg*/, 0 /*cbMisalign*/);
+            break;
+
+        default:
+            return 0;
+    }
+    pThis->cbCurInstr = off;
+    return iEncoding + 1;
+}
+
+
+/* Differs from Bs3Cg1EncodeNext_MODRM_Pq_WO_Eq_WNZ in that REX.R isn't ignored. */
+static unsigned BS3_NEAR_CODE Bs3Cg1EncodeNext_VEX_MODRM_Vq_WO_Eq_WNZ(PBS3CG1STATE pThis, unsigned iEncoding)
+{
+#if ARCH_BITS == 64
+    if (BS3CG1_IS_64BIT_TARGET(pThis))
+    {
+        unsigned off;
+        switch (iEncoding)
+        {
+            case 0:
+                pThis->aOperands[pThis->iRmOp ].enmLocation = pThis->aOperands[pThis->iRmOp].enmLocationReg;
+                off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 0 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 1 /*W*/);
+                off = Bs3Cg1InsertOpcodes(pThis, off);
+                pThis->abCurInstr[off++] = X86_MODRM_MAKE(3, 6, 2);
+                pThis->aOperands[pThis->iRmOp ].idxField = pThis->aOperands[pThis->iRmOp ].idxFieldBase + 2;
+                pThis->aOperands[pThis->iRegOp].idxField = pThis->aOperands[pThis->iRegOp].idxFieldBase + 6;
+                break;
+            case 1:
+                off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 1 /*L-invalid*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 1 /*W*/);
+                off = Bs3Cg1InsertOpcodes(pThis, off);
+                pThis->abCurInstr[off++] = X86_MODRM_MAKE(3, 6, 2);
+                pThis->aOperands[pThis->iRmOp ].idxField = pThis->aOperands[pThis->iRmOp ].idxFieldBase + 2;
+                pThis->aOperands[pThis->iRegOp].idxField = pThis->aOperands[pThis->iRegOp].idxFieldBase + 6;
+                pThis->fInvalidEncoding = true;
+                break;
+            case 2:
+                off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xe /*~V-invalid*/, 0 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 1 /*W*/);
+                off = Bs3Cg1InsertOpcodes(pThis, off);
+                pThis->abCurInstr[off++] = X86_MODRM_MAKE(3, 6, 2);
+                pThis->aOperands[pThis->iRmOp ].idxField = pThis->aOperands[pThis->iRmOp ].idxFieldBase + 2;
+                pThis->aOperands[pThis->iRegOp].idxField = pThis->aOperands[pThis->iRegOp].idxFieldBase + 6;
+                pThis->fInvalidEncoding = true;
+                break;
+            case 3:
+                off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 0 /*L*/, 0 /*~R*/, 1 /*~X*/, 0 /*~B*/, 1 /*W*/);
+                off = Bs3Cg1InsertOpcodes(pThis, off);
+                pThis->abCurInstr[off++] = X86_MODRM_MAKE(3, 6, 2);
+                pThis->aOperands[pThis->iRmOp ].idxField = pThis->aOperands[pThis->iRmOp ].idxFieldBase + 2 + 8;
+                pThis->aOperands[pThis->iRegOp].idxField = pThis->aOperands[pThis->iRegOp].idxFieldBase + 6 + 8;
+                break;
+            case 4:
+                pThis->aOperands[pThis->iRmOp ].enmLocation = pThis->aOperands[pThis->iRmOp].enmLocationMem;
+                off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 0 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 1 /*W*/);
+                off = Bs3Cg1InsertOpcodes(pThis, off);
+                off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, false, off, 4 /*iReg*/, 0 /*cbMisalign*/);
+                break;
+            case 5:
+                off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 0 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 1 /*W*/);
+                off = Bs3Cg1InsertOpcodes(pThis, off);
+                off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, false, off, 4 /*iReg*/, 1 /*cbMisalign*/);
+                iEncoding += !BS3CG1_IS_64BIT_TARGET(pThis) ? 2 : 0;
+                break;
+            case 6:
+                off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 0 /*L*/, 0 /*~R*/, 1 /*~X*/, 1 /*~B*/, 1 /*W*/);
+                off = Bs3Cg1InsertOpcodes(pThis, off);
+                off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, false, off, 4+8 /*iReg*/, 0 /*cbMisalign*/);
+                break;
+
+            default:
+                return 0;
+        }
+        pThis->cbCurInstr = off;
+        return iEncoding + 1;
+    }
+#endif
+    return 0;
+}
+
+
+static unsigned BS3_NEAR_CODE Bs3Cg1EncodeNext_VEX_MODRM_Vps_WO_Wps__OR__VEX_MODRM_Vpd_WO_Wpd(PBS3CG1STATE pThis, unsigned iEncoding)
+{
+    unsigned off;
+    /* 128-bit wide stuff goes first, then we'll update the operand widths afterwards. */
+    if (iEncoding == 0)
+    {
+        off = Bs3Cg1InsertVex2bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 0 /*L*/, 1 /*~R*/);
+        off = Bs3Cg1InsertOpcodes(pThis, off);
+        pThis->abCurInstr[off++] = X86_MODRM_MAKE(3, 1, 0);
+        pThis->aOperands[pThis->iRmOp ].idxField = BS3CG1DST_XMM0;
+        pThis->aOperands[pThis->iRegOp].idxField = BS3CG1DST_XMM1;
+    }
+    else if (iEncoding == 1)
+    {
+        off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 0 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 0 /*W*/);
+        off = Bs3Cg1InsertOpcodes(pThis, off);
+        pThis->abCurInstr[off++] = X86_MODRM_MAKE(3, 4, 5);
+        pThis->aOperands[pThis->iRmOp ].idxField = BS3CG1DST_XMM5;
+        pThis->aOperands[pThis->iRegOp].idxField = BS3CG1DST_XMM4;
+    }
+    else if (iEncoding == 2)
+    {
+        off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 0 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 1 /*W - ignored*/);
+        off = Bs3Cg1InsertOpcodes(pThis, off);
+        pThis->abCurInstr[off++] = X86_MODRM_MAKE(3, 5, 4);
+        pThis->aOperands[pThis->iRmOp ].idxField = BS3CG1DST_XMM4;
+        pThis->aOperands[pThis->iRegOp].idxField = BS3CG1DST_XMM5;
+    }
+    else if (iEncoding == 3)
+    {
+        off = Bs3Cg1InsertVex2bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 0 /*L*/, 1 /*~R*/);
+        off = Bs3Cg1InsertOpcodes(pThis, off);
+        off = Bs3Cfg1EncodeMemMod0Disp(pThis, false, off, 2 /*iReg*/, 16, 0, BS3CG1OPLOC_MEM);
+        pThis->aOperands[pThis->iRegOp].idxField = BS3CG1DST_XMM2;
+    }
+    else if (iEncoding == 4)
+    {
+        off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 0 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 0 /*W*/);
+        off = Bs3Cg1InsertOpcodes(pThis, off);
+        off = Bs3Cfg1EncodeMemMod0Disp(pThis, false, off, 3 /*iReg*/, 16, 0, BS3CG1OPLOC_MEM);
+        pThis->aOperands[pThis->iRegOp].idxField = BS3CG1DST_XMM3;
+    }
+    else if (iEncoding == 5)
+    {
+        off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 0 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 1 /*W - ignored */);
+        off = Bs3Cg1InsertOpcodes(pThis, off);
+        off = Bs3Cfg1EncodeMemMod0Disp(pThis, false, off, 3 /*iReg*/, 16, 0, BS3CG1OPLOC_MEM);
+        pThis->aOperands[pThis->iRegOp].idxField = BS3CG1DST_XMM3;
+    }
+    else if (iEncoding == 6)
+    {
+        off = Bs3Cg1InsertVex2bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 0 /*L*/, 1 /*~R*/);
+        off = Bs3Cg1InsertOpcodes(pThis, off);
+        off = Bs3Cfg1EncodeMemMod0Disp(pThis, false, off, 3 /*iReg*/, 16, 1 /*cbMisalign*/, BS3CG1OPLOC_MEM);
+        if (!Bs3Cg1XcptTypeIsVexUnaligned(pThis->enmXcptType))
+            pThis->bAlignmentXcpt = X86_XCPT_GP;
+        pThis->aOperands[pThis->iRegOp].idxField = BS3CG1DST_XMM3;
+    }
+    else if (iEncoding == 7)
+    {
+        off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 0 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 0 /*W*/);
+        off = Bs3Cg1InsertOpcodes(pThis, off);
+        off = Bs3Cfg1EncodeMemMod0Disp(pThis, false, off, 3 /*iReg*/, 16, 1 /*cbMisalign*/, BS3CG1OPLOC_MEM);
+        if (!Bs3Cg1XcptTypeIsVexUnaligned(pThis->enmXcptType))
+            pThis->bAlignmentXcpt = X86_XCPT_GP;
+        pThis->aOperands[pThis->iRegOp].idxField = BS3CG1DST_XMM3;
+    }
+    /* 128-bit invalid encodings: */
+    else if (iEncoding == 8)
+    {
+        off = Bs3Cg1InsertVex2bPrefix(pThis, 0 /*offDst*/, 0xe /*~V*/, 0 /*L*/, 1 /*~R*/); /* Bad V value */
+        off = Bs3Cg1InsertOpcodes(pThis, off);
+        pThis->abCurInstr[off++] = X86_MODRM_MAKE(3, 1, 0);
+        pThis->aOperands[pThis->iRmOp ].idxField = BS3CG1DST_XMM0;
+        pThis->aOperands[pThis->iRegOp].idxField = BS3CG1DST_XMM1;
+        pThis->fInvalidEncoding = true;
+    }
+    else if (iEncoding == 9)
+    {
+        off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0 /*~V*/, 0 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 0 /*W*/);
+        off = Bs3Cg1InsertOpcodes(pThis, off);
+        pThis->abCurInstr[off++] = X86_MODRM_MAKE(3, 4, 5);
+        pThis->aOperands[pThis->iRmOp ].idxField = BS3CG1DST_XMM5;
+        pThis->aOperands[pThis->iRegOp].idxField = BS3CG1DST_XMM4;
+        pThis->fInvalidEncoding = true;
+    }
+    /* 256-bit encodings: */
+    else if (iEncoding == 10)
+    {
+        off = Bs3Cg1InsertVex2bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 1 /*L*/, 1 /*~R*/);
+        off = Bs3Cg1InsertOpcodes(pThis, off);
+        pThis->abCurInstr[off++] = X86_MODRM_MAKE(3, 1, 0);
+        pThis->aOperands[pThis->iRmOp].cbOp      = 32;
+        pThis->aOperands[pThis->iRmOp ].idxField = BS3CG1DST_YMM0;
+        pThis->aOperands[pThis->iRegOp].cbOp     = 32;
+        pThis->aOperands[pThis->iRegOp].idxField = BS3CG1DST_YMM1;
+    }
+    else if (iEncoding == 11)
+    {
+        off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 1 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 0 /*W*/);
+        off = Bs3Cg1InsertOpcodes(pThis, off);
+        pThis->abCurInstr[off++] = X86_MODRM_MAKE(3, 4, 5);
+        pThis->aOperands[pThis->iRmOp ].idxField = BS3CG1DST_YMM5;
+        pThis->aOperands[pThis->iRegOp].idxField = BS3CG1DST_YMM4;
+    }
+    else if (iEncoding == 12)
+    {
+        off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 1 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 1 /*W - ignored*/);
+        off = Bs3Cg1InsertOpcodes(pThis, off);
+        pThis->abCurInstr[off++] = X86_MODRM_MAKE(3, 5, 4);
+        pThis->aOperands[pThis->iRmOp ].idxField = BS3CG1DST_YMM4;
+        pThis->aOperands[pThis->iRegOp].idxField = BS3CG1DST_YMM5;
+    }
+    else if (iEncoding == 13)
+    {
+        off = Bs3Cg1InsertVex2bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 1 /*L*/, 1 /*~R*/);
+        off = Bs3Cg1InsertOpcodes(pThis, off);
+        off = Bs3Cfg1EncodeMemMod0Disp(pThis, false, off, 2 /*iReg*/, 32, 0, BS3CG1OPLOC_MEM);
+        pThis->aOperands[pThis->iRegOp].idxField = BS3CG1DST_YMM2;
+    }
+    else if (iEncoding == 14)
+    {
+        off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 1 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 0 /*W*/);
+        off = Bs3Cg1InsertOpcodes(pThis, off);
+        off = Bs3Cfg1EncodeMemMod0Disp(pThis, false, off, 3 /*iReg*/, 32, 0, BS3CG1OPLOC_MEM);
+        pThis->aOperands[pThis->iRegOp].idxField = BS3CG1DST_YMM3;
+    }
+    else if (iEncoding == 15)
+    {
+        off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 1 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 1 /*W - ignored */);
+        off = Bs3Cg1InsertOpcodes(pThis, off);
+        off = Bs3Cfg1EncodeMemMod0Disp(pThis, false, off, 3 /*iReg*/, 32, 0, BS3CG1OPLOC_MEM);
+        pThis->aOperands[pThis->iRegOp].idxField = BS3CG1DST_YMM3;
+    }
+    else if (iEncoding == 16)
+    {
+        off = Bs3Cg1InsertVex2bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 1 /*L*/, 1 /*~R*/);
+        off = Bs3Cg1InsertOpcodes(pThis, off);
+        off = Bs3Cfg1EncodeMemMod0Disp(pThis, false, off, 3 /*iReg*/, 32, 1 /*cbMisalign*/, BS3CG1OPLOC_MEM);
+        if (!Bs3Cg1XcptTypeIsVexUnaligned(pThis->enmXcptType))
+            pThis->bAlignmentXcpt = X86_XCPT_GP;
+        pThis->aOperands[pThis->iRegOp].idxField = BS3CG1DST_YMM3;
+    }
+    else if (iEncoding == 17)
+    {
+        off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 1 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 0 /*W*/);
+        off = Bs3Cg1InsertOpcodes(pThis, off);
+        off = Bs3Cfg1EncodeMemMod0Disp(pThis, false, off, 3 /*iReg*/, 32, 1 /*cbMisalign*/, BS3CG1OPLOC_MEM);
+        if (!Bs3Cg1XcptTypeIsVexUnaligned(pThis->enmXcptType))
+            pThis->bAlignmentXcpt = X86_XCPT_GP;
+        pThis->aOperands[pThis->iRegOp].idxField = BS3CG1DST_YMM3;
+    }
+    /* 256-bit invalid encodings: */
+    else if (iEncoding == 18)
+    {
+        off = Bs3Cg1InsertVex2bPrefix(pThis, 0 /*offDst*/, 0xe /*~V - invalid */, 1 /*L*/, 1 /*~R*/); /* Bad V value */
+        off = Bs3Cg1InsertOpcodes(pThis, off);
+        pThis->abCurInstr[off++] = X86_MODRM_MAKE(3, 1, 0);
+        pThis->aOperands[pThis->iRmOp ].idxField = BS3CG1DST_YMM0;
+        pThis->aOperands[pThis->iRegOp].idxField = BS3CG1DST_YMM1;
+        pThis->fInvalidEncoding = true;
+    }
+    else if (iEncoding == 19)
+    {
+        off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0 /*~V - invalid */, 1 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 0 /*W*/);
+        off = Bs3Cg1InsertOpcodes(pThis, off);
+        pThis->abCurInstr[off++] = X86_MODRM_MAKE(3, 4, 5);
+        pThis->aOperands[pThis->iRmOp ].idxField = BS3CG1DST_YMM5;
+        pThis->aOperands[pThis->iRegOp].idxField = BS3CG1DST_YMM4;
+        pThis->fInvalidEncoding = true;
+    }
+    else if (iEncoding == 20)
+    {
+        pThis->abCurInstr[0] = P_RN;
+        off = Bs3Cg1InsertVex3bPrefix(pThis, 1 /*offDst*/, 0xf /*~V*/, 1 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 0 /*W*/);
+        off = Bs3Cg1InsertOpcodes(pThis, off);
+        pThis->abCurInstr[off++] = X86_MODRM_MAKE(3, 4, 5);
+        pThis->aOperands[pThis->iRmOp ].idxField = BS3CG1DST_YMM5;
+        pThis->aOperands[pThis->iRegOp].idxField = BS3CG1DST_YMM4;
+        pThis->fInvalidEncoding = true;
+    }
+    else if (iEncoding == 21)
+    {
+        pThis->abCurInstr[0] = P_RZ;
+        off = Bs3Cg1InsertVex3bPrefix(pThis, 1 /*offDst*/, 0xf /*~V*/, 1 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 0 /*W*/);
+        off = Bs3Cg1InsertOpcodes(pThis, off);
+        pThis->abCurInstr[off++] = X86_MODRM_MAKE(3, 4, 5);
+        pThis->aOperands[pThis->iRmOp ].idxField = BS3CG1DST_YMM5;
+        pThis->aOperands[pThis->iRegOp].idxField = BS3CG1DST_YMM4;
+        pThis->fInvalidEncoding = true;
+    }
+    else if (iEncoding == 22)
+    {
+        pThis->abCurInstr[0] = P_OZ;
+        off = Bs3Cg1InsertVex3bPrefix(pThis, 1 /*offDst*/, 0xf /*~V*/, 1 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 0 /*W*/);
+        off = Bs3Cg1InsertOpcodes(pThis, off);
+        pThis->abCurInstr[off++] = X86_MODRM_MAKE(3, 4, 5);
+        pThis->aOperands[pThis->iRmOp ].idxField = BS3CG1DST_YMM5;
+        pThis->aOperands[pThis->iRegOp].idxField = BS3CG1DST_YMM4;
+        pThis->fInvalidEncoding = true;
+    }
+    else if (iEncoding == 23)
+    {
+        pThis->abCurInstr[0] = P_LK;
+        off = Bs3Cg1InsertVex3bPrefix(pThis, 1 /*offDst*/, 0xf /*~V*/, 1 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 0 /*W*/);
+        off = Bs3Cg1InsertOpcodes(pThis, off);
+        pThis->abCurInstr[off++] = X86_MODRM_MAKE(3, 4, 5);
+        pThis->aOperands[pThis->iRmOp ].idxField = BS3CG1DST_YMM5;
+        pThis->aOperands[pThis->iRegOp].idxField = BS3CG1DST_YMM4;
+        pThis->fInvalidEncoding = true;
+    }
+#if ARCH_BITS == 64
+    /* 64-bit mode registers */
+    else if (BS3CG1_IS_64BIT_TARGET(pThis))
+    {
+        if (iEncoding == 24)
+        {
+            off = Bs3Cg1InsertVex2bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 1 /*L*/, 0 /*~R*/);
+            off = Bs3Cg1InsertOpcodes(pThis, off);
+            pThis->abCurInstr[off++] = X86_MODRM_MAKE(3, 3, 4);
+            pThis->aOperands[pThis->iRmOp ].idxField = BS3CG1DST_YMM4;
+            pThis->aOperands[pThis->iRegOp].idxField = BS3CG1DST_YMM11;
+        }
+        else if (iEncoding == 25)
+        {
+            off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 1 /*L*/, 0 /*~R*/, 1 /*~X*/, 0 /*~B*/, 0 /*W*/);
+            off = Bs3Cg1InsertOpcodes(pThis, off);
+            pThis->abCurInstr[off++] = X86_MODRM_MAKE(3, 1, 4);
+            pThis->aOperands[pThis->iRmOp ].idxField = BS3CG1DST_YMM12;
+            pThis->aOperands[pThis->iRegOp].idxField = BS3CG1DST_YMM9;
+        }
+        else
+            return 0;
+    }
+#endif
+    else
+        return 0;
+    pThis->cbCurInstr = off;
+    return iEncoding + 1;
+}
+
+
+/**
+ * Wip - VEX.W ignored.
+ * Lig - VEX.L ignored.
+ */
+static unsigned BS3_NEAR_CODE
+Bs3Cg1EncodeNext_VEX_MODRM_VsomethingWO_Hsomething_Usomething_Lip_Wip_OR_ViceVersa(PBS3CG1STATE pThis, unsigned iEncoding)
+{
+    unsigned off;
+    switch (iEncoding)
+    {
+        case 0:
+            off = Bs3Cg1InsertVex2bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 0 /*L*/, 1 /*~R*/);
+            off = Bs3Cg1InsertOpcodes(pThis, off);
+            pThis->abCurInstr[off++] = X86_MODRM_MAKE(3, 2, 1);
+            pThis->aOperands[pThis->iRegOp].idxField = pThis->aOperands[pThis->iRegOp].idxFieldBase + 2;
+            pThis->aOperands[1            ].idxField = pThis->aOperands[1            ].idxFieldBase + 0;
+            pThis->aOperands[pThis->iRmOp ].idxField = pThis->aOperands[pThis->iRmOp ].idxFieldBase + 1;
+            break;
+        case 1:
+            off = Bs3Cg1InsertVex2bPrefix(pThis, 0 /*offDst*/, 0x8 /*~V*/, 1 /*L-ignored*/, 1 /*~R*/);
+            off = Bs3Cg1InsertOpcodes(pThis, off);
+            pThis->abCurInstr[off++] = X86_MODRM_MAKE(3, 3, 1);
+            pThis->aOperands[pThis->iRegOp].idxField = pThis->aOperands[pThis->iRegOp].idxFieldBase + 3;
+            pThis->aOperands[1            ].idxField = pThis->aOperands[1            ].idxFieldBase + 7;
+            pThis->aOperands[pThis->iRmOp ].idxField = pThis->aOperands[pThis->iRmOp ].idxFieldBase + 1;
+            iEncoding += !BS3CG1_IS_64BIT_TARGET(pThis) ? 1 : 0;
+            break;
+        case 2:
+#if ARCH_BITS == 64
+            off = Bs3Cg1InsertVex2bPrefix(pThis, 0 /*offDst*/, 0 /*~V*/, 0 /*L*/, 0 /*~R*/);
+            off = Bs3Cg1InsertOpcodes(pThis, off);
+            pThis->abCurInstr[off++] = X86_MODRM_MAKE(3, 3, 2);
+            pThis->aOperands[pThis->iRegOp].idxField = pThis->aOperands[pThis->iRegOp].idxFieldBase + 11;
+            pThis->aOperands[1            ].idxField = pThis->aOperands[1            ].idxFieldBase + 15;
+            pThis->aOperands[pThis->iRmOp ].idxField = pThis->aOperands[pThis->iRmOp ].idxFieldBase + 2;
+            break;
+#endif
+        case 3:
+            off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 0 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 0 /*W*/);
+            off = Bs3Cg1InsertOpcodes(pThis, off);
+            pThis->abCurInstr[off++] = X86_MODRM_MAKE(3, 2, 1);
+            pThis->aOperands[pThis->iRegOp].idxField = pThis->aOperands[pThis->iRegOp].idxFieldBase + 2;
+            pThis->aOperands[1            ].idxField = pThis->aOperands[1            ].idxFieldBase + 0;
+            pThis->aOperands[pThis->iRmOp ].idxField = pThis->aOperands[pThis->iRmOp ].idxFieldBase + 1;
+            break;
+        case 4:
+            off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 1 /*L - ignored*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 0 /*W*/);
+            off = Bs3Cg1InsertOpcodes(pThis, off);
+            pThis->abCurInstr[off++] = X86_MODRM_MAKE(3, 2, 1);
+            pThis->aOperands[pThis->iRegOp].idxField = pThis->aOperands[pThis->iRegOp].idxFieldBase + 2;
+            pThis->aOperands[1            ].idxField = pThis->aOperands[1            ].idxFieldBase + 0;
+            pThis->aOperands[pThis->iRmOp ].idxField = pThis->aOperands[pThis->iRmOp ].idxFieldBase + 1;
+            break;
+        case 5:
+            off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xc /*~V*/, 0 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 1 /*W-ignored*/);
+            off = Bs3Cg1InsertOpcodes(pThis, off);
+            pThis->abCurInstr[off++] = X86_MODRM_MAKE(3, 2, 1);
+            pThis->aOperands[pThis->iRegOp].idxField = pThis->aOperands[pThis->iRegOp].idxFieldBase + 2;
+            pThis->aOperands[1            ].idxField = pThis->aOperands[1            ].idxFieldBase + 3;
+            pThis->aOperands[pThis->iRmOp ].idxField = pThis->aOperands[pThis->iRmOp ].idxFieldBase + 1;
+            break;
+        case 6:
+            off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0 /*~V*/, 0 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 1 /*W-ignored*/);
+            off = Bs3Cg1InsertOpcodes(pThis, off);
+            pThis->abCurInstr[off++] = X86_MODRM_MAKE(3, 2, 1);
+            pThis->aOperands[pThis->iRegOp].idxField = pThis->aOperands[pThis->iRegOp].idxFieldBase + 2;
+            pThis->aOperands[1            ].idxField = pThis->aOperands[1            ].idxFieldBase + (BS3CG1_IS_64BIT_TARGET(pThis) ? 15 : 7);
+            pThis->aOperands[pThis->iRmOp ].idxField = pThis->aOperands[pThis->iRmOp ].idxFieldBase + 1;
+            break;
+        case 7:
+            off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0 /*~V*/, 0 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 0 /*W*/);
+            off = Bs3Cg1InsertOpcodes(pThis, off);
+            pThis->abCurInstr[off++] = X86_MODRM_MAKE(3, 2, 1);
+            pThis->aOperands[pThis->iRegOp].idxField = pThis->aOperands[pThis->iRegOp].idxFieldBase + 2;
+            pThis->aOperands[1            ].idxField = pThis->aOperands[1            ].idxFieldBase + (BS3CG1_IS_64BIT_TARGET(pThis) ? 15 : 7);
+            pThis->aOperands[pThis->iRmOp ].idxField = pThis->aOperands[pThis->iRmOp ].idxFieldBase + 1;
+            break;
+        default:
+            return 0;
+    }
+    pThis->cbCurInstr = off;
+    return iEncoding + 1;
+}
+
+
+/**
+ * Wip - VEX.W ignored.
+ */
+static unsigned BS3_NEAR_CODE
+Bs3Cg1EncodeNext_VEX_MODRM_VsomethingWO_HdqCsomething_Usomething_Wip_OR_ViceVersa(PBS3CG1STATE pThis, unsigned iEncoding)
+{
+    unsigned off;
+    switch (iEncoding)
+    {
+        case 0:
+            off = Bs3Cg1InsertVex2bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 0 /*L*/, 1 /*~R*/);
+            off = Bs3Cg1InsertOpcodes(pThis, off);
+            pThis->abCurInstr[off++] = X86_MODRM_MAKE(3, 2, 1);
+            pThis->aOperands[pThis->iRegOp].idxField = pThis->aOperands[pThis->iRegOp].idxFieldBase + 2;
+            pThis->aOperands[1            ].idxField = pThis->aOperands[1            ].idxFieldBase + 0;
+            pThis->aOperands[pThis->iRmOp ].idxField = pThis->aOperands[pThis->iRmOp ].idxFieldBase + 1;
+            break;
+        case 1:
+            off = Bs3Cg1InsertVex2bPrefix(pThis, 0 /*offDst*/, 0x8 /*~V*/, 1 /*L-ignored*/, 1 /*~R*/);
+            off = Bs3Cg1InsertOpcodes(pThis, off);
+            pThis->abCurInstr[off++] = X86_MODRM_MAKE(3, 3, 1);
+            pThis->aOperands[pThis->iRegOp].idxField = pThis->aOperands[pThis->iRegOp].idxFieldBase + 3;
+            pThis->aOperands[1            ].idxField = pThis->aOperands[1            ].idxFieldBase + 7;
+            pThis->aOperands[pThis->iRmOp ].idxField = pThis->aOperands[pThis->iRmOp ].idxFieldBase + 1;
+            pThis->fInvalidEncoding = true;
+            iEncoding += !BS3CG1_IS_64BIT_TARGET(pThis) ? 1 : 0;
+            break;
+        case 2:
+#if ARCH_BITS == 64
+            off = Bs3Cg1InsertVex2bPrefix(pThis, 0 /*offDst*/, 0 /*~V*/, 0 /*L*/, 0 /*~R*/);
+            off = Bs3Cg1InsertOpcodes(pThis, off);
+            pThis->abCurInstr[off++] = X86_MODRM_MAKE(3, 3, 2);
+            pThis->aOperands[pThis->iRegOp].idxField = pThis->aOperands[pThis->iRegOp].idxFieldBase + 11;
+            pThis->aOperands[1            ].idxField = pThis->aOperands[1            ].idxFieldBase + 15;
+            pThis->aOperands[pThis->iRmOp ].idxField = pThis->aOperands[pThis->iRmOp ].idxFieldBase + 2;
+            break;
+#endif
+        case 3:
+            off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 0 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 0 /*W*/);
+            off = Bs3Cg1InsertOpcodes(pThis, off);
+            pThis->abCurInstr[off++] = X86_MODRM_MAKE(3, 2, 1);
+            pThis->aOperands[pThis->iRegOp].idxField = pThis->aOperands[pThis->iRegOp].idxFieldBase + 2;
+            pThis->aOperands[1            ].idxField = pThis->aOperands[1            ].idxFieldBase + 0;
+            pThis->aOperands[pThis->iRmOp ].idxField = pThis->aOperands[pThis->iRmOp ].idxFieldBase + 1;
+            break;
+        case 4:
+            off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 1 /*L - ignored*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 0 /*W*/);
+            off = Bs3Cg1InsertOpcodes(pThis, off);
+            pThis->abCurInstr[off++] = X86_MODRM_MAKE(3, 2, 1);
+            pThis->aOperands[pThis->iRegOp].idxField = pThis->aOperands[pThis->iRegOp].idxFieldBase + 2;
+            pThis->aOperands[1            ].idxField = pThis->aOperands[1            ].idxFieldBase + 0;
+            pThis->aOperands[pThis->iRmOp ].idxField = pThis->aOperands[pThis->iRmOp ].idxFieldBase + 1;
+            pThis->fInvalidEncoding = true;
+            break;
+        case 5:
+            off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xc /*~V*/, 0 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 1 /*W-ignored*/);
+            off = Bs3Cg1InsertOpcodes(pThis, off);
+            pThis->abCurInstr[off++] = X86_MODRM_MAKE(3, 2, 1);
+            pThis->aOperands[pThis->iRegOp].idxField = pThis->aOperands[pThis->iRegOp].idxFieldBase + 2;
+            pThis->aOperands[1            ].idxField = pThis->aOperands[1            ].idxFieldBase + 3;
+            pThis->aOperands[pThis->iRmOp ].idxField = pThis->aOperands[pThis->iRmOp ].idxFieldBase + 1;
+            break;
+        case 6:
+            off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0 /*~V*/, 0 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 1 /*W-ignored*/);
+            off = Bs3Cg1InsertOpcodes(pThis, off);
+            pThis->abCurInstr[off++] = X86_MODRM_MAKE(3, 2, 1);
+            pThis->aOperands[pThis->iRegOp].idxField = pThis->aOperands[pThis->iRegOp].idxFieldBase + 2;
+            pThis->aOperands[1            ].idxField = pThis->aOperands[1            ].idxFieldBase + (BS3CG1_IS_64BIT_TARGET(pThis) ? 15 : 7);
+            pThis->aOperands[pThis->iRmOp ].idxField = pThis->aOperands[pThis->iRmOp ].idxFieldBase + 1;
+            break;
+        case 7:
+            off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0 /*~V*/, 0 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 0 /*W*/);
+            off = Bs3Cg1InsertOpcodes(pThis, off);
+            pThis->abCurInstr[off++] = X86_MODRM_MAKE(3, 2, 1);
+            pThis->aOperands[pThis->iRegOp].idxField = pThis->aOperands[pThis->iRegOp].idxFieldBase + 2;
+            pThis->aOperands[1            ].idxField = pThis->aOperands[1            ].idxFieldBase + (BS3CG1_IS_64BIT_TARGET(pThis) ? 15 : 7);
+            pThis->aOperands[pThis->iRmOp ].idxField = pThis->aOperands[pThis->iRmOp ].idxFieldBase + 1;
+            break;
+        default:
+            return 0;
+    }
+    pThis->cbCurInstr = off;
+    return iEncoding + 1;
+}
+
+
+/**
+ * Wip - VEX.W ignored.
+ */
+static unsigned BS3_NEAR_CODE
+Bs3Cg1EncodeNext_VEX_MODRM_VsomethingWO_Msomething_Wip_OR_ViceVersa(PBS3CG1STATE pThis, unsigned iEncoding)
+{
+    unsigned off;
+    switch (iEncoding)
+    {
+        case 20: /* Switch to 256-bit operands. */
+            pThis->aOperands[pThis->iRegOp].idxFieldBase = BS3CG1DST_YMM0;
+            pThis->aOperands[pThis->iRegOp].cbOp = 32;
+            pThis->aOperands[pThis->iRmOp ].cbOp = 32;
+            /* fall thru */
+        case 0:
+            off = Bs3Cg1InsertVex2bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, iEncoding >= 20 /*L*/, 1 /*~R*/);
+            off = Bs3Cg1InsertOpcodes(pThis, off);
+            off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, false, off, 0, 0);
+            iEncoding += !BS3CG1_IS_64BIT_TARGET(pThis) ? 1 : 0;
+            break;
+#if ARCH_BITS == 64
+        case 1:
+        case 21:
+            off = Bs3Cg1InsertVex2bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, iEncoding >= 20 /*L*/, 0 /*~R*/);
+            off = Bs3Cg1InsertOpcodes(pThis, off);
+            off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, false, off, 7 + 8, 0);
+            break;
+#endif
+        case 2:
+        case 22:
+            off = Bs3Cg1InsertVex2bPrefix(pThis, 0 /*offDst*/, 0xe /*~V*/, iEncoding >= 20 /*L*/, 1 /*~R*/);
+            off = Bs3Cg1InsertOpcodes(pThis, off);
+            off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, false, off, 0, 0);
+            pThis->fInvalidEncoding = true;
+            break;
+        case 3:
+        case 23:
+            off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, iEncoding >= 20 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 0 /*W*/);
+            off = Bs3Cg1InsertOpcodes(pThis, off);
+            off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, false, off, 1, 0);
+            break;
+        case 4:
+        case 24:
+            off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, iEncoding >= 20 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 1 /*W-ignored*/);
+            off = Bs3Cg1InsertOpcodes(pThis, off);
+            off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, false, off, 5, 0);
+            iEncoding += !BS3CG1_IS_64BIT_TARGET(pThis) ? 3 : 0;
+            break;
+#if ARCH_BITS == 64
+        case 5:
+        case 25:
+            off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, iEncoding >= 20 /*L*/, 0 /*~R*/, 1 /*~X*/, 1 /*~B*/, 0 /*W*/);
+            off = Bs3Cg1InsertOpcodes(pThis, off);
+            off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, false, off, 5+8, 0);
+            break;
+        case 6:
+        case 26:
+            off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, iEncoding >= 20 /*L*/, 1 /*~R*/, 1 /*~X*/, 0 /*~B-ignored*/, 0 /*W*/);
+            off = Bs3Cg1InsertOpcodes(pThis, off);
+            off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, false, off, 1, 0);
+            break;
+        case 7:
+        case 27:
+            off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, iEncoding >= 20 /*L*/, 1 /*~R*/, 0 /*~X-ignored*/, 1 /*~B*/, 0 /*W*/);
+            off = Bs3Cg1InsertOpcodes(pThis, off);
+            off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, false, off, 2, 0);
+            break;
+#endif
+        case 8:
+        case 28:
+            off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0 /*~V*/, iEncoding >= 20 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 0 /*W*/);
+            off = Bs3Cg1InsertOpcodes(pThis, off);
+            off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, false, off, 5, 0);
+            pThis->fInvalidEncoding = true;
+            break;
+        case 9:
+        case 29:
+            off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 7 /*~V*/, iEncoding >= 20 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 0 /*W*/);
+            off = Bs3Cg1InsertOpcodes(pThis, off);
+            off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, false, off, 2, 0);
+            pThis->fInvalidEncoding = true;
+            iEncoding += 10;
+            break;
+
+        default:
+            return 0;
+    }
+    pThis->cbCurInstr = off;
+    return iEncoding + 1;
+}
+
+
+
+/**
+ * Wip - VEX.W ignored.
+ * Lig - VEX.L ignored.
+ */
+static unsigned BS3_NEAR_CODE
+Bs3Cg1EncodeNext_VEX_MODRM_VsomethingWO_Msomething_Wip_Lig_OR_ViceVersa(PBS3CG1STATE pThis, unsigned iEncoding)
+{
+    unsigned off;
+    switch (iEncoding)
+    {
+        case 0:
+            off = Bs3Cg1InsertVex2bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 0 /*L*/, 1 /*~R*/);
+            off = Bs3Cg1InsertOpcodes(pThis, off);
+            off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, false, off, 0, 0);
+            break;
+        case 1:
+            off = Bs3Cg1InsertVex2bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 1 /*L - ignored*/, 1 /*~R*/);
+            off = Bs3Cg1InsertOpcodes(pThis, off);
+            off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, false, off, 7, 0);
+            iEncoding += !BS3CG1_IS_64BIT_TARGET(pThis) ? 1 : 0;
+            break;
+#if ARCH_BITS == 64
+        case 2:
+            off = Bs3Cg1InsertVex2bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 1 /*L - ignored*/, 0 /*~R*/);
+            off = Bs3Cg1InsertOpcodes(pThis, off);
+            off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, false, off, 7 + 8, 0);
+            break;
+#endif
+        case 3:
+            iEncoding = 3;
+            off = Bs3Cg1InsertVex2bPrefix(pThis, 0 /*offDst*/, 0xe /*~V*/, 0 /*L*/, 1 /*~R*/);
+            off = Bs3Cg1InsertOpcodes(pThis, off);
+            off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, false, off, 0, 0);
+            pThis->fInvalidEncoding = true;
+            break;
+        case 4:
+            off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 0 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 0 /*W*/);
+            off = Bs3Cg1InsertOpcodes(pThis, off);
+            off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, false, off, 1, 0);
+            break;
+        case 5:
+            off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 1 /*L-ignored*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 0 /*W*/);
+            off = Bs3Cg1InsertOpcodes(pThis, off);
+            off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, false, off, 1, 0);
+            break;
+        case 6:
+            off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 0 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 1 /*W-ignored*/);
+            off = Bs3Cg1InsertOpcodes(pThis, off);
+            off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, false, off, 5, 0);
+            iEncoding += !BS3CG1_IS_64BIT_TARGET(pThis) ? 3 : 0;
+            break;
+#if ARCH_BITS == 64
+        case 7:
+            off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 0 /*L*/, 0 /*~R*/, 1 /*~X*/, 1 /*~B*/, 0 /*W*/);
+            off = Bs3Cg1InsertOpcodes(pThis, off);
+            off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, false, off, 5+8, 0);
+            break;
+        case 8:
+            off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 0 /*L*/, 1 /*~R*/, 1 /*~X*/, 0 /*~B-ignored*/, 0 /*W*/);
+            off = Bs3Cg1InsertOpcodes(pThis, off);
+            off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, false, off, 1, 0);
+            break;
+        case 9:
+            off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 0 /*L*/, 1 /*~R*/, 0 /*~X-ignored*/, 1 /*~B*/, 0 /*W*/);
+            off = Bs3Cg1InsertOpcodes(pThis, off);
+            off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, false, off, 2, 0);
+            break;
+#endif
+        case 10:
+            off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0 /*~V*/, 0 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 0 /*W*/);
+            off = Bs3Cg1InsertOpcodes(pThis, off);
+            off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, false, off, 5, 0);
+            pThis->fInvalidEncoding = true;
+            break;
+        case 11:
+            off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 7 /*~V*/, 0 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 0 /*W*/);
+            off = Bs3Cg1InsertOpcodes(pThis, off);
+            off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, false, off, 2, 0);
+            pThis->fInvalidEncoding = true;
+            break;
+        default:
+            return 0;
+    }
+    pThis->cbCurInstr = off;
+    return iEncoding + 1;
+}
+
+
+/**
+ * Wip - VEX.W ignored.
+ * L0 - VEX.L must be zero.
+ */
+static unsigned BS3_NEAR_CODE
+Bs3Cg1EncodeNext_VEX_MODRM_VsomethingWO_Msomething_Wip_L0_OR_ViceVersa(PBS3CG1STATE pThis, unsigned iEncoding)
+{
+    unsigned off;
+    switch (iEncoding)
+    {
+        case 0:
+            off = Bs3Cg1InsertVex2bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 0 /*L*/, 1 /*~R*/);
+            off = Bs3Cg1InsertOpcodes(pThis, off);
+            off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, false, off, 0, 0);
+            break;
+        case 1:
+            off = Bs3Cg1InsertVex2bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 1 /*L - invalid*/, 1 /*~R*/);
+            off = Bs3Cg1InsertOpcodes(pThis, off);
+            off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, false, off, 7, 0);
+            pThis->fInvalidEncoding = true;
+            iEncoding += !BS3CG1_IS_64BIT_TARGET(pThis) ? 2 : 0;
+            break;
+#if ARCH_BITS == 64
+        case 2:
+            off = Bs3Cg1InsertVex2bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 0 /*L*/, 0 /*~R*/);
+            off = Bs3Cg1InsertOpcodes(pThis, off);
+            off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, false, off, 7 + 8, 0);
+            break;
+        case 3:
+            off = Bs3Cg1InsertVex2bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 1 /*L - invalid*/, 0 /*~R*/);
+            off = Bs3Cg1InsertOpcodes(pThis, off);
+            off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, false, off, 5 + 8, 0);
+            pThis->fInvalidEncoding = true;
+            break;
+#endif
+        case 4:
+            off = Bs3Cg1InsertVex2bPrefix(pThis, 0 /*offDst*/, 0xe /*~V*/, 0 /*L*/, 1 /*~R*/);
+            off = Bs3Cg1InsertOpcodes(pThis, off);
+            off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, false, off, 0, 0);
+            pThis->fInvalidEncoding = true;
+            break;
+        case 5:
+            off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 0 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 0 /*W*/);
+            off = Bs3Cg1InsertOpcodes(pThis, off);
+            off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, false, off, 1, 0);
+            break;
+        case 6:
+            off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 1 /*L - invalid*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 0 /*W*/);
+            off = Bs3Cg1InsertOpcodes(pThis, off);
+            off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, false, off, 1, 0);
+            pThis->fInvalidEncoding = true;
+            break;
+        case 7:
+            off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 0 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 1 /*W-ignored*/);
+            off = Bs3Cg1InsertOpcodes(pThis, off);
+            off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, false, off, 5, 0);
+            iEncoding += !BS3CG1_IS_64BIT_TARGET(pThis) ? 3 : 0;
+            break;
+#if ARCH_BITS == 64
+        case 8:
+            off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 0 /*L*/, 0 /*~R*/, 1 /*~X*/, 1 /*~B*/, 0 /*W*/);
+            off = Bs3Cg1InsertOpcodes(pThis, off);
+            off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, false, off, 5+8, 0);
+            break;
+        case 9:
+            off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 0 /*L*/, 1 /*~R*/, 1 /*~X*/, 0 /*~B-ignored*/, 0 /*W*/);
+            off = Bs3Cg1InsertOpcodes(pThis, off);
+            off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, false, off, 1, 0);
+            break;
+        case 10:
+            off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 0 /*L*/, 1 /*~R*/, 0 /*~X-ignored*/, 1 /*~B*/, 0 /*W*/);
+            off = Bs3Cg1InsertOpcodes(pThis, off);
+            off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, false, off, 2, 0);
+            break;
+#endif
+        case 11:
+            off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0 /*~V*/, 0 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 0 /*W*/);
+            off = Bs3Cg1InsertOpcodes(pThis, off);
+            off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, false, off, 5, 0);
+            pThis->fInvalidEncoding = true;
+            break;
+        case 12:
+            off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 7 /*~V*/, 0 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 0 /*W*/);
+            off = Bs3Cg1InsertOpcodes(pThis, off);
+            off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, false, off, 2, 0);
+            pThis->fInvalidEncoding = true;
+            break;
+        default:
+            return 0;
+    }
+    pThis->cbCurInstr = off;
+    return iEncoding + 1;
+}
+
+
+/**
+ * Wip - VEX.W ignored.
+ */
+static unsigned BS3_NEAR_CODE
+Bs3Cg1EncodeNext_VEX_MODRM_VsomethingWO_Hsomething_Msomething_Wip_OR_ViceVersa(PBS3CG1STATE pThis, unsigned iEncoding)
+{
+    unsigned off;
+    switch (iEncoding)
+    {
+        case 0:
+            off = Bs3Cg1InsertVex2bPrefix(pThis, 0 /*offDst*/, 0xc /*~V*/, 0 /*L*/, 1 /*~R*/);
+            off = Bs3Cg1InsertOpcodes(pThis, off);
+            off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, false, off, 0, 0);
+            pThis->aOperands[1].idxField = pThis->aOperands[1].idxFieldBase + 3;
+            break;
+        case 1:
+            off = Bs3Cg1InsertVex2bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 1 /*L*/, 1 /*~R*/);
+            off = Bs3Cg1InsertOpcodes(pThis, off);
+            off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, false, off, 7, 0);
+            pThis->aOperands[1].idxField = pThis->aOperands[1].idxFieldBase + 0;
+            pThis->fInvalidEncoding = true;
+            iEncoding += !BS3CG1_IS_64BIT_TARGET(pThis) ? 1 : 0;
+            break;
+#if ARCH_BITS == 64
+        case 2:
+            off = Bs3Cg1InsertVex2bPrefix(pThis, 0 /*offDst*/, 0x1 /*~V*/, 0 /*L*/, 0 /*~R*/);
+            off = Bs3Cg1InsertOpcodes(pThis, off);
+            off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, false, off, 7 + 8, 0);
+            pThis->aOperands[1].idxField = pThis->aOperands[1].idxFieldBase + 14;
+            break;
+#endif
+        case 3:
+            off = Bs3Cg1InsertVex2bPrefix(pThis, 0 /*offDst*/, 0xe /*~V*/, 0 /*L*/, 1 /*~R*/);
+            off = Bs3Cg1InsertOpcodes(pThis, off);
+            off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, false, off, 0, 0);
+            pThis->aOperands[1].idxField = pThis->aOperands[1].idxFieldBase + 1;
+            break;
+        case 4:
+            off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 0 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 0 /*W*/);
+            off = Bs3Cg1InsertOpcodes(pThis, off);
+            off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, false, off, 1, 0);
+            pThis->aOperands[1].idxField = pThis->aOperands[1].idxFieldBase + 0;
+            break;
+        case 5:
+            off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 1 /*L-ignored*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 0 /*W*/);
+            off = Bs3Cg1InsertOpcodes(pThis, off);
+            off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, false, off, 1, 0);
+            pThis->aOperands[1].idxField = pThis->aOperands[1].idxFieldBase + 0;
+            pThis->fInvalidEncoding = true;
+            break;
+        case 6:
+            off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 0 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 1 /*W-ignored*/);
+            off = Bs3Cg1InsertOpcodes(pThis, off);
+            off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, false, off, 5, 0);
+            pThis->aOperands[1].idxField = pThis->aOperands[1].idxFieldBase + 0;
+            iEncoding += !BS3CG1_IS_64BIT_TARGET(pThis) ? 3 : 0;
+            break;
+#if ARCH_BITS == 64
+        case 7:
+            off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 0 /*L*/, 0 /*~R*/, 1 /*~X*/, 1 /*~B*/, 0 /*W*/);
+            off = Bs3Cg1InsertOpcodes(pThis, off);
+            off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, false, off, 5+8, 0);
+            pThis->aOperands[1].idxField = pThis->aOperands[1].idxFieldBase + 0;
+            break;
+        case 8:
+            off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 0 /*L*/, 1 /*~R*/, 1 /*~X*/, 0 /*~B-ignored*/, 0 /*W*/);
+            off = Bs3Cg1InsertOpcodes(pThis, off);
+            off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, false, off, 1, 0);
+            pThis->aOperands[1].idxField = pThis->aOperands[1].idxFieldBase + 0;
+            break;
+        case 9:
+            off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 0 /*L*/, 1 /*~R*/, 0 /*~X-ignored*/, 1 /*~B*/, 0 /*W*/);
+            off = Bs3Cg1InsertOpcodes(pThis, off);
+            off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, false, off, 2, 0);
+            pThis->aOperands[1].idxField = pThis->aOperands[1].idxFieldBase + 0;
+            break;
+#endif
+        case 10:
+            off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0 /*~V*/, 1 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 0 /*W*/);
+            off = Bs3Cg1InsertOpcodes(pThis, off);
+            off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, false, off, 5, 0);
+            pThis->aOperands[1].idxField = pThis->aOperands[1].idxFieldBase + (BS3CG1_IS_64BIT_TARGET(pThis) ? 15 : 7);
+            pThis->fInvalidEncoding = true;
+            break;
+        default:
+            return 0;
+    }
+    pThis->cbCurInstr = off;
+    return iEncoding + 1;
+}
+
+
+static unsigned BS3_NEAR_CODE Bs3Cg1EncodeNext_VEX_MODRM_Md_WO(PBS3CG1STATE pThis, unsigned iEncoding)
+{
+    unsigned off;
+    if (iEncoding == 0)
+    {
+        /** @todo three by opcode needs some tweaking. */
+        off = Bs3Cg1InsertVex2bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 0 /*L*/, 1 /*~R*/);
+        off = Bs3Cg1InsertOpcodes(pThis, off) - 1;
+        off = Bs3Cfg1EncodeMemMod0Disp(pThis, false, off,
+                                       (pThis->abCurInstr[off] & X86_MODRM_REG_MASK) >> X86_MODRM_REG_SHIFT,
+                                       4, 0, BS3CG1OPLOC_MEM_WO);
+    }
+    else if (iEncoding == 1)
+    {
+        off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 0 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 0 /*W*/);
+        off = Bs3Cg1InsertOpcodes(pThis, off) - 1;
+        off = Bs3Cfg1EncodeMemMod0Disp(pThis, false, off,
+                                       (pThis->abCurInstr[off] & X86_MODRM_REG_MASK) >> X86_MODRM_REG_SHIFT,
+                                       4, 0, BS3CG1OPLOC_MEM_WO);
+    }
+    else if (iEncoding == 2)
+    {
+        off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0x7 /*~V-invalid*/, 0 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 0 /*W*/);
+        off = Bs3Cg1InsertOpcodes(pThis, off) - 1;
+        off = Bs3Cfg1EncodeMemMod0Disp(pThis, false, off,
+                                       (pThis->abCurInstr[off] & X86_MODRM_REG_MASK) >> X86_MODRM_REG_SHIFT,
+                                       4, 0, BS3CG1OPLOC_MEM_WO);
+        pThis->fInvalidEncoding = true;
+    }
+    else if (iEncoding == 3)
+    {
+        off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 1 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 0 /*W*/);
+        off = Bs3Cg1InsertOpcodes(pThis, off) - 1;
+        off = Bs3Cfg1EncodeMemMod0Disp(pThis, false, off,
+                                       (pThis->abCurInstr[off] & X86_MODRM_REG_MASK) >> X86_MODRM_REG_SHIFT,
+                                       4, 0, BS3CG1OPLOC_MEM_WO);
+        pThis->fInvalidEncoding = true;
+    }
+    else if (iEncoding == 4)
+    {
+        pThis->abCurInstr[0] = P_OZ;
+        off = Bs3Cg1InsertVex3bPrefix(pThis, 1 /*offDst*/, 0xf /*~V*/, 0 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 0 /*W*/);
+        off = Bs3Cg1InsertOpcodes(pThis, off) - 1;
+        off = Bs3Cfg1EncodeMemMod0Disp(pThis, false, off,
+                                       (pThis->abCurInstr[off] & X86_MODRM_REG_MASK) >> X86_MODRM_REG_SHIFT,
+                                       4, 0, BS3CG1OPLOC_MEM_WO);
+        pThis->fInvalidEncoding = true;
+    }
+    else if (iEncoding == 5)
+    {
+        pThis->abCurInstr[0] = P_RZ;
+        off = Bs3Cg1InsertVex3bPrefix(pThis, 1 /*offDst*/, 0xf /*~V*/, 0 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 0 /*W*/);
+        off = Bs3Cg1InsertOpcodes(pThis, off) - 1;
+        off = Bs3Cfg1EncodeMemMod0Disp(pThis, false, off,
+                                       (pThis->abCurInstr[off] & X86_MODRM_REG_MASK) >> X86_MODRM_REG_SHIFT,
+                                       4, 0, BS3CG1OPLOC_MEM_WO);
+        pThis->fInvalidEncoding = true;
+    }
+    else if (iEncoding == 6)
+    {
+        pThis->abCurInstr[0] = P_RN;
+        off = Bs3Cg1InsertVex3bPrefix(pThis, 1 /*offDst*/, 0xf /*~V*/, 0 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 0 /*W*/);
+        off = Bs3Cg1InsertOpcodes(pThis, off) - 1;
+        off = Bs3Cfg1EncodeMemMod0Disp(pThis, false, off,
+                                       (pThis->abCurInstr[off] & X86_MODRM_REG_MASK) >> X86_MODRM_REG_SHIFT,
+                                       4, 0, BS3CG1OPLOC_MEM_WO);
+        pThis->fInvalidEncoding = true;
+    }
+    else if (iEncoding == 7)
+    {
+        off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 0 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 1 /*W*/);
+        off = Bs3Cg1InsertOpcodes(pThis, off) - 1;
+        off = Bs3Cfg1EncodeMemMod0Disp(pThis, false, off,
+                                       (pThis->abCurInstr[off] & X86_MODRM_REG_MASK) >> X86_MODRM_REG_SHIFT,
+                                       4, 0, BS3CG1OPLOC_MEM_WO);
+    }
+#if ARCH_BITS == 64
+    else if (BS3CG1_IS_64BIT_TARGET(pThis))
+    {
+        if (iEncoding == 8)
+        {
+            pThis->abCurInstr[0] = REX_____;
+            off = Bs3Cg1InsertVex3bPrefix(pThis, 1 /*offDst*/, 0xf /*~V*/, 0 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 0 /*W*/);
+            off = Bs3Cg1InsertOpcodes(pThis, off) - 1;
+            off = Bs3Cfg1EncodeMemMod0Disp(pThis, false, off,
+                                           (pThis->abCurInstr[off] & X86_MODRM_REG_MASK) >> X86_MODRM_REG_SHIFT,
+                                           4, 0, BS3CG1OPLOC_MEM_WO);
+            pThis->fInvalidEncoding = true;
+        }
+        else
+            return 0;
+    }
+#endif
+    else
+        return 0;
+    pThis->cbCurInstr = off;
+    return iEncoding + 1;
+}
+
+
+/**
+ * Wip = VEX.W ignored.
+ * L0 = VEX.L must be zero.
+ */
+static unsigned BS3_NEAR_CODE
+Bs3Cg1EncodeNext_VEX_MODRM_WsomethingWO_Vsomething_Wip_L0_OR_ViceVersa(PBS3CG1STATE pThis, unsigned iEncoding)
+{
+    unsigned off;
+    switch (iEncoding)
+    {
+        /* 128-bit wide stuff goes first, then we'll update the operand widths afterwards. */
+        case 0:
+            off = Bs3Cg1InsertVex2bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 0 /*L*/, 1 /*~R*/);
+            off = Bs3Cg1InsertOpcodes(pThis, off);
+            pThis->abCurInstr[off++] = X86_MODRM_MAKE(3, 1, 0);
+            pThis->aOperands[pThis->iRmOp ].enmLocation = pThis->aOperands[pThis->iRmOp].enmLocationReg;
+            pThis->aOperands[pThis->iRmOp ].idxField = pThis->aOperands[pThis->iRmOp ].idxFieldBase + 0;
+            pThis->aOperands[pThis->iRegOp].idxField = pThis->aOperands[pThis->iRegOp].idxFieldBase + 1;
+            break;
+
+        case 1:
+            off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 0 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 0 /*W*/);
+            off = Bs3Cg1InsertOpcodes(pThis, off);
+            pThis->abCurInstr[off++] = X86_MODRM_MAKE(3, 4, 5);
+            pThis->aOperands[pThis->iRmOp ].idxField = pThis->aOperands[pThis->iRmOp ].idxFieldBase + 5;
+            pThis->aOperands[pThis->iRegOp].idxField = pThis->aOperands[pThis->iRegOp].idxFieldBase + 4;
+            break;
+        case 2:
+            off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 0 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 1 /*W - ignored*/);
+            off = Bs3Cg1InsertOpcodes(pThis, off);
+            pThis->abCurInstr[off++] = X86_MODRM_MAKE(3, 5, 4);
+            pThis->aOperands[pThis->iRmOp ].idxField = pThis->aOperands[pThis->iRmOp ].idxFieldBase + 4;
+            pThis->aOperands[pThis->iRegOp].idxField = pThis->aOperands[pThis->iRegOp].idxFieldBase + 5;
+            break;
+        case 3:
+            pThis->aOperands[pThis->iRmOp].enmLocation = pThis->aOperands[pThis->iRmOp].enmLocationMem;
+            off = Bs3Cg1InsertVex2bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 0 /*L*/, 1 /*~R*/);
+            off = Bs3Cg1InsertOpcodes(pThis, off);
+            off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, false, off, 2 /*iReg*/, 0);
+            break;
+        case 4:
+            off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 0 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 0 /*W*/);
+            off = Bs3Cg1InsertOpcodes(pThis, off);
+            off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, false, off, 3 /*iReg*/, 0);
+            break;
+        case 5:
+            off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 0 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 1 /*W - ignored */);
+            off = Bs3Cg1InsertOpcodes(pThis, off);
+            off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, false, off, 3 /*iReg*/, 0);
+            break;
+        case 6:
+            off = Bs3Cg1InsertVex2bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 0 /*L*/, 1 /*~R*/);
+            off = Bs3Cg1InsertOpcodes(pThis, off);
+            off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, false, off, 3 /*iReg*/, 1 /*cbMisalign*/);
+            if (!Bs3Cg1XcptTypeIsVexUnaligned(pThis->enmXcptType))
+                pThis->bAlignmentXcpt = X86_XCPT_GP;
+            break;
+        case 7:
+            off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 0 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 0 /*W*/);
+            off = Bs3Cg1InsertOpcodes(pThis, off);
+            off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, false, off, 3 /*iReg*/, 1 /*cbMisalign*/);
+            if (!Bs3Cg1XcptTypeIsVexUnaligned(pThis->enmXcptType))
+                pThis->bAlignmentXcpt = X86_XCPT_GP;
+            break;
+        /* 128-bit invalid encodings: */
+        case 8:
+            off = Bs3Cg1InsertVex2bPrefix(pThis, 0 /*offDst*/, 0xe /*~V*/, 0 /*L*/, 1 /*~R*/); /* Bad V value */
+            off = Bs3Cg1InsertOpcodes(pThis, off);
+            pThis->abCurInstr[off++] = X86_MODRM_MAKE(3, 1, 0);
+            pThis->aOperands[pThis->iRmOp ].enmLocation = pThis->aOperands[pThis->iRmOp].enmLocationReg;
+            pThis->aOperands[pThis->iRmOp ].idxField = pThis->aOperands[pThis->iRmOp ].idxFieldBase + 0;
+            pThis->aOperands[pThis->iRegOp].idxField = pThis->aOperands[pThis->iRegOp].idxFieldBase + 1;
+            pThis->fInvalidEncoding = true;
+            break;
+        case 9:
+            off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0 /*~V*/, 0 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 0 /*W*/);
+            off = Bs3Cg1InsertOpcodes(pThis, off);
+            pThis->abCurInstr[off++] = X86_MODRM_MAKE(3, 4, 5);
+            pThis->aOperands[pThis->iRmOp ].idxField = pThis->aOperands[pThis->iRmOp ].idxFieldBase + 5;
+            pThis->aOperands[pThis->iRegOp].idxField = pThis->aOperands[pThis->iRegOp].idxFieldBase + 4;
+            pThis->fInvalidEncoding = true;
+            iEncoding = 20-1;
+            break;
+
+        default:
+            return 0;
+    }
+
+    pThis->cbCurInstr = off;
+    return iEncoding + 1;
+}
+
+
+/**
+ * Wip = VEX.W ignored.
+ */
+static unsigned BS3_NEAR_CODE
+Bs3Cg1EncodeNext_VEX_MODRM_WsomethingWO_Vsomething_Wip_OR_ViceVersa(PBS3CG1STATE pThis, unsigned iEncoding)
+{
+    unsigned off;
+    switch (iEncoding)
+    {
+        /* 128-bit wide stuff goes first, then we'll update the operand widths afterwards. */
+        case 0:
+            off = Bs3Cg1InsertVex2bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 0 /*L*/, 1 /*~R*/);
+            off = Bs3Cg1InsertOpcodes(pThis, off);
+            pThis->abCurInstr[off++] = X86_MODRM_MAKE(3, 1, 0);
+            pThis->aOperands[pThis->iRmOp ].enmLocation = pThis->aOperands[pThis->iRmOp].enmLocationReg;
+            pThis->aOperands[pThis->iRmOp ].idxField = pThis->aOperands[pThis->iRmOp ].idxFieldBase + 0;
+            pThis->aOperands[pThis->iRegOp].idxField = pThis->aOperands[pThis->iRegOp].idxFieldBase + 1;
+            break;
+
+        case 1:
+            off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 0 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 0 /*W*/);
+            off = Bs3Cg1InsertOpcodes(pThis, off);
+            pThis->abCurInstr[off++] = X86_MODRM_MAKE(3, 4, 5);
+            pThis->aOperands[pThis->iRmOp ].idxField = pThis->aOperands[pThis->iRmOp ].idxFieldBase + 5;
+            pThis->aOperands[pThis->iRegOp].idxField = pThis->aOperands[pThis->iRegOp].idxFieldBase + 4;
+            break;
+        case 2:
+            off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 0 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 1 /*W - ignored*/);
+            off = Bs3Cg1InsertOpcodes(pThis, off);
+            pThis->abCurInstr[off++] = X86_MODRM_MAKE(3, 5, 4);
+            pThis->aOperands[pThis->iRmOp ].idxField = pThis->aOperands[pThis->iRmOp ].idxFieldBase + 4;
+            pThis->aOperands[pThis->iRegOp].idxField = pThis->aOperands[pThis->iRegOp].idxFieldBase + 5;
+            break;
+        case 3:
+            pThis->aOperands[pThis->iRmOp].enmLocation = pThis->aOperands[pThis->iRmOp].enmLocationMem;
+            off = Bs3Cg1InsertVex2bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 0 /*L*/, 1 /*~R*/);
+            off = Bs3Cg1InsertOpcodes(pThis, off);
+            off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, false, off, 2 /*iReg*/, 0);
+            break;
+        case 4:
+            off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 0 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 0 /*W*/);
+            off = Bs3Cg1InsertOpcodes(pThis, off);
+            off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, false, off, 3 /*iReg*/, 0);
+            break;
+        case 5:
+            off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 0 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 1 /*W - ignored */);
+            off = Bs3Cg1InsertOpcodes(pThis, off);
+            off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, false, off, 3 /*iReg*/, 0);
+            break;
+        case 6:
+            off = Bs3Cg1InsertVex2bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 0 /*L*/, 1 /*~R*/);
+            off = Bs3Cg1InsertOpcodes(pThis, off);
+            off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, false, off, 3 /*iReg*/, 1 /*cbMisalign*/);
+            if (!Bs3Cg1XcptTypeIsVexUnaligned(pThis->enmXcptType))
+                pThis->bAlignmentXcpt = X86_XCPT_GP;
+            break;
+        case 7:
+            off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 0 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 0 /*W*/);
+            off = Bs3Cg1InsertOpcodes(pThis, off);
+            off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, false, off, 3 /*iReg*/, 1 /*cbMisalign*/);
+            if (!Bs3Cg1XcptTypeIsVexUnaligned(pThis->enmXcptType))
+                pThis->bAlignmentXcpt = X86_XCPT_GP;
+            break;
+        /* 128-bit invalid encodings: */
+        case 8:
+            off = Bs3Cg1InsertVex2bPrefix(pThis, 0 /*offDst*/, 0xe /*~V*/, 0 /*L*/, 1 /*~R*/); /* Bad V value */
+            off = Bs3Cg1InsertOpcodes(pThis, off);
+            pThis->abCurInstr[off++] = X86_MODRM_MAKE(3, 1, 0);
+            pThis->aOperands[pThis->iRmOp ].enmLocation = pThis->aOperands[pThis->iRmOp].enmLocationReg;
+            pThis->aOperands[pThis->iRmOp ].idxField = pThis->aOperands[pThis->iRmOp ].idxFieldBase + 0;
+            pThis->aOperands[pThis->iRegOp].idxField = pThis->aOperands[pThis->iRegOp].idxFieldBase + 1;
+            pThis->fInvalidEncoding = true;
+            break;
+        case 9:
+            off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0 /*~V*/, 0 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 0 /*W*/);
+            off = Bs3Cg1InsertOpcodes(pThis, off);
+            pThis->abCurInstr[off++] = X86_MODRM_MAKE(3, 4, 5);
+            pThis->aOperands[pThis->iRmOp ].idxField = pThis->aOperands[pThis->iRmOp ].idxFieldBase + 5;
+            pThis->aOperands[pThis->iRegOp].idxField = pThis->aOperands[pThis->iRegOp].idxFieldBase + 4;
+            pThis->fInvalidEncoding = true;
+            iEncoding = 20-1;
+            break;
+
+        case 10: case 11: case 12: case 13: case 14: case 15: case 16: case 17: case 18: case 19:
+            /* fall thru */
+
+            /* 256-bit encodings: */
+        case 20:
+            iEncoding = 20;
+            pThis->aOperands[pThis->iRmOp ].cbOp         = 32;
+            pThis->aOperands[pThis->iRmOp ].idxFieldBase = BS3CG1DST_YMM0;
+            pThis->aOperands[pThis->iRmOp ].enmLocation  = pThis->aOperands[pThis->iRmOp].enmLocationReg;
+            pThis->aOperands[pThis->iRegOp].cbOp         = 32;
+            pThis->aOperands[pThis->iRegOp].idxFieldBase = BS3CG1DST_YMM0;
+
+            off = Bs3Cg1InsertVex2bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 1 /*L*/, 1 /*~R*/);
+            off = Bs3Cg1InsertOpcodes(pThis, off);
+            pThis->abCurInstr[off++] = X86_MODRM_MAKE(3, 1, 0);
+            pThis->aOperands[pThis->iRmOp ].idxField = pThis->aOperands[pThis->iRmOp ].idxFieldBase + 0;
+            pThis->aOperands[pThis->iRegOp].idxField = pThis->aOperands[pThis->iRegOp].idxFieldBase + 1;
+            break;
+        case 21:
+            off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 1 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 0 /*W*/);
+            off = Bs3Cg1InsertOpcodes(pThis, off);
+            pThis->abCurInstr[off++] = X86_MODRM_MAKE(3, 4, 5);
+            pThis->aOperands[pThis->iRmOp ].idxField = pThis->aOperands[pThis->iRmOp ].idxFieldBase + 5;
+            pThis->aOperands[pThis->iRegOp].idxField = pThis->aOperands[pThis->iRegOp].idxFieldBase + 4;
+            break;
+        case 22:
+            off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 1 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 1 /*W - ignored*/);
+            off = Bs3Cg1InsertOpcodes(pThis, off);
+            pThis->abCurInstr[off++] = X86_MODRM_MAKE(3, 5, 4);
+            pThis->aOperands[pThis->iRmOp ].idxField = pThis->aOperands[pThis->iRmOp ].idxFieldBase + 4;
+            pThis->aOperands[pThis->iRegOp].idxField = pThis->aOperands[pThis->iRegOp].idxFieldBase + 5;
+            break;
+        case 23:
+            off = Bs3Cg1InsertVex2bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 1 /*L*/, 1 /*~R*/);
+            off = Bs3Cg1InsertOpcodes(pThis, off);
+            pThis->aOperands[pThis->iRmOp ].enmLocation = pThis->aOperands[pThis->iRmOp].enmLocationMem;
+            off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, false, off, 2 /*iReg*/, 0);
+            break;
+        case 24:
+            off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 1 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 0 /*W*/);
+            off = Bs3Cg1InsertOpcodes(pThis, off);
+            off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, false, off, 3 /*iReg*/, 0);
+            break;
+        case 25:
+            off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 1 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 1 /*W - ignored */);
+            off = Bs3Cg1InsertOpcodes(pThis, off);
+            off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, false, off, 3 /*iReg*/, 0);
+            break;
+        case 26:
+            off = Bs3Cg1InsertVex2bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 1 /*L*/, 1 /*~R*/);
+            off = Bs3Cg1InsertOpcodes(pThis, off);
+            off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, false, off, 3 /*iReg*/, 1 /*cbMisalign*/);
+            if (!Bs3Cg1XcptTypeIsVexUnaligned(pThis->enmXcptType))
+                pThis->bAlignmentXcpt = X86_XCPT_GP;
+            break;
+        case 27:
+            off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 1 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 0 /*W*/);
+            off = Bs3Cg1InsertOpcodes(pThis, off);
+            off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, false, off, 3 /*iReg*/, 1 /*cbMisalign*/);
+            if (!Bs3Cg1XcptTypeIsVexUnaligned(pThis->enmXcptType))
+                pThis->bAlignmentXcpt = X86_XCPT_GP;
+            break;
+        /* 256-bit invalid encodings: */
+        case 28:
+            off = Bs3Cg1InsertVex2bPrefix(pThis, 0 /*offDst*/, 0xe /*~V - invalid */, 1 /*L*/, 1 /*~R*/); /* Bad V value */
+            off = Bs3Cg1InsertOpcodes(pThis, off);
+            pThis->abCurInstr[off++] = X86_MODRM_MAKE(3, 1, 0);
+            pThis->aOperands[pThis->iRmOp ].enmLocation = pThis->aOperands[pThis->iRmOp].enmLocationReg;
+            pThis->aOperands[pThis->iRmOp ].idxField = pThis->aOperands[pThis->iRmOp ].idxFieldBase + 0;
+            pThis->aOperands[pThis->iRegOp].idxField = pThis->aOperands[pThis->iRegOp].idxFieldBase + 1;
+            pThis->fInvalidEncoding = true;
+            break;
+        case 29:
+            off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0 /*~V - invalid */, 1 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 0 /*W*/);
+            off = Bs3Cg1InsertOpcodes(pThis, off);
+            pThis->abCurInstr[off++] = X86_MODRM_MAKE(3, 4, 5);
+            pThis->aOperands[pThis->iRmOp ].idxField = pThis->aOperands[pThis->iRmOp ].idxFieldBase + 5;
+            pThis->aOperands[pThis->iRegOp].idxField = pThis->aOperands[pThis->iRegOp].idxFieldBase + 4;
+            pThis->fInvalidEncoding = true;
+            break;
+        case 30:
+            pThis->abCurInstr[0] = P_RN;
+            off = Bs3Cg1InsertVex3bPrefix(pThis, 1 /*offDst*/, 0xf /*~V*/, 1 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 0 /*W*/);
+            off = Bs3Cg1InsertOpcodes(pThis, off);
+            pThis->abCurInstr[off++] = X86_MODRM_MAKE(3, 4, 5);
+            pThis->aOperands[pThis->iRmOp ].idxField = pThis->aOperands[pThis->iRmOp ].idxFieldBase + 5;
+            pThis->aOperands[pThis->iRegOp].idxField = pThis->aOperands[pThis->iRegOp].idxFieldBase + 4;
+            pThis->fInvalidEncoding = true;
+            break;
+        case 31:
+            pThis->abCurInstr[0] = P_RZ;
+            off = Bs3Cg1InsertVex3bPrefix(pThis, 1 /*offDst*/, 0xf /*~V*/, 1 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 0 /*W*/);
+            off = Bs3Cg1InsertOpcodes(pThis, off);
+            pThis->abCurInstr[off++] = X86_MODRM_MAKE(3, 4, 5);
+            pThis->aOperands[pThis->iRmOp ].idxField = pThis->aOperands[pThis->iRmOp ].idxFieldBase + 5;
+            pThis->aOperands[pThis->iRegOp].idxField = pThis->aOperands[pThis->iRegOp].idxFieldBase + 4;
+            pThis->fInvalidEncoding = true;
+            break;
+        case 32:
+            pThis->abCurInstr[0] = P_OZ;
+            off = Bs3Cg1InsertVex3bPrefix(pThis, 1 /*offDst*/, 0xf /*~V*/, 1 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 0 /*W*/);
+            off = Bs3Cg1InsertOpcodes(pThis, off);
+            pThis->abCurInstr[off++] = X86_MODRM_MAKE(3, 4, 5);
+            pThis->aOperands[pThis->iRmOp ].idxField = pThis->aOperands[pThis->iRmOp ].idxFieldBase + 5;
+            pThis->aOperands[pThis->iRegOp].idxField = pThis->aOperands[pThis->iRegOp].idxFieldBase + 4;
+            pThis->fInvalidEncoding = true;
+            break;
+        case 33:
+            pThis->abCurInstr[0] = P_LK;
+            off = Bs3Cg1InsertVex3bPrefix(pThis, 1 /*offDst*/, 0xf /*~V*/, 1 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 0 /*W*/);
+            off = Bs3Cg1InsertOpcodes(pThis, off);
+            pThis->abCurInstr[off++] = X86_MODRM_MAKE(3, 4, 5);
+            pThis->aOperands[pThis->iRmOp ].idxField = pThis->aOperands[pThis->iRmOp ].idxFieldBase + 5;
+            pThis->aOperands[pThis->iRegOp].idxField = pThis->aOperands[pThis->iRegOp].idxFieldBase + 4;
+            pThis->fInvalidEncoding = true;
+            iEncoding += !BS3CG1_IS_64BIT_TARGET(pThis) ? 2 : 0;
+            break;
+
+#if ARCH_BITS == 64
+        /* 64-bit mode registers */
+        case 34:
+            off = Bs3Cg1InsertVex2bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 1 /*L*/, 0 /*~R*/);
+            off = Bs3Cg1InsertOpcodes(pThis, off);
+            pThis->abCurInstr[off++] = X86_MODRM_MAKE(3, 3, 4);
+            pThis->aOperands[pThis->iRmOp ].idxField = pThis->aOperands[pThis->iRmOp ].idxFieldBase + 4;
+            pThis->aOperands[pThis->iRegOp].idxField = pThis->aOperands[pThis->iRegOp].idxFieldBase + 11;
+            break;
+        case 35:
+            off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 1 /*L*/, 0 /*~R*/, 1 /*~X*/, 0 /*~B*/, 0 /*W*/);
+            off = Bs3Cg1InsertOpcodes(pThis, off);
+            pThis->abCurInstr[off++] = X86_MODRM_MAKE(3, 1, 4);
+            pThis->aOperands[pThis->iRmOp ].idxField = pThis->aOperands[pThis->iRmOp ].idxFieldBase + 12;
+            pThis->aOperands[pThis->iRegOp].idxField = pThis->aOperands[pThis->iRegOp].idxFieldBase + 9;
+            break;
+#endif
+        default:
+            return 0;
+    }
+
+    pThis->cbCurInstr = off;
+    return iEncoding + 1;
+}
+
+
+//static unsigned BS3_NEAR_CODE Bs3Cg1EncodeNext_VEX_FIXED(PBS3CG1STATE pThis, unsigned iEncoding)
+//{
+//    unsigned off;
+//    if (iEncoding == 0)
+//        off = Bs3Cg1InsertVex2bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 0 /*L*/, 1 /*~R*/);
+//    else if (iEncoding == 0)
+//        off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 0 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 0 /*W*/);
+//    else
+//        return 0;
+//    pThis->cbCurInstr = off;
+//    return iEncoding + 1;
+//}
+
+
+static unsigned BS3_NEAR_CODE Bs3Cg1EncodeNext_VEX_MODRM_MOD_EQ_3(PBS3CG1STATE pThis, unsigned iEncoding)
+{
+    unsigned off;
+    if (iEncoding < 8)
+    {
+        if (iEncoding & 1)
+            off = Bs3Cg1InsertVex2bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 0 /*L*/, 1 /*~R*/);
+        else
+            off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 0 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 0 /*W*/);
+        off = Bs3Cg1InsertOpcodes(pThis, off);
+        pThis->abCurInstr[off++] = X86_MODRM_MAKE(3, iEncoding, 1);
+    }
+    else if (iEncoding < 16)
+    {
+        if (iEncoding & 1)
+            off = Bs3Cg1InsertVex2bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 1 /*L*/, 1 /*~R*/);
+        else
+            off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 1 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 0 /*W*/);
+        off = Bs3Cg1InsertOpcodes(pThis, off);
+        pThis->abCurInstr[off++] = X86_MODRM_MAKE(3, iEncoding & 7, 1);
+    }
+    else if (iEncoding < 24)
+    {
+        if (iEncoding & 1)
+            off = Bs3Cg1InsertVex2bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 0 /*L*/, 1 /*~R*/);
+        else
+            off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 0 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 0 /*W*/);
+        off = Bs3Cg1InsertOpcodes(pThis, off);
+        pThis->abCurInstr[off++] = X86_MODRM_MAKE(3, 0, iEncoding & 7);
+    }
+    else if (iEncoding < 32)
+    {
+        if (iEncoding & 1)
+            off = Bs3Cg1InsertVex2bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, (iEncoding & 3) != 0 /*L*/, 1 /*~R*/);
+        else
+            off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, (iEncoding & 2) != 0 /*L*/, 1 /*~R*/, 1 /*~X*/,
+                                          1 /*~B*/, (iEncoding & 4) != 0 /*W*/);
+        off = Bs3Cg1InsertOpcodes(pThis, off);
+        pThis->abCurInstr[off++] = X86_MODRM_MAKE(3, 0, iEncoding & 7);
+    }
+    else
+        return 0;
+    pThis->cbCurInstr = off;
+
+    return iEncoding + 1;
+}
+
+
+static unsigned BS3_NEAR_CODE Bs3Cg1EncodeNext_VEX_MODRM_MOD_NE_3(PBS3CG1STATE pThis, unsigned iEncoding)
+{
+    unsigned off;
+    if (iEncoding < 8)
+    {
+        unsigned iMod = iEncoding % 3;
+        if (iEncoding & 1)
+            off = Bs3Cg1InsertVex2bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, (iEncoding & 2) != 0 /*L*/, 1 /*~R*/);
+        else
+            off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, (iEncoding & 2) != 0 /*L*/, 1 /*~R*/,
+                                          1 /*~X*/, 1 /*~B*/, (iEncoding & 4) != 0 /*W*/);
+        off = Bs3Cg1InsertOpcodes(pThis, off);
+        pThis->abCurInstr[off++] = X86_MODRM_MAKE(iMod, 0, 1);
+        if (iMod >= 1)
+            pThis->abCurInstr[off++] = 0x7f;
+        if (iMod == 2)
+        {
+            pThis->abCurInstr[off++] = 0x5f;
+            if (!BS3_MODE_IS_16BIT_CODE(pThis->bMode))
+            {
+                pThis->abCurInstr[off++] = 0x3f;
+                pThis->abCurInstr[off++] = 0x1f;
+            }
+        }
+    }
+    else
+        return 0;
+    pThis->cbCurInstr = off;
+    return iEncoding + 1;
+}
+
+
+static unsigned BS3_NEAR_CODE Bs3Cg1EncodeNext_VEX_MODRM(PBS3CG1STATE pThis, unsigned iEncoding)
+{
+    const unsigned cFirstEncodings = 32;
+    if (iEncoding < cFirstEncodings)
+    {
+        unsigned iRet = Bs3Cg1EncodeNext_VEX_MODRM_MOD_EQ_3(pThis, iEncoding);
+        BS3_ASSERT(iRet > iEncoding);
+        return iRet;
+    }
+    return Bs3Cg1EncodeNext_VEX_MODRM_MOD_NE_3(pThis, iEncoding - cFirstEncodings) + cFirstEncodings;
+}
+
+#endif /* BS3CG1_WITH_VEX */
+
+
+/**
+ * Encodes the next instruction.
+ *
+ * @returns Next iEncoding value.  Returns @a iEncoding unchanged to indicate
+ *          that there are no more encodings to test.
+ * @param   pThis           The state.
+ * @param   iEncoding       The encoding to produce.  Meaning is specific to
+ *                          each BS3CG1ENC_XXX value and should be considered
+ *                          internal.
+ */
+static unsigned BS3_NEAR_CODE Bs3Cg1EncodeNext(PBS3CG1STATE pThis, unsigned iEncoding)
+{
+    pThis->bAlignmentXcpt = UINT8_MAX;
+    pThis->uVexL = UINT8_MAX;
+    if (pThis->pfnEncoder)
+        return pThis->pfnEncoder(pThis, iEncoding);
 
     switch (pThis->enmEncoding)
     {
         case BS3CG1ENC_MODRM_Eb_Gb:
-            return Bs3Cg1EncodeNext_BS3CG1ENC_MODRM_Eb_Gb(pThis, iEncoding);
+            return Bs3Cg1EncodeNext_MODRM_Eb_Gb(pThis, iEncoding);
         case BS3CG1ENC_MODRM_Gb_Eb:
-            return Bs3Cg1EncodeNext_BS3CG1ENC_MODRM_Gb_Eb(pThis, iEncoding);
+            return Bs3Cg1EncodeNext_MODRM_Gb_Eb(pThis, iEncoding);
         case BS3CG1ENC_MODRM_Gv_Ev:
         case BS3CG1ENC_MODRM_Ev_Gv:
-            return Bs3Cg1EncodeNext_BS3CG1ENC_MODRM_Gv_Ev__OR__BS3CG1ENC_MODRM_Ev_Gv(pThis, iEncoding);
-
-        case BS3CG1ENC_MODRM_Wss_Vss:
-            return Bs3Cg1EncodeNext_BS3CG1ENC_MODRM_Wss_Vss(pThis, iEncoding);
-        case BS3CG1ENC_MODRM_Wsd_Vsd:
-            return Bs3Cg1EncodeNext_BS3CG1ENC_MODRM_Wsd_Vsd(pThis, iEncoding);
-        case BS3CG1ENC_MODRM_Wps_Vps:
-        case BS3CG1ENC_MODRM_Wpd_Vpd:
-            return Bs3Cg1EncodeNext_BS3CG1ENC_MODRM_Wps_Vps__OR__BS3CG1ENC_MODRM_Wpd_Vpd(pThis, iEncoding);
-        case BS3CG1ENC_MODRM_WqZxReg_Vq:
-            return Bs3Cg1EncodeNext_BS3CG1ENC_MODRM_WqZxReg_Vq(pThis, iEncoding);
-
-        case BS3CG1ENC_MODRM_Vq_UqHi:
-            return Bs3Cg1EncodeNext_BS3CG1ENC_MODRM_Vq_UqHi(pThis, iEncoding);
-        case BS3CG1ENC_MODRM_Vq_Mq:
-            return Bs3Cg1EncodeNext_BS3CG1ENC_MODRM_Vq_Mq(pThis, iEncoding);
-        case BS3CG1ENC_MODRM_Vdq_Wdq:
-            return Bs3Cg1EncodeNext_BS3CG1ENC_MODRM_Vdq_Wdq(pThis, iEncoding);
-        case BS3CG1ENC_MODRM_VssZxReg_Wss:
-            return Bs3Cg1EncodeNext_BS3CG1ENC_MODRM_VssZxReg_Wss(pThis, iEncoding);
-
-        case BS3CG1ENC_MODRM_Gv_Ma:
-            return Bs3Cg1EncodeNext_BS3CG1ENC_MODRM_Gv_Ma(pThis, iEncoding);
-
-        case BS3CG1ENC_MODRM_MbRO:
-            return Bs3Cg1EncodeNext_BS3CG1ENC_MODRM_MbRO(pThis, iEncoding);
-        case BS3CG1ENC_MODRM_MdRO:
-            return Bs3Cg1EncodeNext_BS3CG1ENC_MODRM_MdRO(pThis, iEncoding);
-        case BS3CG1ENC_MODRM_MdWO:
-            return Bs3Cg1EncodeNext_BS3CG1ENC_MODRM_MdWO(pThis, iEncoding);
-        case BS3CG1ENC_VEX_MODRM_MdWO:
-            return Bs3Cg1EncodeNext_BS3CG1ENC_VEX_MODRM_MdWO(pThis, iEncoding);
+            return Bs3Cg1EncodeNext_MODRM_Gv_Ev__OR__MODRM_Ev_Gv(pThis, iEncoding);
+
+        case BS3CG1ENC_MODRM_Wss_WO_Vss:
+            return Bs3Cg1EncodeNext_MODRM_Wss_WO_Vss(pThis, iEncoding);
+        case BS3CG1ENC_MODRM_Wsd_WO_Vsd:
+            return Bs3Cg1EncodeNext_MODRM_Wsd_WO_Vsd(pThis, iEncoding);
+        case BS3CG1ENC_MODRM_Wps_WO_Vps:
+        case BS3CG1ENC_MODRM_Wpd_WO_Vpd:
+            return Bs3Cg1EncodeNext_MODRM_Wps_WO_Vps__OR__MODRM_Wpd_WO_Vpd(pThis, iEncoding);
+        case BS3CG1ENC_MODRM_WqZxReg_WO_Vq:
+            return Bs3Cg1EncodeNext_MODRM_WqZxReg_WO_Vq(pThis, iEncoding);
+
+        case BS3CG1ENC_MODRM_Vq_WO_UqHi:
+            return Bs3Cg1EncodeNext_MODRM_Vq_WO_UqHi(pThis, iEncoding);
+        case BS3CG1ENC_MODRM_Vq_WO_Mq:
+            return Bs3Cg1EncodeNext_MODRM_Vq_WO_Mq(pThis, iEncoding);
+        case BS3CG1ENC_MODRM_VqHi_WO_Uq:
+            return Bs3Cg1EncodeNext_MODRM_VqHi_WO_Uq(pThis, iEncoding);
+        case BS3CG1ENC_MODRM_VqHi_WO_Mq:
+            return Bs3Cg1EncodeNext_MODRM_VqHi_WO_Mq(pThis, iEncoding);
+        case BS3CG1ENC_MODRM_Vpd_WO_Wpd:
+        case BS3CG1ENC_MODRM_Vps_WO_Wps:
+            return Bs3Cg1EncodeNext_MODRM_Vps_WO_Wps__OR__MODRM_Vpd_WO_Wpd(pThis, iEncoding);
+        case BS3CG1ENC_MODRM_VssZx_WO_Wss:
+            return Bs3Cg1EncodeNext_MODRM_VssZx_WO_Wss(pThis, iEncoding);
+        case BS3CG1ENC_MODRM_VsdZx_WO_Wsd:
+        case BS3CG1ENC_MODRM_VqZx_WO_Wq:
+            return Bs3Cg1EncodeNext_MODRM_VsdZx_WO_Wsd__OR__MODRM_VqZx_WO_Wq(pThis, iEncoding);
+        case BS3CG1ENC_MODRM_VqZx_WO_Nq:
+            return Bs3Cg1EncodeNext_MODRM_VqZx_WO_Nq(pThis, iEncoding);
+
+        case BS3CG1ENC_MODRM_Gv_RO_Ma:
+            return Bs3Cg1EncodeNext_MODRM_Gv_RO_Ma(pThis, iEncoding);
+
+        case BS3CG1ENC_MODRM_Mb_RO:
+            return Bs3Cg1EncodeNext_MODRM_Mb_RO(pThis, iEncoding);
+        case BS3CG1ENC_MODRM_Md_RO:
+            return Bs3Cg1EncodeNext_MODRM_Md_RO(pThis, iEncoding);
+        case BS3CG1ENC_MODRM_Md_WO:
+            return Bs3Cg1EncodeNext_MODRM_Md_WO(pThis, iEncoding);
+        case BS3CG1ENC_MODRM_Mq_WO_Vq:
+            return Bs3Cg1EncodeNext_MODRM_Mq_WO_Vq(pThis, iEncoding);
+        case BS3CG1ENC_MODRM_Mq_WO_VqHi:
+            return Bs3Cg1EncodeNext_MODRM_Mq_WO_VqHi(pThis, iEncoding);
 
         case BS3CG1ENC_FIXED:
-            return Bs3Cg1EncodeNext_BS3CG1ENC_FIXED(pThis, iEncoding);
+            return Bs3Cg1EncodeNext_FIXED(pThis, iEncoding);
         case BS3CG1ENC_FIXED_AL_Ib:
-            return Bs3Cg1EncodeNext_BS3CG1ENC_FIXED_AL_Ib(pThis, iEncoding);
+            return Bs3Cg1EncodeNext_FIXED_AL_Ib(pThis, iEncoding);
         case BS3CG1ENC_FIXED_rAX_Iz:
-            return Bs3Cg1EncodeNext_BS3CG1ENC_FIXED_rAX_Iz(pThis, iEncoding);
+            return Bs3Cg1EncodeNext_FIXED_rAX_Iz(pThis, iEncoding);
 
-        case BS3CG1ENC_MODRM_MOD_EQ_3:
-            return Bs3Cg1EncodeNext_BS3CG1ENC_MODRM_MOD_EQ_3(pThis, iEncoding);
-        case BS3CG1ENC_MODRM_MOD_NE_3:
-            return Bs3Cg1EncodeNext_BS3CG1ENC_MODRM_MOD_NE_3(pThis, iEncoding);
+        /*
+         * VEX stuff
+         */
+#ifdef BS3CG1_WITH_VEX
+        case BS3CG1ENC_VEX_MODRM_VssZx_WO_Md:
+            return Bs3Cg1EncodeNext_VEX_MODRM_VsomethingWO_Msomething_Wip_Lig_OR_ViceVersa(pThis, iEncoding);
+
+#endif /* BS3CG1_WITH_VEX */
 
         default:
             Bs3TestFailedF("Internal error! BS3CG1ENC_XXX = %u not implemented", pThis->enmEncoding);
@@ -2118,177 +4252,731 @@ static unsigned BS3_NEAR_CODE Bs3Cg1EncodeNext(PBS3CG1STATE pThis, unsigned iEnc
 #define Bs3Cg1EncodePrep BS3_CMN_NM(Bs3Cg1EncodePrep)
 bool BS3_NEAR_CODE Bs3Cg1EncodePrep(PBS3CG1STATE pThis)
 {
-    unsigned iRing = 4;
-    while (iRing-- > 0)
-        pThis->aSavedSegRegs[iRing].ds = pThis->aInitialCtxs[iRing].ds;
+    unsigned i = 4;
+    while (i-- > 0)
+        pThis->aSavedSegRegs[i].ds = pThis->aInitialCtxs[i].ds;
+
+    i = RT_ELEMENTS(pThis->aOperands);
+    while (i-- > 0)
+    {
+        pThis->aOperands[i].enmLocationReg  = BS3CG1OPLOC_INVALID;
+        pThis->aOperands[i].enmLocationMem  = BS3CG1OPLOC_INVALID;
+        pThis->aOperands[i].idxFieldBase    = BS3CG1DST_INVALID;
+    }
+
+    pThis->iRmOp            = RT_ELEMENTS(pThis->aOperands) - 1;
+    pThis->iRegOp           = RT_ELEMENTS(pThis->aOperands) - 1;
+    pThis->fSameRingNotOkay = false;
+    pThis->cbOperand        = 0;
+    pThis->pfnEncoder       = NULL;
+
+    switch (pThis->enmEncoding)
+    {
+        case BS3CG1ENC_MODRM_Eb_Gb:
+            pThis->iRmOp             = 0;
+            pThis->iRegOp            = 1;
+            pThis->aOperands[0].cbOp = 1;
+            pThis->aOperands[1].cbOp = 1;
+            pThis->aOperands[0].enmLocation = BS3CG1OPLOC_CTX;
+            pThis->aOperands[1].enmLocation = BS3CG1OPLOC_CTX;
+            break;
+
+        case BS3CG1ENC_MODRM_Ev_Gv:
+            pThis->iRmOp             = 0;
+            pThis->iRegOp            = 1;
+            pThis->cbOperand         = 2;
+            pThis->aOperands[0].cbOp = 2;
+            pThis->aOperands[1].cbOp = 2;
+            pThis->aOperands[0].enmLocation = BS3CG1OPLOC_CTX;
+            pThis->aOperands[1].enmLocation = BS3CG1OPLOC_CTX;
+            break;
+
+        case BS3CG1ENC_MODRM_Ed_WO_Pd_WZ:
+            pThis->pfnEncoder        = Bs3Cg1EncodeNext_MODRM_PdZx_WO_Ed_WZ;
+            pThis->iRmOp             = 0;
+            pThis->iRegOp            = 1;
+            pThis->aOperands[0].cbOp = 4;
+            pThis->aOperands[1].cbOp = 4;
+            pThis->aOperands[0].idxFieldBase   = BS3CG1DST_EAX;
+            pThis->aOperands[1].idxFieldBase   = BS3CG1DST_MM0;
+            pThis->aOperands[0].enmLocation    = BS3CG1OPLOC_CTX;
+            pThis->aOperands[0].enmLocationReg = BS3CG1OPLOC_CTX;
+            pThis->aOperands[0].enmLocationMem = BS3CG1OPLOC_MEM_WO;
+            pThis->aOperands[1].enmLocation    = BS3CG1OPLOC_CTX;
+            break;
+
+        case BS3CG1ENC_MODRM_Eq_WO_Pq_WNZ:
+            pThis->pfnEncoder        = Bs3Cg1EncodeNext_MODRM_Pq_WO_Eq_WNZ;
+            pThis->iRmOp             = 0;
+            pThis->iRegOp            = 1;
+            pThis->aOperands[0].cbOp = 8;
+            pThis->aOperands[1].cbOp = 8;
+            pThis->aOperands[0].idxFieldBase   = BS3CG1DST_RAX;
+            pThis->aOperands[1].idxFieldBase   = BS3CG1DST_MM0;
+            pThis->aOperands[0].enmLocation    = BS3CG1OPLOC_CTX;
+            pThis->aOperands[0].enmLocationReg = BS3CG1OPLOC_CTX;
+            pThis->aOperands[0].enmLocationMem = BS3CG1OPLOC_MEM_WO;
+            pThis->aOperands[1].enmLocation    = BS3CG1OPLOC_CTX;
+            break;
+
+        case BS3CG1ENC_MODRM_Ed_WO_Vd_WZ:
+            pThis->pfnEncoder        = Bs3Cg1EncodeNext_MODRM_Vd_WO_Ed_WZ;
+            pThis->iRmOp             = 0;
+            pThis->iRegOp            = 1;
+            pThis->aOperands[0].cbOp = 4;
+            pThis->aOperands[1].cbOp = 4;
+            pThis->aOperands[0].idxFieldBase   = BS3CG1DST_EAX;
+            pThis->aOperands[1].idxFieldBase   = BS3CG1DST_XMM0;
+            pThis->aOperands[0].enmLocation    = BS3CG1OPLOC_CTX;
+            pThis->aOperands[0].enmLocationReg = BS3CG1OPLOC_CTX;
+            pThis->aOperands[0].enmLocationMem = BS3CG1OPLOC_MEM_WO;
+            pThis->aOperands[1].enmLocation    = BS3CG1OPLOC_CTX;
+            break;
+
+        case BS3CG1ENC_MODRM_Eq_WO_Vq_WNZ:
+            pThis->pfnEncoder        = Bs3Cg1EncodeNext_MODRM_Vq_WO_Eq_WNZ;
+            pThis->iRmOp             = 0;
+            pThis->iRegOp            = 1;
+            pThis->aOperands[0].cbOp = 8;
+            pThis->aOperands[1].cbOp = 8;
+            pThis->aOperands[0].idxFieldBase   = BS3CG1DST_RAX;
+            pThis->aOperands[1].idxFieldBase   = BS3CG1DST_XMM0;
+            pThis->aOperands[0].enmLocation    = BS3CG1OPLOC_CTX;
+            pThis->aOperands[0].enmLocationReg = BS3CG1OPLOC_CTX;
+            pThis->aOperands[0].enmLocationMem = BS3CG1OPLOC_MEM_WO;
+            pThis->aOperands[1].enmLocation    = BS3CG1OPLOC_CTX;
+            break;
+
+        case BS3CG1ENC_MODRM_Gb_Eb:
+            pThis->iRmOp             = 1;
+            pThis->iRegOp            = 0;
+            pThis->aOperands[0].cbOp = 1;
+            pThis->aOperands[1].cbOp = 1;
+            pThis->aOperands[0].enmLocation = BS3CG1OPLOC_CTX;
+            pThis->aOperands[1].enmLocation = BS3CG1OPLOC_CTX;
+            break;
+
+        case BS3CG1ENC_MODRM_Gv_Ev:
+            pThis->iRmOp             = 1;
+            pThis->iRegOp            = 0;
+            pThis->cbOperand         = 2;
+            pThis->aOperands[0].cbOp = 2;
+            pThis->aOperands[1].cbOp = 2;
+            pThis->aOperands[0].enmLocation = BS3CG1OPLOC_CTX;
+            pThis->aOperands[1].enmLocation = BS3CG1OPLOC_CTX;
+            break;
+
+        case BS3CG1ENC_MODRM_Gv_RO_Ma:
+            pThis->iRmOp             = 1;
+            pThis->iRegOp            = 0;
+            pThis->cbOperand         = 2;
+            pThis->aOperands[0].cbOp = 2;
+            pThis->aOperands[1].cbOp = 4;
+            pThis->aOperands[0].enmLocation = BS3CG1OPLOC_CTX;
+            pThis->aOperands[1].enmLocation = BS3CG1OPLOC_MEM;
+            pThis->aOperands[1].idxField    = BS3CG1DST_INVALID;
+            break;
+
+        case BS3CG1ENC_MODRM_Wss_WO_Vss:
+            pThis->iRmOp             = 0;
+            pThis->iRegOp            = 1;
+            pThis->aOperands[0].cbOp = 4;
+            pThis->aOperands[1].cbOp = 4;
+            pThis->aOperands[0].enmLocation = BS3CG1OPLOC_CTX;
+            pThis->aOperands[1].enmLocation = BS3CG1OPLOC_CTX;
+            break;
+
+        case BS3CG1ENC_MODRM_Wsd_WO_Vsd:
+        case BS3CG1ENC_MODRM_WqZxReg_WO_Vq:
+            pThis->iRmOp             = 0;
+            pThis->iRegOp            = 1;
+            pThis->aOperands[0].cbOp = 8;
+            pThis->aOperands[1].cbOp = 8;
+            pThis->aOperands[0].enmLocation = BS3CG1OPLOC_CTX;
+            pThis->aOperands[1].enmLocation = BS3CG1OPLOC_CTX;
+            break;
+
+        case BS3CG1ENC_MODRM_Wps_WO_Vps:
+        case BS3CG1ENC_MODRM_Wpd_WO_Vpd:
+            pThis->iRmOp             = 0;
+            pThis->iRegOp            = 1;
+            pThis->aOperands[0].cbOp = 16;
+            pThis->aOperands[1].cbOp = 16;
+            pThis->aOperands[0].enmLocation = BS3CG1OPLOC_CTX;
+            pThis->aOperands[1].enmLocation = BS3CG1OPLOC_CTX;
+            break;
+
+        case BS3CG1ENC_MODRM_Vdq_WO_Mdq:
+            pThis->pfnEncoder        = Bs3Cg1EncodeNext_MODRM_MsomethingWO_Vsomething_OR_ViceVersa;
+            pThis->iRegOp            = 0;
+            pThis->iRmOp             = 1;
+            pThis->aOperands[0].cbOp = 16;
+            pThis->aOperands[1].cbOp = 16;
+            pThis->aOperands[0].enmLocation  = BS3CG1OPLOC_CTX;
+            pThis->aOperands[1].enmLocation  = BS3CG1OPLOC_MEM;
+            pThis->aOperands[0].idxFieldBase = BS3CG1DST_XMM0;
+            break;
+
+        case BS3CG1ENC_MODRM_Vdq_WO_Wdq:
+            pThis->pfnEncoder        = Bs3Cg1EncodeNext_MODRM_Vdq_WO_Wdq;
+            pThis->iRmOp             = 1;
+            pThis->iRegOp            = 0;
+            pThis->aOperands[0].cbOp = 16;
+            pThis->aOperands[1].cbOp = 16;
+            pThis->aOperands[0].enmLocation = BS3CG1OPLOC_CTX;
+            pThis->aOperands[1].enmLocation = BS3CG1OPLOC_CTX;
+            break;
+
+        case BS3CG1ENC_MODRM_Vpd_WO_Wpd:
+        case BS3CG1ENC_MODRM_Vps_WO_Wps:
+            pThis->iRmOp             = 1;
+            pThis->iRegOp            = 0;
+            pThis->aOperands[0].cbOp = 16;
+            pThis->aOperands[1].cbOp = 16;
+            pThis->aOperands[0].enmLocation = BS3CG1OPLOC_CTX;
+            pThis->aOperands[1].enmLocation = BS3CG1OPLOC_CTX;
+            break;
+
+        case BS3CG1ENC_MODRM_Pq_WO_Qq:
+            pThis->pfnEncoder        = Bs3Cg1EncodeNext_MODRM_Pq_WO_Qq;
+            pThis->iRegOp            = 0;
+            pThis->iRmOp             = 1;
+            pThis->aOperands[0].cbOp = 8;
+            pThis->aOperands[1].cbOp = 8;
+            pThis->aOperands[0].idxFieldBase   = BS3CG1DST_MM0;
+            pThis->aOperands[1].idxFieldBase   = BS3CG1DST_MM0;
+            pThis->aOperands[0].enmLocation    = BS3CG1OPLOC_CTX;
+            pThis->aOperands[1].enmLocation    = BS3CG1OPLOC_CTX;
+            pThis->aOperands[1].enmLocationReg = BS3CG1OPLOC_CTX;
+            pThis->aOperands[1].enmLocationMem = BS3CG1OPLOC_MEM;
+            break;
+
+        case BS3CG1ENC_MODRM_Pq_WO_Uq:
+            pThis->pfnEncoder        = Bs3Cg1EncodeNext_MODRM_Pq_WO_Uq;
+            pThis->iRmOp             = 1;
+            pThis->iRegOp            = 0;
+            pThis->aOperands[0].cbOp = 8;
+            pThis->aOperands[1].cbOp = 8;
+            pThis->aOperands[0].enmLocation = BS3CG1OPLOC_CTX;
+            pThis->aOperands[1].enmLocation = BS3CG1OPLOC_CTX;
+            break;
+
+        case BS3CG1ENC_MODRM_PdZx_WO_Ed_WZ:
+            pThis->pfnEncoder        = Bs3Cg1EncodeNext_MODRM_PdZx_WO_Ed_WZ;
+            pThis->iRegOp            = 0;
+            pThis->iRmOp             = 1;
+            pThis->aOperands[0].cbOp = 4;
+            pThis->aOperands[1].cbOp = 4;
+            pThis->aOperands[0].idxFieldBase   = BS3CG1DST_MM0_LO_ZX;
+            pThis->aOperands[1].idxFieldBase   = BS3CG1DST_EAX;
+            pThis->aOperands[0].enmLocation    = BS3CG1OPLOC_CTX;
+            pThis->aOperands[1].enmLocation    = BS3CG1OPLOC_CTX;
+            pThis->aOperands[1].enmLocationReg = BS3CG1OPLOC_CTX;
+            pThis->aOperands[1].enmLocationMem = BS3CG1OPLOC_MEM;
+            break;
+
+        case BS3CG1ENC_MODRM_Pq_WO_Eq_WNZ:
+            pThis->pfnEncoder        = Bs3Cg1EncodeNext_MODRM_Pq_WO_Eq_WNZ;
+            pThis->iRegOp            = 0;
+            pThis->iRmOp             = 1;
+            pThis->aOperands[0].cbOp = 8;
+            pThis->aOperands[1].cbOp = 8;
+            pThis->aOperands[0].idxFieldBase   = BS3CG1DST_MM0;
+            pThis->aOperands[1].idxFieldBase   = BS3CG1DST_RAX;
+            pThis->aOperands[0].enmLocation    = BS3CG1OPLOC_CTX;
+            pThis->aOperands[1].enmLocation    = BS3CG1OPLOC_CTX;
+            pThis->aOperands[1].enmLocationReg = BS3CG1OPLOC_CTX;
+            pThis->aOperands[1].enmLocationMem = BS3CG1OPLOC_MEM;
+            break;
+
+        case BS3CG1ENC_MODRM_VdZx_WO_Ed_WZ:
+            pThis->pfnEncoder        = Bs3Cg1EncodeNext_MODRM_Vd_WO_Ed_WZ;
+            pThis->iRegOp            = 0;
+            pThis->iRmOp             = 1;
+            pThis->aOperands[0].cbOp = 4;
+            pThis->aOperands[1].cbOp = 4;
+            pThis->aOperands[0].idxFieldBase   = BS3CG1DST_XMM0_DW0_ZX;
+            pThis->aOperands[1].idxFieldBase   = BS3CG1DST_EAX;
+            pThis->aOperands[0].enmLocation    = BS3CG1OPLOC_CTX;
+            pThis->aOperands[1].enmLocation    = BS3CG1OPLOC_CTX;
+            pThis->aOperands[1].enmLocationReg = BS3CG1OPLOC_CTX;
+            pThis->aOperands[1].enmLocationMem = BS3CG1OPLOC_MEM;
+            break;
+
+        case BS3CG1ENC_MODRM_VqZx_WO_Eq_WNZ:
+            pThis->pfnEncoder        = Bs3Cg1EncodeNext_MODRM_Vq_WO_Eq_WNZ;
+            pThis->iRegOp            = 0;
+            pThis->iRmOp             = 1;
+            pThis->aOperands[0].cbOp = 8;
+            pThis->aOperands[1].cbOp = 8;
+            pThis->aOperands[0].idxFieldBase   = BS3CG1DST_XMM0_LO_ZX;
+            pThis->aOperands[1].idxFieldBase   = BS3CG1DST_RAX;
+            pThis->aOperands[0].enmLocation    = BS3CG1OPLOC_CTX;
+            pThis->aOperands[1].enmLocation    = BS3CG1OPLOC_CTX;
+            pThis->aOperands[1].enmLocationReg = BS3CG1OPLOC_CTX;
+            pThis->aOperands[1].enmLocationMem = BS3CG1OPLOC_MEM;
+            break;
+
+        case BS3CG1ENC_MODRM_Vq_WO_UqHi:
+        case BS3CG1ENC_MODRM_VqHi_WO_Uq:
+            pThis->iRmOp             = 1;
+            pThis->iRegOp            = 0;
+            pThis->aOperands[0].cbOp = 8;
+            pThis->aOperands[1].cbOp = 8;
+            pThis->aOperands[0].enmLocation = BS3CG1OPLOC_CTX;
+            pThis->aOperands[1].enmLocation = BS3CG1OPLOC_CTX;
+            break;
+
+        case BS3CG1ENC_MODRM_Vq_WO_Mq:
+        case BS3CG1ENC_MODRM_VqHi_WO_Mq:
+            pThis->iRmOp             = 1;
+            pThis->iRegOp            = 0;
+            pThis->aOperands[0].cbOp = 8;
+            pThis->aOperands[1].cbOp = 8;
+            pThis->aOperands[0].enmLocation = BS3CG1OPLOC_CTX;
+            pThis->aOperands[1].enmLocation = BS3CG1OPLOC_MEM;
+            break;
+
+        case BS3CG1ENC_MODRM_VssZx_WO_Wss:
+            pThis->iRmOp             = 1;
+            pThis->iRegOp            = 0;
+            pThis->aOperands[0].cbOp = 4;
+            pThis->aOperands[1].cbOp = 4;
+            pThis->aOperands[0].enmLocation = BS3CG1OPLOC_CTX;
+            pThis->aOperands[1].enmLocation = BS3CG1OPLOC_CTX;
+            break;
+
+        case BS3CG1ENC_MODRM_VsdZx_WO_Wsd:
+        case BS3CG1ENC_MODRM_VqZx_WO_Wq:
+        case BS3CG1ENC_MODRM_VqZx_WO_Nq:
+            pThis->iRmOp             = 1;
+            pThis->iRegOp            = 0;
+            pThis->aOperands[0].cbOp = 8;
+            pThis->aOperands[1].cbOp = 8;
+            pThis->aOperands[0].enmLocation = BS3CG1OPLOC_CTX;
+            pThis->aOperands[1].enmLocation = BS3CG1OPLOC_CTX;
+            break;
+
+        case BS3CG1ENC_MODRM_Mb_RO:
+            pThis->iRmOp             = 0;
+            pThis->aOperands[0].cbOp = 1;
+            pThis->aOperands[0].enmLocation = BS3CG1OPLOC_MEM;
+            break;
+
+        case BS3CG1ENC_MODRM_Md_RO:
+            pThis->iRmOp             = 0;
+            pThis->aOperands[0].cbOp = 4;
+            pThis->aOperands[0].enmLocation = BS3CG1OPLOC_MEM;
+            break;
+
+        case BS3CG1ENC_MODRM_Md_WO:
+            pThis->iRmOp             = 0;
+            pThis->aOperands[0].cbOp = 4;
+            pThis->aOperands[0].enmLocation = BS3CG1OPLOC_MEM_WO;
+            break;
 
-    pThis->iRmOp            = RT_ELEMENTS(pThis->aOperands) - 1;
-    pThis->iRegOp           = RT_ELEMENTS(pThis->aOperands) - 1;
-    pThis->fSameRingNotOkay = false;
-    pThis->cbOperand        = 0;
+        case BS3CG1ENC_MODRM_Mdq_WO_Vdq:
+            pThis->pfnEncoder        = Bs3Cg1EncodeNext_MODRM_MsomethingWO_Vsomething_OR_ViceVersa;
+            pThis->iRmOp             = 0;
+            pThis->iRegOp            = 1;
+            pThis->aOperands[0].cbOp = 16;
+            pThis->aOperands[1].cbOp = 16;
+            pThis->aOperands[0].enmLocation  = BS3CG1OPLOC_MEM_WO;
+            pThis->aOperands[1].enmLocation  = BS3CG1OPLOC_CTX;
+            pThis->aOperands[1].idxFieldBase = BS3CG1DST_XMM0;
+            break;
 
-    switch (pThis->enmEncoding)
-    {
-        case BS3CG1ENC_MODRM_Eb_Gb:
+        case BS3CG1ENC_MODRM_Mq_WO_Pq:
+            pThis->pfnEncoder        = Bs3Cg1EncodeNext_MODRM_Mq_WO_Pq;
             pThis->iRmOp             = 0;
             pThis->iRegOp            = 1;
-            pThis->aOperands[0].cbOp = 1;
-            pThis->aOperands[1].cbOp = 1;
-            pThis->aOperands[0].enmLocation = BS3CG1OPLOC_CTX;
-            pThis->aOperands[1].enmLocation = BS3CG1OPLOC_CTX;
+            pThis->aOperands[0].cbOp = 8;
+            pThis->aOperands[1].cbOp = 8;
+            pThis->aOperands[1].idxFieldBase = BS3CG1DST_MM0;
+            pThis->aOperands[0].enmLocation  = BS3CG1OPLOC_MEM_WO;
+            pThis->aOperands[1].enmLocation  = BS3CG1OPLOC_CTX;
             break;
 
-        case BS3CG1ENC_MODRM_Ev_Gv:
+        case BS3CG1ENC_MODRM_Mq_WO_Vq:
+        case BS3CG1ENC_MODRM_Mq_WO_VqHi:
             pThis->iRmOp             = 0;
             pThis->iRegOp            = 1;
-            pThis->cbOperand         = 2;
-            pThis->aOperands[0].cbOp = 2;
-            pThis->aOperands[1].cbOp = 2;
-            pThis->aOperands[0].enmLocation = BS3CG1OPLOC_CTX;
+            pThis->aOperands[0].cbOp = 8;
+            pThis->aOperands[1].cbOp = 8;
+            pThis->aOperands[0].enmLocation = BS3CG1OPLOC_MEM_WO;
             pThis->aOperands[1].enmLocation = BS3CG1OPLOC_CTX;
             break;
 
-        case BS3CG1ENC_MODRM_Gb_Eb:
-            pThis->iRmOp             = 1;
-            pThis->iRegOp            = 0;
+        case BS3CG1ENC_MODRM_Mps_WO_Vps:
+        case BS3CG1ENC_MODRM_Mpd_WO_Vpd:
+            pThis->pfnEncoder        = Bs3Cg1EncodeNext_MODRM_MsomethingWO_Vsomething_OR_ViceVersa;
+            pThis->iRmOp             = 0;
+            pThis->iRegOp            = 1;
+            pThis->aOperands[0].cbOp = 16;
+            pThis->aOperands[1].cbOp = 16;
+            pThis->aOperands[0].enmLocation  = BS3CG1OPLOC_MEM_WO;
+            pThis->aOperands[1].enmLocation  = BS3CG1OPLOC_CTX;
+            pThis->aOperands[1].idxFieldBase = BS3CG1DST_XMM0;
+            break;
+
+        case BS3CG1ENC_FIXED:
+            /* nothing to do here */
+            break;
+
+        case BS3CG1ENC_FIXED_AL_Ib:
             pThis->aOperands[0].cbOp = 1;
             pThis->aOperands[1].cbOp = 1;
             pThis->aOperands[0].enmLocation = BS3CG1OPLOC_CTX;
-            pThis->aOperands[1].enmLocation = BS3CG1OPLOC_CTX;
+            pThis->aOperands[1].enmLocation = BS3CG1OPLOC_IMM;
+            pThis->aOperands[0].idxField    = BS3CG1DST_AL;
+            pThis->aOperands[1].idxField    = BS3CG1DST_INVALID;
             break;
 
-        case BS3CG1ENC_MODRM_Gv_Ev:
-            pThis->iRmOp             = 1;
-            pThis->iRegOp            = 0;
-            pThis->cbOperand         = 2;
+        case BS3CG1ENC_FIXED_rAX_Iz:
             pThis->aOperands[0].cbOp = 2;
             pThis->aOperands[1].cbOp = 2;
             pThis->aOperands[0].enmLocation = BS3CG1OPLOC_CTX;
-            pThis->aOperands[1].enmLocation = BS3CG1OPLOC_CTX;
+            pThis->aOperands[1].enmLocation = BS3CG1OPLOC_IMM;
+            pThis->aOperands[0].idxField    = BS3CG1DST_OZ_RAX;
+            pThis->aOperands[1].idxField    = BS3CG1DST_INVALID;
             break;
 
-        case BS3CG1ENC_MODRM_Gv_Ma:
-            pThis->iRmOp             = 1;
-            pThis->iRegOp            = 0;
-            pThis->cbOperand         = 2;
-            pThis->aOperands[0].cbOp = 2;
-            pThis->aOperands[1].cbOp = 4;
-            pThis->aOperands[0].enmLocation = BS3CG1OPLOC_CTX;
-            pThis->aOperands[1].enmLocation = BS3CG1OPLOC_MEM;
-            pThis->aOperands[1].idxField    = BS3CG1DST_INVALID;
+            /* Unused or invalid instructions mostly. */
+        case BS3CG1ENC_MODRM_MOD_EQ_3:
+            pThis->pfnEncoder = Bs3Cg1EncodeNext_MODRM_MOD_EQ_3;
+            break;
+        case BS3CG1ENC_MODRM_MOD_NE_3:
+            pThis->pfnEncoder = Bs3Cg1EncodeNext_MODRM_MOD_NE_3;
             break;
 
-        case BS3CG1ENC_MODRM_Wss_Vss:
-            pThis->iRmOp             = 0;
-            pThis->iRegOp            = 1;
+#ifdef BS3CG1_WITH_VEX
+
+        case BS3CG1ENC_VEX_MODRM_Vd_WO_Ed_WZ:
+            pThis->pfnEncoder        = Bs3Cg1EncodeNext_VEX_MODRM_Vd_WO_Ed_WZ;
+            pThis->iRegOp            = 0;
+            pThis->iRmOp             = 1;
             pThis->aOperands[0].cbOp = 4;
             pThis->aOperands[1].cbOp = 4;
-            pThis->aOperands[0].enmLocation = BS3CG1OPLOC_CTX;
-            pThis->aOperands[1].enmLocation = BS3CG1OPLOC_CTX;
+            pThis->aOperands[0].idxFieldBase   = BS3CG1DST_XMM0_DW0_ZX;
+            pThis->aOperands[1].idxFieldBase   = BS3CG1DST_EAX;
+            pThis->aOperands[0].enmLocation    = BS3CG1OPLOC_CTX_ZX_VLMAX;
+            pThis->aOperands[1].enmLocation    = BS3CG1OPLOC_CTX;
+            pThis->aOperands[1].enmLocationReg = BS3CG1OPLOC_CTX;
+            pThis->aOperands[1].enmLocationMem = BS3CG1OPLOC_MEM;
             break;
 
-        case BS3CG1ENC_MODRM_Wsd_Vsd:
-        case BS3CG1ENC_MODRM_WqZxReg_Vq:
-            pThis->iRmOp             = 0;
-            pThis->iRegOp            = 1;
+        case BS3CG1ENC_VEX_MODRM_Vq_WO_Eq_WNZ:
+            pThis->pfnEncoder        = Bs3Cg1EncodeNext_VEX_MODRM_Vq_WO_Eq_WNZ;
+            pThis->iRegOp            = 0;
+            pThis->iRmOp             = 1;
             pThis->aOperands[0].cbOp = 8;
             pThis->aOperands[1].cbOp = 8;
-            pThis->aOperands[0].enmLocation = BS3CG1OPLOC_CTX;
-            pThis->aOperands[1].enmLocation = BS3CG1OPLOC_CTX;
+            pThis->aOperands[0].idxFieldBase   = BS3CG1DST_XMM0_LO_ZX;
+            pThis->aOperands[1].idxFieldBase   = BS3CG1DST_RAX;
+            pThis->aOperands[0].enmLocation    = BS3CG1OPLOC_CTX_ZX_VLMAX;
+            pThis->aOperands[1].enmLocation    = BS3CG1OPLOC_CTX;
+            pThis->aOperands[1].enmLocationReg = BS3CG1OPLOC_CTX;
+            pThis->aOperands[1].enmLocationMem = BS3CG1OPLOC_MEM;
             break;
 
-        case BS3CG1ENC_MODRM_Wps_Vps:
-        case BS3CG1ENC_MODRM_Wpd_Vpd:
-            pThis->iRmOp             = 0;
-            pThis->iRegOp            = 1;
+        case BS3CG1ENC_VEX_MODRM_Vps_WO_Wps:
+        case BS3CG1ENC_VEX_MODRM_Vpd_WO_Wpd:
+            pThis->pfnEncoder        = Bs3Cg1EncodeNext_VEX_MODRM_Vps_WO_Wps__OR__VEX_MODRM_Vpd_WO_Wpd;
+            pThis->iRmOp             = 1;
+            pThis->iRegOp            = 0;
             pThis->aOperands[0].cbOp = 16;
             pThis->aOperands[1].cbOp = 16;
-            pThis->aOperands[0].enmLocation = BS3CG1OPLOC_CTX;
+            pThis->aOperands[0].enmLocation = BS3CG1OPLOC_CTX_ZX_VLMAX;
             pThis->aOperands[1].enmLocation = BS3CG1OPLOC_CTX;
             break;
 
-        case BS3CG1ENC_MODRM_Vdq_Wdq:
+        case BS3CG1ENC_VEX_MODRM_VssZx_WO_Md:
+            pThis->pfnEncoder        = Bs3Cg1EncodeNext_VEX_MODRM_VsomethingWO_Msomething_Wip_Lig_OR_ViceVersa;
             pThis->iRmOp             = 1;
             pThis->iRegOp            = 0;
+            pThis->aOperands[0].cbOp = 4;
+            pThis->aOperands[1].cbOp = 4;
+            pThis->aOperands[0].enmLocation  = BS3CG1OPLOC_CTX_ZX_VLMAX;
+            pThis->aOperands[1].enmLocation  = BS3CG1OPLOC_MEM;
+            pThis->aOperands[0].idxFieldBase = BS3CG1DST_XMM0_DW0;
+            pThis->aOperands[1].idxFieldBase = BS3CG1DST_INVALID;
+            break;
+
+        case BS3CG1ENC_VEX_MODRM_Vss_WO_HssHi_Uss:
+            pThis->pfnEncoder        = Bs3Cg1EncodeNext_VEX_MODRM_VsomethingWO_Hsomething_Usomething_Lip_Wip_OR_ViceVersa;
+            pThis->iRegOp            = 0;
+            pThis->iRmOp             = 2;
             pThis->aOperands[0].cbOp = 16;
-            pThis->aOperands[1].cbOp = 16;
-            pThis->aOperands[0].enmLocation = BS3CG1OPLOC_CTX;
-            pThis->aOperands[1].enmLocation = BS3CG1OPLOC_CTX;
+            pThis->aOperands[1].cbOp = 12;
+            pThis->aOperands[2].cbOp = 4;
+            pThis->aOperands[0].enmLocation  = BS3CG1OPLOC_CTX_ZX_VLMAX;
+            pThis->aOperands[1].enmLocation  = BS3CG1OPLOC_CTX;
+            pThis->aOperands[2].enmLocation  = BS3CG1OPLOC_CTX;
+            pThis->aOperands[0].idxFieldBase = BS3CG1DST_XMM0;
+            pThis->aOperands[1].idxFieldBase = BS3CG1DST_XMM0_HI96;
+            pThis->aOperands[2].idxFieldBase = BS3CG1DST_XMM0_DW0;
             break;
 
-        case BS3CG1ENC_MODRM_Vq_UqHi:
+        case BS3CG1ENC_VEX_MODRM_VsdZx_WO_Mq:
+            pThis->pfnEncoder        = Bs3Cg1EncodeNext_VEX_MODRM_VsomethingWO_Msomething_Wip_Lig_OR_ViceVersa;
             pThis->iRmOp             = 1;
             pThis->iRegOp            = 0;
             pThis->aOperands[0].cbOp = 8;
             pThis->aOperands[1].cbOp = 8;
-            pThis->aOperands[0].enmLocation = BS3CG1OPLOC_CTX;
-            pThis->aOperands[1].enmLocation = BS3CG1OPLOC_CTX;
+            pThis->aOperands[0].enmLocation  = BS3CG1OPLOC_CTX_ZX_VLMAX;
+            pThis->aOperands[1].enmLocation  = BS3CG1OPLOC_MEM;
+            pThis->aOperands[0].idxFieldBase = BS3CG1DST_XMM0_LO;
+            pThis->aOperands[1].idxFieldBase = BS3CG1DST_INVALID;
             break;
 
-        case BS3CG1ENC_MODRM_Vq_Mq:
-            pThis->iRmOp             = 1;
+        case BS3CG1ENC_VEX_MODRM_Vsd_WO_HsdHi_Usd:
+            pThis->pfnEncoder        = Bs3Cg1EncodeNext_VEX_MODRM_VsomethingWO_Hsomething_Usomething_Lip_Wip_OR_ViceVersa;
             pThis->iRegOp            = 0;
-            pThis->aOperands[0].cbOp = 8;
+            pThis->iRmOp             = 2;
+            pThis->aOperands[0].cbOp = 16;
             pThis->aOperands[1].cbOp = 8;
-            pThis->aOperands[0].enmLocation = BS3CG1OPLOC_CTX;
-            pThis->aOperands[1].enmLocation = BS3CG1OPLOC_MEM;
+            pThis->aOperands[2].cbOp = 8;
+            pThis->aOperands[0].enmLocation  = BS3CG1OPLOC_CTX_ZX_VLMAX;
+            pThis->aOperands[1].enmLocation  = BS3CG1OPLOC_CTX;
+            pThis->aOperands[2].enmLocation  = BS3CG1OPLOC_CTX;
+            pThis->aOperands[0].idxFieldBase = BS3CG1DST_XMM0;
+            pThis->aOperands[1].idxFieldBase = BS3CG1DST_XMM0_HI;
+            pThis->aOperands[2].idxFieldBase = BS3CG1DST_XMM0_LO;
+            break;
+
+        case BS3CG1ENC_VEX_MODRM_Vq_WO_HqHi_UqHi:
+            pThis->pfnEncoder        = Bs3Cg1EncodeNext_VEX_MODRM_VsomethingWO_HdqCsomething_Usomething_Wip_OR_ViceVersa;
+            pThis->iRegOp            = 0;
+            pThis->iRmOp             = 2;
+            pThis->aOperands[0].cbOp = 16;
+            pThis->aOperands[1].cbOp = 8;
+            pThis->aOperands[2].cbOp = 8;
+            pThis->aOperands[0].enmLocation  = BS3CG1OPLOC_CTX_ZX_VLMAX;
+            pThis->aOperands[1].enmLocation  = BS3CG1OPLOC_CTX;
+            pThis->aOperands[2].enmLocation  = BS3CG1OPLOC_CTX;
+            pThis->aOperands[0].idxFieldBase = BS3CG1DST_XMM0;
+            pThis->aOperands[1].idxFieldBase = BS3CG1DST_XMM0_HI;
+            pThis->aOperands[2].idxFieldBase = BS3CG1DST_XMM0_HI;
+            break;
+
+        case BS3CG1ENC_VEX_MODRM_Vq_WO_HqHi_Mq:
+            pThis->pfnEncoder        = Bs3Cg1EncodeNext_VEX_MODRM_VsomethingWO_Hsomething_Msomething_Wip_OR_ViceVersa;
+            pThis->iRegOp            = 0;
+            pThis->iRmOp             = 2;
+            pThis->aOperands[0].cbOp = 16;
+            pThis->aOperands[1].cbOp = 8;
+            pThis->aOperands[2].cbOp = 8;
+            pThis->aOperands[0].enmLocation  = BS3CG1OPLOC_CTX_ZX_VLMAX;
+            pThis->aOperands[1].enmLocation  = BS3CG1OPLOC_CTX;
+            pThis->aOperands[2].enmLocation  = BS3CG1OPLOC_MEM;
+            pThis->aOperands[0].idxFieldBase = BS3CG1DST_XMM0;
+            pThis->aOperands[1].idxFieldBase = BS3CG1DST_XMM0_HI;
+            pThis->aOperands[2].idxFieldBase = BS3CG1DST_INVALID;
             break;
 
-        case BS3CG1ENC_MODRM_VssZxReg_Wss:
+        case BS3CG1ENC_VEX_MODRM_Vq_WO_Wq:
+            pThis->pfnEncoder        = Bs3Cg1EncodeNext_VEX_MODRM_WsomethingWO_Vsomething_Wip_L0_OR_ViceVersa;
+            pThis->iRegOp            = 0;
             pThis->iRmOp             = 1;
+            pThis->aOperands[0].cbOp = 8;
+            pThis->aOperands[1].cbOp = 8;
+            pThis->aOperands[0].enmLocation     = BS3CG1OPLOC_CTX_ZX_VLMAX;
+            pThis->aOperands[1].enmLocation     = BS3CG1OPLOC_CTX;
+            pThis->aOperands[1].enmLocationReg  = BS3CG1OPLOC_CTX;
+            pThis->aOperands[1].enmLocationMem  = BS3CG1OPLOC_MEM;
+            pThis->aOperands[0].idxFieldBase    = BS3CG1DST_XMM0_LO;
+            pThis->aOperands[1].idxFieldBase    = BS3CG1DST_XMM0_LO;
+            break;
+
+        case BS3CG1ENC_VEX_MODRM_Vx_WO_Wx:
+            pThis->pfnEncoder        = Bs3Cg1EncodeNext_VEX_MODRM_WsomethingWO_Vsomething_Wip_OR_ViceVersa;
             pThis->iRegOp            = 0;
+            pThis->iRmOp             = 1;
+            pThis->aOperands[0].cbOp = 16;
+            pThis->aOperands[1].cbOp = 16;
+            pThis->aOperands[0].enmLocation     = BS3CG1OPLOC_CTX_ZX_VLMAX;
+            pThis->aOperands[1].enmLocation     = BS3CG1OPLOC_CTX;
+            pThis->aOperands[1].enmLocationReg  = BS3CG1OPLOC_CTX;
+            pThis->aOperands[1].enmLocationMem  = BS3CG1OPLOC_MEM;
+            pThis->aOperands[0].idxFieldBase    = BS3CG1DST_XMM0;
+            pThis->aOperands[1].idxFieldBase    = BS3CG1DST_XMM0;
+            break;
+
+        case BS3CG1ENC_VEX_MODRM_Ed_WO_Vd_WZ:
+            pThis->pfnEncoder        = Bs3Cg1EncodeNext_VEX_MODRM_Vd_WO_Ed_WZ;
+            pThis->iRmOp             = 0;
+            pThis->iRegOp            = 1;
             pThis->aOperands[0].cbOp = 4;
             pThis->aOperands[1].cbOp = 4;
-            pThis->aOperands[0].enmLocation = BS3CG1OPLOC_CTX;
-            pThis->aOperands[1].enmLocation = BS3CG1OPLOC_CTX;
+            pThis->aOperands[0].idxFieldBase   = BS3CG1DST_EAX;
+            pThis->aOperands[1].idxFieldBase   = BS3CG1DST_XMM0_DW0_ZX;
+            pThis->aOperands[0].enmLocation    = BS3CG1OPLOC_CTX;
+            pThis->aOperands[0].enmLocationReg = BS3CG1OPLOC_CTX;
+            pThis->aOperands[0].enmLocationMem = BS3CG1OPLOC_MEM_WO;
+            pThis->aOperands[1].enmLocation    = BS3CG1OPLOC_CTX;
             break;
 
-        case BS3CG1ENC_MODRM_MbRO:
+        case BS3CG1ENC_VEX_MODRM_Eq_WO_Vq_WNZ:
+            pThis->pfnEncoder        = Bs3Cg1EncodeNext_VEX_MODRM_Vq_WO_Eq_WNZ;
             pThis->iRmOp             = 0;
-            pThis->aOperands[0].cbOp = 1;
-            pThis->aOperands[0].enmLocation = BS3CG1OPLOC_MEM;
+            pThis->iRegOp            = 1;
+            pThis->aOperands[0].cbOp = 8;
+            pThis->aOperands[1].cbOp = 8;
+            pThis->aOperands[0].idxFieldBase   = BS3CG1DST_RAX;
+            pThis->aOperands[1].idxFieldBase   = BS3CG1DST_XMM0_LO_ZX;
+            pThis->aOperands[0].enmLocation    = BS3CG1OPLOC_CTX;
+            pThis->aOperands[0].enmLocationReg = BS3CG1OPLOC_CTX;
+            pThis->aOperands[0].enmLocationMem = BS3CG1OPLOC_MEM_WO;
+            pThis->aOperands[1].enmLocation    = BS3CG1OPLOC_CTX;
             break;
 
-        case BS3CG1ENC_MODRM_MdRO:
+        case BS3CG1ENC_VEX_MODRM_Md_WO:
+            pThis->pfnEncoder        = Bs3Cg1EncodeNext_VEX_MODRM_Md_WO;
             pThis->iRmOp             = 0;
             pThis->aOperands[0].cbOp = 4;
-            pThis->aOperands[0].enmLocation = BS3CG1OPLOC_MEM;
+            pThis->aOperands[0].enmLocation = BS3CG1OPLOC_MEM_WO;
             break;
 
-        case BS3CG1ENC_MODRM_MdWO:
-        case BS3CG1ENC_VEX_MODRM_MdWO:
+        case BS3CG1ENC_VEX_MODRM_Md_WO_Vss:
+            pThis->pfnEncoder        = Bs3Cg1EncodeNext_VEX_MODRM_VsomethingWO_Msomething_Wip_Lig_OR_ViceVersa;
             pThis->iRmOp             = 0;
+            pThis->iRegOp            = 1;
             pThis->aOperands[0].cbOp = 4;
-            pThis->aOperands[0].enmLocation = BS3CG1OPLOC_MEM_RW;
+            pThis->aOperands[1].cbOp = 4;
+            pThis->aOperands[0].enmLocation  = BS3CG1OPLOC_MEM_WO;
+            pThis->aOperands[1].enmLocation  = BS3CG1OPLOC_CTX;
+            pThis->aOperands[0].idxFieldBase = BS3CG1DST_INVALID;
+            pThis->aOperands[1].idxFieldBase = BS3CG1DST_XMM0_DW0;
             break;
 
-        case BS3CG1ENC_FIXED:
-            /* nothing to do here */
+        case BS3CG1ENC_VEX_MODRM_Mq_WO_Vq:
+            pThis->pfnEncoder        = pThis->fFlags & BS3CG1INSTR_F_VEX_L_ZERO
+                                     ? Bs3Cg1EncodeNext_VEX_MODRM_VsomethingWO_Msomething_Wip_L0_OR_ViceVersa
+                                     : Bs3Cg1EncodeNext_VEX_MODRM_VsomethingWO_Msomething_Wip_Lig_OR_ViceVersa;
+            pThis->iRmOp             = 0;
+            pThis->iRegOp            = 1;
+            pThis->aOperands[0].cbOp = 8;
+            pThis->aOperands[1].cbOp = 8;
+            pThis->aOperands[0].enmLocation  = BS3CG1OPLOC_MEM_WO;
+            pThis->aOperands[1].enmLocation  = BS3CG1OPLOC_CTX;
+            pThis->aOperands[1].idxFieldBase = BS3CG1DST_XMM0_LO;
             break;
 
-        case BS3CG1ENC_FIXED_AL_Ib:
-            pThis->aOperands[0].cbOp = 1;
-            pThis->aOperands[1].cbOp = 1;
-            pThis->aOperands[0].enmLocation = BS3CG1OPLOC_CTX;
-            pThis->aOperands[1].enmLocation = BS3CG1OPLOC_IMM;
-            pThis->aOperands[0].idxField    = BS3CG1DST_AL;
-            pThis->aOperands[1].idxField    = BS3CG1DST_INVALID;
+        case BS3CG1ENC_VEX_MODRM_Mq_WO_Vsd:
+            pThis->pfnEncoder        = Bs3Cg1EncodeNext_VEX_MODRM_VsomethingWO_Msomething_Wip_Lig_OR_ViceVersa;
+            pThis->iRmOp             = 0;
+            pThis->iRegOp            = 1;
+            pThis->aOperands[0].cbOp = 8;
+            pThis->aOperands[1].cbOp = 8;
+            pThis->aOperands[0].enmLocation  = BS3CG1OPLOC_MEM_WO;
+            pThis->aOperands[1].enmLocation  = BS3CG1OPLOC_CTX;
+            pThis->aOperands[0].idxFieldBase = BS3CG1DST_INVALID;
+            pThis->aOperands[1].idxFieldBase = BS3CG1DST_XMM0_LO;
             break;
 
-        case BS3CG1ENC_FIXED_rAX_Iz:
-            pThis->aOperands[0].cbOp = 2;
-            pThis->aOperands[1].cbOp = 2;
-            pThis->aOperands[0].enmLocation = BS3CG1OPLOC_CTX;
-            pThis->aOperands[1].enmLocation = BS3CG1OPLOC_IMM;
-            pThis->aOperands[0].idxField    = BS3CG1DST_OZ_RAX;
-            pThis->aOperands[1].idxField    = BS3CG1DST_INVALID;
+        case BS3CG1ENC_VEX_MODRM_Mps_WO_Vps:
+        case BS3CG1ENC_VEX_MODRM_Mpd_WO_Vpd:
+        case BS3CG1ENC_VEX_MODRM_Mx_WO_Vx:
+            pThis->pfnEncoder        = Bs3Cg1EncodeNext_VEX_MODRM_VsomethingWO_Msomething_Wip_OR_ViceVersa;
+            pThis->iRmOp             = 0;
+            pThis->iRegOp            = 1;
+            pThis->aOperands[0].cbOp = 16;
+            pThis->aOperands[1].cbOp = 16;
+            pThis->aOperands[0].enmLocation  = BS3CG1OPLOC_MEM_WO;
+            pThis->aOperands[1].enmLocation  = BS3CG1OPLOC_CTX;
+            pThis->aOperands[1].idxFieldBase = BS3CG1DST_XMM0;
             break;
 
-        case BS3CG1ENC_MODRM_MOD_EQ_3:
-        case BS3CG1ENC_MODRM_MOD_NE_3:
+        case BS3CG1ENC_VEX_MODRM_Uss_WO_HssHi_Vss:
+            pThis->pfnEncoder        = Bs3Cg1EncodeNext_VEX_MODRM_VsomethingWO_Hsomething_Usomething_Lip_Wip_OR_ViceVersa;
+            pThis->iRegOp            = 2;
+            pThis->iRmOp             = 0;
+            pThis->aOperands[0].cbOp = 16;
+            pThis->aOperands[1].cbOp = 96;
+            pThis->aOperands[2].cbOp = 4;
+            pThis->aOperands[0].enmLocation  = BS3CG1OPLOC_CTX_ZX_VLMAX;
+            pThis->aOperands[1].enmLocation  = BS3CG1OPLOC_CTX;
+            pThis->aOperands[2].enmLocation  = BS3CG1OPLOC_CTX;
+            pThis->aOperands[0].idxFieldBase = BS3CG1DST_XMM0;
+            pThis->aOperands[1].idxFieldBase = BS3CG1DST_XMM0_HI96;
+            pThis->aOperands[2].idxFieldBase = BS3CG1DST_XMM0_DW0;
+            break;
+
+        case BS3CG1ENC_VEX_MODRM_Usd_WO_HsdHi_Vsd:
+            pThis->pfnEncoder        = Bs3Cg1EncodeNext_VEX_MODRM_VsomethingWO_Hsomething_Usomething_Lip_Wip_OR_ViceVersa;
+            pThis->iRegOp            = 2;
+            pThis->iRmOp             = 0;
+            pThis->aOperands[0].cbOp = 16;
+            pThis->aOperands[1].cbOp = 8;
+            pThis->aOperands[2].cbOp = 8;
+            pThis->aOperands[0].enmLocation  = BS3CG1OPLOC_CTX_ZX_VLMAX;
+            pThis->aOperands[1].enmLocation  = BS3CG1OPLOC_CTX;
+            pThis->aOperands[2].enmLocation  = BS3CG1OPLOC_CTX;
+            pThis->aOperands[0].idxFieldBase = BS3CG1DST_XMM0;
+            pThis->aOperands[1].idxFieldBase = BS3CG1DST_XMM0_HI;
+            pThis->aOperands[2].idxFieldBase = BS3CG1DST_XMM0_LO;
+            break;
+
+        case BS3CG1ENC_VEX_MODRM_Wps_WO_Vps:
+        case BS3CG1ENC_VEX_MODRM_Wpd_WO_Vpd:
+            pThis->pfnEncoder        = Bs3Cg1EncodeNext_VEX_MODRM_WsomethingWO_Vsomething_Wip_OR_ViceVersa;
+            pThis->iRmOp             = 0;
+            pThis->iRegOp            = 1;
+            pThis->aOperands[0].cbOp = 16;
+            pThis->aOperands[1].cbOp = 16;
+            pThis->aOperands[0].enmLocation     = BS3CG1OPLOC_CTX_ZX_VLMAX;
+            pThis->aOperands[0].enmLocationReg  = BS3CG1OPLOC_CTX_ZX_VLMAX;
+            pThis->aOperands[0].enmLocationMem  = BS3CG1OPLOC_MEM_WO;
+            pThis->aOperands[1].enmLocation     = BS3CG1OPLOC_CTX;
+            pThis->aOperands[0].idxFieldBase    = BS3CG1DST_XMM0;
+            pThis->aOperands[1].idxFieldBase    = BS3CG1DST_XMM0;
+            break;
+
+        case BS3CG1ENC_VEX_MODRM_Wq_WO_Vq:
+            pThis->pfnEncoder        = Bs3Cg1EncodeNext_VEX_MODRM_WsomethingWO_Vsomething_Wip_L0_OR_ViceVersa;
+            pThis->iRegOp            = 1;
+            pThis->iRmOp             = 0;
+            pThis->aOperands[0].cbOp = 8;
+            pThis->aOperands[1].cbOp = 8;
+            pThis->aOperands[0].enmLocation     = BS3CG1OPLOC_CTX_ZX_VLMAX;
+            pThis->aOperands[0].enmLocationReg  = BS3CG1OPLOC_CTX_ZX_VLMAX;
+            pThis->aOperands[0].enmLocationMem  = BS3CG1OPLOC_MEM_WO;
+            pThis->aOperands[1].enmLocation     = BS3CG1OPLOC_CTX;
+            pThis->aOperands[0].idxFieldBase    = BS3CG1DST_XMM0_LO;
+            pThis->aOperands[1].idxFieldBase    = BS3CG1DST_XMM0_LO;
+            break;
+
+        case BS3CG1ENC_VEX_MODRM_Wx_WO_Vx:
+            pThis->pfnEncoder        = Bs3Cg1EncodeNext_VEX_MODRM_WsomethingWO_Vsomething_Wip_OR_ViceVersa;
+            pThis->iRmOp             = 0;
+            pThis->iRegOp            = 1;
+            pThis->aOperands[0].cbOp = 16;
+            pThis->aOperands[1].cbOp = 16;
+            pThis->aOperands[0].enmLocation     = BS3CG1OPLOC_CTX_ZX_VLMAX;
+            pThis->aOperands[0].enmLocationReg  = BS3CG1OPLOC_CTX_ZX_VLMAX;
+            pThis->aOperands[0].enmLocationMem  = BS3CG1OPLOC_MEM_WO;
+            pThis->aOperands[1].enmLocation     = BS3CG1OPLOC_CTX;
+            pThis->aOperands[0].idxFieldBase    = BS3CG1DST_XMM0;
+            pThis->aOperands[1].idxFieldBase    = BS3CG1DST_XMM0;
+            break;
+
+
             /* Unused or invalid instructions mostly. */
+        //case BS3CG1ENC_VEX_FIXED:
+        //    pThis->pfnEncoder = Bs3Cg1EncodeNext_VEX_FIXED;
+        //    break;
+        case BS3CG1ENC_VEX_MODRM_MOD_EQ_3:
+            pThis->pfnEncoder = Bs3Cg1EncodeNext_VEX_MODRM_MOD_EQ_3;
+            break;
+        case BS3CG1ENC_VEX_MODRM_MOD_NE_3:
+            pThis->pfnEncoder = Bs3Cg1EncodeNext_VEX_MODRM_MOD_NE_3;
+            break;
+        case BS3CG1ENC_VEX_MODRM:
+            pThis->pfnEncoder = Bs3Cg1EncodeNext_VEX_MODRM;
             break;
 
+#endif /* BS3CG1_WITH_VEX */
+
         default:
             Bs3TestFailedF("Invalid/unimplemented enmEncoding for instruction #%RU32 (%.*s): %d",
                            pThis->iInstr, pThis->cchMnemonic, pThis->pchMnemonic, pThis->enmEncoding);
@@ -2309,7 +4997,7 @@ static BS3CG1ENC Bs3Cg1CalcNoneIntelInvalidEncoding(BS3CG1ENC enmEncoding)
     switch (enmEncoding)
     {
         case BS3CG1ENC_MODRM_Gb_Eb:
-        case BS3CG1ENC_MODRM_Gv_Ma:
+        case BS3CG1ENC_MODRM_Gv_RO_Ma:
         case BS3CG1ENC_FIXED:
             return BS3CG1ENC_FIXED;
         default:
@@ -2380,7 +5068,7 @@ static bool BS3_NEAR_CODE Bs3Cg3SetupSseAndAvx(PBS3CG1STATE pThis)
 static bool BS3_NEAR_CODE Bs3Cg1CpuSetupNext(PBS3CG1STATE pThis, unsigned iCpuSetup, bool BS3_FAR *pfInvalidInstr)
 {
     if (   (pThis->fFlags & BS3CG1INSTR_F_INVALID_64BIT)
-        && BS3_MODE_IS_64BIT_CODE(pThis->bMode))
+        && BS3CG1_IS_64BIT_TARGET(pThis))
         return false;
 
     switch (pThis->enmCpuTest)
@@ -2395,9 +5083,13 @@ static bool BS3_NEAR_CODE Bs3Cg1CpuSetupNext(PBS3CG1STATE pThis, unsigned iCpuSe
         case BS3CG1CPU_CLFLUSHOPT:
             return false;
 
+        case BS3CG1CPU_MMX:
+            return false;
+
         case BS3CG1CPU_SSE:
         case BS3CG1CPU_SSE2:
         case BS3CG1CPU_SSE3:
+        case BS3CG1CPU_SSE4_1:
         case BS3CG1CPU_AVX:
         case BS3CG1CPU_AVX2:
             if (iCpuSetup > 0 || *pfInvalidInstr)
@@ -2432,7 +5124,7 @@ static bool BS3_NEAR_CODE Bs3Cg1CpuSetupFirst(PBS3CG1STATE pThis)
     uint32_t fEdx;
 
     if (   (pThis->fFlags & BS3CG1INSTR_F_INVALID_64BIT)
-        && BS3_MODE_IS_64BIT_CODE(pThis->bMode))
+        && BS3CG1_IS_64BIT_TARGET(pThis))
         return false;
 
     switch (pThis->enmCpuTest)
@@ -2465,9 +5157,19 @@ static bool BS3_NEAR_CODE Bs3Cg1CpuSetupFirst(PBS3CG1STATE pThis)
                 return true;
             return false;
 
+        case BS3CG1CPU_MMX:
+            if (g_uBs3CpuDetected & BS3CPU_F_CPUID)
+            {
+                ASMCpuIdExSlow(1, 0, 0, 0, NULL, NULL, NULL, &fEdx);
+                if (fEdx & X86_CPUID_FEATURE_EDX_MMX)
+                    return Bs3Cg3SetupSseAndAvx(pThis); /** @todo only do FNSAVE/FXSAVE here? */
+            }
+            return false;
+
         case BS3CG1CPU_SSE:
         case BS3CG1CPU_SSE2:
         case BS3CG1CPU_SSE3:
+        case BS3CG1CPU_SSE4_1:
         case BS3CG1CPU_AVX:
             if (g_uBs3CpuDetected & BS3CPU_F_CPUID)
             {
@@ -2486,6 +5188,10 @@ static bool BS3_NEAR_CODE Bs3Cg1CpuSetupFirst(PBS3CG1STATE pThis)
                         if (fEcx & X86_CPUID_FEATURE_ECX_SSE3)
                             return Bs3Cg3SetupSseAndAvx(pThis);
                         return false;
+                    case BS3CG1CPU_SSE4_1:
+                        if (fEcx & X86_CPUID_FEATURE_ECX_SSE4_1)
+                            return Bs3Cg3SetupSseAndAvx(pThis);
+                        return false;
                     case BS3CG1CPU_AVX:
                         if (fEcx & X86_CPUID_FEATURE_ECX_AVX)
                             return Bs3Cg3SetupSseAndAvx(pThis) && !BS3_MODE_IS_RM_OR_V86(pThis->bMode);
@@ -2562,13 +5268,15 @@ static bool BS3_NEAR_CODE Bs3Cg1RunSelector(PBS3CG1STATE pThis, PCBS3CG1TESTHDR
             CASE_PRED(BS3CG1PRED_SIZE_O16, pThis->cbOperand == 2);
             CASE_PRED(BS3CG1PRED_SIZE_O32, pThis->cbOperand == 4);
             CASE_PRED(BS3CG1PRED_SIZE_O64, pThis->cbOperand == 8);
+            CASE_PRED(BS3CG1PRED_VEXL_0, pThis->uVexL == 0);
+            CASE_PRED(BS3CG1PRED_VEXL_1, pThis->uVexL == 1);
             CASE_PRED(BS3CG1PRED_RING_0, pThis->uCpl == 0);
             CASE_PRED(BS3CG1PRED_RING_1, pThis->uCpl == 1);
             CASE_PRED(BS3CG1PRED_RING_2, pThis->uCpl == 2);
             CASE_PRED(BS3CG1PRED_RING_3, pThis->uCpl == 3);
             CASE_PRED(BS3CG1PRED_RING_0_THRU_2, pThis->uCpl <= 2);
             CASE_PRED(BS3CG1PRED_RING_1_THRU_3, pThis->uCpl >= 1);
-            CASE_PRED(BS3CG1PRED_CODE_64BIT, BS3_MODE_IS_64BIT_CODE(pThis->bMode));
+            CASE_PRED(BS3CG1PRED_CODE_64BIT, BS3CG1_IS_64BIT_TARGET(pThis));
             CASE_PRED(BS3CG1PRED_CODE_32BIT, BS3_MODE_IS_32BIT_CODE(pThis->bMode));
             CASE_PRED(BS3CG1PRED_CODE_16BIT, BS3_MODE_IS_16BIT_CODE(pThis->bMode));
             CASE_PRED(BS3CG1PRED_MODE_REAL,  BS3_MODE_IS_RM_SYS(pThis->bMode));
@@ -2640,29 +5348,34 @@ static bool BS3_NEAR_CODE Bs3Cg1RunContextModifier(PBS3CG1STATE pThis, PBS3REGCT
         /*
          * Decode the instruction.
          */
-        uint8_t const   bOpcode = *pbCode++;
-        unsigned        cbValue;
-        unsigned        cbDst;
-        BS3CG1DST       idxField;
-        BS3PTRUNION     PtrField;
-
-        /* Expand the destiation field (can be escaped). */
+        uint8_t const       bOpcode = *pbCode++;
+        unsigned            cbValue;
+        unsigned            cbDst;
+        BS3CG1DST           idxField;
+        BS3PTRUNION         PtrField;
+        uint8_t BS3_FAR    *pbMemCopy = NULL;
+        bool                fZxVlMax;
+
+        /* Expand the destiation field (can be escaped). Set fZxVlMax. */
         switch (bOpcode & BS3CG1_CTXOP_DST_MASK)
         {
             case BS3CG1_CTXOP_OP1:
                 idxField = pThis->aOperands[0].idxField;
                 if (idxField == BS3CG1DST_INVALID)
                     idxField = BS3CG1DST_OP1;
+                fZxVlMax = pEflCtx != NULL && pThis->aOperands[0].enmLocation == BS3CG1OPLOC_CTX_ZX_VLMAX;
                 break;
 
             case BS3CG1_CTXOP_OP2:
                 idxField = pThis->aOperands[1].idxField;
                 if (idxField == BS3CG1DST_INVALID)
                     idxField = BS3CG1DST_OP2;
+                fZxVlMax = pEflCtx != NULL && pThis->aOperands[1].enmLocation == BS3CG1OPLOC_CTX_ZX_VLMAX;
                 break;
 
             case BS3CG1_CTXOP_EFL:
                 idxField = BS3CG1DST_EFL;
+                fZxVlMax = false;
                 break;
 
             case BS3CG1_CTXOP_DST_ESC:
@@ -2673,14 +5386,19 @@ static bool BS3_NEAR_CODE Bs3Cg1RunContextModifier(PBS3CG1STATE pThis, PBS3REGCT
                     {
                         if (idxField > BS3CG1DST_INVALID)
                         {
-                            uint8_t idxField2 = pThis->aOperands[idxField - BS3CG1DST_OP1].idxField;
+                            unsigned idxOp     = idxField - BS3CG1DST_OP1;
+                            uint8_t  idxField2 = pThis->aOperands[idxOp].idxField;
                             if (idxField2 != BS3CG1DST_INVALID)
                                 idxField = idxField2;
+                            fZxVlMax = pEflCtx != NULL && pThis->aOperands[idxOp].enmLocation == BS3CG1OPLOC_CTX_ZX_VLMAX;
                             break;
                         }
                     }
                     else if (idxField < BS3CG1DST_END)
+                    {
+                        fZxVlMax = false;
                         break;
+                    }
                     return Bs3TestFailedF("Malformed context instruction: idxField=%d", idxField);
                 }
                 /* fall thru */
@@ -2688,7 +5406,6 @@ static bool BS3_NEAR_CODE Bs3Cg1RunContextModifier(PBS3CG1STATE pThis, PBS3REGCT
                 return Bs3TestFailed("Malformed context instruction: Destination");
         }
 
-
         /* Expand value size (can be escaped). */
         switch (bOpcode & BS3CG1_CTXOP_SIZE_MASK)
         {
@@ -2732,6 +5449,7 @@ static bool BS3_NEAR_CODE Bs3Cg1RunContextModifier(PBS3CG1STATE pThis, PBS3REGCT
             /*
              * Deal with fields up to 8-byte wide.
              */
+
             /* Get the value. */
             uint64_t uValue;
             if ((bOpcode & BS3CG1_CTXOP_SIGN_EXT))
@@ -2787,8 +5505,12 @@ static bool BS3_NEAR_CODE Bs3Cg1RunContextModifier(PBS3CG1STATE pThis, PBS3REGCT
                         break;
 
                     case BS3CG1OPLOC_MEM_RW:
+                    case BS3CG1OPLOC_MEM_WO:
                         if (pbInstr)
+                        {
                             PtrField.pu8 = &pThis->pbDataPg[X86_PAGE_SIZE - pThis->aOperands[idxOp].off];
+                            pbMemCopy    = pThis->MemOp.ab;
+                        }
                         else
                             PtrField.pu8 = pThis->MemOp.ab;
                         break;
@@ -2818,7 +5540,7 @@ static bool BS3_NEAR_CODE Bs3Cg1RunContextModifier(PBS3CG1STATE pThis, PBS3REGCT
             }
             /* FPU and FXSAVE format. */
             else if (   pThis->pExtCtx->enmMethod != BS3EXTCTXMETHOD_ANCIENT
-                     && offField - sizeof(BS3REGCTX) <= RT_UOFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[15]) )
+                     && offField - sizeof(BS3REGCTX) < RT_UOFFSET_AFTER(BS3EXTCTX, Ctx.x87.aXMM[15]))
             {
                 if (!pThis->fWorkExtCtx)
                     return Bs3TestFailedF("Extended context disabled: Field %d @ %#x LB %u\n", idxField, offField, cbDst);
@@ -2826,7 +5548,7 @@ static bool BS3_NEAR_CODE Bs3Cg1RunContextModifier(PBS3CG1STATE pThis, PBS3REGCT
             }
             /** @todo other FPU fields and FPU state formats. */
             else
-                return Bs3TestFailedF("Todo implement me: cbDst=%u idxField=%d offField=%#x", cbDst, idxField, offField);
+                return Bs3TestFailedF("Todo implement me: cbDst=%u idxField=%d offField=%#x (<= 8)", cbDst, idxField, offField);
 
 #ifdef BS3CG1_DEBUG_CTX_MOD
             switch (cbDst)
@@ -2874,13 +5596,19 @@ static bool BS3_NEAR_CODE Bs3Cg1RunContextModifier(PBS3CG1STATE pThis, PBS3REGCT
                     break;
 
                 case 4:
-                    if ((unsigned)(idxField - BS3CG1DST_XMM0_DW0_ZX) <= (unsigned)(BS3CG1DST_XMM15_DW0_ZX - BS3CG1DST_XMM0_DW0_ZX))
+                    if (   (unsigned)(idxField - BS3CG1DST_XMM0_DW0_ZX) <= (unsigned)(BS3CG1DST_XMM15_DW0_ZX - BS3CG1DST_XMM0_DW0_ZX)
+                        || fZxVlMax)
                     {
                         PtrField.pu32[1] = 0;
                         PtrField.pu64[1] = 0;
                     }
-                    else if (offField <= RT_OFFSETOF(BS3REGCTX, r15)) /* Clear the top dword. */
+                    else if (offField <= RT_OFFSETOF(BS3REGCTX, r15) /* Clear the top dword. */)
+                        PtrField.pu32[1] = 0;
+                    else if ((unsigned)(idxField - BS3CG1DST_MM0_LO_ZX) <= (unsigned)(BS3CG1DST_MM7_LO_ZX - BS3CG1DST_MM0_LO_ZX))
+                    {
                         PtrField.pu32[1] = 0;
+                        PtrField.pu32[2] = 0xffff; /* observed on skylake */
+                    }
                     switch (bOpcode & BS3CG1_CTXOP_OPERATOR_MASK)
                     {
                         case BS3CG1_CTXOP_ASSIGN:   *PtrField.pu32  =  (uint32_t)uValue; break;
@@ -2891,8 +5619,12 @@ static bool BS3_NEAR_CODE Bs3Cg1RunContextModifier(PBS3CG1STATE pThis, PBS3REGCT
                     break;
 
                 case 8:
-                    if ((unsigned)(idxField - BS3CG1DST_XMM0_LO_ZX) <= (unsigned)(BS3CG1DST_XMM15_LO_ZX - BS3CG1DST_XMM0_LO_ZX))
+                    if (   (unsigned)(idxField - BS3CG1DST_XMM0_LO_ZX) <= (unsigned)(BS3CG1DST_XMM15_LO_ZX - BS3CG1DST_XMM0_LO_ZX)
+                        || fZxVlMax)
                         PtrField.pu64[1] = 0;
+                    else if ((unsigned)(idxField - BS3CG1DST_MM0) <= (unsigned)(BS3CG1DST_MM7 - BS3CG1DST_MM0))
+                        PtrField.pu32[2] = 0xffff; /* observed on skylake */
+
                     switch (bOpcode & BS3CG1_CTXOP_OPERATOR_MASK)
                     {
                         case BS3CG1_CTXOP_ASSIGN:   *PtrField.pu64  =  (uint64_t)uValue; break;
@@ -2915,7 +5647,16 @@ static bool BS3_NEAR_CODE Bs3Cg1RunContextModifier(PBS3CG1STATE pThis, PBS3REGCT
                 default: BS3CG1_DPRINTF(("dbg:    --> %s: %#018RX64\n", g_aszBs3Cg1DstFields[idxField].sz, *PtrField.pu64)); break;
             }
 #endif
-
+            if (fZxVlMax)
+            {
+                uintptr_t iReg = ((uintptr_t)PtrField.pu8 - (uintptr_t)&pThis->pExtCtx->Ctx.x87.aXMM[0])
+                               / sizeof(pThis->pExtCtx->Ctx.x87.aXMM[0]);
+                pThis->pExtCtx->Ctx.x.u.YmmHi.aYmmHi[iReg].au64[0] = 0;
+                pThis->pExtCtx->Ctx.x.u.YmmHi.aYmmHi[iReg].au64[1] = 0;
+#ifdef BS3CG1_DEBUG_CTX_MOD
+                BS3CG1_DPRINTF(("dbg:    --> cleared YMM%u_HI\n", iReg));
+#endif
+            }
         }
         /*
          * Deal with larger field (FPU, SSE, AVX, ...).
@@ -2930,8 +5671,10 @@ static bool BS3_NEAR_CODE Bs3Cg1RunContextModifier(PBS3CG1STATE pThis, PBS3REGCT
                 X86ZMMREG   ZmmReg;
                 uint8_t     ab[sizeof(X86ZMMREG)];
                 uint32_t    au32[sizeof(X86ZMMREG) / sizeof(uint32_t)];
+                uint64_t    au64[sizeof(X86ZMMREG) / sizeof(uint64_t)];
             } Value;
-            unsigned const offField = g_aoffBs3Cg1DstFields[idxField];
+            unsigned const  offField = g_aoffBs3Cg1DstFields[idxField];
+            unsigned        iReg;
 
             if (!pThis->fWorkExtCtx)
                 return Bs3TestFailedF("Extended context disabled: Field %d @ %#x LB %u\n", idxField, offField, cbDst);
@@ -2948,7 +5691,7 @@ static bool BS3_NEAR_CODE Bs3Cg1RunContextModifier(PBS3CG1STATE pThis, PBS3REGCT
 
             /* Optimized access to XMM and STx registers. */
             if (   pThis->pExtCtx->enmMethod != BS3EXTCTXMETHOD_ANCIENT
-                && offField - sizeof(BS3REGCTX) <= RT_UOFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[15]) )
+                && offField - sizeof(BS3REGCTX) < RT_UOFFSET_AFTER(BS3EXTCTX, Ctx.x87.aXMM[15]) )
                 PtrField.pb = (uint8_t *)pThis->pExtCtx + offField - sizeof(BS3REGCTX);
             /* Non-register operands: */
             else if ((unsigned)(idxField - BS3CG1DST_OP1) < 4U)
@@ -2963,8 +5706,12 @@ static bool BS3_NEAR_CODE Bs3Cg1RunContextModifier(PBS3CG1STATE pThis, PBS3REGCT
                         break;
 
                     case BS3CG1OPLOC_MEM_RW:
+                    case BS3CG1OPLOC_MEM_WO:
                         if (pbInstr)
+                        {
                             PtrField.pu8 = &pThis->pbDataPg[X86_PAGE_SIZE - pThis->aOperands[idxOp].off];
+                            pbMemCopy    = pThis->MemOp.ab;
+                        }
                         else
                             PtrField.pu8 = pThis->MemOp.ab;
                         break;
@@ -2975,12 +5722,57 @@ static bool BS3_NEAR_CODE Bs3Cg1RunContextModifier(PBS3CG1STATE pThis, PBS3REGCT
                                               pThis->aOperands[idxOp].off, pThis->aOperands[idxOp].idxField);
                 }
             }
-            /* The YMM (AVX) and the first 16 ZMM (AVX512) registers have split storage in
-               the state, so they need special handling.  */
-            else
+            /* The YMM (AVX) registers have split storage in the state, so they need special handling. */
+            else if ((iReg = idxField - BS3CG1DST_YMM0) < 16U)
             {
-                return Bs3TestFailedF("TODO: implement me: cbDst=%d idxField=%d (AVX and other weird state)", cbDst, idxField);
+                /* The first 128-bits in XMM land. */
+                PtrField.pu64 = &pThis->pExtCtx->Ctx.x87.aXMM[iReg].au64[0];
+                switch (bOpcode & BS3CG1_CTXOP_OPERATOR_MASK)
+                {
+                    case BS3CG1_CTXOP_ASSIGN:
+                        PtrField.pu64[0]  =  Value.au64[0];
+                        PtrField.pu64[1]  =  Value.au64[1];
+                        break;
+                    case BS3CG1_CTXOP_OR:
+                        PtrField.pu64[0] |=  Value.au64[0];
+                        PtrField.pu64[1] |=  Value.au64[1];
+                        break;
+                    case BS3CG1_CTXOP_AND:
+                        PtrField.pu64[0] &=  Value.au64[0];
+                        PtrField.pu64[1] &=  Value.au64[1];
+                        break;
+                    case BS3CG1_CTXOP_AND_INV:
+                        PtrField.pu64[0] &= ~Value.au64[0];
+                        PtrField.pu64[1] &= ~Value.au64[1];
+                        break;
+                }
+
+                /* The second 128-bit in YMM_HI land. */
+                PtrField.pu64 = &pThis->pExtCtx->Ctx.x.u.YmmHi.aYmmHi[iReg].au64[0];
+                switch (bOpcode & BS3CG1_CTXOP_OPERATOR_MASK)
+                {
+                    case BS3CG1_CTXOP_ASSIGN:
+                        PtrField.pu64[0]  =  Value.au64[2];
+                        PtrField.pu64[1]  =  Value.au64[3];
+                        break;
+                    case BS3CG1_CTXOP_OR:
+                        PtrField.pu64[0] |=  Value.au64[2];
+                        PtrField.pu64[1] |=  Value.au64[3];
+                        break;
+                    case BS3CG1_CTXOP_AND:
+                        PtrField.pu64[0] &=  Value.au64[2];
+                        PtrField.pu64[1] &=  Value.au64[3];
+                        break;
+                    case BS3CG1_CTXOP_AND_INV:
+                        PtrField.pu64[0] &= ~Value.au64[2];
+                        PtrField.pu64[1] &= ~Value.au64[3];
+                        break;
+                }
+                PtrField.pb = NULL;
             }
+            /* AVX512 needs handling like above, but more complicated. */
+            else
+                return Bs3TestFailedF("TODO: implement me: cbDst=%d idxField=%d (AVX and other weird state)", cbDst, idxField);
 
             if (PtrField.pb)
             {
@@ -3009,7 +5801,33 @@ static bool BS3_NEAR_CODE Bs3Cg1RunContextModifier(PBS3CG1STATE pThis, PBS3REGCT
 #ifdef BS3CG1_DEBUG_CTX_MOD
                 BS3CG1_DPRINTF(("dbg:    --> %s: %.*Rhxs\n", g_aszBs3Cg1DstFields[idxField].sz, cbDst, PtrField.pb));
 #endif
+
+                if (fZxVlMax)
+                {
+                    uintptr_t iReg = ((uintptr_t)PtrField.pu8 - (uintptr_t)&pThis->pExtCtx->Ctx.x87.aXMM[0])
+                                   / sizeof(pThis->pExtCtx->Ctx.x87.aXMM[0]);
+                    if (cbDst < 16)
+                    {
+                        for (i = cbDst / 4; i < 4; i++)
+                            PtrField.pu32[i++] = 0;
+#ifdef BS3CG1_DEBUG_CTX_MOD
+                        BS3CG1_DPRINTF(("dbg:    --> cleared high %u bytes of XMM%u\n", 16 - cbDst, iReg));
+#endif
+                    }
+                    pThis->pExtCtx->Ctx.x.u.YmmHi.aYmmHi[iReg].au64[0] = 0;
+                    pThis->pExtCtx->Ctx.x.u.YmmHi.aYmmHi[iReg].au64[1] = 0;
+#ifdef BS3CG1_DEBUG_CTX_MOD
+                    BS3CG1_DPRINTF(("dbg:    --> cleared YMM%u_HI\n", iReg));
+#endif
+                }
             }
+
+            /*
+             * Hack! Update pThis->MemOp when setting up the inputs so we can
+             *       correctly validate value and alignment exceptions.
+             */
+            if (pbMemCopy && PtrField.pv)
+                Bs3MemCpy(pbMemCopy, PtrField.pv, cbDst);
         }
 
         /*
@@ -3090,7 +5908,8 @@ static bool BS3_NEAR_CODE Bs3Cg1CheckResult(PBS3CG1STATE pThis, uint8_t bTestXcp
         {
             iOperand = pThis->cOperands;
             while (iOperand-- > 0)
-                if (pThis->aOperands[iOperand].enmLocation == BS3CG1OPLOC_MEM_RW)
+                if (   pThis->aOperands[iOperand].enmLocation == BS3CG1OPLOC_MEM_RW
+                    || pThis->aOperands[iOperand].enmLocation == BS3CG1OPLOC_MEM_WO)
                 {
                     if (pThis->aOperands[iOperand].off)
                     {
@@ -3182,6 +6001,15 @@ static bool BS3_NEAR_CODE Bs3Cg1CheckResult(PBS3CG1STATE pThis, uint8_t bTestXcp
                                                pResult->Ctx.x87.aXMM[i].au64[0],
                                                pExpect->Ctx.x87.aXMM[i].au64[1],
                                                pExpect->Ctx.x87.aXMM[i].au64[0]);
+                if (pExpect->fXcr0Saved & XSAVE_C_YMM)
+                    for (i = 0; i < (ARCH_BITS == 64 ? 16 : 8); i++)
+                        if (   pResult->Ctx.x.u.YmmHi.aYmmHi[i].au64[0] != pExpect->Ctx.x.u.YmmHi.aYmmHi[i].au64[0]
+                            || pResult->Ctx.x.u.YmmHi.aYmmHi[i].au64[1] != pExpect->Ctx.x.u.YmmHi.aYmmHi[i].au64[1])
+                            fOkay = Bs3TestFailedF("YMM%u_HI: %#010RX64'%016RX64, expected %#010RX64'%08RX64", i,
+                                                   pResult->Ctx.x.u.YmmHi.aYmmHi[i].au64[1],
+                                                   pResult->Ctx.x.u.YmmHi.aYmmHi[i].au64[0],
+                                                   pExpect->Ctx.x.u.YmmHi.aYmmHi[i].au64[1],
+                                                   pExpect->Ctx.x.u.YmmHi.aYmmHi[i].au64[0]);
             }
             else
                 fOkay = Bs3TestFailedF("Unsupported extended CPU context method: %d", pExpect->enmMethod);
@@ -3258,6 +6086,7 @@ static bool BS3_NEAR_CODE Bs3Cg1CheckResult(PBS3CG1STATE pThis, uint8_t bTestXcp
 
             case BS3CG1OPLOC_MEM:
             case BS3CG1OPLOC_MEM_RW:
+            case BS3CG1OPLOC_MEM_WO:
                 if (pThis->aOperands[iOperand].off)
                 {
                     PtrUnion.pb = &pThis->pbDataPg[X86_PAGE_SIZE - pThis->aOperands[iOperand].off];
@@ -3272,7 +6101,8 @@ static bool BS3_NEAR_CODE Bs3Cg1CheckResult(PBS3CG1STATE pThis, uint8_t bTestXcp
                                           pThis->aOperands[iOperand].cbOp, PtrUnion.pb);
                             break;
                     }
-                    if (pThis->aOperands[iOperand].enmLocation == BS3CG1OPLOC_MEM_RW)
+                    if (   pThis->aOperands[iOperand].enmLocation == BS3CG1OPLOC_MEM_WO
+                        || pThis->aOperands[iOperand].enmLocation == BS3CG1OPLOC_MEM_RW)
                     {
                         PtrUnion.pb = pThis->MemOp.ab;
                         switch (pThis->aOperands[iOperand].cbOp)
@@ -3306,6 +6136,7 @@ static bool BS3_NEAR_CODE Bs3Cg1CheckResult(PBS3CG1STATE pThis, uint8_t bTestXcp
     if (pThis->fWorkExtCtx)
         Bs3TestPrintf("xcr0=%RX64\n", pThis->pResultExtCtx->fXcr0Saved);
     Bs3TestPrintf("\n");
+ASMHalt();
     return false;
 }
 
@@ -3542,26 +6373,26 @@ bool BS3_NEAR_CODE BS3_CMN_NM(Bs3Cg1Init)(PBS3CG1STATE pThis, uint8_t bMode)
         }
         for (i = 0; i < RT_ELEMENTS(pExtCtx->Ctx.x87.aXMM); i++)
         {
-            pExtCtx->Ctx.x87.aXMM[i].au16[0] = i;
-            pExtCtx->Ctx.x87.aXMM[i].au16[1] = i;
-            pExtCtx->Ctx.x87.aXMM[i].au16[2] = i;
-            pExtCtx->Ctx.x87.aXMM[i].au16[3] = i;
-            pExtCtx->Ctx.x87.aXMM[i].au16[4] = i;
-            pExtCtx->Ctx.x87.aXMM[i].au16[5] = i;
-            pExtCtx->Ctx.x87.aXMM[i].au16[6] = i;
-            pExtCtx->Ctx.x87.aXMM[i].au16[7] = i;
+            pExtCtx->Ctx.x87.aXMM[i].au16[0] = i | UINT16_C(0x8f00);
+            pExtCtx->Ctx.x87.aXMM[i].au16[1] = i | UINT16_C(0x8e00);
+            pExtCtx->Ctx.x87.aXMM[i].au16[2] = i | UINT16_C(0x8d00);
+            pExtCtx->Ctx.x87.aXMM[i].au16[3] = i | UINT16_C(0x8c00);
+            pExtCtx->Ctx.x87.aXMM[i].au16[4] = i | UINT16_C(0x8b00);
+            pExtCtx->Ctx.x87.aXMM[i].au16[5] = i | UINT16_C(0x8a00);
+            pExtCtx->Ctx.x87.aXMM[i].au16[6] = i | UINT16_C(0x8900);
+            pExtCtx->Ctx.x87.aXMM[i].au16[7] = i | UINT16_C(0x8800);
         }
         if (pExtCtx->fXcr0Nominal & XSAVE_C_YMM)
-            for (i = 0; i < RT_ELEMENTS(pExtCtx->Ctx.x.u.Intel.YmmHi.aYmmHi); i++)
+            for (i = 0; i < RT_ELEMENTS(pExtCtx->Ctx.x.u.YmmHi.aYmmHi); i++)
             {
-                pExtCtx->Ctx.x.u.Intel.YmmHi.aYmmHi[i].au16[0] = i << 8;
-                pExtCtx->Ctx.x.u.Intel.YmmHi.aYmmHi[i].au16[1] = i << 8;
-                pExtCtx->Ctx.x.u.Intel.YmmHi.aYmmHi[i].au16[2] = i << 8;
-                pExtCtx->Ctx.x.u.Intel.YmmHi.aYmmHi[i].au16[3] = i << 8;
-                pExtCtx->Ctx.x.u.Intel.YmmHi.aYmmHi[i].au16[4] = i << 8;
-                pExtCtx->Ctx.x.u.Intel.YmmHi.aYmmHi[i].au16[5] = i << 8;
-                pExtCtx->Ctx.x.u.Intel.YmmHi.aYmmHi[i].au16[6] = i << 8;
-                pExtCtx->Ctx.x.u.Intel.YmmHi.aYmmHi[i].au16[7] = i << 8;
+                pExtCtx->Ctx.x.u.YmmHi.aYmmHi[i].au16[0] = (i << 8) | (i << 12) | 0xff;
+                pExtCtx->Ctx.x.u.YmmHi.aYmmHi[i].au16[1] = (i << 8) | (i << 12) | 0xfe;
+                pExtCtx->Ctx.x.u.YmmHi.aYmmHi[i].au16[2] = (i << 8) | (i << 12) | 0xfd;
+                pExtCtx->Ctx.x.u.YmmHi.aYmmHi[i].au16[3] = (i << 8) | (i << 12) | 0xfc;
+                pExtCtx->Ctx.x.u.YmmHi.aYmmHi[i].au16[4] = (i << 8) | (i << 12) | 0xfb;
+                pExtCtx->Ctx.x.u.YmmHi.aYmmHi[i].au16[5] = (i << 8) | (i << 12) | 0xfa;
+                pExtCtx->Ctx.x.u.YmmHi.aYmmHi[i].au16[6] = (i << 8) | (i << 12) | 0xf9;
+                pExtCtx->Ctx.x.u.YmmHi.aYmmHi[i].au16[7] = (i << 8) | (i << 12) | 0xf8;
             }
 
     }
@@ -3636,7 +6467,7 @@ static uint8_t BS3_NEAR_CODE BS3_CMN_NM(Bs3Cg1WorkerInner)(PBS3CG1STATE pThis)
         if (   (pThis->fFlags & BS3CG1INSTR_F_INTEL_DECODES_INVALID)
             && pThis->bCpuVendor != BS3CPUVENDOR_INTEL
             && (   (pThis->fFlags & (BS3CG1INSTR_F_UNUSED | BS3CG1INSTR_F_INVALID))
-                || (BS3_MODE_IS_64BIT_CODE(pThis->bMode) && (pThis->fFlags & BS3CG1INSTR_F_INVALID_64BIT))
+                || (BS3CG1_IS_64BIT_TARGET(pThis) && (pThis->fFlags & BS3CG1INSTR_F_INVALID_64BIT))
                 || fOuterInvalidInstr ) )
             pThis->enmEncoding = Bs3Cg1CalcNoneIntelInvalidEncoding(pThis->enmEncoding);
 
@@ -3732,8 +6563,11 @@ static uint8_t BS3_NEAR_CODE BS3_CMN_NM(Bs3Cg1WorkerInner)(PBS3CG1STATE pThis)
                                     || Bs3Cg1RunContextModifier(pThis, &pThis->Ctx, pHdr,
                                                                 pHdr->cbSelector + pHdr->cbInput, pHdr->cbOutput,
                                                                 &pThis->TrapFrame.Ctx, NULL /*pbCode*/))
-                                {
                                     Bs3Cg1CheckResult(pThis, bTestXcptExpected, false /*fInvalidEncodingPgFault*/, iEncoding);
+                                else
+                                {
+                                    Bs3TestPrintf("Bs3Cg1RunContextModifier(out): iEncoding=%u iTest=%u\n", iEncoding, pThis->iTest);
+                                    ASMHalt();
                                 }
 
                                 /*
@@ -3768,6 +6602,11 @@ static uint8_t BS3_NEAR_CODE BS3_CMN_NM(Bs3Cg1WorkerInner)(PBS3CG1STATE pThis)
                                     Bs3Cg1CheckResult(pThis, X86_XCPT_PF, true /*fInvalidEncodingPgFault*/, iEncoding);
                                 }
                             }
+                            else
+                            {
+                                Bs3TestPrintf("Bs3Cg1RunContextModifier(in): iEncoding=%u iTest=%u\n", iEncoding, pThis->iTest);
+                                ASMHalt();
+                            }
                         }
                         else
                             BS3CG1_DPRINTF(("dbg:  Skipping #%u\n", pThis->iTest));
@@ -3818,7 +6657,7 @@ BS3_DECL_FAR(uint8_t) BS3_CMN_NM(Bs3Cg1Worker)(uint8_t bMode)
 
 #if 0
     /* (for debugging) */
-    //if (bMode == BS3_MODE_PP32)
+    if (bMode == BS3_MODE_PPV86)
     {
         Bs3TestTerm();
         Bs3Shutdown();
diff --git a/src/VBox/ValidationKit/bootsectors/bs3-cpu-generated-1.h b/src/VBox/ValidationKit/bootsectors/bs3-cpu-generated-1.h
index 99a97ee..ec1874a 100644
--- a/src/VBox/ValidationKit/bootsectors/bs3-cpu-generated-1.h
+++ b/src/VBox/ValidationKit/bootsectors/bs3-cpu-generated-1.h
@@ -42,25 +42,68 @@ typedef enum BS3CG1OP
     BS3CG1OP_INVALID = 0,
 
     BS3CG1OP_Eb,
+    BS3CG1OP_Ed,
+    BS3CG1OP_Ed_WO,
+    BS3CG1OP_Eq,
+    BS3CG1OP_Eq_WO,
     BS3CG1OP_Ev,
+    BS3CG1OP_Qq,
+    BS3CG1OP_Qq_WO,
     BS3CG1OP_Wss,
+    BS3CG1OP_Wss_WO,
     BS3CG1OP_Wsd,
+    BS3CG1OP_Wsd_WO,
     BS3CG1OP_Wps,
+    BS3CG1OP_Wps_WO,
     BS3CG1OP_Wpd,
+    BS3CG1OP_Wpd_WO,
     BS3CG1OP_Wdq,
-    BS3CG1OP_WqZxReg,
+    BS3CG1OP_Wdq_WO,
+    BS3CG1OP_Wq,
+    BS3CG1OP_Wq_WO,
+    BS3CG1OP_WqZxReg_WO,
+    BS3CG1OP_Wx,
+    BS3CG1OP_Wx_WO,
 
     BS3CG1OP_Gb,
     BS3CG1OP_Gv,
+    BS3CG1OP_Gv_RO,
+    BS3CG1OP_HssHi,
+    BS3CG1OP_HsdHi,
+    BS3CG1OP_HqHi,
+    BS3CG1OP_Nq,
+    BS3CG1OP_Pd,
+    BS3CG1OP_PdZx_WO,
+    BS3CG1OP_Pq,
+    BS3CG1OP_Pq_WO,
     BS3CG1OP_Uq,
     BS3CG1OP_UqHi,
+    BS3CG1OP_Uss,
+    BS3CG1OP_Uss_WO,
+    BS3CG1OP_Usd,
+    BS3CG1OP_Usd_WO,
+    BS3CG1OP_Vd,
+    BS3CG1OP_Vd_WO,
+    BS3CG1OP_VdZx_WO,
     BS3CG1OP_Vss,
-    BS3CG1OP_VssZxReg,
+    BS3CG1OP_Vss_WO,
+    BS3CG1OP_VssZx_WO,
     BS3CG1OP_Vsd,
+    BS3CG1OP_Vsd_WO,
+    BS3CG1OP_VsdZx_WO,
     BS3CG1OP_Vps,
+    BS3CG1OP_Vps_WO,
     BS3CG1OP_Vpd,
+    BS3CG1OP_Vpd_WO,
     BS3CG1OP_Vq,
+    BS3CG1OP_Vq_WO,
     BS3CG1OP_Vdq,
+    BS3CG1OP_Vdq_WO,
+    BS3CG1OP_VqHi,
+    BS3CG1OP_VqHi_WO,
+    BS3CG1OP_VqZx_WO,
+    BS3CG1OP_Vx,
+    BS3CG1OP_Vx_WO,
 
     BS3CG1OP_Ib,
     BS3CG1OP_Iz,
@@ -69,10 +112,17 @@ typedef enum BS3CG1OP
     BS3CG1OP_rAX,
 
     BS3CG1OP_Ma,
-    BS3CG1OP_MbRO,
-    BS3CG1OP_MdRO,
-    BS3CG1OP_MdWO,
+    BS3CG1OP_Mb_RO,
+    BS3CG1OP_Md,
+    BS3CG1OP_Md_RO,
+    BS3CG1OP_Md_WO,
+    BS3CG1OP_Mdq,
+    BS3CG1OP_Mdq_WO,
     BS3CG1OP_Mq,
+    BS3CG1OP_Mq_WO,
+    BS3CG1OP_Mps_WO,
+    BS3CG1OP_Mpd_WO,
+    BS3CG1OP_Mx_WO,
 
     BS3CG1OP_END
 } BS3CG1OP;
@@ -92,31 +142,86 @@ typedef enum BS3CG1ENC
 
     BS3CG1ENC_MODRM_Eb_Gb,
     BS3CG1ENC_MODRM_Ev_Gv,
-    BS3CG1ENC_MODRM_Wss_Vss,
-    BS3CG1ENC_MODRM_Wsd_Vsd,
-    BS3CG1ENC_MODRM_Wps_Vps,
-    BS3CG1ENC_MODRM_Wpd_Vpd,
-    BS3CG1ENC_MODRM_WqZxReg_Vq,
+    BS3CG1ENC_MODRM_Ed_WO_Pd_WZ,
+    BS3CG1ENC_MODRM_Eq_WO_Pq_WNZ,
+    BS3CG1ENC_MODRM_Ed_WO_Vd_WZ,
+    BS3CG1ENC_MODRM_Eq_WO_Vq_WNZ,
+    BS3CG1ENC_MODRM_Pq_WO_Qq,
+    BS3CG1ENC_MODRM_Wss_WO_Vss,
+    BS3CG1ENC_MODRM_Wsd_WO_Vsd,
+    BS3CG1ENC_MODRM_Wps_WO_Vps,
+    BS3CG1ENC_MODRM_Wpd_WO_Vpd,
+    BS3CG1ENC_MODRM_WqZxReg_WO_Vq,
 
     BS3CG1ENC_MODRM_Gb_Eb,
     BS3CG1ENC_MODRM_Gv_Ev,
-    BS3CG1ENC_MODRM_Gv_Ma, /**< bound instruction */
-    BS3CG1ENC_MODRM_Vq_UqHi,
-    BS3CG1ENC_MODRM_Vq_Mq,
-    BS3CG1ENC_MODRM_Vdq_Wdq,
-    BS3CG1ENC_MODRM_VssZxReg_Wss,
-    BS3CG1ENC_MODRM_MbRO,
-    BS3CG1ENC_MODRM_MdRO,
-    BS3CG1ENC_MODRM_MdWO,
-
-    BS3CG1ENC_VEX_MODRM_MdWO,
+    BS3CG1ENC_MODRM_Gv_RO_Ma, /**< bound instruction */
+    BS3CG1ENC_MODRM_Pq_WO_Uq,
+    BS3CG1ENC_MODRM_PdZx_WO_Ed_WZ,
+    BS3CG1ENC_MODRM_Pq_WO_Eq_WNZ,
+    BS3CG1ENC_MODRM_VdZx_WO_Ed_WZ,
+    BS3CG1ENC_MODRM_Vq_WO_UqHi,
+    BS3CG1ENC_MODRM_Vq_WO_Mq,
+    BS3CG1ENC_MODRM_VqHi_WO_Uq,
+    BS3CG1ENC_MODRM_VqHi_WO_Mq,
+    BS3CG1ENC_MODRM_VqZx_WO_Eq_WNZ,
+    BS3CG1ENC_MODRM_Vdq_WO_Mdq,
+    BS3CG1ENC_MODRM_Vdq_WO_Wdq,
+    BS3CG1ENC_MODRM_Vpd_WO_Wpd,
+    BS3CG1ENC_MODRM_Vps_WO_Wps,
+    BS3CG1ENC_MODRM_VssZx_WO_Wss,
+    BS3CG1ENC_MODRM_VsdZx_WO_Wsd,
+    BS3CG1ENC_MODRM_VqZx_WO_Wq,
+    BS3CG1ENC_MODRM_VqZx_WO_Nq,
+    BS3CG1ENC_MODRM_Mb_RO,
+    BS3CG1ENC_MODRM_Md_RO,
+    BS3CG1ENC_MODRM_Md_WO,
+    BS3CG1ENC_MODRM_Mdq_WO_Vdq,
+    BS3CG1ENC_MODRM_Mq_WO_Pq,
+    BS3CG1ENC_MODRM_Mq_WO_Vq,
+    BS3CG1ENC_MODRM_Mq_WO_VqHi,
+    BS3CG1ENC_MODRM_Mps_WO_Vps,
+    BS3CG1ENC_MODRM_Mpd_WO_Vpd,
+
+    BS3CG1ENC_VEX_MODRM_Vd_WO_Ed_WZ,
+    BS3CG1ENC_VEX_MODRM_Vps_WO_Wps,
+    BS3CG1ENC_VEX_MODRM_Vpd_WO_Wpd,
+    BS3CG1ENC_VEX_MODRM_Vss_WO_HssHi_Uss,
+    BS3CG1ENC_VEX_MODRM_Vsd_WO_HsdHi_Usd,
+    BS3CG1ENC_VEX_MODRM_Vq_WO_Eq_WNZ,
+    BS3CG1ENC_VEX_MODRM_Vq_WO_HqHi_UqHi,
+    BS3CG1ENC_VEX_MODRM_Vq_WO_HqHi_Mq,
+    BS3CG1ENC_VEX_MODRM_Vq_WO_Wq,
+    BS3CG1ENC_VEX_MODRM_VssZx_WO_Md,
+    BS3CG1ENC_VEX_MODRM_VsdZx_WO_Mq,
+    BS3CG1ENC_VEX_MODRM_Vx_WO_Wx,
+    BS3CG1ENC_VEX_MODRM_Ed_WO_Vd_WZ,
+    BS3CG1ENC_VEX_MODRM_Eq_WO_Vq_WNZ,
+    BS3CG1ENC_VEX_MODRM_Md_WO,
+    BS3CG1ENC_VEX_MODRM_Mq_WO_Vq,
+    BS3CG1ENC_VEX_MODRM_Md_WO_Vss,
+    BS3CG1ENC_VEX_MODRM_Mq_WO_Vsd,
+    BS3CG1ENC_VEX_MODRM_Mps_WO_Vps,
+    BS3CG1ENC_VEX_MODRM_Mpd_WO_Vpd,
+    BS3CG1ENC_VEX_MODRM_Mx_WO_Vx,
+    BS3CG1ENC_VEX_MODRM_Uss_WO_HssHi_Vss,
+    BS3CG1ENC_VEX_MODRM_Usd_WO_HsdHi_Vsd,
+    BS3CG1ENC_VEX_MODRM_Wps_WO_Vps,
+    BS3CG1ENC_VEX_MODRM_Wpd_WO_Vpd,
+    BS3CG1ENC_VEX_MODRM_Wq_WO_Vq,
+    BS3CG1ENC_VEX_MODRM_Wx_WO_Vx,
 
     BS3CG1ENC_FIXED,
     BS3CG1ENC_FIXED_AL_Ib,
     BS3CG1ENC_FIXED_rAX_Iz,
 
+
     BS3CG1ENC_MODRM_MOD_EQ_3, /**< Unused or invalid instruction. */
     BS3CG1ENC_MODRM_MOD_NE_3, /**< Unused or invalid instruction. */
+    //BS3CG1ENC_VEX_FIXED,          /**< Unused or invalid instruction. */
+    BS3CG1ENC_VEX_MODRM_MOD_EQ_3, /**< Unused or invalid instruction. */
+    BS3CG1ENC_VEX_MODRM_MOD_NE_3, /**< Unused or invalid instruction. */
+    BS3CG1ENC_VEX_MODRM,          /**< Unused or invalid instruction. */
 
     BS3CG1ENC_END
 } BS3CG1ENC;
@@ -154,9 +259,11 @@ typedef enum BS3CG1CPU
     BS3CG1CPU_GE_80486,
     BS3CG1CPU_GE_Pentium,
 
+    BS3CG1CPU_MMX,
     BS3CG1CPU_SSE,
     BS3CG1CPU_SSE2,
     BS3CG1CPU_SSE3,
+    BS3CG1CPU_SSE4_1,
     BS3CG1CPU_AVX,
     BS3CG1CPU_AVX2,
     BS3CG1CPU_CLFSH,
@@ -179,8 +286,10 @@ typedef enum BS3CG1XCPTTYPE
     BS3CG1XCPTTYPE_4,
     BS3CG1XCPTTYPE_4UA,
     BS3CG1XCPTTYPE_5,
+    BS3CG1XCPTTYPE_5LZ,
     BS3CG1XCPTTYPE_6,
     BS3CG1XCPTTYPE_7,
+    BS3CG1XCPTTYPE_7LZ,
     BS3CG1XCPTTYPE_8,
     BS3CG1XCPTTYPE_11,
     BS3CG1XCPTTYPE_12,
@@ -254,6 +363,8 @@ typedef BS3CG1INSTR const BS3_FAR *PCBS3CG1INSTR;
 /** Only intel does full ModR/M(, ++) decoding for invalid instruction.
  * Always used with BS3CG1INSTR_F_INVALID or BS3CG1INSTR_F_UNUSED. */
 #define BS3CG1INSTR_F_INTEL_DECODES_INVALID UINT32_C(0x00000010)
+/** VEX.L must be zero (IEMOPHINT_VEX_L_ZERO). */
+#define BS3CG1INSTR_F_VEX_L_ZERO            UINT32_C(0x00000020)
 /** @} */
 
 
@@ -452,6 +563,14 @@ typedef enum BS3CG1DST
     BS3CG1DST_MM5,
     BS3CG1DST_MM6,
     BS3CG1DST_MM7,
+    BS3CG1DST_MM0_LO_ZX,
+    BS3CG1DST_MM1_LO_ZX,
+    BS3CG1DST_MM2_LO_ZX,
+    BS3CG1DST_MM3_LO_ZX,
+    BS3CG1DST_MM4_LO_ZX,
+    BS3CG1DST_MM5_LO_ZX,
+    BS3CG1DST_MM6_LO_ZX,
+    BS3CG1DST_MM7_LO_ZX,
     /* SSE registers. */
     BS3CG1DST_XMM0,
     BS3CG1DST_XMM1,
@@ -549,6 +668,22 @@ typedef enum BS3CG1DST
     BS3CG1DST_XMM13_DW0_ZX,
     BS3CG1DST_XMM14_DW0_ZX,
     BS3CG1DST_XMM15_DW0_ZX,
+    BS3CG1DST_XMM0_HI96,
+    BS3CG1DST_XMM1_HI96,
+    BS3CG1DST_XMM2_HI96,
+    BS3CG1DST_XMM3_HI96,
+    BS3CG1DST_XMM4_HI96,
+    BS3CG1DST_XMM5_HI96,
+    BS3CG1DST_XMM6_HI96,
+    BS3CG1DST_XMM7_HI96,
+    BS3CG1DST_XMM8_HI96,
+    BS3CG1DST_XMM9_HI96,
+    BS3CG1DST_XMM10_HI96,
+    BS3CG1DST_XMM11_HI96,
+    BS3CG1DST_XMM12_HI96,
+    BS3CG1DST_XMM13_HI96,
+    BS3CG1DST_XMM14_HI96,
+    BS3CG1DST_XMM15_HI96,
     /* AVX registers. */
     BS3CG1DST_YMM0,
     BS3CG1DST_YMM1,
@@ -601,6 +736,9 @@ typedef enum BS3CG1PRED
     BS3CG1PRED_SIZE_O16,
     BS3CG1PRED_SIZE_O32,
     BS3CG1PRED_SIZE_O64,
+    /* VEX.L values. */
+    BS3CG1PRED_VEXL_0,
+    BS3CG1PRED_VEXL_1,
     /* Execution ring. */
     BS3CG1PRED_RING_0,
     BS3CG1PRED_RING_1,
diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-EnteredMode.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-EnteredMode.asm
index 6a16ec9..3b541fe 100644
--- a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-EnteredMode.asm
+++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-EnteredMode.asm
@@ -4,7 +4,7 @@
 ;
 
 ;
-; Copyright (C) 2007-2016 Oracle Corporation
+; 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;
@@ -43,9 +43,10 @@ BS3_PROC_BEGIN_MODE Bs3EnteredMode, BS3_PBC_NEAR ; won't need this outside the s
         push    xBP
         mov     xBP, xSP
         push    xAX
+        push    xCX
+        push    xDX
+TONLY16 push    xBX
 %if BS3_MODE_IS_64BIT_CODE(TMPL_MODE)
-        push    rcx
-        push    rdx
         push    r8
         push    r9
 %endif
@@ -251,9 +252,10 @@ BS3_PROC_BEGIN_MODE Bs3EnteredMode, BS3_PBC_NEAR ; won't need this outside the s
 %if TMPL_BITS == 64
         pop     r9
         pop     r8
-        pop     rdx
-        pop     rcx
 %endif
+TONLY16 pop     xBX
+        pop     xDX
+        pop     xCX
         pop     xAX
 %ifdef BS3_STRICT
         cmp     xBP, xSP
diff --git a/src/VBox/ValidationKit/common/__init__.py b/src/VBox/ValidationKit/common/__init__.py
old mode 100755
new mode 100644
diff --git a/src/VBox/ValidationKit/common/constants/__init__.py b/src/VBox/ValidationKit/common/constants/__init__.py
old mode 100755
new mode 100644
diff --git a/src/VBox/ValidationKit/common/utils.py b/src/VBox/ValidationKit/common/utils.py
old mode 100755
new mode 100644
diff --git a/src/VBox/ValidationKit/common/webutils.py b/src/VBox/ValidationKit/common/webutils.py
old mode 100755
new mode 100644
diff --git a/src/VBox/ValidationKit/testanalysis/diff.py b/src/VBox/ValidationKit/testanalysis/diff.py
old mode 100755
new mode 100644
diff --git a/src/VBox/ValidationKit/testanalysis/reader.py b/src/VBox/ValidationKit/testanalysis/reader.py
old mode 100755
new mode 100644
diff --git a/src/VBox/ValidationKit/testanalysis/reporting.py b/src/VBox/ValidationKit/testanalysis/reporting.py
old mode 100755
new mode 100644
diff --git a/src/VBox/ValidationKit/testboxscript/testboxcommand.py b/src/VBox/ValidationKit/testboxscript/testboxcommand.py
old mode 100755
new mode 100644
diff --git a/src/VBox/ValidationKit/testboxscript/testboxcommons.py b/src/VBox/ValidationKit/testboxscript/testboxcommons.py
old mode 100755
new mode 100644
diff --git a/src/VBox/ValidationKit/testboxscript/testboxconnection.py b/src/VBox/ValidationKit/testboxscript/testboxconnection.py
old mode 100755
new mode 100644
diff --git a/src/VBox/ValidationKit/testboxscript/testboxtasks.py b/src/VBox/ValidationKit/testboxscript/testboxtasks.py
old mode 100755
new mode 100644
diff --git a/src/VBox/ValidationKit/testboxscript/testboxupgrade.py b/src/VBox/ValidationKit/testboxscript/testboxupgrade.py
old mode 100755
new mode 100644
diff --git a/src/VBox/ValidationKit/testdriver/base.py b/src/VBox/ValidationKit/testdriver/base.py
old mode 100755
new mode 100644
diff --git a/src/VBox/ValidationKit/testdriver/reporter.py b/src/VBox/ValidationKit/testdriver/reporter.py
old mode 100755
new mode 100644
diff --git a/src/VBox/ValidationKit/testdriver/tst-txsclient.py b/src/VBox/ValidationKit/testdriver/tst-txsclient.py
old mode 100755
new mode 100644
diff --git a/src/VBox/ValidationKit/testdriver/txsclient.py b/src/VBox/ValidationKit/testdriver/txsclient.py
old mode 100755
new mode 100644
diff --git a/src/VBox/ValidationKit/testdriver/vbox.py b/src/VBox/ValidationKit/testdriver/vbox.py
old mode 100755
new mode 100644
diff --git a/src/VBox/ValidationKit/testdriver/vboxcon.py b/src/VBox/ValidationKit/testdriver/vboxcon.py
old mode 100755
new mode 100644
diff --git a/src/VBox/ValidationKit/testdriver/vboxtestvms.py b/src/VBox/ValidationKit/testdriver/vboxtestvms.py
old mode 100755
new mode 100644
diff --git a/src/VBox/ValidationKit/testdriver/vboxwrappers.py b/src/VBox/ValidationKit/testdriver/vboxwrappers.py
old mode 100755
new mode 100644
diff --git a/src/VBox/ValidationKit/testdriver/winbase.py b/src/VBox/ValidationKit/testdriver/winbase.py
old mode 100755
new mode 100644
diff --git a/src/VBox/ValidationKit/testmanager/core/base.py b/src/VBox/ValidationKit/testmanager/core/base.py
old mode 100755
new mode 100644
diff --git a/src/VBox/ValidationKit/testmanager/core/build.py b/src/VBox/ValidationKit/testmanager/core/build.py
old mode 100755
new mode 100644
diff --git a/src/VBox/ValidationKit/testmanager/core/buildblacklist.py b/src/VBox/ValidationKit/testmanager/core/buildblacklist.py
old mode 100755
new mode 100644
diff --git a/src/VBox/ValidationKit/testmanager/core/buildsource.py b/src/VBox/ValidationKit/testmanager/core/buildsource.py
old mode 100755
new mode 100644
diff --git a/src/VBox/ValidationKit/testmanager/core/db.py b/src/VBox/ValidationKit/testmanager/core/db.py
old mode 100755
new mode 100644
diff --git a/src/VBox/ValidationKit/testmanager/core/dbobjcache.py b/src/VBox/ValidationKit/testmanager/core/dbobjcache.py
old mode 100755
new mode 100644
diff --git a/src/VBox/ValidationKit/testmanager/core/failurecategory.py b/src/VBox/ValidationKit/testmanager/core/failurecategory.py
old mode 100755
new mode 100644
diff --git a/src/VBox/ValidationKit/testmanager/core/failurereason.py b/src/VBox/ValidationKit/testmanager/core/failurereason.py
old mode 100755
new mode 100644
diff --git a/src/VBox/ValidationKit/testmanager/core/globalresource.py b/src/VBox/ValidationKit/testmanager/core/globalresource.py
old mode 100755
new mode 100644
diff --git a/src/VBox/ValidationKit/testmanager/core/report.py b/src/VBox/ValidationKit/testmanager/core/report.py
old mode 100755
new mode 100644
diff --git a/src/VBox/ValidationKit/testmanager/core/schedgroup.py b/src/VBox/ValidationKit/testmanager/core/schedgroup.py
old mode 100755
new mode 100644
diff --git a/src/VBox/ValidationKit/testmanager/core/schedulerbase.py b/src/VBox/ValidationKit/testmanager/core/schedulerbase.py
old mode 100755
new mode 100644
diff --git a/src/VBox/ValidationKit/testmanager/core/schedulerbeci.py b/src/VBox/ValidationKit/testmanager/core/schedulerbeci.py
old mode 100755
new mode 100644
diff --git a/src/VBox/ValidationKit/testmanager/core/systemlog.py b/src/VBox/ValidationKit/testmanager/core/systemlog.py
old mode 100755
new mode 100644
diff --git a/src/VBox/ValidationKit/testmanager/core/testbox.py b/src/VBox/ValidationKit/testmanager/core/testbox.py
old mode 100755
new mode 100644
diff --git a/src/VBox/ValidationKit/testmanager/core/testboxcontroller.py b/src/VBox/ValidationKit/testmanager/core/testboxcontroller.py
old mode 100755
new mode 100644
diff --git a/src/VBox/ValidationKit/testmanager/core/testboxstatus.py b/src/VBox/ValidationKit/testmanager/core/testboxstatus.py
old mode 100755
new mode 100644
diff --git a/src/VBox/ValidationKit/testmanager/core/testcase.py b/src/VBox/ValidationKit/testmanager/core/testcase.py
old mode 100755
new mode 100644
diff --git a/src/VBox/ValidationKit/testmanager/core/testcaseargs.py b/src/VBox/ValidationKit/testmanager/core/testcaseargs.py
old mode 100755
new mode 100644
diff --git a/src/VBox/ValidationKit/testmanager/core/testgroup.py b/src/VBox/ValidationKit/testmanager/core/testgroup.py
old mode 100755
new mode 100644
diff --git a/src/VBox/ValidationKit/testmanager/core/testresultfailures.py b/src/VBox/ValidationKit/testmanager/core/testresultfailures.py
old mode 100755
new mode 100644
diff --git a/src/VBox/ValidationKit/testmanager/core/testresults.py b/src/VBox/ValidationKit/testmanager/core/testresults.py
old mode 100755
new mode 100644
diff --git a/src/VBox/ValidationKit/testmanager/core/testset.py b/src/VBox/ValidationKit/testmanager/core/testset.py
old mode 100755
new mode 100644
diff --git a/src/VBox/ValidationKit/testmanager/core/useraccount.py b/src/VBox/ValidationKit/testmanager/core/useraccount.py
old mode 100755
new mode 100644
diff --git a/src/VBox/ValidationKit/testmanager/core/vcsrevisions.py b/src/VBox/ValidationKit/testmanager/core/vcsrevisions.py
old mode 100755
new mode 100644
diff --git a/src/VBox/ValidationKit/testmanager/core/webservergluebase.py b/src/VBox/ValidationKit/testmanager/core/webservergluebase.py
old mode 100755
new mode 100644
diff --git a/src/VBox/ValidationKit/testmanager/core/webservergluecgi.py b/src/VBox/ValidationKit/testmanager/core/webservergluecgi.py
old mode 100755
new mode 100644
diff --git a/src/VBox/ValidationKit/testmanager/webui/wuiadmin.py b/src/VBox/ValidationKit/testmanager/webui/wuiadmin.py
old mode 100755
new mode 100644
diff --git a/src/VBox/ValidationKit/testmanager/webui/wuiadminbuild.py b/src/VBox/ValidationKit/testmanager/webui/wuiadminbuild.py
old mode 100755
new mode 100644
diff --git a/src/VBox/ValidationKit/testmanager/webui/wuiadminbuildblacklist.py b/src/VBox/ValidationKit/testmanager/webui/wuiadminbuildblacklist.py
old mode 100755
new mode 100644
diff --git a/src/VBox/ValidationKit/testmanager/webui/wuiadminbuildcategory.py b/src/VBox/ValidationKit/testmanager/webui/wuiadminbuildcategory.py
old mode 100755
new mode 100644
diff --git a/src/VBox/ValidationKit/testmanager/webui/wuiadminbuildsource.py b/src/VBox/ValidationKit/testmanager/webui/wuiadminbuildsource.py
old mode 100755
new mode 100644
diff --git a/src/VBox/ValidationKit/testmanager/webui/wuiadminfailurecategory.py b/src/VBox/ValidationKit/testmanager/webui/wuiadminfailurecategory.py
old mode 100755
new mode 100644
diff --git a/src/VBox/ValidationKit/testmanager/webui/wuiadminfailurereason.py b/src/VBox/ValidationKit/testmanager/webui/wuiadminfailurereason.py
old mode 100755
new mode 100644
diff --git a/src/VBox/ValidationKit/testmanager/webui/wuiadminglobalrsrc.py b/src/VBox/ValidationKit/testmanager/webui/wuiadminglobalrsrc.py
old mode 100755
new mode 100644
diff --git a/src/VBox/ValidationKit/testmanager/webui/wuiadminschedgroup.py b/src/VBox/ValidationKit/testmanager/webui/wuiadminschedgroup.py
old mode 100755
new mode 100644
diff --git a/src/VBox/ValidationKit/testmanager/webui/wuiadminsystemlog.py b/src/VBox/ValidationKit/testmanager/webui/wuiadminsystemlog.py
old mode 100755
new mode 100644
diff --git a/src/VBox/ValidationKit/testmanager/webui/wuiadmintestbox.py b/src/VBox/ValidationKit/testmanager/webui/wuiadmintestbox.py
old mode 100755
new mode 100644
diff --git a/src/VBox/ValidationKit/testmanager/webui/wuiadmintestcase.py b/src/VBox/ValidationKit/testmanager/webui/wuiadmintestcase.py
old mode 100755
new mode 100644
diff --git a/src/VBox/ValidationKit/testmanager/webui/wuiadmintestgroup.py b/src/VBox/ValidationKit/testmanager/webui/wuiadmintestgroup.py
old mode 100755
new mode 100644
diff --git a/src/VBox/ValidationKit/testmanager/webui/wuiadminuseraccount.py b/src/VBox/ValidationKit/testmanager/webui/wuiadminuseraccount.py
old mode 100755
new mode 100644
diff --git a/src/VBox/ValidationKit/testmanager/webui/wuibase.py b/src/VBox/ValidationKit/testmanager/webui/wuibase.py
old mode 100755
new mode 100644
diff --git a/src/VBox/ValidationKit/testmanager/webui/wuicontentbase.py b/src/VBox/ValidationKit/testmanager/webui/wuicontentbase.py
old mode 100755
new mode 100644
diff --git a/src/VBox/ValidationKit/testmanager/webui/wuigraphwiz.py b/src/VBox/ValidationKit/testmanager/webui/wuigraphwiz.py
old mode 100755
new mode 100644
diff --git a/src/VBox/ValidationKit/testmanager/webui/wuihlpform.py b/src/VBox/ValidationKit/testmanager/webui/wuihlpform.py
old mode 100755
new mode 100644
diff --git a/src/VBox/ValidationKit/testmanager/webui/wuihlpgraph.py b/src/VBox/ValidationKit/testmanager/webui/wuihlpgraph.py
old mode 100755
new mode 100644
diff --git a/src/VBox/ValidationKit/testmanager/webui/wuihlpgraphbase.py b/src/VBox/ValidationKit/testmanager/webui/wuihlpgraphbase.py
old mode 100755
new mode 100644
diff --git a/src/VBox/ValidationKit/testmanager/webui/wuihlpgraphgooglechart.py b/src/VBox/ValidationKit/testmanager/webui/wuihlpgraphgooglechart.py
old mode 100755
new mode 100644
diff --git a/src/VBox/ValidationKit/testmanager/webui/wuihlpgraphmatplotlib.py b/src/VBox/ValidationKit/testmanager/webui/wuihlpgraphmatplotlib.py
old mode 100755
new mode 100644
diff --git a/src/VBox/ValidationKit/testmanager/webui/wuihlpgraphsimple.py b/src/VBox/ValidationKit/testmanager/webui/wuihlpgraphsimple.py
old mode 100755
new mode 100644
diff --git a/src/VBox/ValidationKit/testmanager/webui/wuilogviewer.py b/src/VBox/ValidationKit/testmanager/webui/wuilogviewer.py
old mode 100755
new mode 100644
diff --git a/src/VBox/ValidationKit/testmanager/webui/wuimain.py b/src/VBox/ValidationKit/testmanager/webui/wuimain.py
old mode 100755
new mode 100644
diff --git a/src/VBox/ValidationKit/testmanager/webui/wuireport.py b/src/VBox/ValidationKit/testmanager/webui/wuireport.py
old mode 100755
new mode 100644
diff --git a/src/VBox/ValidationKit/testmanager/webui/wuitestresult.py b/src/VBox/ValidationKit/testmanager/webui/wuitestresult.py
old mode 100755
new mode 100644
diff --git a/src/VBox/ValidationKit/testmanager/webui/wuitestresultfailure.py b/src/VBox/ValidationKit/testmanager/webui/wuitestresultfailure.py
old mode 100755
new mode 100644
diff --git a/src/VBox/ValidationKit/testmanager/webui/wuivcshistory.py b/src/VBox/ValidationKit/testmanager/webui/wuivcshistory.py
old mode 100755
new mode 100644
diff --git a/src/VBox/ValidationKit/tests/storage/remoteexecutor.py b/src/VBox/ValidationKit/tests/storage/remoteexecutor.py
old mode 100755
new mode 100644
diff --git a/src/VBox/ValidationKit/tests/storage/storagecfg.py b/src/VBox/ValidationKit/tests/storage/storagecfg.py
old mode 100755
new mode 100644
diff --git a/src/VBox/ValidationKit/tests/usb/tst-utsgadget.py b/src/VBox/ValidationKit/tests/usb/tst-utsgadget.py
old mode 100755
new mode 100644
diff --git a/src/VBox/ValidationKit/tests/usb/usbgadget.py b/src/VBox/ValidationKit/tests/usb/usbgadget.py
old mode 100755
new mode 100644
diff --git a/src/libs/Makefile.kmk b/src/libs/Makefile.kmk
index 0eca838..ac7eea0 100644
--- a/src/libs/Makefile.kmk
+++ b/src/libs/Makefile.kmk
@@ -59,7 +59,7 @@ endif
 if  !defined(VBOX_ONLY_SDK) \
  && (   "$(SDK_VBOX_OPENSSL_INCS)" == "$(SDK_VBOX_OPENSSL_VBOX_DEFAULT_INCS)" \
      || defined(VBOX_WITH_EXTPACK_PUEL_BUILD))
- include $(PATH_SUB_CURRENT)/openssl-1.1.0e/Makefile.kmk
+ include $(PATH_SUB_CURRENT)/openssl-1.1.0f/Makefile.kmk
 endif
 
 # libjpeg for VRDP video redirection and ExtPack's DrvHostWebcam
diff --git a/src/libs/xpcom18a4/nsprpub/Makefile.in b/src/libs/xpcom18a4/nsprpub/Makefile.in
old mode 100644
new mode 100755
diff --git a/src/libs/xpcom18a4/nsprpub/config/config.mk b/src/libs/xpcom18a4/nsprpub/config/config.mk
old mode 100644
new mode 100755
diff --git a/src/libs/xpcom18a4/nsprpub/config/rules.mk b/src/libs/xpcom18a4/nsprpub/config/rules.mk
old mode 100644
new mode 100755
diff --git a/src/libs/xpcom18a4/python/Makefile.kmk b/src/libs/xpcom18a4/python/Makefile.kmk
index 298b279..086a274 100644
--- a/src/libs/xpcom18a4/python/Makefile.kmk
+++ b/src/libs/xpcom18a4/python/Makefile.kmk
@@ -26,7 +26,7 @@ endif
 
 #
 # List of supported Python versions, defining a number of
-# VBOX_PYTHON[26|27|31|32|32M|33|33M|34|34M|35|35M|DEF]_[INC|LIB] variables
+# VBOX_PYTHON[26|27|31|32|32M|33|33M|34|34M|35|35M|36|36M|37|37M|DEF]_[INC|LIB] variables
 # which get picked up below.
 #
 ifeq ($(KBUILD_TARGET),darwin) # Relatively predictable, don't script.
@@ -386,6 +386,98 @@ VBoxPython3_5m_x86_LIBS       = $(VBOX_PYTHON35M_LIB_X86)
  endif
 endif
 
+ifdef VBOX_PYTHON36_INC
+#
+# Python 3.6 version
+#
+DLLS += VBoxPython3_6
+VBoxPython3_6_EXTENDS    = VBoxPythonBase
+VBoxPython3_6_EXTENDS_BY = appending
+VBoxPython3_6_TEMPLATE   = XPCOM
+VBoxPython3_6_INCS       = $(VBOX_PYTHON36_INC)
+VBoxPython3_6_LIBS       = $(VBOX_PYTHON36_LIB)
+
+ ifdef VBOX_WITH_32_ON_64_MAIN_API
+  ifdef VBOX_PYTHON36_LIB_X86
+DLLS += VBoxPython3_6_x86
+VBoxPython3_6_x86_EXTENDS    = VBoxPythonBase_x86
+VBoxPython3_6_x86_EXTENDS_BY = appending
+VBoxPython3_6_x86_TEMPLATE   = XPCOM
+VBoxPython3_6_x86_INCS       = $(VBOX_PYTHON36_INC)
+VBoxPython3_6_x86_LIBS       = $(VBOX_PYTHON36_LIB_X86)
+  endif
+ endif
+endif
+
+ifdef VBOX_PYTHON36M_INC
+#
+# Python 3.6 version with pymalloc
+#
+DLLS += VBoxPython3_6m
+VBoxPython3_6m_EXTENDS    = VBoxPythonBase
+VBoxPython3_6m_EXTENDS_BY = appending
+VBoxPython3_6m_TEMPLATE   = XPCOM
+VBoxPython3_6m_INCS       = $(VBOX_PYTHON36M_INC)
+VBoxPython3_6m_LIBS       = $(VBOX_PYTHON36M_LIB)
+
+ ifdef VBOX_WITH_32_ON_64_MAIN_API
+  ifdef VBOX_PYTHON36M_LIB_X86
+DLLS += VBoxPython3_6m_x86
+VBoxPython3_6m_x86_EXTENDS    = VBoxPythonBase_x86
+VBoxPython3_6m_x86_EXTENDS_BY = appending
+VBoxPython3_6m_x86_TEMPLATE   = XPCOM
+VBoxPython3_6m_x86_INCS       = $(VBOX_PYTHON36M_INC)
+VBoxPython3_6m_x86_LIBS       = $(VBOX_PYTHON36M_LIB_X86)
+  endif
+ endif
+endif
+
+ifdef VBOX_PYTHON37_INC
+#
+# Python 3.7 version
+#
+DLLS += VBoxPython3_7
+VBoxPython3_7_EXTENDS    = VBoxPythonBase
+VBoxPython3_7_EXTENDS_BY = appending
+VBoxPython3_7_TEMPLATE   = XPCOM
+VBoxPython3_7_INCS       = $(VBOX_PYTHON37_INC)
+VBoxPython3_7_LIBS       = $(VBOX_PYTHON37_LIB)
+
+ ifdef VBOX_WITH_32_ON_64_MAIN_API
+  ifdef VBOX_PYTHON37_LIB_X86
+DLLS += VBoxPython3_7_x86
+VBoxPython3_7_x86_EXTENDS    = VBoxPythonBase_x86
+VBoxPython3_7_x86_EXTENDS_BY = appending
+VBoxPython3_7_x86_TEMPLATE   = XPCOM
+VBoxPython3_7_x86_INCS       = $(VBOX_PYTHON37_INC)
+VBoxPython3_7_x86_LIBS       = $(VBOX_PYTHON37_LIB_X86)
+  endif
+ endif
+endif
+
+ifdef VBOX_PYTHON37M_INC
+#
+# Python 3.7 version with pymalloc
+#
+DLLS += VBoxPython3_7m
+VBoxPython3_7m_EXTENDS    = VBoxPythonBase
+VBoxPython3_7m_EXTENDS_BY = appending
+VBoxPython3_7m_TEMPLATE   = XPCOM
+VBoxPython3_7m_INCS       = $(VBOX_PYTHON37M_INC)
+VBoxPython3_7m_LIBS       = $(VBOX_PYTHON37M_LIB)
+
+ ifdef VBOX_WITH_32_ON_64_MAIN_API
+  ifdef VBOX_PYTHON37M_LIB_X86
+DLLS += VBoxPython3_7m_x86
+VBoxPython3_7m_x86_EXTENDS    = VBoxPythonBase_x86
+VBoxPython3_7m_x86_EXTENDS_BY = appending
+VBoxPython3_7m_x86_TEMPLATE   = XPCOM
+VBoxPython3_7m_x86_INCS       = $(VBOX_PYTHON37M_INC)
+VBoxPython3_7m_x86_LIBS       = $(VBOX_PYTHON37M_LIB_X86)
+  endif
+ endif
+endif
+
 ifdef VBOX_PYTHONDEF_INC
 #
 # Python without versioning
diff --git a/src/libs/xpcom18a4/python/__init__.py b/src/libs/xpcom18a4/python/__init__.py
old mode 100755
new mode 100644
diff --git a/src/libs/xpcom18a4/python/client/__init__.py b/src/libs/xpcom18a4/python/client/__init__.py
old mode 100755
new mode 100644
diff --git a/src/libs/xpcom18a4/python/components.py b/src/libs/xpcom18a4/python/components.py
old mode 100755
new mode 100644
diff --git a/src/libs/xpcom18a4/python/file.py b/src/libs/xpcom18a4/python/file.py
old mode 100755
new mode 100644
diff --git a/src/libs/xpcom18a4/python/gen_python_deps.py b/src/libs/xpcom18a4/python/gen_python_deps.py
index 04ec739..a125c0a 100755
--- a/src/libs/xpcom18a4/python/gen_python_deps.py
+++ b/src/libs/xpcom18a4/python/gen_python_deps.py
@@ -16,7 +16,7 @@ from __future__ import print_function
 import os,sys
 from distutils.version import StrictVersion
 
-versions = ["2.6", "2.7", "3.1", "3.2", "3.2m", "3.3", "3.3m", "3.4", "3.4m", "3.5", "3.5m"]
+versions = ["2.6", "2.7", "3.1", "3.2", "3.2m", "3.3", "3.3m", "3.4", "3.4m", "3.5", "3.5m", "3.6", "3.6m", "3.7", "3.7m"]
 prefixes = ["/usr", "/usr/local", "/opt", "/opt/local"]
 known = {}
 
diff --git a/src/libs/xpcom18a4/python/nsError.py b/src/libs/xpcom18a4/python/nsError.py
old mode 100755
new mode 100644
diff --git a/src/libs/xpcom18a4/python/primitives.py b/src/libs/xpcom18a4/python/primitives.py
old mode 100755
new mode 100644
diff --git a/src/libs/xpcom18a4/python/server/__init__.py b/src/libs/xpcom18a4/python/server/__init__.py
old mode 100755
new mode 100644
diff --git a/src/libs/xpcom18a4/python/server/enumerator.py b/src/libs/xpcom18a4/python/server/enumerator.py
old mode 100755
new mode 100644
diff --git a/src/libs/xpcom18a4/python/server/factory.py b/src/libs/xpcom18a4/python/server/factory.py
old mode 100755
new mode 100644
diff --git a/src/libs/xpcom18a4/python/server/loader.py b/src/libs/xpcom18a4/python/server/loader.py
old mode 100755
new mode 100644
diff --git a/src/libs/xpcom18a4/python/server/module.py b/src/libs/xpcom18a4/python/server/module.py
old mode 100755
new mode 100644
diff --git a/src/libs/xpcom18a4/python/server/policy.py b/src/libs/xpcom18a4/python/server/policy.py
old mode 100755
new mode 100644
diff --git a/src/libs/xpcom18a4/python/test/pyxpcom_test_tools.py b/src/libs/xpcom18a4/python/test/pyxpcom_test_tools.py
old mode 100755
new mode 100644
diff --git a/src/libs/xpcom18a4/python/test/test_com_exceptions.py b/src/libs/xpcom18a4/python/test/test_com_exceptions.py
old mode 100755
new mode 100644
diff --git a/src/libs/xpcom18a4/python/test/test_comfile.py b/src/libs/xpcom18a4/python/test/test_comfile.py
old mode 100755
new mode 100644
diff --git a/src/libs/xpcom18a4/python/test/test_component/py_test_component.py b/src/libs/xpcom18a4/python/test/test_component/py_test_component.py
old mode 100755
new mode 100644
diff --git a/src/libs/xpcom18a4/python/test/test_components.py b/src/libs/xpcom18a4/python/test/test_components.py
old mode 100755
new mode 100644
diff --git a/src/libs/xpcom18a4/python/test/test_isupports_primitives.py b/src/libs/xpcom18a4/python/test/test_isupports_primitives.py
old mode 100755
new mode 100644
diff --git a/src/libs/xpcom18a4/python/test/test_misc.py b/src/libs/xpcom18a4/python/test/test_misc.py
old mode 100755
new mode 100644
diff --git a/src/libs/xpcom18a4/python/test/test_streams.py b/src/libs/xpcom18a4/python/test/test_streams.py
old mode 100755
new mode 100644
diff --git a/src/libs/xpcom18a4/python/test/test_test_component.py b/src/libs/xpcom18a4/python/test/test_test_component.py
old mode 100755
new mode 100644
diff --git a/src/libs/xpcom18a4/python/test/test_weakreferences.py b/src/libs/xpcom18a4/python/test/test_weakreferences.py
old mode 100755
new mode 100644
diff --git a/src/libs/xpcom18a4/python/tools/regxpcom.py b/src/libs/xpcom18a4/python/tools/regxpcom.py
old mode 100755
new mode 100644
diff --git a/src/libs/xpcom18a4/python/tools/tracer_demo.py b/src/libs/xpcom18a4/python/tools/tracer_demo.py
old mode 100755
new mode 100644
diff --git a/src/libs/xpcom18a4/python/xpt.py b/src/libs/xpcom18a4/python/xpt.py
old mode 100755
new mode 100644
diff --git a/src/recompiler/Makefile.kmk b/src/recompiler/Makefile.kmk
index 4dcb5cb..6a57085 100644
--- a/src/recompiler/Makefile.kmk
+++ b/src/recompiler/Makefile.kmk
@@ -323,7 +323,8 @@ $$(VBoxREMImp_0_OUTDIR)/VBoxREMWin.def: $(VBOX_PATH_RECOMPILER_SRC)/VBoxREM.def
 
 $$(VBoxREMImp_0_OUTDIR)/VBoxREMRes.o: $(VBOX_PATH_RECOMPILER_SRC)/VBoxREM.rc $(MAKEFILE_CURRENT) $(VBOX_VERSION_MK) | $$(dir $$@)
 	$(call MSG_GENERATE,,$@)
-	$(QUIET)$(REDIRECT) -E 'COMSPEC=$(VBOX_GOOD_COMSPEC_BS)' -- $(TOOL_MINGWW64_PREFIX)windres \
+	$(QUIET)$(REDIRECT) -E 'COMSPEC=$(VBOX_GOOD_COMSPEC_BS)' \
+	    -- $(TOOL_$(VBoxRemPrimary_TOOL.win.$(KBUILD_TARGET_ARCH))_PREFIX)windres \
 	    $(addprefix -I,$(INCS) $(PATH_SDK_$(VBOX_WINPSDK)_INC) $(PATH_TOOL_$(VBOX_VCC_TOOL)_INC)) \
 	    -DVBOX_SVN_REV=$(VBOX_SVN_REV) \
 	    -DVBOX_SVN_REV_MOD_5K=$(expr $(VBOX_SVN_REV) % 50000) \

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-virtualbox/virtualbox.git



More information about the Pkg-virtualbox-commits mailing list