Index: trunk/src/VBox/VMM/VMMAll/IEMAllN8veRecompBltIn.cpp
===================================================================
--- trunk/src/VBox/VMM/VMMAll/IEMAllN8veRecompBltIn.cpp	(revision 102687)
+++ trunk/src/VBox/VMM/VMMAll/IEMAllN8veRecompBltIn.cpp	(revision 102695)
@@ -31,5 +31,5 @@
 *********************************************************************************************************************************/
 #define LOG_GROUP LOG_GROUP_IEM_RE_NATIVE
-#define IEM_WITH_OPAQUE_DECODER_STATE
+//#define IEM_WITH_OPAQUE_DECODER_STATE - need offCurInstrStart access for iemNativeHlpMemCodeNewPageTlbMiss and friends.
 #define VMCPU_INCL_CPUM_GST_CTX
 #define VMM_INCLUDED_SRC_include_IEMMc_h /* block IEMMc.h inclusion. */
@@ -65,4 +65,16 @@
 #endif
 
+
+/**
+ * Used by TB code to deal with a TLB miss for a new page.
+ */
+IEM_DECL_NATIVE_HLP_DEF(RTGCPHYS, iemNativeHlpMemCodeNewPageTlbMiss,(PVMCPUCC pVCpu, uint8_t offInstr))
+{
+    pVCpu->iem.s.pbInstrBuf       = NULL;
+    pVCpu->iem.s.offCurInstrStart = GUEST_PAGE_SIZE - offInstr;
+    pVCpu->iem.s.offInstrNextByte = GUEST_PAGE_SIZE;
+    iemOpcodeFetchBytesJmp(pVCpu, 0, NULL);
+    return pVCpu->iem.s.pbInstrBuf ? pVCpu->iem.s.GCPhysInstrBuf : NIL_RTGCPHYS;
+}
 
 
@@ -247,5 +259,5 @@
 
 /**
- * Sets idxTbCurInstr in preparation of raising an exception.
+ * Sets idxTbCurInstr in preparation of raising an exception or aborting the TB.
  */
 /** @todo Optimize this, so we don't set the same value more than once.  Just
@@ -257,4 +269,10 @@
 # define BODY_SET_CUR_INSTR() ((void)0)
 #endif
+
+/**
+ * Flushes pending writes in preparation of raising an exception or aborting the TB.
+ */
+#define BODY_FLUSH_PENDING_WRITES() \
+    off = iemNativeRegFlushPendingWrites(pReNative, off);
 
 
@@ -1131,4 +1149,74 @@
 
 
+/**
+ * Macro that implements TLB loading and updating pbInstrBuf updating for an
+ * instruction crossing into a new page.
+ *
+ * This may long jump if we're raising a \#PF, \#GP or similar trouble.
+ */
+#define BODY_LOAD_TLB_FOR_NEW_PAGE(a_pTb, a_offInstr, a_idxRange, a_cbInstr) \
+    RT_NOREF(a_cbInstr); \
+    off = iemNativeEmitBltLoadTlbForNewPage(pReNative, off, pTb, a_idxRange, a_offInstr)
+
+DECL_FORCE_INLINE(uint32_t)
+iemNativeEmitBltLoadTlbForNewPage(PIEMRECOMPILERSTATE pReNative, uint32_t off, PCIEMTB pTb, uint8_t idxRange, uint8_t offInstr)
+{
+#ifdef VBOX_STRICT
+    off = iemNativeEmitMarker(pReNative, off, 0x80000005);
+#endif
+
+    /*
+     * Move/spill/flush stuff out of call-volatile registers.
+     * This is the easy way out. We could contain this to the tlb-miss branch
+     * by saving and restoring active stuff here.
+     */
+    /** @todo save+restore active registers and maybe guest shadows in tlb-miss.  */
+    off = iemNativeRegMoveAndFreeAndFlushAtCall(pReNative, off, 0 /* vacate all non-volatile regs */);
+
+    /*
+     * Define labels and allocate the register for holding the GCPhys of the new page.
+     */
+    uint16_t const uTlbSeqNo        = pReNative->uTlbSeqNo++;
+    uint32_t const idxLabelTlbMiss  = iemNativeLabelCreate(pReNative, kIemNativeLabelType_TlbMiss, UINT32_MAX, uTlbSeqNo);
+    uint32_t const idxLabelTlbDone  = iemNativeLabelCreate(pReNative, kIemNativeLabelType_TlbDone, UINT32_MAX, uTlbSeqNo);
+    uint32_t const idxRegGCPhys     = iemNativeRegAllocTmp(pReNative, &off);
+
+    /*
+     * First we try to go via the TLB.
+     */
+    /** @todo  */
+
+    /*
+     * TLB miss: Call iemNativeHlpMemCodeNewPageTlbMiss to do the work.
+     */
+    iemNativeLabelDefine(pReNative, idxLabelTlbMiss, off);
+
+    /* IEMNATIVE_CALL_ARG1_GREG = offInstr */
+    off = iemNativeEmitLoadGpr8Imm(pReNative, off, IEMNATIVE_CALL_ARG1_GREG, offInstr);
+
+    /* IEMNATIVE_CALL_ARG0_GREG = pVCpu */
+    off = iemNativeEmitLoadGprFromGpr(pReNative, off, IEMNATIVE_CALL_ARG0_GREG, IEMNATIVE_REG_FIXED_PVMCPU);
+
+    /* Done setting up parameters, make the call. */
+    off = iemNativeEmitCallImm(pReNative, off, (uintptr_t)iemNativeHlpMemCodeNewPageTlbMiss);
+
+    /* Move the result to the right register. */
+    if (idxRegGCPhys != IEMNATIVE_CALL_RET_GREG)
+        off = iemNativeEmitLoadGprFromGpr(pReNative, off, idxRegGCPhys, IEMNATIVE_CALL_RET_GREG);
+
+    iemNativeLabelDefine(pReNative, idxLabelTlbDone, off);
+
+    /*
+     * Now check the physical address of the page matches the expected one.
+     */
+    RTGCPHYS const GCPhysNewPage = iemTbGetRangePhysPageAddr(pTb, idxRange);
+    off = iemNativeEmitTestIfGprNotEqualImmAndJmpToNewLabel(pReNative, off, idxRegGCPhys, GCPhysNewPage,
+                                                            kIemNativeLabelType_ObsoleteTb);
+
+    iemNativeRegFreeTmp(pReNative, idxRegGCPhys);
+    return off;
+}
+
+
 #ifdef BODY_CHECK_CS_LIM
 /**
@@ -1140,4 +1228,5 @@
     uint32_t const cbInstr = (uint32_t)pCallEntry->auParams[0];
     BODY_SET_CUR_INSTR();
+    BODY_FLUSH_PENDING_WRITES();
     BODY_CHECK_CS_LIM(cbInstr);
     return off;
@@ -1158,4 +1247,5 @@
     uint32_t const offRange = (uint32_t)pCallEntry->auParams[2];
     BODY_SET_CUR_INSTR();
+    BODY_FLUSH_PENDING_WRITES();
     BODY_CHECK_CS_LIM(cbInstr);
     BODY_CHECK_OPCODES(pTb, idxRange, offRange, cbInstr);
@@ -1177,4 +1267,5 @@
     uint32_t const offRange = (uint32_t)pCallEntry->auParams[2];
     BODY_SET_CUR_INSTR();
+    BODY_FLUSH_PENDING_WRITES();
     BODY_CHECK_OPCODES(pTb, idxRange, offRange, cbInstr);
     return off;
@@ -1195,4 +1286,5 @@
     uint32_t const offRange = (uint32_t)pCallEntry->auParams[2];
     BODY_SET_CUR_INSTR();
+    BODY_FLUSH_PENDING_WRITES();
     BODY_CONSIDER_CS_LIM_CHECKING(pTb, cbInstr);
     BODY_CHECK_OPCODES(pTb, idxRange, offRange, cbInstr);
@@ -1221,4 +1313,5 @@
     //LogFunc(("idxRange=%u @ %#x LB %#x: offPhysPage=%#x LB %#x\n", idxRange, offRange, cbInstr, pTb->aRanges[idxRange].offPhysPage, pTb->aRanges[idxRange].cbOpcodes));
     BODY_SET_CUR_INSTR();
+    BODY_FLUSH_PENDING_WRITES();
     BODY_CHECK_CS_LIM(cbInstr);
     BODY_CHECK_PC_AFTER_BRANCH(pTb, idxRange, offRange, cbInstr);
@@ -1245,4 +1338,5 @@
     //LogFunc(("idxRange=%u @ %#x LB %#x: offPhysPage=%#x LB %#x\n", idxRange, offRange, cbInstr, pTb->aRanges[idxRange].offPhysPage, pTb->aRanges[idxRange].cbOpcodes));
     BODY_SET_CUR_INSTR();
+    BODY_FLUSH_PENDING_WRITES();
     BODY_CHECK_PC_AFTER_BRANCH(pTb, idxRange, offRange, cbInstr);
     BODY_CHECK_OPCODES(pTb, idxRange, offRange, cbInstr);
@@ -1269,4 +1363,5 @@
     //LogFunc(("idxRange=%u @ %#x LB %#x: offPhysPage=%#x LB %#x\n", idxRange, offRange, cbInstr, pTb->aRanges[idxRange].offPhysPage, pTb->aRanges[idxRange].cbOpcodes));
     BODY_SET_CUR_INSTR();
+    BODY_FLUSH_PENDING_WRITES();
     BODY_CONSIDER_CS_LIM_CHECKING(pTb, cbInstr);
     BODY_CHECK_PC_AFTER_BRANCH(pTb, idxRange, offRange, cbInstr);
@@ -1296,4 +1391,5 @@
     //LogFunc(("idxRange=%u @ %#x LB %#x: offPhysPage=%#x LB %#x\n", idxRange, offRange, cbInstr, pTb->aRanges[idxRange].offPhysPage, pTb->aRanges[idxRange].cbOpcodes));
     BODY_SET_CUR_INSTR();
+    BODY_FLUSH_PENDING_WRITES();
     BODY_CHECK_CS_LIM(cbInstr);
     BODY_LOAD_TLB_AFTER_BRANCH(pTb, idxRange, cbInstr);
@@ -1323,4 +1419,5 @@
     //LogFunc(("idxRange=%u @ %#x LB %#x: offPhysPage=%#x LB %#x\n", idxRange, offRange, cbInstr, pTb->aRanges[idxRange].offPhysPage, pTb->aRanges[idxRange].cbOpcodes));
     BODY_SET_CUR_INSTR();
+    BODY_FLUSH_PENDING_WRITES();
     BODY_LOAD_TLB_AFTER_BRANCH(pTb, idxRange, cbInstr);
     BODY_CHECK_OPCODES(pTb, idxRange, offRange, cbInstr);
@@ -1349,4 +1446,5 @@
     //LogFunc(("idxRange=%u @ %#x LB %#x: offPhysPage=%#x LB %#x\n", idxRange, offRange, cbInstr, pTb->aRanges[idxRange].offPhysPage, pTb->aRanges[idxRange].cbOpcodes));
     BODY_SET_CUR_INSTR();
+    BODY_FLUSH_PENDING_WRITES();
     BODY_CONSIDER_CS_LIM_CHECKING(pTb, cbInstr);
     BODY_LOAD_TLB_AFTER_BRANCH(pTb, idxRange, cbInstr);
@@ -1383,4 +1481,5 @@
     uint32_t const idxRange2   = idxRange1 + 1;
     BODY_SET_CUR_INSTR();
+    BODY_FLUSH_PENDING_WRITES();
     BODY_CHECK_CS_LIM(cbInstr);
     BODY_CHECK_OPCODES(pTb, idxRange1, offRange1, cbInstr);
@@ -1412,4 +1511,5 @@
     uint32_t const idxRange2   = idxRange1 + 1;
     BODY_SET_CUR_INSTR();
+    BODY_FLUSH_PENDING_WRITES();
     BODY_CHECK_OPCODES(pTb, idxRange1, offRange1, cbInstr);
     BODY_LOAD_TLB_FOR_NEW_PAGE(pTb, cbStartPage, idxRange2, cbInstr);
@@ -1441,4 +1541,5 @@
     uint32_t const idxRange2   = idxRange1 + 1;
     BODY_SET_CUR_INSTR();
+    BODY_FLUSH_PENDING_WRITES();
     BODY_CONSIDER_CS_LIM_CHECKING(pTb, cbInstr);
     BODY_CHECK_OPCODES(pTb, idxRange1, offRange1, cbInstr);
@@ -1468,4 +1569,5 @@
     uint32_t const idxRange2   = idxRange1 + 1;
     BODY_SET_CUR_INSTR();
+    BODY_FLUSH_PENDING_WRITES();
     BODY_CHECK_CS_LIM(cbInstr);
     BODY_LOAD_TLB_FOR_NEW_PAGE(pTb, cbStartPage, idxRange2, cbInstr);
@@ -1494,4 +1596,5 @@
     uint32_t const idxRange2   = idxRange1 + 1;
     BODY_SET_CUR_INSTR();
+    BODY_FLUSH_PENDING_WRITES();
     BODY_LOAD_TLB_FOR_NEW_PAGE(pTb, cbStartPage, idxRange2, cbInstr);
     BODY_CHECK_OPCODES(pTb, idxRange2, 0, cbInstr);
@@ -1519,4 +1622,5 @@
     uint32_t const idxRange2   = idxRange1 + 1;
     BODY_SET_CUR_INSTR();
+    BODY_FLUSH_PENDING_WRITES();
     BODY_CONSIDER_CS_LIM_CHECKING(pTb, cbInstr);
     BODY_LOAD_TLB_FOR_NEW_PAGE(pTb, cbStartPage, idxRange2, cbInstr);
@@ -1540,4 +1644,5 @@
     uint32_t const idxRange    = (uint32_t)pCallEntry->auParams[1];
     BODY_SET_CUR_INSTR();
+    BODY_FLUSH_PENDING_WRITES();
     BODY_CHECK_CS_LIM(cbInstr);
     BODY_LOAD_TLB_FOR_NEW_PAGE(pTb, 0, idxRange, cbInstr);
@@ -1562,4 +1667,5 @@
     uint32_t const idxRange    = (uint32_t)pCallEntry->auParams[1];
     BODY_SET_CUR_INSTR();
+    BODY_FLUSH_PENDING_WRITES();
     BODY_LOAD_TLB_FOR_NEW_PAGE(pTb, 0, idxRange, cbInstr);
     //Assert(pVCpu->iem.s.offCurInstrStart == 0);
@@ -1584,4 +1690,5 @@
     uint32_t const idxRange    = (uint32_t)pCallEntry->auParams[1];
     BODY_SET_CUR_INSTR();
+    BODY_FLUSH_PENDING_WRITES();
     BODY_CONSIDER_CS_LIM_CHECKING(pTb, cbInstr);
     BODY_LOAD_TLB_FOR_NEW_PAGE(pTb, 0, idxRange, cbInstr);
Index: trunk/src/VBox/VMM/VMMAll/IEMAllN8veRecompiler.cpp
===================================================================
--- trunk/src/VBox/VMM/VMMAll/IEMAllN8veRecompiler.cpp	(revision 102687)
+++ trunk/src/VBox/VMM/VMMAll/IEMAllN8veRecompiler.cpp	(revision 102695)
@@ -11210,5 +11210,5 @@
     static const char * const a_apszMarkers[] =
     {
-        "unknown0", "CheckCsLim", "ConsiderLimChecking", "CheckOpcodes", "PcAfterBranch",
+        "unknown0", "CheckCsLim", "ConsiderLimChecking", "CheckOpcodes", "PcAfterBranch", "LoadTlbForNewPage"
     };
 #endif
Index: trunk/src/VBox/VMM/VMMAll/IEMAllThrdPython.py
===================================================================
--- trunk/src/VBox/VMM/VMMAll/IEMAllThrdPython.py	(revision 102687)
+++ trunk/src/VBox/VMM/VMMAll/IEMAllThrdPython.py	(revision 102695)
@@ -1977,7 +1977,7 @@
         ( 'CheckPcAndOpcodesConsiderCsLim',                     3, True  ),
 
-        ( 'CheckCsLimAndOpcodesAcrossPageLoadingTlb',           3, False ),
-        ( 'CheckOpcodesAcrossPageLoadingTlb',                   3, False ),
-        ( 'CheckOpcodesAcrossPageLoadingTlbConsiderCsLim',      2, False ),
+        ( 'CheckCsLimAndOpcodesAcrossPageLoadingTlb',           3, True  ),
+        ( 'CheckOpcodesAcrossPageLoadingTlb',                   3, True  ),
+        ( 'CheckOpcodesAcrossPageLoadingTlbConsiderCsLim',      2, True  ),
 
         ( 'CheckCsLimAndOpcodesLoadingTlb',                     3, False ),
@@ -1985,11 +1985,11 @@
         ( 'CheckOpcodesLoadingTlbConsiderCsLim',                3, False ),
 
-        ( 'CheckCsLimAndOpcodesOnNextPageLoadingTlb',           2, False ),
-        ( 'CheckOpcodesOnNextPageLoadingTlb',                   2, False ),
-        ( 'CheckOpcodesOnNextPageLoadingTlbConsiderCsLim',      2, False ),
-
-        ( 'CheckCsLimAndOpcodesOnNewPageLoadingTlb',            2, False ),
-        ( 'CheckOpcodesOnNewPageLoadingTlb',                    2, False ),
-        ( 'CheckOpcodesOnNewPageLoadingTlbConsiderCsLim',       2, False ),
+        ( 'CheckCsLimAndOpcodesOnNextPageLoadingTlb',           2, True  ),
+        ( 'CheckOpcodesOnNextPageLoadingTlb',                   2, True  ),
+        ( 'CheckOpcodesOnNextPageLoadingTlbConsiderCsLim',      2, True  ),
+
+        ( 'CheckCsLimAndOpcodesOnNewPageLoadingTlb',            2, True  ),
+        ( 'CheckOpcodesOnNewPageLoadingTlb',                    2, True  ),
+        ( 'CheckOpcodesOnNewPageLoadingTlbConsiderCsLim',       2, True  ),
     );
 
