Index: /trunk/include/VBox/dis.h
===================================================================
--- /trunk/include/VBox/dis.h	(revision 41657)
+++ /trunk/include/VBox/dis.h	(revision 41658)
@@ -4,5 +4,5 @@
 
 /*
- * Copyright (C) 2006-2007 Oracle Corporation
+ * Copyright (C) 2006-2012 Oracle Corporation
  *
  * This file is part of VirtualBox Open Source Edition (OSE), as
@@ -370,16 +370,12 @@
 typedef struct OP_PARAMETER
 {
-    /** @todo switch param and parval and move disp64 and flags up here with the other 64-bit vars to get more natural alignment and save space. */
-    int             param;
     uint64_t        parval;
-#ifndef DIS_SEPARATE_FORMATTER
-    char            szParam[32];
-#endif
-
-    int32_t         disp8, disp16, disp32;
+    uint64_t        flags;
+    int64_t         disp64;
+    int32_t         disp32;
+    int32_t         disp16;
+    int32_t         disp8;
     uint32_t        size;
-
-    int64_t         disp64;
-    uint64_t        flags;
+    int32_t         param;
 
     union
@@ -409,4 +405,7 @@
     uint32_t scale;
 
+#ifndef DIS_SEPARATE_FORMATTER
+    char            szParam[32];
+#endif
 } OP_PARAMETER;
 /** Pointer to opcode parameter. */
@@ -421,6 +420,18 @@
 typedef const struct OPCODE *PCOPCODE;
 
-typedef DECLCALLBACK(int) FN_DIS_READBYTES(RTUINTPTR pSrc, uint8_t *pDest, unsigned size, void *pvUserdata);
-typedef FN_DIS_READBYTES *PFN_DIS_READBYTES;
+/**
+ * Callback for reading opcode bytes.
+ *
+ * @param   pDisState       Pointer to the CPU state.  The primary user argument
+ *                          can be retrived from DISCPUSTATE::apvUserData[0]. If
+ *                          more is required these can be passed in the
+ *                          subsequent slots.
+ * @param   pbDst           Pointer to output buffer.
+ * @param   uSrcAddr        The address to start reading at.
+ * @param   cbToRead        The number of bytes to read.
+ */
+typedef DECLCALLBACK(int) FNDISREADBYTES(PDISCPUSTATE pDisState, uint8_t *pbDst, RTUINTPTR uSrcAddr, uint32_t cbToRead);
+/** Pointer to a opcode byte reader. */
+typedef FNDISREADBYTES *PFNDISREADBYTES;
 
 /** Parser callback.
@@ -431,8 +442,8 @@
 typedef struct DISCPUSTATE
 {
-    /* Global setting */
+    /** Global setting. */
     DISCPUMODE      mode;
 
-    /* Per instruction prefix settings */
+    /** Per instruction prefix settings. */
     uint32_t        prefix;
     /** segment prefix value. */
@@ -452,5 +463,5 @@
     union
     {
-        /* Bitfield view */
+        /** Bitfield view */
         struct
         {
@@ -459,5 +470,5 @@
             unsigned        Mod : 2;
         } Bits;
-        /* unsigned view */
+        /** unsigned view */
         unsigned            u;
     } ModRM;
@@ -466,5 +477,5 @@
     union
     {
-        /* Bitfield view */
+        /** Bitfield view */
         struct
         {
@@ -473,16 +484,34 @@
             unsigned        Scale : 2;
         } Bits;
-        /* unsigned view */
+        /** unsigned view */
         unsigned            u;
     } SIB;
-
-    int32_t         disp;
+    int32_t         i32SibDisp;
+
+    /** The instruction size. */
+    uint32_t        opsize;
+    /** The address of the instruction. */
+    RTUINTPTR       uInstrAddr;
+    /** The offsetted address of the instruction. */
+    RTUINTPTR       opaddr;
+    /** The size of the prefix bytes. */
+    uint8_t         cbPrefix;
 
     /** First opcode byte of instruction. */
     uint8_t         opcode;
-    /** Last prefix byte (for SSE2 extension tables) */
+    /** Last prefix byte (for SSE2 extension tables). */
     uint8_t         lastprefix;
-    RTUINTPTR       opaddr;
-    uint32_t        opsize;
+    /** The instruction bytes. */
+    uint8_t         abInstr[16];
+
+    /** Internal: pointer to disassembly function table */
+    PFNDISPARSE    *pfnDisasmFnTable;
+    /** Internal: instruction filter */
+    uint32_t        uFilter;
+    /** Return code set by a worker function like the opcode bytes readers. */
+    int32_t         rc;
+
+    /** Pointer to the current instruction. */
+    PCOPCODE        pCurInstr;
 #ifndef DIS_CORE_ONLY
     /** Opcode format string for current instruction. */
@@ -490,19 +519,10 @@
 #endif
 
-    /** Internal: pointer to disassembly function table */
-    PFNDISPARSE    *pfnDisasmFnTable;
-    /** Internal: instruction filter */
-    uint32_t        uFilter;
-
-    /** Pointer to the current instruction. */
-    PCOPCODE        pCurInstr;
-
+    /** Optional read function */
+    PFNDISREADBYTES pfnReadBytes;
+    /** User data slots for the read callback.  The first entry is used for the
+     *  pvUser argument, the rest are up for grabs.
+     * @remarks This must come last so that we can memset everything before this. */
     void           *apvUserData[3];
-
-    /** Optional read function */
-    PFN_DIS_READBYTES pfnReadBytes;
-#ifdef __L4ENV__
-    jmp_buf *pJumpBuffer;
-#endif /* __L4ENV__ */
 } DISCPUSTATE;
 
@@ -531,88 +551,15 @@
 
 
-/**
- * Disassembles a code block.
- *
- * @returns VBox error code
- * @param   pCpu            Pointer to cpu structure which have DISCPUSTATE::mode
- *                          set correctly.
- * @param   pvCodeBlock     Pointer to the structure to disassemble.
- * @param   cbMax           Maximum number of bytes to disassemble.
- * @param   pcbSize         Where to store the size of the instruction.
- *                          NULL is allowed.
- *
- *
- * @todo    Define output callback.
- * @todo    Using signed integers as sizes is a bit odd. There are still
- *          some GCC warnings about mixing signed and unsigned integers.
- * @todo    Need to extend this interface to include a code address so we
- *          can disassemble GC code. Perhaps a new function is better...
- * @remark  cbMax isn't respected as a boundary. DISInstr() will read beyond cbMax.
- *          This means *pcbSize >= cbMax sometimes.
- */
-DISDECL(int) DISBlock(PDISCPUSTATE pCpu, RTUINTPTR pvCodeBlock, unsigned cbMax, unsigned *pSize);
-
-/**
- * Disassembles one instruction
- *
- * @returns VBox error code
- * @param   pCpu            Pointer to cpu structure which have DISCPUSTATE::mode
- *                          set correctly.
- * @param   pu8Instruction  Pointer to the instrunction to disassemble.
- * @param   u32EipOffset    Offset to add to instruction address to get the real virtual address
- * @param   pcbSize         Where to store the size of the instruction.
- *                          NULL is allowed.
- * @param   pszOutput       Storage for disassembled instruction
- *
- * @todo    Define output callback.
- */
-DISDECL(int) DISInstr(PDISCPUSTATE pCpu, RTUINTPTR pu8Instruction, unsigned u32EipOffset, unsigned *pcbSize, char *pszOutput);
-
-/**
- * Disassembles one instruction
- *
- * @returns VBox error code
- * @param   pCpu            Pointer to cpu structure which have DISCPUSTATE::mode
- *                          set correctly.
- * @param   pu8Instruction  Pointer to the structure to disassemble.
- * @param   u32EipOffset    Offset to add to instruction address to get the real virtual address
- * @param   pcbSize         Where to store the size of the instruction.
- *                          NULL is allowed.
- * @param   pszOutput       Storage for disassembled instruction
- * @param   uFilter         Instruction type filter
- *
- * @todo    Define output callback.
- */
-DISDECL(int) DISInstrEx(PDISCPUSTATE pCpu, RTUINTPTR pu8Instruction, uint32_t u32EipOffset, uint32_t *pcbSize,
-                         char *pszOutput, unsigned uFilter);
-
-/**
- * Parses one instruction.
- * The result is found in pCpu.
- *
- * @returns VBox error code
- * @param   pCpu            Pointer to cpu structure which has DISCPUSTATE::mode set correctly.
- * @param   InstructionAddr Pointer to the instruction to parse.
- * @param   pcbInstruction  Where to store the size of the instruction.
- *                          NULL is allowed.
- */
-DISDECL(int) DISCoreOne(PDISCPUSTATE pCpu, RTUINTPTR InstructionAddr, unsigned *pcbInstruction);
-
-/**
- * Parses one guest instruction.
- * The result is found in pCpu and pcbInstruction.
- *
- * @returns VBox status code.
- * @param   InstructionAddr Address of the instruction to decode. What this means
- *                          is left to the pfnReadBytes function.
- * @param   enmCpuMode      The CPU mode. CPUMODE_32BIT, CPUMODE_16BIT, or CPUMODE_64BIT.
- * @param   pfnReadBytes    Callback for reading instruction bytes.
- * @param   pvUser          User argument for the instruction reader. (Ends up in apvUserData[0].)
- * @param   pCpu            Pointer to cpu structure. Will be initialized.
- * @param   pcbInstruction  Where to store the size of the instruction.
- *                          NULL is allowed.
- */
-DISDECL(int) DISCoreOneEx(RTUINTPTR InstructionAddr, DISCPUMODE enmCpuMode, PFN_DIS_READBYTES pfnReadBytes, void *pvUser,
-                          PDISCPUSTATE pCpu, unsigned *pcbInstruction);
+DISDECL(int) DISInstr(RTUINTPTR uInstrAddr, DISCPUMODE enmCpuMode, PDISCPUSTATE pCpu, uint32_t *pcbSize, char *pszOutput);
+DISDECL(int) DISInstrWithOff(PDISCPUSTATE pCpu, RTUINTPTR uInstrAddr, RTUINTPTR offRealAddr, uint32_t *pcbSize, char *pszOutput);
+DISDECL(int) DISInstrWithReader(RTUINTPTR uInstrAddr, DISCPUMODE enmCpuMode, PFNDISREADBYTES pfnReadBytes, void *pvUser,
+                                PDISCPUSTATE pCpu, uint32_t *pcbSize, char *pszOutput);
+DISDECL(int) DISInstrEx(RTUINTPTR uInstrAddr, RTUINTPTR offRealAddr, DISCPUMODE enmCpuMode,
+                        PFNDISREADBYTES pfnReadBytes, void *pvUser, uint32_t uFilter,
+                        PDISCPUSTATE pCpu, uint32_t *pcbSize, char *pszOutput);
+
+DISDECL(int) DISCoreOne(PDISCPUSTATE pCpu, RTUINTPTR InstructionAddr, uint32_t *pcbInstruction);
+DISDECL(int) DISCoreOneEx(RTUINTPTR InstructionAddr, DISCPUMODE enmCpuMode, PFNDISREADBYTES pfnReadBytes, void *pvUser,
+                          PDISCPUSTATE pCpu, uint32_t *pcbInstruction);
 
 DISDECL(int)        DISGetParamSize(PDISCPUSTATE pCpu, POP_PARAMETER pParam);
@@ -620,18 +567,4 @@
 DISDECL(uint8_t)    DISQuerySegPrefixByte(PDISCPUSTATE pCpu);
 
-/**
- * Returns the value of the parameter in pParam
- *
- * @returns VBox error code
- * @param   pCtx            Exception structure pointer
- * @param   pCpu            Pointer to cpu structure which have DISCPUSTATE::mode
- *                          set correctly.
- * @param   pParam          Pointer to the parameter to parse
- * @param   pParamVal       Pointer to parameter value (OUT)
- * @param   parmtype        Parameter type
- *
- * @note    Currently doesn't handle FPU/XMM/MMX/3DNow! parameters correctly!!
- *
- */
 DISDECL(int) DISQueryParamVal(PCPUMCTXCORE pCtx, PDISCPUSTATE pCpu, POP_PARAMETER pParam, POP_PARAMVAL pParamVal, PARAM_TYPE parmtype);
 DISDECL(int) DISQueryParamRegPtr(PCPUMCTXCORE pCtx, PDISCPUSTATE pCpu, POP_PARAMETER pParam, void **ppReg, size_t *pcbSize);
Index: /trunk/include/VBox/err.h
===================================================================
--- /trunk/include/VBox/err.h	(revision 41657)
+++ /trunk/include/VBox/err.h	(revision 41658)
@@ -1932,4 +1932,12 @@
 /** Generic failure during disassembly. */
 #define VERR_DIS_GEN_FAILURE                        (-4201)
+/** No read callback. */
+#define VERR_DIS_NO_READ_CALLBACK                   (-4202)
+/** Invalid Mod/RM. */
+#define VERR_DIS_INVALID_MODRM                      (-4203)
+/** Invalid parameter index. */
+#define VERR_DIS_INVALID_PARAMETER                  (-4204)
+/** Reading opcode bytes failed. */
+#define VERR_DIS_MEM_READ                           (-4205)
 /** @} */
 
Index: /trunk/include/VBox/vmm/iem.h
===================================================================
--- /trunk/include/VBox/vmm/iem.h	(revision 41657)
+++ /trunk/include/VBox/vmm/iem.h	(revision 41658)
@@ -41,4 +41,6 @@
 VMMDECL(VBOXSTRICTRC)       IEMExecOne(PVMCPU pVCpu);
 VMMDECL(VBOXSTRICTRC)       IEMExecOneEx(PVMCPU pVCpu, PCPUMCTXCORE pCtxCore, uint32_t *pcbWritten);
+VMMDECL(VBOXSTRICTRC)       IEMExecOneWithOpcodes(PVMCPU pVCpu, PCPUMCTXCORE pCtxCore,
+                                                  RTGCPTR GCPtrOpcodeBytes, const void *pvOpcodeBytes, size_t cbOpcodeBytes);
 VMMDECL(VBOXSTRICTRC)       IEMExecLots(PVMCPU pVCpu);
 VMM_INT_DECL(VBOXSTRICTRC)  IEMInjectTrap(PVMCPU pVCpu, uint8_t u8TrapNo, TRPMEVENT enmType, uint16_t uErrCode, RTGCPTR uCr2);
Index: /trunk/include/VBox/vmm/patm.h
===================================================================
--- /trunk/include/VBox/vmm/patm.h	(revision 41657)
+++ /trunk/include/VBox/vmm/patm.h	(revision 41658)
@@ -238,5 +238,5 @@
  * @param   pCtxCore    The relevant core context.
  */
-VMMDECL(int) PATMHandleInt3PatchTrap(PVM pVM, PCPUMCTXCORE pRegFrame);
+VMMRCDECL(int) PATMRCHandleInt3PatchTrap(PVM pVM, PCPUMCTXCORE pRegFrame);
 
 /**
Index: /trunk/src/VBox/Devices/PC/BIOS-new/MakeDebianBiosAssembly.cpp
===================================================================
--- /trunk/src/VBox/Devices/PC/BIOS-new/MakeDebianBiosAssembly.cpp	(revision 41657)
+++ /trunk/src/VBox/Devices/PC/BIOS-new/MakeDebianBiosAssembly.cpp	(revision 41658)
@@ -904,24 +904,20 @@
 
 /**
- * Disassembler callback for reading opcode bytes.
- *
- * @returns VINF_SUCCESS.
- * @param   uFlatAddr           The address to read at.
- * @param   pbDst               Where to store them.
- * @param   cbToRead            How many to read.
- * @param   pvUser              Unused.
- */
-static DECLCALLBACK(int) disReadOpcodeBytes(RTUINTPTR uFlatAddr, uint8_t *pbDst, unsigned cbToRead, void *pvUser)
-{
-    if (uFlatAddr + cbToRead >= VBOX_BIOS_BASE + _64K)
+ * @callback_method_impl{FNDISREADBYTES}
+ *
+ * @remarks @a uSrcAddr is the flat address.
+ */
+static DECLCALLBACK(int) disReadOpcodeBytes(PDISCPUSTATE pDisState, uint8_t *pbDst, RTUINTPTR uSrcAddr, uint32_t cbToRead)
+{
+    if (uSrcAddr + cbToRead >= VBOX_BIOS_BASE + _64K)
     {
         RT_BZERO(pbDst, cbToRead);
-        if (uFlatAddr >= VBOX_BIOS_BASE + _64K)
+        if (uSrcAddr >= VBOX_BIOS_BASE + _64K)
             cbToRead = 0;
         else
-            cbToRead = VBOX_BIOS_BASE + _64K - uFlatAddr;
-    }
-    memcpy(pbDst, &g_pbImg[uFlatAddr - VBOX_BIOS_BASE], cbToRead);
-    NOREF(pvUser);
+            cbToRead = VBOX_BIOS_BASE + _64K - uSrcAddr;
+    }
+    memcpy(pbDst, &g_pbImg[uSrcAddr - VBOX_BIOS_BASE], cbToRead);
+    NOREF(pDisState);
     return VINF_SUCCESS;
 }
