VirtualBox

Changeset 101172 in vbox for trunk/src/VBox/VMM/VMMAll


Ignore:
Timestamp:
Sep 19, 2023 3:14:43 PM (15 months ago)
Author:
vboxsync
Message:

VMM/IEM: Made the native recompiler work for win.amd64 debug builds. bugref:10370

File:
1 edited

Legend:

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

    r101163 r101172  
    5959#include <iprt/mem.h>
    6060#include <iprt/string.h>
     61
    6162#ifdef RT_OS_WINDOWS
    62 /** @todo */
     63# include <iprt/formats/pecoff.h> /* this is incomaptible with windows.h, thus: */
     64extern "C" DECLIMPORT(uint8_t) __cdecl RtlAddFunctionTable(void *pvFunctionTable, uint32_t cEntries, uintptr_t uBaseAddress);
     65extern "C" DECLIMPORT(uint8_t) __cdecl RtlDelFunctionTable(void *pvFunctionTable);
    6366#else
    6467# include <iprt/formats/dwarf.h>
    65 extern "C" void __register_frame_info(void *begin, void *ob);
     68extern "C" void __register_frame_info(void *begin, void *ob); /* found no header for these two */
    6669#endif
    6770
     
    8689# error The setjmp approach must be enabled for the recompiler.
    8790#endif
     91
     92
     93/*********************************************************************************************************************************
     94*   Defined Constants And Macros                                                                                                 *
     95*********************************************************************************************************************************/
     96/** @name Stack Frame Layout
     97 *
     98 * @{  */
     99/** The size of the area for stack variables and spills and stuff. */
     100#define IEMNATIVE_FRAME_VAR_SIZE            0x40
     101#ifdef RT_ARCH_AMD64
     102/** Number of stack arguments slots for calls made from the frame. */
     103# define IEMNATIVE_FRAME_STACK_ARG_COUNT    4
     104/** An stack alignment adjustment (between non-volatile register pushes and
     105 *  the stack variable area, so the latter better aligned). */
     106# define IEMNATIVE_FRAME_ALIGN_SIZE         8
     107/** Number of any shadow arguments (spill area) for calls we make. */
     108# ifdef RT_OS_WINDOWS
     109#  define IEMNATIVE_FRAME_SHADOW_ARG_COUNT  4
     110# else
     111#  define IEMNATIVE_FRAME_SHADOW_ARG_COUNT  0
     112# endif
     113
     114/** Frame pointer (RBP) relative offset of the last push. */
     115# ifdef RT_OS_WINDOWS
     116#  define IEMNATIVE_FP_OFF_LAST_PUSH        (7 * -8)
     117# else
     118#  define IEMNATIVE_FP_OFF_LAST_PUSH        (5 * -8)
     119# endif
     120/** Frame pointer (RBP) relative offset of the stack variable area (the lowest
     121 * address for it). */
     122# define IEMNATIVE_FP_OFF_STACK_VARS        (IEMNATIVE_FP_OFF_LAST_PUSH - IEMNATIVE_FRAME_ALIGN_SIZE - IEMNATIVE_FRAME_VAR_SIZE)
     123/** Frame pointer (RBP) relative offset of the first stack argument for calls. */
     124# define IEMNATIVE_FP_OFF_STACK_ARG0        (IEMNATIVE_FP_OFF_STACK_VARS - IEMNATIVE_FRAME_STACK_ARG_COUNT * 8)
     125/** Frame pointer (RBP) relative offset of the second stack argument for calls. */
     126# define IEMNATIVE_FP_OFF_STACK_ARG1        (IEMNATIVE_FP_OFF_STACK_ARG0 + 8)
     127/** Frame pointer (RBP) relative offset of the third stack argument for calls. */
     128# define IEMNATIVE_FP_OFF_STACK_ARG2        (IEMNATIVE_FP_OFF_STACK_ARG0 + 16)
     129/** Frame pointer (RBP) relative offset of the fourth stack argument for calls. */
     130# define IEMNATIVE_FP_OFF_STACK_ARG3        (IEMNATIVE_FP_OFF_STACK_ARG0 + 24)
     131
     132# ifdef RT_OS_WINDOWS
     133/** Frame pointer (RBP) relative offset of the first incoming shadow argument. */
     134#  define IEMNATIVE_FP_OFF_IN_SHADOW_ARG0   (16)
     135/** Frame pointer (RBP) relative offset of the second incoming shadow argument. */
     136#  define IEMNATIVE_FP_OFF_IN_SHADOW_ARG1   (24)
     137/** Frame pointer (RBP) relative offset of the third incoming shadow argument. */
     138#  define IEMNATIVE_FP_OFF_IN_SHADOW_ARG2   (32)
     139/** Frame pointer (RBP) relative offset of the fourth incoming shadow argument. */
     140#  define IEMNATIVE_FP_OFF_IN_SHADOW_ARG3   (40)
     141# endif
     142
     143#elif RT_ARCH_ARM64
     144
     145#else
     146# error "port me"
     147#endif
     148/** @} */
    88149
    89150
     
    118179    /** Pointer to the chunk. */
    119180    void                   *pvChunk;
    120 #if defined(IN_RING3) && !defined(RT_OS_WINDOWS)
     181#ifdef IN_RING3
     182# ifdef RT_OS_WINDOWS
     183    /** Pointer to the unwind information.  This is allocated from hHeap on
     184     *  windows because (at least for AMD64) the UNWIND_INFO structure address
     185     *  in the RUNTIME_FUNCTION entry is an RVA and the chunk is the "image".  */
     186    void                   *pvUnwindInfo;
     187# else
    121188    /** Exception handling frame information for proper unwinding during C++
    122189     *  throws and (possibly) longjmp(). */
    123190    PIEMEXECMEMCHUNKEHFRAME pEhFrame;
    124 #endif
    125 #ifdef IN_RING0
     191# endif
     192#elif defined(IN_RING0)
    126193    /** Allocation handle. */
    127194    RTR0MEMOBJ              hMemObj;
     
    171238    /** @} */
    172239
    173 #if defined(IN_RING3) && defined(RT_OS_WINDOWS) && (defined(RT_ARCH_AMD64) || defined(RT_ARCH_ARM64))
    174     PRUNTIME_FUNCTION       paUnwindFunctions;
    175 #endif
    176 
    177240    /** The allocation chunks. */
    178241    RT_FLEXIBLE_ARRAY_EXTENSION
     
    186249
    187250
    188 #if defined(IN_RING3) && !defined(RT_OS_WINDOWS)
     251#ifdef IN_RING3
     252# ifdef RT_OS_WINDOWS
     253
     254/**
     255 * Initializes the unwind info structures for windows hosts.
     256 */
     257static void *iemExecMemAllocatorInitAndRegisterUnwindInfoForChunk(PIEMEXECMEMALLOCATOR pExecMemAllocator,
     258                                                                  RTHEAPSIMPLE hHeap, void *pvChunk)
     259{
     260    /*
     261     * The AMD64 unwind opcodes.
     262     *
     263     * This is a program that starts with RSP after a RET instruction that
     264     * ends up in recompiled code, and the operations we describe here will
     265     * restore all non-volatile registers and bring RSP back to where our
     266     * RET address is.  This means it's reverse order from what happens in
     267     * the prologue.
     268     *
     269     * Note! Using a frame register approach here both because we have one
     270     *       and but mainly because the UWOP_ALLOC_LARGE argument values
     271     *       would be a pain to write initializers for.  On the positive
     272     *       side, we're impervious to changes in the the stack variable
     273     *       area can can deal with dynamic stack allocations if necessary.
     274     */
     275    static const IMAGE_UNWIND_CODE s_aOpcodes[] =
     276    {
     277        { { 16, IMAGE_AMD64_UWOP_SET_FPREG,     0 } },              /* RSP  = RBP - FrameOffset * 10 (0x60) */
     278        { { 16, IMAGE_AMD64_UWOP_ALLOC_SMALL,   0 } },              /* RSP += 8; */
     279        { { 14, IMAGE_AMD64_UWOP_PUSH_NONVOL,   X86_GREG_x15 } },   /* R15  = [RSP]; RSP += 8; */
     280        { { 12, IMAGE_AMD64_UWOP_PUSH_NONVOL,   X86_GREG_x14 } },   /* R14  = [RSP]; RSP += 8; */
     281        { { 10, IMAGE_AMD64_UWOP_PUSH_NONVOL,   X86_GREG_x13 } },   /* R13  = [RSP]; RSP += 8; */
     282        { {  8, IMAGE_AMD64_UWOP_PUSH_NONVOL,   X86_GREG_x12 } },   /* R12  = [RSP]; RSP += 8; */
     283        { {  7, IMAGE_AMD64_UWOP_PUSH_NONVOL,   X86_GREG_xDI } },   /* RDI  = [RSP]; RSP += 8; */
     284        { {  6, IMAGE_AMD64_UWOP_PUSH_NONVOL,   X86_GREG_xSI } },   /* RSI  = [RSP]; RSP += 8; */
     285        { {  5, IMAGE_AMD64_UWOP_PUSH_NONVOL,   X86_GREG_xBX } },   /* RBX  = [RSP]; RSP += 8; */
     286        { {  4, IMAGE_AMD64_UWOP_PUSH_NONVOL,   X86_GREG_xBP } },   /* RBP  = [RSP]; RSP += 8; */
     287    };
     288    union
     289    {
     290        IMAGE_UNWIND_INFO Info;
     291        uint8_t abPadding[RT_UOFFSETOF(IMAGE_UNWIND_INFO, aOpcodes) + 16];
     292    } s_UnwindInfo =
     293    {
     294        {
     295            /* .Version = */        1,
     296            /* .Flags = */          0,
     297            /* .SizeOfProlog = */   16, /* whatever */
     298            /* .CountOfCodes = */   RT_ELEMENTS(s_aOpcodes),
     299            /* .FrameRegister = */  X86_GREG_xBP,
     300            /* .FrameOffset = */    (-IEMNATIVE_FP_OFF_LAST_PUSH + 8) / 16 /* we're off by one slot. sigh. */,
     301        }
     302    };
     303    AssertCompile(-IEMNATIVE_FP_OFF_LAST_PUSH < 240 && -IEMNATIVE_FP_OFF_LAST_PUSH > 0);
     304    AssertCompile((-IEMNATIVE_FP_OFF_LAST_PUSH & 0xf) == 8);
     305
     306    /*
     307     * Calc how much space we need and allocate it off the exec heap.
     308     */
     309    unsigned const cFunctionEntries = 1;
     310    unsigned const cbUnwindInfo     = sizeof(s_aOpcodes) + RT_UOFFSETOF(IMAGE_UNWIND_INFO, aOpcodes);
     311    unsigned const cbNeeded         = sizeof(IMAGE_RUNTIME_FUNCTION_ENTRY) * cFunctionEntries + cbUnwindInfo;
     312    unsigned const cbNeededAligned  = RT_ALIGN_32(cbNeeded + pExecMemAllocator->cbHeapBlockHdr, 64)
     313                                    - pExecMemAllocator->cbHeapBlockHdr;
     314
     315    PIMAGE_RUNTIME_FUNCTION_ENTRY const paFunctions = (PIMAGE_RUNTIME_FUNCTION_ENTRY)RTHeapSimpleAlloc(hHeap, cbNeededAligned,
     316                                                                                                       32 /*cbAlignment*/);
     317    AssertReturn(paFunctions, NULL);
     318
     319    /*
     320     * Initialize the structures.
     321     */
     322    PIMAGE_UNWIND_INFO const pInfo = (PIMAGE_UNWIND_INFO)&paFunctions[cFunctionEntries];
     323
     324    paFunctions[0].BeginAddress         = 0;
     325    paFunctions[0].EndAddress           = pExecMemAllocator->cbChunk;
     326    paFunctions[0].UnwindInfoAddress    = (uint32_t)((uintptr_t)pInfo - (uintptr_t)pvChunk);
     327
     328    memcpy(pInfo, &s_UnwindInfo, RT_UOFFSETOF(IMAGE_UNWIND_INFO, aOpcodes));
     329    memcpy(&pInfo->aOpcodes[0], s_aOpcodes, sizeof(s_aOpcodes));
     330
     331    /*
     332     * Register it.
     333     */
     334    uint8_t fRet = RtlAddFunctionTable(paFunctions, cFunctionEntries, (uintptr_t)pvChunk);
     335    AssertReturn(fRet, NULL); /* Nothing to clean up on failure, since its within the chunk itself. */
     336
     337    return paFunctions;
     338}
     339
     340
     341# else /* !RT_OS_WINDOWS */
    189342
    190343/**
     
    272425
    273426/**
    274  * Initalizes the unwind info section for non-windows hosts.
     427 * Initializes the unwind info section for non-windows hosts.
    275428 */
    276429static void iemExecMemAllocatorInitEhFrameForChunk(PIEMEXECMEMALLOCATOR pExecMemAllocator,
     
    327480}
    328481
    329 #endif /* IN_RING3 && !RT_OS_WINDOWS */
     482# endif /* !RT_OS_WINDOWS */
     483#endif /* IN_RING3 */
    330484
    331485
     
    401555# ifdef RT_OS_WINDOWS
    402556            /*
    403              * Register the runtime function table for this chunk.
    404              * We can share the data structure on windows.
     557             * The unwind information need to reside inside the chunk (at least
     558             * the UNWIND_INFO structures does), as the UnwindInfoAddress member
     559             * of RUNTIME_FUNCTION (AMD64) is relative to the "image base".
     560             *
     561             * We need unwind info because even longjmp() does a C++ stack unwind.
    405562             */
    406             /** @todo */
     563            void *pvUnwindInfo = iemExecMemAllocatorInitAndRegisterUnwindInfoForChunk(pExecMemAllocator, hHeap, pvChunk);
     564            AssertStmt(pvUnwindInfo, rc = VERR_INTERNAL_ERROR_3);
    407565# else
    408566            /*
     
    427585                 * Finalize the adding of the chunk.
    428586                 */
    429                 pExecMemAllocator->aChunks[idxChunk].pvChunk  = pvChunk;
    430                 pExecMemAllocator->aChunks[idxChunk].hHeap    = hHeap;
    431 #if defined(IN_RING3) && !defined(RT_OS_WINDOWS)
    432                 pExecMemAllocator->aChunks[idxChunk].pEhFrame = pEhFrame;
     587                pExecMemAllocator->aChunks[idxChunk].pvChunk      = pvChunk;
     588                pExecMemAllocator->aChunks[idxChunk].hHeap        = hHeap;
     589#ifdef IN_RING3
     590# ifdef RT_OS_WINDOWS
     591                pExecMemAllocator->aChunks[idxChunk].pvUnwindInfo = pvUnwindInfo;
     592# else
     593                pExecMemAllocator->aChunks[idxChunk].pEhFrame     = pEhFrame;
     594# endif
    433595#endif
    434596
     
    505667     * Allocate and initialize the allocatore instance.
    506668     */
    507 #if defined(IN_RING3) && defined(RT_OS_WINDOWS) && (defined(RT_ARCH_AMD64) || defined(RT_ARCH_ARM64))
    508     size_t const cbExtra = sizeof(RUNTIME_FUNCTION) + 0; /** @todo */
    509 #else
    510     size_t const cbExtra = 0;
    511 #endif
    512     PIEMEXECMEMALLOCATOR pExecMemAllocator = (PIEMEXECMEMALLOCATOR)RTMemAllocZ(  RT_UOFFSETOF_DYN(IEMEXECMEMALLOCATOR,
    513                                                                                                   aChunks[cMaxChunks])
    514                                                                                + cbExtra);
     669    PIEMEXECMEMALLOCATOR pExecMemAllocator = (PIEMEXECMEMALLOCATOR)RTMemAllocZ(RT_UOFFSETOF_DYN(IEMEXECMEMALLOCATOR,
     670                                                                                                aChunks[cMaxChunks]));
    515671    AssertReturn(pExecMemAllocator, VERR_NO_MEMORY);
    516672    pExecMemAllocator->uMagic       = IEMEXECMEMALLOCATOR_MAGIC;
     
    523679    pExecMemAllocator->cbFree       = 0;
    524680    pExecMemAllocator->cbAllocated  = 0;
    525 #if defined(IN_RING3) && defined(RT_OS_WINDOWS) && (defined(RT_ARCH_AMD64) || defined(RT_ARCH_ARM64))
    526     pExecMemAllocator->paUnwindFunctions = (PRUNTIME_FUNCTION)&pExecMemAllocator->aChunks[cMaxChunks];
    527     /** @todo */
    528 #endif
    529681    for (uint32_t i = 0; i < cMaxChunks; i++)
    530682    {
     
    727879    int8_t      offAddend;
    728880} IEMNATIVEFIXUP;
    729 
     881/** Pointer to a native code generator fixup. */
    730882typedef IEMNATIVEFIXUP *PIEMNATIVEFIXUP;
    731883
     
    9731125        AssertReturn(pbCodeBuf, UINT32_MAX);
    9741126        if (iGpr >= 8)
    975             pbCodeBuf[off++] = X86_OP_REX_R;
     1127            pbCodeBuf[off++] = X86_OP_REX_B;
    9761128        pbCodeBuf[off++] = 0xb8 + (iGpr & 7);
    9771129        pbCodeBuf[off++] = RT_BYTE1(uImm64);
     
    9881140            pbCodeBuf[off++] = X86_OP_REX_W;
    9891141        else
    990             pbCodeBuf[off++] = X86_OP_REX_W | X86_OP_REX_R;
     1142            pbCodeBuf[off++] = X86_OP_REX_W | X86_OP_REX_B;
    9911143        pbCodeBuf[off++] = 0xb8 + (iGpr & 7);
    9921144        pbCodeBuf[off++] = RT_BYTE1(uImm64);
     
    10711223}
    10721224
    1073 
     1225#ifdef RT_ARCH_AMD64
     1226/**
     1227 * Common bit of iemNativeEmitLoadGprByBp and friends.
     1228 */
     1229DECL_FORCE_INLINE(uint32_t) iemNativeEmitGprByBpDisp(uint8_t *pbCodeBuf, uint32_t off, uint8_t iGprReg, int32_t offDisp)
     1230{
     1231    if (offDisp < 128 && offDisp >= -128)
     1232    {
     1233        pbCodeBuf[off++] = X86_MODRM_MAKE(X86_MOD_MEM1, iGprReg & 7, X86_GREG_xBP);
     1234        pbCodeBuf[off++] = (uint8_t)(int8_t)offDisp;
     1235    }
     1236    else
     1237    {
     1238        pbCodeBuf[off++] = X86_MODRM_MAKE(X86_MOD_MEM4, iGprReg & 7, X86_GREG_xBP);
     1239        pbCodeBuf[off++] = RT_BYTE1((uint32_t)offDisp);
     1240        pbCodeBuf[off++] = RT_BYTE2((uint32_t)offDisp);
     1241        pbCodeBuf[off++] = RT_BYTE3((uint32_t)offDisp);
     1242        pbCodeBuf[off++] = RT_BYTE4((uint32_t)offDisp);
     1243    }
     1244    return off;
     1245}
     1246#endif
     1247
     1248
     1249#ifdef RT_ARCH_AMD64
     1250/**
     1251 * Emits a 64-bit GRP load instruction with an BP relative source address.
     1252 */
     1253static uint32_t iemNativeEmitLoadGprByBp(PVMCPUCC pVCpu, uint32_t off, uint8_t iGprDst, int32_t offDisp)
     1254{
     1255    /* mov gprdst, qword [rbp + offDisp]  */
     1256    uint8_t *pbCodeBuf = iemNativeInstrBufEnsure(pVCpu, off, 7);
     1257    if (iGprDst < 8)
     1258        pbCodeBuf[off++] = X86_OP_REX_W;
     1259    else
     1260        pbCodeBuf[off++] = X86_OP_REX_W | X86_OP_REX_R;
     1261    pbCodeBuf[off++] = 0x8b;
     1262    return iemNativeEmitGprByBpDisp(pbCodeBuf, off, iGprDst, offDisp);
     1263}
     1264#endif
     1265
     1266
     1267#ifdef RT_ARCH_AMD64
     1268/**
     1269 * Emits a 32-bit GRP load instruction with an BP relative source address.
     1270 */
     1271static uint32_t iemNativeEmitLoadGprByBpU32(PVMCPUCC pVCpu, uint32_t off, uint8_t iGprDst, int32_t offDisp)
     1272{
     1273    /* mov gprdst, dword [rbp + offDisp]  */
     1274    uint8_t *pbCodeBuf = iemNativeInstrBufEnsure(pVCpu, off, 7);
     1275    if (iGprDst >= 8)
     1276        pbCodeBuf[off++] = X86_OP_REX_R;
     1277    pbCodeBuf[off++] = 0x8b;
     1278    return iemNativeEmitGprByBpDisp(pbCodeBuf, off, iGprDst, offDisp);
     1279}
     1280#endif
     1281
     1282
     1283#ifdef RT_ARCH_AMD64
     1284/**
     1285 * Emits a load effective address to a GRP with an BP relative source address.
     1286 */
     1287static uint32_t iemNativeEmitLeaGrpByBp(PVMCPUCC pVCpu, uint32_t off, uint8_t iGprDst, int32_t offDisp)
     1288{
     1289    /* lea gprdst, [rbp + offDisp] */
     1290    uint8_t *pbCodeBuf = iemNativeInstrBufEnsure(pVCpu, off, 7);
     1291    if (iGprDst < 8)
     1292        pbCodeBuf[off++] = X86_OP_REX_W;
     1293    else
     1294        pbCodeBuf[off++] = X86_OP_REX_W | X86_OP_REX_R;
     1295    pbCodeBuf[off++] = 0x8d;
     1296    return iemNativeEmitGprByBpDisp(pbCodeBuf, off, iGprDst, offDisp);
     1297}
     1298#endif
     1299
     1300
     1301#ifdef RT_ARCH_AMD64
     1302/**
     1303 * Emits a 64-bit GPR store with an BP relative destination address.
     1304 */
     1305static uint32_t iemNativeEmitStoreGprByBp(PVMCPUCC pVCpu, uint32_t off, int32_t offDisp, uint8_t iGprSrc)
     1306{
     1307    /* mov qword [rbp + offDisp], gprdst */
     1308    uint8_t *pbCodeBuf = iemNativeInstrBufEnsure(pVCpu, off, 7);
     1309    if (iGprSrc < 8)
     1310        pbCodeBuf[off++] = X86_OP_REX_W;
     1311    else
     1312        pbCodeBuf[off++] = X86_OP_REX_W | X86_OP_REX_R;
     1313    pbCodeBuf[off++] = 0x89;
     1314    return iemNativeEmitGprByBpDisp(pbCodeBuf, off, iGprSrc, offDisp);
     1315}
     1316#endif
     1317
     1318
     1319#ifdef RT_ARCH_AMD64
     1320/**
     1321 * Emits a 64-bit GPR subtract with a signed immediate subtrahend.
     1322 */
     1323static uint32_t iemNativeEmitSubGprImm(PVMCPUCC pVCpu, uint32_t off, uint8_t iGprDst, int32_t iSubtrahend)
     1324{
     1325    /* sub gprdst, imm8/imm32 */
     1326    uint8_t *pbCodeBuf = iemNativeInstrBufEnsure(pVCpu, off, 7);
     1327    if (iGprDst < 7)
     1328        pbCodeBuf[off++] = X86_OP_REX_W;
     1329    else
     1330        pbCodeBuf[off++] = X86_OP_REX_W | X86_OP_REX_B;
     1331    if (iSubtrahend < 128 && iSubtrahend >= -128)
     1332    {
     1333        pbCodeBuf[off++] = 0x83;
     1334        pbCodeBuf[off++] = X86_MODRM_MAKE(X86_MOD_REG, 5, iGprDst & 7);
     1335        pbCodeBuf[off++] = (uint8_t)iSubtrahend;
     1336    }
     1337    else
     1338    {
     1339        pbCodeBuf[off++] = 0x81;
     1340        pbCodeBuf[off++] = X86_MODRM_MAKE(X86_MOD_REG, 5, iGprDst & 7);
     1341        pbCodeBuf[off++] = RT_BYTE1(iSubtrahend);
     1342        pbCodeBuf[off++] = RT_BYTE2(iSubtrahend);
     1343        pbCodeBuf[off++] = RT_BYTE3(iSubtrahend);
     1344        pbCodeBuf[off++] = RT_BYTE4(iSubtrahend);
     1345    }
     1346    return off;
     1347}
     1348#endif
     1349
     1350
     1351/**
     1352 * Emits a code for checking the return code of a call and rcPassUp, returning
     1353 * from the code if either are non-zero.
     1354 */
    10741355static uint32_t iemNativeEmitCheckCallRetAndPassUp(PVMCPUCC pVCpu, uint32_t off, uint8_t idxInstr)
    10751356{
     
    11151396
    11161397
     1398/**
     1399 * Emits a call to a threaded worker function.
     1400 */
    11171401static uint32_t iemNativeEmitThreadedCall(PVMCPUCC pVCpu, uint32_t off, PCIEMTHRDEDCALLENTRY pCallEntry)
    11181402{
     
    11251409    /* Load the parameters and emit the call. */
    11261410# ifdef RT_OS_WINDOWS
     1411#  ifndef VBOXSTRICTRC_STRICT_ENABLED
    11271412    off = iemNativeEmitLoadGprFromGpr(pVCpu, off, X86_GREG_xCX, X86_GREG_xBX);
    11281413    AssertReturn(off != UINT32_MAX, UINT32_MAX);
     
    11331418    off = iemNativeEmitLoadGprImm64(pVCpu, off, X86_GREG_x9, pCallEntry->auParams[2]);
    11341419    AssertReturn(off != UINT32_MAX, UINT32_MAX);
     1420#  else  /* VBOXSTRICTRC: Returned via hidden parameter. Sigh. */
     1421    off = iemNativeEmitLoadGprFromGpr(pVCpu, off, X86_GREG_xDX, X86_GREG_xBX);
     1422    AssertReturn(off != UINT32_MAX, UINT32_MAX);
     1423    off = iemNativeEmitLoadGprImm64(pVCpu, off, X86_GREG_x8, pCallEntry->auParams[0]);
     1424    AssertReturn(off != UINT32_MAX, UINT32_MAX);
     1425    off = iemNativeEmitLoadGprImm64(pVCpu, off, X86_GREG_x9, pCallEntry->auParams[1]);
     1426    AssertReturn(off != UINT32_MAX, UINT32_MAX);
     1427    off = iemNativeEmitLoadGprImm64(pVCpu, off, X86_GREG_x10, pCallEntry->auParams[2]);
     1428    AssertReturn(off != UINT32_MAX, UINT32_MAX);
     1429    off = iemNativeEmitStoreGprByBp(pVCpu, off, IEMNATIVE_FP_OFF_STACK_ARG0, X86_GREG_x10);
     1430    AssertReturn(off != UINT32_MAX, UINT32_MAX);
     1431    off = iemNativeEmitLeaGrpByBp(pVCpu, off, X86_GREG_xCX, IEMNATIVE_FP_OFF_IN_SHADOW_ARG0); /* rcStrict */
     1432    AssertReturn(off != UINT32_MAX, UINT32_MAX);
     1433#  endif /* VBOXSTRICTRC_STRICT_ENABLED */
    11351434# else
    11361435    off = iemNativeEmitLoadGprFromGpr(pVCpu, off, X86_GREG_xDI, X86_GREG_xBX);
     
    11511450    pbCodeBuf[off++] = X86_MODRM_MAKE(X86_MOD_REG, 2, X86_GREG_xAX);
    11521451
     1452# if defined(VBOXSTRICTRC_STRICT_ENABLED) && defined(RT_OS_WINDOWS)
     1453    off = iemNativeEmitLoadGprByBpU32(pVCpu, off, X86_GREG_xAX, IEMNATIVE_FP_OFF_IN_SHADOW_ARG0); /* rcStrict (see above) */
     1454# endif
     1455
    11531456    /* Check the status code. */
    11541457    off = iemNativeEmitCheckCallRetAndPassUp(pVCpu, off, pCallEntry->idxInstr);
     
    11671470
    11681471
     1472/**
     1473 * Emits a standard epilog.
     1474 */
    11691475static uint32_t iemNativeEmitEpilog(PVMCPUCC pVCpu, uint32_t off)
    11701476{
     
    11891495    pbCodeBuf[off++] = 0x8d;                    /* lea rsp, [rbp - (gcc ? 5 : 7) * 8] */
    11901496    pbCodeBuf[off++] = X86_MODRM_MAKE(X86_MOD_MEM1, X86_GREG_xSP, X86_GREG_xBP);
    1191 # ifdef RT_OS_WINDOWS
    1192     pbCodeBuf[off++] = (uint8_t)(-7 * 8);
    1193 # else
    1194     pbCodeBuf[off++] = (uint8_t)(-5 * 8);
    1195 # endif
     1497    pbCodeBuf[off++] = (uint8_t)IEMNATIVE_FP_OFF_LAST_PUSH;
    11961498
    11971499    /* Pop non-volatile registers and return */
     
    12241526        /* Call helper and jump to return point. */
    12251527# ifdef RT_OS_WINDOWS
    1226         off = iemNativeEmitLoadGprFromGpr(pVCpu, off, X86_GREG_xR8, X86_GREG_xCX); /* cl = instruction number */
     1528        off = iemNativeEmitLoadGprFromGpr(pVCpu, off, X86_GREG_x8, X86_GREG_xCX); /* cl = instruction number */
    12271529        AssertReturn(off != UINT32_MAX, UINT32_MAX);
    12281530        off = iemNativeEmitLoadGprFromGpr(pVCpu, off, X86_GREG_xCX, X86_GREG_xBX);
     
    12771579
    12781580
     1581/**
     1582 * Emits a standard prolog.
     1583 */
    12791584static uint32_t iemNativeEmitProlog(PVMCPUCC pVCpu, uint32_t off)
    12801585{
     
    13151620    pbCodeBuf[off++] = 0x50 + X86_GREG_x15 - 8;
    13161621
    1317     pbCodeBuf[off++] = X86_OP_REX_W;            /* sub rsp, byte 28h */
    1318     pbCodeBuf[off++] = 0x83;
    1319     pbCodeBuf[off++] = X86_MODRM_MAKE(X86_MOD_REG, 5, X86_GREG_xSP);
    1320     pbCodeBuf[off++] = 0x40  /* for variables */
    1321                      + 8     /* stack alignment correction */
    1322                      + 4 * 8 /* 4 non-register arguments */
    1323 # ifdef RT_OS_WINDOWS
    1324                      + 0x20  /* register argument spill area for windows calling convention */
    1325 # endif
    1326                      ;
     1622    off = iemNativeEmitSubGprImm(pVCpu, off,    /* sub rsp, byte 28h */
     1623                                 X86_GREG_xSP,
     1624                                   IEMNATIVE_FRAME_ALIGN_SIZE
     1625                                 + IEMNATIVE_FRAME_VAR_SIZE
     1626                                 + IEMNATIVE_FRAME_STACK_ARG_COUNT * 8
     1627                                 + IEMNATIVE_FRAME_SHADOW_ARG_COUNT * 8);
     1628    AssertCompile(!(IEMNATIVE_FRAME_VAR_SIZE & 0xf));
     1629    AssertCompile(!(IEMNATIVE_FRAME_STACK_ARG_COUNT & 0x1));
     1630    AssertCompile(!(IEMNATIVE_FRAME_SHADOW_ARG_COUNT & 0x1));
    13271631
    13281632#elif RT_ARCH_ARM64
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