Index: /trunk/include/VBox/dis.h
===================================================================
--- /trunk/include/VBox/dis.h	(revision 41785)
+++ /trunk/include/VBox/dis.h	(revision 41786)
@@ -520,6 +520,7 @@
 
 /** Parser callback.
- * @remark no DECLCALLBACK() here because it's considered to be internal (really, I'm too lazy to update all the functions). */
-typedef unsigned FNDISPARSE(RTUINTPTR pu8CodeBlock, PCDISOPCODE pOp, PDISOPPARAM pParam, PDISCPUSTATE pCpu);
+ * @remark no DECLCALLBACK() here because it's considered to be internal and
+ *         there is no point in enforcing CDECL. */
+typedef size_t FNDISPARSE(size_t offInstr, PCDISOPCODE pOp, PDISOPPARAM pParam, PDISCPUSTATE pCpu);
 /** Pointer to a disassembler parser function. */
 typedef FNDISPARSE *PFNDISPARSE;
@@ -657,4 +658,8 @@
                        PFNDISREADBYTES pfnReadBytes, void *pvUser,
                        PDISCPUSTATE pCpu, uint32_t *pcbInstr);
+DISDECL(int) DISInstWithPrefetchedBytes(RTUINTPTR uInstrAddr, DISCPUMODE enmCpuMode, uint32_t fFilter,
+                                        void const *pvPrefetched, size_t cbPretched,
+                                        PFNDISREADBYTES pfnReadBytes, void *pvUser,
+                                        PDISCPUSTATE pCpu, uint32_t *pcbInstr);
 
 DISDECL(int)        DISGetParamSize(PDISCPUSTATE pCpu, PDISOPPARAM pParam);
