Index: trunk/src/VBox/VMM/VMMAll/IEMAllCImpl.cpp
===================================================================
--- trunk/src/VBox/VMM/VMMAll/IEMAllCImpl.cpp	(revision 101275)
+++ trunk/src/VBox/VMM/VMMAll/IEMAllCImpl.cpp	(revision 101304)
@@ -9889,10 +9889,10 @@
  *
  * @param   iStReg              The other stack register.
- * @param   pfnAImpl            The assembly comparison implementation.
+ * @param   fUCmp               true for FUCOMI[P], false for FCOMI[P].
  * @param   uPopAndFpuOpcode    Bits 15-0: The FPU opcode.
  *                              Bit  31: Whether we should pop the stack when
  *                              done or not.
  */
-IEM_CIMPL_DEF_3(iemCImpl_fcomi_fucomi, uint8_t, iStReg, PFNIEMAIMPLFPUR80EFL, pfnAImpl, uint32_t, uPopAndFpuOpcode)
+IEM_CIMPL_DEF_3(iemCImpl_fcomi_fucomi, uint8_t, iStReg, bool, fUCmp, uint32_t, uPopAndFpuOpcode)
 {
     Assert(iStReg < 8);
@@ -9918,5 +9918,9 @@
     if ((pFpuCtx->FTW & (RT_BIT(iReg1) | RT_BIT(iReg2))) == (RT_BIT(iReg1) | RT_BIT(iReg2)))
     {
-        uint32_t u32Eflags = pfnAImpl(pFpuCtx, &u16Fsw, &pFpuCtx->aRegs[0].r80, &pFpuCtx->aRegs[iStReg].r80);
+        uint32_t u32Eflags;
+        if (!fUCmp)
+            u32Eflags = iemAImpl_fcomi_r80_by_r80(pFpuCtx, &u16Fsw, &pFpuCtx->aRegs[0].r80, &pFpuCtx->aRegs[iStReg].r80);
+        else
+            u32Eflags = iemAImpl_fucomi_r80_by_r80(pFpuCtx, &u16Fsw, &pFpuCtx->aRegs[0].r80, &pFpuCtx->aRegs[iStReg].r80);
 
         pFpuCtx->FSW &= ~X86_FSW_C1;
Index: trunk/src/VBox/VMM/VMMAll/IEMAllInstOneByte.cpp.h
===================================================================
--- trunk/src/VBox/VMM/VMMAll/IEMAllInstOneByte.cpp.h	(revision 101275)
+++ trunk/src/VBox/VMM/VMMAll/IEMAllInstOneByte.cpp.h	(revision 101304)
@@ -10538,5 +10538,5 @@
     IEMOP_MNEMONIC(fucomi_st0_stN, "fucomi st0,stN");
     IEM_MC_DEFER_TO_CIMPL_3_RET(IEM_CIMPL_F_FPU | IEM_CIMPL_F_STATUS_FLAGS,
-                                iemCImpl_fcomi_fucomi, IEM_GET_MODRM_RM_8(bRm), iemAImpl_fucomi_r80_by_r80,
+                                iemCImpl_fcomi_fucomi, IEM_GET_MODRM_RM_8(bRm), true /*fUCmp*/,
                                 0 /*fPop*/ | pVCpu->iem.s.uFpuOpcode);
 }
@@ -10548,5 +10548,5 @@
     IEMOP_MNEMONIC(fcomi_st0_stN, "fcomi st0,stN");
     IEM_MC_DEFER_TO_CIMPL_3_RET(IEM_CIMPL_F_FPU | IEM_CIMPL_F_STATUS_FLAGS,
-                                iemCImpl_fcomi_fucomi, IEM_GET_MODRM_RM_8(bRm), iemAImpl_fcomi_r80_by_r80,
+                                iemCImpl_fcomi_fucomi, IEM_GET_MODRM_RM_8(bRm), false /*fUCmp*/,
                                 false /*fPop*/ | pVCpu->iem.s.uFpuOpcode);
 }
