Changeset 105818 in vbox for trunk/src/VBox
- Timestamp:
- Aug 22, 2024 2:19:39 PM (3 months ago)
- Location:
- trunk/src/VBox/VMM
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/VMMAll/IEMAllN8veRecompFuncs.h
r105768 r105818 386 386 /* As this code returns from the TB any pending register writes must be flushed. */ 387 387 off = iemNativeRegFlushPendingWrites(pReNative, off); 388 389 /* 390 * If we're in a conditional, mark the current branch as exiting so we 391 * can disregard its state when we hit the IEM_MC_ENDIF. 392 */ 393 uint8_t idxCondDepth = pReNative->cCondDepth; 394 if (idxCondDepth) 395 { 396 idxCondDepth--; 397 if (pReNative->aCondStack[idxCondDepth].fInElse) 398 pReNative->aCondStack[idxCondDepth].fElseExitTb = true; 399 else 400 pReNative->aCondStack[idxCondDepth].fIfExitTb = true; 401 } 388 402 389 403 /* … … 2464 2478 uint16_t const uCondSeqNo = ++pReNative->uCondSeqNo; 2465 2479 pEntry->fInElse = false; 2480 pEntry->fIfExitTb = false; 2481 pEntry->fElseExitTb = false; 2466 2482 pEntry->idxLabelElse = iemNativeLabelCreate(pReNative, kIemNativeLabelType_Else, UINT32_MAX /*offWhere*/, uCondSeqNo); 2467 2483 pEntry->idxLabelEndIf = iemNativeLabelCreate(pReNative, kIemNativeLabelType_Endif, UINT32_MAX /*offWhere*/, uCondSeqNo); … … 2552 2568 Assert(pReNative->cCondDepth > 0 && pReNative->cCondDepth <= RT_ELEMENTS(pReNative->aCondStack)); 2553 2569 PIEMNATIVECOND const pEntry = &pReNative->aCondStack[pReNative->cCondDepth - 1]; 2554 2555 2570 #ifdef IEMNATIVE_WITH_DELAYED_PC_UPDATING 2556 2571 Assert(pReNative->Core.offPc == 0); 2557 2572 #endif 2573 2574 /* 2575 * If either of the branches exited the TB, we can take the state from the 2576 * other branch and skip all the merging headache. 2577 */ 2578 if (pEntry->fElseExitTb || pEntry->fIfExitTb) 2579 { 2580 #ifdef VBOX_STRICT 2581 Assert(pReNative->cCondDepth == 1); /* Assuming this only happens in simple conditional structures. */ 2582 Assert(pEntry->fElseExitTb != pEntry->fIfExitTb); /* Assuming we don't have any code where both branches exits. */ 2583 PCIEMNATIVECORESTATE const pExitCoreState = pEntry->fIfExitTb && pEntry->fInElse 2584 ? &pEntry->IfFinalState : &pReNative->Core; 2585 # ifdef IEMNATIVE_WITH_DELAYED_REGISTER_WRITEBACK 2586 Assert(pExitCoreState->bmGstRegShadowDirty == 0); 2587 # endif 2588 # ifdef IEMNATIVE_WITH_DELAYED_PC_UPDATING 2589 Assert(pExitCoreState->offPc == 0); 2590 # endif 2591 RT_NOREF(pExitCoreState); 2592 #endif 2593 2594 if (!pEntry->fIfExitTb) 2595 { 2596 Assert(pEntry->fInElse); 2597 pReNative->Core = pEntry->IfFinalState; 2598 } 2599 } 2600 else 2601 { 2558 2602 #ifdef IEMNATIVE_WITH_DELAYED_REGISTER_WRITEBACK 2559 /* Writeback any dirty shadow registers (else branch). */2560 /** @todo r=aeichner Possible optimization is to only writeback guest registers which became dirty2561 * in one of the branches and leave guest registers already dirty before the start of the if2562 * block alone. */2563 off = iemNativeRegFlushDirtyGuest(pReNative, off);2564 #endif 2565 2566 /*2567 * Now we have find common group with the core state at the end of the2568 * if-final. Use the smallest common denominator and just drop anything2569 * that isn't the same in both states.2570 */2571 /** @todo We could, maybe, shuffle registers around if we thought it helpful,2572 * which is why we're doing this at the end of the else-block.2573 * But we'd need more info about future for that to be worth the effort. */2574 PCIEMNATIVECORESTATE const pOther = pEntry->fInElse ? &pEntry->IfFinalState : &pEntry->InitialState;2603 /* Writeback any dirty shadow registers (else branch). */ 2604 /** @todo r=aeichner Possible optimization is to only writeback guest registers which became dirty 2605 * in one of the branches and leave guest registers already dirty before the start of the if 2606 * block alone. */ 2607 off = iemNativeRegFlushDirtyGuest(pReNative, off); 2608 #endif 2609 2610 /* 2611 * Now we have find common group with the core state at the end of the 2612 * if-final. Use the smallest common denominator and just drop anything 2613 * that isn't the same in both states. 2614 */ 2615 /** @todo We could, maybe, shuffle registers around if we thought it helpful, 2616 * which is why we're doing this at the end of the else-block. 2617 * But we'd need more info about future for that to be worth the effort. */ 2618 PCIEMNATIVECORESTATE const pOther = pEntry->fInElse ? &pEntry->IfFinalState : &pEntry->InitialState; 2575 2619 #ifdef IEMNATIVE_WITH_DELAYED_REGISTER_WRITEBACK 2576 Assert( pOther->bmGstRegShadowDirty == 0 2577 && pReNative->Core.bmGstRegShadowDirty == 0); 2578 #endif 2579 2580 if (memcmp(&pReNative->Core, pOther, sizeof(*pOther)) != 0) 2581 { 2582 /* shadow guest stuff first. */ 2583 uint64_t fGstRegs = pReNative->Core.bmGstRegShadows; 2584 if (fGstRegs) 2620 Assert( pOther->bmGstRegShadowDirty == 0 2621 && pReNative->Core.bmGstRegShadowDirty == 0); 2622 #endif 2623 2624 if (memcmp(&pReNative->Core, pOther, sizeof(*pOther)) != 0) 2585 2625 { 2586 Assert(pReNative->Core.bmHstRegsWithGstShadow != 0); 2587 do 2626 /* shadow guest stuff first. */ 2627 uint64_t fGstRegs = pReNative->Core.bmGstRegShadows; 2628 if (fGstRegs) 2588 2629 { 2589 unsigned idxGstReg = ASMBitFirstSetU64(fGstRegs) - 1; 2590 fGstRegs &= ~RT_BIT_64(idxGstReg); 2591 2592 uint8_t const idxHstReg = pReNative->Core.aidxGstRegShadows[idxGstReg]; 2593 if ( !(pOther->bmGstRegShadows & RT_BIT_64(idxGstReg)) 2594 || idxHstReg != pOther->aidxGstRegShadows[idxGstReg]) 2630 Assert(pReNative->Core.bmHstRegsWithGstShadow != 0); 2631 do 2595 2632 { 2596 Log12(("iemNativeEmitEndIf: dropping gst %s from hst %s\n", 2597 g_aGstShadowInfo[idxGstReg].pszName, g_apszIemNativeHstRegNames[idxHstReg])); 2633 unsigned idxGstReg = ASMBitFirstSetU64(fGstRegs) - 1; 2634 fGstRegs &= ~RT_BIT_64(idxGstReg); 2635 2636 uint8_t const idxHstReg = pReNative->Core.aidxGstRegShadows[idxGstReg]; 2637 if ( !(pOther->bmGstRegShadows & RT_BIT_64(idxGstReg)) 2638 || idxHstReg != pOther->aidxGstRegShadows[idxGstReg]) 2639 { 2640 Log12(("iemNativeEmitEndIf: dropping gst %s from hst %s\n", 2641 g_aGstShadowInfo[idxGstReg].pszName, g_apszIemNativeHstRegNames[idxHstReg])); 2598 2642 2599 2643 #ifdef IEMNATIVE_WITH_DELAYED_REGISTER_WRITEBACK 2600 /* Writeback any dirty shadow registers we are about to unshadow. */ 2601 off = iemNativeRegFlushDirtyGuestByHostRegShadow(pReNative, off, idxHstReg); 2602 #endif 2603 iemNativeRegClearGstRegShadowing(pReNative, idxHstReg, off); 2604 } 2605 } while (fGstRegs); 2644 /* Writeback any dirty shadow registers we are about to unshadow. */ 2645 off = iemNativeRegFlushDirtyGuestByHostRegShadow(pReNative, off, idxHstReg); 2646 #endif 2647 iemNativeRegClearGstRegShadowing(pReNative, idxHstReg, off); 2648 } 2649 } while (fGstRegs); 2650 } 2651 else 2652 { 2653 Assert(pReNative->Core.bmHstRegsWithGstShadow == 0); 2654 #ifdef IEMNATIVE_WITH_DELAYED_REGISTER_WRITEBACK 2655 Assert(pReNative->Core.bmGstRegShadowDirty == 0); 2656 #endif 2657 } 2658 2659 /* Check variables next. For now we must require them to be identical 2660 or stuff we can recreate. */ 2661 Assert(pReNative->Core.u64ArgVars == pOther->u64ArgVars); 2662 uint32_t fVars = pReNative->Core.bmVars | pOther->bmVars; 2663 if (fVars) 2664 { 2665 uint32_t const fVarsMustRemove = pReNative->Core.bmVars ^ pOther->bmVars; 2666 do 2667 { 2668 unsigned idxVar = ASMBitFirstSetU32(fVars) - 1; 2669 fVars &= ~RT_BIT_32(idxVar); 2670 2671 if (!(fVarsMustRemove & RT_BIT_32(idxVar))) 2672 { 2673 if (pReNative->Core.aVars[idxVar].idxReg == pOther->aVars[idxVar].idxReg) 2674 continue; 2675 if (pReNative->Core.aVars[idxVar].enmKind != kIemNativeVarKind_Stack) 2676 { 2677 uint8_t const idxHstReg = pReNative->Core.aVars[idxVar].idxReg; 2678 if (idxHstReg != UINT8_MAX) 2679 { 2680 pReNative->Core.bmHstRegs &= ~RT_BIT_32(idxHstReg); 2681 pReNative->Core.aVars[idxVar].idxReg = UINT8_MAX; 2682 Log12(("iemNativeEmitEndIf: Dropping hst reg %s for var #%u/%#x\n", 2683 g_apszIemNativeHstRegNames[idxHstReg], idxVar, IEMNATIVE_VAR_IDX_PACK(idxVar))); 2684 } 2685 continue; 2686 } 2687 } 2688 else if (!(pReNative->Core.bmVars & RT_BIT_32(idxVar))) 2689 continue; 2690 2691 /* Irreconcilable, so drop it. */ 2692 uint8_t const idxHstReg = pReNative->Core.aVars[idxVar].idxReg; 2693 if (idxHstReg != UINT8_MAX) 2694 { 2695 pReNative->Core.bmHstRegs &= ~RT_BIT_32(idxHstReg); 2696 pReNative->Core.aVars[idxVar].idxReg = UINT8_MAX; 2697 Log12(("iemNativeEmitEndIf: Dropping hst reg %s for var #%u/%#x (also dropped)\n", 2698 g_apszIemNativeHstRegNames[idxHstReg], idxVar, IEMNATIVE_VAR_IDX_PACK(idxVar))); 2699 } 2700 Log11(("iemNativeEmitEndIf: Freeing variable #%u/%#x\n", idxVar, IEMNATIVE_VAR_IDX_PACK(idxVar))); 2701 pReNative->Core.bmVars &= ~RT_BIT_32(idxVar); 2702 } while (fVars); 2703 } 2704 2705 /* Finally, check that the host register allocations matches. */ 2706 AssertMsgStmt(pReNative->Core.bmHstRegs == pOther->bmHstRegs, 2707 ("Core.bmHstRegs=%#x pOther->bmHstRegs=%#x - %#x\n", 2708 pReNative->Core.bmHstRegs, pOther->bmHstRegs, pReNative->Core.bmHstRegs ^ pOther->bmHstRegs), 2709 IEMNATIVE_DO_LONGJMP(pReNative, VERR_IEM_COND_ENDIF_RECONCILIATION_FAILED)); 2606 2710 } 2607 else2608 {2609 Assert(pReNative->Core.bmHstRegsWithGstShadow == 0);2610 #ifdef IEMNATIVE_WITH_DELAYED_REGISTER_WRITEBACK2611 Assert(pReNative->Core.bmGstRegShadowDirty == 0);2612 #endif2613 }2614 2615 /* Check variables next. For now we must require them to be identical2616 or stuff we can recreate. */2617 Assert(pReNative->Core.u64ArgVars == pOther->u64ArgVars);2618 uint32_t fVars = pReNative->Core.bmVars | pOther->bmVars;2619 if (fVars)2620 {2621 uint32_t const fVarsMustRemove = pReNative->Core.bmVars ^ pOther->bmVars;2622 do2623 {2624 unsigned idxVar = ASMBitFirstSetU32(fVars) - 1;2625 fVars &= ~RT_BIT_32(idxVar);2626 2627 if (!(fVarsMustRemove & RT_BIT_32(idxVar)))2628 {2629 if (pReNative->Core.aVars[idxVar].idxReg == pOther->aVars[idxVar].idxReg)2630 continue;2631 if (pReNative->Core.aVars[idxVar].enmKind != kIemNativeVarKind_Stack)2632 {2633 uint8_t const idxHstReg = pReNative->Core.aVars[idxVar].idxReg;2634 if (idxHstReg != UINT8_MAX)2635 {2636 pReNative->Core.bmHstRegs &= ~RT_BIT_32(idxHstReg);2637 pReNative->Core.aVars[idxVar].idxReg = UINT8_MAX;2638 Log12(("iemNativeEmitEndIf: Dropping hst reg %s for var #%u/%#x\n",2639 g_apszIemNativeHstRegNames[idxHstReg], idxVar, IEMNATIVE_VAR_IDX_PACK(idxVar)));2640 }2641 continue;2642 }2643 }2644 else if (!(pReNative->Core.bmVars & RT_BIT_32(idxVar)))2645 continue;2646 2647 /* Irreconcilable, so drop it. */2648 uint8_t const idxHstReg = pReNative->Core.aVars[idxVar].idxReg;2649 if (idxHstReg != UINT8_MAX)2650 {2651 pReNative->Core.bmHstRegs &= ~RT_BIT_32(idxHstReg);2652 pReNative->Core.aVars[idxVar].idxReg = UINT8_MAX;2653 Log12(("iemNativeEmitEndIf: Dropping hst reg %s for var #%u/%#x (also dropped)\n",2654 g_apszIemNativeHstRegNames[idxHstReg], idxVar, IEMNATIVE_VAR_IDX_PACK(idxVar)));2655 }2656 Log11(("iemNativeEmitEndIf: Freeing variable #%u/%#x\n", idxVar, IEMNATIVE_VAR_IDX_PACK(idxVar)));2657 pReNative->Core.bmVars &= ~RT_BIT_32(idxVar);2658 } while (fVars);2659 }2660 2661 /* Finally, check that the host register allocations matches. */2662 AssertMsgStmt(pReNative->Core.bmHstRegs == pOther->bmHstRegs,2663 ("Core.bmHstRegs=%#x pOther->bmHstRegs=%#x - %#x\n",2664 pReNative->Core.bmHstRegs, pOther->bmHstRegs, pReNative->Core.bmHstRegs ^ pOther->bmHstRegs),2665 IEMNATIVE_DO_LONGJMP(pReNative, VERR_IEM_COND_ENDIF_RECONCILIATION_FAILED));2666 2711 } 2667 2712 -
trunk/src/VBox/VMM/include/IEMN8veRecompiler.h
r105739 r105818 1386 1386 /** Set if we're in the "else" part, clear if we're in the "if" before it. */ 1387 1387 bool fInElse; 1388 /** Set if the if-block unconditionally exited the TB. */ 1389 bool fIfExitTb; 1390 /** Set if the else-block unconditionally exited the TB. */ 1391 bool fElseExitTb; 1392 bool afPadding[5]; 1388 1393 /** The label for the IEM_MC_ELSE. */ 1389 1394 uint32_t idxLabelElse; … … 2429 2434 * RIP updates, since these are the most common ones. 2430 2435 * 2431 * @note This function does not flush any shadowing information for guest registers. This needs to be done by2432 * the caller if it wishes to do so.2436 * @note This function does not flush any shadowing information for guest 2437 * registers. This needs to be done by the caller if it wishes to do so. 2433 2438 */ 2434 2439 DECL_INLINE_THROW(uint32_t) 2435 iemNativeRegFlushPendingWrites(PIEMRECOMPILERSTATE pReNative, uint32_t off, uint64_t fGstShwExcept = 0, uint64_t fGstSimdShwExcept = 0) 2440 iemNativeRegFlushPendingWrites(PIEMRECOMPILERSTATE pReNative, uint32_t off, uint64_t fGstShwExcept = 0, 2441 uint64_t fGstSimdShwExcept = 0) 2436 2442 { 2437 2443 #ifdef IEMNATIVE_WITH_DELAYED_REGISTER_WRITEBACK 2438 uint64_t const bmGstRegShadowDirty = pReNative->Core.bmGstRegShadowDirty & ~fGstShwExcept;2439 #else 2440 uint64_t const bmGstRegShadowDirty = 0;2444 uint64_t const bmGstRegShadowDirty = pReNative->Core.bmGstRegShadowDirty & ~fGstShwExcept; 2445 #else 2446 uint64_t const bmGstRegShadowDirty = 0; 2441 2447 #endif 2442 2448 #ifdef IEMNATIVE_WITH_SIMD_REG_ALLOCATOR 2443 uint64_t const bmGstSimdRegShadowDirty = (pReNative->Core.bmGstSimdRegShadowDirtyLo128 | pReNative->Core.bmGstSimdRegShadowDirtyHi128) 2444 & ~fGstSimdShwExcept; 2449 uint64_t const bmGstSimdRegShadowDirty = ( pReNative->Core.bmGstSimdRegShadowDirtyLo128 2450 | pReNative->Core.bmGstSimdRegShadowDirtyHi128) 2451 & ~fGstSimdShwExcept; 2445 2452 #else 2446 2453 uint64_t const bmGstSimdRegShadowDirty = 0; 2447 2454 #endif 2448 2455 #ifdef IEMNATIVE_WITH_DELAYED_PC_UPDATING 2449 uint64_t const fWritebackPc = ~(fGstShwExcept & kIemNativeGstReg_Pc);2450 #else 2451 uint64_t const fWritebackPc = 0;2456 uint64_t const fWritebackPc = ~(fGstShwExcept & kIemNativeGstReg_Pc); 2457 #else 2458 uint64_t const fWritebackPc = 0; 2452 2459 #endif 2453 2460 if (bmGstRegShadowDirty | bmGstSimdRegShadowDirty | fWritebackPc)
Note:
See TracChangeset
for help on using the changeset viewer.