Index: /trunk/include/iprt/armv8.h
===================================================================
--- /trunk/include/iprt/armv8.h	(revision 102509)
+++ /trunk/include/iprt/armv8.h	(revision 102510)
@@ -2656,4 +2656,12 @@
 
 
+/** A64: Encodes an MOV instruction.
+ * This is an alias for "orr dst, xzr, src".  */
+DECL_FORCE_INLINE(uint32_t) Armv8A64MkInstrMov(uint32_t iRegResult, uint32_t idxRegSrc, bool f64Bit = true)
+{
+    return Armv8A64MkInstrOrr(iRegResult, ARMV8_A64_REG_XZR, idxRegSrc, f64Bit);
+}
+
+
 /** A64: Encodes an ORN instruction.
  * @see Armv8A64MkInstrLogicalShiftedReg for parameter details.  */
Index: /trunk/src/VBox/VMM/VMMAll/IEMAllInstCommon.cpp.h
===================================================================
--- /trunk/src/VBox/VMM/VMMAll/IEMAllInstCommon.cpp.h	(revision 102509)
+++ /trunk/src/VBox/VMM/VMMAll/IEMAllInstCommon.cpp.h	(revision 102510)
@@ -1033,4 +1033,5 @@
             IEM_MC_CALC_RM_EFF_ADDR(GCPtrEff, bRm, 0);
             IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
+IEM_MC_NO_NATIVE_RECOMPILE(); /** @todo sort out the IEM_IS_GUEST_CPU_AMD stuff. */
             if (IEM_IS_GUEST_CPU_AMD(pVCpu)) /** @todo testcase: rev 3.15 of the amd manuals claims it only loads a 32-bit greg. */
                 IEM_MC_FETCH_MEM_U32_SX_U64(offSeg, pVCpu->iem.s.iEffSeg, GCPtrEff);
Index: /trunk/src/VBox/VMM/VMMAll/IEMAllN8vePython.py
===================================================================
--- /trunk/src/VBox/VMM/VMMAll/IEMAllN8vePython.py	(revision 102509)
+++ /trunk/src/VBox/VMM/VMMAll/IEMAllN8vePython.py	(revision 102510)
@@ -62,7 +62,7 @@
     'IEM_MC_CALC_RM_EFF_ADDR_THREADED_16':                       (None, False, True,  ),
     'IEM_MC_CALC_RM_EFF_ADDR_THREADED_32':                       (None, False, True,  ),
-    'IEM_MC_CALC_RM_EFF_ADDR_THREADED_64_ADDR32':                (None, False, False, ),
-    'IEM_MC_CALC_RM_EFF_ADDR_THREADED_64_FSGS':                  (None, False, False, ),
-    'IEM_MC_CALC_RM_EFF_ADDR_THREADED_64':                       (None, False, False, ),
+    'IEM_MC_CALC_RM_EFF_ADDR_THREADED_64_ADDR32':                (None, False, True,  ),
+    'IEM_MC_CALC_RM_EFF_ADDR_THREADED_64_FSGS':                  (None, False, True,  ),
+    'IEM_MC_CALC_RM_EFF_ADDR_THREADED_64':                       (None, False, True,  ),
 
     'IEM_MC_CALL_CIMPL_1_THREADED':                              (None, True,  True,  ),
Index: /trunk/src/VBox/VMM/VMMAll/IEMAllN8veRecompiler.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMAll/IEMAllN8veRecompiler.cpp	(revision 102509)
+++ /trunk/src/VBox/VMM/VMMAll/IEMAllN8veRecompiler.cpp	(revision 102510)
@@ -6,5 +6,5 @@
  *      - Level 1  (Log)  : ...
  *      - Flow  (LogFlow) : ...
- *      - Level 2  (Log2) : ...
+ *      - Level 2  (Log2) : Details calls as they're recompiled.
  *      - Level 3  (Log3) : Disassemble native code after recompiling.
  *      - Level 4  (Log4) : ...
@@ -3438,5 +3438,5 @@
                       && enmIntendedUse != kIemNativeGstRegUse_ForFullWrite,
                       ("This shouldn't happen: idxReg=%d enmGstReg=%d enmIntendedUse=%s\n",
-                       idxReg, s_pszIntendedUse[enmIntendedUse]));
+                       idxReg, enmGstReg, s_pszIntendedUse[enmIntendedUse]));
 
             /*
@@ -8729,11 +8729,334 @@
 
 #define IEM_MC_CALC_RM_EFF_ADDR_THREADED_64(a_GCPtrEff, a_bRmEx, a_uSibAndRspOffset, a_u32Disp, a_cbImm) \
-    off = iemNativeEmitCalcRmEffAddrThreadedAddr64(pReNative, off, a_bRmEx, a_uSibAndRspOffset, a_u32Disp, a_cbImm, a_GCPtrEff)
+    off = iemNativeEmitCalcRmEffAddrThreadedAddr64(pReNative, off, a_bRmEx, a_uSibAndRspOffset, \
+                                                   a_u32Disp, a_cbImm, a_GCPtrEff, true /*f64Bit*/)
 
 #define IEM_MC_CALC_RM_EFF_ADDR_THREADED_64_FSGS(a_GCPtrEff, a_bRmEx, a_uSibAndRspOffset, a_u32Disp, a_cbImm) \
-    off = iemNativeEmitCalcRmEffAddrThreadedAddr64(pReNative, off, a_bRmEx, a_uSibAndRspOffset, a_u32Disp, a_cbImm, a_GCPtrEff, 64)
+    off = iemNativeEmitCalcRmEffAddrThreadedAddr64(pReNative, off, a_bRmEx, a_uSibAndRspOffset, \
+                                                   a_u32Disp, a_cbImm, a_GCPtrEff, true /*f64Bit*/)
 
 #define IEM_MC_CALC_RM_EFF_ADDR_THREADED_64_ADDR32(a_GCPtrEff, a_bRmEx, a_uSibAndRspOffset, a_u32Disp, a_cbImm) \
-    off = iemNativeEmitCalcRmEffAddrThreadedAddr64(pReNative, off, a_bRmEx, a_uSibAndRspOffset, a_u32Disp, a_cbImm, a_GCPtrEff, 32)
+    off = iemNativeEmitCalcRmEffAddrThreadedAddr64(pReNative, off, a_bRmEx, a_uSibAndRspOffset, \
+                                                   a_u32Disp, a_cbImm, a_GCPtrEff, false /*f64Bit*/)
+
+/**
+ * Emit code for IEM_MC_CALC_RM_EFF_ADDR_THREADED_64*.
+ *
+ * @returns New off.
+ * @param   pReNative           .
+ * @param   off                 .
+ * @param   bRmEx               The ModRM byte but with bit 3 set to REX.B and
+ *                              bit 4 to REX.X.  The two bits are part of the
+ *                              REG sub-field, which isn't needed in this
+ *                              function.
+ * @param   uSibAndRspOffset    Two parts:
+ *                                - The first 8 bits make up the SIB byte.
+ *                                - The next 8 bits are the fixed RSP/ESP offset
+ *                                  in case of a pop [xSP].
+ * @param   u32Disp             The displacement byte/word/dword, if any.
+ * @param   cbInstr             The size of the fully decoded instruction. Used
+ *                              for RIP relative addressing.
+ * @param   idxVarRet           .
+ *
+ * @see iemOpHlpCalcRmEffAddrThreadedAddr64
+ */
+DECL_INLINE_THROW(uint32_t)
+iemNativeEmitCalcRmEffAddrThreadedAddr64(PIEMRECOMPILERSTATE pReNative, uint32_t off, uint8_t bRmEx, uint32_t uSibAndRspOffset,
+                                         uint32_t u32Disp, uint8_t cbInstr, uint8_t idxVarRet, bool f64Bit)
+{
+    IEMNATIVE_ASSERT_VAR_IDX(pReNative, idxVarRet);
+
+    /*
+     * Special case the rip + disp32 form first.
+     */
+    if ((bRmEx & (X86_MODRM_MOD_MASK | X86_MODRM_RM_MASK)) == 5)
+    {
+        uint8_t const idxRegRet = iemNativeVarAllocRegister(pReNative, idxVarRet, &off);
+        uint8_t const idxRegPc  = iemNativeRegAllocTmpForGuestReg(pReNative, &off, kIemNativeGstReg_Pc,
+                                                                  kIemNativeGstRegUse_ReadOnly);
+#ifdef RT_ARCH_AMD64
+        if (f64Bit)
+        {
+            int64_t const offFinalDisp = (int64_t)(int32_t)u32Disp + cbInstr;
+            if ((int32_t)offFinalDisp == offFinalDisp)
+                off = iemNativeEmitLoadGprFromGprWithAddendMaybeZero(pReNative, off, idxRegRet, idxRegPc, (int32_t)offFinalDisp);
+            else
+            {
+                off = iemNativeEmitLoadGprFromGprWithAddend(pReNative, off, idxRegRet, idxRegPc, (int32_t)u32Disp);
+                off = iemNativeEmitAddGprImm8(pReNative, off, idxRegRet, cbInstr);
+            }
+        }
+        else
+            off = iemNativeEmitLoadGprFromGpr32WithAddendMaybeZero(pReNative, off, idxRegRet, idxRegPc, (int32_t)u32Disp + cbInstr);
+
+#elif defined(RT_ARCH_ARM64)
+        if (f64Bit)
+            off = iemNativeEmitLoadGprFromGprWithAddendMaybeZero(pReNative, off, idxRegRet, idxRegPc,
+                                                                 (int64_t)(int32_t)u32Disp + cbInstr);
+        else
+            off = iemNativeEmitLoadGprFromGpr32WithAddendMaybeZero(pReNative, off, idxRegRet, idxRegPc,
+                                                                   (int32_t)u32Disp + cbInstr);
+
+#else
+# error "Port me!"
+#endif
+        iemNativeRegFreeTmp(pReNative, idxRegPc);
+        return off;
+    }
+
+    /* Calculate the fixed displacement (more down in SIB.B=4 and SIB.B=5 on this). */
+    int64_t i64EffAddr = 0;
+    switch ((bRmEx >> X86_MODRM_MOD_SHIFT) & X86_MODRM_MOD_SMASK)
+    {
+        case 0: break;
+        case 1: i64EffAddr = (int8_t)u32Disp; break;
+        case 2: i64EffAddr = (int32_t)u32Disp; break;
+        default: AssertFailed();
+    }
+
+    /* Get the register (or SIB) value. */
+    uint8_t idxGstRegBase  = UINT8_MAX;
+    uint8_t idxGstRegIndex = UINT8_MAX;
+    uint8_t cShiftIndex    = 0;
+    if ((bRmEx & X86_MODRM_RM_MASK) != 4)
+        idxGstRegBase = bRmEx & (X86_MODRM_RM_MASK | 0x8); /* bRmEx[bit 3] = REX.B */
+    else /* SIB: */
+    {
+        /* index /w scaling . */
+        cShiftIndex    = (uSibAndRspOffset >> X86_SIB_SCALE_SHIFT) & X86_SIB_SCALE_SMASK;
+        idxGstRegIndex = ((uSibAndRspOffset >> X86_SIB_INDEX_SHIFT) & X86_SIB_INDEX_SMASK)
+                       | ((bRmEx & 0x10) >> 1); /* bRmEx[bit 4] = REX.X */
+        if (idxGstRegIndex == 4)
+        {
+            /* no index */
+            cShiftIndex    = 0;
+            idxGstRegIndex = UINT8_MAX;
+        }
+
+        /* base */
+        idxGstRegBase = (uSibAndRspOffset & X86_SIB_BASE_MASK) | (bRmEx & 0x8); /* bRmEx[bit 3] = REX.B */
+        if (idxGstRegBase == 4)
+        {
+            /* pop [rsp] hack */
+            i64EffAddr += uSibAndRspOffset >> 8; /* (this is why i64EffAddr must be 64-bit) */
+        }
+        else if (   (idxGstRegBase & X86_SIB_BASE_MASK) == 5
+                 && (bRmEx & X86_MODRM_MOD_MASK) == 0)
+        {
+            /* mod=0 and base=5 -> disp32, no base reg. */
+            Assert(i64EffAddr == 0);
+            i64EffAddr    = (int32_t)u32Disp;
+            idxGstRegBase = UINT8_MAX;
+        }
+    }
+
+    /*
+     * If no registers are involved (SIB.B=5, SIB.X=4) repeat what we did at
+     * the start of the function.
+     */
+    if (idxGstRegBase == UINT8_MAX && idxGstRegIndex == UINT8_MAX)
+    {
+        if (f64Bit)
+            iemNativeVarSetKindToConst(pReNative, idxVarRet, (uint64_t)i64EffAddr);
+        else
+            iemNativeVarSetKindToConst(pReNative, idxVarRet, (uint64_t)(int32_t)i64EffAddr);
+        return off;
+    }
+
+    /*
+     * Now emit code that calculates:
+     *      idxRegRet = (uint64_t)(i64EffAddr [+ idxGstRegBase] [+ (idxGstRegIndex << cShiftIndex)])
+     * or if !f64Bit:
+     *      idxRegRet = (uint32_t)(i64EffAddr [+ idxGstRegBase] [+ (idxGstRegIndex << cShiftIndex)])
+     */
+    uint8_t const idxRegRet   = iemNativeVarAllocRegister(pReNative, idxVarRet, &off);
+    uint8_t       idxRegBase  = idxGstRegBase == UINT8_MAX ? UINT8_MAX
+                              : iemNativeRegAllocTmpForGuestReg(pReNative, &off, IEMNATIVEGSTREG_GPR(idxGstRegBase),
+                                                                kIemNativeGstRegUse_ReadOnly);
+    uint8_t       idxRegIndex = idxGstRegIndex == UINT8_MAX ? UINT8_MAX
+                              : iemNativeRegAllocTmpForGuestReg(pReNative, &off, IEMNATIVEGSTREG_GPR(idxGstRegIndex),
+                                                               kIemNativeGstRegUse_ReadOnly);
+
+    /* If base is not given and there is no shifting, swap the registers to avoid code duplication. */
+    if (idxRegBase == UINT8_MAX && cShiftIndex == 0)
+    {
+        idxRegBase  = idxRegIndex;
+        idxRegIndex = UINT8_MAX;
+    }
+
+#ifdef RT_ARCH_AMD64
+    uint8_t bFinalAdj;
+    if (!f64Bit || (int32_t)i64EffAddr == i64EffAddr)
+        bFinalAdj = 0; /* likely */
+    else
+    {
+        /* pop [rsp] with a problematic disp32 value.  Split out the
+           RSP offset and add it separately afterwards (bFinalAdj). */
+        /** @todo testcase: pop [rsp] with problematic disp32 (mod4).   */
+        Assert(idxGstRegBase == X86_GREG_xSP);
+        Assert(((bRmEx >> X86_MODRM_MOD_SHIFT) & X86_MODRM_MOD_SMASK) == X86_MOD_MEM4);
+        bFinalAdj   = (uint8_t)(uSibAndRspOffset >> 8);
+        Assert(bFinalAdj != 0);
+        i64EffAddr -= bFinalAdj;
+        Assert((int32_t)i64EffAddr == i64EffAddr);
+    }
+    uint32_t const u32EffAddr = (uint32_t)i64EffAddr;
+//pReNative->pInstrBuf[off++] = 0xcc;
+
+    if (idxRegIndex == UINT8_MAX)
+    {
+        if (u32EffAddr == 0)
+        {
+            /* mov ret, base */
+            if (f64Bit)
+                off = iemNativeEmitLoadGprFromGpr(pReNative, off, idxRegRet, idxRegBase);
+            else
+                off = iemNativeEmitLoadGprFromGpr32(pReNative, off, idxRegRet, idxRegBase);
+        }
+        else
+        {
+            /* lea ret, [base + disp32] */
+            Assert(idxRegBase != X86_GREG_xSP /*SIB*/);
+            uint8_t * const pbCodeBuf = iemNativeInstrBufEnsure(pReNative, off, 8);
+            if (f64Bit || idxRegRet >= 8 || idxRegBase >= 8)
+                pbCodeBuf[off++] = (idxRegRet  >= 8 ? X86_OP_REX_R : 0)
+                                 | (idxRegBase >= 8 ? X86_OP_REX_B : 0)
+                                 | (f64Bit          ? X86_OP_REX_W : 0);
+            pbCodeBuf[off++] = 0x8d;
+            uint8_t const bMod = (int8_t)u32EffAddr == (int32_t)u32EffAddr ? X86_MOD_MEM1 : X86_MOD_MEM4;
+            if (idxRegBase != X86_GREG_x12 /*SIB*/)
+                pbCodeBuf[off++] = X86_MODRM_MAKE(bMod, idxRegRet & 7, idxRegBase & 7);
+            else
+            {
+                pbCodeBuf[off++] = X86_MODRM_MAKE(bMod, idxRegRet & 7, 4 /*SIB*/);
+                pbCodeBuf[off++] = X86_SIB_MAKE(X86_GREG_x12 & 7, 4 /*no index*/, 0);
+            }
+            pbCodeBuf[off++] = RT_BYTE1(u32EffAddr);
+            if (bMod == X86_MOD_MEM4)
+            {
+                pbCodeBuf[off++] = RT_BYTE2(u32EffAddr);
+                pbCodeBuf[off++] = RT_BYTE3(u32EffAddr);
+                pbCodeBuf[off++] = RT_BYTE4(u32EffAddr);
+            }
+            IEMNATIVE_ASSERT_INSTR_BUF_ENSURE(pReNative, off);
+        }
+    }
+    else
+    {
+        Assert(idxRegIndex != X86_GREG_xSP /*no-index*/);
+        uint8_t * const pbCodeBuf = iemNativeInstrBufEnsure(pReNative, off, 8);
+        if (idxRegBase == UINT8_MAX)
+        {
+            /* lea ret, [(index64 << cShiftIndex) + disp32] */
+            if (f64Bit || idxRegRet >= 8 || idxRegIndex >= 8)
+                pbCodeBuf[off++] = (idxRegRet   >= 8 ? X86_OP_REX_R : 0)
+                                 | (idxRegIndex >= 8 ? X86_OP_REX_X : 0)
+                                 | (f64Bit           ? X86_OP_REX_W : 0);
+            pbCodeBuf[off++] = 0x8d;
+            pbCodeBuf[off++] = X86_MODRM_MAKE(X86_MOD_MEM0, idxRegRet & 7, 4 /*SIB*/);
+            pbCodeBuf[off++] = X86_SIB_MAKE(5 /*nobase/bp*/, idxRegIndex & 7, cShiftIndex);
+            pbCodeBuf[off++] = RT_BYTE1(u32EffAddr);
+            pbCodeBuf[off++] = RT_BYTE2(u32EffAddr);
+            pbCodeBuf[off++] = RT_BYTE3(u32EffAddr);
+            pbCodeBuf[off++] = RT_BYTE4(u32EffAddr);
+        }
+        else
+        {
+            /* lea ret, [(index64 << cShiftIndex) + base64 (+ disp32)] */
+            if (f64Bit || idxRegRet >= 8 || idxRegBase >= 8 || idxRegIndex >= 8)
+                pbCodeBuf[off++] = (idxRegRet   >= 8 ? X86_OP_REX_R : 0)
+                                 | (idxRegBase  >= 8 ? X86_OP_REX_B : 0)
+                                 | (idxRegIndex >= 8 ? X86_OP_REX_X : 0)
+                                 | (f64Bit           ? X86_OP_REX_W : 0);
+            pbCodeBuf[off++] = 0x8d;
+            uint8_t const bMod = u32EffAddr == 0 && (idxRegBase & 7) != X86_GREG_xBP ? X86_MOD_MEM0
+                               : (int8_t)u32EffAddr == (int32_t)u32EffAddr           ? X86_MOD_MEM1 : X86_MOD_MEM4;
+            pbCodeBuf[off++] = X86_MODRM_MAKE(bMod, idxRegRet & 7, 4 /*SIB*/);
+            pbCodeBuf[off++] = X86_SIB_MAKE(idxRegBase & 7, idxRegIndex & 7, cShiftIndex);
+            if (bMod != X86_MOD_MEM0)
+            {
+                pbCodeBuf[off++] = RT_BYTE1(u32EffAddr);
+                if (bMod == X86_MOD_MEM4)
+                {
+                    pbCodeBuf[off++] = RT_BYTE2(u32EffAddr);
+                    pbCodeBuf[off++] = RT_BYTE3(u32EffAddr);
+                    pbCodeBuf[off++] = RT_BYTE4(u32EffAddr);
+                }
+            }
+        }
+        IEMNATIVE_ASSERT_INSTR_BUF_ENSURE(pReNative, off);
+    }
+
+    if (!bFinalAdj)
+    { /* likely */ }
+    else
+    {
+        Assert(f64Bit);
+        off = iemNativeEmitAddGprImm8(pReNative, off, idxRegRet, bFinalAdj);
+    }
+
+#elif defined(RT_ARCH_ARM64)
+    if (i64EffAddr == 0)
+    {
+        uint32_t * const pu32CodeBuf = iemNativeInstrBufEnsure(pReNative, off, 1);
+        if (idxRegIndex == UINT8_MAX)
+            pu32CodeBuf[off++] = Armv8A64MkInstrMov(idxRegRet, idxRegBase, f64Bit);
+        else if (idxRegBase != UINT8_MAX)
+            pu32CodeBuf[off++] = Armv8A64MkInstrAddSubReg(false /*fSub*/, idxRegRet, idxRegBase, idxRegIndex,
+                                                          f64Bit, false /*fSetFlags*/, cShiftIndex);
+        else
+        {
+            Assert(cShiftIndex != 0); /* See base = index swap above when shift is 0 and we have no base reg. */
+            pu32CodeBuf[off++] = Armv8A64MkInstrLslImm(idxRegRet, idxRegIndex, cShiftIndex, f64Bit);
+        }
+    }
+    else
+    {
+        if (f64Bit)
+        { /* likely */ }
+        else
+            i64EffAddr = (int32_t)i64EffAddr;
+
+        if (i64EffAddr < 4096 && i64EffAddr >= 0 && idxRegBase != UINT8_MAX)
+        {
+            uint32_t * const pu32CodeBuf = iemNativeInstrBufEnsure(pReNative, off, 1);
+            pu32CodeBuf[off++] = Armv8A64MkInstrAddSubUImm12(false /*fSub*/, idxRegRet, idxRegBase, i64EffAddr, f64Bit);
+        }
+        else if (i64EffAddr > -4096 && i64EffAddr < 0 && idxRegBase != UINT8_MAX)
+        {
+            uint32_t * const pu32CodeBuf = iemNativeInstrBufEnsure(pReNative, off, 1);
+            pu32CodeBuf[off++] = Armv8A64MkInstrAddSubUImm12(true /*fSub*/, idxRegRet, idxRegBase, (uint32_t)-i64EffAddr, f64Bit);
+        }
+        else
+        {
+            if (f64Bit)
+                off = iemNativeEmitLoadGprImm64(pReNative, off, idxRegRet, i64EffAddr);
+            else
+                off = iemNativeEmitLoadGprImm64(pReNative, off, idxRegRet, (uint32_t)i64EffAddr);
+            if (idxRegBase != UINT8_MAX)
+            {
+                uint32_t * const pu32CodeBuf = iemNativeInstrBufEnsure(pReNative, off, 1);
+                pu32CodeBuf[off++] = Armv8A64MkInstrAddSubReg(false /*fSub*/, idxRegRet, idxRegRet, idxRegBase, f64Bit);
+            }
+        }
+        if (idxRegIndex != UINT8_MAX)
+        {
+            uint32_t * const pu32CodeBuf = iemNativeInstrBufEnsure(pReNative, off, 1);
+            pu32CodeBuf[off++] = Armv8A64MkInstrAddSubReg(false /*fSub*/, idxRegRet, idxRegRet, idxRegIndex,
+                                                          f64Bit, false /*fSetFlags*/, cShiftIndex);
+        }
+    }
+
+#else
+# error "port me"
+#endif
+
+    if (idxRegIndex != UINT8_MAX)
+        iemNativeRegFreeTmp(pReNative, idxRegIndex);
+    if (idxRegBase != UINT8_MAX)
+        iemNativeRegFreeTmp(pReNative, idxRegBase);
+    return off;
+}
+
 
 
@@ -9280,5 +9603,5 @@
                                                (uintptr_t)iemNativeHlpMemFlatStoreDataU32, pCallEntry->idxInstr)
 
-#define IEM_MC_STORE_MEM_FLAT_U64_CONST(_GCPtrMem, a_u64ConstValue) \
+#define IEM_MC_STORE_MEM_FLAT_U64_CONST(a_GCPtrMem, a_u64ConstValue) \
     off = iemNativeEmitMemStoreConstDataCommon(pReNative, off, a_u64ConstValue, UINT8_MAX, a_GCPtrMem, sizeof(uint64_t), \
                                                (uintptr_t)iemNativeHlpMemFlatStoreDataU64, pCallEntry->idxInstr)
@@ -10125,4 +10448,5 @@
         uint32_t                offRange         = 0;
         uint32_t                offOpcodes       = 0;
+        uint32_t const          cbOpcodes        = pTb->cbOpcodes;
         RTGCPHYS                GCPhysPc         = pTb->GCPhysPc;
         uint32_t const          cDbgEntries      = pDbgInfo->cEntries;
@@ -10162,5 +10486,5 @@
                                of ranges, or when some complicated interrupts/FFs are found to be pending or
                                similar.  So, we just deal with it here rather than in the compiler code as it
-                               is a lot simpler to do up here. */
+                               is a lot simpler to do here. */
                             if (   idxRange == UINT8_MAX
                                 || idxRange >= cRanges
@@ -10169,8 +10493,8 @@
                                 idxRange += 1;
                                 if (idxRange < cRanges)
-                                    offRange = 0;
+                                    offRange = !idxRange ? 0 : offRange - pTb->aRanges[idxRange - 1].cbOpcodes;
                                 else
                                     continue;
-                                Assert(offOpcodes == pTb->aRanges[idxRange].offOpcodes);
+                                Assert(offOpcodes == pTb->aRanges[idxRange].offOpcodes + offRange);
                                 GCPhysPc = pTb->aRanges[idxRange].offPhysPage
                                          + (pTb->aRanges[idxRange].idxPhysPage == 0
@@ -10180,8 +10504,10 @@
                                                 idxRange, GCPhysPc, pTb->aRanges[idxRange].cbOpcodes,
                                                 pTb->aRanges[idxRange].idxPhysPage);
+                                GCPhysPc += offRange;
                             }
 
                             /* Disassemble the instruction. */
