VirtualBox

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

Cleanup of emR3RawExecuteIOInstruction: use existing IOM functions.
Moved IOMInterpretIN & IOMInterpretOUT to the VMMAll directory.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/VMMGC/IOMGC.cpp

    r2202 r2226  
    4646
    4747
    48 /*******************************************************************************
    49 *   Internal Functions                                                         *
    50 *******************************************************************************/
    51 static unsigned iomGCGetRegSize(PDISCPUSTATE pCpu, PCOP_PARAMETER pParam);
    52 static bool iomGCGetRegImmData(PDISCPUSTATE pCpu, PCOP_PARAMETER pParam, PCPUMCTXCORE pRegFrame, uint32_t *pu32Data, unsigned *pcbSize);
    53 static bool iomGCSaveDataToReg(PDISCPUSTATE pCpu, PCOP_PARAMETER pParam, PCPUMCTXCORE pRegFrame, uint32_t u32Data);
    54 
    55 
    56 /*******************************************************************************
    57 *   Global Variables                                                           *
    58 *******************************************************************************/
    59 
    60 /**
    61  * Array for fast recode of the operand size (1/2/4/8 bytes) to bit shift value.
    62  */
    63 static const unsigned g_aSize2Shift[] =
    64 {
    65     ~0,    /* 0 - invalid */
    66     0,     /* *1 == 2^0 */
    67     1,     /* *2 == 2^1 */
    68     ~0,    /* 3 - invalid */
    69     2,     /* *4 == 2^2 */
    70     ~0,    /* 5 - invalid */
    71     ~0,    /* 6 - invalid */
    72     ~0,    /* 7 - invalid */
    73     3      /* *8 == 2^3 */
    74 };
    75 
    76 /**
    77  * Macro for fast recode of the operand size (1/2/4/8 bytes) to bit shift value.
    78  */
    79 #define SIZE2SHIFT(cb) (g_aSize2Shift[cb])
    80 
    81 /**
    82  * Calculates the size of register parameter.
    83  *
    84  * @returns 1, 2, 4 on success.
    85  * @returns 0 if non-register parameter.
    86  * @param   pCpu                Pointer to current disassembler context.
    87  * @param   pParam              Pointer to parameter of instruction to proccess.
    88  */
    89 static unsigned iomGCGetRegSize(PDISCPUSTATE pCpu, PCOP_PARAMETER pParam)
    90 {
    91     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))
    92         return 0;
    93 
    94     if (pParam->flags & USE_REG_GEN32)
    95         return 4;
    96 
    97     if (pParam->flags & USE_REG_GEN16)
    98         return 2;
    99 
    100     if (pParam->flags & USE_REG_GEN8)
    101         return 1;
    102 
    103     if (pParam->flags & USE_REG_SEG)
    104         return 2;
    105     return 0;
    106 }
    107 
    108 /**
    109  * Returns the contents of register or immediate data of instruction's parameter.
    110  *
    111  * @returns true on success.
    112  *
    113  * @param   pCpu                Pointer to current disassembler context.
    114  * @param   pParam              Pointer to parameter of instruction to proccess.
    115  * @param   pRegFrame           Pointer to CPUMCTXCORE guest structure.
    116  * @param   pu32Data            Where to store retrieved data.
    117  * @param   pcbSize             Where to store the size of data (1, 2, 4).
    118  */
    119 static bool iomGCGetRegImmData(PDISCPUSTATE pCpu, PCOP_PARAMETER pParam, PCPUMCTXCORE pRegFrame, uint32_t *pu32Data, unsigned *pcbSize)
    120 {
    121     if (pParam->flags & (USE_BASE | USE_INDEX | USE_SCALE | USE_DISPLACEMENT8 | USE_DISPLACEMENT16 | USE_DISPLACEMENT32))
    122     {
    123         *pcbSize  = 0;
    124         *pu32Data = 0;
    125         return false;
    126     }
    127 
    128     if (pParam->flags & USE_REG_GEN32)
    129     {
    130         *pcbSize  = 4;
    131         DISFetchReg32(pRegFrame, pParam->base.reg_gen32, pu32Data);
    132         return true;
    133     }
    134 
    135     if (pParam->flags & USE_REG_GEN16)
    136     {
    137         *pcbSize  = 2;
    138         DISFetchReg16(pRegFrame, pParam->base.reg_gen16, (uint16_t *)pu32Data);
    139         return true;
    140     }
    141 
    142     if (pParam->flags & USE_REG_GEN8)
    143     {
    144         *pcbSize  = 1;
    145         DISFetchReg8(pRegFrame, pParam->base.reg_gen8, (uint8_t *)pu32Data);
    146         return true;
    147     }
    148 
    149     if (pParam->flags & (USE_IMMEDIATE32|USE_IMMEDIATE32_SX8))
    150     {
    151         *pcbSize  = 4;
    152         *pu32Data = (uint32_t)pParam->parval;
    153         return true;
    154     }
    155 
    156     if (pParam->flags & (USE_IMMEDIATE16|USE_IMMEDIATE16_SX8))
    157     {
    158         *pcbSize  = 2;
    159         *pu32Data = (uint16_t)pParam->parval;
    160         return true;
    161     }
    162 
    163     if (pParam->flags & USE_IMMEDIATE8)
    164     {
    165         *pcbSize  = 1;
    166         *pu32Data = (uint8_t)pParam->parval;
    167         return true;
    168     }
    169 
    170     if (pParam->flags & USE_REG_SEG)
    171     {
    172         *pcbSize  = 2;
    173         DISFetchRegSeg(pRegFrame, pParam->base.reg_seg, (RTSEL *)pu32Data);
    174         return true;
    175     } /* Else - error. */
    176 
    177     *pcbSize  = 0;
    178     *pu32Data = 0;
    179     return false;
    180 }
    181 
    182 
    183 /**
    184  * Saves data to 8/16/32 general purpose or segment register defined by
    185  * instruction's parameter.
    186  *
    187  * @returns true on success.
    188  * @param   pCpu                Pointer to current disassembler context.
    189  * @param   pParam              Pointer to parameter of instruction to proccess.
    190  * @param   pRegFrame           Pointer to CPUMCTXCORE guest structure.
    191  * @param   u32Data             8/16/32 bit data to store.
    192  */
    193 static bool iomGCSaveDataToReg(PDISCPUSTATE pCpu, PCOP_PARAMETER pParam, PCPUMCTXCORE pRegFrame, unsigned u32Data)
    194 {
    195     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))
    196     {
    197         return false;
    198     }
    199 
    200     if (pParam->flags & USE_REG_GEN32)
    201     {
    202         DISWriteReg32(pRegFrame, pParam->base.reg_gen32, u32Data);
    203         return true;
    204     }
    205 
    206     if (pParam->flags & USE_REG_GEN16)
    207     {
    208         DISWriteReg16(pRegFrame, pParam->base.reg_gen16, (uint16_t)u32Data);
    209         return true;
    210     }
    211 
    212     if (pParam->flags & USE_REG_GEN8)
    213     {
    214         DISWriteReg8(pRegFrame, pParam->base.reg_gen8, (uint8_t)u32Data);
    215         return true;
    216     }
    217 
    218     if (pParam->flags & USE_REG_SEG)
    219     {
    220         DISWriteRegSeg(pRegFrame, pParam->base.reg_seg, (RTSEL)u32Data);
    221         return true;
    222     }
    223 
    224     /* Else - error. */
    225     return false;
    226 }
    227 
    228 
    229 /*
    230  * Internal - statistics only.
    231  */
    232 inline void iomGCMMIOStatLength(PVM pVM, unsigned cb)
    233 {
    234 #ifdef VBOX_WITH_STATISTICS
    235     switch (cb)
    236     {
    237         case 1:
    238             STAM_COUNTER_INC(&pVM->iom.s.StatGCMMIO1Byte);
    239             break;
    240         case 2:
    241             STAM_COUNTER_INC(&pVM->iom.s.StatGCMMIO2Bytes);
    242             break;
    243         case 4:
    244             STAM_COUNTER_INC(&pVM->iom.s.StatGCMMIO4Bytes);
    245             break;
    246         default:
    247             /* No way. */
    248             AssertMsgFailed(("Invalid data length %d\n", cb));
    249             break;
    250     }
    251 #else
    252     NOREF(pVM); NOREF(cb);
    253 #endif
    254 }
    255 
    256 
    257 /**
    258  * IN <AL|AX|EAX>, <DX|imm16>
    259  *
    260  * @returns VBox status code.
    261  *
    262  * @param   pVM         The virtual machine (GC pointer ofcourse).
    263  * @param   pRegFrame   Pointer to CPUMCTXCORE guest registers structure.
    264  * @param   pCpu        Disassembler CPU state.
    265  */
    266 IOMDECL(int) IOMInterpretIN(PVM pVM, PCPUMCTXCORE pRegFrame, PDISCPUSTATE pCpu)
    267 {
    268 #ifdef VBOX_WITH_STATISTICS
    269     STAM_COUNTER_INC(&pVM->iom.s.StatGCInstIn);
    270 #endif
    271 
    272     /*
    273      * Get port number from second parameter.
    274      * And get the register size from the first parameter.
    275      */
    276     uint32_t    uPort = 0;
    277     unsigned    cbSize = 0;
    278     bool fRc = iomGCGetRegImmData(pCpu, &pCpu->param2, pRegFrame, &uPort, &cbSize);
    279     AssertMsg(fRc, ("Failed to get reg/imm port number!\n")); NOREF(fRc);
    280 
    281     cbSize = iomGCGetRegSize(pCpu, &pCpu->param1);
    282     Assert(cbSize > 0);
    283     int rc = IOMInterpretCheckPortIOAccess(pVM, pRegFrame, uPort, cbSize);
    284     if (rc == VINF_SUCCESS)
    285     {
    286         /*
    287          * Attemp to read the port.
    288          */
    289         uint32_t    u32Data = ~0U;
    290         rc = IOMIOPortRead(pVM, uPort, &u32Data, cbSize);
    291         if (rc == VINF_SUCCESS)
    292         {
    293             /*
    294              * Store the result in the AL|AX|EAX register.
    295              */
    296             fRc = iomGCSaveDataToReg(pCpu, &pCpu->param1, pRegFrame, u32Data);
    297             AssertMsg(fRc, ("Failed to store register value!\n")); NOREF(fRc);
    298         }
    299     }
    300     return rc;
    301 }
    302 
    303 
    304 /**
    305  * OUT <DX|imm16>, <AL|AX|EAX>
    306  *
    307  * @returns VBox status code.
    308  *
    309  * @param   pVM         The virtual machine (GC pointer ofcourse).
    310  * @param   pRegFrame   Pointer to CPUMCTXCORE guest registers structure.
    311  * @param   pCpu        Disassembler CPU state.
    312  */
    313 IOMDECL(int) IOMInterpretOUT(PVM pVM, PCPUMCTXCORE pRegFrame, PDISCPUSTATE pCpu)
    314 {
    315 #ifdef VBOX_WITH_STATISTICS
    316     STAM_COUNTER_INC(&pVM->iom.s.StatGCInstOut);
    317 #endif
    318 
    319     /*
    320      * Get port number from first parameter.
    321      * And get the register size and value from the second parameter.
    322      */
    323     uint32_t    uPort = 0;
    324     unsigned    cbSize = 0;
    325     bool fRc = iomGCGetRegImmData(pCpu, &pCpu->param1, pRegFrame, &uPort, &cbSize);
    326     AssertMsg(fRc, ("Failed to get reg/imm port number!\n")); NOREF(fRc);
    327 
    328     int rc = IOMInterpretCheckPortIOAccess(pVM, pRegFrame, uPort, cbSize);
    329     if (rc == VINF_SUCCESS)
    330     {
    331         uint32_t    u32Data = 0;
    332         fRc = iomGCGetRegImmData(pCpu, &pCpu->param2, pRegFrame, &u32Data, &cbSize);
    333         AssertMsg(fRc, ("Failed to get reg value!\n")); NOREF(fRc);
    334 
    335         /*
    336          * Attemp to write to the port.
    337          */
    338         rc = IOMIOPortWrite(pVM, uPort, u32Data, cbSize);
    339     }
    340     return rc;
    341 }
    34248
    34349/**
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