Index: trunk/src/VBox/VMM/VMMAll/IEMAll.cpp
===================================================================
--- trunk/src/VBox/VMM/VMMAll/IEMAll.cpp	(revision 36814)
+++ trunk/src/VBox/VMM/VMMAll/IEMAll.cpp	(revision 36815)
@@ -3893,45 +3893,45 @@
 
 /**
- * Implements a 16-bit relative call.
- *
- *
- * @param   offDisp      The displacment offset.
- */
-IEM_CIMPL_DEF_1(iemCImpl_call_rel_16, int16_t, offDisp)
-{
-    PCPUMCTX pCtx  = pIemCpu->CTX_SUFF(pCtx);
-    uint16_t OldPC = pCtx->ip + cbInstr;
-    uint16_t NewPC = OldPC + offDisp;
-    if (NewPC > pCtx->csHid.u32Limit)
+ * Implements an indirect call.
+ *
+ * @param   uNewPC          The new program counter (RIP) value (loaded from the
+ *                          operand).
+ * @param   enmEffOpSize    The effective operand size.
+ */
+IEM_CIMPL_DEF_1(iemCImpl_call_16, uint16_t, uNewPC)
+{
+    PCPUMCTX pCtx   = pIemCpu->CTX_SUFF(pCtx);
+    uint16_t uOldPC = pCtx->ip + cbInstr;
+    if (uNewPC > pCtx->csHid.u32Limit)
         return iemRaiseGeneralProtectionFault0(pIemCpu);
 
-    VBOXSTRICTRC rcStrict = iemMemStackPushU16(pIemCpu, OldPC);
+    VBOXSTRICTRC rcStrict = iemMemStackPushU16(pIemCpu, uOldPC);
     if (rcStrict != VINF_SUCCESS)
         return rcStrict;
 
-    pCtx->rip = NewPC;
+    pCtx->rip = uNewPC;
     return VINF_SUCCESS;
-}
-
-
-/**
- * Implements a 32-bit relative call.
- *
+
+}
+
+
+/**
+ * Implements a 16-bit relative call.
  *
  * @param   offDisp      The displacment offset.
  */
-IEM_CIMPL_DEF_1(iemCImpl_call_rel_32, int32_t, offDisp)
-{
-    PCPUMCTX pCtx  = pIemCpu->CTX_SUFF(pCtx);
-    uint32_t OldPC = pCtx->eip + cbInstr;
-    uint32_t NewPC = OldPC + offDisp;
-    if (NewPC > pCtx->csHid.u32Limit)
+IEM_CIMPL_DEF_1(iemCImpl_call_rel_16, int16_t, offDisp)
+{
+    PCPUMCTX pCtx   = pIemCpu->CTX_SUFF(pCtx);
+    uint16_t uOldPC = pCtx->ip + cbInstr;
+    uint16_t uNewPC = uOldPC + offDisp;
+    if (uNewPC > pCtx->csHid.u32Limit)
         return iemRaiseGeneralProtectionFault0(pIemCpu);
 
-    VBOXSTRICTRC rcStrict = iemMemStackPushU32(pIemCpu, OldPC);
+    VBOXSTRICTRC rcStrict = iemMemStackPushU16(pIemCpu, uOldPC);
     if (rcStrict != VINF_SUCCESS)
         return rcStrict;
 
-    pCtx->rip = NewPC;
+    pCtx->rip = uNewPC;
     return VINF_SUCCESS;
 }
@@ -3939,22 +3939,91 @@
 
 /**
- * Implements a 64-bit relative call.
- *
- *
- * @param   offDisp      The displacment offset.
- */
-IEM_CIMPL_DEF_1(iemCImpl_call_rel_64, int64_t, offDisp)
-{
-    PCPUMCTX pCtx  = pIemCpu->CTX_SUFF(pCtx);
-    uint64_t OldPC = pCtx->rip + cbInstr;
-    uint64_t NewPC = OldPC + offDisp;
-    if (!IEM_IS_CANONICAL(NewPC))
-        return iemRaiseNotCanonical(pIemCpu);
-
-    VBOXSTRICTRC rcStrict = iemMemStackPushU64(pIemCpu, OldPC);
+ * Implements a 32-bit indirect call.
+ *
+ * @param   uNewPC          The new program counter (RIP) value (loaded from the
+ *                          operand).
+ * @param   enmEffOpSize    The effective operand size.
+ */
+IEM_CIMPL_DEF_1(iemCImpl_call_32, uint32_t, uNewPC)
+{
+    PCPUMCTX pCtx   = pIemCpu->CTX_SUFF(pCtx);
+    uint32_t uOldPC = pCtx->eip + cbInstr;
+    if (uNewPC > pCtx->csHid.u32Limit)
+        return iemRaiseGeneralProtectionFault0(pIemCpu);
+
+    VBOXSTRICTRC rcStrict = iemMemStackPushU32(pIemCpu, uOldPC);
     if (rcStrict != VINF_SUCCESS)
         return rcStrict;
 
-    pCtx->rip = NewPC;
+    pCtx->rip = uNewPC;
+    return VINF_SUCCESS;
+
+}
+
+
+/**
+ * Implements a 32-bit relative call.
+ *
+ * @param   offDisp      The displacment offset.
+ */
+IEM_CIMPL_DEF_1(iemCImpl_call_rel_32, int32_t, offDisp)
+{
+    PCPUMCTX pCtx   = pIemCpu->CTX_SUFF(pCtx);
+    uint32_t uOldPC = pCtx->eip + cbInstr;
+    uint32_t uNewPC = uOldPC + offDisp;
+    if (uNewPC > pCtx->csHid.u32Limit)
+        return iemRaiseGeneralProtectionFault0(pIemCpu);
+
+    VBOXSTRICTRC rcStrict = iemMemStackPushU32(pIemCpu, uOldPC);
+    if (rcStrict != VINF_SUCCESS)
+        return rcStrict;
+
+    pCtx->rip = uNewPC;
+    return VINF_SUCCESS;
+}
+
+
+/**
+ * Implements a 64-bit indirect call.
+ *
+ * @param   uNewPC          The new program counter (RIP) value (loaded from the
+ *                          operand).
+ * @param   enmEffOpSize    The effective operand size.
+ */
+IEM_CIMPL_DEF_1(iemCImpl_call_64, uint64_t, uNewPC)
+{
+    PCPUMCTX pCtx   = pIemCpu->CTX_SUFF(pCtx);
+    uint64_t uOldPC = pCtx->rip + cbInstr;
+    if (!IEM_IS_CANONICAL(uNewPC))
+        return iemRaiseGeneralProtectionFault0(pIemCpu);
+
+    VBOXSTRICTRC rcStrict = iemMemStackPushU64(pIemCpu, uOldPC);
+    if (rcStrict != VINF_SUCCESS)
+        return rcStrict;
+
+    pCtx->rip = uNewPC;
+    return VINF_SUCCESS;
+
+}
+
+
+/**
+ * Implements a 64-bit relative call.
+ *
+ * @param   offDisp      The displacment offset.
+ */
+IEM_CIMPL_DEF_1(iemCImpl_call_rel_64, int64_t, offDisp)
+{
+    PCPUMCTX pCtx   = pIemCpu->CTX_SUFF(pCtx);
+    uint64_t uOldPC = pCtx->rip + cbInstr;
+    uint64_t uNewPC = uOldPC + offDisp;
+    if (!IEM_IS_CANONICAL(uNewPC))
+        return iemRaiseNotCanonical(pIemCpu);
+
+    VBOXSTRICTRC rcStrict = iemMemStackPushU64(pIemCpu, uOldPC);
+    if (rcStrict != VINF_SUCCESS)
+        return rcStrict;
+
+    pCtx->rip = uNewPC;
     return VINF_SUCCESS;
 }
@@ -4526,5 +4595,5 @@
     PCPUMSELREGHID  pHid = iemSRegGetHid(pIemCpu, iSegReg);
 
-    Assert(iSegReg < X86_SREG_GS && iSegReg != X86_SREG_CS);
+    Assert(iSegReg <= X86_SREG_GS && iSegReg != X86_SREG_CS);
 
     /*
Index: trunk/src/VBox/VMM/VMMAll/IEMAllAImpl.asm
===================================================================
--- trunk/src/VBox/VMM/VMMAll/IEMAllAImpl.asm	(revision 36814)
+++ trunk/src/VBox/VMM/VMMAll/IEMAllAImpl.asm	(revision 36815)
@@ -374,4 +374,51 @@
 
 
+;
+; XCHG for memory operands.  This implies locking.  No flag changes.
+;
+; Each function takes two arguments, first the pointer to the memory,
+; then the pointer to the register.  They all return void.
+;
+BEGINPROC iemAImpl_xchg_u8
+        PROLOGUE_2_ARGS
+        mov     T0_8, [A1]
+        xchg    [A0], T0_8
+        mov     [A1], T0_8
+        EPILOGUE_2_ARGS
+        ret
+ENDPROC iemAImpl_xchg_u8
+
+BEGINPROC iemAImpl_xchg_u16
+        PROLOGUE_2_ARGS
+        mov     T0_16, [A1]
+        xchg    [A0], T0_16
+        mov     [A1], T0_16
+        EPILOGUE_2_ARGS
+        ret
+ENDPROC iemAImpl_xchg_u16
+
+BEGINPROC iemAImpl_xchg_u32
+        PROLOGUE_2_ARGS
+        mov     T0_32, [A1]
+        xchg    [A0], T0_32
+        mov     [A1], T0_32
+        EPILOGUE_2_ARGS
+        ret
+ENDPROC iemAImpl_xchg_u32
+
+BEGINPROC iemAImpl_xchg_u64
+%ifdef RT_ARCH_AMD64
+        PROLOGUE_2_ARGS
+        mov     T0, [A1]
+        xchg    [A0], T0
+        mov     [A1], T0
+        EPILOGUE_2_ARGS
+        ret
+%else
+        int3
+%endif
+ENDPROC iemAImpl_xchg_u64
+
+
 ;;
 ; Macro for implementing a unary operator.
Index: trunk/src/VBox/VMM/VMMAll/IEMAllInstructions.cpp.h
===================================================================
--- trunk/src/VBox/VMM/VMMAll/IEMAllInstructions.cpp.h	(revision 36814)
+++ trunk/src/VBox/VMM/VMMAll/IEMAllInstructions.cpp.h	(revision 36815)
@@ -1894,5 +1894,70 @@
 
 /** Opcode 0x0f 0xb7. */
-FNIEMOP_STUB(iemOp_movzx_Gv_Ew);
+FNIEMOP_DEF(iemOp_movzx_Gv_Ew)
+{
+    IEMOP_MNEMONIC("movzx Gv,Ew");
+
+    uint8_t bRm; IEM_OPCODE_GET_NEXT_BYTE(pIemCpu, &bRm);
+    IEMOP_HLP_NO_LOCK_PREFIX(); /** @todo should probably not be raised until we've fetched all the opcode bytes? */
+
+    /** @todo Not entirely sure how the operand size prefix is handled here,
+     *        assuming that it will be ignored. Would be nice to have a few
+     *        test for this. */
+    /*
+     * If rm is denoting a register, no more instruction bytes.
+     */
+    if ((bRm & X86_MODRM_MOD_MASK) == (3 << X86_MODRM_MOD_SHIFT))
+    {
+        if (pIemCpu->enmEffOpSize != IEMMODE_64BIT)
+        {
+            IEM_MC_BEGIN(0, 1);
+            IEM_MC_LOCAL(uint32_t, u32Value);
+            IEM_MC_FETCH_GREG_U16_ZX_U32(u32Value, (bRm & X86_MODRM_RM_MASK) | pIemCpu->uRexB);
+            IEM_MC_STORE_GREG_U32(((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pIemCpu->uRexReg, u32Value);
+            IEM_MC_ADVANCE_RIP();
+            IEM_MC_END();
+        }
+        else
+        {
+            IEM_MC_BEGIN(0, 1);
+            IEM_MC_LOCAL(uint64_t, u64Value);
+            IEM_MC_FETCH_GREG_U16_ZX_U64(u64Value, (bRm & X86_MODRM_RM_MASK) | pIemCpu->uRexB);
+            IEM_MC_STORE_GREG_U64(((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pIemCpu->uRexReg, u64Value);
+            IEM_MC_ADVANCE_RIP();
+            IEM_MC_END();
+        }
+    }
+    else
+    {
+        /*
+         * We're loading a register from memory.
+         */
+        if (pIemCpu->enmEffOpSize != IEMMODE_64BIT)
+        {
+            IEM_MC_BEGIN(0, 2);
+            IEM_MC_LOCAL(uint32_t, u32Value);
+            IEM_MC_LOCAL(RTGCPTR, GCPtrEffDst);
+            IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffDst, bRm);
+            IEM_MC_FETCH_MEM_U16_ZX_U32(u32Value, pIemCpu->iEffSeg, GCPtrEffDst);
+            IEM_MC_STORE_GREG_U32(((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pIemCpu->uRexReg, u32Value);
+            IEM_MC_ADVANCE_RIP();
+            IEM_MC_END();
+        }
+        else
+        {
+            IEM_MC_BEGIN(0, 2);
+            IEM_MC_LOCAL(uint64_t, u64Value);
+            IEM_MC_LOCAL(RTGCPTR, GCPtrEffDst);
+            IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffDst, bRm);
+            IEM_MC_FETCH_MEM_U16_ZX_U64(u64Value, pIemCpu->iEffSeg, GCPtrEffDst);
+            IEM_MC_STORE_GREG_U64(((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pIemCpu->uRexReg, u64Value);
+            IEM_MC_ADVANCE_RIP();
+            IEM_MC_END();
+        }
+    }
+    return VINF_SUCCESS;
+}
+
+
 /** Opcode 0x0f 0xb8. */
 FNIEMOP_STUB(iemOp_popcnt_Gv_Ev_jmpe);
@@ -4706,7 +4771,170 @@
 
 /** Opcode 0x86. */
-FNIEMOP_STUB(iemOp_xchg_Eb_Gb);
+FNIEMOP_DEF(iemOp_xchg_Eb_Gb)
+{
+    uint8_t bRm; IEM_OPCODE_GET_NEXT_BYTE(pIemCpu, &bRm);
+    IEMOP_MNEMONIC("xchg Eb,Gb");
+
+    /*
+     * If rm is denoting a register, no more instruction bytes.
+     */
+    if ((bRm & X86_MODRM_MOD_MASK) == (3 << X86_MODRM_MOD_SHIFT))
+    {
+        IEMOP_HLP_NO_LOCK_PREFIX();
+
+        IEM_MC_BEGIN(0, 2);
+        IEM_MC_LOCAL(uint8_t, uTmp1);
+        IEM_MC_LOCAL(uint8_t, uTmp2);
+
+        IEM_MC_FETCH_GREG_U8(uTmp1, ((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pIemCpu->uRexReg);
+        IEM_MC_FETCH_GREG_U8(uTmp2, (bRm & X86_MODRM_RM_MASK) | pIemCpu->uRexB);
+        IEM_MC_STORE_GREG_U8((bRm & X86_MODRM_RM_MASK) | pIemCpu->uRexB,                              uTmp1);
+        IEM_MC_STORE_GREG_U8(((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pIemCpu->uRexReg, uTmp2);
+
+        IEM_MC_ADVANCE_RIP();
+        IEM_MC_END();
+    }
+    else
+    {
+        /*
+         * We're accessing memory.
+         */
+        IEM_MC_BEGIN(2, 2);
+        IEM_MC_ARG(uint8_t *,  pu8Mem,           0);
+        IEM_MC_ARG(uint8_t *,  pu8Reg,           1);
+        IEM_MC_LOCAL(RTGCPTR, GCPtrEffDst);
+
+        IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffDst, bRm);
+        IEM_MC_MEM_MAP(pu8Mem, IEM_ACCESS_DATA_RW, pIemCpu->iEffSeg, GCPtrEffDst, 0 /*arg*/);
+        IEM_MC_REF_GREG_U8(pu8Reg, ((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pIemCpu->uRexReg);
+        IEM_MC_CALL_VOID_AIMPL_2(iemAImpl_xchg_u8, pu8Mem, pu8Reg);
+        IEM_MC_MEM_COMMIT_AND_UNMAP(pu8Mem, IEM_ACCESS_DATA_RW);
+
+        IEM_MC_ADVANCE_RIP();
+        IEM_MC_END();
+    }
+    return VINF_SUCCESS;
+}
+
+
 /** Opcode 0x87. */
-FNIEMOP_STUB(iemOp_xchg_Ev_Gv);
+FNIEMOP_DEF(iemOp_xchg_Ev_Gv)
+{
+    IEMOP_MNEMONIC("xchg Ev,Gv");
+    uint8_t bRm; IEM_OPCODE_GET_NEXT_BYTE(pIemCpu, &bRm);
+
+    /*
+     * If rm is denoting a register, no more instruction bytes.
+     */
+    if ((bRm & X86_MODRM_MOD_MASK) == (3 << X86_MODRM_MOD_SHIFT))
+    {
+        IEMOP_HLP_NO_LOCK_PREFIX();
+
+        switch (pIemCpu->enmEffOpSize)
+        {
+            case IEMMODE_16BIT:
+                IEM_MC_BEGIN(0, 2);
+                IEM_MC_LOCAL(uint16_t, uTmp1);
+                IEM_MC_LOCAL(uint16_t, uTmp2);
+
+                IEM_MC_FETCH_GREG_U16(uTmp1, ((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pIemCpu->uRexReg);
+                IEM_MC_FETCH_GREG_U16(uTmp2, (bRm & X86_MODRM_RM_MASK) | pIemCpu->uRexB);
+                IEM_MC_STORE_GREG_U16((bRm & X86_MODRM_RM_MASK) | pIemCpu->uRexB,                              uTmp1);
+                IEM_MC_STORE_GREG_U16(((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pIemCpu->uRexReg, uTmp2);
+
+                IEM_MC_ADVANCE_RIP();
+                IEM_MC_END();
+                return VINF_SUCCESS;
+
+            case IEMMODE_32BIT:
+                IEM_MC_BEGIN(0, 2);
+                IEM_MC_LOCAL(uint32_t, uTmp1);
+                IEM_MC_LOCAL(uint32_t, uTmp2);
+
+                IEM_MC_FETCH_GREG_U32(uTmp1, ((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pIemCpu->uRexReg);
+                IEM_MC_FETCH_GREG_U32(uTmp2, (bRm & X86_MODRM_RM_MASK) | pIemCpu->uRexB);
+                IEM_MC_STORE_GREG_U32((bRm & X86_MODRM_RM_MASK) | pIemCpu->uRexB,                              uTmp1);
+                IEM_MC_STORE_GREG_U32(((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pIemCpu->uRexReg, uTmp2);
+
+                IEM_MC_ADVANCE_RIP();
+                IEM_MC_END();
+                return VINF_SUCCESS;
+
+            case IEMMODE_64BIT:
+                IEM_MC_BEGIN(0, 2);
+                IEM_MC_LOCAL(uint64_t, uTmp1);
+                IEM_MC_LOCAL(uint64_t, uTmp2);
+
+                IEM_MC_FETCH_GREG_U64(uTmp1, ((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pIemCpu->uRexReg);
+                IEM_MC_FETCH_GREG_U64(uTmp2, (bRm & X86_MODRM_RM_MASK) | pIemCpu->uRexB);
+                IEM_MC_STORE_GREG_U64((bRm & X86_MODRM_RM_MASK) | pIemCpu->uRexB,                              uTmp1);
+                IEM_MC_STORE_GREG_U64(((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pIemCpu->uRexReg, uTmp2);
+
+                IEM_MC_ADVANCE_RIP();
+                IEM_MC_END();
+                return VINF_SUCCESS;
+
+            IEM_NOT_REACHED_DEFAULT_CASE_RET();
+        }
+    }
+    else
+    {
+        /*
+         * We're accessing memory.
+         */
+        switch (pIemCpu->enmEffOpSize)
+        {
+            case IEMMODE_16BIT:
+                IEM_MC_BEGIN(2, 2);
+                IEM_MC_ARG(uint16_t *,  pu16Mem, 0);
+                IEM_MC_ARG(uint16_t *,  pu16Reg, 1);
+                IEM_MC_LOCAL(RTGCPTR, GCPtrEffDst);
+
+                IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffDst, bRm);
+                IEM_MC_MEM_MAP(pu16Mem, IEM_ACCESS_DATA_RW, pIemCpu->iEffSeg, GCPtrEffDst, 0 /*arg*/);
+                IEM_MC_REF_GREG_U16(pu16Reg, ((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pIemCpu->uRexReg);
+                IEM_MC_CALL_VOID_AIMPL_2(iemAImpl_xchg_u16, pu16Mem, pu16Reg);
+                IEM_MC_MEM_COMMIT_AND_UNMAP(pu16Mem, IEM_ACCESS_DATA_RW);
+
+                IEM_MC_ADVANCE_RIP();
+                IEM_MC_END();
+                return VINF_SUCCESS;
+
+            case IEMMODE_32BIT:
+                IEM_MC_BEGIN(2, 2);
+                IEM_MC_ARG(uint32_t *,  pu32Mem, 0);
+                IEM_MC_ARG(uint32_t *,  pu32Reg, 1);
+                IEM_MC_LOCAL(RTGCPTR, GCPtrEffDst);
+
+                IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffDst, bRm);
+                IEM_MC_MEM_MAP(pu32Mem, IEM_ACCESS_DATA_RW, pIemCpu->iEffSeg, GCPtrEffDst, 0 /*arg*/);
+                IEM_MC_REF_GREG_U32(pu32Reg, ((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pIemCpu->uRexReg);
+                IEM_MC_CALL_VOID_AIMPL_2(iemAImpl_xchg_u32, pu32Mem, pu32Reg);
+                IEM_MC_MEM_COMMIT_AND_UNMAP(pu32Mem, IEM_ACCESS_DATA_RW);
+
+                IEM_MC_ADVANCE_RIP();
+                IEM_MC_END();
+                return VINF_SUCCESS;
+
+            case IEMMODE_64BIT:
+                IEM_MC_BEGIN(2, 2);
+                IEM_MC_ARG(uint64_t *,  pu64Mem, 0);
+                IEM_MC_ARG(uint64_t *,  pu64Reg, 1);
+                IEM_MC_LOCAL(RTGCPTR, GCPtrEffDst);
+
+                IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffDst, bRm);
+                IEM_MC_MEM_MAP(pu64Mem, IEM_ACCESS_DATA_RW, pIemCpu->iEffSeg, GCPtrEffDst, 0 /*arg*/);
+                IEM_MC_REF_GREG_U64(pu64Reg, ((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pIemCpu->uRexReg);
+                IEM_MC_CALL_VOID_AIMPL_2(iemAImpl_xchg_u64, pu64Mem, pu64Reg);
+                IEM_MC_MEM_COMMIT_AND_UNMAP(pu64Mem, IEM_ACCESS_DATA_RW);
+
+                IEM_MC_ADVANCE_RIP();
+                IEM_MC_END();
+                return VINF_SUCCESS;
+
+            IEM_NOT_REACHED_DEFAULT_CASE_RET();
+        }
+    }
+}
 
 
@@ -7241,6 +7469,6 @@
             return IEM_MC_DEFER_TO_CIMPL_1(iemCImpl_call_rel_64, u64Imm);
         }
-        default:
-            AssertFailedReturn(VERR_INTERNAL_ERROR_3);
+
+        IEM_NOT_REACHED_DEFAULT_CASE_RET();
     }
 }
@@ -8094,6 +8322,78 @@
 FNIEMOP_DEF_1(iemOp_Grp5_calln_Ev, uint8_t, bRm)
 {
-    AssertFailed(); // FNIEMOP_STUB
-    return VERR_NOT_IMPLEMENTED;
+    IEMOP_MNEMONIC("calln Ev");
+    IEMOP_HLP_NO_LOCK_PREFIX(); /** @todo Too early? */
+    IEMOP_HLP_DEFAULT_64BIT_OP_SIZE();
+
+    if ((bRm & X86_MODRM_MOD_MASK) == (3 << X86_MODRM_MOD_SHIFT))
+    {
+        /* The new RIP is taken from a register. */
+        switch (pIemCpu->enmEffOpSize)
+        {
+            case IEMMODE_16BIT:
+                IEM_MC_BEGIN(1, 0);
+                IEM_MC_ARG(uint16_t, u16Target, 0);
+                IEM_MC_FETCH_GREG_U16(u16Target, (bRm & X86_MODRM_RM_MASK) | pIemCpu->uRexB);
+                IEM_MC_CALL_CIMPL_1(iemCImpl_call_16, u16Target);
+                IEM_MC_END()
+                return VINF_SUCCESS;
+
+            case IEMMODE_32BIT:
+                IEM_MC_BEGIN(1, 0);
+                IEM_MC_ARG(uint32_t, u32Target, 0);
+                IEM_MC_FETCH_GREG_U32(u32Target, (bRm & X86_MODRM_RM_MASK) | pIemCpu->uRexB);
+                IEM_MC_CALL_CIMPL_1(iemCImpl_call_32, u32Target);
+                IEM_MC_END()
+                return VINF_SUCCESS;
+
+            case IEMMODE_64BIT:
+                IEM_MC_BEGIN(1, 0);
+                IEM_MC_ARG(uint64_t, u64Target, 0);
+                IEM_MC_FETCH_GREG_U64(u64Target, (bRm & X86_MODRM_RM_MASK) | pIemCpu->uRexB);
+                IEM_MC_CALL_CIMPL_1(iemCImpl_call_64, u64Target);
+                IEM_MC_END()
+                return VINF_SUCCESS;
+
+            IEM_NOT_REACHED_DEFAULT_CASE_RET();
+        }
+    }
+    else
+    {
+        /* The new RIP is taken from a register. */
+        switch (pIemCpu->enmEffOpSize)
+        {
+            case IEMMODE_16BIT:
+                IEM_MC_BEGIN(1, 1);
+                IEM_MC_ARG(uint16_t,  u16Target, 0);
+                IEM_MC_LOCAL(RTGCPTR, GCPtrEffSrc);
+                IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, bRm);
+                IEM_MC_FETCH_MEM_U16(u16Target, pIemCpu->iEffSeg, GCPtrEffSrc);
+                IEM_MC_CALL_CIMPL_1(iemCImpl_call_16, u16Target);
+                IEM_MC_END()
+                return VINF_SUCCESS;
+
+            case IEMMODE_32BIT:
+                IEM_MC_BEGIN(1, 1);
+                IEM_MC_ARG(uint32_t,  u32Target, 0);
+                IEM_MC_LOCAL(RTGCPTR, GCPtrEffSrc);
+                IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, bRm);
+                IEM_MC_FETCH_MEM_U32(u32Target, pIemCpu->iEffSeg, GCPtrEffSrc);
+                IEM_MC_CALL_CIMPL_1(iemCImpl_call_32, u32Target);
+                IEM_MC_END()
+                return VINF_SUCCESS;
+
+            case IEMMODE_64BIT:
+                IEM_MC_BEGIN(1, 1);
+                IEM_MC_ARG(uint64_t,  u64Target, 0);
+                IEM_MC_LOCAL(RTGCPTR, GCPtrEffSrc);
+                IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, bRm);
+                IEM_MC_FETCH_MEM_U64(u64Target, pIemCpu->iEffSeg, GCPtrEffSrc);
+                IEM_MC_CALL_CIMPL_1(iemCImpl_call_64, u64Target);
+                IEM_MC_END()
+                return VINF_SUCCESS;
+
+            IEM_NOT_REACHED_DEFAULT_CASE_RET();
+        }
+    }
 }
 
@@ -8258,5 +8558,4 @@
             IEM_NOT_REACHED_DEFAULT_CASE_RET();
         }
-
     }
 }
Index: trunk/src/VBox/VMM/include/IEMInternal.h
===================================================================
--- trunk/src/VBox/VMM/include/IEMInternal.h	(revision 36814)
+++ trunk/src/VBox/VMM/include/IEMInternal.h	(revision 36815)
@@ -443,4 +443,12 @@
 /** @}  */
 
+/** @name Exchange memory with register operations.
+ * @{ */
+IEM_DECL_IMPL_DEF(void, iemAImpl_xchg_u8, (uint8_t  *pu8Mem,  uint8_t  *pu8Reg));
+IEM_DECL_IMPL_DEF(void, iemAImpl_xchg_u16,(uint16_t *pu16Mem, uint16_t *pu16Reg));
+IEM_DECL_IMPL_DEF(void, iemAImpl_xchg_u32,(uint32_t *pu32Mem, uint32_t *pu32Reg));
+IEM_DECL_IMPL_DEF(void, iemAImpl_xchg_u64,(uint64_t *pu64Mem, uint64_t *pu64Reg));
+/** @}  */
+
 /** @name Signed multiplication operations (thrown in with the binary ops).
  * @{ */