@@ -11467,5 +11467,5 @@
     IEMOP_MNEMONIC(fucomip_st0_stN, "fucomip st0,stN");
     IEM_MC_DEFER_TO_CIMPL_3_RET(IEM_CIMPL_F_FPU | IEM_CIMPL_F_STATUS_FLAGS,
-                                iemCImpl_fcomi_fucomi, IEM_GET_MODRM_RM_8(bRm), iemAImpl_fcomi_r80_by_r80,
+                                iemCImpl_fcomi_fucomi, IEM_GET_MODRM_RM_8(bRm), false /*fUCmp*/,
                                 RT_BIT_32(31) /*fPop*/ | pVCpu->iem.s.uFpuOpcode);
 }
@@ -11477,5 +11477,5 @@
     IEMOP_MNEMONIC(fcomip_st0_stN, "fcomip st0,stN");
     IEM_MC_DEFER_TO_CIMPL_3_RET(IEM_CIMPL_F_FPU | IEM_CIMPL_F_STATUS_FLAGS,
-                                iemCImpl_fcomi_fucomi, IEM_GET_MODRM_RM_8(bRm), iemAImpl_fcomi_r80_by_r80,
+                                iemCImpl_fcomi_fucomi, IEM_GET_MODRM_RM_8(bRm), false /*fUCmp*/,
                                 RT_BIT_32(31) /*fPop*/ | pVCpu->iem.s.uFpuOpcode);
 }
Index: trunk/src/VBox/VMM/VMMAll/IEMAllN8vePython.py
===================================================================
--- trunk/src/VBox/VMM/VMMAll/IEMAllN8vePython.py	(revision 101275)
+++ trunk/src/VBox/VMM/VMMAll/IEMAllN8vePython.py	(revision 101304)
@@ -37,8 +37,9 @@
 __version__ = "$Revision$"
 
-# Standard python imports.
+# Standard python imports:
 #import sys;
 
-#import IEMAllInstPython as iai;
+# Out python imports:
+import IEMAllInstPython as iai;
 
 
@@ -47,4 +48,7 @@
     Class that deals with transforming a threaded function variation into a
     native recompiler function.
+
+    This base class doesn't do any transforming and just renders the same
+    code as for the threaded function.
     """
 
@@ -58,5 +62,5 @@
         (for the selected host architecture).
         """
-        return False;
+        return True;
 
     def renderCode(self, cchIndent):
@@ -64,5 +68,6 @@
         Returns the native recompiler function body for this threaded variant.
         """
-        return ' ' * cchIndent + '    AssertFailed();';
+        aoStmts = self.oVariation.aoStmtsForThreadedFunction # type: list(McStmt)
+        return iai.McStmt.renderCodeForList(aoStmts, cchIndent);
 
 
@@ -78,6 +83,15 @@
     """
 
-    _ = oVariation;
-    _ = sHostArch;
+    #
+    # Analyze the statements.
+    #
+    aoStmts = oVariation.aoStmtsForThreadedFunction # type: list(McStmt)
+
+    # The simplest case are the IEM_MC_DEFER_TO_CIMPL_*_RET_THREADED ones, just pass them thru:
+    if (    len(aoStmts) == 1
+        and aoStmts[0].sName.startswith('IEM_MC_DEFER_TO_CIMPL_')
+        and aoStmts[0].sName.endswith('_RET_THREADED')
+        and sHostArch in ('amd64',)):
+        return NativeRecompFunctionVariation(oVariation, sHostArch);
 
     return None;
