VirtualBox

Ignore:
Timestamp:
Apr 19, 2007 2:01:32 PM (18 years ago)
Author:
vboxsync
Message:

Partial 20576 commit

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/VMMAll/IOMAll.cpp

    r2228 r2230  
    3838
    3939
     40/*******************************************************************************
     41*   Global Variables                                                           *
     42*******************************************************************************/
     43
     44/**
     45 * Array for fast recode of the operand size (1/2/4/8 bytes) to bit shift value.
     46 */
     47static const unsigned g_aSize2Shift[] =
     48{
     49    ~0,    /* 0 - invalid */
     50    0,     /* *1 == 2^0 */
     51    1,     /* *2 == 2^1 */
     52    ~0,    /* 3 - invalid */
     53    2,     /* *4 == 2^2 */
     54    ~0,    /* 5 - invalid */
     55    ~0,    /* 6 - invalid */
     56    ~0,    /* 7 - invalid */
     57    3      /* *8 == 2^3 */
     58};
     59
     60/**
     61 * Macro for fast recode of the operand size (1/2/4/8 bytes) to bit shift value.
     62 */
     63#define SIZE2SHIFT(cb) (g_aSize2Shift[cb])
     64
     65/**
     66 * Calculates the size of register parameter.
     67 *
     68 * @returns 1, 2, 4 on success.
     69 * @returns 0 if non-register parameter.
     70 * @param   pCpu                Pointer to current disassembler context.
     71 * @param   pParam              Pointer to parameter of instruction to proccess.
     72 */
     73static unsigned iomGCGetRegSize(PDISCPUSTATE pCpu, PCOP_PARAMETER pParam)
     74{
     75    if (pParam->flags & (USE_BASE | USE_INDEX | USE_SCALE | USE_DISPLACEMENT8 | USE_DISPLACEMENT16 | USE_DISPLACEMENT32 | USE_IMMEDIATE8 | USE_IMMEDIATE16 | USE_IMMEDIATE32 | USE_IMMEDIATE16_SX8 | USE_IMMEDIATE32_SX8))
     76        return 0;
     77
     78    if (pParam->flags & USE_REG_GEN32)
     79        return 4;
     80
     81    if (pParam->flags & USE_REG_GEN16)
     82        return 2;
     83
     84    if (pParam->flags & USE_REG_GEN8)
     85        return 1;
     86
     87    if (pParam->flags & USE_REG_SEG)
     88        return 2;
     89    return 0;
     90}
     91
     92/**
     93 * Returns the contents of register or immediate data of instruction's parameter.
     94 *
     95 * @returns true on success.
     96 *
     97 * @param   pCpu                Pointer to current disassembler context.
     98 * @param   pParam              Pointer to parameter of instruction to proccess.
     99 * @param   pRegFrame           Pointer to CPUMCTXCORE guest structure.
     100 * @param   pu32Data            Where to store retrieved data.
     101 * @param   pcbSize             Where to store the size of data (1, 2, 4).
     102 */
     103static bool iomGCGetRegImmData(PDISCPUSTATE pCpu, PCOP_PARAMETER pParam, PCPUMCTXCORE pRegFrame, uint32_t *pu32Data, unsigned *pcbSize)
     104{
     105    if (pParam->flags & (USE_BASE | USE_INDEX | USE_SCALE | USE_DISPLACEMENT8 | USE_DISPLACEMENT16 | USE_DISPLACEMENT32))
     106    {
     107        *pcbSize  = 0;
     108        *pu32Data = 0;
     109        return false;
     110    }
     111
     112    if (pParam->flags & USE_REG_GEN32)
     113    {
     114        *pcbSize  = 4;
     115        DISFetchReg32(pRegFrame, pParam->base.reg_gen32, pu32Data);
     116        return true;
     117    }
     118
     119    if (pParam->flags & USE_REG_GEN16)
     120    {
     121        *pcbSize  = 2;
     122        DISFetchReg16(pRegFrame, pParam->base.reg_gen16, (uint16_t *)pu32Data);
     123        return true;
     124    }
     125
     126    if (pParam->flags & USE_REG_GEN8)
     127    {
     128        *pcbSize  = 1;
     129        DISFetchReg8(pRegFrame, pParam->base.reg_gen8, (uint8_t *)pu32Data);
     130        return true;
     131    }
     132
     133    if (pParam->flags & (USE_IMMEDIATE32|USE_IMMEDIATE32_SX8))
     134    {
     135        *pcbSize  = 4;
     136        *pu32Data = (uint32_t)pParam->parval;
     137        return true;
     138    }
     139
     140    if (pParam->flags & (USE_IMMEDIATE16|USE_IMMEDIATE16_SX8))
     141    {
     142        *pcbSize  = 2;
     143        *pu32Data = (uint16_t)pParam->parval;
     144        return true;
     145    }
     146
     147    if (pParam->flags & USE_IMMEDIATE8)
     148    {
     149        *pcbSize  = 1;
     150        *pu32Data = (uint8_t)pParam->parval;
     151        return true;
     152    }
     153
     154    if (pParam->flags & USE_REG_SEG)
     155    {
     156        *pcbSize  = 2;
     157        DISFetchRegSeg(pRegFrame, pParam->base.reg_seg, (RTSEL *)pu32Data);
     158        return true;
     159    } /* Else - error. */
     160
     161    *pcbSize  = 0;
     162    *pu32Data = 0;
     163    return false;
     164}
     165
     166
     167/**
     168 * Saves data to 8/16/32 general purpose or segment register defined by
     169 * instruction's parameter.
     170 *
     171 * @returns true on success.
     172 * @param   pCpu                Pointer to current disassembler context.
     173 * @param   pParam              Pointer to parameter of instruction to proccess.
     174 * @param   pRegFrame           Pointer to CPUMCTXCORE guest structure.
     175 * @param   u32Data             8/16/32 bit data to store.
     176 */
     177static bool iomGCSaveDataToReg(PDISCPUSTATE pCpu, PCOP_PARAMETER pParam, PCPUMCTXCORE pRegFrame, unsigned u32Data)
     178{
     179    if (pParam->flags & (USE_BASE | USE_INDEX | USE_SCALE | USE_DISPLACEMENT8 | USE_DISPLACEMENT16 | USE_DISPLACEMENT32 | USE_IMMEDIATE8 | USE_IMMEDIATE16 | USE_IMMEDIATE32 | USE_IMMEDIATE32_SX8 | USE_IMMEDIATE16_SX8))
     180    {
     181        return false;
     182    }
     183
     184    if (pParam->flags & USE_REG_GEN32)
     185    {
     186        DISWriteReg32(pRegFrame, pParam->base.reg_gen32, u32Data);
     187        return true;
     188    }
     189
     190    if (pParam->flags & USE_REG_GEN16)
     191    {
     192        DISWriteReg16(pRegFrame, pParam->base.reg_gen16, (uint16_t)u32Data);
     193        return true;
     194    }
     195
     196    if (pParam->flags & USE_REG_GEN8)
     197    {
     198        DISWriteReg8(pRegFrame, pParam->base.reg_gen8, (uint8_t)u32Data);
     199        return true;
     200    }
     201
     202    if (pParam->flags & USE_REG_SEG)
     203    {
     204        DISWriteRegSeg(pRegFrame, pParam->base.reg_seg, (RTSEL)u32Data);
     205        return true;
     206    }
     207
     208    /* Else - error. */
     209    return false;
     210}
     211
     212/*
     213 * Internal - statistics only.
     214 */
     215inline void iomGCMMIOStatLength(PVM pVM, unsigned cb)
     216{
     217#ifdef VBOX_WITH_STATISTICS
     218    switch (cb)
     219    {
     220        case 1:
     221            STAM_COUNTER_INC(&pVM->iom.s.StatGCMMIO1Byte);
     222            break;
     223        case 2:
     224            STAM_COUNTER_INC(&pVM->iom.s.StatGCMMIO2Bytes);
     225            break;
     226        case 4:
     227            STAM_COUNTER_INC(&pVM->iom.s.StatGCMMIO4Bytes);
     228            break;
     229        default:
     230            /* No way. */
     231            AssertMsgFailed(("Invalid data length %d\n", cb));
     232            break;
     233    }
     234#else
     235    NOREF(pVM); NOREF(cb);
     236#endif
     237}
     238
    40239/**
    41240 * Registers a Port IO GC handler.
     
    10941293    return VINF_SUCCESS;
    10951294}
     1295
     1296/**
     1297 * IN <AL|AX|EAX>, <DX|imm16>
     1298 *
     1299 * @returns VBox status code.
     1300 *
     1301 * @param   pVM         The virtual machine (GC pointer ofcourse).
     1302 * @param   pRegFrame   Pointer to CPUMCTXCORE guest registers structure.
     1303 * @param   pCpu        Disassembler CPU state.
     1304 */
     1305IOMDECL(int) IOMInterpretIN(PVM pVM, PCPUMCTXCORE pRegFrame, PDISCPUSTATE pCpu)
     1306{
     1307#ifdef IN_GC
     1308    STAM_COUNTER_INC(&pVM->iom.s.StatGCInstIn);
     1309#endif
     1310
     1311    /*
     1312     * Get port number from second parameter.
     1313     * And get the register size from the first parameter.
     1314     */
     1315    uint32_t    uPort = 0;
     1316    unsigned    cbSize = 0;
     1317    bool fRc = iomGCGetRegImmData(pCpu, &pCpu->param2, pRegFrame, &uPort, &cbSize);
     1318    AssertMsg(fRc, ("Failed to get reg/imm port number!\n")); NOREF(fRc);
     1319
     1320    cbSize = iomGCGetRegSize(pCpu, &pCpu->param1);
     1321    Assert(cbSize > 0);
     1322    int rc = IOMInterpretCheckPortIOAccess(pVM, pRegFrame, uPort, cbSize);
     1323    if (rc == VINF_SUCCESS)
     1324    {
     1325        /*
     1326         * Attemp to read the port.
     1327         */
     1328        uint32_t    u32Data = ~0U;
     1329        rc = IOMIOPortRead(pVM, uPort, &u32Data, cbSize);
     1330        if (rc == VINF_SUCCESS)
     1331        {
     1332            /*
     1333             * Store the result in the AL|AX|EAX register.
     1334             */
     1335            fRc = iomGCSaveDataToReg(pCpu, &pCpu->param1, pRegFrame, u32Data);
     1336            AssertMsg(fRc, ("Failed to store register value!\n")); NOREF(fRc);
     1337        }
     1338    }
     1339    return rc;
     1340}
     1341
     1342
     1343/**
     1344 * OUT <DX|imm16>, <AL|AX|EAX>
     1345 *
     1346 * @returns VBox status code.
     1347 *
     1348 * @param   pVM         The virtual machine (GC pointer ofcourse).
     1349 * @param   pRegFrame   Pointer to CPUMCTXCORE guest registers structure.
     1350 * @param   pCpu        Disassembler CPU state.
     1351 */
     1352IOMDECL(int) IOMInterpretOUT(PVM pVM, PCPUMCTXCORE pRegFrame, PDISCPUSTATE pCpu)
     1353{
     1354#ifdef IN_GC
     1355    STAM_COUNTER_INC(&pVM->iom.s.StatGCInstOut);
     1356#endif
     1357
     1358    /*
     1359     * Get port number from first parameter.
     1360     * And get the register size and value from the second parameter.
     1361     */
     1362    uint32_t    uPort = 0;
     1363    unsigned    cbSize = 0;
     1364    bool fRc = iomGCGetRegImmData(pCpu, &pCpu->param1, pRegFrame, &uPort, &cbSize);
     1365    AssertMsg(fRc, ("Failed to get reg/imm port number!\n")); NOREF(fRc);
     1366
     1367    int rc = IOMInterpretCheckPortIOAccess(pVM, pRegFrame, uPort, cbSize);
     1368    if (rc == VINF_SUCCESS)
     1369    {
     1370        uint32_t    u32Data = 0;
     1371        fRc = iomGCGetRegImmData(pCpu, &pCpu->param2, pRegFrame, &u32Data, &cbSize);
     1372        AssertMsg(fRc, ("Failed to get reg value!\n")); NOREF(fRc);
     1373
     1374        /*
     1375         * Attemp to write to the port.
     1376         */
     1377        rc = IOMIOPortWrite(pVM, uPort, u32Data, cbSize);
     1378    }
     1379    return rc;
     1380}
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette