Changeset 36794 in vbox
- Timestamp:
- Apr 21, 2011 3:02:34 PM (14 years ago)
- svn:sync-xref-src-repo-rev:
- 71349
- Location:
- trunk
- Files:
-
- 8 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/VBox/vmm/iem.h
r36768 r36794 40 40 VMMDECL(VBOXSTRICTRC) IEMExecOne(PVMCPU pVCpu); 41 41 42 #if defined(IEM_VERIFICATION_MODE) && defined(IN_RING3) 43 VMM_INT_DECL(void) IEMNotifyMMIORead(PVM pVM, RTGCPHYS GCPhys, size_t cbValue); 44 VMM_INT_DECL(void) IEMNotifyMMIOWrite(PVM pVM, RTGCPHYS GCPhys, uint32_t u32Value, size_t cbValue); 45 VMM_INT_DECL(void) IEMNotifyIOPortRead(PVM pVM, RTIOPORT Port, size_t cbValue); 46 VMM_INT_DECL(void) IEMNotifyIOPortWrite(PVM pVM, RTIOPORT Port, uint32_t u32Value, size_t cbValue); 47 VMM_INT_DECL(void) IEMNotifyIOPortReadString(PVM pVM, RTIOPORT Port, RTGCPTR GCPtrDst, RTGCUINTREG cTransfers, size_t cbValue); 48 VMM_INT_DECL(void) IEMNotifyIOPortWriteString(PVM pVM, RTIOPORT Port, RTGCPTR GCPtrSrc, RTGCUINTREG cTransfers, size_t cbValue); 49 #endif 42 50 43 51 -
trunk/src/VBox/VMM/VMMAll/IEMAll.cpp
r36780 r36794 53 53 #ifdef IEM_VERIFICATION_MODE 54 54 # include <VBox/vmm/rem.h> 55 # include <VBox/vmm/mm.h> 55 56 #endif 56 57 #include "IEMInternal.h" … … 187 188 * Defined Constants And Macros * 188 189 *******************************************************************************/ 190 /** Temporary hack to disable the double execution. Will be removed in favor 191 * of a dedicated execution mode in EM. */ 192 //#define IEM_VERIFICATION_MODE_NO_REM 193 189 194 /** Used to shut up GCC warnings about variables that 'may be used uninitialized' 190 195 * due to GCC lacking knowledge about the value range of a switch. */ … … 500 505 static VBOXSTRICTRC iemRaiseSelectorNotPresent(PIEMCPU pIemCpu, uint32_t iSegReg, uint32_t fAccess); 501 506 static VBOXSTRICTRC iemRaisePageFault(PIEMCPU pIemCpu, RTGCPTR GCPtrWhere, uint32_t fAccess, int rc); 507 #if defined(IEM_VERIFICATION_MODE) && !defined(IEM_VERIFICATION_MODE_NO_REM) 508 static PIEMVERIFYEVTREC iemVerifyAllocRecord(PIEMCPU pIemCpu); 509 static VBOXSTRICTRC iemVerifyFakeIOPortRead(PIEMCPU pIemCpu, RTIOPORT Port, uint32_t *pu32Value, size_t cbValue); 510 static VBOXSTRICTRC iemVerifyFakeIOPortWrite(PIEMCPU pIemCpu, RTIOPORT Port, uint32_t u32Value, size_t cbValue); 511 #endif 502 512 503 513 … … 2078 2088 static int iemMemPageMap(PIEMCPU pIemCpu, RTGCPHYS GCPhysMem, uint32_t fAccess, void **ppvMem) 2079 2089 { 2080 #if def IEM_VERIFICATION_MODE2090 #if defined(IEM_VERIFICATION_MODE) && !defined(IEM_VERIFICATION_MODE_NO_REM) 2081 2091 /* Force the alternative path so we can ignore writes. */ 2082 2092 if (fAccess & IEM_ACCESS_TYPE_WRITE) … … 2162 2172 */ 2163 2173 int rc; 2164 #if ndef IEM_VERIFICATION_MODE/* No memory changes in verification mode. */2174 #if !defined(IEM_VERIFICATION_MODE) || defined(IEM_VERIFICATION_MODE_NO_REM) /* No memory changes in verification mode. */ 2165 2175 if (!pIemCpu->aMemBbMappings[iMemMap].fUnassigned) 2166 2176 { … … 2197 2207 rc = VINF_SUCCESS; 2198 2208 2209 #if defined(IEM_VERIFICATION_MODE) && !defined(IEM_VERIFICATION_MODE_NO_REM) 2210 /* 2211 * Record the write(s). 2212 */ 2213 PIEMVERIFYEVTREC pEvtRec = iemVerifyAllocRecord(pIemCpu); 2214 if (pEvtRec) 2215 { 2216 pEvtRec->enmEvent = IEMVERIFYEVENT_RAM_WRITE; 2217 pEvtRec->u.RamWrite.GCPhys = pIemCpu->aMemBbMappings[iMemMap].GCPhysFirst; 2218 pEvtRec->u.RamWrite.cb = pIemCpu->aMemBbMappings[iMemMap].cbFirst; 2219 memcpy(pEvtRec->u.RamWrite.ab, &pIemCpu->aBounceBuffers[iMemMap].ab[0], pIemCpu->aMemBbMappings[iMemMap].cbFirst); 2220 pEvtRec->pNext = *pIemCpu->ppIemEvtRecNext; 2221 *pIemCpu->ppIemEvtRecNext = pEvtRec; 2222 } 2223 if (pIemCpu->aMemBbMappings[iMemMap].cbSecond) 2224 { 2225 pEvtRec = iemVerifyAllocRecord(pIemCpu); 2226 if (pEvtRec) 2227 { 2228 pEvtRec->enmEvent = IEMVERIFYEVENT_RAM_WRITE; 2229 pEvtRec->u.RamWrite.GCPhys = pIemCpu->aMemBbMappings[iMemMap].GCPhysSecond; 2230 pEvtRec->u.RamWrite.cb = pIemCpu->aMemBbMappings[iMemMap].cbSecond; 2231 memcpy(pEvtRec->u.RamWrite.ab, 2232 &pIemCpu->aBounceBuffers[iMemMap].ab[pIemCpu->aMemBbMappings[iMemMap].cbFirst], 2233 pIemCpu->aMemBbMappings[iMemMap].cbSecond); 2234 pEvtRec->pNext = *pIemCpu->ppIemEvtRecNext; 2235 *pIemCpu->ppIemEvtRecNext = pEvtRec; 2236 } 2237 } 2238 #endif 2239 2199 2240 /* 2200 2241 * Free the mapping entry. … … 2255 2296 return rc; 2256 2297 } 2298 2299 #if defined(IEM_VERIFICATION_MODE) && !defined(IEM_VERIFICATION_MODE_NO_REM) 2300 /* 2301 * Record the reads. 2302 */ 2303 PIEMVERIFYEVTREC pEvtRec = iemVerifyAllocRecord(pIemCpu); 2304 if (pEvtRec) 2305 { 2306 pEvtRec->enmEvent = IEMVERIFYEVENT_RAM_READ; 2307 pEvtRec->u.RamRead.GCPhys = GCPhysFirst; 2308 pEvtRec->u.RamRead.cb = cbFirstPage; 2309 pEvtRec->pNext = *pIemCpu->ppIemEvtRecNext; 2310 *pIemCpu->ppIemEvtRecNext = pEvtRec; 2311 } 2312 pEvtRec = iemVerifyAllocRecord(pIemCpu); 2313 if (pEvtRec) 2314 { 2315 pEvtRec->enmEvent = IEMVERIFYEVENT_RAM_READ; 2316 pEvtRec->u.RamRead.GCPhys = GCPhysSecond; 2317 pEvtRec->u.RamRead.cb = cbSecondPage; 2318 pEvtRec->pNext = *pIemCpu->ppIemEvtRecNext; 2319 *pIemCpu->ppIemEvtRecNext = pEvtRec; 2320 } 2321 #endif 2257 2322 } 2258 2323 #ifdef VBOX_STRICT … … 2318 2383 return rc; 2319 2384 } 2385 2386 #if defined(IEM_VERIFICATION_MODE) && !defined(IEM_VERIFICATION_MODE_NO_REM) 2387 /* 2388 * Record the read. 2389 */ 2390 PIEMVERIFYEVTREC pEvtRec = iemVerifyAllocRecord(pIemCpu); 2391 if (pEvtRec) 2392 { 2393 pEvtRec->enmEvent = IEMVERIFYEVENT_RAM_READ; 2394 pEvtRec->u.RamRead.GCPhys = GCPhysFirst; 2395 pEvtRec->u.RamRead.cb = cbMem; 2396 pEvtRec->pNext = *pIemCpu->ppIemEvtRecNext; 2397 *pIemCpu->ppIemEvtRecNext = pEvtRec; 2398 } 2399 #endif 2320 2400 } 2321 2401 #ifdef VBOX_STRICT … … 2362 2442 * memory. 2363 2443 * @param cbMem The number of bytes to map. This is usually 1, 2364 * 2, 4, 6, 8, 12 or 16. When used by string2444 * 2, 4, 6, 8, 12, 16 or 32. When used by string 2365 2445 * operations it can be up to a page. 2366 2446 * @param iSegReg The index of the segment register to use for … … 2380 2460 * Check the input and figure out which mapping entry to use. 2381 2461 */ 2382 Assert(cbMem <= 16);2462 Assert(cbMem <= 32); 2383 2463 Assert(~(fAccess & ~(IEM_ACCESS_TYPE_MASK | IEM_ACCESS_WHAT_MASK))); 2384 2464 … … 3796 3876 * Commit the flags. 3797 3877 */ 3878 Assert(fEflNew & RT_BIT_32(1)); 3798 3879 pCtx->eflags.u = fEflNew; 3799 3880 iemRegAddToRip(pIemCpu, cbInstr); … … 4357 4438 | X86_EFL_RF /*| X86_EFL_VM*/ | X86_EFL_AC /*|X86_EFL_VIF*/ /*|X86_EFL_VIP*/ 4358 4439 | X86_EFL_ID; 4359 uNewFlags |= pCtx->eflags.u & (X86_EFL_VM | X86_EFL_VIF | X86_EFL_VIP );4440 uNewFlags |= pCtx->eflags.u & (X86_EFL_VM | X86_EFL_VIF | X86_EFL_VIP | X86_EFL_1); 4360 4441 } 4361 4442 else … … 4369 4450 uNewFlags &= X86_EFL_CF | X86_EFL_PF | X86_EFL_AF | X86_EFL_ZF | X86_EFL_SF 4370 4451 | X86_EFL_TF | X86_EFL_IF | X86_EFL_DF | X86_EFL_OF | X86_EFL_IOPL | X86_EFL_NT; 4371 uNewFlags |= pCtx->eflags.u & UINT16_C(0xffff0000);4452 uNewFlags |= pCtx->eflags.u & (UINT16_C(0xffff0000) | X86_EFL_1); 4372 4453 /** @todo The intel pseudo code does not indicate what happens to 4373 4454 * reserved flags. We just ignore them. */ … … 4413 4494 pCtx->csHid.u64Base = (uint32_t)uNewCs << 4; 4414 4495 /** @todo do we load attribs and limit as well? */ 4496 Assert(uNewFlags & X86_EFL_1); 4415 4497 pCtx->eflags.u = uNewFlags; 4416 4498 … … 4492 4574 4493 4575 *pSel = uSel; /* Not RPL, remember :-) */ 4494 if (pIemCpu->enmCpuMode == IEMMODE_64BIT) 4576 if ( pIemCpu->enmCpuMode == IEMMODE_64BIT 4577 && iSegReg != X86_SREG_FS 4578 && iSegReg != X86_SREG_GS) 4495 4579 { 4496 4580 /** @todo figure out what this actually does, it works. Needs … … 4634 4718 4635 4719 /** 4720 * Implements lgs, lfs, les, lds & lss. 4721 */ 4722 IEM_CIMPL_DEF_5(iemCImpl_load_SReg_Greg, 4723 uint16_t, uSel, 4724 uint64_t, offSeg, 4725 uint8_t, iSegReg, 4726 uint8_t, iGReg, 4727 IEMMODE, enmEffOpSize) 4728 { 4729 PCPUMCTX pCtx = pIemCpu->CTX_SUFF(pCtx); 4730 VBOXSTRICTRC rcStrict; 4731 4732 /* 4733 * Use iemCImpl_LoadSReg to do the tricky segment register loading. 4734 */ 4735 /** @todo verify and test that mov, pop and lXs works the segment 4736 * register loading in the exact same way. */ 4737 rcStrict = IEM_CIMPL_CALL_2(iemCImpl_LoadSReg, iSegReg, uSel); 4738 if (rcStrict == VINF_SUCCESS) 4739 { 4740 switch (enmEffOpSize) 4741 { 4742 case IEMMODE_16BIT: 4743 *(uint16_t *)iemGRegRef(pIemCpu, iGReg) = offSeg; 4744 break; 4745 case IEMMODE_32BIT: 4746 *(uint64_t *)iemGRegRef(pIemCpu, iGReg) = offSeg; 4747 break; 4748 case IEMMODE_64BIT: 4749 *(uint64_t *)iemGRegRef(pIemCpu, iGReg) = offSeg; 4750 break; 4751 IEM_NOT_REACHED_DEFAULT_CASE_RET(); 4752 } 4753 } 4754 4755 return rcStrict; 4756 } 4757 4758 4759 /** 4636 4760 * Implements 'pop SReg'. 4637 4761 * … … 4710 4834 if (rcStrict == VINF_SUCCESS) 4711 4835 { 4712 #if ndef IEM_VERIFICATION_MODE4836 #if !defined(IEM_VERIFICATION_MODE) || defined(IEM_VERIFICATION_MODE_NO_REM) 4713 4837 rcStrict = CPUMSetGuestGDTR(IEMCPU_TO_VMCPU(pIemCpu), GCPtrBase, cbLimit); 4714 4838 #else … … 4745 4869 if (rcStrict == VINF_SUCCESS) 4746 4870 { 4747 #if ndef IEM_VERIFICATION_MODE4871 #if !defined(IEM_VERIFICATION_MODE) || defined(IEM_VERIFICATION_MODE_NO_REM) 4748 4872 rcStrict = CPUMSetGuestIDTR(IEMCPU_TO_VMCPU(pIemCpu), GCPtrBase, cbLimit); 4749 4873 #else … … 4781 4905 case 4: crX = pCtx->cr4; break; 4782 4906 case 8: 4783 #if ndef IEM_VERIFICATION_MODE4907 #if !defined(IEM_VERIFICATION_MODE) || defined(IEM_VERIFICATION_MODE_NO_REM) 4784 4908 AssertFailedReturn(VERR_NOT_IMPLEMENTED); /** @todo implement CR8 reading and writing. */ 4785 4909 #else … … 4888 5012 * Change CR0. 4889 5013 */ 4890 #if ndef IEM_VERIFICATION_MODE5014 #if !defined(IEM_VERIFICATION_MODE) || defined(IEM_VERIFICATION_MODE_NO_REM) 4891 5015 rc = CPUMSetGuestCR0(pVCpu, NewCrX); 4892 5016 AssertRCSuccessReturn(rc, RT_FAILURE_NP(rc) ? rc : VERR_INTERNAL_ERROR_3); … … 4908 5032 NewEFER &= ~MSR_K6_EFER_LME; 4909 5033 4910 #if ndef IEM_VERIFICATION_MODE5034 #if !defined(IEM_VERIFICATION_MODE) || defined(IEM_VERIFICATION_MODE_NO_REM) 4911 5035 CPUMSetGuestEFER(pVCpu, NewEFER); 4912 5036 #else … … 4916 5040 } 4917 5041 4918 #if ndef IEM_VERIFICATION_MODE5042 #if !defined(IEM_VERIFICATION_MODE) || defined(IEM_VERIFICATION_MODE_NO_REM) 4919 5043 /* 4920 5044 * Inform PGM. … … 4978 5102 4979 5103 /* Make the change. */ 4980 #if ndef IEM_VERIFICATION_MODE5104 #if !defined(IEM_VERIFICATION_MODE) || defined(IEM_VERIFICATION_MODE_NO_REM) 4981 5105 rc = CPUMSetGuestCR3(pVCpu, NewCrX); 4982 5106 AssertRCSuccessReturn(rc, rc); … … 4985 5109 #endif 4986 5110 4987 #if ndef IEM_VERIFICATION_MODE5111 #if !defined(IEM_VERIFICATION_MODE) || defined(IEM_VERIFICATION_MODE_NO_REM) 4988 5112 /* Inform PGM. */ 4989 5113 if (pCtx->cr0 & X86_CR0_PG) … … 5037 5161 * Change it. 5038 5162 */ 5039 #if ndef IEM_VERIFICATION_MODE5163 #if !defined(IEM_VERIFICATION_MODE) || defined(IEM_VERIFICATION_MODE_NO_REM) 5040 5164 rc = CPUMSetGuestCR4(pVCpu, NewCrX); 5041 5165 AssertRCSuccessReturn(rc, rc); … … 5048 5172 * Notify SELM and PGM. 5049 5173 */ 5050 #if ndef IEM_VERIFICATION_MODE5174 #if !defined(IEM_VERIFICATION_MODE) || defined(IEM_VERIFICATION_MODE_NO_REM) 5051 5175 /* SELM - VME may change things wrt to the TSS shadowing. */ 5052 5176 if ((NewCrX ^ OldCrX) & X86_CR4_VME) … … 5073 5197 */ 5074 5198 case 8: 5075 #if ndef IEM_VERIFICATION_MODE5199 #if !defined(IEM_VERIFICATION_MODE) || defined(IEM_VERIFICATION_MODE_NO_REM) 5076 5200 AssertFailedReturn(VERR_NOT_IMPLEMENTED); /** @todo implement CR8 reading and writing. */ 5077 5201 #else … … 5114 5238 */ 5115 5239 uint32_t u32Value; 5116 #if ndef IEM_VERIFICATION_MODE5240 #if !defined(IEM_VERIFICATION_MODE) || defined(IEM_VERIFICATION_MODE_NO_REM) 5117 5241 rcStrict = IOMIOPortRead(IEMCPU_TO_VM(pIemCpu), u16Port, &u32Value, cbReg); 5118 5242 #else 5119 u32Value = 0xffffffff; 5120 rcStrict = VINF_SUCCESS; 5121 pIemCpu->cIOReads++; 5243 rcStrict = iemVerifyFakeIOPortRead(pIemCpu, u16Port, &u32Value, cbReg); 5122 5244 #endif 5123 5245 if (IOM_SUCCESS(rcStrict)) … … 5181 5303 default: AssertFailedReturn(VERR_INTERNAL_ERROR_3); 5182 5304 } 5183 # ifndef IEM_VERIFICATION_MODE5305 # if !defined(IEM_VERIFICATION_MODE) || defined(IEM_VERIFICATION_MODE_NO_REM) 5184 5306 VBOXSTRICTRC rc = IOMIOPortWrite(IEMCPU_TO_VM(pIemCpu), u16Port, u32Value, cbReg); 5185 #else 5186 VBOXSTRICTRC rc = VINF_SUCCESS; 5187 pIemCpu->cIOWrites++; 5188 #endif 5307 # else 5308 VBOXSTRICTRC rc = iemVerifyFakeIOPortWrite(pIemCpu, u16Port, u32Value, cbReg); 5309 # endif 5189 5310 if (IOM_SUCCESS(rc)) 5190 5311 { … … 5369 5490 uint32_t a_Name; \ 5370 5491 uint32_t *a_pName = &a_Name 5371 #define IEM_MC_COMMIT_EFLAGS(a_EFlags) (pIemCpu)->CTX_SUFF(pCtx)->eflags.u = (a_EFlags) 5492 #define IEM_MC_COMMIT_EFLAGS(a_EFlags) \ 5493 do { (pIemCpu)->CTX_SUFF(pCtx)->eflags.u = (a_EFlags); Assert((pIemCpu)->CTX_SUFF(pCtx)->eflags.u & X86_EFL_1); } while (0) 5372 5494 5373 5495 #define IEM_MC_ASSIGN(a_VarOrArg, a_CVariableOrConst) (a_VarOrArg) = (a_CVariableOrConst) … … 5565 5687 5566 5688 /** 5689 * Defers the rest of the instruction emulation to a C implementation routine 5690 * and returns, taking two arguments in addition to the standard ones. 5691 * 5692 * @param a_pfnCImpl The pointer to the C routine. 5693 * @param a0 The first extra argument. 5694 * @param a1 The second extra argument. 5695 * @param a2 The third extra argument. 5696 * @param a3 The fourth extra argument. 5697 * @param a4 The fifth extra argument. 5698 */ 5699 #define IEM_MC_CALL_CIMPL_5(a_pfnCImpl, a0, a1, a2, a3, a4) return (a_pfnCImpl)(pIemCpu, pIemCpu->offOpcode, a0, a1, a2, a3, a4) 5700 5701 /** 5567 5702 * Defers the entire instruction emulation to a C implementation routine and 5568 5703 * returns, only taking the standard parameters. … … 5629 5764 && !(pIemCpu->CTX_SUFF(pCtx)->eflags.u & a_fBit)) { 5630 5765 #define IEM_MC_IF_LOCAL_IS_Z(a_Local) if ((a_Local) == 0) { 5766 #define IEM_MC_IF_GREG_BIT_SET(a_iGReg, a_iBitNo) if (*(uint64_t *)iemGRegRef(pIemCpu, (a_iGReg)) & RT_BIT_64(a_iBitNo)) { 5631 5767 #define IEM_MC_ELSE() } else { 5632 5768 #define IEM_MC_ENDIF() } do {} while (0) … … 5998 6134 static void iemExecVerificationModeSetup(PIEMCPU pIemCpu) 5999 6135 { 6136 PCPUMCTX pOrgCtx = pIemCpu->CTX_SUFF(pCtx); 6137 6138 # ifndef IEM_VERIFICATION_MODE_NO_REM 6000 6139 /* 6001 6140 * Switch state. … … 6003 6142 static CPUMCTX s_DebugCtx; /* Ugly! */ 6004 6143 6005 PCPUMCTX pOrgCtx = pIemCpu->CTX_SUFF(pCtx);6006 6144 s_DebugCtx = *pOrgCtx; 6007 6145 pIemCpu->CTX_SUFF(pCtx) = &s_DebugCtx; 6146 # endif 6008 6147 6009 6148 /* … … 6027 6166 pIemCpu->fMulDivHack = false; 6028 6167 pIemCpu->fShlHack = false; 6029 } 6168 6169 /* 6170 * Free all verification records. 6171 */ 6172 PIEMVERIFYEVTREC pEvtRec = pIemCpu->pIemEvtRecHead; 6173 pIemCpu->pIemEvtRecHead = NULL; 6174 pIemCpu->ppIemEvtRecNext = &pIemCpu->pIemEvtRecHead; 6175 do 6176 { 6177 while (pEvtRec) 6178 { 6179 PIEMVERIFYEVTREC pNext = pEvtRec->pNext; 6180 pEvtRec->pNext = pIemCpu->pFreeEvtRec; 6181 pIemCpu->pFreeEvtRec = pEvtRec; 6182 pEvtRec = pNext; 6183 } 6184 pEvtRec = pIemCpu->pOtherEvtRecHead; 6185 pIemCpu->pOtherEvtRecHead = NULL; 6186 pIemCpu->ppOtherEvtRecNext = &pIemCpu->pOtherEvtRecHead; 6187 } while (pEvtRec); 6188 } 6189 6190 /** 6191 * Allocate an event record. 6192 * @returns Poitner to a record. 6193 */ 6194 static PIEMVERIFYEVTREC iemVerifyAllocRecord(PIEMCPU pIemCpu) 6195 { 6196 PIEMVERIFYEVTREC pEvtRec = pIemCpu->pFreeEvtRec; 6197 if (pEvtRec) 6198 pIemCpu->pFreeEvtRec = pEvtRec->pNext; 6199 else 6200 { 6201 if (!pIemCpu->ppIemEvtRecNext) 6202 return NULL; /* Too early (fake PCIBIOS), ignore notification. */ 6203 6204 pEvtRec = (PIEMVERIFYEVTREC)MMR3HeapAlloc(IEMCPU_TO_VM(pIemCpu), MM_TAG_EM /* lazy bird*/, sizeof(*pEvtRec)); 6205 if (!pEvtRec) 6206 return NULL; 6207 } 6208 pEvtRec->enmEvent = IEMVERIFYEVENT_INVALID; 6209 pEvtRec->pNext = NULL; 6210 return pEvtRec; 6211 } 6212 6213 6214 /** 6215 * IOMMMIORead notification. 6216 */ 6217 VMM_INT_DECL(void) IEMNotifyMMIORead(PVM pVM, RTGCPHYS GCPhys, size_t cbValue) 6218 { 6219 # ifndef IEM_VERIFICATION_MODE_NO_REM 6220 PVMCPU pVCpu = VMMGetCpu(pVM); 6221 if (!pVCpu) 6222 return; 6223 PIEMCPU pIemCpu = &pVCpu->iem.s; 6224 PIEMVERIFYEVTREC pEvtRec = iemVerifyAllocRecord(pIemCpu); 6225 if (!pEvtRec) 6226 return; 6227 pEvtRec->enmEvent = IEMVERIFYEVENT_RAM_READ; 6228 pEvtRec->u.RamRead.GCPhys = GCPhys; 6229 pEvtRec->u.RamRead.cb = cbValue; 6230 pEvtRec->pNext = *pIemCpu->ppOtherEvtRecNext; 6231 *pIemCpu->ppOtherEvtRecNext = pEvtRec; 6232 # endif 6233 } 6234 6235 6236 /** 6237 * IOMMMIOWrite notification. 6238 */ 6239 VMM_INT_DECL(void) IEMNotifyMMIOWrite(PVM pVM, RTGCPHYS GCPhys, uint32_t u32Value, size_t cbValue) 6240 { 6241 # ifndef IEM_VERIFICATION_MODE_NO_REM 6242 PVMCPU pVCpu = VMMGetCpu(pVM); 6243 if (!pVCpu) 6244 return; 6245 PIEMCPU pIemCpu = &pVCpu->iem.s; 6246 PIEMVERIFYEVTREC pEvtRec = iemVerifyAllocRecord(pIemCpu); 6247 if (!pEvtRec) 6248 return; 6249 pEvtRec->enmEvent = IEMVERIFYEVENT_RAM_WRITE; 6250 pEvtRec->u.RamWrite.GCPhys = GCPhys; 6251 pEvtRec->u.RamWrite.cb = cbValue; 6252 pEvtRec->u.RamWrite.ab[0] = RT_BYTE1(u32Value); 6253 pEvtRec->u.RamWrite.ab[1] = RT_BYTE2(u32Value); 6254 pEvtRec->u.RamWrite.ab[2] = RT_BYTE3(u32Value); 6255 pEvtRec->u.RamWrite.ab[3] = RT_BYTE4(u32Value); 6256 pEvtRec->pNext = *pIemCpu->ppOtherEvtRecNext; 6257 *pIemCpu->ppOtherEvtRecNext = pEvtRec; 6258 # endif 6259 } 6260 6261 6262 /** 6263 * IOMIOPortRead notification. 6264 */ 6265 VMM_INT_DECL(void) IEMNotifyIOPortRead(PVM pVM, RTIOPORT Port, size_t cbValue) 6266 { 6267 # ifndef IEM_VERIFICATION_MODE_NO_REM 6268 PVMCPU pVCpu = VMMGetCpu(pVM); 6269 if (!pVCpu) 6270 return; 6271 PIEMCPU pIemCpu = &pVCpu->iem.s; 6272 PIEMVERIFYEVTREC pEvtRec = iemVerifyAllocRecord(pIemCpu); 6273 if (!pEvtRec) 6274 return; 6275 pEvtRec->enmEvent = IEMVERIFYEVENT_IOPORT_READ; 6276 pEvtRec->u.IOPortRead.Port = Port; 6277 pEvtRec->u.IOPortRead.cbValue = cbValue; 6278 pEvtRec->pNext = *pIemCpu->ppOtherEvtRecNext; 6279 *pIemCpu->ppOtherEvtRecNext = pEvtRec; 6280 # endif 6281 } 6282 6283 /** 6284 * IOMIOPortWrite notification. 6285 */ 6286 VMM_INT_DECL(void) IEMNotifyIOPortWrite(PVM pVM, RTIOPORT Port, uint32_t u32Value, size_t cbValue) 6287 { 6288 # ifndef IEM_VERIFICATION_MODE_NO_REM 6289 PVMCPU pVCpu = VMMGetCpu(pVM); 6290 if (!pVCpu) 6291 return; 6292 PIEMCPU pIemCpu = &pVCpu->iem.s; 6293 PIEMVERIFYEVTREC pEvtRec = iemVerifyAllocRecord(pIemCpu); 6294 if (!pEvtRec) 6295 return; 6296 pEvtRec->enmEvent = IEMVERIFYEVENT_IOPORT_WRITE; 6297 pEvtRec->u.IOPortWrite.Port = Port; 6298 pEvtRec->u.IOPortWrite.cbValue = cbValue; 6299 pEvtRec->u.IOPortWrite.u32Value = u32Value; 6300 pEvtRec->pNext = *pIemCpu->ppOtherEvtRecNext; 6301 *pIemCpu->ppOtherEvtRecNext = pEvtRec; 6302 # endif 6303 } 6304 6305 6306 VMM_INT_DECL(void) IEMNotifyIOPortReadString(PVM pVM, RTIOPORT Port, RTGCPTR GCPtrDst, RTGCUINTREG cTransfers, size_t cbValue) 6307 { 6308 AssertFailed(); 6309 } 6310 6311 6312 VMM_INT_DECL(void) IEMNotifyIOPortWriteString(PVM pVM, RTIOPORT Port, RTGCPTR GCPtrSrc, RTGCUINTREG cTransfers, size_t cbValue) 6313 { 6314 AssertFailed(); 6315 } 6316 6317 6318 /** 6319 * Fakes and records an I/O port read. 6320 * 6321 * @returns VINF_SUCCESS. 6322 * @param pIemCpu The IEM per CPU data. 6323 * @param Port The I/O port. 6324 * @param pu32Value Where to store the fake value. 6325 * @param cbValue The size of the access. 6326 */ 6327 static VBOXSTRICTRC iemVerifyFakeIOPortRead(PIEMCPU pIemCpu, RTIOPORT Port, uint32_t *pu32Value, size_t cbValue) 6328 { 6329 PIEMVERIFYEVTREC pEvtRec = iemVerifyAllocRecord(pIemCpu); 6330 if (pEvtRec) 6331 { 6332 pEvtRec->enmEvent = IEMVERIFYEVENT_IOPORT_READ; 6333 pEvtRec->u.IOPortRead.Port = Port; 6334 pEvtRec->u.IOPortRead.cbValue = cbValue; 6335 pEvtRec->pNext = *pIemCpu->ppIemEvtRecNext; 6336 *pIemCpu->ppIemEvtRecNext = pEvtRec; 6337 } 6338 pIemCpu->cIOReads++; 6339 *pu32Value = 0xffffffff; 6340 return VINF_SUCCESS; 6341 } 6342 6343 6344 /** 6345 * Fakes and records an I/O port write. 6346 * 6347 * @returns VINF_SUCCESS. 6348 * @param pIemCpu The IEM per CPU data. 6349 * @param Port The I/O port. 6350 * @param u32Value The value being written. 6351 * @param cbValue The size of the access. 6352 */ 6353 static VBOXSTRICTRC iemVerifyFakeIOPortWrite(PIEMCPU pIemCpu, RTIOPORT Port, uint32_t u32Value, size_t cbValue) 6354 { 6355 PIEMVERIFYEVTREC pEvtRec = iemVerifyAllocRecord(pIemCpu); 6356 if (pEvtRec) 6357 { 6358 pEvtRec->enmEvent = IEMVERIFYEVENT_IOPORT_WRITE; 6359 pEvtRec->u.IOPortWrite.Port = Port; 6360 pEvtRec->u.IOPortWrite.cbValue = cbValue; 6361 pEvtRec->u.IOPortWrite.u32Value = u32Value; 6362 pEvtRec->pNext = *pIemCpu->ppIemEvtRecNext; 6363 *pIemCpu->ppIemEvtRecNext = pEvtRec; 6364 } 6365 pIemCpu->cIOWrites++; 6366 return VINF_SUCCESS; 6367 } 6368 6369 6370 /** 6371 * Used by iemVerifyAssertRecord and iemVerifyAssertRecords to add a record 6372 * dump to the assertion info. 6373 * 6374 * @param pEvtRec The record to dump. 6375 */ 6376 static void iemVerifyAssertAddRecordDump(PIEMVERIFYEVTREC pEvtRec) 6377 { 6378 switch (pEvtRec->enmEvent) 6379 { 6380 case IEMVERIFYEVENT_IOPORT_READ: 6381 RTAssertMsg2Add("I/O PORT READ from %#6x, %d bytes\n", 6382 pEvtRec->u.IOPortWrite.Port, 6383 pEvtRec->u.IOPortWrite.cbValue); 6384 break; 6385 case IEMVERIFYEVENT_IOPORT_WRITE: 6386 RTAssertMsg2Add("I/O PORT WRITE to %#6x, %d bytes, value %#x\n", 6387 pEvtRec->u.IOPortWrite.Port, 6388 pEvtRec->u.IOPortWrite.cbValue, 6389 pEvtRec->u.IOPortWrite.u32Value); 6390 break; 6391 case IEMVERIFYEVENT_RAM_READ: 6392 RTAssertMsg2Add("RAM READ at %RGp, %#4zx bytes\n", 6393 pEvtRec->u.RamRead.GCPhys, 6394 pEvtRec->u.RamRead.cb); 6395 break; 6396 case IEMVERIFYEVENT_RAM_WRITE: 6397 RTAssertMsg2Add("RAM WRITE at %RGp, %#4zx bytes: %.*RHxs\n", 6398 pEvtRec->u.RamWrite.GCPhys, 6399 pEvtRec->u.RamWrite.cb, 6400 (int)pEvtRec->u.RamWrite.cb, 6401 pEvtRec->u.RamWrite.ab); 6402 break; 6403 default: 6404 AssertMsgFailed(("Invalid event type %d\n", pEvtRec->enmEvent)); 6405 break; 6406 } 6407 } 6408 6409 6410 /** 6411 * Raises an assertion on the specified record, showing the given message with 6412 * a record dump attached. 6413 * 6414 * @param pEvtRec1 The first record. 6415 * @param pEvtRec2 The second record. 6416 * @param pszMsg The message explaining why we're asserting. 6417 */ 6418 static void iemVerifyAssertRecords(PIEMVERIFYEVTREC pEvtRec1, PIEMVERIFYEVTREC pEvtRec2, const char *pszMsg) 6419 { 6420 RTAssertMsg1(pszMsg, __LINE__, __FILE__, __PRETTY_FUNCTION__); 6421 iemVerifyAssertAddRecordDump(pEvtRec1); 6422 iemVerifyAssertAddRecordDump(pEvtRec2); 6423 RTAssertPanic(); 6424 } 6425 6426 6427 /** 6428 * Raises an assertion on the specified record, showing the given message with 6429 * a record dump attached. 6430 * 6431 * @param pEvtRec1 The first record. 6432 * @param pszMsg The message explaining why we're asserting. 6433 */ 6434 static void iemVerifyAssertRecord(PIEMVERIFYEVTREC pEvtRec, const char *pszMsg) 6435 { 6436 RTAssertMsg1(pszMsg, __LINE__, __FILE__, __PRETTY_FUNCTION__); 6437 iemVerifyAssertAddRecordDump(pEvtRec); 6438 RTAssertPanic(); 6439 } 6440 6030 6441 6031 6442 /** … … 6034 6445 static void iemExecVerificationModeCheck(PIEMCPU pIemCpu) 6035 6446 { 6447 # if defined(IEM_VERIFICATION_MODE) && !defined(IEM_VERIFICATION_MODE_NO_REM) 6448 /* 6449 * Switch back the state. 6450 */ 6036 6451 PCPUMCTX pOrgCtx = CPUMQueryGuestCtxPtr(IEMCPU_TO_VMCPU(pIemCpu)); 6037 6452 PCPUMCTX pDebugCtx = pIemCpu->CTX_SUFF(pCtx); … … 6039 6454 pIemCpu->CTX_SUFF(pCtx) = pOrgCtx; 6040 6455 6456 /* 6457 * Execute the instruction in REM. 6458 */ 6041 6459 int rc = REMR3EmulateInstruction(IEMCPU_TO_VM(pIemCpu), IEMCPU_TO_VMCPU(pIemCpu)); 6042 6460 AssertRC(rc); 6043 6461 #if 0 6462 if (pIemCpu->fPrefixes & (IEM_OP_PRF_REPNZ | IEM_OP_PRF_REPZ)) 6463 { 6464 while ( pOrgCtx->rip == pDebugCtx->rip - pIemCpu->offOpcode 6465 && pOrgCtx->rcx != pDebugCtx->rcx 6466 && pOrgCtx->rsi != pDebugCtx->rsi 6467 && pOrgCtx->rdi != pDebugCtx->rdi) 6468 { 6469 rc = REMR3EmulateInstruction(IEMCPU_TO_VM(pIemCpu), IEMCPU_TO_VMCPU(pIemCpu)); 6470 AssertRC(rc); 6471 } 6472 } 6473 #endif 6474 6475 /* 6476 * Compare the register states. 6477 */ 6478 unsigned cDiffs = 0; 6044 6479 if (memcmp(pOrgCtx, pDebugCtx, sizeof(*pDebugCtx))) 6045 6480 { 6046 6481 Log(("REM and IEM ends up with different registers!\n")); 6047 unsigned cDiffs = 0; 6048 6049 # define CHECK_FIELD(a_Field) \ 6482 6483 # define CHECK_FIELD(a_Field) \ 6050 6484 do \ 6051 6485 { \ … … 6064 6498 } while (0) 6065 6499 6066 # define CHECK_BIT_FIELD(a_Field) \6500 # define CHECK_BIT_FIELD(a_Field) \ 6067 6501 do \ 6068 6502 { \ … … 6087 6521 uint32_t fFlagsMask = UINT32_MAX; 6088 6522 if (pIemCpu->fMulDivHack) 6089 fFlagsMask &= ~(X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF );6523 fFlagsMask &= ~(X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF | X86_EFL_CF); 6090 6524 if (pIemCpu->fShlHack) 6091 6525 fFlagsMask &= ~(X86_EFL_OF); … … 6094 6528 RTAssertMsg2Weak(" rflags differs - iem=%08llx rem=%08llx\n", pDebugCtx->rflags.u, pOrgCtx->rflags.u); 6095 6529 CHECK_BIT_FIELD(rflags.Bits.u1CF); 6096 /*CHECK_BIT_FIELD(rflags.Bits.u1Reserved0); */ /** @todo why does REM set this? */6530 CHECK_BIT_FIELD(rflags.Bits.u1Reserved0); 6097 6531 CHECK_BIT_FIELD(rflags.Bits.u1PF); 6098 6532 CHECK_BIT_FIELD(rflags.Bits.u1Reserved1); … … 6190 6624 if (cDiffs != 0) 6191 6625 AssertFailed(); 6192 # undef CHECK_FIELD 6626 # undef CHECK_FIELD 6627 # undef CHECK_BIT_FIELD 6628 } 6629 6630 /* 6631 * If the register state compared fine, check the verification event 6632 * records. 6633 */ 6634 if (cDiffs == 0) 6635 { 6636 /* 6637 * Compare verficiation event records. 6638 * - I/O port accesses should be a 1:1 match. 6639 */ 6640 PIEMVERIFYEVTREC pIemRec = pIemCpu->pIemEvtRecHead; 6641 PIEMVERIFYEVTREC pOtherRec = pIemCpu->pOtherEvtRecHead; 6642 while (pIemRec && pOtherRec) 6643 { 6644 /* Since we might miss RAM writes and reads, ignore extra ones 6645 made by IEM. */ 6646 while ( IEMVERIFYEVENT_IS_RAM(pIemRec->enmEvent) 6647 && !IEMVERIFYEVENT_IS_RAM(pOtherRec->enmEvent) 6648 && pIemRec->pNext) 6649 pIemRec = pIemRec->pNext; 6650 6651 /* Do the compare. */ 6652 if (pIemRec->enmEvent != pOtherRec->enmEvent) 6653 { 6654 iemVerifyAssertRecords(pIemRec, pOtherRec, "Type mismatches"); 6655 break; 6656 } 6657 bool fEquals; 6658 switch (pIemRec->enmEvent) 6659 { 6660 case IEMVERIFYEVENT_IOPORT_READ: 6661 fEquals = pIemRec->u.IOPortRead.Port == pOtherRec->u.IOPortRead.Port 6662 && pIemRec->u.IOPortRead.cbValue == pOtherRec->u.IOPortRead.cbValue; 6663 break; 6664 case IEMVERIFYEVENT_IOPORT_WRITE: 6665 fEquals = pIemRec->u.IOPortWrite.Port == pOtherRec->u.IOPortWrite.Port 6666 && pIemRec->u.IOPortWrite.cbValue == pOtherRec->u.IOPortWrite.cbValue 6667 && pIemRec->u.IOPortWrite.u32Value == pOtherRec->u.IOPortWrite.u32Value; 6668 break; 6669 case IEMVERIFYEVENT_RAM_READ: 6670 fEquals = pIemRec->u.RamRead.GCPhys == pOtherRec->u.RamRead.GCPhys 6671 && pIemRec->u.RamRead.cb == pOtherRec->u.RamRead.cb; 6672 break; 6673 case IEMVERIFYEVENT_RAM_WRITE: 6674 fEquals = pIemRec->u.RamWrite.GCPhys == pOtherRec->u.RamWrite.GCPhys 6675 && pIemRec->u.RamWrite.cb == pOtherRec->u.RamWrite.cb 6676 && !memcmp(pIemRec->u.RamWrite.ab, pOtherRec->u.RamWrite.ab, pIemRec->u.RamWrite.cb); 6677 break; 6678 default: 6679 fEquals = false; 6680 break; 6681 } 6682 if (!fEquals) 6683 { 6684 iemVerifyAssertRecords(pIemRec, pOtherRec, "Mismatch"); 6685 break; 6686 } 6687 6688 /* advance */ 6689 pIemRec = pIemRec->pNext; 6690 pOtherRec = pOtherRec->pNext; 6691 } 6692 6693 /* Ignore extra writes and reads. */ 6694 while (pIemRec && IEMVERIFYEVENT_IS_RAM(pIemRec->enmEvent)) 6695 pIemRec = pIemRec->pNext; 6696 if (pIemRec != NULL) 6697 iemVerifyAssertRecord(pIemRec, "Extra IEM record!"); 6698 else if (pOtherRec != NULL) 6699 iemVerifyAssertRecord(pIemRec, "Extra Other record!"); 6193 6700 } 6194 6701 pIemCpu->CTX_SUFF(pCtx) = pOrgCtx; 6702 # endif 6195 6703 } 6196 6704 … … 6261 6769 pIemCpu->cInstructions++; 6262 6770 } 6771 EMSetInhibitInterruptsPC(pVCpu, UINT64_C(0x7777555533331111)); 6263 6772 } 6264 6773 -
trunk/src/VBox/VMM/VMMAll/IEMAllCImplStrInstr.cpp.h
r36768 r36794 297 297 298 298 299 /** 300 * Implements 'REP LODS'. 301 */ 302 IEM_CIMPL_DEF_1(RT_CONCAT4(iemCImpl_lods_,OP_rAX,_m,ADDR_SIZE), int8_t, iEffSeg) 303 { 304 PCPUMCTX pCtx = pIemCpu->CTX_SUFF(pCtx); 305 306 /* 307 * Setup. 308 */ 309 ADDR_TYPE uCounterReg = pCtx->ADDR_rCX; 310 if (uCounterReg == 0) 311 return VINF_SUCCESS; 312 313 PCCPUMSELREGHID pSrcHid = iemSRegGetHid(pIemCpu, iEffSeg); 314 VBOXSTRICTRC rcStrict = iemMemSegCheckReadAccessEx(pIemCpu, pSrcHid, iEffSeg); 315 if (rcStrict != VINF_SUCCESS) 316 return rcStrict; 317 318 int8_t const cbIncr = pCtx->eflags.Bits.u1DF ? -(OP_SIZE / 8) : (OP_SIZE / 8); 319 OP_TYPE uValueReg = pCtx->OP_rAX; 320 ADDR_TYPE uAddrReg = pCtx->ADDR_rSI; 321 322 /* 323 * The loop. 324 */ 325 do 326 { 327 /* 328 * Do segmentation and virtual page stuff. 329 */ 330 #if ADDR_SIZE != 64 331 ADDR2_TYPE uVirtAddr = (uint32_t)pSrcHid->u64Base + uAddrReg; 332 #else 333 uint64_t uVirtAddr = uAddrReg; 334 #endif 335 uint32_t cLeftPage = (PAGE_SIZE - (uVirtAddr & PAGE_OFFSET_MASK)) / (OP_SIZE / 8); 336 if (cLeftPage > uCounterReg) 337 cLeftPage = uCounterReg; 338 if ( cLeftPage > 0 /* can be null if unaligned, do one fallback round. */ 339 && cbIncr > 0 /** @todo Implement reverse direction string ops. */ 340 #if ADDR_SIZE != 64 341 && uAddrReg < pSrcHid->u32Limit 342 && uAddrReg + (cLeftPage * (OP_SIZE / 8)) <= pSrcHid->u32Limit 343 #endif 344 ) 345 { 346 RTGCPHYS GCPhysMem; 347 rcStrict = iemMemPageTranslateAndCheckAccess(pIemCpu, uVirtAddr, IEM_ACCESS_DATA_R, &GCPhysMem); 348 if (rcStrict != VINF_SUCCESS) 349 break; 350 351 /* 352 * If we can map the page without trouble, we can get away with 353 * just reading the last value on the page. 354 */ 355 OP_TYPE const *puMem; 356 rcStrict = iemMemPageMap(pIemCpu, GCPhysMem, IEM_ACCESS_DATA_R, (void **)&puMem); 357 if (rcStrict == VINF_SUCCESS) 358 { 359 /* Only get the last byte, the rest doesn't matter in direct access mode. */ 360 uValueReg = puMem[cLeftPage - 1]; 361 362 /* Update the regs. */ 363 uCounterReg -= cLeftPage; 364 uAddrReg += cLeftPage * cbIncr; 365 366 /* If unaligned, we drop thru and do the page crossing access 367 below. Otherwise, do the next page. */ 368 if (!(uVirtAddr & (OP_SIZE - 1))) 369 continue; 370 if (uCounterReg == 0) 371 break; 372 cLeftPage = 0; 373 } 374 } 375 376 /* 377 * Fallback - slow processing till the end of the current page. 378 * In the cross page boundrary case we will end up here with cLeftPage 379 * as 0, we execute one loop then. 380 */ 381 do 382 { 383 OP_TYPE uTmpValue; 384 rcStrict = RT_CONCAT(iemMemFetchDataU,OP_SIZE)(pIemCpu, &uTmpValue, iEffSeg, uAddrReg); 385 if (rcStrict != VINF_SUCCESS) 386 break; 387 uValueReg = uTmpValue; 388 uAddrReg += cbIncr; 389 uCounterReg--; 390 cLeftPage--; 391 } while ((int32_t)cLeftPage > 0); 392 if (rcStrict != VINF_SUCCESS) 393 break; 394 } while (uCounterReg != 0); 395 396 /* 397 * Update the registers. 398 */ 399 pCtx->ADDR_rCX = uCounterReg; 400 pCtx->ADDR_rDI = uAddrReg; 401 #if OP_SIZE == 32 402 pCtx->rax = uValueReg; 403 #else 404 pCtx->OP_rAX = uValueReg; 405 #endif 406 if (rcStrict == VINF_SUCCESS) 407 iemRegAddToRip(pIemCpu, cbInstr); 408 409 return rcStrict; 410 } 411 412 299 413 #if OP_SIZE != 64 300 414 … … 323 437 324 438 uint32_t u32Value; 439 # if !defined(IEM_VERIFICATION_MODE) || defined(IEM_VERIFICATION_MODE_NO_REM) 325 440 rcStrict = IOMIOPortRead(pVM, pCtx->dx, &u32Value, OP_SIZE / 8); 441 # else 442 iemVerifyFakeIOPortRead(pIemCpu, pCtx->dx, &u32Value, OP_SIZE / 8); 443 # endif 326 444 if (IOM_SUCCESS(rcStrict)) 327 445 { … … 344 462 return rcStrict; 345 463 } 464 346 465 347 466 /** … … 417 536 { 418 537 uint32_t u32Value; 538 # if !defined(IEM_VERIFICATION_MODE) || defined(IEM_VERIFICATION_MODE_NO_REM) 419 539 rcStrict = IOMIOPortRead(pVM, u16Port, &u32Value, OP_SIZE / 8); 540 # else 541 rcStrict = iemVerifyFakeIOPortRead(pIemCpu, u16Port, &u32Value, OP_SIZE / 8); 542 # endif 420 543 if (!IOM_SUCCESS(rcStrict)) 421 544 break; … … 461 584 462 585 uint32_t u32Value; 586 # if !defined(IEM_VERIFICATION_MODE) || defined(IEM_VERIFICATION_MODE_NO_REM) 463 587 rcStrict = IOMIOPortRead(pVM, u16Port, &u32Value, OP_SIZE / 8); 588 # else 589 rcStrict = iemVerifyFakeIOPortRead(pIemCpu, u16Port, &u32Value, OP_SIZE / 8); 590 # endif 464 591 if (!IOM_SUCCESS(rcStrict)) 465 592 break; … … 496 623 * Implements 'OUTS' (no rep) 497 624 */ 498 IEM_CIMPL_DEF_ 0(RT_CONCAT4(iemCImpl_outs_op,OP_SIZE,_addr,ADDR_SIZE))625 IEM_CIMPL_DEF_1(RT_CONCAT4(iemCImpl_outs_op,OP_SIZE,_addr,ADDR_SIZE), uint8_t, iEffSeg) 499 626 { 500 627 PVM pVM = IEMCPU_TO_VM(pIemCpu); … … 512 639 513 640 OP_TYPE uValue; 514 rcStrict = RT_CONCAT(iemMemFetchDataU,OP_SIZE)(pIemCpu, &uValue, X86_SREG_ES, pCtx->ADDR_rDI);641 rcStrict = RT_CONCAT(iemMemFetchDataU,OP_SIZE)(pIemCpu, &uValue, iEffSeg, pCtx->ADDR_rSI); 515 642 if (rcStrict == VINF_SUCCESS) 516 643 { 644 # if !defined(IEM_VERIFICATION_MODE) || defined(IEM_VERIFICATION_MODE_NO_REM) 517 645 rcStrict = IOMIOPortWrite(pVM, pCtx->dx, uValue, OP_SIZE / 8); 646 # else 647 rcStrict = iemVerifyFakeIOPortWrite(pIemCpu, pCtx->dx, uValue, OP_SIZE / 8); 648 # endif 518 649 if (IOM_SUCCESS(rcStrict)) 519 650 { 520 651 if (!pCtx->eflags.Bits.u1DF) 521 pCtx->ADDR_r DI += OP_SIZE / 8;652 pCtx->ADDR_rSI += OP_SIZE / 8; 522 653 else 523 pCtx->ADDR_r DI -= OP_SIZE / 8;654 pCtx->ADDR_rSI -= OP_SIZE / 8; 524 655 iemRegAddToRip(pIemCpu, cbInstr); 525 656 /** @todo massage IOM status codes. */ … … 529 660 } 530 661 662 531 663 /** 532 664 * Implements 'REP OUTS'. 533 665 */ 534 IEM_CIMPL_DEF_ 0(RT_CONCAT4(iemCImpl_rep_outs_op,OP_SIZE,_addr,ADDR_SIZE))666 IEM_CIMPL_DEF_1(RT_CONCAT4(iemCImpl_rep_outs_op,OP_SIZE,_addr,ADDR_SIZE), uint8_t, iEffSeg) 535 667 { 536 668 PVM pVM = IEMCPU_TO_VM(pIemCpu); … … 549 681 return VINF_SUCCESS; 550 682 551 rcStrict = iemMemSegCheckReadAccessEx(pIemCpu, &pCtx->esHid, X86_SREG_ES); 683 PCCPUMSELREGHID pHid = iemSRegGetHid(pIemCpu, iEffSeg); 684 rcStrict = iemMemSegCheckReadAccessEx(pIemCpu, pHid, iEffSeg); 552 685 if (rcStrict != VINF_SUCCESS) 553 686 return rcStrict; 554 687 555 688 int8_t const cbIncr = pCtx->eflags.Bits.u1DF ? -(OP_SIZE / 8) : (OP_SIZE / 8); 556 ADDR_TYPE uAddrReg = pCtx->ADDR_r DI;689 ADDR_TYPE uAddrReg = pCtx->ADDR_rSI; 557 690 558 691 /* … … 565 698 */ 566 699 #if ADDR_SIZE != 64 567 ADDR2_TYPE uVirtAddr = (uint32_t)p Ctx->esHid.u64Base + uAddrReg;700 ADDR2_TYPE uVirtAddr = (uint32_t)pHid->u64Base + uAddrReg; 568 701 #else 569 702 uint64_t uVirtAddr = uAddrReg; … … 575 708 && cbIncr > 0 /** @todo Implement reverse direction string ops. */ 576 709 #if ADDR_SIZE != 64 577 && uAddrReg < p Ctx->esHid.u32Limit578 && uAddrReg + (cLeftPage * (OP_SIZE / 8)) <= p Ctx->esHid.u32Limit710 && uAddrReg < pHid->u32Limit 711 && uAddrReg + (cLeftPage * (OP_SIZE / 8)) <= pHid->u32Limit 579 712 #endif 580 713 ) … … 601 734 { 602 735 uint32_t u32Value = *puMem++; 736 # if !defined(IEM_VERIFICATION_MODE) || defined(IEM_VERIFICATION_MODE_NO_REM) 603 737 rcStrict = IOMIOPortWrite(pVM, u16Port, u32Value, OP_SIZE / 8); 738 # else 739 rcStrict = iemVerifyFakeIOPortWrite(pIemCpu, u16Port, u32Value, OP_SIZE / 8); 740 # endif 604 741 if (!IOM_SUCCESS(rcStrict)) 605 742 break; … … 639 776 { 640 777 OP_TYPE uValue; 641 rcStrict = RT_CONCAT(iemMemFetchDataU,OP_SIZE)(pIemCpu, &uValue, X86_SREG_ES, uAddrReg); 642 if (rcStrict != VINF_SUCCESS) 643 break; 644 778 rcStrict = RT_CONCAT(iemMemFetchDataU,OP_SIZE)(pIemCpu, &uValue, iEffSeg, uAddrReg); 779 if (rcStrict != VINF_SUCCESS) 780 break; 781 782 # if !defined(IEM_VERIFICATION_MODE) || defined(IEM_VERIFICATION_MODE_NO_REM) 645 783 rcStrict = IOMIOPortWrite(pVM, u16Port, uValue, OP_SIZE / 8); 784 # else 785 rcStrict = iemVerifyFakeIOPortWrite(pIemCpu, u16Port, uValue, OP_SIZE / 8); 786 # endif 646 787 if (!IOM_SUCCESS(rcStrict)) 647 788 break; … … 664 805 */ 665 806 pCtx->ADDR_rCX = uCounterReg; 666 pCtx->ADDR_r DI = uAddrReg;807 pCtx->ADDR_rSI = uAddrReg; 667 808 if (rcStrict == VINF_SUCCESS) 668 809 iemRegAddToRip(pIemCpu, cbInstr); -
trunk/src/VBox/VMM/VMMAll/IEMAllInstructions.cpp.h
r36780 r36794 1710 1710 /** Opcode 0x0f 0xb1. */ 1711 1711 FNIEMOP_STUB(iemOp_cmpxchg_Ev_Gv); 1712 1713 1714 FNIEMOP_DEF_1(iemOpCommonLoadSRegAndGreg, uint8_t, iSegReg) 1715 { 1716 uint8_t bRm; IEM_OPCODE_GET_NEXT_BYTE(pIemCpu, &bRm); 1717 IEMOP_HLP_NO_LOCK_PREFIX(); /** @todo should probably not be raised until we've fetched all the opcode bytes? */ 1718 1719 /* The source cannot be a register. */ 1720 if ((bRm & X86_MODRM_MOD_MASK) == (3 << X86_MODRM_MOD_SHIFT)) 1721 return IEMOP_RAISE_INVALID_LOCK_PREFIX(); 1722 uint8_t const iGReg = ((bRm >> X86_MODRM_REG_SHIFT) & bRm & X86_MODRM_REG_SMASK) | pIemCpu->uRexReg; 1723 1724 switch (pIemCpu->enmEffOpSize) 1725 { 1726 case IEMMODE_16BIT: 1727 IEM_MC_BEGIN(5, 1); 1728 IEM_MC_ARG(uint16_t, uSel, 0); 1729 IEM_MC_ARG(uint16_t, offSeg, 1); 1730 IEM_MC_ARG_CONST(uint8_t, iSegRegArg,/*=*/iSegReg, 2); 1731 IEM_MC_ARG_CONST(uint8_t, iGRegArg, /*=*/iGReg, 3); 1732 IEM_MC_ARG_CONST(IEMMODE, enmEffOpSize,/*=*/pIemCpu->enmEffOpSize, 4); 1733 IEM_MC_LOCAL(RTGCPTR, GCPtrEff); 1734 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEff, bRm); 1735 IEM_MC_FETCH_MEM_U16(offSeg, pIemCpu->iEffSeg, GCPtrEff); 1736 IEM_MC_FETCH_MEM_U16(uSel, pIemCpu->iEffSeg, GCPtrEff + 2); 1737 IEM_MC_CALL_CIMPL_5(iemCImpl_load_SReg_Greg, uSel, offSeg, iSegRegArg, iGRegArg, enmEffOpSize); 1738 IEM_MC_END(); 1739 return VINF_SUCCESS; 1740 1741 case IEMMODE_32BIT: 1742 IEM_MC_BEGIN(5, 1); 1743 IEM_MC_ARG(uint16_t, uSel, 0); 1744 IEM_MC_ARG(uint32_t, offSeg, 1); 1745 IEM_MC_ARG_CONST(uint8_t, iSegRegArg,/*=*/iSegReg, 2); 1746 IEM_MC_ARG_CONST(uint8_t, iGRegArg, /*=*/iGReg, 3); 1747 IEM_MC_ARG_CONST(IEMMODE, enmEffOpSize,/*=*/pIemCpu->enmEffOpSize, 4); 1748 IEM_MC_LOCAL(RTGCPTR, GCPtrEff); 1749 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEff, bRm); 1750 IEM_MC_FETCH_MEM_U32(offSeg, pIemCpu->iEffSeg, GCPtrEff); 1751 IEM_MC_FETCH_MEM_U16(uSel, pIemCpu->iEffSeg, GCPtrEff + 4); 1752 IEM_MC_CALL_CIMPL_5(iemCImpl_load_SReg_Greg, uSel, offSeg, iSegRegArg, iGRegArg, enmEffOpSize); 1753 IEM_MC_END(); 1754 return VINF_SUCCESS; 1755 1756 case IEMMODE_64BIT: 1757 IEM_MC_BEGIN(5, 1); 1758 IEM_MC_ARG(uint16_t, uSel, 0); 1759 IEM_MC_ARG(uint64_t, offSeg, 1); 1760 IEM_MC_ARG_CONST(uint8_t, iSegRegArg,/*=*/iSegReg, 2); 1761 IEM_MC_ARG_CONST(uint8_t, iGRegArg, /*=*/iGReg, 3); 1762 IEM_MC_ARG_CONST(IEMMODE, enmEffOpSize,/*=*/pIemCpu->enmEffOpSize, 4); 1763 IEM_MC_LOCAL(RTGCPTR, GCPtrEff); 1764 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEff, bRm); 1765 IEM_MC_FETCH_MEM_U64(offSeg, pIemCpu->iEffSeg, GCPtrEff); 1766 IEM_MC_FETCH_MEM_U16(uSel, pIemCpu->iEffSeg, GCPtrEff + 8); 1767 IEM_MC_CALL_CIMPL_5(iemCImpl_load_SReg_Greg, uSel, offSeg, iSegRegArg, iGRegArg, enmEffOpSize); 1768 IEM_MC_END(); 1769 return VINF_SUCCESS; 1770 1771 IEM_NOT_REACHED_DEFAULT_CASE_RET(); 1772 } 1773 } 1774 1775 1712 1776 /** Opcode 0x0f 0xb2. */ 1713 FNIEMOP_STUB(iemOp_lss_Gv_Mp); 1777 FNIEMOP_DEF(iemOp_lss_Gv_Mp) 1778 { 1779 IEMOP_MNEMONIC("lss Gv,Mp"); 1780 return FNIEMOP_CALL_1(iemOpCommonLoadSRegAndGreg, X86_SREG_SS); 1781 } 1782 1783 1714 1784 /** Opcode 0x0f 0xb3. */ 1715 1785 FNIEMOP_STUB(iemOp_btr_Ev_Gv); 1786 1787 1716 1788 /** Opcode 0x0f 0xb4. */ 1717 FNIEMOP_STUB(iemOp_lfs_Gv_Mp); 1789 FNIEMOP_DEF(iemOp_lfs_Gv_Mp) 1790 { 1791 IEMOP_MNEMONIC("lfs Gv,Mp"); 1792 return FNIEMOP_CALL_1(iemOpCommonLoadSRegAndGreg, X86_SREG_FS); 1793 } 1794 1795 1718 1796 /** Opcode 0x0f 0xb5. */ 1719 FNIEMOP_STUB(iemOp_lgs_Gv_Mp); 1797 FNIEMOP_DEF(iemOp_lgs_Gv_Mp) 1798 { 1799 IEMOP_MNEMONIC("lgs Gv,Mp"); 1800 return FNIEMOP_CALL_1(iemOpCommonLoadSRegAndGreg, X86_SREG_GS); 1801 } 1720 1802 1721 1803 … … 3817 3899 switch (pIemCpu->enmEffAddrMode) 3818 3900 { 3819 case IEMMODE_16BIT: return IEM_MC_DEFER_TO_CIMPL_ 0(iemCImpl_rep_outs_op8_addr16);3820 case IEMMODE_32BIT: return IEM_MC_DEFER_TO_CIMPL_ 0(iemCImpl_rep_outs_op8_addr32);3821 case IEMMODE_64BIT: return IEM_MC_DEFER_TO_CIMPL_ 0(iemCImpl_rep_outs_op8_addr64);3901 case IEMMODE_16BIT: return IEM_MC_DEFER_TO_CIMPL_1(iemCImpl_rep_outs_op8_addr16, pIemCpu->iEffSeg); 3902 case IEMMODE_32BIT: return IEM_MC_DEFER_TO_CIMPL_1(iemCImpl_rep_outs_op8_addr32, pIemCpu->iEffSeg); 3903 case IEMMODE_64BIT: return IEM_MC_DEFER_TO_CIMPL_1(iemCImpl_rep_outs_op8_addr64, pIemCpu->iEffSeg); 3822 3904 IEM_NOT_REACHED_DEFAULT_CASE_RET(); 3823 3905 } … … 3828 3910 switch (pIemCpu->enmEffAddrMode) 3829 3911 { 3830 case IEMMODE_16BIT: return IEM_MC_DEFER_TO_CIMPL_ 0(iemCImpl_outs_op8_addr16);3831 case IEMMODE_32BIT: return IEM_MC_DEFER_TO_CIMPL_ 0(iemCImpl_outs_op8_addr32);3832 case IEMMODE_64BIT: return IEM_MC_DEFER_TO_CIMPL_ 0(iemCImpl_outs_op8_addr64);3912 case IEMMODE_16BIT: return IEM_MC_DEFER_TO_CIMPL_1(iemCImpl_outs_op8_addr16, pIemCpu->iEffSeg); 3913 case IEMMODE_32BIT: return IEM_MC_DEFER_TO_CIMPL_1(iemCImpl_outs_op8_addr32, pIemCpu->iEffSeg); 3914 case IEMMODE_64BIT: return IEM_MC_DEFER_TO_CIMPL_1(iemCImpl_outs_op8_addr64, pIemCpu->iEffSeg); 3833 3915 IEM_NOT_REACHED_DEFAULT_CASE_RET(); 3834 3916 } … … 3849 3931 switch (pIemCpu->enmEffAddrMode) 3850 3932 { 3851 case IEMMODE_16BIT: return IEM_MC_DEFER_TO_CIMPL_ 0(iemCImpl_rep_outs_op16_addr16);3852 case IEMMODE_32BIT: return IEM_MC_DEFER_TO_CIMPL_ 0(iemCImpl_rep_outs_op16_addr32);3853 case IEMMODE_64BIT: return IEM_MC_DEFER_TO_CIMPL_ 0(iemCImpl_rep_outs_op16_addr64);3933 case IEMMODE_16BIT: return IEM_MC_DEFER_TO_CIMPL_1(iemCImpl_rep_outs_op16_addr16, pIemCpu->iEffSeg); 3934 case IEMMODE_32BIT: return IEM_MC_DEFER_TO_CIMPL_1(iemCImpl_rep_outs_op16_addr32, pIemCpu->iEffSeg); 3935 case IEMMODE_64BIT: return IEM_MC_DEFER_TO_CIMPL_1(iemCImpl_rep_outs_op16_addr64, pIemCpu->iEffSeg); 3854 3936 IEM_NOT_REACHED_DEFAULT_CASE_RET(); 3855 3937 } … … 3859 3941 switch (pIemCpu->enmEffAddrMode) 3860 3942 { 3861 case IEMMODE_16BIT: return IEM_MC_DEFER_TO_CIMPL_ 0(iemCImpl_rep_outs_op32_addr16);3862 case IEMMODE_32BIT: return IEM_MC_DEFER_TO_CIMPL_ 0(iemCImpl_rep_outs_op32_addr32);3863 case IEMMODE_64BIT: return IEM_MC_DEFER_TO_CIMPL_ 0(iemCImpl_rep_outs_op32_addr64);3943 case IEMMODE_16BIT: return IEM_MC_DEFER_TO_CIMPL_1(iemCImpl_rep_outs_op32_addr16, pIemCpu->iEffSeg); 3944 case IEMMODE_32BIT: return IEM_MC_DEFER_TO_CIMPL_1(iemCImpl_rep_outs_op32_addr32, pIemCpu->iEffSeg); 3945 case IEMMODE_64BIT: return IEM_MC_DEFER_TO_CIMPL_1(iemCImpl_rep_outs_op32_addr64, pIemCpu->iEffSeg); 3864 3946 IEM_NOT_REACHED_DEFAULT_CASE_RET(); 3865 3947 } … … 3876 3958 switch (pIemCpu->enmEffAddrMode) 3877 3959 { 3878 case IEMMODE_16BIT: return IEM_MC_DEFER_TO_CIMPL_ 0(iemCImpl_outs_op16_addr16);3879 case IEMMODE_32BIT: return IEM_MC_DEFER_TO_CIMPL_ 0(iemCImpl_outs_op16_addr32);3880 case IEMMODE_64BIT: return IEM_MC_DEFER_TO_CIMPL_ 0(iemCImpl_outs_op16_addr64);3960 case IEMMODE_16BIT: return IEM_MC_DEFER_TO_CIMPL_1(iemCImpl_outs_op16_addr16, pIemCpu->iEffSeg); 3961 case IEMMODE_32BIT: return IEM_MC_DEFER_TO_CIMPL_1(iemCImpl_outs_op16_addr32, pIemCpu->iEffSeg); 3962 case IEMMODE_64BIT: return IEM_MC_DEFER_TO_CIMPL_1(iemCImpl_outs_op16_addr64, pIemCpu->iEffSeg); 3881 3963 IEM_NOT_REACHED_DEFAULT_CASE_RET(); 3882 3964 } … … 3886 3968 switch (pIemCpu->enmEffAddrMode) 3887 3969 { 3888 case IEMMODE_16BIT: return IEM_MC_DEFER_TO_CIMPL_ 0(iemCImpl_outs_op32_addr16);3889 case IEMMODE_32BIT: return IEM_MC_DEFER_TO_CIMPL_ 0(iemCImpl_outs_op32_addr32);3890 case IEMMODE_64BIT: return IEM_MC_DEFER_TO_CIMPL_ 0(iemCImpl_outs_op32_addr64);3970 case IEMMODE_16BIT: return IEM_MC_DEFER_TO_CIMPL_1(iemCImpl_outs_op32_addr16, pIemCpu->iEffSeg); 3971 case IEMMODE_32BIT: return IEM_MC_DEFER_TO_CIMPL_1(iemCImpl_outs_op32_addr32, pIemCpu->iEffSeg); 3972 case IEMMODE_64BIT: return IEM_MC_DEFER_TO_CIMPL_1(iemCImpl_outs_op32_addr64, pIemCpu->iEffSeg); 3891 3973 IEM_NOT_REACHED_DEFAULT_CASE_RET(); 3892 3974 } … … 5194 5276 /** Opcode 0x98. */ 5195 5277 FNIEMOP_STUB(iemOp_cbw); 5278 5279 5196 5280 /** Opcode 0x99. */ 5197 FNIEMOP_STUB(iemOp_cwd); 5281 FNIEMOP_DEF(iemOp_cwd) 5282 { 5283 IEMOP_HLP_NO_LOCK_PREFIX(); 5284 switch (pIemCpu->enmEffOpSize) 5285 { 5286 case IEMMODE_16BIT: 5287 IEMOP_MNEMONIC("cwd"); 5288 IEM_MC_BEGIN(0, 1); 5289 IEM_MC_IF_GREG_BIT_SET(X86_GREG_xAX, 15) { 5290 IEM_MC_STORE_GREG_U16(X86_GREG_xDX, UINT16_C(0xffff)); 5291 } IEM_MC_ELSE() { 5292 IEM_MC_STORE_GREG_U16(X86_GREG_xDX, 0); 5293 } IEM_MC_ENDIF(); 5294 IEM_MC_ADVANCE_RIP(); 5295 IEM_MC_END(); 5296 return VINF_SUCCESS; 5297 5298 case IEMMODE_32BIT: 5299 IEMOP_MNEMONIC("cwq"); 5300 IEM_MC_BEGIN(0, 1); 5301 IEM_MC_IF_GREG_BIT_SET(X86_GREG_xAX, 31) { 5302 IEM_MC_STORE_GREG_U32(X86_GREG_xDX, UINT32_C(0xffffffff)); 5303 } IEM_MC_ELSE() { 5304 IEM_MC_STORE_GREG_U32(X86_GREG_xDX, 0); 5305 } IEM_MC_ENDIF(); 5306 IEM_MC_ADVANCE_RIP(); 5307 IEM_MC_END(); 5308 return VINF_SUCCESS; 5309 5310 case IEMMODE_64BIT: 5311 IEMOP_MNEMONIC("cqo"); 5312 IEM_MC_BEGIN(0, 1); 5313 IEM_MC_IF_GREG_BIT_SET(X86_GREG_xAX, 63) { 5314 IEM_MC_STORE_GREG_U64(X86_GREG_xDX, UINT64_C(0xffffffffffffffff)); 5315 } IEM_MC_ELSE() { 5316 IEM_MC_STORE_GREG_U64(X86_GREG_xDX, 0); 5317 } IEM_MC_ENDIF(); 5318 IEM_MC_ADVANCE_RIP(); 5319 IEM_MC_END(); 5320 return VINF_SUCCESS; 5321 5322 IEM_NOT_REACHED_DEFAULT_CASE_RET(); 5323 } 5324 } 5325 5326 5198 5327 /** Opcode 0x9a. */ 5199 5328 FNIEMOP_STUB(iemOp_call_Ap); … … 5689 5818 #undef IEM_STOS_CASE 5690 5819 5820 /** Macro used by iemOp_lodsb_AL_Xb and iemOp_lodswd_eAX_Xv */ 5821 #define IEM_LODS_CASE(ValBits, AddrBits) \ 5822 IEM_MC_BEGIN(0, 2); \ 5823 IEM_MC_LOCAL(uint##ValBits##_t, uValue); \ 5824 IEM_MC_LOCAL(uint##AddrBits##_t, uAddr); \ 5825 IEM_MC_FETCH_GREG_U##AddrBits(uAddr, X86_GREG_xSI); \ 5826 IEM_MC_FETCH_MEM_U##ValBits(uValue, pIemCpu->iEffSeg, uAddr); \ 5827 IEM_MC_STORE_GREG_U##ValBits(X86_GREG_xAX, uValue); \ 5828 IEM_MC_IF_EFL_BIT_SET(X86_EFL_DF) { \ 5829 IEM_MC_SUB_GREG_U##AddrBits(X86_GREG_xSI, ValBits / 8); \ 5830 } IEM_MC_ELSE() { \ 5831 IEM_MC_ADD_GREG_U##AddrBits(X86_GREG_xSI, ValBits / 8); \ 5832 } IEM_MC_ENDIF(); \ 5833 IEM_MC_ADVANCE_RIP(); \ 5834 IEM_MC_END(); 5835 5691 5836 /** Opcode 0xac. */ 5692 FNIEMOP_STUB(iemOp_lodsb_AL_Xb); 5837 FNIEMOP_DEF(iemOp_lodsb_AL_Xb) 5838 { 5839 IEMOP_HLP_NO_LOCK_PREFIX(); 5840 5841 /* 5842 * Use the C implementation if a repeate prefix is encountered. 5843 */ 5844 if (pIemCpu->fPrefixes & (IEM_OP_PRF_REPNZ | IEM_OP_PRF_REPZ)) 5845 { 5846 IEMOP_MNEMONIC("rep lodsb al,Xb"); 5847 switch (pIemCpu->enmEffAddrMode) 5848 { 5849 case IEMMODE_16BIT: return IEM_MC_DEFER_TO_CIMPL_1(iemCImpl_lods_al_m16, pIemCpu->iEffSeg); 5850 case IEMMODE_32BIT: return IEM_MC_DEFER_TO_CIMPL_1(iemCImpl_lods_al_m32, pIemCpu->iEffSeg); 5851 case IEMMODE_64BIT: return IEM_MC_DEFER_TO_CIMPL_1(iemCImpl_lods_al_m64, pIemCpu->iEffSeg); 5852 IEM_NOT_REACHED_DEFAULT_CASE_RET(); 5853 } 5854 } 5855 IEMOP_MNEMONIC("lodsb al,Xb"); 5856 5857 /* 5858 * Sharing case implementation with stos[wdq] below. 5859 */ 5860 switch (pIemCpu->enmEffAddrMode) 5861 { 5862 case IEMMODE_16BIT: IEM_LODS_CASE(8, 16); break; 5863 case IEMMODE_32BIT: IEM_LODS_CASE(8, 32); break; 5864 case IEMMODE_64BIT: IEM_LODS_CASE(8, 64); break; 5865 IEM_NOT_REACHED_DEFAULT_CASE_RET(); 5866 } 5867 return VINF_SUCCESS; 5868 } 5869 5870 5693 5871 /** Opcode 0xad. */ 5694 FNIEMOP_STUB(iemOp_lodswd_eAX_Xv); 5872 FNIEMOP_DEF(iemOp_lodswd_eAX_Xv) 5873 { 5874 IEMOP_HLP_NO_LOCK_PREFIX(); 5875 5876 /* 5877 * Use the C implementation if a repeate prefix is encountered. 5878 */ 5879 if (pIemCpu->fPrefixes & (IEM_OP_PRF_REPNZ | IEM_OP_PRF_REPZ)) 5880 { 5881 IEMOP_MNEMONIC("rep lods rAX,Xv"); 5882 switch (pIemCpu->enmEffOpSize) 5883 { 5884 case IEMMODE_16BIT: 5885 switch (pIemCpu->enmEffAddrMode) 5886 { 5887 case IEMMODE_16BIT: return IEM_MC_DEFER_TO_CIMPL_1(iemCImpl_lods_ax_m16, pIemCpu->iEffSeg); 5888 case IEMMODE_32BIT: return IEM_MC_DEFER_TO_CIMPL_1(iemCImpl_lods_ax_m32, pIemCpu->iEffSeg); 5889 case IEMMODE_64BIT: return IEM_MC_DEFER_TO_CIMPL_1(iemCImpl_lods_ax_m64, pIemCpu->iEffSeg); 5890 IEM_NOT_REACHED_DEFAULT_CASE_RET(); 5891 } 5892 break; 5893 case IEMMODE_32BIT: 5894 switch (pIemCpu->enmEffAddrMode) 5895 { 5896 case IEMMODE_16BIT: return IEM_MC_DEFER_TO_CIMPL_1(iemCImpl_lods_eax_m16, pIemCpu->iEffSeg); 5897 case IEMMODE_32BIT: return IEM_MC_DEFER_TO_CIMPL_1(iemCImpl_lods_eax_m32, pIemCpu->iEffSeg); 5898 case IEMMODE_64BIT: return IEM_MC_DEFER_TO_CIMPL_1(iemCImpl_lods_eax_m64, pIemCpu->iEffSeg); 5899 IEM_NOT_REACHED_DEFAULT_CASE_RET(); 5900 } 5901 case IEMMODE_64BIT: 5902 switch (pIemCpu->enmEffAddrMode) 5903 { 5904 case IEMMODE_16BIT: AssertFailedReturn(VERR_INTERNAL_ERROR_3); 5905 case IEMMODE_32BIT: return IEM_MC_DEFER_TO_CIMPL_1(iemCImpl_lods_rax_m32, pIemCpu->iEffSeg); 5906 case IEMMODE_64BIT: return IEM_MC_DEFER_TO_CIMPL_1(iemCImpl_lods_rax_m64, pIemCpu->iEffSeg); 5907 IEM_NOT_REACHED_DEFAULT_CASE_RET(); 5908 } 5909 IEM_NOT_REACHED_DEFAULT_CASE_RET(); 5910 } 5911 } 5912 IEMOP_MNEMONIC("lods rAX,Xv"); 5913 5914 /* 5915 * Annoying double switch here. 5916 * Using ugly macro for implementing the cases, sharing it with lodsb. 5917 */ 5918 switch (pIemCpu->enmEffOpSize) 5919 { 5920 case IEMMODE_16BIT: 5921 switch (pIemCpu->enmEffAddrMode) 5922 { 5923 case IEMMODE_16BIT: IEM_LODS_CASE(16, 16); break; 5924 case IEMMODE_32BIT: IEM_LODS_CASE(16, 32); break; 5925 case IEMMODE_64BIT: IEM_LODS_CASE(16, 64); break; 5926 IEM_NOT_REACHED_DEFAULT_CASE_RET(); 5927 } 5928 break; 5929 5930 case IEMMODE_32BIT: 5931 switch (pIemCpu->enmEffAddrMode) 5932 { 5933 case IEMMODE_16BIT: IEM_LODS_CASE(32, 16); break; 5934 case IEMMODE_32BIT: IEM_LODS_CASE(32, 32); break; 5935 case IEMMODE_64BIT: IEM_LODS_CASE(32, 64); break; 5936 IEM_NOT_REACHED_DEFAULT_CASE_RET(); 5937 } 5938 break; 5939 5940 case IEMMODE_64BIT: 5941 switch (pIemCpu->enmEffAddrMode) 5942 { 5943 case IEMMODE_16BIT: AssertFailedReturn(VERR_INTERNAL_ERROR_4); /* cannot be encoded */ break; 5944 case IEMMODE_32BIT: IEM_LODS_CASE(64, 32); break; 5945 case IEMMODE_64BIT: IEM_LODS_CASE(64, 64); break; 5946 IEM_NOT_REACHED_DEFAULT_CASE_RET(); 5947 } 5948 break; 5949 IEM_NOT_REACHED_DEFAULT_CASE_RET(); 5950 } 5951 return VINF_SUCCESS; 5952 } 5953 5954 #undef IEM_LODS_CASE 5955 5695 5956 /** Opcode 0xae. */ 5696 5957 FNIEMOP_STUB(iemOp_scasb_AL_Xb); … … 6117 6378 6118 6379 /** Opcode 0xc4. */ 6119 FNIEMOP_STUB(iemOp_les_Gv_Mp); 6380 FNIEMOP_DEF(iemOp_les_Gv_Mp) 6381 { 6382 IEMOP_MNEMONIC("les Gv,Mp"); 6383 return FNIEMOP_CALL_1(iemOpCommonLoadSRegAndGreg, X86_SREG_ES); 6384 } 6385 6386 6120 6387 /** Opcode 0xc5. */ 6121 FNIEMOP_STUB(iemOp_lds_Gv_Mp); 6388 FNIEMOP_DEF(iemOp_lds_Gv_Mp) 6389 { 6390 IEMOP_MNEMONIC("lds Gv,Mp"); 6391 return FNIEMOP_CALL_1(iemOpCommonLoadSRegAndGreg, X86_SREG_DS); 6392 } 6122 6393 6123 6394 … … 6874 7145 IEM_MC_BEGIN(0,0); 6875 7146 IEM_MC_IF_CX_IS_NZ() { 7147 IEM_MC_ADVANCE_RIP(); 7148 } IEM_MC_ELSE() { 6876 7149 IEM_MC_REL_JMP_S8(i8Imm); 6877 } IEM_MC_ELSE() {6878 IEM_MC_ADVANCE_RIP();6879 7150 } IEM_MC_ENDIF(); 6880 7151 IEM_MC_END(); … … 6884 7155 IEM_MC_BEGIN(0,0); 6885 7156 IEM_MC_IF_ECX_IS_NZ() { 7157 IEM_MC_ADVANCE_RIP(); 7158 } IEM_MC_ELSE() { 6886 7159 IEM_MC_REL_JMP_S8(i8Imm); 6887 } IEM_MC_ELSE() {6888 IEM_MC_ADVANCE_RIP();6889 7160 } IEM_MC_ENDIF(); 6890 7161 IEM_MC_END(); … … 6894 7165 IEM_MC_BEGIN(0,0); 6895 7166 IEM_MC_IF_RCX_IS_NZ() { 7167 IEM_MC_ADVANCE_RIP(); 7168 } IEM_MC_ELSE() { 6896 7169 IEM_MC_REL_JMP_S8(i8Imm); 6897 } IEM_MC_ELSE() {6898 IEM_MC_ADVANCE_RIP();6899 7170 } IEM_MC_ENDIF(); 6900 7171 IEM_MC_END(); -
trunk/src/VBox/VMM/VMMAll/IOMAll.cpp
r35346 r36794 22 22 #include <VBox/vmm/iom.h> 23 23 #include <VBox/vmm/mm.h> 24 #if defined(IEM_VERIFICATION_MODE) && defined(IN_RING3) 25 # include <VBox/vmm/iem.h> 26 #endif 24 27 #include <VBox/param.h> 25 28 #include "IOMInternal.h" … … 265 268 #endif 266 269 AssertRC(rc2); 270 #if defined(IEM_VERIFICATION_MODE) && defined(IN_RING3) 271 IEMNotifyIOPortRead(pVM, Port, cbValue); 272 #endif 267 273 268 274 #ifdef VBOX_WITH_STATISTICS … … 455 461 #endif 456 462 AssertRC(rc2); 463 #if defined(IEM_VERIFICATION_MODE) && defined(IN_RING3) 464 IEMNotifyIOPortReadString(pVM, Port, *pGCPtrDst, *pcTransfers, cb); 465 #endif 457 466 458 467 #ifdef LOG_ENABLED … … 623 632 #endif 624 633 AssertRC(rc2); 634 #if defined(IEM_VERIFICATION_MODE) && defined(IN_RING3) 635 IEMNotifyIOPortWrite(pVM, Port, u32Value, cbValue); 636 #endif 625 637 626 638 /** @todo bird: When I get time, I'll remove the RC/R0 trees and link the RC/R0 … … 789 801 #endif 790 802 AssertRC(rc2); 803 #if defined(IEM_VERIFICATION_MODE) && defined(IN_RING3) 804 IEMNotifyIOPortWriteString(pVM, Port, *pGCPtrSrc, *pcTransfers, cb); 805 #endif 791 806 792 807 #ifdef LOG_ENABLED -
trunk/src/VBox/VMM/VMMAll/IOMAllMMIO.cpp
r35346 r36794 29 29 #include <VBox/vmm/pgm.h> 30 30 #include <VBox/vmm/trpm.h> 31 #if defined(IEM_VERIFICATION_MODE) && defined(IN_RING3) 32 # include <VBox/vmm/iem.h> 33 #endif 31 34 #include "IOMInternal.h" 32 35 #include <VBox/vmm/vm.h> … … 1374 1377 #endif 1375 1378 AssertRC(rc); 1379 #if defined(IEM_VERIFICATION_MODE) && defined(IN_RING3) 1380 IEMNotifyMMIORead(pVM, GCPhys, cbValue); 1381 #endif 1376 1382 1377 1383 /* … … 1500 1506 #endif 1501 1507 AssertRC(rc); 1508 #if defined(IEM_VERIFICATION_MODE) && defined(IN_RING3) 1509 IEMNotifyMMIOWrite(pVM, GCPhys, u32Value, cbValue); 1510 #endif 1502 1511 1503 1512 /* -
trunk/src/VBox/VMM/include/IEMInternal.h
r36768 r36794 60 60 AssertCompileSize(IEMMODEX, 4); 61 61 62 63 #ifdef IEM_VERIFICATION_MODE 64 65 /** 66 * Verification event type. 67 */ 68 typedef enum IEMVERIFYEVENT 69 { 70 IEMVERIFYEVENT_INVALID = 0, 71 IEMVERIFYEVENT_IOPORT_READ, 72 IEMVERIFYEVENT_IOPORT_WRITE, 73 IEMVERIFYEVENT_RAM_WRITE, 74 IEMVERIFYEVENT_RAM_READ 75 } IEMVERIFYEVENT; 76 77 /** Checks if the event type is a RAM read or write. */ 78 # define IEMVERIFYEVENT_IS_RAM(a_enmType) ((a_enmType) == IEMVERIFYEVENT_RAM_WRITE || (a_enmType) == IEMVERIFYEVENT_RAM_READ) 79 80 /** 81 * Verification event record. 82 */ 83 typedef struct IEMVERIFYEVTREC 84 { 85 /** Pointer to the next record in the list. */ 86 struct IEMVERIFYEVTREC *pNext; 87 /** The event type. */ 88 IEMVERIFYEVENT enmEvent; 89 /** The event data. */ 90 union 91 { 92 /** IEMVERIFYEVENT_IOPORT_READ */ 93 struct 94 { 95 RTIOPORT Port; 96 uint32_t cbValue; 97 } IOPortRead; 98 99 /** IEMVERIFYEVENT_IOPORT_WRITE */ 100 struct 101 { 102 RTIOPORT Port; 103 uint32_t cbValue; 104 uint32_t u32Value; 105 } IOPortWrite; 106 107 /** IEMVERIFYEVENT_RAM_READ */ 108 struct 109 { 110 RTGCPHYS GCPhys; 111 uint32_t cb; 112 } RamRead; 113 114 /** IEMVERIFYEVENT_RAM_WRITE */ 115 struct 116 { 117 RTGCPHYS GCPhys; 118 uint32_t cb; 119 uint8_t ab[32]; 120 } RamWrite; 121 } u; 122 } IEMVERIFYEVTREC; 123 /** Pointer to an IEM event verification records. */ 124 typedef IEMVERIFYEVTREC *PIEMVERIFYEVTREC; 125 126 #endif /* IEM_VERIFICATION_MODE */ 62 127 63 128 … … 188 253 struct 189 254 { 190 uint8_t ab[ /*PAGE_SIZE*/16];255 uint8_t ab[64]; 191 256 } aBounceBuffers[3]; 192 257 258 #ifdef IEM_VERIFICATION_MODE 259 /** The event verification records for what IEM did (LIFO). */ 260 R3PTRTYPE(PIEMVERIFYEVTREC) pIemEvtRecHead; 261 /** Insertion point for pIemEvtRecHead. */ 262 R3PTRTYPE(PIEMVERIFYEVTREC *) ppIemEvtRecNext; 263 /** The event verification records for what the other party did (FIFO). */ 264 R3PTRTYPE(PIEMVERIFYEVTREC) pOtherEvtRecHead; 265 /** Insertion point for pOtherEvtRecHead. */ 266 R3PTRTYPE(PIEMVERIFYEVTREC *) ppOtherEvtRecNext; 267 /** List of free event records. */ 268 R3PTRTYPE(PIEMVERIFYEVTREC) pFreeEvtRec; 269 #endif 193 270 } IEMCPU; 194 271 /** Pointer to the per-CPU IEM state. */ … … 630 707 * @param a2 The name of the 3rd argument. 631 708 */ 632 # define IEM_CIMPL_CALL_3(a_fn, a0, a1, a2) a_fn(pIemCpu, cbInstr, (a0), (a1)) 709 # define IEM_CIMPL_CALL_3(a_fn, a0, a1, a2) a_fn(pIemCpu, cbInstr, (a0), (a1), (a2)) 710 711 712 /** 713 * For typedef'ing or declaring a C instruction implementation function taking 714 * four extra arguments. 715 * 716 * @param a_Name The name of the type. 717 * @param a_Type0 The type of the 1st argument 718 * @param a_Arg0 The name of the 1st argument. 719 * @param a_Type1 The type of the 2nd argument. 720 * @param a_Arg1 The name of the 2nd argument. 721 * @param a_Type2 The type of the 3rd argument. 722 * @param a_Arg2 The name of the 3rd argument. 723 * @param a_Type3 The type of the 4th argument. 724 * @param a_Arg3 The name of the 4th argument. 725 */ 726 # define IEM_CIMPL_DECL_TYPE_4(a_Name, a_Type0, a_Arg0, a_Type1, a_Arg1, a_Type2, a_Arg2, a_Type3, a_Arg3) \ 727 IEM_DECL_IMPL_TYPE(VBOXSTRICTRC, a_Name, (PIEMCPU pIemCpu, uint8_t cbInstr, a_Type0 a_Arg0, a_Type1 a_Arg1, a_Type2 a_Arg2, a_Type3 a_Arg3)) 728 /** 729 * For defining a C instruction implementation function taking four extra 730 * arguments. 731 * 732 * @param a_Name The name of the function. 733 * @param a_Type0 The type of the 1st argument 734 * @param a_Arg0 The name of the 1st argument. 735 * @param a_Type1 The type of the 2nd argument. 736 * @param a_Arg1 The name of the 2nd argument. 737 * @param a_Type2 The type of the 3rd argument. 738 * @param a_Arg2 The name of the 3rd argument. 739 * @param a_Type3 The type of the 4th argument. 740 * @param a_Arg3 The name of the 4th argument. 741 */ 742 # define IEM_CIMPL_DEF_4(a_Name, a_Type0, a_Arg0, a_Type1, a_Arg1, a_Type2, a_Arg2, a_Type3, aArg3) \ 743 IEM_DECL_IMPL_DEF(VBOXSTRICTRC, a_Name, (PIEMCPU pIemCpu, uint8_t cbInstr, a_Type0 a_Arg0, a_Type1 a_Arg1, a_Type2 a_Arg2, a_Type3 a_Arg3)) 744 /** 745 * For calling a C instruction implementation function taking four extra 746 * arguments. 747 * 748 * This special call macro adds default arguments to the call and allow us to 749 * change these later. 750 * 751 * @param a_fn The name of the function. 752 * @param a0 The name of the 1st argument. 753 * @param a1 The name of the 2nd argument. 754 * @param a2 The name of the 3rd argument. 755 * @param a3 The name of the 4th argument. 756 */ 757 # define IEM_CIMPL_CALL_4(a_fn, a0, a1, a2, a3) a_fn(pIemCpu, cbInstr, (a0), (a1), (a2), (a3)) 758 759 760 /** 761 * For typedef'ing or declaring a C instruction implementation function taking 762 * five extra arguments. 763 * 764 * @param a_Name The name of the type. 765 * @param a_Type0 The type of the 1st argument 766 * @param a_Arg0 The name of the 1st argument. 767 * @param a_Type1 The type of the 2nd argument. 768 * @param a_Arg1 The name of the 2nd argument. 769 * @param a_Type2 The type of the 3rd argument. 770 * @param a_Arg2 The name of the 3rd argument. 771 * @param a_Type3 The type of the 4th argument. 772 * @param a_Arg3 The name of the 4th argument. 773 * @param a_Type4 The type of the 5th argument. 774 * @param a_Arg4 The name of the 5th argument. 775 */ 776 # define IEM_CIMPL_DECL_TYPE_5(a_Name, a_Type0, a_Arg0, a_Type1, a_Arg1, a_Type2, a_Arg2, a_Type3, a_Arg3, a_Type4, a_Arg4) \ 777 IEM_DECL_IMPL_TYPE(VBOXSTRICTRC, a_Name, (PIEMCPU pIemCpu, uint8_t cbInstr, \ 778 a_Type0 a_Arg0, a_Type1 a_Arg1, a_Type2 a_Arg2, \ 779 a_Type3 a_Arg3, a_Type4 a_Arg4)) 780 /** 781 * For defining a C instruction implementation function taking five extra 782 * arguments. 783 * 784 * @param a_Name The name of the function. 785 * @param a_Type0 The type of the 1st argument 786 * @param a_Arg0 The name of the 1st argument. 787 * @param a_Type1 The type of the 2nd argument. 788 * @param a_Arg1 The name of the 2nd argument. 789 * @param a_Type2 The type of the 3rd argument. 790 * @param a_Arg2 The name of the 3rd argument. 791 * @param a_Type3 The type of the 4th argument. 792 * @param a_Arg3 The name of the 4th argument. 793 * @param a_Type4 The type of the 5th argument. 794 * @param a_Arg4 The name of the 5th argument. 795 */ 796 # define IEM_CIMPL_DEF_5(a_Name, a_Type0, a_Arg0, a_Type1, a_Arg1, a_Type2, a_Arg2, a_Type3, a_Arg3, a_Type4, a_Arg4) \ 797 IEM_DECL_IMPL_DEF(VBOXSTRICTRC, a_Name, (PIEMCPU pIemCpu, uint8_t cbInstr, \ 798 a_Type0 a_Arg0, a_Type1 a_Arg1, a_Type2 a_Arg2, \ 799 a_Type3 a_Arg3, a_Type4 a_Arg4)) 800 /** 801 * For calling a C instruction implementation function taking five extra 802 * arguments. 803 * 804 * This special call macro adds default arguments to the call and allow us to 805 * change these later. 806 * 807 * @param a_fn The name of the function. 808 * @param a0 The name of the 1st argument. 809 * @param a1 The name of the 2nd argument. 810 * @param a2 The name of the 3rd argument. 811 * @param a3 The name of the 4th argument. 812 * @param a4 The name of the 5th argument. 813 */ 814 # define IEM_CIMPL_CALL_5(a_fn, a0, a1, a2, a3, a4) a_fn(pIemCpu, cbInstr, (a0), (a1), (a2), (a3), (a4)) 633 815 634 816 /** @} */ -
trunk/src/recompiler/VBoxRecompiler.c
r36490 r36794 1407 1407 uint32_t u32CR0; 1408 1408 1409 #ifdef IEM_VERIFICATION_MODE 1410 return false; 1411 #endif 1412 1409 1413 /* Update counter. */ 1410 1414 env->pVM->rem.s.cCanExecuteRaw++; … … 4171 4175 REMR3DECL(void) REMR3NotifyInterruptSet(PVM pVM, PVMCPU pVCpu) 4172 4176 { 4177 #ifndef IEM_VERIFICATION_MODE 4173 4178 LogFlow(("REMR3NotifyInterruptSet: fInRem=%d interrupts %s\n", pVM->rem.s.fInREM, 4174 4179 (pVM->rem.s.Env.eflags & IF_MASK) && !(pVM->rem.s.Env.hflags & HF_INHIBIT_IRQ_MASK) ? "enabled" : "disabled")); … … 4178 4183 CPU_INTERRUPT_EXTERNAL_HARD); 4179 4184 } 4185 #endif 4180 4186 } 4181 4187 … … 4208 4214 REMR3DECL(void) REMR3NotifyTimerPending(PVM pVM, PVMCPU pVCpuDst) 4209 4215 { 4216 #ifndef IEM_VERIFICATION_MODE 4210 4217 #ifndef DEBUG_bird 4211 4218 LogFlow(("REMR3NotifyTimerPending: fInRem=%d\n", pVM->rem.s.fInREM)); … … 4224 4231 else 4225 4232 LogIt(LOG_INSTANCE, RTLOGGRPFLAGS_LEVEL_5, LOG_GROUP_TM, ("REMR3NotifyTimerPending: !fInREM; cpu state=%d\n", VMCPU_GET_STATE(pVCpuDst))); 4233 #endif 4226 4234 } 4227 4235 … … 4235 4243 REMR3DECL(void) REMR3NotifyDmaPending(PVM pVM) 4236 4244 { 4245 #ifndef IEM_VERIFICATION_MODE 4237 4246 LogFlow(("REMR3NotifyDmaPending: fInRem=%d\n", pVM->rem.s.fInREM)); 4238 4247 if (pVM->rem.s.fInREM) … … 4241 4250 CPU_INTERRUPT_EXTERNAL_DMA); 4242 4251 } 4252 #endif 4243 4253 } 4244 4254 … … 4252 4262 REMR3DECL(void) REMR3NotifyQueuePending(PVM pVM) 4253 4263 { 4264 #ifndef IEM_VERIFICATION_MODE 4254 4265 LogFlow(("REMR3NotifyQueuePending: fInRem=%d\n", pVM->rem.s.fInREM)); 4255 4266 if (pVM->rem.s.fInREM) … … 4258 4269 CPU_INTERRUPT_EXTERNAL_EXIT); 4259 4270 } 4271 #endif 4260 4272 } 4261 4273 … … 4269 4281 REMR3DECL(void) REMR3NotifyFF(PVM pVM) 4270 4282 { 4283 #ifndef IEM_VERIFICATION_MODE 4271 4284 LogFlow(("REMR3NotifyFF: fInRem=%d\n", pVM->rem.s.fInREM)); 4272 4285 if (pVM->rem.s.fInREM) … … 4275 4288 CPU_INTERRUPT_EXTERNAL_EXIT); 4276 4289 } 4290 #endif 4277 4291 } 4278 4292
Note:
See TracChangeset
for help on using the changeset viewer.