Index: /trunk/src/VBox/Disassembler/Disasm.cpp
===================================================================
--- /trunk/src/VBox/Disassembler/Disasm.cpp	(revision 41657)
+++ /trunk/src/VBox/Disassembler/Disasm.cpp	(revision 41658)
@@ -34,41 +34,20 @@
 
 /**
- * Disassembles a code block.
+ * Disassembles one instruction
  *
  * @returns VBox error code
  * @param   pCpu            Pointer to cpu structure which have DISCPUSTATE::mode
  *                          set correctly.
- * @param   pvCodeBlock     Pointer to the structure to disassemble.
- * @param   cbMax           Maximum number of bytes to disassemble.
+ * @param   uInstrAddr      Pointer to the structure to disassemble.
  * @param   pcbSize         Where to store the size of the instruction.
  *                          NULL is allowed.
- *
+ * @param   pszOutput       Storage for disassembled instruction
  *
  * @todo    Define output callback.
- * @todo    Using signed integers as sizes is a bit odd. There are still
- *          some GCC warnings about mixing signed and unsigned integers.
- * @todo    Need to extend this interface to include a code address so we
- *          can disassemble GC code. Perhaps a new function is better...
- * @remark  cbMax isn't respected as a boundary. DISInstr() will read beyond cbMax.
- *          This means *pcbSize >= cbMax sometimes.
- */
-DISDECL(int) DISBlock(PDISCPUSTATE pCpu, RTUINTPTR pvCodeBlock, unsigned cbMax, unsigned *pSize)
-{
-    unsigned i = 0;
-    char szOutput[256];
-
-    while (i < cbMax)
-    {
-        unsigned cbInstr;
-        int rc = DISInstr(pCpu, pvCodeBlock + i, 0, &cbInstr, szOutput);
-        if (RT_FAILURE(rc))
-            return rc;
-
-        i += cbInstr;
-    }
-
-    if (pSize)
-        *pSize = i;
-    return true;
+ */
+DISDECL(int) DISInstr(RTUINTPTR uInstrAddr, DISCPUMODE enmCpuMode, PDISCPUSTATE pCpu, uint32_t *pcbSize, char *pszOutput)
+{
+    return DISInstrEx(uInstrAddr, 0, enmCpuMode, NULL, NULL, OPTYPE_ALL,
+                      pCpu, pcbSize, pszOutput);
 }
 
@@ -79,6 +58,7 @@
  * @param   pCpu            Pointer to cpu structure which have DISCPUSTATE::mode
  *                          set correctly.
- * @param   pu8Instruction  Pointer to the structure to disassemble.
- * @param   u32EipOffset    Offset to add to instruction address to get the real virtual address
+ * @param   uInstrAddr      Pointer to the structure to disassemble.
+ * @param   offRealAddr     Offset to add to instruction address to get the real
+ *                          virtual address.
  * @param   pcbSize         Where to store the size of the instruction.
  *                          NULL is allowed.
@@ -87,8 +67,33 @@
  * @todo    Define output callback.
  */
-DISDECL(int) DISInstr(PDISCPUSTATE pCpu, RTUINTPTR pu8Instruction, unsigned u32EipOffset, unsigned *pcbSize,
-                      char *pszOutput)
-{
-    return DISInstrEx(pCpu, pu8Instruction, u32EipOffset, pcbSize, pszOutput, OPTYPE_ALL);
+DISDECL(int) DISInstrWithOff(PDISCPUSTATE pCpu, RTUINTPTR uInstrAddr, RTUINTPTR offRealAddr,
+                             unsigned *pcbSize, char *pszOutput)
+{
+    return DISInstrEx(uInstrAddr, offRealAddr, pCpu->mode, pCpu->pfnReadBytes, pCpu->apvUserData[0], OPTYPE_ALL,
+                      pCpu, pcbSize, pszOutput);
+}
+
+/**
+ * Disassembles one instruction with a byte fetcher caller.
+ *
+ * @returns VBox error code
+ * @param   uInstrAddr      Pointer to the structure to disassemble.
+ * @param   enmCpuMode      The CPU mode.
+ * @param   pfnCallback     The byte fetcher callback.
+ * @param   pvUser          The user argument (found in
+ *                          DISCPUSTATE::apvUserData[0]).
+ * @param   pCpu            Where to return the disassembled instruction.
+ * @param   pcbSize         Where to store the size of the instruction.
+ *                          NULL is allowed.
+ * @param   pszOutput       Storage for disassembled instruction
+ *
+ * @todo    Define output callback.
+ */
+DISDECL(int) DISInstrWithReader(RTUINTPTR uInstrAddr, DISCPUMODE enmCpuMode, PFNDISREADBYTES pfnReadBytes, void *pvUser,
+                                PDISCPUSTATE pCpu, uint32_t *pcbSize, char *pszOutput)
+
+{
+    return DISInstrEx(uInstrAddr, 0, enmCpuMode, pfnReadBytes, pvUser, OPTYPE_ALL,
+                      pCpu, pcbSize, pszOutput);
 }
 
@@ -99,5 +104,5 @@
  * @param   pCpu            Pointer to cpu structure which have DISCPUSTATE::mode
  *                          set correctly.
- * @param   pu8Instruction  Pointer to the structure to disassemble.
+ * @param   uInstrAddr      Pointer to the structure to disassemble.
  * @param   u32EipOffset    Offset to add to instruction address to get the real virtual address
  * @param   pcbSize         Where to store the size of the instruction.
@@ -108,185 +113,156 @@
  * @todo    Define output callback.
  */
-DISDECL(int) DISInstrEx(PDISCPUSTATE pCpu, RTUINTPTR pu8Instruction, unsigned u32EipOffset, unsigned *pcbSize,
-                        char *pszOutput, unsigned uFilter)
-{
-    unsigned i = 0, prefixbytes;
-    unsigned idx, inc;
-    const OPCODE *paOneByteMap;
-#ifdef __L4ENV__
-    jmp_buf jumpbuffer;
-#endif
-
-    //reset instruction settings
-    pCpu->prefix        = PREFIX_NONE;
-    pCpu->enmPrefixSeg  = DIS_SELREG_DS;
-    pCpu->ModRM.u       = 0;
-    pCpu->SIB.u         = 0;
-    pCpu->lastprefix    = 0;
-    pCpu->param1.parval = 0;
-    pCpu->param2.parval = 0;
-    pCpu->param3.parval = 0;
-    pCpu->param1.szParam[0] = 0;
-    pCpu->param2.szParam[0] = 0;
-    pCpu->param3.szParam[0] = 0;
-    pCpu->param1.size   = 0;
-    pCpu->param2.size   = 0;
-    pCpu->param3.size   = 0;
-    pCpu->param1.flags  = 0;
-    pCpu->param2.flags  = 0;
-    pCpu->param3.flags  = 0;
-    pCpu->uFilter       = uFilter;
-    pCpu->pfnDisasmFnTable = pfnFullDisasm;
-
-    if (pszOutput)
-        *pszOutput = '\0';
-
-    if (pCpu->mode == CPUMODE_64BIT)
+DISDECL(int) DISInstrEx(RTUINTPTR uInstrAddr, RTUINTPTR offRealAddr, DISCPUMODE enmCpuMode,
+                        PFNDISREADBYTES pfnReadBytes, void *pvUser, uint32_t uFilter,
+                        PDISCPUSTATE pCpu, uint32_t *pcbSize, char *pszOutput)
+{
+    const OPCODE   *paOneByteMap;
+
+    /*
+     * Initialize the CPU state.
+     * Note! The RT_BZERO make ASSUMPTIONS about the placement of apvUserData.
+     */
+    RT_BZERO(pCpu, RT_OFFSETOF(DISCPUSTATE, apvUserData));
+
+    pCpu->mode              = enmCpuMode;
+    if (enmCpuMode == CPUMODE_64BIT)
     {
-        paOneByteMap     = g_aOneByteMapX64;
-        pCpu->addrmode   = CPUMODE_64BIT;
-        pCpu->opmode     = CPUMODE_32BIT;
+        paOneByteMap        = g_aOneByteMapX64;
+        pCpu->addrmode      = CPUMODE_64BIT;
+        pCpu->opmode        = CPUMODE_32BIT;
     }
     else
     {
-        paOneByteMap     = g_aOneByteMapX86;
-        pCpu->addrmode   = pCpu->mode;
-        pCpu->opmode     = pCpu->mode;
+        paOneByteMap        = g_aOneByteMapX86;
+        pCpu->addrmode      = enmCpuMode;
+        pCpu->opmode        = enmCpuMode;
     }
-
-    prefixbytes = 0;
-#ifndef __L4ENV__  /* Unfortunately, we have no exception handling in l4env */
-    try
-#else
-    pCpu->pJumpBuffer = &jumpbuffer;
-    if (setjmp(jumpbuffer) == 0)
-#endif
+    pCpu->prefix            = PREFIX_NONE;
+    pCpu->enmPrefixSeg      = DIS_SELREG_DS;
+    pCpu->uInstrAddr        = uInstrAddr;
+    pCpu->opaddr            = uInstrAddr + offRealAddr;
+    pCpu->pfnDisasmFnTable  = pfnFullDisasm;
+    pCpu->uFilter           = uFilter;
+    pCpu->rc                = VINF_SUCCESS;
+    pCpu->pfnReadBytes      = pfnReadBytes ? pfnReadBytes : disReadBytesDefault;
+    pCpu->apvUserData[0]    = pvUser;
+
+    /*
+     * Parse the instruction byte by byte.
+     */
+    unsigned i        = 0;
+    unsigned cbPrefix = 0; /** @todo this isn't really needed, is it? Seems to be a bit too many variables tracking the same stuff here. cbInc, i, cbPrefix, idx... */
+    for (;;)
     {
-        while(1)
+        uint8_t codebyte = DISReadByte(pCpu, uInstrAddr+i);
+        uint8_t opcode   = paOneByteMap[codebyte].opcode;
+
+        /* Hardcoded assumption about OP_* values!! */
+        if (opcode <= OP_LAST_PREFIX)
         {
-            uint8_t codebyte = DISReadByte(pCpu, pu8Instruction+i);
-            uint8_t opcode   = paOneByteMap[codebyte].opcode;
-
-            /* Hardcoded assumption about OP_* values!! */
-            if (opcode <= OP_LAST_PREFIX)
+            /* The REX prefix must precede the opcode byte(s). Any other placement is ignored. */
+            if (opcode != OP_REX)
             {
-                /* The REX prefix must precede the opcode byte(s). Any other placement is ignored. */
-                if (opcode != OP_REX)
-                {
-                    pCpu->lastprefix = opcode;
-                    pCpu->prefix &= ~PREFIX_REX;
-                }
-
-                switch(opcode)
-                {
-                case OP_INVALID:
-#if 0 //defined (DEBUG_Sander)
-                    AssertMsgFailed(("Invalid opcode!!\n"));
-#endif
-                    return VERR_DIS_INVALID_OPCODE;
-
-                // segment override prefix byte
-                case OP_SEG:
-                    pCpu->enmPrefixSeg = (DIS_SELREG)(paOneByteMap[codebyte].param1 - OP_PARM_REG_SEG_START);
-                    /* Segment prefixes for CS, DS, ES and SS are ignored in long mode. */
-                    if (   pCpu->mode != CPUMODE_64BIT
-                        || pCpu->enmPrefixSeg >= DIS_SELREG_FS)
-                    {
-                        pCpu->prefix    |= PREFIX_SEG;
-                    }
-                    i += sizeof(uint8_t);
-                    prefixbytes++;
-                    continue;   //fetch the next byte
-
-                // lock prefix byte
-                case OP_LOCK:
-                    pCpu->prefix |= PREFIX_LOCK;
-                    i += sizeof(uint8_t);
-                    prefixbytes++;
-                    continue;   //fetch the next byte
-
-                // address size override prefix byte
-                case OP_ADDRSIZE:
-                    pCpu->prefix |= PREFIX_ADDRSIZE;
-                    if (pCpu->mode == CPUMODE_16BIT)
-                        pCpu->addrmode = CPUMODE_32BIT;
-                    else
-                    if (pCpu->mode == CPUMODE_32BIT)
-                        pCpu->addrmode = CPUMODE_16BIT;
-                    else
-                        pCpu->addrmode = CPUMODE_32BIT;     /* 64 bits */
-
-                    i += sizeof(uint8_t);
-                    prefixbytes++;
-                    continue;   //fetch the next byte
-
-                // operand size override prefix byte
-                case OP_OPSIZE:
-                    pCpu->prefix |= PREFIX_OPSIZE;
-                    if (pCpu->mode == CPUMODE_16BIT)
-                        pCpu->opmode = CPUMODE_32BIT;
-                    else
-                        pCpu->opmode = CPUMODE_16BIT;  /* for 32 and 64 bits mode (there is no 32 bits operand size override prefix) */
-
-                    i += sizeof(uint8_t);
-                    prefixbytes++;
-                    continue;   //fetch the next byte
-
-                // rep and repne are not really prefixes, but we'll treat them as such
-                case OP_REPE:
-                    pCpu->prefix |= PREFIX_REP;
-                    i += sizeof(uint8_t);
-                    prefixbytes += sizeof(uint8_t);
-                    continue;   //fetch the next byte
-
-                case OP_REPNE:
-                    pCpu->prefix |= PREFIX_REPNE;
-                    i += sizeof(uint8_t);
-                    prefixbytes += sizeof(uint8_t);
-                    continue;   //fetch the next byte
-
-                case OP_REX:
-                    Assert(pCpu->mode == CPUMODE_64BIT);
-                    /* REX prefix byte */
-                    pCpu->prefix    |= PREFIX_REX;
-                    pCpu->prefix_rex = PREFIX_REX_OP_2_FLAGS(paOneByteMap[codebyte].param1);
-                    i += sizeof(uint8_t);
-                    prefixbytes += sizeof(uint8_t);
-
-                    if (pCpu->prefix_rex & PREFIX_REX_FLAGS_W)
-                        pCpu->opmode = CPUMODE_64BIT;  /* overrides size prefix byte */
-                    continue;   //fetch the next byte
-                }
+                pCpu->lastprefix = opcode;
+                pCpu->prefix &= ~PREFIX_REX;
             }
 
-            idx = i;
-            i += sizeof(uint8_t); //first opcode byte
-
-            pCpu->opcode = codebyte;
-            /* Prefix byte(s) is/are part of the instruction. */
-            pCpu->opaddr = pu8Instruction + idx + u32EipOffset - prefixbytes;
-
-            inc = ParseInstruction(pu8Instruction + i, &paOneByteMap[pCpu->opcode], pCpu);
-
-            pCpu->opsize = prefixbytes + inc + sizeof(uint8_t);
-
-            if(pszOutput) {
-                disasmSprintf(pszOutput, pu8Instruction+i-1-prefixbytes, pCpu, &pCpu->param1, &pCpu->param2, &pCpu->param3);
+            switch (opcode)
+            {
+            case OP_INVALID:
+                if (pcbSize)
+                    *pcbSize = pCpu->opsize;
+                return pCpu->rc = VERR_DIS_INVALID_OPCODE;
+
+            // segment override prefix byte
+            case OP_SEG:
+                pCpu->enmPrefixSeg = (DIS_SELREG)(paOneByteMap[codebyte].param1 - OP_PARM_REG_SEG_START);
+                /* Segment prefixes for CS, DS, ES and SS are ignored in long mode. */
+                if (   pCpu->mode != CPUMODE_64BIT
+                    || pCpu->enmPrefixSeg >= DIS_SELREG_FS)
+                    pCpu->prefix |= PREFIX_SEG;
+                i += sizeof(uint8_t);
+                cbPrefix++;
+                continue;   //fetch the next byte
+
+            // lock prefix byte
+            case OP_LOCK:
+                pCpu->prefix |= PREFIX_LOCK;
+                i += sizeof(uint8_t);
+                cbPrefix++;
+                continue;   //fetch the next byte
+
+            // address size override prefix byte
+            case OP_ADDRSIZE:
+                pCpu->prefix |= PREFIX_ADDRSIZE;
+                if (pCpu->mode == CPUMODE_16BIT)
+                    pCpu->addrmode = CPUMODE_32BIT;
+                else
+                if (pCpu->mode == CPUMODE_32BIT)
+                    pCpu->addrmode = CPUMODE_16BIT;
+                else
+                    pCpu->addrmode = CPUMODE_32BIT;     /* 64 bits */
+
+                i += sizeof(uint8_t);
+                cbPrefix++;
+                continue;   //fetch the next byte
+
+            // operand size override prefix byte
+            case OP_OPSIZE:
+                pCpu->prefix |= PREFIX_OPSIZE;
+                if (pCpu->mode == CPUMODE_16BIT)
+                    pCpu->opmode = CPUMODE_32BIT;
+                else
+                    pCpu->opmode = CPUMODE_16BIT;  /* for 32 and 64 bits mode (there is no 32 bits operand size override prefix) */
+
+                i += sizeof(uint8_t);
+                cbPrefix++;
+                continue;   //fetch the next byte
+
+            // rep and repne are not really prefixes, but we'll treat them as such
+            case OP_REPE:
+                pCpu->prefix |= PREFIX_REP;
+                i += sizeof(uint8_t);
+                cbPrefix += sizeof(uint8_t);
+                continue;   //fetch the next byte
+
+            case OP_REPNE:
+                pCpu->prefix |= PREFIX_REPNE;
+                i += sizeof(uint8_t);
+                cbPrefix += sizeof(uint8_t);
+                continue;   //fetch the next byte
+
+            case OP_REX:
+                Assert(pCpu->mode == CPUMODE_64BIT);
+                /* REX prefix byte */
+                pCpu->prefix    |= PREFIX_REX;
+                pCpu->prefix_rex = PREFIX_REX_OP_2_FLAGS(paOneByteMap[codebyte].param1);
+                i += sizeof(uint8_t);
+                cbPrefix += sizeof(uint8_t);
+
+                if (pCpu->prefix_rex & PREFIX_REX_FLAGS_W)
+                    pCpu->opmode = CPUMODE_64BIT;  /* overrides size prefix byte */
+                continue;   //fetch the next byte
             }
-
-            i += inc;
-            prefixbytes = 0;
-            break;
         }
-    }
-#ifndef __L4ENV__
-    catch(...)
-#else
-    else  /* setjmp has returned a non-zero value: an exception occurred */
-#endif
-    {
-        if (pcbSize)
-            *pcbSize = 0;
-        return VERR_DIS_GEN_FAILURE;
+
+        pCpu->cbPrefix = i; Assert(cbPrefix == i);
+        pCpu->opcode   = codebyte;
+
+        unsigned idx = i;
+        i += sizeof(uint8_t); //first opcode byte
+
+        unsigned cbInc = ParseInstruction(uInstrAddr + i, &paOneByteMap[pCpu->opcode], pCpu);
+
+        AssertMsg(pCpu->opsize == cbPrefix + cbInc + sizeof(uint8_t),
+                  ("%u %u\n", pCpu->opsize, cbPrefix + cbInc + sizeof(uint8_t)));
+        pCpu->opsize = cbPrefix + cbInc + sizeof(uint8_t);
+
+        if (pszOutput)
+            disasmSprintf(pszOutput, uInstrAddr+i-1-cbPrefix, pCpu, &pCpu->param1, &pCpu->param2, &pCpu->param3);
+
+        i += cbInc;
+        cbPrefix = 0;
+        break;
     }
 
@@ -297,162 +273,150 @@
         disValidateLockSequence(pCpu);
 
-    return VINF_SUCCESS;
-}
-//*****************************************************************************
-//*****************************************************************************
-char *DbgBytesToString(PDISCPUSTATE pCpu, RTUINTPTR pBytes, int size, char *pszOutput)
-{
-    char   *psz = strchr(pszOutput, '\0');
-    size_t  len;
-    int     i;
-
-    for(len = psz - pszOutput; len < 40; len++)
-        *psz++ = ' ';
-    *psz++ = ' ';
-    *psz++ = '[';
-
-    for(i = 0; (int)i < size; i++)
-        psz += RTStrPrintf(psz, 64, "%02X ", DISReadByte(pCpu, pBytes+i));
-
-    psz[-1] = ']';  // replaces space
-
-    return pszOutput;
-}
-//*****************************************************************************
-//*****************************************************************************
-void disasmSprintf(char *pszOutput, RTUINTPTR pu8Instruction, PDISCPUSTATE pCpu, OP_PARAMETER *pParam1, OP_PARAMETER *pParam2, OP_PARAMETER *pParam3)
-{
-    const char *lpszFormat = pCpu->pszOpcode;
+    return pCpu->rc;
+}
+//*****************************************************************************
+//*****************************************************************************
+static size_t DbgBytesToString(PDISCPUSTATE pCpu, char *pszOutput, size_t offStart)
+{
+    unsigned off = offStart;
+
+    while (off < 40)
+        pszOutput[off++] = ' ';
+    pszOutput[off++] = ' ';
+    pszOutput[off++] = '[';
+
+    for (unsigned i = 0; i < pCpu->opsize; i++)
+        off += RTStrPrintf(&pszOutput[off], 64, "%02X ", pCpu->abInstr[i]);
+
+    pszOutput[off - 1] = ']';  // replaces space
+    return off - offStart;
+}
+//*****************************************************************************
+//*****************************************************************************
+void disasmSprintf(char *pszOutput, RTUINTPTR uInstrAddr, PDISCPUSTATE pCpu,
+                   OP_PARAMETER *pParam1, OP_PARAMETER *pParam2, OP_PARAMETER *pParam3)
+{
+    const char *pszFormat = pCpu->pszOpcode;
     int   param = 1;
 
-    RTStrPrintf(pszOutput, 64, "%08X:  ", (unsigned)pCpu->opaddr);
-    if(pCpu->prefix & PREFIX_LOCK)
+
+    size_t off = RTStrPrintf(pszOutput, 64, "%08RTptr:  ", pCpu->opaddr);
+    if (pCpu->prefix & PREFIX_LOCK)
+        off += RTStrPrintf(&pszOutput[off], 64, "lock ");
+    if (pCpu->prefix & PREFIX_REP)
+        off += RTStrPrintf(&pszOutput[off], 64, "rep(e) ");
+    else if(pCpu->prefix & PREFIX_REPNE)
+        off += RTStrPrintf(&pszOutput[off], 64, "repne ");
+
+    if (!strcmp("Invalid Opcode", pszFormat))
     {
-        RTStrPrintf(&pszOutput[strlen(pszOutput)], 64,  "lock ");
-    }
-    if(pCpu->prefix & PREFIX_REP)
-    {
-        RTStrPrintf(&pszOutput[strlen(pszOutput)], 64, "rep(e) ");
+        if (pCpu->opsize >= 2)
+            off += RTStrPrintf(&pszOutput[off], 64, "Invalid Opcode [%02X][%02X]", pCpu->abInstr[0], pCpu->abInstr[1]);
+        else
+            off += RTStrPrintf(&pszOutput[off], 64, "Invalid Opcode [%02X]", pCpu->abInstr[0]);
     }
     else
-    if(pCpu->prefix & PREFIX_REPNE)
-    {
-        RTStrPrintf(&pszOutput[strlen(pszOutput)], 64, "repne ");
-    }
-
-    if(!strcmp("Invalid Opcode", lpszFormat))
-    {
-        RTStrPrintf(&pszOutput[strlen(pszOutput)], 64, "Invalid Opcode [%02X][%02X]", DISReadByte(pCpu, pu8Instruction), DISReadByte(pCpu, pu8Instruction+1) );
-    }
-    else
-    while(*lpszFormat)
-    {
-        switch(*lpszFormat)
+        while (*pszFormat)
         {
-        case '%':
-            switch(*(lpszFormat+1))
+            switch (*pszFormat)
             {
-            case 'J': //Relative jump offset
-            {
-                int32_t disp;
-
-                AssertMsg(param == 1, ("Invalid branch parameter nr"));
-                if(pParam1->flags & USE_IMMEDIATE8_REL)
+            case '%':
+                switch (pszFormat[1])
                 {
-                    disp = (int32_t)(char)pParam1->parval;
+                case 'J': //Relative jump offset
+                {
+                    int32_t disp;
+
+                    AssertMsg(param == 1, ("Invalid branch parameter nr"));
+                    if (pParam1->flags & USE_IMMEDIATE8_REL)
+                        disp = (int32_t)(char)pParam1->parval;
+                    else if (pParam1->flags & USE_IMMEDIATE16_REL)
+                        disp = (int32_t)(uint16_t)pParam1->parval;
+                    else if (pParam1->flags & USE_IMMEDIATE32_REL)
+                        disp = (int32_t)pParam1->parval;
+                    else if(pParam1->flags & USE_IMMEDIATE64_REL)
+                        /** @todo: is this correct? */
+                        disp = (int32_t)pParam1->parval;
+                    else
+                    {
+                        AssertMsgFailed(("Oops!\n"));
+                        return;
+                    }
+                    uint32_t addr = (uint32_t)(pCpu->opaddr + pCpu->opsize) + disp;
+                    off += RTStrPrintf(&pszOutput[off], 64, "[%08X]", addr);
                 }
-                else
-                if(pParam1->flags & USE_IMMEDIATE16_REL)
-                {
-                    disp = (int32_t)(uint16_t)pParam1->parval;
-                }
-                else
-                if(pParam1->flags & USE_IMMEDIATE32_REL)
-                {
-                    disp = (int32_t)pParam1->parval;
-                }
-                else
-                if(pParam1->flags & USE_IMMEDIATE64_REL)
-                {
-                    /* @todo: is this correct? */
-                    disp = (int32_t)pParam1->parval;
-                }
-                else
-                {
+
+                    //no break;
+
+                case 'A': //direct address
+                case 'C': //control register
+                case 'D': //debug register
+                case 'E': //ModRM specifies parameter
+                case 'F': //Eflags register
+                case 'G': //ModRM selects general register
+                case 'I': //Immediate data
+                case 'M': //ModRM may only refer to memory
+                case 'O': //No ModRM byte
+                case 'P': //ModRM byte selects MMX register
+                case 'Q': //ModRM byte selects MMX register or memory address
+                case 'R': //ModRM byte may only refer to a general register
+                case 'S': //ModRM byte selects a segment register
+                case 'T': //ModRM byte selects a test register
+                case 'V': //ModRM byte selects an XMM/SSE register
+                case 'W': //ModRM byte selects an XMM/SSE register or a memory address
+                case 'X': //DS:SI
+                case 'Y': //ES:DI
+                    switch(param)
+                    {
+                    case 1:
+                        off += RTStrPrintf(&pszOutput[off], 64, pParam1->szParam);
+                        break;
+                    case 2:
+                        off += RTStrPrintf(&pszOutput[off], 64, pParam2->szParam);
+                        break;
+                    case 3:
+                        off += RTStrPrintf(&pszOutput[off], 64, pParam3->szParam);
+                        break;
+                    }
+                    break;
+
+                case 'e': //register based on operand size (e.g. %eAX)
+                    if(pCpu->opmode == CPUMODE_32BIT)
+                        off += RTStrPrintf(&pszOutput[off], 64, "E");
+                    if(pCpu->opmode == CPUMODE_64BIT)
+                        off += RTStrPrintf(&pszOutput[off], 64, "R");
+
+                    off += RTStrPrintf(&pszOutput[off], 64, "%c%c", pszFormat[2], pszFormat[3]);
+                    break;
+
+                default:
                     AssertMsgFailed(("Oops!\n"));
-                    return;
-                }
-                uint32_t addr = (uint32_t)(pCpu->opaddr + pCpu->opsize) + disp;
-                RTStrPrintf(&pszOutput[strlen(pszOutput)], 64, "[%08X]", addr);
-            }
-
-                //no break;
-
-            case 'A': //direct address
-            case 'C': //control register
-            case 'D': //debug register
-            case 'E': //ModRM specifies parameter
-            case 'F': //Eflags register
-            case 'G': //ModRM selects general register
-            case 'I': //Immediate data
-            case 'M': //ModRM may only refer to memory
-            case 'O': //No ModRM byte
-            case 'P': //ModRM byte selects MMX register
-            case 'Q': //ModRM byte selects MMX register or memory address
-            case 'R': //ModRM byte may only refer to a general register
-            case 'S': //ModRM byte selects a segment register
-            case 'T': //ModRM byte selects a test register
-            case 'V': //ModRM byte selects an XMM/SSE register
-            case 'W': //ModRM byte selects an XMM/SSE register or a memory address
-            case 'X': //DS:SI
-            case 'Y': //ES:DI
-                switch(param)
-                {
-                case 1:
-                    RTStrPrintf(&pszOutput[strlen(pszOutput)], 64, pParam1->szParam);
-                    break;
-                case 2:
-                    RTStrPrintf(&pszOutput[strlen(pszOutput)], 64, pParam2->szParam);
-                    break;
-                case 3:
-                    RTStrPrintf(&pszOutput[strlen(pszOutput)], 64, pParam3->szParam);
                     break;
                 }
+
+                //Go to the next parameter in the format string
+                while (*pszFormat && *pszFormat != ',')
+                    pszFormat++;
+                if (*pszFormat == ',')
+                    pszFormat--;
+
                 break;
 
-            case 'e': //register based on operand size (e.g. %eAX)
-                if(pCpu->opmode == CPUMODE_32BIT)
-                    RTStrPrintf(&pszOutput[strlen(pszOutput)], 64, "E");
-                if(pCpu->opmode == CPUMODE_64BIT)
-                    RTStrPrintf(&pszOutput[strlen(pszOutput)], 64, "R");
-
-                RTStrPrintf(&pszOutput[strlen(pszOutput)], 64, "%c%c", lpszFormat[2], lpszFormat[3]);
-                break;
+            case ',':
+                param++;
+                //no break
 
             default:
-                AssertMsgFailed(("Oops!\n"));
+                off += RTStrPrintf(&pszOutput[off], 64, "%c", *pszFormat);
                 break;
             }
 
-            //Go to the next parameter in the format string
-            while(*lpszFormat && *lpszFormat != ',') lpszFormat++;
-            if(*lpszFormat == ',') lpszFormat--;
-
-            break;
-
-        case ',':
-            param++;
-            //no break
-
-        default:
-            RTStrPrintf(&pszOutput[strlen(pszOutput)], 64, "%c", *lpszFormat);
-            break;
+            if (*pszFormat)
+                pszFormat++;
         }
 
-        if(*lpszFormat) lpszFormat++;
-    }
-    DbgBytesToString(pCpu, pu8Instruction, pCpu->opsize, pszOutput);
-    RTStrPrintf(&pszOutput[strlen(pszOutput)], 64, "\n");
-}
-//*****************************************************************************
-//*****************************************************************************
+    off += DbgBytesToString(pCpu, pszOutput, off);
+    off += RTStrPrintf(&pszOutput[off], 64, "\n");
+}
+//*****************************************************************************
+//*****************************************************************************
Index: /trunk/src/VBox/Disassembler/DisasmCore.cpp
===================================================================
--- /trunk/src/VBox/Disassembler/DisasmCore.cpp	(revision 41657)
+++ /trunk/src/VBox/Disassembler/DisasmCore.cpp	(revision 41658)
@@ -1,10 +1,9 @@
+/* $Id$ */
 /** @file
- *
- * VBox disassembler:
- * Core components
+ * VBox Disassembler - Core Components.
  */
 
 /*
- * Copyright (C) 2006-2007 Oracle Corporation
+ * Copyright (C) 2006-2012 Oracle Corporation
  *
  * This file is part of VirtualBox Open Source Edition (OSE), as
@@ -45,5 +44,6 @@
 *   Internal Functions                                                         *
 *******************************************************************************/
-static int disCoreOne(PDISCPUSTATE pCpu, RTUINTPTR InstructionAddr, unsigned *pcbInstruction);
+static int disCoreParseInstr(PDISCPUSTATE pCpu, RTUINTPTR uInstrAddr, const OPCODE *paOneByteMap,
+                             unsigned *pcbInstruction);
 #if !defined(DIS_CORE_ONLY) && defined(LOG_ENABLED)
 static void disasmAddString(char *psz, const char *pszString);
@@ -160,42 +160,4 @@
 };
 
-/**
- * Parses one instruction.
- * The result is found in pCpu.
- *
- * @returns Success indicator.
- * @param   pCpu            Pointer to cpu structure which has DISCPUSTATE::mode set correctly.
- * @param   InstructionAddr Pointer to the instruction to parse.
- * @param   pcbInstruction  Where to store the size of the instruction.
- *                          NULL is allowed.
- */
-DISDECL(int) DISCoreOne(PDISCPUSTATE pCpu, RTUINTPTR InstructionAddr, unsigned *pcbInstruction)
-{
-    /*
-     * Reset instruction settings
-     */
-    pCpu->prefix        = PREFIX_NONE;
-    pCpu->enmPrefixSeg  = DIS_SELREG_DS;
-    pCpu->lastprefix    = 0;
-    pCpu->ModRM.u       = 0;
-    pCpu->SIB.u         = 0;
-    pCpu->param1.parval = 0;
-    pCpu->param2.parval = 0;
-    pCpu->param3.parval = 0;
-    pCpu->param1.szParam[0] = '\0';
-    pCpu->param2.szParam[0] = '\0';
-    pCpu->param3.szParam[0] = '\0';
-    pCpu->param1.flags  = 0;
-    pCpu->param2.flags  = 0;
-    pCpu->param3.flags  = 0;
-    pCpu->param1.size   = 0;
-    pCpu->param2.size   = 0;
-    pCpu->param3.size   = 0;
-    pCpu->pfnReadBytes  = 0;
-    pCpu->uFilter       = OPTYPE_ALL;
-    pCpu->pfnDisasmFnTable = pfnFullDisasm;
-
-    return RT_SUCCESS(disCoreOne(pCpu, InstructionAddr, pcbInstruction));
-}
 
 /**
@@ -204,5 +166,5 @@
  *
  * @returns VBox status code.
- * @param   InstructionAddr Address of the instruction to decode. What this means
+ * @param   uInstrAddr      Address of the instruction to decode. What this means
  *                          is left to the pfnReadBytes function.
  * @param   enmCpuMode      The CPU mode. CPUMODE_32BIT, CPUMODE_16BIT, or CPUMODE_64BIT.
@@ -213,34 +175,38 @@
  *                          NULL is allowed.
  */
-DISDECL(int) DISCoreOneEx(RTUINTPTR InstructionAddr, DISCPUMODE enmCpuMode, PFN_DIS_READBYTES pfnReadBytes, void *pvUser,
+DISDECL(int) DISCoreOneEx(RTUINTPTR uInstrAddr, DISCPUMODE enmCpuMode, PFNDISREADBYTES pfnReadBytes, void *pvUser,
                           PDISCPUSTATE pCpu, unsigned *pcbInstruction)
 {
+    const OPCODE *paOneByteMap;
+
     /*
-     * Reset instruction settings
+     * Initialize the CPU state.
+     * Note! The RT_BZERO make ASSUMPTIONS about the placement of apvUserData.
      */
+    RT_BZERO(pCpu, RT_OFFSETOF(DISCPUSTATE, apvUserData));
+
+    pCpu->mode              = enmCpuMode;
+    if (enmCpuMode == CPUMODE_64BIT)
+    {
+        paOneByteMap        = g_aOneByteMapX64;
+        pCpu->addrmode      = CPUMODE_64BIT;
+        pCpu->opmode        = CPUMODE_32BIT;
+    }
+    else
+    {
+        paOneByteMap        = g_aOneByteMapX86;
+        pCpu->addrmode      = enmCpuMode;
+        pCpu->opmode        = enmCpuMode;
+    }
     pCpu->prefix            = PREFIX_NONE;
     pCpu->enmPrefixSeg      = DIS_SELREG_DS;
-    pCpu->lastprefix        = 0;
-    pCpu->mode              = enmCpuMode;
-    pCpu->ModRM.u           = 0;
-    pCpu->SIB.u             = 0;
-    pCpu->param1.parval     = 0;
-    pCpu->param2.parval     = 0;
-    pCpu->param3.parval     = 0;
-    pCpu->param1.szParam[0] = '\0';
-    pCpu->param2.szParam[0] = '\0';
-    pCpu->param3.szParam[0] = '\0';
-    pCpu->param1.flags      = 0;
-    pCpu->param2.flags      = 0;
-    pCpu->param3.flags      = 0;
-    pCpu->param1.size       = 0;
-    pCpu->param2.size       = 0;
-    pCpu->param3.size       = 0;
-    pCpu->pfnReadBytes      = pfnReadBytes;
+    pCpu->uInstrAddr        = uInstrAddr;
+    pCpu->pfnDisasmFnTable  = pfnFullDisasm;
+    pCpu->uFilter           = OPTYPE_ALL;
+    pCpu->rc                = VINF_SUCCESS;
+    pCpu->pfnReadBytes      = pfnReadBytes ? pfnReadBytes : disReadBytesDefault;
     pCpu->apvUserData[0]    = pvUser;
-    pCpu->uFilter           = OPTYPE_ALL;
-    pCpu->pfnDisasmFnTable  = pfnFullDisasm;
-
-    return disCoreOne(pCpu, InstructionAddr, pcbInstruction);
+
+    return disCoreParseInstr(pCpu, uInstrAddr, paOneByteMap, pcbInstruction);
 }
 
@@ -250,11 +216,10 @@
  * @returns VBox status code.
  * @param   pCpu            Initialized cpu state.
- * @param   InstructionAddr Instruction address.
+ * @param   paOneByteMap    The one byte opcode map to use.
+ * @param   uInstrAddr      Instruction address.
  * @param   pcbInstruction  Where to store the instruction size. Can be NULL.
  */
-static int disCoreOne(PDISCPUSTATE pCpu, RTUINTPTR InstructionAddr, unsigned *pcbInstruction)
-{
-    const OPCODE *paOneByteMap;
-
+static int disCoreParseInstr(PDISCPUSTATE pCpu, RTUINTPTR uInstrAddr, const OPCODE *paOneByteMap, unsigned *pcbInstruction)
+{
     /*
      * Parse byte by byte.
@@ -262,141 +227,106 @@
     unsigned  iByte = 0;
     unsigned  cbInc;
-
-    if (pCpu->mode == CPUMODE_64BIT)
-    {
-        paOneByteMap     = g_aOneByteMapX64;
-        pCpu->addrmode   = CPUMODE_64BIT;
-        pCpu->opmode     = CPUMODE_32BIT;
-    }
-    else
-    {
-        paOneByteMap     = g_aOneByteMapX86;
-        pCpu->addrmode   = pCpu->mode;
-        pCpu->opmode     = pCpu->mode;
-    }
-
-#ifdef IN_RING3
-# ifndef __L4ENV__  /* Unfortunately, we have no exception handling in l4env */
-    try
-# else
-    pCpu->pJumpBuffer = &jumpbuffer;
-    if (setjmp(jumpbuffer) == 0)
-# endif
-#endif
-    {
-        while(1)
+    for (;;)
+    {
+        uint8_t codebyte = DISReadByte(pCpu, uInstrAddr+iByte);
+        uint8_t opcode   = paOneByteMap[codebyte].opcode;
+
+        /* Hardcoded assumption about OP_* values!! */
+        if (opcode <= OP_LAST_PREFIX)
         {
-            uint8_t codebyte = DISReadByte(pCpu, InstructionAddr+iByte);
-            uint8_t opcode   = paOneByteMap[codebyte].opcode;
-
-            /* Hardcoded assumption about OP_* values!! */
-            if (opcode <= OP_LAST_PREFIX)
+            /* The REX prefix must precede the opcode byte(s). Any other placement is ignored. */
+            if (opcode != OP_REX)
             {
-                /* The REX prefix must precede the opcode byte(s). Any other placement is ignored. */
-                if (opcode != OP_REX)
+                /** Last prefix byte (for SSE2 extension tables); don't include the REX prefix */
+                pCpu->lastprefix = opcode;
+                pCpu->prefix &= ~PREFIX_REX;
+            }
+
+            switch (opcode)
+            {
+            case OP_INVALID:
+                if (pcbInstruction)
+                    *pcbInstruction = iByte + 1;
+                return pCpu->rc = VERR_DIS_INVALID_OPCODE;
+
+            // segment override prefix byte
+            case OP_SEG:
+                pCpu->enmPrefixSeg = (DIS_SELREG)(paOneByteMap[codebyte].param1 - OP_PARM_REG_SEG_START);
+                /* Segment prefixes for CS, DS, ES and SS are ignored in long mode. */
+                if (   pCpu->mode != CPUMODE_64BIT
+                    || pCpu->enmPrefixSeg >= DIS_SELREG_FS)
                 {
-                    /** Last prefix byte (for SSE2 extension tables); don't include the REX prefix */
-                    pCpu->lastprefix = opcode;
-                    pCpu->prefix &= ~PREFIX_REX;
+                    pCpu->prefix    |= PREFIX_SEG;
                 }
-
-                switch (opcode)
-                {
-                case OP_INVALID:
-#if 0
-                    AssertMsgFailed(("Invalid opcode!!\n"));
-#endif
-                    return VERR_DIS_INVALID_OPCODE;
-
-                // segment override prefix byte
-                case OP_SEG:
-                    pCpu->enmPrefixSeg = (DIS_SELREG)(paOneByteMap[codebyte].param1 - OP_PARM_REG_SEG_START);
-                    /* Segment prefixes for CS, DS, ES and SS are ignored in long mode. */
-                    if (   pCpu->mode != CPUMODE_64BIT
-                        || pCpu->enmPrefixSeg >= DIS_SELREG_FS)
-                    {
-                        pCpu->prefix    |= PREFIX_SEG;
-                    }
-                    iByte += sizeof(uint8_t);
-                    continue;   //fetch the next byte
-
-                // lock prefix byte
-                case OP_LOCK:
-                    pCpu->prefix |= PREFIX_LOCK;
-                    iByte       += sizeof(uint8_t);
-                    continue;   //fetch the next byte
-
-                // address size override prefix byte
-                case OP_ADDRSIZE:
-                    pCpu->prefix |= PREFIX_ADDRSIZE;
-                    if (pCpu->mode == CPUMODE_16BIT)
-                        pCpu->addrmode = CPUMODE_32BIT;
-                    else
-                    if (pCpu->mode == CPUMODE_32BIT)
-                        pCpu->addrmode = CPUMODE_16BIT;
-                    else
-                        pCpu->addrmode = CPUMODE_32BIT;     /* 64 bits */
-
-                    iByte        += sizeof(uint8_t);
-                    continue;   //fetch the next byte
-
-                // operand size override prefix byte
-                case OP_OPSIZE:
-                    pCpu->prefix |= PREFIX_OPSIZE;
-                    if (pCpu->mode == CPUMODE_16BIT)
-                        pCpu->opmode = CPUMODE_32BIT;
-                    else
-                        pCpu->opmode = CPUMODE_16BIT;  /* for 32 and 64 bits mode (there is no 32 bits operand size override prefix) */
-
-                    iByte        += sizeof(uint8_t);
-                    continue;   //fetch the next byte
-
-                // rep and repne are not really prefixes, but we'll treat them as such
-                case OP_REPE:
-                    pCpu->prefix |= PREFIX_REP;
-                    iByte       += sizeof(uint8_t);
-                    continue;   //fetch the next byte
-
-                case OP_REPNE:
-                    pCpu->prefix |= PREFIX_REPNE;
-                    iByte       += sizeof(uint8_t);
-                    continue;   //fetch the next byte
-
-                case OP_REX:
-                    Assert(pCpu->mode == CPUMODE_64BIT);
-                    /* REX prefix byte */
-                    pCpu->prefix    |= PREFIX_REX;
-                    pCpu->prefix_rex = PREFIX_REX_OP_2_FLAGS(paOneByteMap[codebyte].param1);
-                    iByte           += sizeof(uint8_t);
-
-                    if (pCpu->prefix_rex & PREFIX_REX_FLAGS_W)
-                        pCpu->opmode = CPUMODE_64BIT;  /* overrides size prefix byte */
-                    continue;   //fetch the next byte
-                }
+                iByte += sizeof(uint8_t);
+                continue;   //fetch the next byte
+
+            // lock prefix byte
+            case OP_LOCK:
+                pCpu->prefix |= PREFIX_LOCK;
+                iByte       += sizeof(uint8_t);
+                continue;   //fetch the next byte
+
+            // address size override prefix byte
+            case OP_ADDRSIZE:
+                pCpu->prefix |= PREFIX_ADDRSIZE;
+                if (pCpu->mode == CPUMODE_16BIT)
+                    pCpu->addrmode = CPUMODE_32BIT;
+                else
+                if (pCpu->mode == CPUMODE_32BIT)
+                    pCpu->addrmode = CPUMODE_16BIT;
+                else
+                    pCpu->addrmode = CPUMODE_32BIT;     /* 64 bits */
+
+                iByte        += sizeof(uint8_t);
+                continue;   //fetch the next byte
+
+            // operand size override prefix byte
+            case OP_OPSIZE:
+                pCpu->prefix |= PREFIX_OPSIZE;
+                if (pCpu->mode == CPUMODE_16BIT)
+                    pCpu->opmode = CPUMODE_32BIT;
+                else
+                    pCpu->opmode = CPUMODE_16BIT;  /* for 32 and 64 bits mode (there is no 32 bits operand size override prefix) */
+
+                iByte        += sizeof(uint8_t);
+                continue;   //fetch the next byte
+
+            // rep and repne are not really prefixes, but we'll treat them as such
+            case OP_REPE:
+                pCpu->prefix |= PREFIX_REP;
+                iByte       += sizeof(uint8_t);
+                continue;   //fetch the next byte
+
+            case OP_REPNE:
+                pCpu->prefix |= PREFIX_REPNE;
+                iByte       += sizeof(uint8_t);
+                continue;   //fetch the next byte
+
+            case OP_REX:
+                Assert(pCpu->mode == CPUMODE_64BIT);
+                /* REX prefix byte */
+                pCpu->prefix    |= PREFIX_REX;
+                pCpu->prefix_rex = PREFIX_REX_OP_2_FLAGS(paOneByteMap[codebyte].param1);
+                iByte           += sizeof(uint8_t);
+
+                if (pCpu->prefix_rex & PREFIX_REX_FLAGS_W)
+                    pCpu->opmode = CPUMODE_64BIT;  /* overrides size prefix byte */
+                continue;   //fetch the next byte
             }
-
-            unsigned uIdx = iByte;
-            iByte += sizeof(uint8_t); //first opcode byte
-
-            pCpu->opaddr = InstructionAddr;
-            pCpu->opcode = codebyte;
-
-            cbInc = ParseInstruction(InstructionAddr + iByte, &paOneByteMap[pCpu->opcode], pCpu);
-            iByte += cbInc;
-            break;
-        }
-    }
-#ifdef IN_RING3
-# ifndef __L4ENV__
-    catch(...)
-# else
-    else  /* setjmp has returned a non-zero value: an exception occurred */
-# endif
-    {
-        pCpu->opsize = 0;
-        return VERR_DIS_GEN_FAILURE;
-    }
-#endif
-
+        }
+
+        unsigned uIdx = iByte;
+        iByte += sizeof(uint8_t); //first opcode byte
+
+        pCpu->opaddr = uInstrAddr;
+        pCpu->opcode = codebyte;
+
+        cbInc = ParseInstruction(uInstrAddr + iByte, &paOneByteMap[pCpu->opcode], pCpu);
+        iByte += cbInc;
+        break;
+    }
+
+    AssertMsg(pCpu->opsize == iByte || RT_FAILURE_NP(pCpu->rc), ("%u %u\n", pCpu->opsize, iByte));
     pCpu->opsize = iByte;
     if (pcbInstruction)
@@ -406,5 +336,5 @@
         disValidateLockSequence(pCpu);
 
-    return VINF_SUCCESS;
+    return pCpu->rc;
 }
 //*****************************************************************************
@@ -619,5 +549,5 @@
         {
             pParam->flags |= USE_DISPLACEMENT32;
-            pParam->disp32 = pCpu->disp;
+            pParam->disp32 = pCpu->i32SibDisp;
             disasmAddChar(pParam->szParam, '+');
             disasmPrintDisp32(pParam);
@@ -626,5 +556,5 @@
         {   /* sign-extend to 64 bits */
             pParam->flags |= USE_DISPLACEMENT64;
-            pParam->disp64 = pCpu->disp;
+            pParam->disp64 = pCpu->i32SibDisp;
             disasmAddChar(pParam->szParam, '+');
             disasmPrintDisp64(pParam);
@@ -666,5 +596,5 @@
     {
         /* Additional 32 bits displacement. No change in long mode. */
-        pCpu->disp = DISReadDWord(pCpu, lpszCodeBlock);
+        pCpu->i32SibDisp = DISReadDWord(pCpu, lpszCodeBlock);
         size += sizeof(int32_t);
     }
@@ -807,5 +737,5 @@
                 {
                     pParam->flags |= USE_DISPLACEMENT32;
-                    pParam->disp32 = pCpu->disp;
+                    pParam->disp32 = pCpu->i32SibDisp;
                     disasmPrintDisp32(pParam);
                 }
@@ -813,5 +743,5 @@
                 {
                     pParam->flags |= USE_RIPDISPLACEMENT32;
-                    pParam->disp32 = pCpu->disp;
+                    pParam->disp32 = pCpu->i32SibDisp;
                     disasmAddString(pParam->szParam, "RIP+");
                     disasmPrintDisp32(pParam);
@@ -836,5 +766,5 @@
                 disasmModRMReg(pCpu, pOp, rm, pParam, 1);
             }
-            pParam->disp8 = pCpu->disp;
+            pParam->disp8 = pCpu->i32SibDisp;
             pParam->flags |= USE_DISPLACEMENT8;
 
@@ -859,5 +789,5 @@
                 disasmModRMReg(pCpu, pOp, rm, pParam, 1);
             }
-            pParam->disp32 = pCpu->disp;
+            pParam->disp32 = pCpu->i32SibDisp;
             pParam->flags |= USE_DISPLACEMENT32;
 
@@ -884,5 +814,5 @@
             if (rm == 6)
             {//16 bits displacement
-                pParam->disp16 = pCpu->disp;
+                pParam->disp16 = pCpu->i32SibDisp;
                 pParam->flags |= USE_DISPLACEMENT16;
                 disasmPrintDisp16(pParam);
@@ -900,5 +830,5 @@
             disasmAddChar(pParam->szParam, '[');
             disasmModRMReg16(pCpu, pOp, rm, pParam);
-            pParam->disp8 = pCpu->disp;
+            pParam->disp8 = pCpu->i32SibDisp;
             pParam->flags |= USE_BASE | USE_DISPLACEMENT8;
 
@@ -916,5 +846,5 @@
             disasmAddChar(pParam->szParam, '[');
             disasmModRMReg16(pCpu, pOp, rm, pParam);
-            pParam->disp16 = pCpu->disp;
+            pParam->disp16 = pCpu->i32SibDisp;
             pParam->flags |= USE_BASE | USE_DISPLACEMENT16;
 
@@ -968,5 +898,5 @@
         case 0: /* Effective address */
             if (rm == 5) {  /* 32 bits displacement */
-                pCpu->disp = DISReadDWord(pCpu, lpszCodeBlock);
+                pCpu->i32SibDisp = DISReadDWord(pCpu, lpszCodeBlock);
                 size += sizeof(int32_t);
             }
@@ -975,10 +905,10 @@
 
         case 1: /* Effective address + 8 bits displacement */
-            pCpu->disp = (int8_t)DISReadByte(pCpu, lpszCodeBlock);
+            pCpu->i32SibDisp = (int8_t)DISReadByte(pCpu, lpszCodeBlock);
             size += sizeof(char);
             break;
 
         case 2: /* Effective address + 32 bits displacement */
-            pCpu->disp = DISReadDWord(pCpu, lpszCodeBlock);
+            pCpu->i32SibDisp = DISReadDWord(pCpu, lpszCodeBlock);
             size += sizeof(int32_t);
             break;
@@ -995,5 +925,5 @@
         case 0: /* Effective address */
             if (rm == 6) {
-                pCpu->disp = DISReadWord(pCpu, lpszCodeBlock);
+                pCpu->i32SibDisp = DISReadWord(pCpu, lpszCodeBlock);
                 size += sizeof(uint16_t);
             }
@@ -1002,10 +932,10 @@
 
         case 1: /* Effective address + 8 bits displacement */
-            pCpu->disp = (int8_t)DISReadByte(pCpu, lpszCodeBlock);
+            pCpu->i32SibDisp = (int8_t)DISReadByte(pCpu, lpszCodeBlock);
             size += sizeof(char);
             break;
 
         case 2: /* Effective address + 32 bits displacement */
-            pCpu->disp = (int16_t)DISReadWord(pCpu, lpszCodeBlock);
+            pCpu->i32SibDisp = (int16_t)DISReadWord(pCpu, lpszCodeBlock);
             size += sizeof(uint16_t);
             break;
@@ -2473,10 +2403,6 @@
 
     default:
-#ifdef IN_RING3
         Log(("disasmModRMReg %x:%x failed!!\n", type, subtype));
-        DIS_THROW(ExceptionInvalidModRM);
-#else
-        AssertMsgFailed(("Oops!\n"));
-#endif
+        pCpu->rc = VERR_DIS_INVALID_MODRM;
         break;
     }
@@ -2500,17 +2426,12 @@
 void disasmModRMSReg(PDISCPUSTATE pCpu, PCOPCODE pOp, unsigned idx, POP_PARAMETER pParam)
 {
-    NOREF(pCpu); NOREF(pOp);
-#if 0 //def DEBUG_Sander
-    AssertMsg(idx < RT_ELEMENTS(szModRMSegReg), ("idx=%d\n", idx));
-#endif
-#ifdef IN_RING3
+    NOREF(pOp);
     if (idx >= RT_ELEMENTS(szModRMSegReg))
     {
         Log(("disasmModRMSReg %d failed!!\n", idx));
-        DIS_THROW(ExceptionInvalidParameter);
-    }
-#endif
-
-    idx = RT_MIN(idx, RT_ELEMENTS(szModRMSegReg)-1);
+        pCpu->rc = VERR_DIS_INVALID_PARAMETER;
+        return;
+    }
+
     disasmAddString(pParam->szParam, szModRMSegReg[idx]);
     pParam->flags |= USE_REG_SEG;
@@ -2610,101 +2531,193 @@
         disasmAddStringF1(pParam->szParam, "%s:", szModRMSegReg[pCpu->enmPrefixSeg]);
 }
-//*****************************************************************************
-/* Read functions for getting the opcode bytes */
-//*****************************************************************************
-uint8_t DISReadByte(PDISCPUSTATE pCpu, RTUINTPTR pAddress)
-{
-    if (pCpu->pfnReadBytes)
-    {
-         uint8_t temp = 0;
-         int     rc;
-
-         rc = pCpu->pfnReadBytes(pAddress, &temp, sizeof(temp), pCpu);
-         if (RT_FAILURE(rc))
-         {
-             Log(("DISReadByte failed!!\n"));
-             DIS_THROW(ExceptionMemRead);
-         }
-         return temp;
-    }
-#ifdef IN_RING0
-    AssertMsgFailed(("DISReadByte with no read callback in ring 0!!\n"));
-    return 0;
-#else
-    return *(uint8_t *)(uintptr_t)pAddress;
-#endif
-}
-//*****************************************************************************
-//*****************************************************************************
-uint16_t DISReadWord(PDISCPUSTATE pCpu, RTUINTPTR pAddress)
-{
-    if (pCpu->pfnReadBytes)
-    {
-         uint16_t temp = 0;
-         int     rc;
-
-         rc = pCpu->pfnReadBytes(pAddress, (uint8_t*)&temp, sizeof(temp), pCpu);
-         if (RT_FAILURE(rc))
-         {
-             Log(("DISReadWord failed!!\n"));
-             DIS_THROW(ExceptionMemRead);
-         }
-         return temp;
-    }
+
+
+/**
+ * Slow path for storing instruction bytes.
+ *
+ * @param   pCpu                The disassembler state.
+ * @param   uAddress            The address.
+ * @param   pbSrc               The bytes.
+ * @param   cbSrc               The number of bytes.
+ */
+DECL_NO_INLINE(static, void)
+disStoreInstrBytesSlow(PDISCPUSTATE pCpu, RTUINTPTR uAddress, const uint8_t *pbSrc, size_t cbSrc)
+{
+    /*
+     * Figure out which case it is.
+     */
+    uint32_t  cbInstr = pCpu->opsize;
+    RTUINTPTR off     = uAddress - pCpu->uInstrAddr;
+    if (off < cbInstr)
+    {
+        if (off + cbSrc <= cbInstr)
+        {
+            AssertMsg(memcmp(&pCpu->abInstr[off], pbSrc, cbSrc) == 0,
+                      ("%RTptr LB %zx off=%RTptr (%.*Rhxs)", uAddress, cbSrc, off, cbInstr, pCpu->abInstr));
+            return; /* fully re-reading old stuff. */
+        }
+
+        /* Only partially re-reading stuff, skip ahead and add the rest. */
+        uint32_t cbAlreadyRead = cbInstr - (uint32_t)off;
+        Assert(memcmp(&pCpu->abInstr[off], pbSrc, cbAlreadyRead) == 0);
+        uAddress += cbAlreadyRead;
+        pbSrc    += cbAlreadyRead;
+        cbSrc    -= cbAlreadyRead;
+    }
+
+    if (off >= sizeof(cbInstr))
+    {
+        /* The instruction is too long! This shouldn't happen. */
+        AssertMsgFailed(("%RTptr LB %zx off=%RTptr (%.*Rhxs)", uAddress, cbSrc, off, cbInstr, pCpu->abInstr));
+        return;
+    }
+    else if (off > cbInstr)
+    {
+        /* Mind the gap - this shouldn't happen, but read the gap bytes if it does. */
+        AssertMsgFailed(("%RTptr LB %zx off=%RTptr (%.16Rhxs)", uAddress, cbSrc, off, cbInstr, pCpu->abInstr));
+        uint32_t cbGap = off - cbInstr;
+        int rc = pCpu->pfnReadBytes(pCpu, &pCpu->abInstr[cbInstr], uAddress - cbGap, cbGap);
+        if (RT_FAILURE(rc))
+        {
+            pCpu->rc = VERR_DIS_MEM_READ;
+            RT_BZERO(&pCpu->abInstr[cbInstr], cbGap);
+        }
+        pCpu->opsize = cbInstr = off;
+    }
+
+    /*
+     * Copy the bytes.
+     */
+    if (off + cbSrc <= sizeof(pCpu->abInstr))
+    {
+        memcpy(&pCpu->abInstr[cbInstr], pbSrc, cbSrc);
+        pCpu->opsize = cbInstr + cbSrc;
+    }
+    else
+    {
+        uint32_t cbToCopy = sizeof(pCpu->abInstr) - off;
+        memcpy(&pCpu->abInstr[cbInstr], pbSrc, cbToCopy);
+        pCpu->opsize = sizeof(pCpu->abInstr);
+        AssertMsgFailed(("%RTptr LB %zx off=%RTptr (%.*Rhxs)", uAddress, cbSrc, off, sizeof(pCpu->abInstr), pCpu->abInstr));
+    }
+}
+
+DECLCALLBACK(int) disReadBytesDefault(PDISCPUSTATE pCpu, uint8_t *pbDst, RTUINTPTR uSrcAddr, uint32_t cbToRead)
+{
 #ifdef IN_RING0
     AssertMsgFailed(("DISReadWord with no read callback in ring 0!!\n"));
-    return 0;
+    RT_BZERO(pbDst, cbToRead);
+    return VERR_DIS_NO_READ_CALLBACK;
 #else
-    return *(uint16_t *)(uintptr_t)pAddress;
+    memcpy(pbDst, (void const *)(uintptr_t)uSrcAddr, cbToRead);
+    return VINF_SUCCESS;
 #endif
 }
-//*****************************************************************************
-//*****************************************************************************
-uint32_t DISReadDWord(PDISCPUSTATE pCpu, RTUINTPTR pAddress)
-{
-    if (pCpu->pfnReadBytes)
-    {
-         uint32_t temp = 0;
-         int     rc;
-
-         rc = pCpu->pfnReadBytes(pAddress, (uint8_t*)&temp, sizeof(temp), pCpu);
-         if (RT_FAILURE(rc))
-         {
-             Log(("DISReadDWord failed!!\n"));
-             DIS_THROW(ExceptionMemRead);
-         }
-         return temp;
-    }
-#ifdef IN_RING0
-    AssertMsgFailed(("DISReadDWord with no read callback in ring 0!!\n"));
-    return 0;
-#else
-    return *(uint32_t *)(uintptr_t)pAddress;
-#endif
-}
-//*****************************************************************************
-//*****************************************************************************
-uint64_t DISReadQWord(PDISCPUSTATE pCpu, RTUINTPTR pAddress)
-{
-    if (pCpu->pfnReadBytes)
-    {
-         uint64_t temp = 0;
-         int     rc;
-
-         rc = pCpu->pfnReadBytes(pAddress, (uint8_t*)&temp, sizeof(temp), pCpu);
-         if (RT_FAILURE(rc))
-         {
-             Log(("DISReadQWord %x failed!!\n", pAddress));
-             DIS_THROW(ExceptionMemRead);
-         }
-
-         return temp;
-    }
-#ifdef IN_RING0
-    AssertMsgFailed(("DISReadQWord with no read callback in ring 0!!\n"));
-    return 0;
-#else
-    return *(uint64_t *)(uintptr_t)pAddress;
-#endif
+
+//*****************************************************************************
+/* Read functions for getting the opcode bytes */
+//*****************************************************************************
+uint8_t DISReadByte(PDISCPUSTATE pCpu, RTUINTPTR uAddress)
+{
+    uint8_t bTemp = 0;
+    int rc = pCpu->pfnReadBytes(pCpu, &bTemp, uAddress, sizeof(bTemp));
+    if (RT_FAILURE(rc))
+    {
+        Log(("DISReadByte failed!!\n"));
+        pCpu->rc = VERR_DIS_MEM_READ;
+    }
+
+/** @todo change this into reading directly into abInstr and use it as a
+ *        cache. */
+    if (RT_LIKELY(   pCpu->uInstrAddr + pCpu->opsize == uAddress
+                  && pCpu->opsize + sizeof(bTemp) < sizeof(pCpu->abInstr)))
+        pCpu->abInstr[pCpu->opsize++] = bTemp;
+    else
+        disStoreInstrBytesSlow(pCpu, uAddress, &bTemp, sizeof(bTemp));
+
+    return bTemp;
+}
+//*****************************************************************************
+//*****************************************************************************
+uint16_t DISReadWord(PDISCPUSTATE pCpu, RTUINTPTR uAddress)
+{
+    RTUINT16U uTemp;
+    uTemp.u = 0;
+    int rc = pCpu->pfnReadBytes(pCpu, uTemp.au8, uAddress, sizeof(uTemp));
+    if (RT_FAILURE(rc))
+    {
+        Log(("DISReadWord failed!!\n"));
+        pCpu->rc = VERR_DIS_MEM_READ;
+    }
+
+    if (RT_LIKELY(   pCpu->uInstrAddr + pCpu->opsize == uAddress
+                  && pCpu->opsize + sizeof(uTemp) < sizeof(pCpu->abInstr)))
+    {
+        pCpu->abInstr[pCpu->opsize    ] = uTemp.au8[0];
+        pCpu->abInstr[pCpu->opsize + 1] = uTemp.au8[1];
+        pCpu->opsize += 2;
+    }
+    else
+        disStoreInstrBytesSlow(pCpu, uAddress, uTemp.au8, sizeof(uTemp));
+
+    return uTemp.u;
+}
+//*****************************************************************************
+//*****************************************************************************
+uint32_t DISReadDWord(PDISCPUSTATE pCpu, RTUINTPTR uAddress)
+{
+    RTUINT32U uTemp;
+    uTemp.u = 0;
+    int rc = pCpu->pfnReadBytes(pCpu, uTemp.au8, uAddress, sizeof(uTemp));
+    if (RT_FAILURE(rc))
+    {
+        Log(("DISReadDWord failed!!\n"));
+        pCpu->rc = VERR_DIS_MEM_READ;
+    }
+
+    if (RT_LIKELY(   pCpu->uInstrAddr + pCpu->opsize == uAddress
+                  && pCpu->opsize + sizeof(uTemp) < sizeof(pCpu->abInstr)))
+    {
+        pCpu->abInstr[pCpu->opsize    ] = uTemp.au8[0];
+        pCpu->abInstr[pCpu->opsize + 1] = uTemp.au8[1];
+        pCpu->abInstr[pCpu->opsize + 2] = uTemp.au8[2];
+        pCpu->abInstr[pCpu->opsize + 3] = uTemp.au8[3];
+        pCpu->opsize += 4;
+    }
+    else
+        disStoreInstrBytesSlow(pCpu, uAddress, uTemp.au8, sizeof(uTemp));
+
+    return uTemp.u;
+}
+//*****************************************************************************
+//*****************************************************************************
+uint64_t DISReadQWord(PDISCPUSTATE pCpu, RTUINTPTR uAddress)
+{
+    RTUINT64U uTemp;
+    uTemp.u = 0;
+    int rc = pCpu->pfnReadBytes(pCpu, uTemp.au8, uAddress, sizeof(uTemp));
+    if (RT_FAILURE(rc))
+    {
+        Log(("DISReadQWord %x failed!!\n", uAddress));
+        pCpu->rc = VERR_DIS_MEM_READ;
+    }
+
+    if (RT_LIKELY(   pCpu->uInstrAddr + pCpu->opsize == uAddress
+                  && pCpu->opsize + sizeof(uTemp) < sizeof(pCpu->abInstr)))
+    {
+        pCpu->abInstr[pCpu->opsize    ] = uTemp.au8[0];
+        pCpu->abInstr[pCpu->opsize + 1] = uTemp.au8[1];
+        pCpu->abInstr[pCpu->opsize + 2] = uTemp.au8[2];
+        pCpu->abInstr[pCpu->opsize + 3] = uTemp.au8[3];
+        pCpu->abInstr[pCpu->opsize + 4] = uTemp.au8[4];
+        pCpu->abInstr[pCpu->opsize + 5] = uTemp.au8[5];
+        pCpu->abInstr[pCpu->opsize + 6] = uTemp.au8[6];
+        pCpu->abInstr[pCpu->opsize + 7] = uTemp.au8[7];
+        pCpu->opsize += 4;
+    }
+    else
+        disStoreInstrBytesSlow(pCpu, uAddress, uTemp.au8, sizeof(uTemp));
+
+    return uTemp.u;
 }
 
Index: /trunk/src/VBox/Disassembler/DisasmFormatBytes.cpp
===================================================================
--- /trunk/src/VBox/Disassembler/DisasmFormatBytes.cpp	(revision 41657)
+++ /trunk/src/VBox/Disassembler/DisasmFormatBytes.cpp	(revision 41658)
@@ -5,5 +5,5 @@
 
 /*
- * Copyright (C) 2008 Oracle Corporation
+ * Copyright (C) 2008-2012 Oracle Corporation
  *
  * This file is part of VirtualBox Open Source Edition (OSE), as
@@ -38,37 +38,8 @@
 size_t disFormatBytes(PCDISCPUSTATE pCpu, char *pszDst, size_t cchDst, uint32_t fFlags)
 {
-    /*
-     * Read the bytes first.
-     */
-    uint8_t     ab[16];
-    uint32_t    cb = pCpu->opsize;
-    Assert(cb <= 16);
-    if (cb > 16)
-        cb = 16;
+    size_t      cchOutput = 0;
+    uint32_t    cb        = pCpu->opsize;
+    AssertStmt(cb <= 16, cb = 16);
 
-    if (pCpu->pfnReadBytes)
-    {
-        int rc = pCpu->pfnReadBytes(pCpu->opaddr, &ab[0], cb, (void *)pCpu);
-        if (RT_FAILURE(rc))
-        {
-            for (uint32_t i = 0; i < cb; i++)
-            {
-                int rc2 = pCpu->pfnReadBytes(pCpu->opaddr + i, &ab[i], 1, (void *)pCpu);
-                if (RT_FAILURE(rc2))
-                    ab[i] = 0xcc;
-            }
-        }
-    }
-    else
-    {
-        uint8_t const *pabSrc = (uint8_t const *)(uintptr_t)pCpu->opaddr;
-        for (uint32_t i = 0; i < cb; i++)
-            ab[i] = pabSrc[i];
-    }
-
-    /*
-     * Now for the output.
-     */
-    size_t cchOutput = 0;
 #define PUT_C(ch) \
             do { \
@@ -98,7 +69,7 @@
     {
         if (i != 0 && (fFlags & DIS_FMT_FLAGS_BYTES_SPACED))
-            PUT_NUM(3, " %02x", ab[i]);
+            PUT_NUM(3, " %02x", pCpu->abInstr[i]);
         else
-            PUT_NUM(2, "%02x", ab[i]);
+            PUT_NUM(2, "%02x", pCpu->abInstr[i]);
     }
 
Index: /trunk/src/VBox/Disassembler/DisasmFormatYasm.cpp
===================================================================
--- /trunk/src/VBox/Disassembler/DisasmFormatYasm.cpp	(revision 41657)
+++ /trunk/src/VBox/Disassembler/DisasmFormatYasm.cpp	(revision 41658)
@@ -689,8 +689,9 @@
                                 PUT_SZ("word ");
                             else if (   (pParam->flags & USE_DISPLACEMENT32)
-                                     && (int8_t)pParam->disp32 == (int32_t)pParam->disp32)
+                                     && (int16_t)pParam->disp32 == (int32_t)pParam->disp32) //??
                                 PUT_SZ("dword ");
                             else if (   (pParam->flags & USE_DISPLACEMENT64)
-                                     && (int8_t)pParam->disp64 == (int64_t)pParam->disp32)
+                                     && (pCpu->SIB.Bits.Base != 5 || pCpu->ModRM.Bits.Mod != 0)
+                                     && (int32_t)pParam->disp64 == (int64_t)pParam->disp64) //??
                                 PUT_SZ("qword ");
                         }
@@ -1231,5 +1232,5 @@
     {
         uint32_t f;
-        switch (DISReadByte(pCpu, offOpcode + pCpu->opaddr))
+        switch (pCpu->abInstr[offOpcode])
         {
             case 0xf0:
Index: /trunk/src/VBox/Disassembler/DisasmInternal.h
===================================================================
--- /trunk/src/VBox/Disassembler/DisasmInternal.h	(revision 41657)
+++ /trunk/src/VBox/Disassembler/DisasmInternal.h	(revision 41658)
@@ -70,12 +70,4 @@
 #define IDX_ParseImmAddrF           40
 #define IDX_ParseMax                (IDX_ParseImmAddrF+1)
-
-#if defined(IN_RING0) || defined(IN_RC)
-#define DIS_THROW(a)                /* Not available. */
-#elif  __L4ENV__
-#define DIS_THROW(a)                longjmp(*pCpu->pJumpBuffer, a)
-#else
-#define DIS_THROW(a)                throw(a)
-#endif
 
 
@@ -161,4 +153,5 @@
 
 /* Read functions */
+DECLCALLBACK(int) disReadBytesDefault(PDISCPUSTATE pCpu, uint8_t *pbDst, RTUINTPTR uSrcAddr, uint32_t cbToRead);
 uint8_t  DISReadByte(PDISCPUSTATE pCpu, RTUINTPTR pAddress);
 uint16_t DISReadWord(PDISCPUSTATE pCpu, RTUINTPTR pAddress);
Index: /trunk/src/VBox/Disassembler/DisasmTest.cpp
===================================================================
--- /trunk/src/VBox/Disassembler/DisasmTest.cpp	(revision 41657)
+++ /trunk/src/VBox/Disassembler/DisasmTest.cpp	(revision 41658)
@@ -48,9 +48,7 @@
             unsigned    cb;
             DISCPUSTATE cpu;
-            char         szOutput[256];
+            char        szOutput[256];
 
-            memset(&cpu, 0, sizeof(cpu));
-            cpu.mode = CPUMODE_32BIT;
-            if (RT_SUCCESS(DISInstr(&cpu, pInstr, 0, &cb, szOutput)))
+            if (RT_SUCCESS(DISInstr(pInstr, CPUMODE_32BIT, &cpu, &cb, szOutput)))
             {
                 printf("%s", szOutput);
@@ -73,9 +71,7 @@
             unsigned    cb;
             DISCPUSTATE cpu;
-            char         szOutput[256];
+            char        szOutput[256];
 
-            memset(&cpu, 0, sizeof(cpu));
-            cpu.mode = CPUMODE_64BIT;
-            if (RT_SUCCESS(DISInstr(&cpu, pInstr, 0, &cb, szOutput)))
+            if (RT_SUCCESS(DISInstr(pInstr, CPUMODE_64BIT, &cpu, &cb, szOutput)))
                 printf("%s", szOutput);
             else
Index: /trunk/src/VBox/Disassembler/DisasmTestCore.cpp
===================================================================
--- /trunk/src/VBox/Disassembler/DisasmTestCore.cpp	(revision 41657)
+++ /trunk/src/VBox/Disassembler/DisasmTestCore.cpp	(revision 41658)
@@ -39,6 +39,5 @@
         unsigned    cb;
         DISCPUSTATE cpu;
-        cpu.mode = CPUMODE_32BIT;
-        if (DISCoreOne(&cpu, (uintptr_t)&DISCoreOne, &cb))
+        if (DISCoreOneEx((uintptr_t)&DISCoreOneEx, CPUMODE_32BIT, NULL /*pfnReadBytes*/, NULL /*pvUser*/, &cpu, &cb))
             printf("ok %d\n", cpu.addrmode);
         else
Index: /trunk/src/VBox/Disassembler/testcase/Makefile.kmk
===================================================================
--- /trunk/src/VBox/Disassembler/testcase/Makefile.kmk	(revision 41657)
+++ /trunk/src/VBox/Disassembler/testcase/Makefile.kmk	(revision 41658)
@@ -60,4 +60,8 @@
 #	$(PATH_STAGE_BIN)/testcase/tstDisasm-2$(SUFF_EXEC)
 endif
+VBOX_DISAS_TESTS_BINARIES_NOT_16BIT := \
+	tstBinFnstsw-1.bin
+VBOX_DISAS_TESTS_BINARIES_NOT_32BIT :=
+VBOX_DISAS_TESTS_BINARIES_NOT_64BIT :=
 
 
@@ -195,6 +199,7 @@
 
 ## @todo 64-bit is problematic because of bugs like POP RDI ending up as POP EDI (incorrect default opmode).
-#$(foreach bits, 32 16 64, $(foreach binary, $(VBOX_DISAS_TESTS_BINARIES), $(evalvalctx def_vbox_disas_binary)))
-$(foreach bits, 32 16, $(foreach binary, $(VBOX_DISAS_TESTS_BINARIES), $(evalvalctx def_vbox_disas_binary)))
+#$(foreach bits, 64, $(foreach binary, $(VBOX_DISAS_TESTS_BINARIES), $(evalvalctx def_vbox_disas_binary)))
+$(foreach bits, 32 16, $(foreach binary, $(filter-out $(VBOX_DISAS_TESTS_BINARIES_NOT_$(bits)BIT), $(VBOX_DISAS_TESTS_BINARIES)) \
+	, $(evalvalctx def_vbox_disas_binary)))
 
 
Index: /trunk/src/VBox/Disassembler/testcase/tstDisasm-2.cpp
===================================================================
--- /trunk/src/VBox/Disassembler/testcase/tstDisasm-2.cpp	(revision 41657)
+++ /trunk/src/VBox/Disassembler/testcase/tstDisasm-2.cpp	(revision 41658)
@@ -171,14 +171,14 @@
  *       however the current doesn't do this and is just complicated...
  */
-static DECLCALLBACK(int) MyDisasInstrRead(RTUINTPTR uSrcAddr, uint8_t *pbDst, uint32_t cbRead, void *pvDisCpu)
-{
-    PMYDISSTATE pState = (PMYDISSTATE)pvDisCpu;
+static DECLCALLBACK(int) MyDisasInstrRead(PDISCPUSTATE pDisState, uint8_t *pbDst, RTUINTPTR uSrcAddr, uint32_t cbToRead)
+{
+    PMYDISSTATE pState = (PMYDISSTATE)pDisState;
     if (RT_LIKELY(   pState->uNextAddr == uSrcAddr
-                  && pState->cbLeft >= cbRead))
+                  && pState->cbLeft >= cbToRead))
     {
         /*
          * Straight forward reading.
          */
-        if (cbRead == 1)
+        if (cbToRead == 1)
         {
             pState->cbLeft--;
@@ -188,8 +188,8 @@
         else
         {
-            memcpy(pbDst, pState->pbNext, cbRead);
-            pState->pbNext += cbRead;
-            pState->cbLeft -= cbRead;
-            pState->uNextAddr += cbRead;
+            memcpy(pbDst, pState->pbNext, cbToRead);
+            pState->pbNext += cbToRead;
+            pState->cbLeft -= cbToRead;
+            pState->uNextAddr += cbToRead;
         }
     }
@@ -211,5 +211,5 @@
                 pState->cbLeft = 0;
 
-                memset(pbDst, 0xcc, cbRead);
+                memset(pbDst, 0xcc, cbToRead);
                 pState->rc = VERR_EOF;
                 return VERR_EOF;
@@ -227,10 +227,10 @@
 
             /* do the reading. */
-            if (pState->cbLeft >= cbRead)
-            {
-                memcpy(pbDst, pState->pbNext, cbRead);
-                pState->cbLeft -= cbRead;
-                pState->pbNext += cbRead;
-                pState->uNextAddr += cbRead;
+            if (pState->cbLeft >= cbToRead)
+            {
+                memcpy(pbDst, pState->pbNext, cbToRead);
+                pState->cbLeft -= cbToRead;
+                pState->pbNext += cbToRead;
+                pState->uNextAddr += cbToRead;
             }
             else
@@ -240,10 +240,10 @@
                     memcpy(pbDst, pState->pbNext, pState->cbLeft);
                     pbDst += pState->cbLeft;
-                    cbRead -= (uint32_t)pState->cbLeft;
+                    cbToRead -= (uint32_t)pState->cbLeft;
                     pState->pbNext += pState->cbLeft;
                     pState->uNextAddr += pState->cbLeft;
                     pState->cbLeft = 0;
                 }
-                memset(pbDst, 0xcc, cbRead);
+                memset(pbDst, 0xcc, cbToRead);
                 pState->rc = VERR_EOF;
                 return VERR_EOF;
@@ -253,5 +253,5 @@
         {
             RTStrmPrintf(g_pStdErr, "Reading before current instruction!\n");
-            memset(pbDst, 0x90, cbRead);
+            memset(pbDst, 0x90, cbToRead);
             pState->rc = VERR_INTERNAL_ERROR;
             return VERR_INTERNAL_ERROR;
@@ -286,6 +286,4 @@
      */
     MYDISSTATE State;
-    State.Cpu.mode = enmCpuMode;
-    State.Cpu.pfnReadBytes = MyDisasInstrRead;
     State.uAddress = uAddress;
     State.pbInstr = pbFile;
@@ -331,5 +329,7 @@
         State.pbNext = State.pbInstr;
 
-        int rc = DISInstr(&State.Cpu, State.uAddress, 0, &State.cbInstr, State.szLine);
+
+        int rc = DISInstrWithReader(State.uAddress, enmCpuMode, MyDisasInstrRead, &State,
+                                    &State.Cpu, &State.cbInstr, State.szLine);
         if (    RT_SUCCESS(rc)
             ||  (   (   rc == VERR_DIS_INVALID_OPCODE
@@ -345,13 +345,13 @@
             if (State.fUndefOp && State.enmUndefOp == kUndefOp_DefineByte)
             {
+                if (!State.cbInstr)
+                {
+                    State.Cpu.abInstr[0] = 0;
+                    State.Cpu.pfnReadBytes(&State.Cpu, &State.Cpu.abInstr[0], State.uAddress, 1);
+                    State.cbInstr = 1;
+                }
                 RTPrintf("    db");
-                if (!State.cbInstr)
-                    State.cbInstr = 1;
                 for (unsigned off = 0; off < State.cbInstr; off++)
-                {
-                    uint8_t b;
-                    State.Cpu.pfnReadBytes(State.uAddress + off, &b, 1, &State.Cpu);
-                    RTPrintf(off ? ", %03xh" : " %03xh", b);
-                }
+                    RTPrintf(off ? ", %03xh" : " %03xh", State.Cpu.abInstr[off]);
                 RTPrintf("    ; %s\n", State.szLine);
             }
@@ -376,9 +376,5 @@
                     RTPrintf("    db");
                     for (unsigned off = 0; off < State.cbInstr; off++)
-                    {
-                        uint8_t b;
-                        State.Cpu.pfnReadBytes(State.uAddress + off, &b, 1, &State.Cpu);
-                        RTPrintf(off ? ", %03xh" : " %03xh", b);
-                    }
+                        RTPrintf(off ? ", %03xh" : " %03xh", State.Cpu.abInstr[off]);
                     RTPrintf(" ; ");
                 }
Index: /trunk/src/VBox/Runtime/testcase/tstLdr-2.cpp
===================================================================
--- /trunk/src/VBox/Runtime/testcase/tstLdr-2.cpp	(revision 41657)
+++ /trunk/src/VBox/Runtime/testcase/tstLdr-2.cpp	(revision 41658)
@@ -46,5 +46,5 @@
         char        szOutput[256];
         uint32_t    cbInstr;
-        if (RT_FAILURE(DISInstr(pCpu, pvCodeBlock + i, off, &cbInstr, szOutput)))
+        if (RT_FAILURE(DISInstrWithOff(pCpu, pvCodeBlock + i, off, &cbInstr, szOutput)))
             return false;
 
Index: /trunk/src/VBox/Runtime/testcase/tstLdr-3.cpp
===================================================================
--- /trunk/src/VBox/Runtime/testcase/tstLdr-3.cpp	(revision 41657)
+++ /trunk/src/VBox/Runtime/testcase/tstLdr-3.cpp	(revision 41658)
@@ -144,8 +144,10 @@
 
 
-static DECLCALLBACK(int) MyReadBytes(RTUINTPTR uSrc, uint8_t *pbDst, unsigned cb, void *pvUser)
-{
-    PDISCPUSTATE pCpu = (PDISCPUSTATE)pvUser;
-    memcpy(pbDst, (uint8_t const *)((uintptr_t)uSrc + (uintptr_t)pCpu->apvUserData[0]), cb);
+/**
+ * @callback_method_impl{FNDISREADBYTES}
+ */
+static DECLCALLBACK(int) MyReadBytes(PDISCPUSTATE pDisState, uint8_t *pbDst, RTUINTPTR uSrcAddr, uint32_t cbToRead)
+{
+    memcpy(pbDst, (uint8_t const *)((uintptr_t)uSrcAddr + (uintptr_t)pDisState->apvUserData[0]), cbToRead);
     return VINF_SUCCESS;
 }
Index: /trunk/src/VBox/Runtime/testcase/tstLdrDisasmTest.cpp
===================================================================
--- /trunk/src/VBox/Runtime/testcase/tstLdrDisasmTest.cpp	(revision 41657)
+++ /trunk/src/VBox/Runtime/testcase/tstLdrDisasmTest.cpp	(revision 41658)
@@ -80,14 +80,18 @@
 
 
-DECLCALLBACK(int) DisasmTest1ReadCode(RTUINTPTR SrcAddr, uint8_t *pbDst, uint32_t cb, void *pvUser)
+/**
+ * @callback_method_impl{FNDISREADBYTES}
+ */
+static DECLCALLBACK(int) DisasmTest1ReadCode(PDISCPUSTATE pDisState, uint8_t *pbDst, RTUINTPTR uSrcAddr, uint32_t cbToRead)
 {
-    NOREF(pvUser);
-    while (cb > 0)
+    NOREF(pDisState);
+    while (cbToRead > 0)
     {
-        *pbDst = g_ab32BitCode[SrcAddr];
+        *pbDst = g_ab32BitCode[uSrcAddr];
+
         /* next */
         pbDst++;
-        SrcAddr++;
-        cb--;
+        uSrcAddr++;
+        cbToRead--;
     }
     return 0;
Index: /trunk/src/VBox/Runtime/testcase/tstLdrObj.cpp
===================================================================
--- /trunk/src/VBox/Runtime/testcase/tstLdrObj.cpp	(revision 41657)
+++ /trunk/src/VBox/Runtime/testcase/tstLdrObj.cpp	(revision 41658)
@@ -98,7 +98,5 @@
     static unsigned cb;
     DISCPUSTATE Cpu;
-    memset(&Cpu, 0, sizeof(Cpu));
-    Cpu.mode = CPUMODE_32BIT;
-    DISCoreOne(&Cpu, (uintptr_t)SomeExportFunction3, &cb);
+    DISCoreOneEx((uintptr_t)SomeExportFunction3, CPUMODE_32BIT, NULL /*pfnReadBytes*/, NULL /*pvUser*/, &Cpu, &cb);
     return (void *)(uintptr_t)&SomeExportFunction1;
 }
Index: /trunk/src/VBox/Runtime/testcase/tstLdrObjR0.cpp
===================================================================
--- /trunk/src/VBox/Runtime/testcase/tstLdrObjR0.cpp	(revision 41657)
+++ /trunk/src/VBox/Runtime/testcase/tstLdrObjR0.cpp	(revision 41658)
@@ -98,5 +98,5 @@
     Cpu.mode = CPUMODE_32BIT;
 
-    DISCoreOne(&Cpu, (uintptr_t)SomeExportFunction3, &cb);
+    DISCoreOneEx((uintptr_t)SomeExportFunction3, CPUMODE_32BIT, NULL /*pfnReadBytes*/, NULL /*pvUser*/, &Cpu, &cb);
     return (void *)(uintptr_t)&SomeExportFunction1;
 }
Index: /trunk/src/VBox/VMM/VMMAll/EMAll.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMAll/EMAll.cpp	(revision 41657)
+++ /trunk/src/VBox/VMM/VMMAll/EMAll.cpp	(revision 41658)
@@ -5,5 +5,5 @@
 
 /*
- * Copyright (C) 2006-2007 Oracle Corporation
+ * Copyright (C) 2006-2012 Oracle Corporation
  *
  * This file is part of VirtualBox Open Source Edition (OSE), as
@@ -282,17 +282,9 @@
 
 /**
- * Read callback for disassembly function; supports reading bytes that cross a page boundary
- *
- * @returns VBox status code.
- * @param   pSrc        GC source pointer
- * @param   pDest       HC destination pointer
- * @param   cb          Number of bytes to read
- * @param   dwUserdata  Callback specific user data (pDis)
- *
- */
-static DECLCALLBACK(int) emReadBytes(RTUINTPTR pSrc, uint8_t *pDest, unsigned cb, void *pvUserdata)
-{
-    PDISCPUSTATE  pDis   = (PDISCPUSTATE)pvUserdata;
-    PEMDISSTATE   pState = (PEMDISSTATE)pDis->apvUserData[0];
+ * @callback_method_impl{FNDISREADBYTES}
+ */
+static DECLCALLBACK(int) emReadBytes(PDISCPUSTATE pDisState, uint8_t *pbDst, RTUINTPTR uSrcAddr, uint32_t cbToRead)
+{
+    PEMDISSTATE   pState = (PEMDISSTATE)pDisState->apvUserData[0];
 # ifndef IN_RING0
     PVM           pVM    = pState->pVM;
@@ -304,38 +296,38 @@
 
     if (    pState->GCPtr
-        &&  pSrc + cb <= pState->GCPtr + sizeof(pState->aOpcode))
-    {
-        unsigned offset = pSrc - pState->GCPtr;
-        Assert(pSrc >= pState->GCPtr);
-
-        for (unsigned i = 0; i < cb; i++)
-            pDest[i] = pState->aOpcode[offset + i];
+        &&  uSrcAddr + cbToRead <= pState->GCPtr + sizeof(pState->aOpcode))
+    {
+        unsigned offset = uSrcAddr - pState->GCPtr;
+        Assert(uSrcAddr >= pState->GCPtr);
+
+        for (unsigned i = 0; i < cbToRead; i++)
+            pbDst[i] = pState->aOpcode[offset + i];
         return VINF_SUCCESS;
     }
 
-    rc = PGMPhysSimpleReadGCPtr(pVCpu, pDest, pSrc, cb);
-    AssertMsgRC(rc, ("PGMPhysSimpleReadGCPtr failed for pSrc=%RGv cb=%x rc=%d\n", pSrc, cb, rc));
+    rc = PGMPhysSimpleReadGCPtr(pVCpu, pbDst, uSrcAddr, cbToRead);
+    AssertMsgRC(rc, ("PGMPhysSimpleReadGCPtr failed for uSrcAddr=%RTptr cbToRead=%x rc=%d\n", uSrcAddr, cbToRead, rc));
 # elif defined(IN_RING3)
-    if (!PATMIsPatchGCAddr(pVM, pSrc))
-    {
-        int rc = PGMPhysSimpleReadGCPtr(pVCpu, pDest, pSrc, cb);
+    if (!PATMIsPatchGCAddr(pVM, uSrcAddr))
+    {
+        int rc = PGMPhysSimpleReadGCPtr(pVCpu, pbDst, uSrcAddr, cbToRead);
         AssertRC(rc);
     }
     else
-        memcpy(pDest, PATMR3GCPtrToHCPtr(pVM, pSrc), cb);
+        memcpy(pbDst, PATMR3GCPtrToHCPtr(pVM, uSrcAddr), cbToRead);
 
 # elif defined(IN_RC)
-    if (!PATMIsPatchGCAddr(pVM, pSrc))
-    {
-        int rc = MMGCRamRead(pVM, pDest, (void *)(uintptr_t)pSrc, cb);
+    if (!PATMIsPatchGCAddr(pVM, uSrcAddr))
+    {
+        int rc = MMGCRamRead(pVM, pbDst, (void *)(uintptr_t)uSrcAddr, cbToRead);
         if (rc == VERR_ACCESS_DENIED)
         {
             /* Recently flushed; access the data manually. */
-            rc = PGMPhysSimpleReadGCPtr(pVCpu, pDest, pSrc, cb);
+            rc = PGMPhysSimpleReadGCPtr(pVCpu, pbDst, uSrcAddr, cbToRead);
             AssertRC(rc);
         }
     }
     else /* the hypervisor region is always present. */
-        memcpy(pDest, (RTRCPTR)(uintptr_t)pSrc, cb);
+        memcpy(pbDst, (RTRCPTR)(uintptr_t)uSrcAddr, cbToRead);
 
 # endif /* IN_RING3 */
@@ -343,6 +335,6 @@
 }
 
-
 #ifndef IN_RC
+
 DECLINLINE(int) emDisCoreOne(PVM pVM, PVMCPU pVCpu, PDISCPUSTATE pDis, RTGCUINTPTR InstrGC, uint32_t *pOpsize)
 {
@@ -467,5 +459,6 @@
 #endif
 
-    rc = DISCoreOneEx(GCPtrInstr, SELMGetCpuModeFromSelector(pVCpu, pCtxCore->eflags, pCtxCore->cs, (PCPUMSELREGHID)&pCtxCore->csHid),
+    rc = DISCoreOneEx(GCPtrInstr,
+                      SELMGetCpuModeFromSelector(pVCpu, pCtxCore->eflags, pCtxCore->cs, (PCPUMSELREGHID)&pCtxCore->csHid),
                       emReadBytes, &State,
                       pDis, pcbInstr);
@@ -659,5 +652,5 @@
     Assert(!CPUMIsGuestIn64BitCode(pVCpu, pRegFrame));
     /** @todo Rainy day: Test what happens when VERR_EM_INTERPRETER is returned by
-     *        this function.  Faire that it may guru on us, thus not converted to
+     *        this function.  Fear that it may guru on us, thus not converted to
      *        IEM. */
 
Index: /trunk/src/VBox/VMM/VMMR3/CPUM.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMR3/CPUM.cpp	(revision 41657)
+++ /trunk/src/VBox/VMM/VMMR3/CPUM.cpp	(revision 41658)
@@ -906,5 +906,5 @@
             pCPUM->aGuestCpuIdCentaur[i] = pCPUM->GuestCpuIdDef;
 
-    /* 
+    /*
      * Hypervisor identification.
      *
@@ -3525,22 +3525,13 @@
 
 /**
- * Instruction reader.
- *
- * @returns VBox status code.
- * @param   PtrSrc      Address to read from.
- *                      In our case this is relative to the selector pointed to by the 2nd user argument of uDisCpu.
- * @param   pu8Dst      Where to store the bytes.
- * @param   cbRead      Number of bytes to read.
- * @param   uDisCpu     Pointer to the disassembler cpu state.
- *                      In this context it's always pointer to the Core of a DBGFDISASSTATE.
- */
-static DECLCALLBACK(int) cpumR3DisasInstrRead(RTUINTPTR PtrSrc, uint8_t *pu8Dst, unsigned cbRead, void *uDisCpu)
-{
-    PDISCPUSTATE pCpu = (PDISCPUSTATE)uDisCpu;
-    PCPUMDISASSTATE pState = (PCPUMDISASSTATE)pCpu->apvUserData[0];
-    Assert(cbRead > 0);
+ * @callback_method_impl{FNDISREADBYTES}
+ */
+static DECLCALLBACK(int) cpumR3DisasInstrRead(PDISCPUSTATE pDisState, uint8_t *pbDst, RTUINTPTR uSrcAddr, uint32_t cbToRead)
+{
+    PCPUMDISASSTATE pState = (PCPUMDISASSTATE)pDisState->apvUserData[0];
+    Assert(cbToRead > 0);
     for (;;)
     {
-        RTGCUINTPTR GCPtr = PtrSrc + pState->GCPtrSegBase;
+        RTGCUINTPTR GCPtr = uSrcAddr + pState->GCPtrSegBase;
 
         /* Need to update the page translation? */
@@ -3575,5 +3566,5 @@
 
         /* check the segment limit */
-        if (!pState->f64Bits && PtrSrc > pState->cbSegLimit)
+        if (!pState->f64Bits && uSrcAddr > pState->cbSegLimit)
             return VERR_OUT_OF_SELECTOR_BOUNDS;
 
@@ -3586,14 +3577,14 @@
                 cb = cbSeg;
         }
-        if (cb > cbRead)
-            cb = cbRead;
+        if (cb > cbToRead)
+            cb = cbToRead;
 
         /* read and advance */
-        memcpy(pu8Dst, (char *)pState->pvPageR3 + (GCPtr & PAGE_OFFSET_MASK), cb);
-        cbRead -= cb;
-        if (!cbRead)
+        memcpy(pbDst, (char *)pState->pvPageR3 + (GCPtr & PAGE_OFFSET_MASK), cb);
+        cbToRead -= cb;
+        if (!cbToRead)
             return VINF_SUCCESS;
-        pu8Dst += cb;
-        PtrSrc += cb;
+        pbDst    += cb;
+        uSrcAddr += cb;
     }
 }
@@ -3629,4 +3620,5 @@
      * Get selector information.
      */
+    DISCPUMODE enmDisCpuMode;
     if (    (pCtx->cr0 & X86_CR0_PE)
         &&   pCtx->eflags.Bits.u1VM == 0)
@@ -3638,5 +3630,5 @@
             State.GCPtrSegEnd     = pCtx->csHid.u32Limit + 1 + (RTGCUINTPTR)pCtx->csHid.u64Base;
             State.cbSegLimit      = pCtx->csHid.u32Limit;
-            pCpu->mode            = (State.f64Bits)
+            enmDisCpuMode         = (State.f64Bits)
                                     ? CPUMODE_64BIT
                                     : pCtx->csHid.Attr.n.u1DefBig
@@ -3667,5 +3659,5 @@
             State.GCPtrSegEnd     = SelInfo.cbLimit + 1 + (RTGCUINTPTR)SelInfo.GCPtrBase;
             State.cbSegLimit      = SelInfo.cbLimit;
-            pCpu->mode            = SelInfo.u.Raw.Gen.u1DefBig ? CPUMODE_32BIT : CPUMODE_16BIT;
+            enmDisCpuMode         = SelInfo.u.Raw.Gen.u1DefBig ? CPUMODE_32BIT : CPUMODE_16BIT;
         }
     }
@@ -3673,5 +3665,5 @@
     {
         /* real or V86 mode */
-        pCpu->mode            = CPUMODE_16BIT;
+        enmDisCpuMode         = CPUMODE_16BIT;
         State.GCPtrSegBase    = pCtx->cs * 16;
         State.GCPtrSegEnd     = 0xFFFFFFFF;
@@ -3682,15 +3674,12 @@
      * Disassemble the instruction.
      */
-    pCpu->pfnReadBytes    = cpumR3DisasInstrRead;
-    pCpu->apvUserData[0]  = &State;
-
     uint32_t cbInstr;
 #ifndef LOG_ENABLED
-    rc = DISInstr(pCpu, GCPtrPC, 0, &cbInstr, NULL);
+    rc = DISInstrWithReader(GCPtrPC, enmDisCpuMode, cpumR3DisasInstrRead, &State, pCpu, &cbInstr, NULL);
     if (RT_SUCCESS(rc))
     {
 #else
     char szOutput[160];
-    rc = DISInstr(pCpu, GCPtrPC, 0, &cbInstr, &szOutput[0]);
+    rc = DISInstrWithReader(GCPtrPC, enmDisCpuMode, cpumR3DisasInstrRead, &State, pCpu, &cbInstr, szOutput);
     if (RT_SUCCESS(rc))
     {
Index: /trunk/src/VBox/VMM/VMMR3/CSAM.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMR3/CSAM.cpp	(revision 41657)
+++ /trunk/src/VBox/VMM/VMMR3/CSAM.cpp	(revision 41658)
@@ -724,68 +724,53 @@
 
 /**
- * Read callback for disassembly function; supports reading bytes that cross a page boundary
- *
- * @returns VBox status code.
- * @param   pSrc        GC source pointer
- * @param   pDest       HC destination pointer
- * @param   size        Number of bytes to read
- * @param   dwUserdata  Callback specific user data (pCpu)
- *
- */
-static DECLCALLBACK(int) CSAMR3ReadBytes(RTUINTPTR pSrc, uint8_t *pDest, unsigned size, void *pvUserdata)
-{
-    DISCPUSTATE  *pCpu     = (DISCPUSTATE *)pvUserdata;
-    PVM           pVM      = (PVM)pCpu->apvUserData[0];
-    RTHCUINTPTR   pInstrHC = (RTHCUINTPTR)pCpu->apvUserData[1];
-    RTGCUINTPTR32 pInstrGC = (uintptr_t)pCpu->apvUserData[2];
-    int           orgsize  = size;
-    Assert(pVM->cCpus == 1);
-    PVMCPU        pVCpu = VMMGetCpu0(pVM);
-
-    /* We are not interested in patched instructions, so read the original opcode bytes. */
-    /** @note single instruction patches (int3) are checked in CSAMR3AnalyseCallback */
-    for (int i=0;i<orgsize;i++)
-    {
-        int rc = PATMR3QueryOpcode(pVM, (RTRCPTR)pSrc, pDest);
-        if (RT_SUCCESS(rc))
-        {
-            pSrc++;
-            pDest++;
-            size--;
-        }
-        else
+ * @callback_method_impl{FNDISREADBYTES}
+ */
+static DECLCALLBACK(int) CSAMR3ReadBytes(PDISCPUSTATE pDisState, uint8_t *pbDst, RTUINTPTR uSrcAddr, uint32_t cbToRead)
+{
+    PVM           pVM      = (PVM)pDisState->apvUserData[0];
+    RTHCUINTPTR   pInstrHC = (RTHCUINTPTR)pDisState->apvUserData[1];
+    RTGCUINTPTR32 pInstrGC = pDisState->uInstrAddr;
+    int           orgsize  = cbToRead;
+    PVMCPU        pVCpu    = VMMGetCpu0(pVM);
+
+    /* We are not interested in patched instructions, so read the original opcode bytes.
+       Note! single instruction patches (int3) are checked in CSAMR3AnalyseCallback */
+    for (int i = 0; i < orgsize; i++)
+    {
+        int rc = PATMR3QueryOpcode(pVM, (RTRCPTR)uSrcAddr, pbDst);
+        if (RT_FAILURE(rc))
             break;
-    }
-    if (size == 0)
+        uSrcAddr++;
+        pbDst++;
+        cbToRead--;
+    }
+    if (cbToRead == 0)
         return VINF_SUCCESS;
 
-    if (PAGE_ADDRESS(pInstrGC) != PAGE_ADDRESS(pSrc + size - 1) && !PATMIsPatchGCAddr(pVM, pSrc))
-    {
-        return PGMPhysSimpleReadGCPtr(pVCpu, pDest, pSrc, size);
-    }
-    else
-    {
-        Assert(pInstrHC);
-
-        /* pInstrHC is the base address; adjust according to the GC pointer. */
-        pInstrHC = pInstrHC + (pSrc - pInstrGC);
-
-        memcpy(pDest, (void *)pInstrHC, size);
-    }
+    if (PAGE_ADDRESS(pInstrGC) != PAGE_ADDRESS(uSrcAddr + cbToRead - 1) && !PATMIsPatchGCAddr(pVM, uSrcAddr))
+        return PGMPhysSimpleReadGCPtr(pVCpu, pbDst, uSrcAddr, cbToRead);
+
+    Assert(pInstrHC);
+
+    /* pInstrHC is the base address; adjust according to the GC pointer. */
+    pInstrHC = pInstrHC + (uSrcAddr - pInstrGC);
+
+    memcpy(pbDst, (void *)pInstrHC, cbToRead);
 
     return VINF_SUCCESS;
 }
 
-inline int CSAMR3DISInstr(PVM pVM, DISCPUSTATE *pCpu, RTRCPTR InstrGC, uint8_t *InstrHC, uint32_t *pOpsize, char *pszOutput)
-{
-    (pCpu)->pfnReadBytes  = CSAMR3ReadBytes;
-    (pCpu)->apvUserData[0] = pVM;
+DECLINLINE(int) CSAMR3DISInstr(PVM pVM, RTRCPTR InstrGC, uint8_t *InstrHC, DISCPUMODE enmCpuMode,
+                               PDISCPUSTATE pCpu, uint32_t *pcbInstr, char *pszOutput)
+{
     (pCpu)->apvUserData[1] = InstrHC;
     (pCpu)->apvUserData[2] = (void *)(uintptr_t)InstrGC; Assert(sizeof(InstrGC) <= sizeof(pCpu->apvUserData[0]));
 #ifdef DEBUG
-    return DISInstrEx(pCpu, InstrGC, 0, pOpsize, pszOutput, OPTYPE_ALL);
+    return DISInstrEx(InstrGC, 0, enmCpuMode, CSAMR3ReadBytes, pVM, OPTYPE_ALL,
+                      pCpu, pcbInstr, pszOutput);
 #else
     /* We are interested in everything except harmless stuff */
-    return DISInstrEx(pCpu, InstrGC, 0, pOpsize, pszOutput, ~(OPTYPE_INVALID | OPTYPE_HARMLESS | OPTYPE_RRM_MASK));
+    return DISInstrEx(InstrGC, 0, enmCpuMode, CSAMR3ReadBytes, pVM, ~(OPTYPE_INVALID | OPTYPE_HARMLESS | OPTYPE_RRM_MASK),
+                      pCpu, pcbInstr, pszOutput);
 #endif
 }
@@ -883,6 +868,6 @@
                 Assert(VALID_PTR(pCurInstrHC));
 
-                cpu.mode = (fCode32) ? CPUMODE_32BIT : CPUMODE_16BIT;
-                rc = CSAMR3DISInstr(pVM, &cpu, pCurInstrGC, pCurInstrHC, &opsize, NULL);
+                rc = CSAMR3DISInstr(pVM, pCurInstrGC, pCurInstrHC, (fCode32) ? CPUMODE_32BIT : CPUMODE_16BIT,
+                                    &cpu, &opsize, NULL);
             }
             AssertRC(rc);
@@ -1054,5 +1039,5 @@
              * - push ebp after the filler (can extend this later); aligned at at least a 4 byte boundary
              */
-            for (int j=0;j<16;j++)
+            for (int j = 0; j < 16; j++)
             {
                 uint8_t *pCurInstrHC = (uint8_t *)CSAMGCVirtToHCVirt(pVM, pCacheRec, pCurInstrGC);
@@ -1064,11 +1049,12 @@
                 Assert(VALID_PTR(pCurInstrHC));
 
-                cpu.mode = (fCode32) ? CPUMODE_32BIT : CPUMODE_16BIT;
                 STAM_PROFILE_START(&pVM->csam.s.StatTimeDisasm, a);
 #ifdef DEBUG
-                rc2 = CSAMR3DISInstr(pVM, &cpu, pCurInstrGC, pCurInstrHC, &opsize, szOutput);
+                rc2 = CSAMR3DISInstr(pVM, pCurInstrGC, pCurInstrHC, (fCode32) ? CPUMODE_32BIT : CPUMODE_16BIT,
+                                     &cpu, &opsize, szOutput);
                 if (RT_SUCCESS(rc2)) Log(("CSAM Call Analysis: %s", szOutput));
 #else
-                rc2 = CSAMR3DISInstr(pVM, &cpu, pCurInstrGC, pCurInstrHC, &opsize, NULL);
+                rc2 = CSAMR3DISInstr(pVM, pCurInstrGC, pCurInstrHC, (fCode32) ? CPUMODE_32BIT : CPUMODE_16BIT,
+                                     &cpu, &opsize, NULL);
 #endif
                 STAM_PROFILE_STOP(&pVM->csam.s.StatTimeDisasm, a);
@@ -1276,11 +1262,12 @@
             Assert(VALID_PTR(pCurInstrHC));
 
-            cpu.mode = (fCode32) ? CPUMODE_32BIT : CPUMODE_16BIT;
             STAM_PROFILE_START(&pVM->csam.s.StatTimeDisasm, a);
 #ifdef DEBUG
-            rc2 = CSAMR3DISInstr(pVM, &cpu, pCurInstrGC, pCurInstrHC, &opsize, szOutput);
+            rc2 = CSAMR3DISInstr(pVM, pCurInstrGC, pCurInstrHC, (fCode32) ? CPUMODE_32BIT : CPUMODE_16BIT,
+                                 &cpu, &opsize, szOutput);
             if (RT_SUCCESS(rc2)) Log(("CSAM Analysis: %s", szOutput));
 #else
-            rc2 = CSAMR3DISInstr(pVM, &cpu, pCurInstrGC, pCurInstrHC, &opsize, NULL);
+            rc2 = CSAMR3DISInstr(pVM, &cpu, pCurInstrGC, pCurInstrHC, (fCode32) ? CPUMODE_32BIT : CPUMODE_16BIT,
+                                 &cpu, &opsize, NULL);
 #endif
             STAM_PROFILE_STOP(&pVM->csam.s.StatTimeDisasm, a);
Index: /trunk/src/VBox/VMM/VMMR3/DBGFDisas.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMR3/DBGFDisas.cpp	(revision 41657)
+++ /trunk/src/VBox/VMM/VMMR3/DBGFDisas.cpp	(revision 41658)
@@ -82,5 +82,5 @@
 *   Internal Functions                                                         *
 *******************************************************************************/
-static DECLCALLBACK(int) dbgfR3DisasInstrRead(RTUINTPTR pSrc, uint8_t *pDest, uint32_t size, void *pvUserdata);
+static FNDISREADBYTES dbgfR3DisasInstrRead;
 
 
@@ -199,21 +199,16 @@
 
 /**
- * Instruction reader.
- *
- * @returns VBox status code. (Why this is a int32_t and not just an int is also beyond me.)
- * @param   PtrSrc      Address to read from.
- *                      In our case this is relative to the selector pointed to by the 2nd user argument of uDisCpu.
- * @param   pu8Dst      Where to store the bytes.
- * @param   cbRead      Number of bytes to read.
- * @param   uDisCpu     Pointer to the disassembler cpu state. (Why this is a VBOXHUINTPTR is beyond me...)
- *                      In this context it's always pointer to the Core of a DBGFDISASSTATE.
- */
-static DECLCALLBACK(int) dbgfR3DisasInstrRead(RTUINTPTR PtrSrc, uint8_t *pu8Dst, uint32_t cbRead, void *pvDisCpu)
-{
-    PDBGFDISASSTATE pState = (PDBGFDISASSTATE)pvDisCpu;
-    Assert(cbRead > 0);
+ * @callback_method_impl{FNDISREADBYTES}
+ *
+ * @remarks @a uSrcAddr is relative to the base address indicated by
+ *          DBGFDISASSTATE::GCPtrSegBase.
+ */
+static DECLCALLBACK(int) dbgfR3DisasInstrRead(PDISCPUSTATE pDisState, uint8_t *pbDst, RTUINTPTR uSrcAddr, uint32_t cbToRead)
+{
+    PDBGFDISASSTATE pState = (PDBGFDISASSTATE)pDisState;
+    Assert(cbToRead > 0);
     for (;;)
     {
-        RTGCUINTPTR GCPtr = PtrSrc + pState->GCPtrSegBase;
+        RTGCUINTPTR GCPtr = uSrcAddr + pState->GCPtrSegBase;
 
         /* Need to update the page translation? */
@@ -250,5 +245,5 @@
 
         /* check the segment limit */
-        if (!pState->f64Bits && PtrSrc > pState->cbSegLimit)
+        if (!pState->f64Bits && uSrcAddr > pState->cbSegLimit)
             return VERR_OUT_OF_SELECTOR_BOUNDS;
 
@@ -261,14 +256,14 @@
                 cb = cbSeg;
         }
-        if (cb > cbRead)
-            cb = cbRead;
+        if (cb > cbToRead)
+            cb = cbToRead;
 
         /* read and advance */
-        memcpy(pu8Dst, (char *)pState->pvPageR3 + (GCPtr & PAGE_OFFSET_MASK), cb);
-        cbRead -= cb;
-        if (!cbRead)
+        memcpy(pbDst, (char *)pState->pvPageR3 + (GCPtr & PAGE_OFFSET_MASK), cb);
+        cbToRead -= cb;
+        if (!cbToRead)
             return VINF_SUCCESS;
-        pu8Dst += cb;
-        PtrSrc += cb;
+        pbDst    += cb;
+        uSrcAddr += cb;
     }
 }
@@ -507,5 +502,5 @@
         uint32_t cbBits = State.Cpu.opsize;
         uint8_t *pau8Bits = (uint8_t *)alloca(cbBits);
-        rc = dbgfR3DisasInstrRead(GCPtr, pau8Bits, cbBits, &State);
+        rc = dbgfR3DisasInstrRead(&State.Cpu, pau8Bits, GCPtr, cbBits);
         AssertRC(rc);
         if (fFlags & DBGF_DISAS_FLAGS_NO_ADDRESS)
Index: /trunk/src/VBox/VMM/VMMR3/PATM.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMR3/PATM.cpp	(revision 41657)
+++ /trunk/src/VBox/VMM/VMMR3/PATM.cpp	(revision 41658)
@@ -517,22 +517,11 @@
 }
 
-/**
- * Read callback for disassembly function; supports reading bytes that cross a page boundary
- *
- * @returns VBox status code.
- * @param   pSrc        GC source pointer
- * @param   pDest       HC destination pointer
- * @param   size        Number of bytes to read
- * @param   pvUserdata  Callback specific user data (pCpu)
- *
- */
-int patmReadBytes(RTUINTPTR pSrc, uint8_t *pDest, unsigned size, void *pvUserdata)
-{
-    DISCPUSTATE  *pCpu     = (DISCPUSTATE *)pvUserdata;
-    PATMDISASM   *pDisInfo = (PATMDISASM *)pCpu->apvUserData[0];
-    int           orgsize  = size;
-
-    Assert(size);
-    if (size == 0)
+DECLCALLBACK(int) patmReadBytes(PDISCPUSTATE pDisState, uint8_t *pbDst, RTUINTPTR uSrcAddr, uint32_t cbToRead)
+{
+    PATMDISASM   *pDisInfo = (PATMDISASM *)pDisState->apvUserData[0];
+    int           orgsize  = cbToRead;
+
+    Assert(cbToRead);
+    if (cbToRead == 0)
         return VERR_INVALID_PARAMETER;
 
@@ -544,16 +533,14 @@
     if (pDisInfo->fReadFlags & PATMREAD_ORGCODE)
     {
-        for (int i=0;i<orgsize;i++)
-        {
-            int rc = PATMR3QueryOpcode(pDisInfo->pVM, (RTRCPTR)pSrc, pDest);
-            if (RT_SUCCESS(rc))
-            {
-                pSrc++;
-                pDest++;
-                size--;
-            }
-            else break;
-        }
-        if (size == 0)
+        for (int i = 0; i < orgsize; i++)
+        {
+            int rc = PATMR3QueryOpcode(pDisInfo->pVM, (RTRCPTR)uSrcAddr, pbDst);
+            if (RT_FAILURE(rc))
+                break;
+            uSrcAddr++;
+            pbDst++;
+            cbToRead--;
+        }
+        if (cbToRead == 0)
             return VINF_SUCCESS;
 #ifdef VBOX_STRICT
@@ -561,6 +548,6 @@
             &&  !(pDisInfo->fReadFlags & PATMREAD_NOCHECK))
         {
-            Assert(PATMR3IsInsidePatchJump(pDisInfo->pVM, pSrc, NULL) == false);
-            Assert(PATMR3IsInsidePatchJump(pDisInfo->pVM, pSrc+size-1, NULL) == false);
+            Assert(PATMR3IsInsidePatchJump(pDisInfo->pVM, uSrcAddr, NULL) == false);
+            Assert(PATMR3IsInsidePatchJump(pDisInfo->pVM, uSrcAddr+cbToRead-1, NULL) == false);
         }
 #endif
@@ -568,23 +555,21 @@
 
     if (    !pDisInfo->pInstrHC
-        ||  (   PAGE_ADDRESS(pDisInfo->pInstrGC) != PAGE_ADDRESS(pSrc + size - 1)
-             && !PATMIsPatchGCAddr(pDisInfo->pVM, pSrc)))
-    {
-        Assert(!PATMIsPatchGCAddr(pDisInfo->pVM, pSrc));
-        return PGMPhysSimpleReadGCPtr(&pDisInfo->pVM->aCpus[0], pDest, pSrc, size);
-    }
-    else
-    {
-        Assert(pDisInfo->pInstrHC);
-
-        uint8_t *pInstrHC = pDisInfo->pInstrHC;
-
-        Assert(pInstrHC);
-
-        /* pInstrHC is the base address; adjust according to the GC pointer. */
-        pInstrHC = pInstrHC + (pSrc - pDisInfo->pInstrGC);
-
-        memcpy(pDest, (void *)pInstrHC, size);
-    }
+        ||  (   PAGE_ADDRESS(pDisInfo->pInstrGC) != PAGE_ADDRESS(uSrcAddr + cbToRead - 1)
+             && !PATMIsPatchGCAddr(pDisInfo->pVM, uSrcAddr)))
+    {
+        Assert(!PATMIsPatchGCAddr(pDisInfo->pVM, uSrcAddr));
+        return PGMPhysSimpleReadGCPtr(&pDisInfo->pVM->aCpus[0], pbDst, uSrcAddr, cbToRead);
+    }
+
+    Assert(pDisInfo->pInstrHC);
+
+    uint8_t *pInstrHC = pDisInfo->pInstrHC;
+
+    Assert(pInstrHC);
+
+    /* pInstrHC is the base address; adjust according to the GC pointer. */
+    pInstrHC = pInstrHC + (uSrcAddr - pDisInfo->pInstrGC);
+
+    memcpy(pbDst, (void *)pInstrHC, cbToRead);
 
     return VINF_SUCCESS;
@@ -2837,5 +2822,5 @@
     if (pPatch->flags & PATMFL_INT3_REPLACEMENT_BLOCK)
     {
-        /*uint8_t ASMInt3 = 0xCC; - unused */
+        /*uint8_t bASMInt3 = 0xCC; - unused */
 
         Log(("PATMR3PatchBlock %RRv -> int 3 callable patch.\n", pPatch->pPrivInstrGC));
@@ -3786,5 +3771,5 @@
 static int patmActivateInt3Patch(PVM pVM, PPATCHINFO pPatch)
 {
-    uint8_t ASMInt3 = 0xCC;
+    uint8_t bASMInt3 = 0xCC;
     int     rc;
 
@@ -3793,8 +3778,8 @@
 
     /* Replace first opcode byte with 'int 3'. */
-    rc = PGMPhysSimpleDirtyWriteGCPtr(VMMGetCpu0(pVM), pPatch->pPrivInstrGC, &ASMInt3, sizeof(ASMInt3));
+    rc = PGMPhysSimpleDirtyWriteGCPtr(VMMGetCpu0(pVM), pPatch->pPrivInstrGC, &bASMInt3, sizeof(bASMInt3));
     AssertRC(rc);
 
-    pPatch->cbPatchJump = sizeof(ASMInt3);
+    pPatch->cbPatchJump = sizeof(bASMInt3);
 
     return rc;
@@ -3823,5 +3808,6 @@
 
 /**
- * Replace an instruction with a breakpoint (0xCC), that is handled dynamically in the guest context.
+ * Replace an instruction with a breakpoint (0xCC), that is handled dynamically
+ * in the raw-mode context.
  *
  * @returns VBox status code.
@@ -3835,7 +3821,8 @@
  *
  */
-VMMR3DECL(int) PATMR3PatchInstrInt3(PVM pVM, RTRCPTR pInstrGC, R3PTRTYPE(uint8_t *) pInstrHC, DISCPUSTATE *pCpu, PPATCHINFO pPatch)
-{
-    uint8_t ASMInt3 = 0xCC;
+VMMR3DECL(int) PATMR3PatchInstrInt3(PVM pVM, RTRCPTR pInstrGC, R3PTRTYPE(uint8_t *) pInstrHC, DISCPUSTATE *pCpu,
+                                    PPATCHINFO pPatch)
+{
+    uint8_t bASMInt3 = 0xCC;
     int rc;
 
@@ -3855,5 +3842,5 @@
     rc = PGMPhysSimpleReadGCPtr(VMMGetCpu0(pVM), pPatch->aPrivInstr, pPatch->pPrivInstrGC, pPatch->cbPrivInstr);
     AssertRC(rc);
-    pPatch->cbPatchJump = sizeof(ASMInt3);  /* bit of a misnomer in this case; size of replacement instruction. */
+    pPatch->cbPatchJump = sizeof(bASMInt3);  /* bit of a misnomer in this case; size of replacement instruction. */
 
     pPatch->flags |= PATMFL_INT3_REPLACEMENT;
Index: /trunk/src/VBox/VMM/VMMR3/VMMSwitcher.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMR3/VMMSwitcher.cpp	(revision 41657)
+++ /trunk/src/VBox/VMM/VMMR3/VMMSwitcher.cpp	(revision 41658)
@@ -837,5 +837,6 @@
                 uint32_t cbInstr = 0;
                 char szDisas[256];
-                if (RT_SUCCESS(DISInstr(&Cpu, (uintptr_t)pu8CodeR3 + offCode, uBase - (uintptr_t)pu8CodeR3, &cbInstr, szDisas)))
+                if (RT_SUCCESS(DISInstrWithOff(&Cpu, (uintptr_t)pu8CodeR3 + offCode, uBase - (uintptr_t)pu8CodeR3,
+                                               &cbInstr, szDisas)))
                     RTLogPrintf("  %04x: %s", offCode, szDisas); //for whatever reason szDisas includes '\n'.
                 else
Index: /trunk/src/VBox/VMM/VMMRC/PATMRC.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMRC/PATMRC.cpp	(revision 41657)
+++ /trunk/src/VBox/VMM/VMMRC/PATMRC.cpp	(revision 41658)
@@ -1,9 +1,9 @@
 /* $Id$ */
 /** @file
- * PATM - Dynamic Guest OS Patching Manager - Guest Context
+ * PATM - Dynamic Guest OS Patching Manager - Raw-mode Context.
  */
 
 /*
- * Copyright (C) 2006-2007 Oracle Corporation
+ * Copyright (C) 2006-2012 Oracle Corporation
  *
  * This file is part of VirtualBox Open Source Edition (OSE), as
@@ -21,13 +21,15 @@
 *******************************************************************************/
 #define LOG_GROUP LOG_GROUP_PATM
+#include <VBox/vmm/patm.h>
 #include <VBox/vmm/cpum.h>
 #include <VBox/vmm/stam.h>
-#include <VBox/vmm/patm.h>
 #include <VBox/vmm/pgm.h>
 #include <VBox/vmm/mm.h>
-#include <VBox/sup.h>
+#include <VBox/vmm/em.h>
+#ifdef VBOX_WITH_IEM
+# include <VBox/vmm/iem.h>
+#endif
+#include <VBox/vmm/selm.h>
 #include <VBox/vmm/mm.h>
-#include <VBox/param.h>
-#include <iprt/avl.h>
 #include "PATMInternal.h"
 #include "PATMA.h"
@@ -36,7 +38,5 @@
 #include <VBox/dis.h>
 #include <VBox/disopcode.h>
-#include <VBox/vmm/em.h>
 #include <VBox/err.h>
-#include <VBox/vmm/selm.h>
 #include <VBox/log.h>
 #include <iprt/assert.h>
@@ -441,10 +441,14 @@
  * Checks if the int 3 was caused by a patched instruction
  *
- * @returns VBox status
+ * @returns Strict VBox status, includes all statuses that
+ *          EMInterpretInstructionDisasState and
+ * @retval  VINF_SUCCESS
+ * @retval  VINF_PATM_PATCH_INT3
+ * @retval  VINF_EM_RAW_EMULATE_INSTR
  *
  * @param   pVM         The VM handle.
  * @param   pCtxCore    The relevant core context.
  */
-VMMDECL(int) PATMHandleInt3PatchTrap(PVM pVM, PCPUMCTXCORE pRegFrame)
+VMMRCDECL(int) PATMRCHandleInt3PatchTrap(PVM pVM, PCPUMCTXCORE pRegFrame)
 {
     PPATMPATCHREC pRec;
@@ -456,5 +460,5 @@
     if (PATMIsPatchGCAddr(pVM, pRegFrame->eip))
     {
-        /* @note hardcoded assumption about it being a single byte int 3 instruction. */
+        /* Note! Hardcoded assumption about it being a single byte int 3 instruction. */
         pRegFrame->eip--;
         return VINF_PATM_PATCH_INT3;
@@ -512,5 +516,13 @@
                 return VINF_EM_RAW_EMULATE_INSTR;
             }
-            rc = DISCoreOne(&cpu, (uintptr_t)&pRec->patch.aPrivInstr[0], &cbOp);
+
+#ifdef VBOX_WITH_IEM
+            VBOXSTRICTRC rcStrict;
+            rcStrict = IEMExecOneWithOpcodes(VMMGetCpu0(pVM), pRegFrame, pRec->patch.pPrivInstrGC,
+                                             pRec->patch.aPrivInstr, pRec->patch.cbPrivInstr);
+            rc = VBOXSTRICTRC_TODO(rcStrict);
+#else
+            rc = DISCoreOneEx((uintptr_t)&pRec->patch.aPrivInstr[0], cpu.mode, NULL /*pfnReadBytes*/, NULL /*pvUser*/,
+                              &cpu, &cbOp);
             if (RT_FAILURE(rc))
             {
@@ -523,5 +535,6 @@
             rc = EMInterpretInstructionDisasState(VMMGetCpu0(pVM), &cpu, pRegFrame, 0 /* not relevant here */,
                                                   EMCODETYPE_SUPERVISOR);
-            if (rc != VINF_SUCCESS)
+#endif
+            if (RT_FAILURE(rc))
             {
                 Log(("EMInterpretInstructionCPU failed with %Rrc\n", rc));
@@ -530,5 +543,5 @@
                 return VINF_EM_RAW_EMULATE_INSTR;
             }
-            return VINF_SUCCESS;
+            return rc;
         }
     }
Index: /trunk/src/VBox/VMM/VMMRC/TRPMRCHandlers.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMRC/TRPMRCHandlers.cpp	(revision 41657)
+++ /trunk/src/VBox/VMM/VMMRC/TRPMRCHandlers.cpp	(revision 41658)
@@ -421,6 +421,9 @@
         &&  !pRegFrame->eflags.Bits.u1VM)
     {
-        rc = PATMHandleInt3PatchTrap(pVM, pRegFrame);
-        if (rc == VINF_SUCCESS || rc == VINF_EM_RAW_EMULATE_INSTR || rc == VINF_PATM_PATCH_INT3 || rc == VINF_PATM_DUPLICATE_FUNCTION)
+        rc = PATMRCHandleInt3PatchTrap(pVM, pRegFrame);
+        if (   rc == VINF_SUCCESS
+            || rc == VINF_EM_RAW_EMULATE_INSTR
+            || rc == VINF_PATM_PATCH_INT3
+            || rc == VINF_PATM_DUPLICATE_FUNCTION)
         {
             rc = trpmGCExitTrap(pVM, pVCpu, rc, pRegFrame);
@@ -745,5 +748,5 @@
             {
                 /* Int 3 replacement patch? */
-                if (PATMHandleInt3PatchTrap(pVM, pRegFrame) == VINF_SUCCESS)
+                if (PATMRCHandleInt3PatchTrap(pVM, pRegFrame) == VINF_SUCCESS)
                 {
                     AssertFailed();
Index: /trunk/src/VBox/VMM/include/PATMInternal.h
===================================================================
--- /trunk/src/VBox/VMM/include/PATMInternal.h	(revision 41657)
+++ /trunk/src/VBox/VMM/include/PATMInternal.h	(revision 41658)
@@ -273,5 +273,5 @@
     /** Size of the patch jump in the guest code. */
     uint32_t                    cbPatchJump;
-    /* Only valid for PATMFL_JUMP_CONFLICT patches */
+    /** Only valid for PATMFL_JUMP_CONFLICT patches */
     RTRCPTR                     pPatchJumpDestGC;
     /** Offset of the patch code from the beginning of the patch memory area. */
@@ -675,15 +675,5 @@
 
 
-/**
- * Read callback for disassembly function; supports reading bytes that cross a page boundary
- *
- * @returns VBox status code.
- * @param   pSrc        GC source pointer
- * @param   pDest       HC destination pointer
- * @param   size        Number of bytes to read
- * @param   pvUserdata  Callback specific user data (pCpu)
- *
- */
-int patmReadBytes(RTUINTPTR pSrc, uint8_t *pDest, unsigned size, void *pvUserdata);
+FNDISREADBYTES patmReadBytes;
 
 
@@ -706,7 +696,7 @@
 } PATMDISASM, *PPATMDISASM;
 
-inline bool PATMR3DISInstr(PVM pVM, PPATCHINFO pPatch, DISCPUSTATE *pCpu, RTRCPTR InstrGC,
-                           uint8_t *InstrHC, uint32_t *pOpsize, char *pszOutput,
-                           uint32_t fReadFlags = PATMREAD_ORGCODE)
+DECLINLINE(bool) PATMR3DISInstr(PVM pVM, PPATCHINFO pPatch, PDISCPUSTATE pCpu, RTRCPTR InstrGC,
+                                uint8_t *InstrHC, uint32_t *pOpsize, char *pszOutput,
+                                uint32_t fReadFlags = PATMREAD_ORGCODE)
 {
     PATMDISASM disinfo;
@@ -718,5 +708,5 @@
     (pCpu)->pfnReadBytes = patmReadBytes;
     (pCpu)->apvUserData[0] = &disinfo;
-    return RT_SUCCESS(DISInstr(pCpu, InstrGC, 0, pOpsize, pszOutput));
+    return RT_SUCCESS(DISInstrWithReader(InstrGC, pCpu->mode, patmReadBytes, &disinfo, pCpu, pOpsize, pszOutput));
 }
 #endif /* !IN_RC */
Index: /trunk/src/VBox/VMM/testcase/tstCompiler.cpp
===================================================================
--- /trunk/src/VBox/VMM/testcase/tstCompiler.cpp	(revision 41657)
+++ /trunk/src/VBox/VMM/testcase/tstCompiler.cpp	(revision 41658)
@@ -204,10 +204,9 @@
 
     memset(&Cpu, 0, sizeof(Cpu));
-    Cpu.mode = CPUMODE_32BIT;
     do
     {
         char        sz[256];
         uint32_t    cbInstr = 0;
-        if (RT_SUCCESS(DISInstr(&Cpu, uCur, 0, &cbInstr, sz)))
+        if (RT_SUCCESS(DISInstr(uCur, CPUMODE_32BIT, &Cpu, &cbInstr, sz)))
         {
             RTPrintf("tstBitFields: %s", sz);
Index: /trunk/src/recompiler/VBoxREMWrapper.cpp
===================================================================
--- /trunk/src/recompiler/VBoxREMWrapper.cpp	(revision 41657)
+++ /trunk/src/recompiler/VBoxREMWrapper.cpp	(revision 41658)
@@ -654,7 +654,7 @@
 static const REMPARMDESC g_aArgsDISInstr[] =
 {
-    { REMPARMDESC_FLAGS_INT,        sizeof(PVM),                NULL },
     { REMPARMDESC_FLAGS_INT,        sizeof(RTUINTPTR),          NULL },
-    { REMPARMDESC_FLAGS_INT,        sizeof(uint32_t),           NULL },
+    { REMPARMDESC_FLAGS_INT,        sizeof(DISCPUMODE),         NULL },
+    { REMPARMDESC_FLAGS_INT,        sizeof(PDISCPUSTATE),       NULL },
     { REMPARMDESC_FLAGS_INT,        sizeof(uint32_t *),         NULL },
     { REMPARMDESC_FLAGS_INT,        sizeof(char *),             NULL }
Index: /trunk/src/recompiler/VBoxRecompiler.c
===================================================================
--- /trunk/src/recompiler/VBoxRecompiler.c	(revision 41657)
+++ /trunk/src/recompiler/VBoxRecompiler.c	(revision 41658)
@@ -4071,10 +4071,8 @@
         char            szOutput[256];
         DISCPUSTATE     Cpu;
-
-        memset(&Cpu, 0, sizeof(Cpu));
 #ifdef RT_ARCH_X86
-        Cpu.mode = CPUMODE_32BIT;
+        DISCPUMODE      enmCpuMode = CPUMODE_32BIT;
 #else
-        Cpu.mode = CPUMODE_64BIT;
+        DISCPUMODE      enmCpuMode = CPUMODE_64BIT;
 #endif
 
@@ -4083,13 +4081,11 @@
         {
             uint32_t cbInstr;
-            if (RT_SUCCESS(DISInstr(&Cpu, (uintptr_t)pvCode + off, 0, &cbInstr, szOutput)))
+            int rc = DISInstr((uintptr_t)pvCode + off, enmCpuMode, &Cpu, &cbInstr, szOutput);
+            if (RT_SUCCESS(rc))
                 RTLogPrintf("%s", szOutput);
             else
             {
-                RTLogPrintf("disas error\n");
+                RTLogPrintf("disas error %Rrc\n", rc);
                 cbInstr = 1;
-#ifdef RT_ARCH_AMD64 /** @todo remove when DISInstr starts supporting 64-bit code. */
-                break;
-#endif
             }
             off += cbInstr;