Index: trunk/src/VBox/VMM/VMMAll/IEMAllN8veRecompiler.cpp
===================================================================
--- trunk/src/VBox/VMM/VMMAll/IEMAllN8veRecompiler.cpp	(revision 101275)
+++ trunk/src/VBox/VMM/VMMAll/IEMAllN8veRecompiler.cpp	(revision 101304)
@@ -1405,4 +1405,81 @@
 
 /**
+ * Emits a call to a CImpl function or something similar.
+ */
+static int32_t iemNativeEmitCImplCall(PIEMRECOMPILERSTATE pReNative, uint32_t off, uint8_t idxInstr,
+                                      uintptr_t pfnCImpl, uint8_t cbInstr, uint8_t cAddParams,
+                                      uint64_t uParam0, uint64_t uParam1, uint64_t uParam2)
+{
+#ifdef VBOX_STRICT
+    off = iemNativeEmitMarker(pReNative, off);
+    AssertReturn(off != UINT32_MAX, UINT32_MAX);
+#endif
+
+    /*
+     * Load the parameters.
+     */
+#if defined(RT_OS_WINDOWS) && defined(VBOXSTRICTRC_STRICT_ENABLED)
+    /* Special code the hidden VBOXSTRICTRC pointer. */
+    off = iemNativeEmitLoadGprFromGpr(  pReNative, off, IEMNATIVE_CALL_ARG1_GREG, IEMNATIVE_REG_FIXED_PVMCPU);
+    off = iemNativeEmitLoadGprImm64(    pReNative, off, IEMNATIVE_CALL_ARG2_GREG, cbInstr); /** @todo 8-bit reg load opt for amd64 */
+    if (cAddParams > 0)
+        off = iemNativeEmitLoadGprImm64(pReNative, off, IEMNATIVE_CALL_ARG3_GREG, uParam0);
+    if (cAddParams > 1)
+        off = iemNativeEmitStoreImm64ByBp(pReNative, off, IEMNATIVE_FP_OFF_STACK_ARG0, uParam1);
+    if (cAddParams > 2)
+        off = iemNativeEmitStoreImm64ByBp(pReNative, off, IEMNATIVE_FP_OFF_STACK_ARG1, uParam2);
+    off = iemNativeEmitLeaGrpByBp(pReNative, off, X86_GREG_xCX, IEMNATIVE_FP_OFF_IN_SHADOW_ARG0); /* rcStrict */
+
+#else
+    AssertCompile(IEMNATIVE_CALL_ARG_GREG_COUNT >= 4);
+    off = iemNativeEmitLoadGprFromGpr(  pReNative, off, IEMNATIVE_CALL_ARG0_GREG, IEMNATIVE_REG_FIXED_PVMCPU);
+    off = iemNativeEmitLoadGprImm64(    pReNative, off, IEMNATIVE_CALL_ARG1_GREG, cbInstr); /** @todo 8-bit reg load opt for amd64 */
+    if (cAddParams > 0)
+        off = iemNativeEmitLoadGprImm64(pReNative, off, IEMNATIVE_CALL_ARG2_GREG, uParam0);
+    if (cAddParams > 1)
+        off = iemNativeEmitLoadGprImm64(pReNative, off, IEMNATIVE_CALL_ARG3_GREG, uParam1);
+    if (cAddParams > 2)
+# if IEMNATIVE_CALL_ARG_GREG_COUNT >= 5
+        off = iemNativeEmitLoadGprImm64(pReNative, off, IEMNATIVE_CALL_ARG4_GREG, uParam2);
+# else
+        off = iemNativeEmitStoreImm64ByBp(pReNative, off, IEMNATIVE_FP_OFF_STACK_ARG0, uParam2);
+# endif
+#endif
+    AssertReturn(off != UINT32_MAX, off);
+
+    /*
+     * Make the call.
+     */
+#ifdef RT_ARCH_AMD64
+    off = iemNativeEmitLoadGprImm64(pReNative, off, X86_GREG_xAX, pfnCImpl);
+
+    uint8_t *pbCodeBuf = iemNativeInstrBufEnsure(pReNative, off, 2);
+    AssertReturn(pbCodeBuf, UINT32_MAX);
+    pbCodeBuf[off++] = 0xff;                    /* call rax */
+    pbCodeBuf[off++] = X86_MODRM_MAKE(X86_MOD_REG, 2, X86_GREG_xAX);
+
+# if defined(VBOXSTRICTRC_STRICT_ENABLED) && defined(RT_OS_WINDOWS)
+    off = iemNativeEmitLoadGprByBpU32(pReNative, off, X86_GREG_xAX, IEMNATIVE_FP_OFF_IN_SHADOW_ARG0); /* rcStrict (see above) */
+# endif
+
+#elif defined(RT_ARCH_ARM64)
+    off = iemNativeEmitLoadGprImm64(pReNative, off, IEMNATIVE_REG_FIXED_TMP0, pfnCImpl);
+
+    uint32_t *pu32CodeBuf = iemNativeInstrBufEnsure(pReNative, off, 1);
+    AssertReturn(pu32CodeBuf, UINT32_MAX);
+    pu32CodeBuf[off++] = Armv8A64MkInstrBlr(IEMNATIVE_REG_FIXED_TMP0);
+
+#else
+# error "Port me!"
+#endif
+
+    /*
+     * Check the status code.
+     */
+    return iemNativeEmitCheckCallRetAndPassUp(pReNative, off, idxInstr);
+}
+
+
+/**
  * Emits a call to a threaded worker function.
  */
