Changeset 2226 in vbox for trunk/src/VBox/VMM/VMMGC/IOMGC.cpp
- Timestamp:
- Apr 19, 2007 1:48:01 PM (18 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/VMMGC/IOMGC.cpp
r2202 r2226 46 46 47 47 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 by185 * 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_STATISTICS235 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 #else252 NOREF(pVM); NOREF(cb);253 #endif254 }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_STATISTICS269 STAM_COUNTER_INC(&pVM->iom.s.StatGCInstIn);270 #endif271 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_STATISTICS316 STAM_COUNTER_INC(&pVM->iom.s.StatGCInstOut);317 #endif318 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 }342 48 343 49 /**
Note:
See TracChangeset
for help on using the changeset viewer.