Beispiel #1
0
/** @interface_method_impl{PDMDEVHLPR0,pfnPCISetIrq} */
static DECLCALLBACK(void) pdmR0DevHlp_ISASetIrq(PPDMDEVINS pDevIns, int iIrq, int iLevel)
{
    PDMDEV_ASSERT_DEVINS(pDevIns);
    LogFlow(("pdmR0DevHlp_ISASetIrq: caller=%p/%d: iIrq=%d iLevel=%d\n", pDevIns, pDevIns->iInstance, iIrq, iLevel));
    PVM pVM = pDevIns->Internal.s.pVMR0;

    pdmLock(pVM);
    uint32_t uTagSrc;
    if (iLevel & PDM_IRQ_LEVEL_HIGH)
    {
        pDevIns->Internal.s.uLastIrqTag = uTagSrc = pdmCalcIrqTag(pVM, pDevIns->idTracing);
        if (iLevel == PDM_IRQ_LEVEL_HIGH)
            VBOXVMM_PDM_IRQ_HIGH(VMMGetCpu(pVM), RT_LOWORD(uTagSrc), RT_HIWORD(uTagSrc));
        else
            VBOXVMM_PDM_IRQ_HILO(VMMGetCpu(pVM), RT_LOWORD(uTagSrc), RT_HIWORD(uTagSrc));
    }
    else
        uTagSrc = pDevIns->Internal.s.uLastIrqTag;

    bool fRc = pdmR0IsaSetIrq(pVM, iIrq, iLevel, uTagSrc);

    if (iLevel == PDM_IRQ_LEVEL_LOW && fRc)
        VBOXVMM_PDM_IRQ_LOW(VMMGetCpu(pVM), RT_LOWORD(uTagSrc), RT_HIWORD(uTagSrc));
    pdmUnlock(pVM);
    LogFlow(("pdmR0DevHlp_ISASetIrq: caller=%p/%d: returns void; uTagSrc=%#x\n", pDevIns, pDevIns->iInstance, uTagSrc));
}
/** @interface_method_impl{PDMHPETHLPR3,pfnSetIrq} */
static DECLCALLBACK(int) pdmR3HpetHlp_SetIrq(PPDMDEVINS pDevIns, int iIrq, int iLevel)
{
    PDMDEV_ASSERT_DEVINS(pDevIns);
    LogFlow(("pdmR3HpetHlp_SetIrq: caller='%s'/%d: iIrq=%d iLevel=%d\n", pDevIns->pReg->szName, pDevIns->iInstance, iIrq, iLevel));
    PVM pVM = pDevIns->Internal.s.pVMR3;

    pdmLock(pVM);
    uint32_t uTagSrc;
    if (iLevel & PDM_IRQ_LEVEL_HIGH)
    {
        pDevIns->Internal.s.uLastIrqTag = uTagSrc = pdmCalcIrqTag(pVM, pDevIns->idTracing);
        if (iLevel == PDM_IRQ_LEVEL_HIGH)
            VBOXVMM_PDM_IRQ_HIGH(VMMGetCpu(pVM), RT_LOWORD(uTagSrc), RT_HIWORD(uTagSrc));
        else
            VBOXVMM_PDM_IRQ_HILO(VMMGetCpu(pVM), RT_LOWORD(uTagSrc), RT_HIWORD(uTagSrc));
    }
    else
        uTagSrc = pDevIns->Internal.s.uLastIrqTag;

    PDMIsaSetIrq(pVM, iIrq, iLevel, uTagSrc); /* (The API takes the lock recursively.) */

    if (iLevel == PDM_IRQ_LEVEL_LOW)
        VBOXVMM_PDM_IRQ_LOW(VMMGetCpu(pVM), RT_LOWORD(uTagSrc), RT_HIWORD(uTagSrc));
    pdmUnlock(pVM);
    return 0;
}
Beispiel #3
0
/**
 * Gets the pending interrupt.
 *
 * @returns VBox status code.
 * @param   pVCpu           Pointer to the VMCPU.
 * @param   pu8Interrupt    Where to store the interrupt on success.
 */