-                            uint8_t const cbInstrMax = RT_MIN(pTb->aRanges[idxRange].cbOpcodes - offRange, 15);
+                            //uint8_t const cbInstrMax = RT_MIN(pTb->aRanges[idxRange].cbOpcodes - offRange, 15);
+                            uint8_t const cbInstrMax = RT_MIN(cbOpcodes - offRange, 15);
                             uint32_t      cbInstr    = 1;
                             int rc = DISInstrWithPrefetchedBytes(GCPhysPc, enmGstCpuMode, DISOPTYPE_ALL,
@@ -10221,9 +10547,9 @@
                         case kIemTbDbgEntryType_ThreadedCall:
                             pHlp->pfnPrintf(pHlp,
-                                            "  Call #%u to %s (%u args)%s\n",
+                                            "  Call #%u to %s (%u args) - %s\n",
                                             idxThreadedCall,
                                             g_apszIemThreadedFunctions[pDbgInfo->aEntries[iDbgEntry].ThreadedCall.enmCall],
                                             g_acIemThreadedFunctionUsedArgs[pDbgInfo->aEntries[iDbgEntry].ThreadedCall.enmCall],
-                                            pDbgInfo->aEntries[iDbgEntry].ThreadedCall.fRecompiled ? " - recompiled" : "");
+                                            pDbgInfo->aEntries[iDbgEntry].ThreadedCall.fRecompiled ? "recompiled" : "todo");
                             idxThreadedCall++;
                             continue;