@@ -1524,5 +1601,5 @@
 
 /**
- * Emits a standard epilog.
+ * Emits the RC fiddling code for handling non-zero return code or rcPassUp.
  */
 static uint32_t iemNativeEmitRcFiddling(PIEMRECOMPILERSTATE pReNative, uint32_t off, uint32_t idxReturnLabel)
@@ -1808,4 +1885,43 @@
 
 
+DECLINLINE(uint32_t) iemNativeEmitCImplCall1(PIEMRECOMPILERSTATE pReNative, uint32_t off, uint8_t idxInstr,
+                                             uintptr_t pfnCImpl, uint8_t cbInstr, uint64_t uArg0)
+{
+    return iemNativeEmitCImplCall(pReNative, off, idxInstr, pfnCImpl, cbInstr, 1, uArg0, 0, 0);
+}
+
+
+DECLINLINE(uint32_t) iemNativeEmitCImplCall2(PIEMRECOMPILERSTATE pReNative, uint32_t off, uint8_t idxInstr,
+                                             uintptr_t pfnCImpl, uint8_t cbInstr, uint64_t uArg0, uint64_t uArg1)
+{
+    return iemNativeEmitCImplCall(pReNative, off, idxInstr, pfnCImpl, cbInstr, 2, uArg0, uArg1, 0);
+}
+
+
+DECLINLINE(uint32_t) iemNativeEmitCImplCall3(PIEMRECOMPILERSTATE pReNative, uint32_t off, uint8_t idxInstr,
+                                             uintptr_t pfnCImpl, uint8_t cbInstr, uint64_t uArg0, uint64_t uArg1, uint64_t uArg2)
+{
+    return iemNativeEmitCImplCall(pReNative, off, idxInstr, pfnCImpl, cbInstr, 3, uArg0, uArg1, uArg2);
+}
+
+
+/*
+ * MC definitions for the native recompiler.
+ */
+
+#define IEM_MC_DEFER_TO_CIMPL_0_RET_THREADED(a_cbInstr, a_fFlags, a_pfnCImpl) \
+    return iemNativeEmitCImplCall0(pReNative, off, pCallEntry->idxInstr, (uintptr_t)a_pfnCImpl, a_cbInstr) /** @todo not used ... */
+
+#define IEM_MC_DEFER_TO_CIMPL_1_RET_THREADED(a_cbInstr, a_fFlags, a_pfnCImpl, a0) \
+    return iemNativeEmitCImplCall1(pReNative, off, pCallEntry->idxInstr, (uintptr_t)a_pfnCImpl, a_cbInstr, a0)
+
+#define IEM_MC_DEFER_TO_CIMPL_2_RET_THREADED(a_cbInstr, a_fFlags, a_pfnCImpl, a0, a1) \
+    return iemNativeEmitCImplCall2(pReNative, off, pCallEntry->idxInstr, (uintptr_t)a_pfnCImpl, a_cbInstr, a0, a1)
+
+#define IEM_MC_DEFER_TO_CIMPL_3_RET_THREADED(a_cbInstr, a_fFlags, a_pfnCImpl, a0, a1, a2) \
+    return iemNativeEmitCImplCall3(pReNative, off, pCallEntry->idxInstr, (uintptr_t)a_pfnCImpl, a_cbInstr, a0, a1, a2)
+
+
+
 /*
  * Include g_apfnIemNativeRecompileFunctions and associated functions.
Index: trunk/src/VBox/VMM/include/IEMInternal.h
===================================================================
--- trunk/src/VBox/VMM/include/IEMInternal.h	(revision 101275)
+++ trunk/src/VBox/VMM/include/IEMInternal.h	(revision 101304)
@@ -5092,5 +5092,5 @@
 IEM_CIMPL_PROTO_1(iemCImpl_fldcw, uint16_t, u16Fcw);
 IEM_CIMPL_PROTO_2(iemCImpl_fxch_underflow, uint8_t, iStReg, uint16_t, uFpuOpcode);
-IEM_CIMPL_PROTO_3(iemCImpl_fcomi_fucomi, uint8_t, iStReg, PFNIEMAIMPLFPUR80EFL, pfnAImpl, uint32_t, uPopAndFpuOpcode);
+IEM_CIMPL_PROTO_3(iemCImpl_fcomi_fucomi, uint8_t, iStReg, bool, fUCmp, uint32_t, uPopAndFpuOpcode);
 /** @} */
 
