- Timestamp:
- Oct 23, 2023 12:50:37 AM (12 months ago)
- Location:
- trunk/src/VBox/VMM
- Files:
-
- 3 edited
-
VMMAll/IEMAllN8veRecompiler.cpp (modified) (39 diffs)
-
include/IEMInternal.h (modified) (3 diffs)
-
include/IEMN8veRecompiler.h (modified) (6 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/VMMAll/IEMAllN8veRecompiler.cpp
r101539 r101547 128 128 *********************************************************************************************************************************/ 129 129 static uint32_t iemNativeEmitGuestRegValueCheck(PIEMRECOMPILERSTATE pReNative, uint32_t off, 130 uint8_t idxReg, IEMNATIVEGSTREG enmGstReg); 130 uint8_t idxReg, IEMNATIVEGSTREG enmGstReg) RT_NOEXCEPT; 131 static bool iemNativeDbgInfoAddNativeOffset(PIEMRECOMPILERSTATE pReNative, uint32_t off) RT_NOEXCEPT; 132 static bool iemNativeDbgInfoAddLabel(PIEMRECOMPILERSTATE pReNative, IEMNATIVELABELTYPE enmType, uint16_t uData) RT_NOEXCEPT; 131 133 132 134 … … 1580 1582 pReNative->bmLabelTypes = 0; 1581 1583 pReNative->cFixups = 0; 1584 #ifdef IEMNATIVE_WITH_TB_DEBUG_INFO 1585 pReNative->pDbgInfo->cEntries = 0; 1586 #endif 1582 1587 pReNative->pTbOrg = pTb; 1583 1588 … … 1652 1657 pReNative->paLabels = (PIEMNATIVELABEL)RTMemAllocZ(sizeof(IEMNATIVELABEL) * _8K); 1653 1658 pReNative->paFixups = (PIEMNATIVEFIXUP)RTMemAllocZ(sizeof(IEMNATIVEFIXUP) * _16K); 1659 #ifdef IEMNATIVE_WITH_TB_DEBUG_INFO 1660 pReNative->pDbgInfo = (PIEMTBDBG)RTMemAllocZ(RT_UOFFSETOF_DYN(IEMTBDBG, aEntries[_16K])); 1661 #endif 1654 1662 if (RT_LIKELY( pReNative->pInstrBuf 1655 1663 && pReNative->paLabels 1656 && pReNative->paFixups)) 1664 && pReNative->paFixups) 1665 #ifdef IEMNATIVE_WITH_TB_DEBUG_INFO 1666 && pReNative->pDbgInfo 1667 #endif 1668 ) 1657 1669 { 1658 1670 /* … … 1662 1674 pReNative->cLabelsAlloc = _8K; 1663 1675 pReNative->cFixupsAlloc = _16K; 1676 #ifdef IEMNATIVE_WITH_TB_DEBUG_INFO 1677 pReNative->cDbgInfoAlloc = _16K; 1678 #endif 1664 1679 1665 1680 /* … … 1677 1692 RTMemFree(pReNative->paLabels); 1678 1693 RTMemFree(pReNative->paFixups); 1694 #ifdef IEMNATIVE_WITH_TB_DEBUG_INFO 1695 RTMemFree(pReNative->pDbgInfo); 1696 #endif 1679 1697 RTMemFree(pReNative); 1680 1698 return NULL; … … 1683 1701 1684 1702 /** 1685 * Defines a label. 1703 * Creates a label 1704 * 1705 * If the label does not yet have a defined position, 1706 * call iemNativeLabelDefine() later to set it. 1686 1707 * 1687 1708 * @returns Label ID. … … 1693 1714 * certain type of labels. Default is zero. 1694 1715 */ 1695 DECLHIDDEN(uint32_t) iemNativeMakeLabel(PIEMRECOMPILERSTATE pReNative, IEMNATIVELABELTYPE enmType, 1696 uint32_t offWhere /*= UINT32_MAX*/, uint16_t uData /*= 0*/) RT_NOEXCEPT 1697 { 1698 /* 1699 * Do we have the label already? 1716 DECLHIDDEN(uint32_t) iemNativeLabelCreate(PIEMRECOMPILERSTATE pReNative, IEMNATIVELABELTYPE enmType, 1717 uint32_t offWhere /*= UINT32_MAX*/, uint16_t uData /*= 0*/) RT_NOEXCEPT 1718 { 1719 /* 1720 * Locate existing label definition. 1721 * 1722 * This is only allowed for forward declarations where offWhere=UINT32_MAX 1723 * and uData is zero. 1700 1724 */ 1701 1725 PIEMNATIVELABEL paLabels = pReNative->paLabels; 1702 1726 uint32_t const cLabels = pReNative->cLabels; 1703 for (uint32_t i = 0; i < cLabels; i++) 1704 if ( paLabels[i].enmType == enmType 1705 && paLabels[i].uData == uData) 1706 { 1707 if (paLabels[i].off == offWhere || offWhere == UINT32_MAX) 1708 return i; 1709 if (paLabels[i].off == UINT32_MAX) 1727 if ( pReNative->bmLabelTypes & RT_BIT_64(enmType) 1728 #ifndef VBOX_STRICT 1729 && offWhere == UINT32_MAX 1730 && uData == 0 1731 #endif 1732 ) 1733 { 1734 /** @todo Since this is only used for labels with uData = 0, just use a 1735 * lookup array? */ 1736 for (uint32_t i = 0; i < cLabels; i++) 1737 if ( paLabels[i].enmType == enmType 1738 && paLabels[i].uData == uData) 1710 1739 { 1711 paLabels[i].off = offWhere; 1740 #ifdef VBOX_STRICT 1741 AssertReturn(uData == 0, UINT32_MAX); 1742 AssertReturn(offWhere == UINT32_MAX, UINT32_MAX); 1743 #endif 1744 AssertReturn(paLabels[i].off == UINT32_MAX, UINT32_MAX); 1712 1745 return i; 1713 1746 } 1714 }1747 } 1715 1748 1716 1749 /* … … 1742 1775 Assert(enmType >= 0 && enmType < 64); 1743 1776 pReNative->bmLabelTypes |= RT_BIT_64(enmType); 1777 1778 if (offWhere != UINT32_MAX) 1779 { 1780 #ifdef IEMNATIVE_WITH_TB_DEBUG_INFO 1781 iemNativeDbgInfoAddNativeOffset(pReNative, offWhere); 1782 iemNativeDbgInfoAddLabel(pReNative, enmType, uData); 1783 #endif 1784 } 1744 1785 return cLabels; 1745 1786 } … … 1747 1788 1748 1789 /** 1790 * Defines the location of an existing label. 1791 * 1792 * @param pReNative The native recompile state. 1793 * @param idxLabel The label to define. 1794 * @param offWhere The position. 1795 */ 1796 DECLHIDDEN(void) iemNativeLabelDefine(PIEMRECOMPILERSTATE pReNative, uint32_t idxLabel, uint32_t offWhere) RT_NOEXCEPT 1797 { 1798 AssertReturnVoid(idxLabel < pReNative->cLabels); 1799 PIEMNATIVELABEL const pLabel = &pReNative->paLabels[idxLabel]; 1800 AssertReturnVoid(pLabel->off == UINT32_MAX); 1801 pLabel->off = offWhere; 1802 #ifdef IEMNATIVE_WITH_TB_DEBUG_INFO 1803 iemNativeDbgInfoAddNativeOffset(pReNative, offWhere); 1804 iemNativeDbgInfoAddLabel(pReNative, (IEMNATIVELABELTYPE)pLabel->enmType, pLabel->uData); 1805 #endif 1806 } 1807 1808 1809 /** 1749 1810 * Looks up a lable. 1750 1811 * 1751 1812 * @returns Label ID if found, UINT32_MAX if not. 1752 1813 */ 1753 static uint32_t iemNative FindLabel(PIEMRECOMPILERSTATE pReNative, IEMNATIVELABELTYPE enmType,1814 static uint32_t iemNativeLabelFind(PIEMRECOMPILERSTATE pReNative, IEMNATIVELABELTYPE enmType, 1754 1815 uint32_t offWhere = UINT32_MAX, uint16_t uData = 0) RT_NOEXCEPT 1755 1816 { … … 1846 1907 } 1847 1908 1909 #ifdef IEMNATIVE_WITH_TB_DEBUG_INFO 1910 1911 /** 1912 * Grows the static debug info array used during recompilation. 1913 * @returns Pointer to the new debug info block, NULL on failure. 1914 */ 1915 DECL_NO_INLINE(static, PIEMTBDBG) iemNativeDbgInfoGrow(PIEMRECOMPILERSTATE pReNative, PIEMTBDBG pDbgInfo) RT_NOEXCEPT 1916 { 1917 uint32_t cNew = pReNative->cDbgInfoAlloc * 2; 1918 AssertReturn(cNew < _1M && cNew != 0, NULL); 1919 pDbgInfo = (PIEMTBDBG)RTMemRealloc(pDbgInfo, RT_UOFFSETOF_DYN(IEMTBDBG, aEntries[cNew])); 1920 AssertReturn(pDbgInfo, NULL); 1921 pReNative->pDbgInfo = pDbgInfo; 1922 pReNative->cDbgInfoAlloc = cNew; 1923 return pDbgInfo; 1924 } 1925 1926 1927 /** 1928 * Adds a new debug info uninitialized entry, returning the pointer to it. 1929 */ 1930 DECLINLINE(PIEMTBDBGENTRY) iemNativeDbgInfoAddNewEntry(PIEMRECOMPILERSTATE pReNative, PIEMTBDBG pDbgInfo) 1931 { 1932 if (RT_LIKELY(pDbgInfo->cEntries < pReNative->cDbgInfoAlloc)) 1933 { /* likely */ } 1934 else 1935 { 1936 pDbgInfo = iemNativeDbgInfoGrow(pReNative, pDbgInfo); 1937 AssertReturn(pDbgInfo, NULL); 1938 } 1939 return &pDbgInfo->aEntries[pDbgInfo->cEntries++]; 1940 } 1941 1942 1943 /** 1944 * Debug Info: Adds a native offset record, if necessary. 1945 */ 1946 static bool iemNativeDbgInfoAddNativeOffset(PIEMRECOMPILERSTATE pReNative, uint32_t off) RT_NOEXCEPT 1947 { 1948 PIEMTBDBG pDbgInfo = pReNative->pDbgInfo; 1949 1950 /* 1951 * Search backwards to see if we've got a similar record already. 1952 */ 1953 uint32_t idx = pDbgInfo->cEntries; 1954 uint32_t idxStop = idx > 8 ? idx - 8 : 0; 1955 while (idx-- > idxStop) 1956 if (pDbgInfo->aEntries[idx].Gen.uType == kIemTbDbgEntryType_NativeOffset) 1957 { 1958 if (pDbgInfo->aEntries[idx].NativeOffset.offNative == off) 1959 return true; 1960 AssertReturn(pDbgInfo->aEntries[idx].NativeOffset.offNative < off, false); 1961 break; 1962 } 1963 1964 /* 1965 * Add it. 1966 */ 1967 PIEMTBDBGENTRY const pEntry = iemNativeDbgInfoAddNewEntry(pReNative, pDbgInfo); 1968 AssertReturn(pEntry, false); 1969 pEntry->NativeOffset.uType = kIemTbDbgEntryType_NativeOffset; 1970 pEntry->NativeOffset.offNative = off; 1971 1972 return true; 1973 } 1974 1975 1976 /** 1977 * Debug Info: Record info about a label. 1978 */ 1979 static bool iemNativeDbgInfoAddLabel(PIEMRECOMPILERSTATE pReNative, IEMNATIVELABELTYPE enmType, uint16_t uData) RT_NOEXCEPT 1980 { 1981 PIEMTBDBGENTRY const pEntry = iemNativeDbgInfoAddNewEntry(pReNative, pReNative->pDbgInfo); 1982 AssertReturn(pEntry, false); 1983 1984 pEntry->Label.uType = kIemTbDbgEntryType_Label; 1985 pEntry->Label.uUnused = 0; 1986 pEntry->Label.enmLabel = (uint8_t)enmType; 1987 pEntry->Label.uData = uData; 1988 1989 return true; 1990 } 1991 1992 1993 /** 1994 * Debug Info: Record info about a threaded call. 1995 */ 1996 static bool iemNativeDbgInfoAddThreadedCall(PIEMRECOMPILERSTATE pReNative, IEMTHREADEDFUNCS enmCall) RT_NOEXCEPT 1997 { 1998 PIEMTBDBGENTRY const pEntry = iemNativeDbgInfoAddNewEntry(pReNative, pReNative->pDbgInfo); 1999 AssertReturn(pEntry, false); 2000 2001 pEntry->ThreadedCall.uType = kIemTbDbgEntryType_ThreadedCall; 2002 pEntry->ThreadedCall.uUnused = 0; 2003 pEntry->ThreadedCall.enmCall = (uint16_t)enmCall; 2004 2005 return true; 2006 } 2007 2008 2009 /** 2010 * Debug Info: Record info about a new guest instruction. 2011 */ 2012 static bool iemNativeDbgInfoAddGuestInstruction(PIEMRECOMPILERSTATE pReNative, uint32_t fExec) RT_NOEXCEPT 2013 { 2014 PIEMTBDBGENTRY const pEntry = iemNativeDbgInfoAddNewEntry(pReNative, pReNative->pDbgInfo); 2015 AssertReturn(pEntry, false); 2016 2017 pEntry->GuestInstruction.uType = kIemTbDbgEntryType_GuestInstruction; 2018 pEntry->GuestInstruction.uUnused = 0; 2019 pEntry->GuestInstruction.fExec = fExec; 2020 2021 return true; 2022 } 2023 2024 2025 /** 2026 * Debug Info: Record info about guest register shadowing. 2027 */ 2028 static bool iemNativeDbgInfoAddGuestRegShadowing(PIEMRECOMPILERSTATE pReNative, IEMNATIVEGSTREG enmGstReg, 2029 uint8_t idxHstReg = UINT8_MAX, uint8_t idxHstRegPrev = UINT8_MAX) RT_NOEXCEPT 2030 { 2031 PIEMTBDBGENTRY const pEntry = iemNativeDbgInfoAddNewEntry(pReNative, pReNative->pDbgInfo); 2032 AssertReturn(pEntry, false); 2033 2034 pEntry->GuestRegShadowing.uType = kIemTbDbgEntryType_GuestRegShadowing; 2035 pEntry->GuestRegShadowing.uUnused = 0; 2036 pEntry->GuestRegShadowing.idxGstReg = enmGstReg; 2037 pEntry->GuestRegShadowing.idxHstReg = idxHstReg; 2038 pEntry->GuestRegShadowing.idxHstRegPrev = idxHstRegPrev; 2039 2040 return true; 2041 } 2042 2043 #endif /* IEMNATIVE_WITH_TB_DEBUG_INFO */ 1848 2044 1849 2045 … … 2251 2447 */ 2252 2448 DECL_FORCE_INLINE(void) 2253 iemNativeRegMarkAsGstRegShadow(PIEMRECOMPILERSTATE pReNative, uint8_t idxHstReg, IEMNATIVEGSTREG enmGstReg )2449 iemNativeRegMarkAsGstRegShadow(PIEMRECOMPILERSTATE pReNative, uint8_t idxHstReg, IEMNATIVEGSTREG enmGstReg, uint32_t off) 2254 2450 { 2255 2451 Assert(!(pReNative->bmGstRegShadows & RT_BIT_64(enmGstReg))); … … 2259 2455 pReNative->bmGstRegShadows |= RT_BIT_64(enmGstReg); 2260 2456 pReNative->bmHstRegsWithGstShadow |= RT_BIT_32(idxHstReg); 2457 #ifdef IEMNATIVE_WITH_TB_DEBUG_INFO 2458 iemNativeDbgInfoAddNativeOffset(pReNative, off); 2459 iemNativeDbgInfoAddGuestRegShadowing(pReNative, enmGstReg, idxHstReg); 2460 #else 2461 RT_NOREF(off); 2462 #endif 2261 2463 } 2262 2464 … … 2268 2470 */ 2269 2471 DECL_FORCE_INLINE(void) 2270 iemNativeRegClearGstRegShadowing(PIEMRECOMPILERSTATE pReNative, uint8_t idxHstReg )2472 iemNativeRegClearGstRegShadowing(PIEMRECOMPILERSTATE pReNative, uint8_t idxHstReg, uint32_t off) 2271 2473 { 2272 2474 Assert( (pReNative->bmGstRegShadows & pReNative->aHstRegs[idxHstReg].fGstRegShadows) … … 2275 2477 == RT_BOOL(pReNative->aHstRegs[idxHstReg].fGstRegShadows)); 2276 2478 2479 #ifdef IEMNATIVE_WITH_TB_DEBUG_INFO 2480 uint64_t fGstRegs = pReNative->aHstRegs[idxHstReg].fGstRegShadows; 2481 if (fGstRegs) 2482 { 2483 iemNativeDbgInfoAddNativeOffset(pReNative, off); 2484 while (fGstRegs) 2485 { 2486 unsigned const iGstReg = ASMBitFirstSetU64(fGstRegs) - 1; 2487 fGstRegs &= ~RT_BIT_64(iGstReg); 2488 iemNativeDbgInfoAddGuestRegShadowing(pReNative, (IEMNATIVEGSTREG)iGstReg, UINT8_MAX, idxHstReg); 2489 } 2490 } 2491 #else 2492 RT_NOREF(off); 2493 #endif 2494 2277 2495 pReNative->bmHstRegsWithGstShadow &= ~RT_BIT_32(idxHstReg); 2278 2496 pReNative->bmGstRegShadows &= ~pReNative->aHstRegs[idxHstReg].fGstRegShadows; … … 2286 2504 */ 2287 2505 DECL_FORCE_INLINE(void) 2288 iemNativeRegTransferGstRegShadowing(PIEMRECOMPILERSTATE pReNative, uint8_t idxRegFrom, uint8_t idxRegTo, IEMNATIVEGSTREG enmGstReg) 2506 iemNativeRegTransferGstRegShadowing(PIEMRECOMPILERSTATE pReNative, uint8_t idxRegFrom, uint8_t idxRegTo, 2507 IEMNATIVEGSTREG enmGstReg, uint32_t off) 2289 2508 { 2290 2509 Assert(pReNative->aHstRegs[idxRegFrom].fGstRegShadows & RT_BIT_64(enmGstReg)); … … 2297 2516 pReNative->aHstRegs[idxRegTo].fGstRegShadows = RT_BIT_64(enmGstReg); 2298 2517 pReNative->aidxGstRegShadows[enmGstReg] = idxRegTo; 2518 #ifdef IEMNATIVE_WITH_TB_DEBUG_INFO 2519 iemNativeDbgInfoAddNativeOffset(pReNative, off); 2520 iemNativeDbgInfoAddGuestRegShadowing(pReNative, enmGstReg, idxRegTo, idxRegFrom); 2521 #else 2522 RT_NOREF(off); 2523 #endif 2299 2524 } 2300 2525 … … 2389 2614 else 2390 2615 { 2391 iemNativeRegClearGstRegShadowing(pReNative, idxReg );2616 iemNativeRegClearGstRegShadowing(pReNative, idxReg, *poff); 2392 2617 Log12(("iemNativeRegAllocTmpForGuestReg: Grabbing %s for guest %s - destructive calc\n", 2393 2618 g_apszIemNativeHstRegNames[idxReg], g_aGstShadowInfo[enmGstReg].pszName)); … … 2418 2643 else 2419 2644 { 2420 iemNativeRegTransferGstRegShadowing(pReNative, idxReg, idxRegNew, enmGstReg );2645 iemNativeRegTransferGstRegShadowing(pReNative, idxReg, idxRegNew, enmGstReg, *poff); 2421 2646 Log12(("iemNativeRegAllocTmpForGuestReg: Moved %s for guest %s into %s for update\n", 2422 2647 g_apszIemNativeHstRegNames[idxReg], g_aGstShadowInfo[enmGstReg].pszName, … … 2447 2672 2448 2673 if (enmIntendedUse != kIemNativeGstRegUse_Calculation) 2449 iemNativeRegMarkAsGstRegShadow(pReNative, idxRegNew, enmGstReg );2674 iemNativeRegMarkAsGstRegShadow(pReNative, idxRegNew, enmGstReg, off); 2450 2675 Log12(("iemNativeRegAllocTmpForGuestReg: Allocated %s for guest %s %s\n", 2451 2676 g_apszIemNativeHstRegNames[idxRegNew], g_aGstShadowInfo[enmGstReg].pszName, s_pszIntendedUse[enmIntendedUse])); … … 2859 3084 */ 2860 3085 static uint32_t iemNativeEmitGuestRegValueCheck(PIEMRECOMPILERSTATE pReNative, uint32_t off, 2861 uint8_t idxReg, IEMNATIVEGSTREG enmGstReg) 3086 uint8_t idxReg, IEMNATIVEGSTREG enmGstReg) RT_NOEXCEPT 2862 3087 { 2863 3088 # ifdef RT_ARCH_AMD64 … … 3013 3238 pu32CodeBuf[off++] = Armv8A64MkInstrOrr(ARMV8_A64_REG_X4, ARMV8_A64_REG_X3, ARMV8_A64_REG_X0, false /*f64Bit*/); 3014 3239 3015 uint32_t const idxLabel = iemNative MakeLabel(pReNative, kIemNativeLabelType_NonZeroRetOrPassUp);3240 uint32_t const idxLabel = iemNativeLabelCreate(pReNative, kIemNativeLabelType_NonZeroRetOrPassUp); 3016 3241 AssertReturn(idxLabel != UINT32_MAX, UINT32_MAX); 3017 3242 AssertReturn(iemNativeAddFixup(pReNative, off, idxLabel, kIemNativeFixupType_RelImm19At5), UINT32_MAX); … … 3301 3526 static uint32_t iemNativeEmitRaiseGp0(PIEMRECOMPILERSTATE pReNative, uint32_t off) 3302 3527 { 3303 uint32_t idxLabel = iemNativeFindLabel(pReNative, kIemNativeLabelType_RaiseGp0);3528 uint32_t const idxLabel = iemNativeLabelFind(pReNative, kIemNativeLabelType_RaiseGp0); 3304 3529 if (idxLabel != UINT32_MAX) 3305 3530 { 3306 Assert(pReNative->paLabels[idxLabel].off == UINT32_MAX); 3307 pReNative->paLabels[idxLabel].off = off; 3531 iemNativeLabelDefine(pReNative, idxLabel, off); 3308 3532 3309 3533 /* iemNativeHlpExecRaiseGp0(PVMCPUCC pVCpu, uint8_t idxInstr) */ … … 3315 3539 3316 3540 /* jump back to the return sequence. */ 3317 off = iemNativeEmitJmpToLabel(pReNative, off, iemNative FindLabel(pReNative, kIemNativeLabelType_Return));3541 off = iemNativeEmitJmpToLabel(pReNative, off, iemNativeLabelFind(pReNative, kIemNativeLabelType_Return)); 3318 3542 } 3319 3543 return off; … … 3329 3553 * Generate the rc + rcPassUp fiddling code if needed. 3330 3554 */ 3331 uint32_t idxLabel = iemNativeFindLabel(pReNative, kIemNativeLabelType_NonZeroRetOrPassUp);3555 uint32_t const idxLabel = iemNativeLabelFind(pReNative, kIemNativeLabelType_NonZeroRetOrPassUp); 3332 3556 if (idxLabel != UINT32_MAX) 3333 3557 { 3334 Assert(pReNative->paLabels[idxLabel].off == UINT32_MAX); 3335 pReNative->paLabels[idxLabel].off = off; 3558 iemNativeLabelDefine(pReNative, idxLabel, off); 3336 3559 3337 3560 /* iemNativeHlpExecStatusCodeFiddling(PVMCPUCC pVCpu, int rc, uint8_t idxInstr) */ … … 3381 3604 * Define label for common return point. 3382 3605 */ 3383 uint32_t const idxReturn = iemNative MakeLabel(pReNative, kIemNativeLabelType_Return, off);3606 uint32_t const idxReturn = iemNativeLabelCreate(pReNative, kIemNativeLabelType_Return, off); 3384 3607 AssertReturn(idxReturn != UINT32_MAX, UINT32_MAX); 3385 3608 … … 3853 4076 uint16_t const uCondSeqNo = ++pReNative->uCondSeqNo; 3854 4077 pEntry->fInElse = false; 3855 pEntry->idxLabelElse = iemNative MakeLabel(pReNative, kIemNativeLabelType_Else, UINT32_MAX /*offWhere*/, uCondSeqNo);4078 pEntry->idxLabelElse = iemNativeLabelCreate(pReNative, kIemNativeLabelType_Else, UINT32_MAX /*offWhere*/, uCondSeqNo); 3856 4079 AssertReturn(pEntry->idxLabelElse != UINT32_MAX, NULL); 3857 pEntry->idxLabelEndIf = iemNative MakeLabel(pReNative, kIemNativeLabelType_Endif, UINT32_MAX /*offWhere*/, uCondSeqNo);4080 pEntry->idxLabelEndIf = iemNativeLabelCreate(pReNative, kIemNativeLabelType_Endif, UINT32_MAX /*offWhere*/, uCondSeqNo); 3858 4081 AssertReturn(pEntry->idxLabelEndIf != UINT32_MAX, NULL); 3859 4082 … … 3880 4103 3881 4104 /* Define the else label and enter the else part of the condition. */ 3882 pReNative->paLabels[pEntry->idxLabelElse].off = off;4105 iemNativeLabelDefine(pReNative, pEntry->idxLabelElse, off); 3883 4106 pEntry->fInElse = true; 3884 4107 … … 3901 4124 /* Define the endif label and maybe the else one if we're still in the 'if' part. */ 3902 4125 if (!pEntry->fInElse) 3903 pReNative->paLabels[pEntry->idxLabelElse].off = off;4126 iemNativeLabelDefine(pReNative, pEntry->idxLabelElse, off); 3904 4127 else 3905 4128 Assert(pReNative->paLabels[pEntry->idxLabelElse].off <= off); 3906 pReNative->paLabels[pEntry->idxLabelEndIf].off = off;4129 iemNativeLabelDefine(pReNative, pEntry->idxLabelEndIf, off); 3907 4130 3908 4131 /* Pop the conditional stack.*/ … … 3989 4212 3990 4213 4214 /** 4215 * Formats TB flags (IEM_F_XXX and IEMTB_F_XXX) to string. 4216 * @returns pszBuf. 4217 * @param fFlags The flags. 4218 * @param pszBuf The output buffer. 4219 * @param cchBuf The output buffer length. At least 32 bytes. 4220 */ 4221 const char *iemTbFlagsToString(uint32_t fFlags, char *pszBuf, size_t cbBuf) 4222 { 4223 Assert(cbBuf >= 32); 4224 static RTSTRTUPLE const s_aModes[] = 4225 { 4226 /* [00] = */ { RT_STR_TUPLE("16BIT") }, 4227 /* [01] = */ { RT_STR_TUPLE("32BIT") }, 4228 /* [02] = */ { RT_STR_TUPLE("!2!") }, 4229 /* [03] = */ { RT_STR_TUPLE("!3!") }, 4230 /* [04] = */ { RT_STR_TUPLE("16BIT_PRE_386") }, 4231 /* [05] = */ { RT_STR_TUPLE("32BIT_FLAT") }, 4232 /* [06] = */ { RT_STR_TUPLE("!6!") }, 4233 /* [07] = */ { RT_STR_TUPLE("!7!") }, 4234 /* [08] = */ { RT_STR_TUPLE("16BIT_PROT") }, 4235 /* [09] = */ { RT_STR_TUPLE("32BIT_PROT") }, 4236 /* [0a] = */ { RT_STR_TUPLE("64BIT") }, 4237 /* [0b] = */ { RT_STR_TUPLE("!b!") }, 4238 /* [0c] = */ { RT_STR_TUPLE("16BIT_PROT_PRE_386") }, 4239 /* [0d] = */ { RT_STR_TUPLE("32BIT_PROT_FLAT") }, 4240 /* [0e] = */ { RT_STR_TUPLE("!e!") }, 4241 /* [0f] = */ { RT_STR_TUPLE("!f!") }, 4242 /* [10] = */ { RT_STR_TUPLE("!10!") }, 4243 /* [11] = */ { RT_STR_TUPLE("!11!") }, 4244 /* [12] = */ { RT_STR_TUPLE("!12!") }, 4245 /* [13] = */ { RT_STR_TUPLE("!13!") }, 4246 /* [14] = */ { RT_STR_TUPLE("!14!") }, 4247 /* [15] = */ { RT_STR_TUPLE("!15!") }, 4248 /* [16] = */ { RT_STR_TUPLE("!16!") }, 4249 /* [17] = */ { RT_STR_TUPLE("!17!") }, 4250 /* [18] = */ { RT_STR_TUPLE("16BIT_PROT_V86") }, 4251 /* [19] = */ { RT_STR_TUPLE("32BIT_PROT_V86") }, 4252 /* [1a] = */ { RT_STR_TUPLE("!1a!") }, 4253 /* [1b] = */ { RT_STR_TUPLE("!1b!") }, 4254 /* [1c] = */ { RT_STR_TUPLE("!1c!") }, 4255 /* [1d] = */ { RT_STR_TUPLE("!1d!") }, 4256 /* [1e] = */ { RT_STR_TUPLE("!1e!") }, 4257 /* [1f] = */ { RT_STR_TUPLE("!1f!") }, 4258 }; 4259 AssertCompile(RT_ELEMENTS(s_aModes) == IEM_F_MODE_MASK + 1); 4260 memcpy(pszBuf, s_aModes[fFlags & IEM_F_MODE_MASK].psz, s_aModes[fFlags & IEM_F_MODE_MASK].cch); 4261 unsigned off = s_aModes[fFlags & IEM_F_MODE_MASK].cch; 4262 4263 pszBuf[off++] = ' '; 4264 pszBuf[off++] = 'C'; 4265 pszBuf[off++] = 'P'; 4266 pszBuf[off++] = 'L'; 4267 pszBuf[off++] = '0' + ((fFlags >> IEM_F_X86_CPL_SHIFT) & IEM_F_X86_CPL_SMASK); 4268 Assert(off < 32); 4269 4270 fFlags &= ~(IEM_F_MODE_MASK | IEM_F_X86_CPL_SMASK); 4271 4272 static struct { const char *pszName; uint32_t cchName; uint32_t fFlag; } const s_aFlags[] = 4273 { 4274 { RT_STR_TUPLE("BYPASS_HANDLERS"), IEM_F_BYPASS_HANDLERS }, 4275 { RT_STR_TUPLE("PENDING_BRK_INSTR"), IEM_F_PENDING_BRK_INSTR }, 4276 { RT_STR_TUPLE("PENDING_BRK_DATA"), IEM_F_PENDING_BRK_DATA }, 4277 { RT_STR_TUPLE("PENDING_BRK_X86_IO"), IEM_F_PENDING_BRK_X86_IO }, 4278 { RT_STR_TUPLE("X86_DISREGARD_LOCK"), IEM_F_X86_DISREGARD_LOCK }, 4279 { RT_STR_TUPLE("X86_CTX_VMX"), IEM_F_X86_CTX_VMX }, 4280 { RT_STR_TUPLE("X86_CTX_SVM"), IEM_F_X86_CTX_SVM }, 4281 { RT_STR_TUPLE("X86_CTX_IN_GUEST"), IEM_F_X86_CTX_IN_GUEST }, 4282 { RT_STR_TUPLE("X86_CTX_SMM"), IEM_F_X86_CTX_SMM }, 4283 { RT_STR_TUPLE("INHIBIT_SHADOW"), IEMTB_F_INHIBIT_SHADOW }, 4284 { RT_STR_TUPLE("INHIBIT_NMI"), IEMTB_F_INHIBIT_NMI }, 4285 { RT_STR_TUPLE("CS_LIM_CHECKS"), IEMTB_F_CS_LIM_CHECKS }, 4286 { RT_STR_TUPLE("TYPE_THREADED"), IEMTB_F_TYPE_THREADED }, 4287 { RT_STR_TUPLE("TYPE_NATIVE"), IEMTB_F_TYPE_NATIVE }, 4288 }; 4289 for (unsigned i = 0; i < RT_ELEMENTS(s_aFlags) && fFlags; i++) 4290 if (s_aFlags[i].fFlag & fFlags) 4291 { 4292 AssertReturnStmt(off + 1 + s_aFlags[i].cchName + 1 <= cbBuf, pszBuf[off] = '\0', pszBuf); 4293 pszBuf[off++] = ' '; 4294 memcpy(&pszBuf[off], s_aFlags[i].pszName, s_aFlags[i].cchName); 4295 off += s_aFlags[i].cchName; 4296 fFlags &= ~s_aFlags[i].fFlag; 4297 } 4298 pszBuf[off] = '\0'; 4299 4300 return pszBuf; 4301 } 4302 3991 4303 3992 4304 void iemNativeDisassembleTb(PCIEMTB pTb, PCDBGFINFOHLP pHlp) … … 3996 4308 char szDisBuf[512]; 3997 4309 DISSTATE Dis; 3998 PCIEMNATIVEINSTR const paInstrs = pTb->Native.paInstructions; 3999 uint32_t const cInstrs = pTb->Native.cInstructions; 4310 PCIEMNATIVEINSTR const paNative = pTb->Native.paInstructions; 4311 uint32_t const cNative = pTb->Native.cInstructions; 4312 uint32_t offNative = 0; 4313 #ifdef IEMNATIVE_WITH_TB_DEBUG_INFO 4000 4314 PCIEMTBDBG const pDbgInfo = pTb->pDbgInfo; 4315 #endif 4001 4316 DISCPUMODE enmGstCpuMode = (pTb->fFlags & IEM_F_MODE_CPUMODE_MASK) == IEMMODE_16BIT ? DISCPUMODE_16BIT 4002 4317 : (pTb->fFlags & IEM_F_MODE_CPUMODE_MASK) == IEMMODE_32BIT ? DISCPUMODE_32BIT … … 4010 4325 #endif 4011 4326 4327 /* 4328 * Print TB info. 4329 */ 4012 4330 pHlp->pfnPrintf(pHlp, 4013 4331 "pTb=%p: GCPhysPc=%RGp cInstructions=%u LB %#x cRanges=%u\n" 4014 "pTb=%p: fFlags=%#010x cUsed=%u msLastUsed=%u\n",4332 "pTb=%p: cUsed=%u msLastUsed=%u fFlags=%#010x %s\n", 4015 4333 pTb, pTb->GCPhysPc, pTb->cInstructions, pTb->cbOpcodes, pTb->cRanges, 4016 pTb, pTb->fFlags, pTb->cUsed, pTb->msLastUsed); 4017 if (pDbgInfo) 4018 { 4019 4020 4334 pTb, pTb->cUsed, pTb->msLastUsed, pTb->fFlags, iemTbFlagsToString(pTb->fFlags, szDisBuf, sizeof(szDisBuf))); 4335 #ifdef IEMNATIVE_WITH_TB_DEBUG_INFO 4336 if (pDbgInfo && pDbgInfo->cEntries > 1) 4337 { 4338 Assert(pDbgInfo->aEntries[0].Gen.uType == kIemTbDbgEntryType_NativeOffset); 4339 4340 /* 4341 * This disassembly is driven by the debug info which follows the native 4342 * code and indicates when it starts with the next guest instructions, 4343 * where labels are and such things. 4344 */ 4345 uint32_t idxThreadedCall = 0; 4346 uint32_t fExec = pTb->fFlags & UINT32_C(0x00ffffff); 4347 uint8_t idxRange = UINT8_MAX; 4348 uint8_t const cRanges = RT_MIN(pTb->cRanges, RT_ELEMENTS(pTb->aRanges)); 4349 uint32_t offRange = 0; 4350 uint32_t offOpcodes = 0; 4351 RTGCPHYS GCPhysPc = pTb->GCPhysPc; 4352 uint32_t const cDbgEntries = pDbgInfo->cEntries; 4353 uint32_t iDbgEntry = 1; 4354 uint32_t offDbgNativeNext = pDbgInfo->aEntries[0].NativeOffset.offNative; 4355 4356 while (offNative < cNative) 4357 { 4358 /* If we're at or have passed the point where the next chunk of debug 4359 info starts, process it. */ 4360 if (offDbgNativeNext <= offNative) 4361 { 4362 offDbgNativeNext = UINT32_MAX; 4363 for (; iDbgEntry < cDbgEntries; iDbgEntry++) 4364 { 4365 switch (pDbgInfo->aEntries[iDbgEntry].Gen.uType) 4366 { 4367 case kIemTbDbgEntryType_GuestInstruction: 4368 { 4369 /* Did the exec flag change? */ 4370 if (fExec == pDbgInfo->aEntries[iDbgEntry].GuestInstruction.fExec) 4371 {} //pHlp->pfnPrintf(pHlp, "\n"); 4372 else 4373 { 4374 pHlp->pfnPrintf(pHlp, 4375 " fExec change %#08x -> %#08x %s\n", 4376 fExec, pDbgInfo->aEntries[iDbgEntry].GuestInstruction.fExec, 4377 iemTbFlagsToString(pDbgInfo->aEntries[iDbgEntry].GuestInstruction.fExec, 4378 szDisBuf, sizeof(szDisBuf))); 4379 fExec = pDbgInfo->aEntries[iDbgEntry].GuestInstruction.fExec; 4380 enmGstCpuMode = (fExec & IEM_F_MODE_CPUMODE_MASK) == IEMMODE_16BIT ? DISCPUMODE_16BIT 4381 : (fExec & IEM_F_MODE_CPUMODE_MASK) == IEMMODE_32BIT ? DISCPUMODE_32BIT 4382 : DISCPUMODE_64BIT; 4383 } 4384 4385 /* New opcode range? We need to fend up a spurious debug info entry here for cases 4386 where the compilation was aborted before the opcode was recorded and the actual 4387 instruction was translated to a threaded call. This may happen when we run out 4388 of ranges, or when some complicated interrupts/FFs are found to be pending or 4389 similar. So, we just deal with it here rather than in the compiler code as it 4390 is a lot simpler to do up here. */ 4391 if ( idxRange == UINT8_MAX 4392 || idxRange >= cRanges 4393 || offRange >= pTb->aRanges[idxRange].cbOpcodes) 4394 { 4395 idxRange += 1; 4396 if (idxRange < cRanges) 4397 offRange = 0; 4398 else 4399 continue; 4400 Assert(offOpcodes == pTb->aRanges[idxRange].offOpcodes); 4401 GCPhysPc = pTb->aRanges[idxRange].offPhysPage 4402 + (pTb->aRanges[idxRange].idxPhysPage == 0 4403 ? pTb->GCPhysPc & ~(RTGCPHYS)GUEST_PAGE_OFFSET_MASK 4404 : pTb->aGCPhysPages[pTb->aRanges[idxRange].idxPhysPage - 1]); 4405 pHlp->pfnPrintf(pHlp, " Range #%u: GCPhysPc=%RGp LB %#x [idxPg=%d]\n", 4406 idxRange, GCPhysPc, pTb->aRanges[idxRange].cbOpcodes, 4407 pTb->aRanges[idxRange].idxPhysPage); 4408 } 4409 4410 /* Disassemble the instruction. */ 4411 uint8_t const cbInstrMax = RT_MIN(pTb->aRanges[idxRange].cbOpcodes - offRange, 15); 4412 uint32_t cbInstr = 1; 4413 int rc = DISInstrWithPrefetchedBytes(GCPhysPc, enmGstCpuMode, DISOPTYPE_ALL, 4414 &pTb->pabOpcodes[offOpcodes], cbInstrMax, 4415 iemNativeDisasReadBytesDummy, NULL, &Dis, &cbInstr); 4416 if (RT_SUCCESS(rc)) 4417 { 4418 size_t cch = DISFormatYasmEx(&Dis, szDisBuf, sizeof(szDisBuf), 4419 DIS_FMT_FLAGS_BYTES_WIDTH_MAKE(10) | DIS_FMT_FLAGS_BYTES_LEFT 4420 | DIS_FMT_FLAGS_RELATIVE_BRANCH | DIS_FMT_FLAGS_C_HEX, 4421 NULL /*pfnGetSymbol*/, NULL /*pvUser*/); 4422 4423 static unsigned const s_offMarker = 55; 4424 static char const s_szMarker[] = " ; <--- guest"; 4425 if (cch < s_offMarker) 4426 { 4427 memset(&szDisBuf[cch], ' ', s_offMarker - cch); 4428 cch = s_offMarker; 4429 } 4430 if (cch + sizeof(s_szMarker) <= sizeof(szDisBuf)) 4431 memcpy(&szDisBuf[cch], s_szMarker, sizeof(s_szMarker)); 4432 4433 pHlp->pfnPrintf(pHlp, " %%%%%RGp: %s\n", GCPhysPc, szDisBuf); 4434 } 4435 else 4436 { 4437 pHlp->pfnPrintf(pHlp, " %%%%%RGp: %.*Rhxs - guest disassembly failure %Rrc\n", 4438 GCPhysPc, cbInstrMax, &pTb->pabOpcodes[offOpcodes], rc); 4439 cbInstr = 1; 4440 } 4441 GCPhysPc += cbInstr; 4442 offOpcodes += cbInstr; 4443 offRange += cbInstr; 4444 continue; 4445 } 4446 4447 case kIemTbDbgEntryType_ThreadedCall: 4448 pHlp->pfnPrintf(pHlp, 4449 " Call #%u to %s (%u args)\n", 4450 idxThreadedCall, 4451 g_apszIemThreadedFunctions[pDbgInfo->aEntries[iDbgEntry].ThreadedCall.enmCall], 4452 g_acIemThreadedFunctionUsedArgs[pDbgInfo->aEntries[iDbgEntry].ThreadedCall.enmCall]); 4453 idxThreadedCall++; 4454 continue; 4455 4456 case kIemTbDbgEntryType_GuestRegShadowing: 4457 { 4458 PCIEMTBDBGENTRY const pEntry = &pDbgInfo->aEntries[iDbgEntry]; 4459 const char * const pszGstReg = g_aGstShadowInfo[pEntry->GuestRegShadowing.idxGstReg].pszName; 4460 if (pEntry->GuestRegShadowing.idxHstReg == UINT8_MAX) 4461 pHlp->pfnPrintf(pHlp, " Guest register %s != host register %s\n", pszGstReg, 4462 g_apszIemNativeHstRegNames[pEntry->GuestRegShadowing.idxHstRegPrev]); 4463 else if (pEntry->GuestRegShadowing.idxHstRegPrev == UINT8_MAX) 4464 pHlp->pfnPrintf(pHlp, " Guest register %s == host register %s\n", pszGstReg, 4465 g_apszIemNativeHstRegNames[pEntry->GuestRegShadowing.idxHstReg]); 4466 else 4467 pHlp->pfnPrintf(pHlp, " Guest register %s == host register %s (previously in %s)\n", pszGstReg, 4468 g_apszIemNativeHstRegNames[pEntry->GuestRegShadowing.idxHstReg], 4469 g_apszIemNativeHstRegNames[pEntry->GuestRegShadowing.idxHstRegPrev]); 4470 continue; 4471 } 4472 4473 case kIemTbDbgEntryType_Label: 4474 { 4475 const char *pszName = "what_the_fudge"; 4476 bool fNumbered = pDbgInfo->aEntries[iDbgEntry].Label.uData != 0; 4477 switch ((IEMNATIVELABELTYPE)pDbgInfo->aEntries[iDbgEntry].Label.enmLabel) 4478 { 4479 case kIemNativeLabelType_Return: pszName = "Return"; break; 4480 case kIemNativeLabelType_Else: pszName = "Else"; fNumbered = true; break; 4481 case kIemNativeLabelType_Endif: pszName = "Endif"; fNumbered = true; break; 4482 case kIemNativeLabelType_NonZeroRetOrPassUp: pszName = "NonZeroRetOrPassUp"; break; 4483 case kIemNativeLabelType_RaiseGp0: pszName = "RaiseGp0"; break; 4484 case kIemNativeLabelType_Invalid: break; 4485 case kIemNativeLabelType_End: break; 4486 } 4487 if (fNumbered) 4488 pHlp->pfnPrintf(pHlp, " %s_%u:\n", pszName, pDbgInfo->aEntries[iDbgEntry].Label.uData); 4489 else 4490 pHlp->pfnPrintf(pHlp, " %s:\n", pszName); 4491 continue; 4492 } 4493 4494 case kIemTbDbgEntryType_NativeOffset: 4495 offDbgNativeNext = pDbgInfo->aEntries[iDbgEntry].NativeOffset.offNative; 4496 Assert(offDbgNativeNext > offNative); 4497 break; 4498 4499 default: 4500 AssertFailed(); 4501 } 4502 iDbgEntry++; 4503 break; 4504 } 4505 } 4506 4507 /* 4508 * Disassemble the next native instruction. 4509 */ 4510 uint32_t cbInstr = sizeof(paNative[0]); 4511 int const rc = DISInstr(&paNative[offNative], enmHstCpuMode, &Dis, &cbInstr); 4512 if (RT_SUCCESS(rc)) 4513 { 4514 # if defined(RT_ARCH_AMD64) 4515 if (Dis.pCurInstr->uOpcode == OP_NOP && cbInstr == 7) /* iemNativeEmitMarker */ 4516 { 4517 uint32_t const uInfo = *(uint32_t const *)&Dis.Instr.ab[3]; 4518 if (RT_HIWORD(uInfo) < kIemThreadedFunc_End) 4519 pHlp->pfnPrintf(pHlp, " %p: nop ; marker: call #%u to %s (%u args)\n", 4520 &paNative[offNative], RT_LOWORD(uInfo), g_apszIemThreadedFunctions[RT_HIWORD(uInfo)], 4521 g_acIemThreadedFunctionUsedArgs[RT_HIWORD(uInfo)]); 4522 else 4523 pHlp->pfnPrintf(pHlp, " %p: nop ; unknown marker: %#x (%d)\n", &paNative[offNative], uInfo, uInfo); 4524 } 4525 else 4526 # endif 4527 { 4528 DISFormatYasmEx(&Dis, szDisBuf, sizeof(szDisBuf), 4529 DIS_FMT_FLAGS_BYTES_WIDTH_MAKE(10) | DIS_FMT_FLAGS_BYTES_LEFT 4530 | DIS_FMT_FLAGS_RELATIVE_BRANCH | DIS_FMT_FLAGS_C_HEX, 4531 NULL /*pfnGetSymbol*/, NULL /*pvUser*/); 4532 pHlp->pfnPrintf(pHlp, " %p: %s\n", &paNative[offNative], szDisBuf); 4533 } 4534 } 4535 else 4536 { 4537 # if defined(RT_ARCH_AMD64) 4538 pHlp->pfnPrintf(pHlp, " %p: %.*Rhxs - disassembly failure %Rrc\n", 4539 &paNative[offNative], RT_MIN(cNative - offNative, 16), &paNative[offNative], rc); 4540 # elif defined(RT_ARCH_ARM64) 4541 pHlp->pfnPrintf(pHlp, " %p: %#010RX32 - disassembly failure %Rrc\n", 4542 &paNative[offNative], paNative[offNative], rc); 4543 # else 4544 # error "Port me" 4545 # endif 4546 cbInstr = sizeof(paNative[0]); 4547 } 4548 offNative += cbInstr / sizeof(paNative[0]); 4549 } 4021 4550 } 4022 4551 else 4552 #endif /* IEMNATIVE_WITH_TB_DEBUG_INFO */ 4023 4553 { 4024 4554 /* … … 4045 4575 { 4046 4576 DISFormatYasmEx(&Dis, szDisBuf, sizeof(szDisBuf), 4047 DIS_FMT_FLAGS_BYTES_LEFT | DIS_FMT_FLAGS_RELATIVE_BRANCH, 4577 DIS_FMT_FLAGS_BYTES_WIDTH_MAKE(10) | DIS_FMT_FLAGS_BYTES_LEFT 4578 | DIS_FMT_FLAGS_RELATIVE_BRANCH | DIS_FMT_FLAGS_C_HEX, 4048 4579 NULL /*pfnGetSymbol*/, NULL /*pvUser*/); 4049 pHlp->pfnPrintf(pHlp, " %s\n", szDisBuf); 4050 off += cbInstr; 4580 pHlp->pfnPrintf(pHlp, " %RGp: %s\n", GCPhysPc, szDisBuf); 4581 GCPhysPc += cbInstr; 4582 off += cbInstr; 4051 4583 } 4052 4584 else 4053 4585 { 4054 pHlp->pfnPrintf(pHlp, " % .*Rhxs - disassembly failure %Rrc\n",4055 cbOpcodes - off, &pTb->pabOpcodes[off], rc);4586 pHlp->pfnPrintf(pHlp, " %RGp: %.*Rhxs - disassembly failure %Rrc\n", 4587 GCPhysPc, cbOpcodes - off, &pTb->pabOpcodes[off], rc); 4056 4588 break; 4057 4589 } … … 4060 4592 4061 4593 /* The native code: */ 4062 pHlp->pfnPrintf(pHlp, " Native code %p L %#x\n", pa Instrs, cInstrs);4063 for (uint32_t offNative = 0; offNative < cInstrs;)4594 pHlp->pfnPrintf(pHlp, " Native code %p L %#x\n", paNative, cNative); 4595 while(offNative < cNative) 4064 4596 { 4065 uint32_t cbInstr = sizeof(pa Instrs[0]);4066 int const rc = DISInstr(&pa Instrs[offNative], enmHstCpuMode, &Dis, &cbInstr);4597 uint32_t cbInstr = sizeof(paNative[0]); 4598 int const rc = DISInstr(&paNative[offNative], enmHstCpuMode, &Dis, &cbInstr); 4067 4599 if (RT_SUCCESS(rc)) 4068 4600 { 4069 # if defined(RT_ARCH_AMD64) && 04070 if (Dis.pCurInstr->uOpcode == )4601 # if defined(RT_ARCH_AMD64) 4602 if (Dis.pCurInstr->uOpcode == OP_NOP && cbInstr == 7) /* iemNativeEmitMarker */ 4071 4603 { 4604 uint32_t const uInfo = *(uint32_t const *)&Dis.Instr.ab[3]; 4605 if (RT_HIWORD(uInfo) < kIemThreadedFunc_End) 4606 pHlp->pfnPrintf(pHlp, "\n %p: nop ; marker: call #%u to %s (%u args)\n", 4607 &paNative[offNative], RT_LOWORD(uInfo), g_apszIemThreadedFunctions[RT_HIWORD(uInfo)], 4608 g_acIemThreadedFunctionUsedArgs[RT_HIWORD(uInfo)]); 4609 else 4610 pHlp->pfnPrintf(pHlp, " %p: nop ; unknown marker: %#x (%d)\n", &paNative[offNative], uInfo, uInfo); 4072 4611 } 4073 4612 else … … 4075 4614 { 4076 4615 DISFormatYasmEx(&Dis, szDisBuf, sizeof(szDisBuf), 4077 DIS_FMT_FLAGS_BYTES_LEFT | DIS_FMT_FLAGS_RELATIVE_BRANCH, 4616 DIS_FMT_FLAGS_BYTES_WIDTH_MAKE(10) | DIS_FMT_FLAGS_BYTES_LEFT 4617 | DIS_FMT_FLAGS_RELATIVE_BRANCH | DIS_FMT_FLAGS_C_HEX, 4078 4618 NULL /*pfnGetSymbol*/, NULL /*pvUser*/); 4079 pHlp->pfnPrintf(pHlp, " %p: %s\n", &pa Instrs[offNative], szDisBuf);4619 pHlp->pfnPrintf(pHlp, " %p: %s\n", &paNative[offNative], szDisBuf); 4080 4620 } 4081 4621 } … … 4084 4624 # if defined(RT_ARCH_AMD64) 4085 4625 pHlp->pfnPrintf(pHlp, " %p: %.*Rhxs - disassembly failure %Rrc\n", 4086 &pa Instrs[offNative], RT_MIN(cInstrs - offNative, 16), &paInstrs[offNative], rc);4626 &paNative[offNative], RT_MIN(cNative - offNative, 16), &paNative[offNative], rc); 4087 4627 # elif defined(RT_ARCH_ARM64) 4088 4628 pHlp->pfnPrintf(pHlp, " %p: %#010RX32 - disassembly failure %Rrc\n", 4089 &pa Instrs[offNative], paInstrs[offNative], rc);4629 &paNative[offNative], paNative[offNative], rc); 4090 4630 # else 4091 4631 # error "Port me" 4092 4632 #endif 4093 cbInstr = sizeof(pa Instrs[0]);4633 cbInstr = sizeof(paNative[0]); 4094 4634 } 4095 offNative += cbInstr / sizeof(pa Instrs[0]);4635 offNative += cbInstr / sizeof(paNative[0]); 4096 4636 } 4097 4637 } … … 4133 4673 * Convert the calls to native code. 4134 4674 */ 4675 #ifdef IEMNATIVE_WITH_TB_DEBUG_INFO 4676 int32_t iGstInstr = -1; 4677 uint32_t fExec = pTb->fFlags; 4678 #endif 4135 4679 PCIEMTHRDEDCALLENTRY pCallEntry = pTb->Thrd.paCalls; 4136 4680 uint32_t cCallsLeft = pTb->Thrd.cCalls; 4681 #ifdef LOG_ENABLED 4682 uint32_t const cCallsOrg = cCallsLeft; 4683 #endif 4137 4684 while (cCallsLeft-- > 0) 4138 4685 { 4686 /* 4687 * Debug info and assembly markup. 4688 */ 4689 #ifdef IEMNATIVE_WITH_TB_DEBUG_INFO 4690 if (pCallEntry->enmFunction == kIemThreadedFunc_BltIn_CheckMode) 4691 fExec = pCallEntry->auParams[0]; 4692 iemNativeDbgInfoAddNativeOffset(pReNative, off); 4693 if (iGstInstr < (int32_t)pCallEntry->idxInstr) 4694 { 4695 if (iGstInstr < (int32_t)pTb->cInstructions) 4696 iemNativeDbgInfoAddGuestInstruction(pReNative, fExec); 4697 else 4698 Assert(iGstInstr == pTb->cInstructions); 4699 iGstInstr = pCallEntry->idxInstr; 4700 } 4701 iemNativeDbgInfoAddThreadedCall(pReNative, (IEMTHREADEDFUNCS)pCallEntry->enmFunction); 4702 #endif 4703 4139 4704 #ifdef VBOX_STRICT 4140 4705 off = iemNativeEmitMarker(pReNative, off, RT_MAKE_U32(pTb->Thrd.cCalls - cCallsLeft - 1, pCallEntry->enmFunction)); 4141 4706 AssertReturn(off != UINT32_MAX, pTb); 4142 4707 #endif 4708 /* 4709 * Actual work. 4710 */ 4143 4711 PFNIEMNATIVERECOMPFUNC const pfnRecom = g_apfnIemNativeRecompileFunctions[pCallEntry->enmFunction]; 4144 4712 if (pfnRecom) /** @todo stats on this. */ … … 4152 4720 Assert(pReNative->cCondDepth == 0); 4153 4721 4722 /* 4723 * Advance. 4724 */ 4154 4725 pCallEntry++; 4155 4726 } … … 4236 4807 pTb->Native.cInstructions = off; 4237 4808 pTb->fFlags = (pTb->fFlags & ~IEMTB_F_TYPE_MASK) | IEMTB_F_TYPE_NATIVE; 4809 #ifdef IEMNATIVE_WITH_TB_DEBUG_INFO 4810 pTb->pDbgInfo = (PIEMTBDBG)RTMemDup(pReNative->pDbgInfo, /* non-fatal, so not return check. */ 4811 RT_UOFFSETOF_DYN(IEMTBDBG, aEntries[pReNative->pDbgInfo->cEntries])); 4812 #endif 4238 4813 4239 4814 Assert(pTbAllocator->cThreadedTbs > 0); … … 4247 4822 */ 4248 4823 if (LogIs3Enabled()) 4824 { 4825 Log3(("----------------------------------------- %d calls ---------------------------------------\n", cCallsOrg)); 4249 4826 iemNativeDisassembleTb(pTb, DBGFR3InfoLogHlp()); 4827 } 4250 4828 #endif 4251 4829 -
trunk/src/VBox/VMM/include/IEMInternal.h
r101543 r101547 879 879 { 880 880 kIemTbDbgEntryType_Invalid = 0, 881 /** The entry is for marking a native code position. 882 * Entries following this all apply to this position. */ 883 kIemTbDbgEntryType_NativeOffset, 881 884 /** The entry is for a new guest instruction. */ 882 885 kIemTbDbgEntryType_GuestInstruction, 883 /** Marks the start of a nativecall. */884 kIemTbDbgEntryType_ThreadedCall 1,885 /** 2nd entry for the start of a native call. */886 kIemTbDbgEntryType_ ThreadedCall2,886 /** Marks the start of a threaded call. */ 887 kIemTbDbgEntryType_ThreadedCall, 888 /** Marks the location of a label. */ 889 kIemTbDbgEntryType_Label, 887 890 /** Info about a host register shadowing a guest register. */ 888 kIemTbDbgEntryType_GuestRegShadow ,891 kIemTbDbgEntryType_GuestRegShadowing, 889 892 kIemTbDbgEntryType_End 890 893 } IEMTBDBGENTRYTYPE; … … 908 911 struct 909 912 { 910 /** kIemTbDbgEntryType_GuestInstruction. */911 uint32_t uType : 4;912 /** Index into IEMTB::aRanges. */913 uint32_t idxRange : 4;914 /** Offset relative to the start of the range. */915 uint32_t offOpcodes : 12;916 /** Number of opcode bytes for the instruction. */917 uint32_t cbOpcodes : 4;918 /** Basic CPU mode for the disassembler (low 8 bits IEM_F_XXX). */919 uint32_t fCpuMode : 8;920 } GuestInstruction;921 922 struct923 {924 913 /** kIemTbDbgEntryType_ThreadedCall1. */ 925 914 uint32_t uType : 4; 926 915 /** Native code offset. */ 927 916 uint32_t offNative : 28; 928 } ThreadedCall1;917 } NativeOffset; 929 918 930 919 struct 931 920 { 932 /* kIemTbDbgEntryType_ThreadedCall2. */921 /** kIemTbDbgEntryType_GuestInstruction. */ 933 922 uint32_t uType : 4; 923 uint32_t uUnused : 4; 924 /** The IEM_F_XXX flags. */ 925 uint32_t fExec : 24; 926 } GuestInstruction; 927 928 struct 929 { 930 /* kIemTbDbgEntryType_ThreadedCall. */ 931 uint32_t uType : 4; 932 uint32_t uUnused : 12; 934 933 /** The threaded call number (IEMTHREADEDFUNCS). */ 935 934 uint32_t enmCall : 16; 936 } ThreadedCall 2;935 } ThreadedCall; 937 936 938 937 struct 939 938 { 940 /* kIemTbDbgEntryType_ GuestRegShadow. */939 /* kIemTbDbgEntryType_Label. */ 941 940 uint32_t uType : 4; 942 uint32_t uPadding : 4; 943 /** The host register number. */ 944 uint32_t idxHstReg : 8; 941 uint32_t uUnused : 4; 942 /** The label type (IEMNATIVELABELTYPE). */ 943 uint32_t enmLabel : 8; 944 /** The label data. */ 945 uint32_t uData : 16; 946 } Label; 947 948 struct 949 { 950 /* kIemTbDbgEntryType_GuestRegShadowing. */ 951 uint32_t uType : 4; 952 uint32_t uUnused : 4; 945 953 /** The guest register being shadowed (IEMNATIVEGSTREG). */ 946 uint32_t idxGstReg : 8; 947 uint32_t uUnused : 8; 948 } GuestRegShadow; 954 uint32_t idxGstReg : 8; 955 /** The host new register number, UINT8_MAX if dropped. */ 956 uint32_t idxHstReg : 8; 957 /** The previous host register number, UINT8_MAX if new. */ 958 uint32_t idxHstRegPrev : 8; 959 } GuestRegShadowing; 949 960 } IEMTBDBGENTRY; 950 961 AssertCompileSize(IEMTBDBGENTRY, sizeof(uint32_t)); 962 /** Pointer to a debug info entry. */ 963 typedef IEMTBDBGENTRY *PIEMTBDBGENTRY; 964 /** Pointer to a const debug info entry. */ 965 typedef IEMTBDBGENTRY const *PCIEMTBDBGENTRY; 951 966 952 967 /** … … 957 972 /** Number of entries in aEntries. */ 958 973 uint32_t cEntries; 959 /** Number of entries we've allocated. */960 uint32_t cAllocated;961 974 /** Debug info entries. */ 962 975 RT_FLEXIBLE_ARRAY_EXTENSION -
trunk/src/VBox/VMM/include/IEMN8veRecompiler.h
r101537 r101547 37 37 * @{ 38 38 */ 39 40 /** @def IEMNATIVE_WITH_TB_DEBUG_INFO 41 * Enables generating internal debug info for better TB disassembly dumping. */ 42 #if defined(DEBUG) || defined(DOXYGEN_RUNNING) 43 # define IEMNATIVE_WITH_TB_DEBUG_INFO 44 #endif 45 39 46 40 47 /** @name Stack Frame Layout … … 518 525 PIEMNATIVEFIXUP paFixups; 519 526 527 #ifdef IEMNATIVE_WITH_TB_DEBUG_INFO 528 /** Number of debug info entries allocated for pDbgInfo. */ 529 uint32_t cDbgInfoAlloc; 530 uint32_t uPadding; 531 /** Debug info. */ 532 PIEMTBDBG pDbgInfo; 533 #else 534 uint32_t abPadding1[2]; 535 uintptr_t uPtrPadding2; 536 #endif 537 520 538 /** The translation block being recompiled. */ 521 539 PCIEMTB pTbOrg; … … 586 604 587 605 588 DECLHIDDEN(uint32_t) iemNativeMakeLabel(PIEMRECOMPILERSTATE pReNative, IEMNATIVELABELTYPE enmType, 589 uint32_t offWhere = UINT32_MAX, uint16_t uData = 0) RT_NOEXCEPT; 606 DECLHIDDEN(uint32_t) iemNativeLabelCreate(PIEMRECOMPILERSTATE pReNative, IEMNATIVELABELTYPE enmType, 607 uint32_t offWhere = UINT32_MAX, uint16_t uData = 0) RT_NOEXCEPT; 608 DECLHIDDEN(void) iemNativeLabelDefine(PIEMRECOMPILERSTATE pReNative, uint32_t idxLabel, uint32_t offWhere) RT_NOEXCEPT; 590 609 DECLHIDDEN(bool) iemNativeAddFixup(PIEMRECOMPILERSTATE pReNative, uint32_t offWhere, uint32_t idxLabel, 591 610 IEMNATIVEFIXUPTYPE enmType, int8_t offAddend = 0) RT_NOEXCEPT; … … 1762 1781 pbCodeBuf[off++] = 0xeb; /* jmp rel8 */ 1763 1782 pbCodeBuf[off++] = (uint8_t)offRel; 1764 off++;1765 1783 } 1766 1784 else … … 1810 1828 IEMNATIVELABELTYPE enmLabelType, uint16_t uData = 0) 1811 1829 { 1812 uint32_t const idxLabel = iemNative MakeLabel(pReNative, enmLabelType, UINT32_MAX /*offWhere*/, uData);1830 uint32_t const idxLabel = iemNativeLabelCreate(pReNative, enmLabelType, UINT32_MAX /*offWhere*/, uData); 1813 1831 AssertReturn(idxLabel != UINT32_MAX, UINT32_MAX); 1814 1832 return iemNativeEmitJmpToLabel(pReNative, off, idxLabel); … … 1883 1901 IEMNATIVELABELTYPE enmLabelType, uint16_t uData, IEMNATIVEINSTRCOND enmCond) 1884 1902 { 1885 uint32_t const idxLabel = iemNative MakeLabel(pReNative, enmLabelType, UINT32_MAX /*offWhere*/, uData);1903 uint32_t const idxLabel = iemNativeLabelCreate(pReNative, enmLabelType, UINT32_MAX /*offWhere*/, uData); 1886 1904 AssertReturn(idxLabel != UINT32_MAX, UINT32_MAX); 1887 1905 return iemNativeEmitJccToLabel(pReNative, off, idxLabel, enmCond);
Note:
See TracChangeset
for help on using the changeset viewer.