@@ -10331,8 +10657,8 @@
                     uint32_t const uInfo = *(uint32_t const *)&Dis.Instr.ab[3];
                     if (RT_HIWORD(uInfo) < kIemThreadedFunc_End)
-                        pHlp->pfnPrintf(pHlp, "    %p: nop ; marker: call #%u to %s (%u args)%s\n",
+                        pHlp->pfnPrintf(pHlp, "    %p: nop ; marker: call #%u to %s (%u args) - %s\n",
                                         pNativeCur, uInfo & 0x7fff, g_apszIemThreadedFunctions[RT_HIWORD(uInfo)],
                                         g_acIemThreadedFunctionUsedArgs[RT_HIWORD(uInfo)],
-                                        uInfo & 0x8000 ? " - recompiled" : "");
+                                        uInfo & 0x8000 ? "recompiled" : "todo");
                     else
                         pHlp->pfnPrintf(pHlp, "    %p: nop ; unknown marker: %#x (%d)\n", pNativeCur, uInfo, uInfo);
@@ -10417,4 +10743,5 @@
                             i, GCPhysPc, pTb->aRanges[i].cbOpcodes, pTb->aRanges[i].idxPhysPage);
             unsigned       off       = pTb->aRanges[i].offOpcodes;
+            /** @todo this ain't working when crossing pages!   */
             unsigned const cbOpcodes = pTb->aRanges[i].cbOpcodes + off;
             while (off < cbOpcodes)
@@ -10460,8 +10787,8 @@
                     uint32_t const uInfo = *(uint32_t const *)&Dis.Instr.ab[3];
                     if (RT_HIWORD(uInfo) < kIemThreadedFunc_End)