Index: trunk/src/VBox/VMM/include/IEMN8veRecompiler.h
===================================================================
--- trunk/src/VBox/VMM/include/IEMN8veRecompiler.h	(revision 101275)
+++ trunk/src/VBox/VMM/include/IEMN8veRecompiler.h	(revision 101304)
@@ -114,11 +114,13 @@
 /** @def IEMNATIVE_REG_FIXED_PVMCPU
  * The register number hold in pVCpu pointer.  */
+/** @def IEMNATIVE_REG_FIXED_TMP0
+ * Dedicated temporary register.
+ * @todo replace this by a register allocator and content tracker.  */
 #ifdef RT_ARCH_AMD64
 # define IEMNATIVE_REG_FIXED_PVMCPU         X86_GREG_xBX
+# define IEMNATIVE_REG_FIXED_TMP0           X86_GREG_x11
 
 #elif defined(RT_ARCH_ARM64)
 # define IEMNATIVE_REG_FIXED_PVMCPU         ARMV8_A64_REG_X28
-/** Dedicated temporary register.
- * @todo replace this by a register allocator and content tracker.  */
 # define IEMNATIVE_REG_FIXED_TMP0           ARMV8_A64_REG_X15
 
@@ -584,4 +586,5 @@
     /* mov gprdst, qword [rbp + offDisp]  */
     uint8_t *pbCodeBuf = iemNativeInstrBufEnsure(pReNative, off, 7);
+    AssertReturn(pbCodeBuf, UINT32_MAX);
     if (iGprDst < 8)
         pbCodeBuf[off++] = X86_OP_REX_W;
@@ -602,4 +605,5 @@
     /* mov gprdst, dword [rbp + offDisp]  */
     uint8_t *pbCodeBuf = iemNativeInstrBufEnsure(pReNative, off, 7);
+    AssertReturn(pbCodeBuf, UINT32_MAX);
     if (iGprDst >= 8)
         pbCodeBuf[off++] = X86_OP_REX_R;
@@ -618,4 +622,5 @@
     /* lea gprdst, [rbp + offDisp] */
     uint8_t *pbCodeBuf = iemNativeInstrBufEnsure(pReNative, off, 7);
+    AssertReturn(pbCodeBuf, UINT32_MAX);
     if (iGprDst < 8)
         pbCodeBuf[off++] = X86_OP_REX_W;