VMMDECL(int) PDMGetInterrupt(PVMCPU pVCpu, uint8_t *pu8Interrupt)
{
    PVM pVM = pVCpu->CTX_SUFF(pVM);

    pdmLock(pVM);

    /*
     * The local APIC has a higher priority than the PIC.
     */
    if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INTERRUPT_APIC))
    {
        VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INTERRUPT_APIC);
        Assert(pVM->pdm.s.Apic.CTX_SUFF(pDevIns));
        Assert(pVM->pdm.s.Apic.CTX_SUFF(pfnGetInterrupt));
        uint32_t uTagSrc;
        int i = pVM->pdm.s.Apic.CTX_SUFF(pfnGetInterrupt)(pVM->pdm.s.Apic.CTX_SUFF(pDevIns), pVCpu->idCpu, &uTagSrc);
        AssertMsg(i <= 255 && i >= 0, ("i=%d\n", i));
        if (i >= 0)
        {
            pdmUnlock(pVM);
            *pu8Interrupt = (uint8_t)i;
            VBOXVMM_PDM_IRQ_GET(pVCpu, RT_LOWORD(uTagSrc), RT_HIWORD(uTagSrc), i);
            return VINF_SUCCESS;
        }
    }

    /*
     * Check the PIC.
     */
    if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INTERRUPT_PIC))
    {
        VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INTERRUPT_PIC);
        Assert(pVM->pdm.s.Pic.CTX_SUFF(pDevIns));
        Assert(pVM->pdm.s.Pic.CTX_SUFF(pfnGetInterrupt));
        uint32_t uTagSrc;
        int i = pVM->pdm.s.Pic.CTX_SUFF(pfnGetInterrupt)(pVM->pdm.s.Pic.CTX_SUFF(pDevIns), &uTagSrc);
        AssertMsg(i <= 255 && i >= 0, ("i=%d\n", i));
        if (i >= 0)
        {
            pdmUnlock(pVM);
            *pu8Interrupt = (uint8_t)i;
            VBOXVMM_PDM_IRQ_GET(pVCpu, RT_LOWORD(uTagSrc), RT_HIWORD(uTagSrc), i);
            return VINF_SUCCESS;
        }
    }

    /** @todo Figure out exactly why we can get here without anything being set. (REM) */

    pdmUnlock(pVM);
    return VERR_NO_DATA;
}
Beispiel #4
0
/** @interface_method_impl{PDMDEVHLPR0,pfnPCISetIrq} */
static DECLCALLBACK(void) pdmR0DevHlp_PCISetIrq(PPDMDEVINS pDevIns, int iIrq, int iLevel)
{
    PDMDEV_ASSERT_DEVINS(pDevIns);
    LogFlow(("pdmR0DevHlp_PCISetIrq: caller=%p/%d: iIrq=%d iLevel=%d\n", pDevIns, pDevIns->iInstance, iIrq, iLevel));
    PVM          pVM     = pDevIns->Internal.s.pVMR0;
    PPCIDEVICE   pPciDev = pDevIns->Internal.s.pPciDeviceR0;
    PPDMPCIBUS   pPciBus = pDevIns->Internal.s.pPciBusR0;

    pdmLock(pVM);
    uint32_t uTagSrc;
    if (iLevel & PDM_IRQ_LEVEL_HIGH)
    {
        pDevIns->Internal.s.uLastIrqTag = uTagSrc = pdmCalcIrqTag(pVM, pDevIns->idTracing);
        if (iLevel == PDM_IRQ_LEVEL_HIGH)
            VBOXVMM_PDM_IRQ_HIGH(VMMGetCpu(pVM), RT_LOWORD(uTagSrc), RT_HIWORD(uTagSrc));
        else
            VBOXVMM_PDM_IRQ_HILO(VMMGetCpu(pVM), RT_LOWORD(uTagSrc), RT_HIWORD(uTagSrc));
    }
    else
        uTagSrc = pDevIns->Internal.s.uLastIrqTag;

    if (    pPciDev
        &&  pPciBus
        &&  pPciBus->pDevInsR0)
    {
        pPciBus->pfnSetIrqR0(pPciBus->pDevInsR0, pPciDev, iIrq, iLevel, uTagSrc);

        pdmUnlock(pVM);

        if (iLevel == PDM_IRQ_LEVEL_LOW)
            VBOXVMM_PDM_IRQ_LOW(VMMGetCpu(pVM), RT_LOWORD(uTagSrc), RT_HIWORD(uTagSrc));
    }
    else
    {
        pdmUnlock(pVM);

        /* queue for ring-3 execution. */
        PPDMDEVHLPTASK pTask = (PPDMDEVHLPTASK)PDMQueueAlloc(pVM->pdm.s.pDevHlpQueueR0);
        AssertReturnVoid(pTask);

        pTask->enmOp = PDMDEVHLPTASKOP_PCI_SET_IRQ;
        pTask->pDevInsR3 = PDMDEVINS_2_R3PTR(pDevIns);
        pTask->u.SetIRQ.iIrq = iIrq;
        pTask->u.SetIRQ.iLevel = iLevel;
        pTask->u.SetIRQ.uTagSrc = uTagSrc;

        PDMQueueInsertEx(pVM->pdm.s.pDevHlpQueueR0, &pTask->Core, 0);
    }

    LogFlow(("pdmR0DevHlp_PCISetIrq: caller=%p/%d: returns void; uTagSrc=%#x\n", pDevIns, pDevIns->iInstance, uTagSrc));
}
Beispiel #5
0
/**
 * @copydoc RTNetIPv6PseudoChecksumBits
 */