-                        pHlp->pfnPrintf(pHlp, "\n    %p: nop ; marker: call #%u to %s (%u args)%s\n",
+                        pHlp->pfnPrintf(pHlp, "\n    %p: nop ; marker: call #%u to %s (%u args) - %s\n",
                                         pNativeCur, uInfo & 0x7fff, g_apszIemThreadedFunctions[RT_HIWORD(uInfo)],
                                         g_acIemThreadedFunctionUsedArgs[RT_HIWORD(uInfo)],
-                                        uInfo & 0x8000 ? " - recompiled" : "");
+                                        uInfo & 0x8000 ? "recompiled" : "todo");
                     else
                         pHlp->pfnPrintf(pHlp, "    %p: nop ; unknown marker: %#x (%d)\n", pNativeCur, uInfo, uInfo);
@@ -10625,5 +10952,5 @@
              */
             Log2(("%u[%u]: %s%s\n", pTb->Thrd.cCalls - cCallsLeft - 1, pCallEntry->idxInstr,
-                  g_apszIemThreadedFunctions[pCallEntry->enmFunction], pfnRecom ? "" : "(todo)"));
+                  g_apszIemThreadedFunctions[pCallEntry->enmFunction], pfnRecom ? "(recompiled)" : "(todo)"));
             if (pfnRecom) /** @todo stats on this.   */
             {
Index: /trunk/src/VBox/VMM/VMMAll/IEMAllThrdFuncs.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMAll/IEMAllThrdFuncs.cpp	(revision 102509)
+++ /trunk/src/VBox/VMM/VMMAll/IEMAllThrdFuncs.cpp	(revision 102510)
@@ -537,5 +537,5 @@
  * @param   uSibAndRspOffset    Two parts:
  *                                - The first 8 bits make up the SIB byte.
- *                                - The next 8 bits are the fixed RSP/ESP offse
+ *                                - The next 8 bits are the fixed RSP/ESP offset
  *                                  in case of a pop [xSP].
  * @param   u32Disp             The displacement byte/word/dword, if any.
Index: /trunk/src/VBox/VMM/include/IEMMc.h
===================================================================
--- /trunk/src/VBox/VMM/include/IEMMc.h	(revision 102509)
+++ /trunk/src/VBox/VMM/include/IEMMc.h	(revision 102510)
@@ -979,5 +979,5 @@
     iemMemFlatFetchDataR80Jmp(pVCpu, &(a_r80Dst), (a_GCPtrMem))
 # define IEM_MC_FETCH_MEM_FLAT_D80(a_d80Dst, a_GCPtrMem) \
-    iemMemFetchDataD80Jmp(pVCpu, &(a_d80Dst), UINT8_MAX, (a_GCPtrMem))
+    iemMemFlatFetchDataD80Jmp(pVCpu, &(a_d80Dst), (a_GCPtrMem))
 #endif
 
@@ -1078,5 +1078,5 @@
     (a_XmmDst).au32[(a_iDWord)] = iemMemFlatFetchDataU32Jmp(pVCpu, (a_GCPtrMem))
 # define IEM_MC_FETCH_MEM_FLAT_XMM_U64(a_XmmDst, a_iQWord, a_GCPtrMem) \
-    (a_XmmDst).au64[(a_iQWord)] = iemMemFetchDataU64Jmp(pVCpu, UINT8_MAX, (a_GCPtrMem))
+    (a_XmmDst).au64[(a_iQWord)] = iemMemFlatFetchDataU64Jmp(pVCpu, (a_GCPtrMem))
 
 # define IEM_MC_FETCH_MEM_U128_AND_XREG_U128(a_Dst, a_iXReg1, a_iSeg2, a_GCPtrMem2) do { \
Index: /trunk/src/VBox/VMM/include/IEMN8veRecompilerEmit.h
===================================================================
--- /trunk/src/VBox/VMM/include/IEMN8veRecompilerEmit.h	(revision 102509)
+++ /trunk/src/VBox/VMM/include/IEMN8veRecompilerEmit.h	(revision 102510)
@@ -105,4 +105,38 @@
 *********************************************************************************************************************************/
 
+#ifdef RT_ARCH_AMD64
+/**
+ * Common bit of iemNativeEmitLoadGprByGpr and friends.
+ */
+DECL_FORCE_INLINE(uint32_t)
+iemNativeEmitGprByGprDisp(uint8_t *pbCodeBuf, uint32_t off, uint8_t iGprReg, uint8_t iGprBase, int32_t offDisp)
+{
+    if (offDisp == 0 && (iGprBase & 7) != X86_GREG_xBP) /* Can use encoding w/o displacement field. */
+    {
+        pbCodeBuf[off++] = X86_MODRM_MAKE(X86_MOD_MEM0, iGprReg & 7, iGprBase & 7);
+        if ((iGprBase & 7) == X86_GREG_xSP) /* for RSP/R12 relative addressing we have to use a SIB byte. */
+            pbCodeBuf[off++] = X86_SIB_MAKE(X86_GREG_xSP, X86_GREG_xSP, 0); /* -> [RSP/R12] */
+    }
+    else if (offDisp == (int8_t)offDisp)
+    {
+        pbCodeBuf[off++] = X86_MODRM_MAKE(X86_MOD_MEM1, iGprReg & 7, iGprBase & 7);
+        if ((iGprBase & 7) == X86_GREG_xSP) /* for RSP/R12 relative addressing we have to use a SIB byte. */
+            pbCodeBuf[off++] = X86_SIB_MAKE(X86_GREG_xSP, X86_GREG_xSP, 0); /* -> [RSP/R12] */
+        pbCodeBuf[off++] = (uint8_t)offDisp;
+    }
+    else
+    {
+        pbCodeBuf[off++] = X86_MODRM_MAKE(X86_MOD_MEM4, iGprReg & 7, iGprBase & 7);
+        if ((iGprBase & 7) == X86_GREG_xSP) /* for RSP/R12 relative addressing we have to use a SIB byte. */
+            pbCodeBuf[off++] = X86_SIB_MAKE(X86_GREG_xSP, X86_GREG_xSP, 0); /* -> [RSP/R12] */
+        pbCodeBuf[off++] = RT_BYTE1((uint32_t)offDisp);
+        pbCodeBuf[off++] = RT_BYTE2((uint32_t)offDisp);
+        pbCodeBuf[off++] = RT_BYTE3((uint32_t)offDisp);
+        pbCodeBuf[off++] = RT_BYTE4((uint32_t)offDisp);
+    }
+    return off;
+}
+#endif /* RT_ARCH_AMD64 */
+
 /**
  * Emits setting a GPR to zero.
@@ -889,5 +923,5 @@
 /**
  * Sign-extends 8-bit value in @a iGprSrc into a 32-bit value in @a iGprDst.
- * @note Bits 64 thru 32 are cleared.
+ * @note Bits 63 thru 32 are cleared.
  */
 DECL_INLINE_THROW(uint32_t)
@@ -918,5 +952,5 @@
 /**
  * Sign-extends 8-bit value in @a iGprSrc into a 16-bit value in @a iGprDst.
- * @note Bits 64 thru 16 are cleared.
+ * @note Bits 63 thru 16 are cleared.
  */
 DECL_INLINE_THROW(uint32_t)
@@ -957,5 +991,7 @@
 /**
  * Emits a gprdst = gprsrc + addend load.
- */
+ * @note The added is 32-bit for AMD64 and 64-bit for ARM64.
+ */
+#ifdef RT_ARCH_AMD64
 DECL_INLINE_THROW(uint32_t)
 iemNativeEmitLoadGprFromGprWithAddend(PIEMRECOMPILERSTATE pReNative, uint32_t off,
@@ -964,29 +1000,18 @@
     Assert(iAddend != 0);
 
-#ifdef RT_ARCH_AMD64
     /* lea gprdst, [gprsrc + iAddend] */
-    uint8_t * const pbCodeBuf = iemNativeInstrBufEnsure(pReNative, off, 7);
-    if ((iGprDst | iGprSrc) >= 8)
-        pbCodeBuf[off++] = iGprDst < 8  ? X86_OP_REX_W | X86_OP_REX_B
-                         : iGprSrc >= 8 ? X86_OP_REX_W | X86_OP_REX_R | X86_OP_REX_B
-                         :                X86_OP_REX_W | X86_OP_REX_R;
-    else
-        pbCodeBuf[off++] = X86_OP_REX_W;
+    uint8_t * const pbCodeBuf = iemNativeInstrBufEnsure(pReNative, off, 8);
+    pbCodeBuf[off++] = X86_OP_REX_W | (iGprDst >= 8 ? X86_OP_REX_R : 0) | (iGprSrc >= 8 ? X86_OP_REX_B : 0);
     pbCodeBuf[off++] = 0x8d;
-    if (iAddend >= -128 && iAddend < 128)
-    {
-        pbCodeBuf[off++] = X86_MODRM_MAKE(X86_MOD_MEM1, iGprDst & 7, iGprSrc & 7);
-        pbCodeBuf[off++] = (int8_t)iAddend;
-    }
-    else
-    {
-        pbCodeBuf[off++] = X86_MODRM_MAKE(X86_MOD_MEM4, iGprDst & 7, iGprSrc & 7);
-        pbCodeBuf[off++] = RT_BYTE1((uint32_t)iAddend);
-        pbCodeBuf[off++] = RT_BYTE2((uint32_t)iAddend);
-        pbCodeBuf[off++] = RT_BYTE3((uint32_t)iAddend);
-        pbCodeBuf[off++] = RT_BYTE4((uint32_t)iAddend);
-    }
-
-#elif defined(RT_ARCH_ARM64)
+    off = iemNativeEmitGprByGprDisp(pbCodeBuf, off, iGprDst, iGprSrc, iAddend);
+    IEMNATIVE_ASSERT_INSTR_BUF_ENSURE(pReNative, off);
+    return off;
+}
+
+#elif defined(RT_ARCH_ARM64)
+DECL_INLINE_THROW(uint32_t)
+iemNativeEmitLoadGprFromGprWithAddend(PIEMRECOMPILERSTATE pReNative, uint32_t off,
+                                      uint8_t iGprDst, uint8_t iGprSrc, int64_t iAddend)
+{
     if ((uint32_t)iAddend < 4096)
     {
@@ -1003,15 +1028,96 @@
     else
     {
+        Assert(iGprSrc != iGprDst);
+        off = iemNativeEmitLoadGprImm64(pReNative, off, iGprDst, iAddend);
+        uint32_t * const pu32CodeBuf = iemNativeInstrBufEnsure(pReNative, off, 1);
+        pu32CodeBuf[off++] = Armv8A64MkInstrAddSubReg(false /*fSub*/, iGprDst, iGprSrc, iGprDst);
+    }
+    IEMNATIVE_ASSERT_INSTR_BUF_ENSURE(pReNative, off);
+    return off;
+}
+#else
+# error "port me"
+#endif
+
+/**
+ * Emits a gprdst = gprsrc + addend load, accepting iAddend == 0.
+ * @note The added is 32-bit for AMD64 and 64-bit for ARM64.
+ */
+#ifdef RT_ARCH_AMD64
+DECL_INLINE_THROW(uint32_t)
+iemNativeEmitLoadGprFromGprWithAddendMaybeZero(PIEMRECOMPILERSTATE pReNative, uint32_t off,
+                                               uint8_t iGprDst, uint8_t iGprSrc, int32_t iAddend)
+#else
+DECL_INLINE_THROW(uint32_t)
+iemNativeEmitLoadGprFromGprWithAddendMaybeZero(PIEMRECOMPILERSTATE pReNative, uint32_t off,
+                                               uint8_t iGprDst, uint8_t iGprSrc, int64_t iAddend)
+#endif
+{
+    if (iAddend != 0)
+        return iemNativeEmitLoadGprFromGprWithAddend(pReNative, off, iGprDst, iGprSrc, iAddend);
+    return iemNativeEmitLoadGprFromGpr(pReNative, off, iGprDst, iGprSrc);
+}
+
+
+/**
+ * Emits a gprdst = gprsrc32 + addend load.
+ * @note Bits 63 thru 32 are cleared.
+ */
+DECL_INLINE_THROW(uint32_t)
+iemNativeEmitLoadGprFromGpr32WithAddend(PIEMRECOMPILERSTATE pReNative, uint32_t off,
+                                        uint8_t iGprDst, uint8_t iGprSrc, int32_t iAddend)
+{
+    Assert(iAddend != 0);
+
+#ifdef RT_ARCH_AMD64
+    /* a32 o32 lea gprdst, [gprsrc + iAddend] */
+    uint8_t * const pbCodeBuf = iemNativeInstrBufEnsure(pReNative, off, 9);
+    pbCodeBuf[off++] = X86_OP_PRF_SIZE_ADDR;
+    if ((iGprDst | iGprSrc) >= 8)
+        pbCodeBuf[off++] = (iGprDst >= 8 ? X86_OP_REX_R : 0) | (iGprSrc >= 8 ? X86_OP_REX_B : 0);
+    pbCodeBuf[off++] = 0x8d;
+    off = iemNativeEmitGprByGprDisp(pbCodeBuf, off, iGprDst, iGprSrc, iAddend);
+
+#elif defined(RT_ARCH_ARM64)
+    if ((uint32_t)iAddend < 4096)
+    {
+        /* add dst, src, uimm12 */
+        uint32_t * const pu32CodeBuf = iemNativeInstrBufEnsure(pReNative, off, 1);
+        pu32CodeBuf[off++] = Armv8A64MkInstrAddSubUImm12(false /*fSub*/, iGprDst, iGprSrc, (uint32_t)iAddend, false /*f64Bit*/);
+    }
+    else if ((uint32_t)-iAddend < 4096)
+    {
+        /* sub dst, src, uimm12 */
+        uint32_t * const pu32CodeBuf = iemNativeInstrBufEnsure(pReNative, off, 1);
+        pu32CodeBuf[off++] = Armv8A64MkInstrAddSubUImm12(true /*fSub*/, iGprDst, iGprSrc, (uint32_t)-iAddend, false /*f64Bit*/);
+    }
+    else
+    {
+        Assert(iGprSrc != iGprDst);
         off = iemNativeEmitLoadGprImm64(pReNative, off, iGprDst, (int64_t)iAddend);
         uint32_t * const pu32CodeBuf = iemNativeInstrBufEnsure(pReNative, off, 1);
-        pu32CodeBuf[off++] = Armv8A64MkInstrAddSubReg(false /*fSub*/, iGprDst, iGprSrc, iGprDst);
-    }
-
-#else
-# error "port me"
-#endif
-    IEMNATIVE_ASSERT_INSTR_BUF_ENSURE(pReNative, off);
-    return off;
-}
+        pu32CodeBuf[off++] = Armv8A64MkInstrAddSubReg(false /*fSub*/, iGprDst, iGprSrc, iGprDst, false /*f64Bit*/);
+    }
+
+#else
+# error "port me"
+#endif
+    IEMNATIVE_ASSERT_INSTR_BUF_ENSURE(pReNative, off);
+    return off;
+}
+
+
+/**
+ * Emits a gprdst = gprsrc32 + addend load, accepting iAddend == 0.
+ */
+DECL_INLINE_THROW(uint32_t)
+iemNativeEmitLoadGprFromGpr32WithAddendMaybeZero(PIEMRECOMPILERSTATE pReNative, uint32_t off,
+                                                 uint8_t iGprDst, uint8_t iGprSrc, int32_t iAddend)
+{
+    if (iAddend != 0)
+        return iemNativeEmitLoadGprFromGpr32WithAddend(pReNative, off, iGprDst, iGprSrc, iAddend);
+    return iemNativeEmitLoadGprFromGpr32(pReNative, off, iGprDst, iGprSrc);
+}
+
 
 
@@ -1319,37 +1425,5 @@
 
 
-#ifdef RT_ARCH_AMD64
-/**
- * Common bit of iemNativeEmitLoadGprByGpr and friends.
- */
-DECL_FORCE_INLINE(uint32_t)
-iemNativeEmitGprByGprDisp(uint8_t *pbCodeBuf, uint32_t off, uint8_t iGprReg, uint8_t iGprBase, int32_t offDisp)
-{
-    if (offDisp == 0 && (iGprBase & 7) != X86_GREG_xBP) /* Can use encoding w/o displacement field. */
-    {
-        pbCodeBuf[off++] = X86_MODRM_MAKE(X86_MOD_MEM0, iGprReg & 7, iGprBase & 7);
-        if ((iGprBase & 7) == X86_GREG_xSP) /* for RSP/R12 relative addressing we have to use a SIB byte. */
-            pbCodeBuf[off++] = X86_SIB_MAKE(X86_GREG_xSP, X86_GREG_xSP, 0); /* -> [RSP/R12] */
-    }
-    else if (offDisp == (int8_t)offDisp)
-    {
-        pbCodeBuf[off++] = X86_MODRM_MAKE(X86_MOD_MEM1, iGprReg & 7, iGprBase & 7);
-        if ((iGprBase & 7) == X86_GREG_xSP) /* for RSP/R12 relative addressing we have to use a SIB byte. */
-            pbCodeBuf[off++] = X86_SIB_MAKE(X86_GREG_xSP, X86_GREG_xSP, 0); /* -> [RSP/R12] */
-        pbCodeBuf[off++] = (uint8_t)offDisp;
-    }
-    else
-    {
-        pbCodeBuf[off++] = X86_MODRM_MAKE(X86_MOD_MEM1, iGprReg & 7, iGprBase & 7);
-        if ((iGprBase & 7) == X86_GREG_xSP) /* for RSP/R12 relative addressing we have to use a SIB byte. */
-            pbCodeBuf[off++] = X86_SIB_MAKE(X86_GREG_xSP, X86_GREG_xSP, 0); /* -> [RSP/R12] */
-        pbCodeBuf[off++] = RT_BYTE1((uint32_t)offDisp);
-        pbCodeBuf[off++] = RT_BYTE2((uint32_t)offDisp);
-        pbCodeBuf[off++] = RT_BYTE3((uint32_t)offDisp);
-        pbCodeBuf[off++] = RT_BYTE4((uint32_t)offDisp);
-    }
-    return off;
-}
-#elif defined(RT_ARCH_ARM64)
+#if defined(RT_ARCH_ARM64)
 /**
  * Common bit of iemNativeEmitLoadGprFromVCpuU64 and friends.