@@ -628,12 +633,15 @@
 
 
-#ifdef RT_ARCH_AMD64
 /**
  * Emits a 64-bit GPR store with an BP relative destination address.
+ *
+ * @note May trash IEMNATIVE_REG_FIXED_TMP0.
  */
 DECLINLINE(uint32_t) iemNativeEmitStoreGprByBp(PIEMRECOMPILERSTATE pReNative, uint32_t off, int32_t offDisp, uint8_t iGprSrc)
 {
+#ifdef RT_ARCH_AMD64
     /* mov qword [rbp + offDisp], gprdst */
     uint8_t *pbCodeBuf = iemNativeInstrBufEnsure(pReNative, off, 7);
+    AssertReturn(pbCodeBuf, UINT32_MAX);
     if (iGprSrc < 8)
         pbCodeBuf[off++] = X86_OP_REX_W;
@@ -642,6 +650,79 @@
     pbCodeBuf[off++] = 0x89;
     return iemNativeEmitGprByBpDisp(pbCodeBuf, off, iGprSrc, offDisp);
-}
-#endif
+
+#elif defined(RT_ARCH_ARM64)
+    if (offDisp >= 0 && offDisp < 4096 * 8 && !((uint32_t)offDisp & 7))
+    {
+        /* str w/ unsigned imm12 (scaled) */
+        uint32_t *pu32CodeBuf = iemNativeInstrBufEnsure(pReNative, off, 1);
+        AssertReturn(pu32CodeBuf, UINT32_MAX);
+        pu32CodeBuf[off++] = Armv8A64MkInstrStLdRUOff(kArmv8A64InstrLdStType_St_Dword, iGprSrc,
+                                                      ARMV8_A64_BP, (uint32_t)offDisp / 8);
+    }
+    else if (offDisp >= -256 offDisp <= 256)
+    {
+        /* stur w/ signed imm9 (unscaled) */
+        uint32_t *pu32CodeBuf = iemNativeInstrBufEnsure(pReNative, off, 1);
+        AssertReturn(pu32CodeBuf, UINT32_MAX);
+        pu32CodeBuf[off++] = Armv8A64MkInstrSturLdur(kArmv8A64InstrLdStType_St_Dword, iGprSrc, ARMV8_A64_BP, offDisp);
+    }
+    else
+    {
+        /* Use temporary indexing register. */
+        off = iemNativeEmitLoadGprImm64(pReNative, off, IEMNATIVE_REG_FIXED_TMP0, (uint32_t)offDisp);
+        uint32_t *pu32CodeBuf = iemNativeInstrBufEnsure(pReNative, off, 1);
+        AssertReturn(pu32CodeBuf, UINT32_MAX);
+        pu32CodeBuf[off++] = Armv8A64MkInstrStLdRegIdx(kArmv8A64InstrLdStType_St_Dword, iGprSrc, ARMV8_A64_BP,
+                                                       IEMNATIVE_REG_FIXDE_TMP0, kArmv8A64InstrLdStExtend_Sxtw);
+    }
+    return off;
+
+#else
+# error "Port me!"
+#endif
+}
+
+
+/**
+ * Emits a 64-bit immediate store with an BP relative destination address.
+ *
+ * @note May trash IEMNATIVE_REG_FIXED_TMP0.
+ */
+DECLINLINE(uint32_t) iemNativeEmitStoreImm64ByBp(PIEMRECOMPILERSTATE pReNative, uint32_t off, int32_t offDisp, uint64_t uImm64)
+{
+#ifdef RT_ARCH_AMD64
+    if ((int64_t)uImm64 == (int32_t)uImm64)
+    {
+        /* mov qword [rbp + offDisp], imm32 - sign extended */
+        uint8_t *pbCodeBuf = iemNativeInstrBufEnsure(pReNative, off, 11);
+        AssertReturn(pbCodeBuf, UINT32_MAX);
+
+        pbCodeBuf[off++] = X86_OP_REX_W;
+        pbCodeBuf[off++] = 0xc7;
+        if (offDisp < 128 && offDisp >= -128)
+        {
+            pbCodeBuf[off++] = X86_MODRM_MAKE(X86_MOD_MEM1, 0, X86_GREG_xBP);
+            pbCodeBuf[off++] = (uint8_t)offDisp;
+        }
+        else
+        {
+            pbCodeBuf[off++] = X86_MODRM_MAKE(X86_MOD_MEM4, 0, X86_GREG_xBP);
+            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);
+        }
+        pbCodeBuf[off++] = RT_BYTE1(uImm64);
+        pbCodeBuf[off++] = RT_BYTE2(uImm64);
+        pbCodeBuf[off++] = RT_BYTE3(uImm64);
+        pbCodeBuf[off++] = RT_BYTE4(uImm64);
+        return off;
+    }
+#endif
+
+    /* Load tmp0, imm64; Store tmp to bp+disp. */
+    off = iemNativeEmitLoadGprImm64(pReNative, off, IEMNATIVE_REG_FIXED_TMP0, uImm64);
+    return iemNativeEmitStoreGprByBp(pReNative, off, offDisp, IEMNATIVE_REG_FIXED_TMP0);
+}
 
 
@@ -654,4 +735,5 @@
     /* sub gprdst, imm8/imm32 */
     uint8_t *pbCodeBuf = iemNativeInstrBufEnsure(pReNative, off, 7);
+    AssertReturn(pbCodeBuf, UINT32_MAX);
     if (iGprDst < 7)
         pbCodeBuf[off++] = X86_OP_REX_W;