Index: /trunk/src/VBox/Disassembler/DisasmCore.cpp
===================================================================
--- /trunk/src/VBox/Disassembler/DisasmCore.cpp	(revision 41785)
+++ /trunk/src/VBox/Disassembler/DisasmCore.cpp	(revision 41786)
@@ -2642,4 +2642,101 @@
 
 /**
+ * Inlined worker that initializes the disassembler state.
+ *
+ * @returns The primary opcode map to use.
+ * @param   pCpu            The disassembler state.
+ * @param   uInstrAddr      The instruction address.
+ * @param   enmCpuMode      The CPU mode.
+ * @param   fFilter         The instruction filter settings.
+ * @param   pfnReadBytes    The byte reader, can be NULL.
+ * @param   pvUser          The the user data for the reader.
+ */
+DECL_FORCE_INLINE(PCDISOPCODE)
+disInitializeState(PDISCPUSTATE pCpu, RTUINTPTR uInstrAddr, DISCPUMODE enmCpuMode, uint32_t fFilter,
+                   PFNDISREADBYTES pfnReadBytes, void *pvUser)
+{
+
+    /*
+     * Initialize the CPU state.
+     * Note! The RT_BZERO make ASSUMPTIONS about the placement of pvUser2.
+     */
+    RT_BZERO(pCpu, RT_OFFSETOF(DISCPUSTATE, pvUser2));
+
+#ifdef VBOX_STRICT /* poison */
+    pCpu->Param1.Base.idxGenReg  = 0xc1;
+    pCpu->Param2.Base.idxGenReg  = 0xc2;
+    pCpu->Param3.Base.idxGenReg  = 0xc3;
+    pCpu->Param1.Index.idxGenReg = 0xc4;
+    pCpu->Param2.Index.idxGenReg = 0xc5;
+    pCpu->Param3.Index.idxGenReg = 0xc6;
+    pCpu->Param1.uDisp.u64 = UINT64_C(0xd1d1d1d1d1d1d1d1);
+    pCpu->Param2.uDisp.u64 = UINT64_C(0xd2d2d2d2d2d2d2d2);
+    pCpu->Param3.uDisp.u64 = UINT64_C(0xd3d3d3d3d3d3d3d3);
+    pCpu->Param1.uValue    = UINT64_C(0xb1b1b1b1b1b1b1b1);
+    pCpu->Param2.uValue    = UINT64_C(0xb2b2b2b2b2b2b2b2);
+    pCpu->Param3.uValue    = UINT64_C(0xb3b3b3b3b3b3b3b3);
+    pCpu->Param1.uScale    = 28;
+    pCpu->Param2.uScale    = 29;
+    pCpu->Param3.uScale    = 30;
+#endif
+
+    pCpu->fPrefix           = DISPREFIX_NONE;
+    pCpu->idxSegPrefix      = DISSELREG_DS;
+    pCpu->rc                = VINF_SUCCESS;
+    pCpu->pfnDisasmFnTable  = g_apfnFullDisasm;
+
+    pCpu->uInstrAddr        = uInstrAddr;
+    pCpu->fFilter           = fFilter;
+    pCpu->pfnReadBytes      = pfnReadBytes ? pfnReadBytes : disReadBytesDefault;
+    pCpu->pvUser            = pvUser;
+    pCpu->uCpuMode          = enmCpuMode;
+    PCDISOPCODE paOneByteMap;
+    if (enmCpuMode == DISCPUMODE_64BIT)
+    {
+        pCpu->uAddrMode     = DISCPUMODE_64BIT;
+        pCpu->uOpMode       = DISCPUMODE_32BIT;
+        paOneByteMap        = g_aOneByteMapX64;
+    }
+    else
+    {
+        pCpu->uAddrMode     = enmCpuMode;
+        pCpu->uOpMode       = enmCpuMode;
+        paOneByteMap        = g_aOneByteMapX86;
+    }
+    return paOneByteMap;
+}
+
+
+/**
+ * Reads some bytes into the cache.
+ *
+ * While this will set DISCPUSTATE::rc on failure, the caller should disregard
+ * this since that is what would happen if we didn't prefetch bytes prior to the
+ * instruction parsing.
+ *
+ * @param   pCpu                The disassembler state.
+ */
+DECL_FORCE_INLINE(void) disPrefetchBytes(PDISCPUSTATE pCpu)
+{
+    /*
+     * Read some bytes into the cache.  (If this fail we continue as nothing
+     * has gone wrong since this is what would happen if we didn't precharge
+     * the cache here.)
+     */
+    int rc = pCpu->pfnReadBytes(pCpu, 0, 1, sizeof(pCpu->abInstr));
+    if (RT_SUCCESS(rc))
+    {
+        Assert(pCpu->cbCachedInstr >= 1);
+        Assert(pCpu->cbCachedInstr <= sizeof(pCpu->abInstr));
+    }
+    else
+    {
+        Log(("Initial read failed with rc=%Rrc!!\n", rc));
+        pCpu->rc = VERR_DIS_MEM_READ;
+    }
+}
+
+
+/**
  * Disassembles on instruction, details in @a pCpu and length in @a pcbInstr.
  *
@@ -2662,71 +2759,58 @@
                        PDISCPUSTATE pCpu, uint32_t *pcbInstr)
 {
-    PCDISOPCODE paOneByteMap;
-
-    /*
-     * Initialize the CPU state.
-     * Note! The RT_BZERO make ASSUMPTIONS about the placement of pvUser2.
-     */
-    RT_BZERO(pCpu, RT_OFFSETOF(DISCPUSTATE, pvUser2));
-
-#ifdef VBOX_STRICT /* poison */
-    pCpu->Param1.Base.idxGenReg  = 0xc1;
-    pCpu->Param2.Base.idxGenReg  = 0xc2;
-    pCpu->Param3.Base.idxGenReg  = 0xc3;
-    pCpu->Param1.Index.idxGenReg = 0xc4;
-    pCpu->Param2.Index.idxGenReg = 0xc5;
-    pCpu->Param3.Index.idxGenReg = 0xc6;
-    pCpu->Param1.uDisp.u64 = UINT64_C(0xd1d1d1d1d1d1d1d1);
-    pCpu->Param2.uDisp.u64 = UINT64_C(0xd2d2d2d2d2d2d2d2);
-    pCpu->Param3.uDisp.u64 = UINT64_C(0xd3d3d3d3d3d3d3d3);
-    pCpu->Param1.uValue    = UINT64_C(0xb1b1b1b1b1b1b1b1);
-    pCpu->Param2.uValue    = UINT64_C(0xb2b2b2b2b2b2b2b2);
-    pCpu->Param3.uValue    = UINT64_C(0xb3b3b3b3b3b3b3b3);
-    pCpu->Param1.uScale    = 28;
-    pCpu->Param2.uScale    = 29;
-    pCpu->Param3.uScale    = 30;
-#endif
-
-    pCpu->uCpuMode          = enmCpuMode;
-    if (enmCpuMode == DISCPUMODE_64BIT)
-    {
-        paOneByteMap        = g_aOneByteMapX64;
-        pCpu->uAddrMode     = DISCPUMODE_64BIT;
-        pCpu->uOpMode       = DISCPUMODE_32BIT;
-    }
-    else
-    {
-        paOneByteMap        = g_aOneByteMapX86;
-        pCpu->uAddrMode     = enmCpuMode;
-        pCpu->uOpMode       = enmCpuMode;
-    }
-    pCpu->fPrefix           = DISPREFIX_NONE;
-    pCpu->idxSegPrefix      = DISSELREG_DS;
-    pCpu->uInstrAddr        = uInstrAddr;
-    pCpu->pfnDisasmFnTable  = g_apfnFullDisasm;
-    pCpu->fFilter           = fFilter;
-    pCpu->rc                = VINF_SUCCESS;
-    pCpu->pfnReadBytes      = pfnReadBytes ? pfnReadBytes : disReadBytesDefault;
-    pCpu->pvUser            = pvUser;
-
-    /*
-     * Read some bytes into the cache.  (If this fail we continue as nothing
-     * has gone wrong since this is what would happen if we didn't precharge
-     * the cache here.)
-     */
-    int rc = pCpu->pfnReadBytes(pCpu, 0, 1, sizeof(pCpu->abInstr));
-    if (RT_SUCCESS(rc))
-    {
-        Assert(pCpu->cbCachedInstr >= 1);
-        Assert(pCpu->cbCachedInstr <= sizeof(pCpu->abInstr));
-    }
-    else
-    {
-        Log(("Initial read failed with rc=%Rrc!!\n", rc));
-        pCpu->rc = VERR_DIS_MEM_READ;
-    }
-
+
+    PCDISOPCODE paOneByteMap = disInitializeState(pCpu, uInstrAddr, enmCpuMode, fFilter, pfnReadBytes, pvUser);
+    disPrefetchBytes(pCpu);
     return disInstrWorker(pCpu, paOneByteMap, pcbInstr);
 }
