Changeset 2230 in vbox for trunk/src/VBox/VMM/VMMAll/IOMAll.cpp
- Timestamp:
- Apr 19, 2007 2:01:32 PM (18 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/VMMAll/IOMAll.cpp
r2228 r2230 38 38 39 39 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 */ 47 static 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 */ 73 static 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 */ 103 static 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 */ 177 static 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 */ 215 inline 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 40 239 /** 41 240 * Registers a Port IO GC handler. … … 1094 1293 return VINF_SUCCESS; 1095 1294 } 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 */ 1305 IOMDECL(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 */ 1352 IOMDECL(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.