DECLINLINE(uint32_t) rtNetIPv6PseudoChecksumBits(PCRTNETADDRIPV6 pSrcAddr, PCRTNETADDRIPV6 pDstAddr,
                                                 uint8_t bProtocol, uint32_t cbPkt)
{
    uint32_t u32Sum = pSrcAddr->au16[0]
                    + pSrcAddr->au16[1]
                    + pSrcAddr->au16[2]
                    + pSrcAddr->au16[3]
                    + pSrcAddr->au16[4]
                    + pSrcAddr->au16[5]
                    + pSrcAddr->au16[6]
                    + pSrcAddr->au16[7]
                    + pDstAddr->au16[0]
                    + pDstAddr->au16[1]
                    + pDstAddr->au16[2]
                    + pDstAddr->au16[3]
                    + pDstAddr->au16[4]
                    + pDstAddr->au16[5]
                    + pDstAddr->au16[6]
                    + pDstAddr->au16[7]
                    + RT_H2BE_U16(RT_HIWORD(cbPkt))
                    + RT_H2BE_U16(RT_LOWORD(cbPkt))
                    + 0
                    + RT_H2BE_U16(RT_MAKE_U16(bProtocol, 0));
    return u32Sum;
}
Beispiel #6
0
/** @interface_method_impl{PDMAPICHLPR0,pfnCalcIrqTag} */
static DECLCALLBACK(uint32_t) pdmR0ApicHlp_CalcIrqTag(PPDMDEVINS pDevIns, uint8_t u8Level)
{
    PDMDEV_ASSERT_DEVINS(pDevIns);
    PVM pVM = pDevIns->Internal.s.pVMR0;

    pdmLock(pVM);

    uint32_t uTagSrc = pdmCalcIrqTag(pVM, pDevIns->idTracing);
    if (u8Level == PDM_IRQ_LEVEL_HIGH)
        VBOXVMM_PDM_IRQ_HIGH(VMMGetCpu(pVM), RT_LOWORD(uTagSrc), RT_HIWORD(uTagSrc));
    else
        VBOXVMM_PDM_IRQ_HILO(VMMGetCpu(pVM), RT_LOWORD(uTagSrc), RT_HIWORD(uTagSrc));


    pdmUnlock(pVM);
    LogFlow(("pdmR0ApicHlp_CalcIrqTag: caller=%p/%d: returns %#x (u8Level=%d)\n",
             pDevIns, pDevIns->iInstance, uTagSrc, u8Level));
    return uTagSrc;
}
Beispiel #7
0
/**
 * Returns the value of the parameter in pParam
 *
 * @returns VBox error code
 * @param   pCtx            CPU context 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)
{
    memset(pParamVal, 0, sizeof(*pParamVal));

    if (DIS_IS_EFFECTIVE_ADDR(pParam->flags))
    {
        // Effective address
        pParamVal->type = PARMTYPE_ADDRESS;
        pParamVal->size = pParam->size;

        if (pParam->flags & USE_BASE)
        {
            if (pParam->flags & USE_REG_GEN8)
            {
                pParamVal->flags |= PARAM_VAL8;
                if (RT_FAILURE(DISFetchReg8(pCtx, pParam->base.reg_gen, &pParamVal->val.val8))) return VERR_INVALID_PARAMETER;
            }
            else
            if (pParam->flags & USE_REG_GEN16)
            {
                pParamVal->flags |= PARAM_VAL16;
                if (RT_FAILURE(DISFetchReg16(pCtx, pParam->base.reg_gen, &pParamVal->val.val16))) return VERR_INVALID_PARAMETER;
            }
            else
            if (pParam->flags & USE_REG_GEN32)
            {
                pParamVal->flags |= PARAM_VAL32;
                if (RT_FAILURE(DISFetchReg32(pCtx, pParam->base.reg_gen, &pParamVal->val.val32))) return VERR_INVALID_PARAMETER;
            }
            else
            if (pParam->flags & USE_REG_GEN64)
            {
                pParamVal->flags |= PARAM_VAL64;
                if (RT_FAILURE(DISFetchReg64(pCtx, pParam->base.reg_gen, &pParamVal->val.val64))) return VERR_INVALID_PARAMETER;
            }
            else
            {
                AssertFailed();
                return VERR_INVALID_PARAMETER;
            }
        }
        // Note that scale implies index (SIB byte)
        if (pParam->flags & USE_INDEX)
        {
            if (pParam->flags & USE_REG_GEN16)
            {
                uint16_t val16;

                pParamVal->flags |= PARAM_VAL16;
                if (RT_FAILURE(DISFetchReg16(pCtx, pParam->index.reg_gen, &val16))) return VERR_INVALID_PARAMETER;

                Assert(!(pParam->flags & USE_SCALE));   /* shouldn't be possible in 16 bits mode */

                pParamVal->val.val16 += val16;
            }
            else
            if (pParam->flags & USE_REG_GEN32)
            {
                uint32_t val32;

                pParamVal->flags |= PARAM_VAL32;
                if (RT_FAILURE(DISFetchReg32(pCtx, pParam->index.reg_gen, &val32))) return VERR_INVALID_PARAMETER;

                if (pParam->flags & USE_SCALE)
                    val32 *= pParam->scale;

                pParamVal->val.val32 += val32;
            }
            else
            if (pParam->flags & USE_REG_GEN64)
            {
                uint64_t val64;

                pParamVal->flags |= PARAM_VAL64;
                if (RT_FAILURE(DISFetchReg64(pCtx, pParam->index.reg_gen, &val64))) return VERR_INVALID_PARAMETER;

                if (pParam->flags & USE_SCALE)
                    val64 *= pParam->scale;

                pParamVal->val.val64 += val64;
            }
            else
                AssertFailed();
        }

        if (pParam->flags & USE_DISPLACEMENT8)
        {
            if (pCpu->mode == CPUMODE_32BIT)
                pParamVal->val.val32 += (int32_t)pParam->disp8;
            else
            if (pCpu->mode == CPUMODE_64BIT)
                pParamVal->val.val64 += (int64_t)pParam->disp8;
            else
                pParamVal->val.val16 += (int16_t)pParam->disp8;
        }
        else
        if (pParam->flags & USE_DISPLACEMENT16)
        {
            if (pCpu->mode == CPUMODE_32BIT)
                pParamVal->val.val32 += (int32_t)pParam->disp16;
            else
            if (pCpu->mode == CPUMODE_64BIT)
                pParamVal->val.val64 += (int64_t)pParam->disp16;
            else
                pParamVal->val.val16 += pParam->disp16;
        }
        else
        if (pParam->flags & USE_DISPLACEMENT32)
        {
            if (pCpu->mode == CPUMODE_32BIT)
                pParamVal->val.val32 += pParam->disp32;
            else
                pParamVal->val.val64 += pParam->disp32;
        }
        else
        if (pParam->flags & USE_DISPLACEMENT64)
        {
            Assert(pCpu->mode == CPUMODE_64BIT);
            pParamVal->val.val64 += (int64_t)pParam->disp64;
        }
        else
        if (pParam->flags & USE_RIPDISPLACEMENT32)
        {
            Assert(pCpu->mode == CPUMODE_64BIT);
            /* Relative to the RIP of the next instruction. */
            pParamVal->val.val64 += pParam->disp32 + pCtx->rip + pCpu->opsize;
        }
        return VINF_SUCCESS;
    }

    if (pParam->flags & (USE_REG_GEN8|USE_REG_GEN16|USE_REG_GEN32|USE_REG_GEN64|USE_REG_FP|USE_REG_MMX|USE_REG_XMM|USE_REG_CR|USE_REG_DBG|USE_REG_SEG|USE_REG_TEST))
    {
        if (parmtype == PARAM_DEST)
        {
            // Caller needs to interpret the register according to the instruction (source/target, special value etc)
            pParamVal->type = PARMTYPE_REGISTER;
            pParamVal->size = pParam->size;
            return VINF_SUCCESS;
        }
        //else PARAM_SOURCE

        pParamVal->type = PARMTYPE_IMMEDIATE;

        if (pParam->flags & USE_REG_GEN8)
        {
            pParamVal->flags |= PARAM_VAL8;
            pParamVal->size   = sizeof(uint8_t);
            if (RT_FAILURE(DISFetchReg8(pCtx, pParam->base.reg_gen, &pParamVal->val.val8))) return VERR_INVALID_PARAMETER;
        }
        else
        if (pParam->flags & USE_REG_GEN16)
        {
            pParamVal->flags |= PARAM_VAL16;
            pParamVal->size   = sizeof(uint16_t);
            if (RT_FAILURE(DISFetchReg16(pCtx, pParam->base.reg_gen, &pParamVal->val.val16))) return VERR_INVALID_PARAMETER;
        }
        else
        if (pParam->flags & USE_REG_GEN32)
        {
            pParamVal->flags |= PARAM_VAL32;
            pParamVal->size   = sizeof(uint32_t);
            if (RT_FAILURE(DISFetchReg32(pCtx, pParam->base.reg_gen, &pParamVal->val.val32))) return VERR_INVALID_PARAMETER;
        }
        else
        if (pParam->flags & USE_REG_GEN64)
        {
            pParamVal->flags |= PARAM_VAL64;
            pParamVal->size   = sizeof(uint64_t);
            if (RT_FAILURE(DISFetchReg64(pCtx, pParam->base.reg_gen, &pParamVal->val.val64))) return VERR_INVALID_PARAMETER;
        }
        else
        {
            // Caller needs to interpret the register according to the instruction (source/target, special value etc)
            pParamVal->type = PARMTYPE_REGISTER;
        }
        Assert(!(pParam->flags & USE_IMMEDIATE));
        return VINF_SUCCESS;
    }

    if (pParam->flags & USE_IMMEDIATE)
    {
        pParamVal->type = PARMTYPE_IMMEDIATE;
        if (pParam->flags & (USE_IMMEDIATE8|USE_IMMEDIATE8_REL))
        {
            pParamVal->flags |= PARAM_VAL8;
            if (pParam->size == 2)
            {
                pParamVal->size   = sizeof(uint16_t);
                pParamVal->val.val16 = (uint8_t)pParam->parval;
            }
            else
            {
                pParamVal->size   = sizeof(uint8_t);
                pParamVal->val.val8 = (uint8_t)pParam->parval;
            }
        }
        else
        if (pParam->flags & (USE_IMMEDIATE16|USE_IMMEDIATE16_REL|USE_IMMEDIATE_ADDR_0_16|USE_IMMEDIATE16_SX8))
        {
            pParamVal->flags |= PARAM_VAL16;
            pParamVal->size   = sizeof(uint16_t);
            pParamVal->val.val16 = (uint16_t)pParam->parval;
            AssertMsg(pParamVal->size == pParam->size || ((pParam->size == 1) && (pParam->flags & USE_IMMEDIATE16_SX8)), ("pParamVal->size %d vs %d EIP=%RX32\n", pParamVal->size, pParam->size, pCtx->eip) );
        }
        else
        if (pParam->flags & (USE_IMMEDIATE32|USE_IMMEDIATE32_REL|USE_IMMEDIATE_ADDR_0_32|USE_IMMEDIATE32_SX8))
        {
            pParamVal->flags |= PARAM_VAL32;
            pParamVal->size   = sizeof(uint32_t);
            pParamVal->val.val32 = (uint32_t)pParam->parval;
            Assert(pParamVal->size == pParam->size || ((pParam->size == 1) && (pParam->flags & USE_IMMEDIATE32_SX8)) );
        }
        else
        if (pParam->flags & (USE_IMMEDIATE64 | USE_IMMEDIATE64_REL | USE_IMMEDIATE64_SX8))
        {
            pParamVal->flags |= PARAM_VAL64;
            pParamVal->size   = sizeof(uint64_t);
            pParamVal->val.val64 = pParam->parval;
            Assert(pParamVal->size == pParam->size || ((pParam->size == 1) && (pParam->flags & USE_IMMEDIATE64_SX8)) );
        }
        else
        if (pParam->flags & (USE_IMMEDIATE_ADDR_16_16))
        {
            pParamVal->flags |= PARAM_VALFARPTR16;
            pParamVal->size   = sizeof(uint16_t)*2;
            pParamVal->val.farptr.sel    = (uint16_t)RT_LOWORD(pParam->parval >> 16);
            pParamVal->val.farptr.offset = (uint32_t)RT_LOWORD(pParam->parval);
            Assert(pParamVal->size == pParam->size);
        }
/**
 * Returns the value of the parameter in pParam
 *
 * @returns VBox error code
 * @param   pCtx            CPU context structure pointer
 * @param   pDis            Pointer to the disassembler state.
 * @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, PCDISSTATE pDis, PCDISOPPARAM pParam, PDISQPVPARAMVAL pParamVal, DISQPVWHICH parmtype)
{
    memset(pParamVal, 0, sizeof(*pParamVal));

    if (DISUSE_IS_EFFECTIVE_ADDR(pParam->fUse))
    {
        // Effective address
        pParamVal->type = DISQPV_TYPE_ADDRESS;
        pParamVal->size = pParam->cb;

        if (pParam->fUse & DISUSE_BASE)
        {
            if (pParam->fUse & DISUSE_REG_GEN8)
            {
                pParamVal->flags |= DISQPV_FLAG_8;
                if (RT_FAILURE(DISFetchReg8(pCtx, pParam->Base.idxGenReg, &pParamVal->val.val8))) return VERR_INVALID_PARAMETER;
            }
            else
            if (pParam->fUse & DISUSE_REG_GEN16)
            {
                pParamVal->flags |= DISQPV_FLAG_16;
                if (RT_FAILURE(DISFetchReg16(pCtx, pParam->Base.idxGenReg, &pParamVal->val.val16))) return VERR_INVALID_PARAMETER;
            }
            else
            if (pParam->fUse & DISUSE_REG_GEN32)
            {
                pParamVal->flags |= DISQPV_FLAG_32;
                if (RT_FAILURE(DISFetchReg32(pCtx, pParam->Base.idxGenReg, &pParamVal->val.val32))) return VERR_INVALID_PARAMETER;
            }
            else
            if (pParam->fUse & DISUSE_REG_GEN64)
            {
                pParamVal->flags |= DISQPV_FLAG_64;
                if (RT_FAILURE(DISFetchReg64(pCtx, pParam->Base.idxGenReg, &pParamVal->val.val64))) return VERR_INVALID_PARAMETER;
            }
            else
            {
                AssertFailed();
                return VERR_INVALID_PARAMETER;
            }
        }
        // Note that scale implies index (SIB byte)
        if (pParam->fUse & DISUSE_INDEX)
        {
            if (pParam->fUse & DISUSE_REG_GEN16)
            {
                uint16_t val16;

                pParamVal->flags |= DISQPV_FLAG_16;
                if (RT_FAILURE(DISFetchReg16(pCtx, pParam->Index.idxGenReg, &val16))) return VERR_INVALID_PARAMETER;

                Assert(!(pParam->fUse & DISUSE_SCALE));   /* shouldn't be possible in 16 bits mode */

                pParamVal->val.val16 += val16;
            }
            else
            if (pParam->fUse & DISUSE_REG_GEN32)
            {
                uint32_t val32;

                pParamVal->flags |= DISQPV_FLAG_32;
                if (RT_FAILURE(DISFetchReg32(pCtx, pParam->Index.idxGenReg, &val32))) return VERR_INVALID_PARAMETER;

                if (pParam->fUse & DISUSE_SCALE)
                    val32 *= pParam->uScale;

                pParamVal->val.val32 += val32;
            }
            else
            if (pParam->fUse & DISUSE_REG_GEN64)
            {
                uint64_t val64;

                pParamVal->flags |= DISQPV_FLAG_64;
                if (RT_FAILURE(DISFetchReg64(pCtx, pParam->Index.idxGenReg, &val64))) return VERR_INVALID_PARAMETER;

                if (pParam->fUse & DISUSE_SCALE)
                    val64 *= pParam->uScale;

                pParamVal->val.val64 += val64;
            }
            else
                AssertFailed();
        }

        if (pParam->fUse & DISUSE_DISPLACEMENT8)
        {
            if (pDis->uCpuMode == DISCPUMODE_32BIT)
                pParamVal->val.val32 += (int32_t)pParam->uDisp.i8;
            else
            if (pDis->uCpuMode == DISCPUMODE_64BIT)
                pParamVal->val.val64 += (int64_t)pParam->uDisp.i8;
            else
                pParamVal->val.val16 += (int16_t)pParam->uDisp.i8;
        }
        else
        if (pParam->fUse & DISUSE_DISPLACEMENT16)
        {
            if (pDis->uCpuMode == DISCPUMODE_32BIT)
                pParamVal->val.val32 += (int32_t)pParam->uDisp.i16;
            else
            if (pDis->uCpuMode == DISCPUMODE_64BIT)
                pParamVal->val.val64 += (int64_t)pParam->uDisp.i16;
            else
                pParamVal->val.val16 += pParam->uDisp.i16;
        }
        else
        if (pParam->fUse & DISUSE_DISPLACEMENT32)
        {
            if (pDis->uCpuMode == DISCPUMODE_32BIT)
                pParamVal->val.val32 += pParam->uDisp.i32;
            else
                pParamVal->val.val64 += pParam->uDisp.i32;
        }
        else
        if (pParam->fUse & DISUSE_DISPLACEMENT64)
        {
            Assert(pDis->uCpuMode == DISCPUMODE_64BIT);
            pParamVal->val.val64 += pParam->uDisp.i64;
        }
        else
        if (pParam->fUse & DISUSE_RIPDISPLACEMENT32)
        {
            Assert(pDis->uCpuMode == DISCPUMODE_64BIT);
            /* Relative to the RIP of the next instruction. */
            pParamVal->val.val64 += pParam->uDisp.i32 + pCtx->rip + pDis->cbInstr;
        }
        return VINF_SUCCESS;
    }

    if (pParam->fUse & (DISUSE_REG_GEN8|DISUSE_REG_GEN16|DISUSE_REG_GEN32|DISUSE_REG_GEN64|DISUSE_REG_FP|DISUSE_REG_MMX|DISUSE_REG_XMM|DISUSE_REG_CR|DISUSE_REG_DBG|DISUSE_REG_SEG|DISUSE_REG_TEST))
    {
        if (parmtype == DISQPVWHICH_DST)
        {
            // Caller needs to interpret the register according to the instruction (source/target, special value etc)
            pParamVal->type = DISQPV_TYPE_REGISTER;
            pParamVal->size = pParam->cb;
            return VINF_SUCCESS;
        }
        //else DISQPVWHICH_SRC

        pParamVal->type = DISQPV_TYPE_IMMEDIATE;

        if (pParam->fUse & DISUSE_REG_GEN8)
        {
            pParamVal->flags |= DISQPV_FLAG_8;
            pParamVal->size   = sizeof(uint8_t);
            if (RT_FAILURE(DISFetchReg8(pCtx, pParam->Base.idxGenReg, &pParamVal->val.val8))) return VERR_INVALID_PARAMETER;
        }
        else
        if (pParam->fUse & DISUSE_REG_GEN16)
        {
            pParamVal->flags |= DISQPV_FLAG_16;
            pParamVal->size   = sizeof(uint16_t);
            if (RT_FAILURE(DISFetchReg16(pCtx, pParam->Base.idxGenReg, &pParamVal->val.val16))) return VERR_INVALID_PARAMETER;
        }
        else
        if (pParam->fUse & DISUSE_REG_GEN32)
        {
            pParamVal->flags |= DISQPV_FLAG_32;
            pParamVal->size   = sizeof(uint32_t);
            if (RT_FAILURE(DISFetchReg32(pCtx, pParam->Base.idxGenReg, &pParamVal->val.val32))) return VERR_INVALID_PARAMETER;
        }
        else
        if (pParam->fUse & DISUSE_REG_GEN64)
        {
            pParamVal->flags |= DISQPV_FLAG_64;
            pParamVal->size   = sizeof(uint64_t);
            if (RT_FAILURE(DISFetchReg64(pCtx, pParam->Base.idxGenReg, &pParamVal->val.val64))) return VERR_INVALID_PARAMETER;
        }
        else
        {
            // Caller needs to interpret the register according to the instruction (source/target, special value etc)
            pParamVal->type = DISQPV_TYPE_REGISTER;
        }
        Assert(!(pParam->fUse & DISUSE_IMMEDIATE));
        return VINF_SUCCESS;
    }

    if (pParam->fUse & DISUSE_IMMEDIATE)
    {
        pParamVal->type = DISQPV_TYPE_IMMEDIATE;
        if (pParam->fUse & (DISUSE_IMMEDIATE8|DISUSE_IMMEDIATE8_REL))
        {
            pParamVal->flags |= DISQPV_FLAG_8;
            if (pParam->cb == 2)
            {
                pParamVal->size   = sizeof(uint16_t);
                pParamVal->val.val16 = (uint8_t)pParam->uValue;
            }
            else
            {
                pParamVal->size   = sizeof(uint8_t);
                pParamVal->val.val8 = (uint8_t)pParam->uValue;
            }
        }
        else
        if (pParam->fUse & (DISUSE_IMMEDIATE16|DISUSE_IMMEDIATE16_REL|DISUSE_IMMEDIATE_ADDR_0_16|DISUSE_IMMEDIATE16_SX8))
        {
            pParamVal->flags |= DISQPV_FLAG_16;
            pParamVal->size   = sizeof(uint16_t);
            pParamVal->val.val16 = (uint16_t)pParam->uValue;
            AssertMsg(pParamVal->size == pParam->cb || ((pParam->cb == 1) && (pParam->fUse & DISUSE_IMMEDIATE16_SX8)), ("pParamVal->size %d vs %d EIP=%RX32\n", pParamVal->size, pParam->cb, pCtx->eip) );
        }
        else
        if (pParam->fUse & (DISUSE_IMMEDIATE32|DISUSE_IMMEDIATE32_REL|DISUSE_IMMEDIATE_ADDR_0_32|DISUSE_IMMEDIATE32_SX8))
        {
            pParamVal->flags |= DISQPV_FLAG_32;
            pParamVal->size   = sizeof(uint32_t);
            pParamVal->val.val32 = (uint32_t)pParam->uValue;
            Assert(pParamVal->size == pParam->cb || ((pParam->cb == 1) && (pParam->fUse & DISUSE_IMMEDIATE32_SX8)) );
        }
        else
        if (pParam->fUse & (DISUSE_IMMEDIATE64 | DISUSE_IMMEDIATE64_REL | DISUSE_IMMEDIATE64_SX8))
        {
            pParamVal->flags |= DISQPV_FLAG_64;
            pParamVal->size   = sizeof(uint64_t);
            pParamVal->val.val64 = pParam->uValue;
            Assert(pParamVal->size == pParam->cb || ((pParam->cb == 1) && (pParam->fUse & DISUSE_IMMEDIATE64_SX8)) );
        }
        else
        if (pParam->fUse & (DISUSE_IMMEDIATE_ADDR_16_16))
        {
            pParamVal->flags |= DISQPV_FLAG_FARPTR16;
            pParamVal->size   = sizeof(uint16_t)*2;
            pParamVal->val.farptr.sel    = (uint16_t)RT_LOWORD(pParam->uValue >> 16);
            pParamVal->val.farptr.offset = (uint32_t)RT_LOWORD(pParam->uValue);
            Assert(pParamVal->size == pParam->cb);
        }