+
+
+/**
+ * Disassembles on instruction partially or fully from prefetched bytes, details
+ * in @a pCpu and length in @a pcbInstr.
+ *
+ * @returns VBox status code.
+ * @param   uInstrAddr      Address of the instruction to decode. What this means
+ *                          is left to the pfnReadBytes function.
+ * @param   enmCpuMode      The CPU mode. DISCPUMODE_32BIT, DISCPUMODE_16BIT, or DISCPUMODE_64BIT.
+ * @param   pvPrefetched    Pointer to the prefetched bytes.
+ * @param   cbPrefetched    The number of valid bytes pointed to by @a
+ *                          pbPrefetched.
+ * @param   pfnReadBytes    Callback for reading instruction bytes.
+ * @param   fFilter         Instruction type filter.
+ * @param   pvUser          User argument for the instruction reader. (Ends up in pvUser.)
+ * @param   pCpu            Pointer to CPU structure. With the exception of
+ *                          DISCPUSTATE::pvUser2, the structure will be
+ *                          completely initialized by this API, i.e. no input is
+ *                          taken from it.
+ * @param   pcbInstr        Where to store the size of the instruction.  (This
+ *                          is also stored in PDISCPUSTATE::cbInstr.)  Optional.
+ */
+DISDECL(int) DISInstWithPrefetchedBytes(RTUINTPTR uInstrAddr, DISCPUMODE enmCpuMode, uint32_t fFilter,
+                                        void const *pvPrefetched, size_t cbPretched,
+                                        PFNDISREADBYTES pfnReadBytes, void *pvUser,
+                                        PDISCPUSTATE pCpu, uint32_t *pcbInstr)
+{
+    PCDISOPCODE paOneByteMap = disInitializeState(pCpu, uInstrAddr, enmCpuMode, fFilter, pfnReadBytes, pvUser);
+
+    if (!cbPretched)
+        disPrefetchBytes(pCpu);
+    else
+    {
+        if (cbPretched >= sizeof(pCpu->abInstr))
+        {
+            memcpy(pCpu->abInstr, pvPrefetched, sizeof(pCpu->abInstr));
+            pCpu->cbCachedInstr = (uint8_t)sizeof(pCpu->abInstr);
+        }
+        else
+        {
+            memcpy(pCpu->abInstr, pvPrefetched, cbPretched);
+            pCpu->cbCachedInstr = (uint8_t)cbPretched;
+        }
+    }
+
+    return disInstrWorker(pCpu, paOneByteMap, pcbInstr);
+}
+
 
 
