VirtualBox

Changeset 101547 in vbox for trunk


Ignore:
Timestamp:
Oct 23, 2023 12:50:37 AM (12 months ago)
Author:
vboxsync
Message:

VMM/IEM: More TB disassembly and TB debuginfo. bugref:10371

Location:
trunk/src/VBox/VMM
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/VMMAll/IEMAllN8veRecompiler.cpp

    r101539 r101547  
    128128*********************************************************************************************************************************/
    129129static uint32_t iemNativeEmitGuestRegValueCheck(PIEMRECOMPILERSTATE pReNative, uint32_t off,
    130                                                 uint8_t idxReg, IEMNATIVEGSTREG enmGstReg);
     130                                                uint8_t idxReg, IEMNATIVEGSTREG enmGstReg) RT_NOEXCEPT;
     131static bool iemNativeDbgInfoAddNativeOffset(PIEMRECOMPILERSTATE pReNative, uint32_t off) RT_NOEXCEPT;
     132static bool iemNativeDbgInfoAddLabel(PIEMRECOMPILERSTATE pReNative, IEMNATIVELABELTYPE enmType, uint16_t uData) RT_NOEXCEPT;
    131133
    132134
     
    15801582    pReNative->bmLabelTypes           = 0;
    15811583    pReNative->cFixups                = 0;
     1584#ifdef IEMNATIVE_WITH_TB_DEBUG_INFO
     1585    pReNative->pDbgInfo->cEntries     = 0;
     1586#endif
    15821587    pReNative->pTbOrg                 = pTb;
    15831588
     
    16521657    pReNative->paLabels  = (PIEMNATIVELABEL)RTMemAllocZ(sizeof(IEMNATIVELABEL) * _8K);
    16531658    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
    16541662    if (RT_LIKELY(   pReNative->pInstrBuf
    16551663                  && pReNative->paLabels
    1656                   && pReNative->paFixups))
     1664                  && pReNative->paFixups)
     1665#ifdef IEMNATIVE_WITH_TB_DEBUG_INFO
     1666        && pReNative->pDbgInfo
     1667#endif
     1668       )
    16571669    {
    16581670        /*
     
    16621674        pReNative->cLabelsAlloc   = _8K;
    16631675        pReNative->cFixupsAlloc   = _16K;
     1676#ifdef IEMNATIVE_WITH_TB_DEBUG_INFO
     1677        pReNative->cDbgInfoAlloc  = _16K;
     1678#endif
    16641679
    16651680        /*
     
    16771692    RTMemFree(pReNative->paLabels);
    16781693    RTMemFree(pReNative->paFixups);
     1694#ifdef IEMNATIVE_WITH_TB_DEBUG_INFO
     1695    RTMemFree(pReNative->pDbgInfo);
     1696#endif
    16791697    RTMemFree(pReNative);
    16801698    return NULL;
     
    16831701
    16841702/**
    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.
    16861707 *
    16871708 * @returns Label ID.
     
    16931714 *                      certain type of labels. Default is zero.
    16941715 */
    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?
     1716DECLHIDDEN(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.
    17001724     */
    17011725    PIEMNATIVELABEL paLabels = pReNative->paLabels;
    17021726    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)
    17101739            {
    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);
    17121745                return i;
    17131746            }
    1714         }
     1747    }
    17151748
    17161749    /*
     
    17421775    Assert(enmType >= 0 && enmType < 64);
    17431776    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    }
    17441785    return cLabels;
    17451786}
     
    17471788
    17481789/**
     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 */
     1796DECLHIDDEN(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/**
    17491810 * Looks up a lable.
    17501811 *
    17511812 * @returns Label ID if found, UINT32_MAX if not.
    17521813 */
    1753 static uint32_t iemNativeFindLabel(PIEMRECOMPILERSTATE pReNative, IEMNATIVELABELTYPE enmType,
     1814static uint32_t iemNativeLabelFind(PIEMRECOMPILERSTATE pReNative, IEMNATIVELABELTYPE enmType,
    17541815                                   uint32_t offWhere = UINT32_MAX, uint16_t uData = 0) RT_NOEXCEPT
    17551816{
     
    18461907}
    18471908
     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 */
     1915DECL_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 */
     1930DECLINLINE(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 */
     1946static 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 */
     1979static 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 */
     1996static 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 */
     2012static 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 */
     2028static 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 */
    18482044
    18492045
     
    22512447 */
    22522448DECL_FORCE_INLINE(void)
    2253 iemNativeRegMarkAsGstRegShadow(PIEMRECOMPILERSTATE pReNative, uint8_t idxHstReg, IEMNATIVEGSTREG enmGstReg)
     2449iemNativeRegMarkAsGstRegShadow(PIEMRECOMPILERSTATE pReNative, uint8_t idxHstReg, IEMNATIVEGSTREG enmGstReg, uint32_t off)
    22542450{
    22552451    Assert(!(pReNative->bmGstRegShadows & RT_BIT_64(enmGstReg)));
     
    22592455    pReNative->bmGstRegShadows                   |= RT_BIT_64(enmGstReg);
    22602456    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
    22612463}
    22622464
     
    22682470 */
    22692471DECL_FORCE_INLINE(void)
    2270 iemNativeRegClearGstRegShadowing(PIEMRECOMPILERSTATE pReNative, uint8_t idxHstReg)
     2472iemNativeRegClearGstRegShadowing(PIEMRECOMPILERSTATE pReNative, uint8_t idxHstReg, uint32_t off)
    22712473{
    22722474    Assert(   (pReNative->bmGstRegShadows & pReNative->aHstRegs[idxHstReg].fGstRegShadows)
     
    22752477           == RT_BOOL(pReNative->aHstRegs[idxHstReg].fGstRegShadows));
    22762478
     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
    22772495    pReNative->bmHstRegsWithGstShadow            &= ~RT_BIT_32(idxHstReg);
    22782496    pReNative->bmGstRegShadows                   &= ~pReNative->aHstRegs[idxHstReg].fGstRegShadows;
     
    22862504 */
    22872505DECL_FORCE_INLINE(void)
    2288 iemNativeRegTransferGstRegShadowing(PIEMRECOMPILERSTATE pReNative, uint8_t idxRegFrom, uint8_t idxRegTo, IEMNATIVEGSTREG enmGstReg)
     2506iemNativeRegTransferGstRegShadowing(PIEMRECOMPILERSTATE pReNative, uint8_t idxRegFrom, uint8_t idxRegTo,
     2507                                    IEMNATIVEGSTREG enmGstReg, uint32_t off)
    22892508{
    22902509    Assert(pReNative->aHstRegs[idxRegFrom].fGstRegShadows & RT_BIT_64(enmGstReg));
     
    22972516    pReNative->aHstRegs[idxRegTo].fGstRegShadows    = RT_BIT_64(enmGstReg);
    22982517    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
    22992524}
    23002525
     
    23892614                else
    23902615                {
    2391                     iemNativeRegClearGstRegShadowing(pReNative, idxReg);
     2616                    iemNativeRegClearGstRegShadowing(pReNative, idxReg, *poff);
    23922617                    Log12(("iemNativeRegAllocTmpForGuestReg: Grabbing %s for guest %s - destructive calc\n",
    23932618                           g_apszIemNativeHstRegNames[idxReg], g_aGstShadowInfo[enmGstReg].pszName));
     
    24182643            else
    24192644            {
    2420                 iemNativeRegTransferGstRegShadowing(pReNative, idxReg, idxRegNew, enmGstReg);
     2645                iemNativeRegTransferGstRegShadowing(pReNative, idxReg, idxRegNew, enmGstReg, *poff);
    24212646                Log12(("iemNativeRegAllocTmpForGuestReg: Moved %s for guest %s into %s for update\n",
    24222647                       g_apszIemNativeHstRegNames[idxReg], g_aGstShadowInfo[enmGstReg].pszName,
     
    24472672
    24482673    if (enmIntendedUse != kIemNativeGstRegUse_Calculation)
    2449         iemNativeRegMarkAsGstRegShadow(pReNative, idxRegNew, enmGstReg);
     2674        iemNativeRegMarkAsGstRegShadow(pReNative, idxRegNew, enmGstReg, off);
    24502675    Log12(("iemNativeRegAllocTmpForGuestReg: Allocated %s for guest %s %s\n",
    24512676           g_apszIemNativeHstRegNames[idxRegNew], g_aGstShadowInfo[enmGstReg].pszName, s_pszIntendedUse[enmIntendedUse]));
     
    28593084 */
    28603085static uint32_t iemNativeEmitGuestRegValueCheck(PIEMRECOMPILERSTATE pReNative, uint32_t off,
    2861                                                 uint8_t idxReg, IEMNATIVEGSTREG enmGstReg)
     3086                                                uint8_t idxReg, IEMNATIVEGSTREG enmGstReg) RT_NOEXCEPT
    28623087{
    28633088# ifdef RT_ARCH_AMD64
     
    30133238    pu32CodeBuf[off++] = Armv8A64MkInstrOrr(ARMV8_A64_REG_X4, ARMV8_A64_REG_X3, ARMV8_A64_REG_X0, false /*f64Bit*/);
    30143239
    3015     uint32_t const idxLabel = iemNativeMakeLabel(pReNative, kIemNativeLabelType_NonZeroRetOrPassUp);
     3240    uint32_t const idxLabel = iemNativeLabelCreate(pReNative, kIemNativeLabelType_NonZeroRetOrPassUp);
    30163241    AssertReturn(idxLabel != UINT32_MAX, UINT32_MAX);
    30173242    AssertReturn(iemNativeAddFixup(pReNative, off, idxLabel, kIemNativeFixupType_RelImm19At5), UINT32_MAX);
     
    33013526static uint32_t iemNativeEmitRaiseGp0(PIEMRECOMPILERSTATE pReNative, uint32_t off)
    33023527{
    3303     uint32_t idxLabel = iemNativeFindLabel(pReNative, kIemNativeLabelType_RaiseGp0);
     3528    uint32_t const idxLabel = iemNativeLabelFind(pReNative, kIemNativeLabelType_RaiseGp0);
    33043529    if (idxLabel != UINT32_MAX)
    33053530    {
    3306         Assert(pReNative->paLabels[idxLabel].off == UINT32_MAX);
    3307         pReNative->paLabels[idxLabel].off = off;
     3531        iemNativeLabelDefine(pReNative, idxLabel, off);
    33083532
    33093533        /* iemNativeHlpExecRaiseGp0(PVMCPUCC pVCpu, uint8_t idxInstr) */
     
    33153539
    33163540        /* jump back to the return sequence. */
    3317         off = iemNativeEmitJmpToLabel(pReNative, off, iemNativeFindLabel(pReNative, kIemNativeLabelType_Return));
     3541        off = iemNativeEmitJmpToLabel(pReNative, off, iemNativeLabelFind(pReNative, kIemNativeLabelType_Return));
    33183542    }
    33193543    return off;
     
    33293553     * Generate the rc + rcPassUp fiddling code if needed.
    33303554     */
    3331     uint32_t idxLabel = iemNativeFindLabel(pReNative, kIemNativeLabelType_NonZeroRetOrPassUp);
     3555    uint32_t const idxLabel = iemNativeLabelFind(pReNative, kIemNativeLabelType_NonZeroRetOrPassUp);
    33323556    if (idxLabel != UINT32_MAX)
    33333557    {
    3334         Assert(pReNative->paLabels[idxLabel].off == UINT32_MAX);
    3335         pReNative->paLabels[idxLabel].off = off;
     3558        iemNativeLabelDefine(pReNative, idxLabel, off);
    33363559
    33373560        /* iemNativeHlpExecStatusCodeFiddling(PVMCPUCC pVCpu, int rc, uint8_t idxInstr) */
     
    33813604     * Define label for common return point.
    33823605     */
    3383     uint32_t const idxReturn = iemNativeMakeLabel(pReNative, kIemNativeLabelType_Return, off);
     3606    uint32_t const idxReturn = iemNativeLabelCreate(pReNative, kIemNativeLabelType_Return, off);
    33843607    AssertReturn(idxReturn != UINT32_MAX, UINT32_MAX);
    33853608
     
    38534076    uint16_t const uCondSeqNo = ++pReNative->uCondSeqNo;
    38544077    pEntry->fInElse       = false;
    3855     pEntry->idxLabelElse  = iemNativeMakeLabel(pReNative, kIemNativeLabelType_Else, UINT32_MAX /*offWhere*/, uCondSeqNo);
     4078    pEntry->idxLabelElse  = iemNativeLabelCreate(pReNative, kIemNativeLabelType_Else, UINT32_MAX /*offWhere*/, uCondSeqNo);
    38564079    AssertReturn(pEntry->idxLabelElse != UINT32_MAX, NULL);
    3857     pEntry->idxLabelEndIf = iemNativeMakeLabel(pReNative, kIemNativeLabelType_Endif, UINT32_MAX /*offWhere*/, uCondSeqNo);
     4080    pEntry->idxLabelEndIf = iemNativeLabelCreate(pReNative, kIemNativeLabelType_Endif, UINT32_MAX /*offWhere*/, uCondSeqNo);
    38584081    AssertReturn(pEntry->idxLabelEndIf != UINT32_MAX, NULL);
    38594082
     
    38804103
    38814104    /* 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);
    38834106    pEntry->fInElse = true;
    38844107
     
    39014124    /* Define the endif label and maybe the else one if we're still in the 'if' part. */
    39024125    if (!pEntry->fInElse)
    3903         pReNative->paLabels[pEntry->idxLabelElse].off = off;
     4126        iemNativeLabelDefine(pReNative, pEntry->idxLabelElse, off);
    39044127    else
    39054128        Assert(pReNative->paLabels[pEntry->idxLabelElse].off <= off);
    3906     pReNative->paLabels[pEntry->idxLabelEndIf].off    = off;
     4129    iemNativeLabelDefine(pReNative, pEntry->idxLabelEndIf, off);
    39074130
    39084131    /* Pop the conditional stack.*/
     
    39894212
    39904213
     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 */
     4221const 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
    39914303
    39924304void iemNativeDisassembleTb(PCIEMTB pTb, PCDBGFINFOHLP pHlp)
     
    39964308    char                    szDisBuf[512];
    39974309    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
    40004314    PCIEMTBDBG const        pDbgInfo      = pTb->pDbgInfo;
     4315#endif
    40014316    DISCPUMODE              enmGstCpuMode = (pTb->fFlags & IEM_F_MODE_CPUMODE_MASK) == IEMMODE_16BIT ? DISCPUMODE_16BIT
    40024317                                          : (pTb->fFlags & IEM_F_MODE_CPUMODE_MASK) == IEMMODE_32BIT ? DISCPUMODE_32BIT
     
    40104325#endif
    40114326
     4327    /*
     4328     * Print TB info.
     4329     */
    40124330    pHlp->pfnPrintf(pHlp,
    40134331                    "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",
    40154333                    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        }
    40214550    }
    40224551    else
     4552#endif /* IEMNATIVE_WITH_TB_DEBUG_INFO */
    40234553    {
    40244554        /*
     
    40454575                {
    40464576                    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,
    40484579                                    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;
    40514583                }
    40524584                else
    40534585                {
    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);
    40564588                    break;
    40574589                }
     
    40604592
    40614593        /* The native code: */
    4062         pHlp->pfnPrintf(pHlp, "  Native code %p L %#x\n", paInstrs, 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)
    40644596        {
    4065             uint32_t  cbInstr = sizeof(paInstrs[0]);
    4066             int const rc      = DISInstr(&paInstrs[offNative], enmHstCpuMode, &Dis, &cbInstr);
     4597            uint32_t  cbInstr = sizeof(paNative[0]);
     4598            int const rc      = DISInstr(&paNative[offNative], enmHstCpuMode, &Dis, &cbInstr);
    40674599            if (RT_SUCCESS(rc))
    40684600            {
    4069 # if defined(RT_ARCH_AMD64) && 0
    4070                 if (Dis.pCurInstr->uOpcode == )
     4601# if defined(RT_ARCH_AMD64)
     4602                if (Dis.pCurInstr->uOpcode == OP_NOP && cbInstr == 7) /* iemNativeEmitMarker */
    40714603                {
     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);
    40724611                }
    40734612                else
     
    40754614                {
    40764615                    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,
    40784618                                    NULL /*pfnGetSymbol*/, NULL /*pvUser*/);
    4079                     pHlp->pfnPrintf(pHlp, "    %p: %s\n", &paInstrs[offNative], szDisBuf);
     4619                    pHlp->pfnPrintf(pHlp, "    %p: %s\n", &paNative[offNative], szDisBuf);
    40804620                }
    40814621            }
     
    40844624# if defined(RT_ARCH_AMD64)
    40854625                pHlp->pfnPrintf(pHlp, "    %p:  %.*Rhxs - disassembly failure %Rrc\n",
    4086                                 &paInstrs[offNative], RT_MIN(cInstrs - offNative, 16), &paInstrs[offNative], rc);
     4626                                &paNative[offNative], RT_MIN(cNative - offNative, 16), &paNative[offNative], rc);
    40874627# elif defined(RT_ARCH_ARM64)
    40884628                pHlp->pfnPrintf(pHlp, "    %p:  %#010RX32 - disassembly failure %Rrc\n",
    4089                                 &paInstrs[offNative], paInstrs[offNative], rc);
     4629                                &paNative[offNative], paNative[offNative], rc);
    40904630# else
    40914631#  error "Port me"
    40924632#endif
    4093                 cbInstr = sizeof(paInstrs[0]);
     4633                cbInstr = sizeof(paNative[0]);
    40944634            }
    4095             offNative += cbInstr / sizeof(paInstrs[0]);
     4635            offNative += cbInstr / sizeof(paNative[0]);
    40964636        }
    40974637    }
     
    41334673     * Convert the calls to native code.
    41344674     */
     4675#ifdef IEMNATIVE_WITH_TB_DEBUG_INFO
     4676    int32_t              iGstInstr  = -1;
     4677    uint32_t             fExec      = pTb->fFlags;
     4678#endif
    41354679    PCIEMTHRDEDCALLENTRY pCallEntry = pTb->Thrd.paCalls;
    41364680    uint32_t             cCallsLeft = pTb->Thrd.cCalls;
     4681#ifdef LOG_ENABLED
     4682    uint32_t const       cCallsOrg  = cCallsLeft;
     4683#endif
    41374684    while (cCallsLeft-- > 0)
    41384685    {
     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
    41394704#ifdef VBOX_STRICT
    41404705        off = iemNativeEmitMarker(pReNative, off, RT_MAKE_U32(pTb->Thrd.cCalls - cCallsLeft - 1, pCallEntry->enmFunction));
    41414706        AssertReturn(off != UINT32_MAX, pTb);
    41424707#endif
     4708        /*
     4709         * Actual work.
     4710         */
    41434711        PFNIEMNATIVERECOMPFUNC const pfnRecom = g_apfnIemNativeRecompileFunctions[pCallEntry->enmFunction];
    41444712        if (pfnRecom) /** @todo stats on this.   */
     
    41524720        Assert(pReNative->cCondDepth == 0);
    41534721
     4722        /*
     4723         * Advance.
     4724         */
    41544725        pCallEntry++;
    41554726    }
     
    42364807    pTb->Native.cInstructions   = off;
    42374808    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
    42384813
    42394814    Assert(pTbAllocator->cThreadedTbs > 0);
     
    42474822     */
    42484823    if (LogIs3Enabled())
     4824    {
     4825        Log3(("----------------------------------------- %d calls ---------------------------------------\n", cCallsOrg));
    42494826        iemNativeDisassembleTb(pTb, DBGFR3InfoLogHlp());
     4827    }
    42504828#endif
    42514829
  • trunk/src/VBox/VMM/include/IEMInternal.h

    r101543 r101547  
    879879{
    880880    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,
    881884    /** The entry is for a new guest instruction. */
    882885    kIemTbDbgEntryType_GuestInstruction,
    883     /** Marks the start of a native call. */
    884     kIemTbDbgEntryType_ThreadedCall1,
    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,
    887890    /** Info about a host register shadowing a guest register. */
    888     kIemTbDbgEntryType_GuestRegShadow,
     891    kIemTbDbgEntryType_GuestRegShadowing,
    889892    kIemTbDbgEntryType_End
    890893} IEMTBDBGENTRYTYPE;
     
    908911    struct
    909912    {
    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     struct
    923     {
    924913        /** kIemTbDbgEntryType_ThreadedCall1. */
    925914        uint32_t    uType      : 4;
    926915        /** Native code offset. */
    927916        uint32_t    offNative  : 28;
    928     } ThreadedCall1;
     917    } NativeOffset;
    929918
    930919    struct
    931920    {
    932         /* kIemTbDbgEntryType_ThreadedCall2. */
     921        /** kIemTbDbgEntryType_GuestInstruction. */
    933922        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;
    934933        /** The threaded call number (IEMTHREADEDFUNCS). */
    935934        uint32_t    enmCall    : 16;
    936     } ThreadedCall2;
     935    } ThreadedCall;
    937936
    938937    struct
    939938    {
    940         /* kIemTbDbgEntryType_GuestRegShadow. */
     939        /* kIemTbDbgEntryType_Label. */
    941940        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;
    945953        /** 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;
    949960} IEMTBDBGENTRY;
    950961AssertCompileSize(IEMTBDBGENTRY, sizeof(uint32_t));
     962/** Pointer to a debug info entry. */
     963typedef IEMTBDBGENTRY *PIEMTBDBGENTRY;
     964/** Pointer to a const debug info entry. */
     965typedef IEMTBDBGENTRY const *PCIEMTBDBGENTRY;
    951966
    952967/**
     
    957972    /** Number of entries in aEntries. */
    958973    uint32_t        cEntries;
    959     /** Number of entries we've allocated. */
    960     uint32_t        cAllocated;
    961974    /** Debug info entries. */
    962975    RT_FLEXIBLE_ARRAY_EXTENSION
  • trunk/src/VBox/VMM/include/IEMN8veRecompiler.h

    r101537 r101547  
    3737 * @{
    3838 */
     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
    3946
    4047/** @name Stack Frame Layout
     
    518525    PIEMNATIVEFIXUP             paFixups;
    519526
     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
    520538    /** The translation block being recompiled. */
    521539    PCIEMTB                     pTbOrg;
     
    586604
    587605
    588 DECLHIDDEN(uint32_t)        iemNativeMakeLabel(PIEMRECOMPILERSTATE pReNative, IEMNATIVELABELTYPE enmType,
    589                                                uint32_t offWhere = UINT32_MAX, uint16_t uData = 0) RT_NOEXCEPT;
     606DECLHIDDEN(uint32_t)        iemNativeLabelCreate(PIEMRECOMPILERSTATE pReNative, IEMNATIVELABELTYPE enmType,
     607                                                 uint32_t offWhere = UINT32_MAX, uint16_t uData = 0) RT_NOEXCEPT;
     608DECLHIDDEN(void)            iemNativeLabelDefine(PIEMRECOMPILERSTATE pReNative, uint32_t idxLabel, uint32_t offWhere) RT_NOEXCEPT;
    590609DECLHIDDEN(bool)            iemNativeAddFixup(PIEMRECOMPILERSTATE pReNative, uint32_t offWhere, uint32_t idxLabel,
    591610                                              IEMNATIVEFIXUPTYPE enmType, int8_t offAddend = 0) RT_NOEXCEPT;
     
    17621781            pbCodeBuf[off++] = 0xeb;                /* jmp rel8 */
    17631782            pbCodeBuf[off++] = (uint8_t)offRel;
    1764             off++;
    17651783        }
    17661784        else
     
    18101828                                                IEMNATIVELABELTYPE enmLabelType, uint16_t uData = 0)
    18111829{
    1812     uint32_t const idxLabel = iemNativeMakeLabel(pReNative, enmLabelType, UINT32_MAX /*offWhere*/, uData);
     1830    uint32_t const idxLabel = iemNativeLabelCreate(pReNative, enmLabelType, UINT32_MAX /*offWhere*/, uData);
    18131831    AssertReturn(idxLabel != UINT32_MAX, UINT32_MAX);
    18141832    return iemNativeEmitJmpToLabel(pReNative, off, idxLabel);
     
    18831901                                                IEMNATIVELABELTYPE enmLabelType, uint16_t uData, IEMNATIVEINSTRCOND enmCond)
    18841902{
    1885     uint32_t const idxLabel = iemNativeMakeLabel(pReNative, enmLabelType, UINT32_MAX /*offWhere*/, uData);
     1903    uint32_t const idxLabel = iemNativeLabelCreate(pReNative, enmLabelType, UINT32_MAX /*offWhere*/, uData);
    18861904    AssertReturn(idxLabel != UINT32_MAX, UINT32_MAX);
    18871905    return iemNativeEmitJccToLabel(pReNative, off, idxLabel, enmCond);
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette