Changeset 105261 in vbox
- Timestamp:
- Jul 10, 2024 2:51:55 PM (5 months ago)
- Location:
- trunk/src/VBox/VMM
- Files:
-
- 8 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/VMMAll/IEMAllN8veExecMem.cpp
r104876 r105261 226 226 /** Pointer to the readable/executable view of the memory chunk. */ 227 227 void *pvChunkRx; 228 #ifdef IEMNATIVE_WITH_RECOMPILER_PER_CHUNK_TAIL_CODE 229 /** Pointer to the context structure detailing the per chunk common code. */ 230 PCIEMNATIVEPERCHUNKCTX pCtx; 231 #endif 228 232 #ifdef IN_RING3 229 233 /** … … 347 351 static int iemExecMemAllocatorGrow(PVMCPUCC pVCpu, PIEMEXECMEMALLOCATOR pExecMemAllocator); 348 352 353 349 354 #ifdef IEMEXECMEM_ALT_SUB_WITH_ALT_PRUNING 350 355 /** … … 461 466 static void * 462 467 iemExecMemAllocatorAllocInChunkInt(PIEMEXECMEMALLOCATOR pExecMemAllocator, uint64_t *pbmAlloc, uint32_t idxFirst, 463 uint32_t cToScan, uint32_t cReqUnits, uint32_t idxChunk, PIEMTB pTb, void **ppvExec) 468 uint32_t cToScan, uint32_t cReqUnits, uint32_t idxChunk, PIEMTB pTb, 469 void **ppvExec, PCIEMNATIVEPERCHUNKCTX *ppChunkCtx) 464 470 { 465 471 /* … … 497 503 void * const pvMemRw = (uint8_t *)pChunk->pvChunkRw 498 504 + ((idxFirst + (uint32_t)iBit) << IEMEXECMEM_ALT_SUB_ALLOC_UNIT_SHIFT); 505 506 if (ppChunkCtx) 507 *ppChunkCtx = pChunk->pCtx; 499 508 500 509 /* … … 529 538 530 539 531 static void *540 static PIEMNATIVEINSTR 532 541 iemExecMemAllocatorAllocInChunk(PIEMEXECMEMALLOCATOR pExecMemAllocator, uint32_t idxChunk, uint32_t cbReq, PIEMTB pTb, 533 void **ppvExec)542 PIEMNATIVEINSTR *ppaExec, PCIEMNATIVEPERCHUNKCTX *ppChunkCtx) 534 543 { 535 544 /* … … 550 559 void *pvRet = iemExecMemAllocatorAllocInChunkInt(pExecMemAllocator, pbmAlloc, idxHint, 551 560 pExecMemAllocator->cUnitsPerChunk - idxHint, 552 cReqUnits, idxChunk, pTb, ppvExec);561 cReqUnits, idxChunk, pTb, (void **)ppaExec, ppChunkCtx); 553 562 if (pvRet) 554 return pvRet;563 return (PIEMNATIVEINSTR)pvRet; 555 564 } 556 return iemExecMemAllocatorAllocInChunkInt(pExecMemAllocator, pbmAlloc, 0, 557 RT_MIN(pExecMemAllocator->cUnitsPerChunk, RT_ALIGN_32(idxHint + cReqUnits, 64)), 558 cReqUnits, idxChunk, pTb, ppvExec); 565 return (PIEMNATIVEINSTR)iemExecMemAllocatorAllocInChunkInt(pExecMemAllocator, pbmAlloc, 0, 566 RT_MIN(pExecMemAllocator->cUnitsPerChunk, 567 RT_ALIGN_32(idxHint + cReqUnits, 64)), 568 cReqUnits, idxChunk, pTb, (void **)ppaExec, ppChunkCtx); 559 569 } 560 570 return NULL; … … 567 577 * @returns Pointer to the readable/writeable memory, NULL if out of memory or other problem 568 578 * encountered. 569 * @param pVCpu The cross context virtual CPU structure of the calling 570 * thread. 571 * @param cbReq How many bytes are required. 572 * @param pTb The translation block that will be using the allocation. 573 * @param ppvExec Where to return the pointer to executable view of the allocated memory, optional. 574 */ 575 DECLHIDDEN(void *) iemExecMemAllocatorAlloc(PVMCPU pVCpu, uint32_t cbReq, PIEMTB pTb, void **ppvExec) RT_NOEXCEPT 579 * @param pVCpu The cross context virtual CPU structure of the 580 * calling thread. 581 * @param cbReq How many bytes are required. 582 * @param pTb The translation block that will be using the allocation. 583 * @param ppaExec Where to return the pointer to executable view of 584 * the allocated memory, optional. 585 * @param ppChunkCtx Where to return the per chunk attached context 586 * if available, optional. 587 */ 588 DECLHIDDEN(PIEMNATIVEINSTR) iemExecMemAllocatorAlloc(PVMCPU pVCpu, uint32_t cbReq, PIEMTB pTb, 589 PIEMNATIVEINSTR *ppaExec, PCIEMNATIVEPERCHUNKCTX *ppChunkCtx) RT_NOEXCEPT 576 590 { 577 591 PIEMEXECMEMALLOCATOR pExecMemAllocator = pVCpu->iem.s.pExecMemAllocatorR3; … … 588 602 for (uint32_t idxChunk = idxChunkHint; idxChunk < cChunks; idxChunk++) 589 603 { 590 void *pvRet = iemExecMemAllocatorAllocInChunk(pExecMemAllocator, idxChunk, cbReq, pTb, ppvExec); 591 if (pvRet) 604 PIEMNATIVEINSTR const pRet = iemExecMemAllocatorAllocInChunk(pExecMemAllocator, idxChunk, cbReq, pTb, 605 ppaExec, ppChunkCtx); 606 if (pRet) 592 607 { 593 608 STAM_PROFILE_STOP(&pExecMemAllocator->StatAlloc, a); 594 return p vRet;609 return pRet; 595 610 } 596 611 } 597 612 for (uint32_t idxChunk = 0; idxChunk < idxChunkHint; idxChunk++) 598 613 { 599 void *pvRet = iemExecMemAllocatorAllocInChunk(pExecMemAllocator, idxChunk, cbReq, pTb, ppvExec); 600 if (pvRet) 614 PIEMNATIVEINSTR const pRet = iemExecMemAllocatorAllocInChunk(pExecMemAllocator, idxChunk, cbReq, pTb, 615 ppaExec, ppChunkCtx); 616 if (pRet) 601 617 { 602 618 STAM_PROFILE_STOP(&pExecMemAllocator->StatAlloc, a); 603 return p vRet;619 return pRet; 604 620 } 605 621 } … … 615 631 616 632 uint32_t const idxChunk = pExecMemAllocator->cChunks - 1; 617 void *pvRet = iemExecMemAllocatorAllocInChunk(pExecMemAllocator, idxChunk, cbReq, pTb, ppvExec); 618 if (pvRet) 633 PIEMNATIVEINSTR const pRet = iemExecMemAllocatorAllocInChunk(pExecMemAllocator, idxChunk, cbReq, pTb, 634 ppaExec, ppChunkCtx); 635 if (pRet) 619 636 { 620 637 STAM_PROFILE_STOP(&pExecMemAllocator->StatAlloc, a); 621 return p vRet;638 return pRet; 622 639 } 623 640 AssertFailed(); … … 659 676 sys_icache_invalidate(pv, cb); 660 677 RT_NOREF(pVCpu); 678 661 679 #elif defined(RT_OS_LINUX) 662 680 RT_NOREF(pVCpu); … … 673 691 674 692 asm volatile ("dsb ish\n\t isb\n\t" : : : "memory"); 693 675 694 #else 676 695 RT_NOREF(pVCpu, pv, cb); … … 747 766 } 748 767 768 769 /** 770 * Interface used by iemNativeRecompileAttachExecMemChunkCtx and unwind info 771 * generators. 772 */ 773 DECLHIDDEN(PIEMNATIVEINSTR) 774 iemExecMemAllocatorAllocFromChunk(PVMCPU pVCpu, uint32_t idxChunk, uint32_t cbReq, PIEMNATIVEINSTR *ppaExec) 775 { 776 PIEMEXECMEMALLOCATOR pExecMemAllocator = pVCpu->iem.s.pExecMemAllocatorR3; 777 AssertReturn(idxChunk < pExecMemAllocator->cChunks, NULL); 778 Assert(cbReq < _1M); 779 return iemExecMemAllocatorAllocInChunk(pExecMemAllocator, idxChunk, cbReq, NULL /*pTb*/, ppaExec, NULL /*ppChunkCtx*/); 780 } 781 782 783 #ifdef IEMNATIVE_WITH_RECOMPILER_PER_CHUNK_TAIL_CODE 784 /** 785 * For getting the per-chunk context detailing common code for a TB. 786 * 787 * This is for use by the disassembler. 788 */ 789 DECLHIDDEN(PCIEMNATIVEPERCHUNKCTX) iemExecMemGetTbChunkCtx(PVMCPU pVCpu, PCIEMTB pTb) 790 { 791 PIEMEXECMEMALLOCATOR pExecMemAllocator = pVCpu->iem.s.pExecMemAllocatorR3; 792 if ((pTb->fFlags & IEMTB_F_TYPE_MASK) == IEMTB_F_TYPE_NATIVE) 793 { 794 uintptr_t const uAddress = (uintptr_t)pTb->Native.paInstructions; 795 uint32_t const cbChunk = pExecMemAllocator->cbChunk; 796 uint32_t idxChunk = pExecMemAllocator->cChunks; 797 while (idxChunk-- > 0) 798 if (uAddress - (uintptr_t)pExecMemAllocator->aChunks[idxChunk].pvChunkRx < cbChunk) 799 return pExecMemAllocator->aChunks[idxChunk].pCtx; 800 } 801 return NULL; 802 } 803 #endif 749 804 750 805 … … 814 869 unsigned const cbNeeded = sizeof(IMAGE_RUNTIME_FUNCTION_ENTRY) * cFunctionEntries + cbUnwindInfo; 815 870 PIMAGE_RUNTIME_FUNCTION_ENTRY const paFunctions 816 = (PIMAGE_RUNTIME_FUNCTION_ENTRY)iemExecMemAllocatorAllocInChunk(pExecMemAllocator, idxChunk, cbNeeded, NULL, NULL );871 = (PIMAGE_RUNTIME_FUNCTION_ENTRY)iemExecMemAllocatorAllocInChunk(pExecMemAllocator, idxChunk, cbNeeded, NULL, NULL, NULL); 817 872 AssertReturn(paFunctions, VERR_INTERNAL_ERROR_5); 818 873 pExecMemAllocator->aChunks[idxChunk].pvUnwindInfo = paFunctions; … … 1050 1105 */ 1051 1106 GDBJITSYMFILE * const pSymFile = (GDBJITSYMFILE *)iemExecMemAllocatorAllocInChunk(pExecMemAllocator, idxChunk, 1052 sizeof(GDBJITSYMFILE), NULL, NULL );1107 sizeof(GDBJITSYMFILE), NULL, NULL, NULL); 1053 1108 AssertReturn(pSymFile, VERR_INTERNAL_ERROR_5); 1054 1109 unsigned const offSymFileInChunk = (uintptr_t)pSymFile - (uintptr_t)pvChunk; … … 1393 1448 * protections when exeuctable memory is allocated. 1394 1449 */ 1450 int rc = VERR_NO_EXEC_MEMORY; 1395 1451 mach_port_t hPortTask = mach_task_self(); 1396 1452 mach_vm_address_t AddrChunk = (mach_vm_address_t)pvChunk; 1397 1453 mach_vm_address_t AddrRemapped = 0; 1398 vm_prot_t ProtCur, ProtMax; 1454 vm_prot_t ProtCur = 0; 1455 vm_prot_t ProtMax = 0; 1399 1456 kern_return_t krc = mach_vm_remap(hPortTask, &AddrRemapped, pExecMemAllocator->cbChunk, 0, 1400 1457 VM_FLAGS_ANYWHERE | VM_FLAGS_RETURN_DATA_ADDR, 1401 1458 hPortTask, AddrChunk, FALSE, &ProtCur, &ProtMax, 1402 1459 VM_INHERIT_NONE); 1403 if (krc != KERN_SUCCESS) 1460 if (krc == KERN_SUCCESS) 1461 { 1462 krc = mach_vm_protect(mach_task_self(), AddrRemapped, pExecMemAllocator->cbChunk, FALSE, VM_PROT_READ | VM_PROT_EXECUTE); 1463 if (krc == KERN_SUCCESS) 1464 rc = VINF_SUCCESS; 1465 else 1466 { 1467 AssertLogRelMsgFailed(("mach_vm_protect -> %d (%#x)\n", krc, krc)); 1468 krc = mach_vm_deallocate(hPortTask, AddrRemapped, pExecMemAllocator->cbChunk); 1469 Assert(krc == KERN_SUCCESS); 1470 } 1471 } 1472 else 1473 AssertLogRelMsgFailed(("mach_vm_remap -> %d (%#x)\n", krc, krc)); 1474 if (RT_FAILURE(rc)) 1404 1475 { 1405 1476 RTMemPageFree(pvChunk, pExecMemAllocator->cbChunk); 1406 AssertLogRelFailed(); 1407 return VERR_NO_EXEC_MEMORY; 1408 } 1409 1410 krc = mach_vm_protect(mach_task_self(), AddrRemapped, pExecMemAllocator->cbChunk, FALSE, VM_PROT_READ | VM_PROT_EXECUTE); 1411 if (krc != KERN_SUCCESS) 1412 { 1413 krc = mach_vm_deallocate(hPortTask, AddrRemapped, pExecMemAllocator->cbChunk); 1414 Assert(krc == KERN_SUCCESS); 1415 RTMemPageFree(pvChunk, pExecMemAllocator->cbChunk); 1416 AssertLogRelFailed(); 1417 return VERR_NO_EXEC_MEMORY; 1477 return rc; 1418 1478 } 1419 1479 1420 1480 void *pvChunkRx = (void *)AddrRemapped; 1421 1481 #else 1482 # if defined(IN_RING3) || defined(IEMNATIVE_WITH_RECOMPILER_PER_CHUNK_TAIL_CODE) 1483 int rc = VINF_SUCCESS; 1484 # endif 1422 1485 void *pvChunkRx = pvChunk; 1423 1486 #endif … … 1445 1508 pExecMemAllocator->cbFree += pExecMemAllocator->cbChunk; 1446 1509 1510 /* If there is a chunk context init callback call it. */ 1511 #ifdef IEMNATIVE_WITH_RECOMPILER_PER_CHUNK_TAIL_CODE 1512 pExecMemAllocator->aChunks[idxChunk].pCtx = iemNativeRecompileAttachExecMemChunkCtx(pVCpu, idxChunk); 1513 if (pExecMemAllocator->aChunks[idxChunk].pCtx) 1514 #endif 1515 { 1447 1516 #ifdef IN_RING3 1448 /* 1449 * Initialize the unwind information (this cannot really fail atm). 1450 * (This sets pvUnwindInfo.) 1451 */ 1452 int rc = iemExecMemAllocatorInitAndRegisterUnwindInfoForChunk(pVCpu, pExecMemAllocator, pvChunkRx, idxChunk); 1517 /* 1518 * Initialize the unwind information (this cannot really fail atm). 1519 * (This sets pvUnwindInfo.) 1520 */ 1521 rc = iemExecMemAllocatorInitAndRegisterUnwindInfoForChunk(pVCpu, pExecMemAllocator, pvChunkRx, idxChunk); 1522 #endif 1523 } 1524 #if defined(IN_RING3) || defined(IEMNATIVE_WITH_RECOMPILER_PER_CHUNK_TAIL_CODE) 1453 1525 if (RT_SUCCESS(rc)) 1454 1526 { /* likely */ } … … 1464 1536 pExecMemAllocator->aChunks[idxChunk].cFreeUnits = 0; 1465 1537 1466 # ifdef RT_OS_DARWIN1538 # ifdef RT_OS_DARWIN 1467 1539 krc = mach_vm_deallocate(mach_task_self(), (mach_vm_address_t)pExecMemAllocator->aChunks[idxChunk].pvChunkRx, 1468 1540 pExecMemAllocator->cbChunk); 1469 1541 Assert(krc == KERN_SUCCESS); 1470 # endif1542 # endif 1471 1543 1472 1544 RTMemPageFree(pvChunk, pExecMemAllocator->cbChunk); … … 1474 1546 } 1475 1547 #endif 1548 1476 1549 return VINF_SUCCESS; 1477 1550 } … … 1523 1596 } 1524 1597 } 1598 #ifdef IEMNATIVE_WITH_RECOMPILER_PER_CHUNK_TAIL_CODE 1599 # if defined(RT_OS_AMD64) 1600 Assert(cbChunk <= _2G); 1601 # elif defined(RT_OS_ARM64) 1602 if (cbChunk > _128M) 1603 cbChunk = _128M; /* Max relative branch distance is +/-2^(25+2) = +/-0x8000000 (134 217 728). */ 1604 # endif 1605 #endif 1525 1606 1526 1607 if (cbChunk > cbMax) -
trunk/src/VBox/VMM/VMMAll/IEMAllN8veHlpA-arm64.S
r104798 r105261 94 94 */ 95 95 br x2 96 97 #ifdef IEMNATIVE_WITH_RECOMPILER_EPILOGUE_SINGLETON98 /**99 * This is the common epilog for all TBs, restoring all volatile registers100 * and cleaning up the stack frame. This is a direct jump target and not a101 * real function to call using bl/blr.102 */103 ALIGNCODE(IEM_HLP_FUNCTION_ALIGNMENT)104 BEGINPROC_HIDDEN iemNativeTbEpilog105 ldp x19, x20, [sp, #IEMNATIVE_FRAME_VAR_SIZE]!106 ldp x21, x22, [sp, #0x10]107 ldp x23, x24, [sp, #0x20]108 ldp x25, x26, [sp, #0x30]109 ldp x27, x28, [sp, #0x40]110 ldp x29, x30, [sp, #0x50]111 add sp, sp, #IEMNATIVE_FRAME_SAVE_REG_SIZE112 # ifdef RT_OS_DARWIN113 retab114 # else115 ret116 # endif117 #endif118 96 119 97 -
trunk/src/VBox/VMM/VMMAll/IEMAllN8veRecompBltIn.cpp
r104957 r105261 598 598 } while (0) 599 599 600 # ifdef IEMNATIVE_WITH_RECOMPILER_PER_CHUNK_TAIL_CODE 601 # define NEAR_JMP_SIZE 5 602 # else 603 # define NEAR_JMP_SIZE 6 604 # endif 605 600 606 # define CHECK_OPCODES_CMP_JMP() /* cost: 7 bytes first time, then 2 bytes */ do { \ 601 607 if (offConsolidatedJump != UINT32_MAX) \ … … 608 614 else \ 609 615 { \ 610 pbCodeBuf[off++] = 0x74; /* jz near + 6*/ \611 pbCodeBuf[off++] = 0x06+ BP_ON_OBSOLETION; \616 pbCodeBuf[off++] = 0x74; /* jz near +NEAR_JMP_SIZE */ \ 617 pbCodeBuf[off++] = NEAR_JMP_SIZE + BP_ON_OBSOLETION; \ 612 618 offConsolidatedJump = off; \ 613 619 if (BP_ON_OBSOLETION) pbCodeBuf[off++] = 0xcc; \ -
trunk/src/VBox/VMM/VMMAll/IEMAllN8veRecompiler.cpp
r105036 r105261 113 113 IEMNATIVEGSTREG enmGstReg, uint32_t off); 114 114 DECL_INLINE_THROW(void) iemNativeVarRegisterRelease(PIEMRECOMPILERSTATE pReNative, uint8_t idxVar); 115 static const char *iemNativeGetLabelName(IEMNATIVELABELTYPE enmLabel, bool fCommonCode = false); 115 116 116 117 … … 2057 2058 pReNative->bmLabelTypes = 0; 2058 2059 pReNative->cFixups = 0; 2060 #ifdef IEMNATIVE_WITH_RECOMPILER_PER_CHUNK_TAIL_CODE 2061 pReNative->cTbExitFixups = 0; 2062 #endif 2059 2063 #ifdef IEMNATIVE_WITH_TB_DEBUG_INFO 2060 2064 pReNative->pDbgInfo->cEntries = 0; … … 2196 2200 2197 2201 /** 2202 * Used when done emitting the per-chunk code and for iemNativeInit bailout. 2203 */ 2204 static void iemNativeTerm(PIEMRECOMPILERSTATE pReNative) 2205 { 2206 RTMemFree(pReNative->pInstrBuf); 2207 RTMemFree(pReNative->paLabels); 2208 RTMemFree(pReNative->paFixups); 2209 #ifdef IEMNATIVE_WITH_RECOMPILER_PER_CHUNK_TAIL_CODE 2210 RTMemFree(pReNative->paTbExitFixups); 2211 #endif 2212 #ifdef IEMNATIVE_WITH_TB_DEBUG_INFO 2213 RTMemFree(pReNative->pDbgInfo); 2214 #endif 2215 RTMemFree(pReNative); 2216 } 2217 2218 2219 /** 2198 2220 * Allocates and initializes the native recompiler state. 2199 2221 * … … 2203 2225 * @param pVCpu The cross context virtual CPU structure of the calling 2204 2226 * thread. 2205 * @param pTb The TB that's about to be recompiled. 2227 * @param pTb The TB that's about to be recompiled. When this is NULL, 2228 * the recompiler state is for emitting the common per-chunk 2229 * code from iemNativeRecompileAttachExecMemChunkCtx. 2206 2230 * @thread EMT(pVCpu) 2207 2231 */ … … 2216 2240 * Try allocate all the buffers and stuff we need. 2217 2241 */ 2218 pReNative->pInstrBuf = (PIEMNATIVEINSTR)RTMemAllocZ(_64K); 2219 pReNative->paLabels = (PIEMNATIVELABEL)RTMemAllocZ(sizeof(IEMNATIVELABEL) * _8K); 2220 pReNative->paFixups = (PIEMNATIVEFIXUP)RTMemAllocZ(sizeof(IEMNATIVEFIXUP) * _16K); 2242 uint32_t const cFactor = pTb ? 1 : 32 /* per-chunk stuff doesn't really need anything but the code buffer */; 2243 pReNative->pInstrBuf = (PIEMNATIVEINSTR)RTMemAllocZ(_64K); 2244 pReNative->paLabels = (PIEMNATIVELABEL)RTMemAllocZ(sizeof(IEMNATIVELABEL) * _8K / cFactor); 2245 pReNative->paFixups = (PIEMNATIVEFIXUP)RTMemAllocZ(sizeof(IEMNATIVEFIXUP) * _16K / cFactor); 2246 #ifdef IEMNATIVE_WITH_RECOMPILER_PER_CHUNK_TAIL_CODE 2247 pReNative->paTbExitFixups = (PIEMNATIVEEXITFIXUP)RTMemAllocZ(sizeof(IEMNATIVEEXITFIXUP) * _8K / cFactor); 2248 #endif 2221 2249 #ifdef IEMNATIVE_WITH_TB_DEBUG_INFO 2222 pReNative->pDbgInfo = (PIEMTBDBG)RTMemAllocZ(RT_UOFFSETOF_DYN(IEMTBDBG, aEntries[_16K]));2250 pReNative->pDbgInfo = (PIEMTBDBG)RTMemAllocZ(RT_UOFFSETOF_DYN(IEMTBDBG, aEntries[_16K / cFactor])); 2223 2251 #endif 2224 2252 if (RT_LIKELY( pReNative->pInstrBuf 2225 2253 && pReNative->paLabels 2226 2254 && pReNative->paFixups) 2255 #ifdef IEMNATIVE_WITH_RECOMPILER_PER_CHUNK_TAIL_CODE 2256 && pReNative->paTbExitFixups 2257 #endif 2227 2258 #ifdef IEMNATIVE_WITH_TB_DEBUG_INFO 2228 2259 && pReNative->pDbgInfo … … 2233 2264 * Set the buffer & array sizes on success. 2234 2265 */ 2235 pReNative->cInstrBufAlloc = _64K / sizeof(IEMNATIVEINSTR); 2236 pReNative->cLabelsAlloc = _8K; 2237 pReNative->cFixupsAlloc = _16K; 2266 pReNative->cInstrBufAlloc = _64K / sizeof(IEMNATIVEINSTR); 2267 pReNative->cLabelsAlloc = _8K / cFactor; 2268 pReNative->cFixupsAlloc = _16K / cFactor; 2269 #ifdef IEMNATIVE_WITH_RECOMPILER_PER_CHUNK_TAIL_CODE 2270 pReNative->cTbExitFixupsAlloc = _8K / cFactor; 2271 #endif 2238 2272 #ifdef IEMNATIVE_WITH_TB_DEBUG_INFO 2239 pReNative->cDbgInfoAlloc = _16K;2273 pReNative->cDbgInfoAlloc = _16K / cFactor; 2240 2274 #endif 2241 2275 2242 2276 /* Other constant stuff: */ 2243 pReNative->pVCpu = pVCpu;2277 pReNative->pVCpu = pVCpu; 2244 2278 2245 2279 /* 2246 * Done, just need to save it andreinit it.2280 * Done, just reinit it. 2247 2281 */ 2248 pVCpu->iem.s.pNativeRecompilerStateR3 = pReNative;2249 2282 return iemNativeReInit(pReNative, pTb); 2250 2283 } … … 2254 2287 */ 2255 2288 AssertFailed(); 2256 RTMemFree(pReNative->pInstrBuf); 2257 RTMemFree(pReNative->paLabels); 2258 RTMemFree(pReNative->paFixups); 2259 #ifdef IEMNATIVE_WITH_TB_DEBUG_INFO 2260 RTMemFree(pReNative->pDbgInfo); 2261 #endif 2262 RTMemFree(pReNative); 2289 iemNativeTerm(pReNative); 2263 2290 return NULL; 2264 2291 } … … 2285 2312 { 2286 2313 Assert(uData == 0 || enmType >= kIemNativeLabelType_FirstWithMultipleInstances); 2314 #if defined(IEMNATIVE_WITH_RECOMPILER_PER_CHUNK_TAIL_CODE) && defined(RT_ARCH_AMD64) 2315 Assert(enmType >= kIemNativeLabelType_FirstWithMultipleInstances); 2316 #endif 2287 2317 2288 2318 /* … … 2391 2421 2392 2422 2423 #if !defined(IEMNATIVE_WITH_RECOMPILER_PER_CHUNK_TAIL_CODE) || !defined(RT_ARCH_AMD64) 2393 2424 /** 2394 2425 * Looks up a lable. … … 2417 2448 return UINT32_MAX; 2418 2449 } 2450 #endif 2419 2451 2420 2452 … … 2470 2502 pReNative->cFixups = cFixups + 1; 2471 2503 } 2504 2505 2506 #ifdef IEMNATIVE_WITH_RECOMPILER_PER_CHUNK_TAIL_CODE 2507 /** 2508 * Adds a fixup to the per chunk tail code. 2509 * 2510 * @throws VBox status code (int) on failure. 2511 * @param pReNative The native recompile state. 2512 * @param offWhere The instruction offset of the fixup location. 2513 * @param enmExitReason The exit reason to jump to. 2514 */ 2515 DECL_HIDDEN_THROW(void) 2516 iemNativeAddTbExitFixup(PIEMRECOMPILERSTATE pReNative, uint32_t offWhere, IEMNATIVEEXITREASON enmExitReason) 2517 { 2518 /* 2519 * Make sure we've room. 2520 */ 2521 PIEMNATIVEEXITFIXUP paTbExitFixups = pReNative->paTbExitFixups; 2522 uint32_t const cTbExitFixups = pReNative->cTbExitFixups; 2523 if (RT_LIKELY(cTbExitFixups < pReNative->cTbExitFixupsAlloc)) 2524 { /* likely */ } 2525 else 2526 { 2527 uint32_t cNew = pReNative->cTbExitFixupsAlloc; 2528 AssertStmt(cNew, IEMNATIVE_DO_LONGJMP(pReNative, VERR_IEM_FIXUP_IPE_1)); 2529 AssertStmt(cTbExitFixups == cNew, IEMNATIVE_DO_LONGJMP(pReNative, VERR_IEM_FIXUP_IPE_1)); 2530 cNew *= 2; 2531 AssertStmt(cNew <= _128K, IEMNATIVE_DO_LONGJMP(pReNative, VERR_IEM_FIXUP_TOO_MANY)); 2532 paTbExitFixups = (PIEMNATIVEEXITFIXUP)RTMemRealloc(paTbExitFixups, cNew * sizeof(paTbExitFixups[0])); 2533 AssertStmt(paTbExitFixups, IEMNATIVE_DO_LONGJMP(pReNative, VERR_IEM_FIXUP_OUT_OF_MEMORY)); 2534 pReNative->paTbExitFixups = paTbExitFixups; 2535 pReNative->cTbExitFixupsAlloc = cNew; 2536 } 2537 2538 /* 2539 * Add the fixup. 2540 */ 2541 paTbExitFixups[cTbExitFixups].off = offWhere; 2542 paTbExitFixups[cTbExitFixups].enmExitReason = (uint32_t)enmExitReason; 2543 pReNative->cTbExitFixups = cTbExitFixups + 1; 2544 } 2545 #endif 2472 2546 2473 2547 … … 6097 6171 # ifdef RT_ARCH_AMD64 6098 6172 /* test dword [pVCpu + offVCpu], imm32 */ 6099 PIEMNATIVEINSTR const pCodeBuf = iemNativeInstrBufEnsure(pReNative, off, 1 0);6173 PIEMNATIVEINSTR const pCodeBuf = iemNativeInstrBufEnsure(pReNative, off, 13); 6100 6174 if (fEflNeeded <= 0xff) 6101 6175 { … … 6113 6187 pCodeBuf[off++] = RT_BYTE4(fEflNeeded); 6114 6188 } 6189 6190 off = iemNativeEmitJccToFixedEx(pCodeBuf, off, off + 3, kIemNativeInstrCond_e); 6191 pCodeBuf[off++] = 0xcc; 6192 6115 6193 IEMNATIVE_ASSERT_INSTR_BUF_ENSURE(pReNative, off); 6116 6194 … … 6158 6236 6159 6237 /* Jump to non-zero status return path. */ 6160 off = iemNativeEmitJnzT oNewLabel(pReNative, off, kIemNativeLabelType_NonZeroRetOrPassUp);6238 off = iemNativeEmitJnzTbExit(pReNative, off, kIemNativeExitReason_NonZeroRetOrPassUp); 6161 6239 6162 6240 /* done. */ … … 6175 6253 pu32CodeBuf[off++] = Armv8A64MkInstrOrr(ARMV8_A64_REG_X4, ARMV8_A64_REG_X3, ARMV8_A64_REG_X0, false /*f64Bit*/); 6176 6254 6177 uint32_t const idxLabel = iemNativeLabelCreate(pReNative, kIemNativeLabelType_NonZeroRetOrPassUp); 6178 iemNativeAddFixup(pReNative, off, idxLabel, kIemNativeFixupType_RelImm19At5); 6179 pu32CodeBuf[off++] = Armv8A64MkInstrCbzCbnz(true /*fJmpIfNotZero*/, 0, ARMV8_A64_REG_X4, false /*f64Bit*/); 6255 off = iemNativeEmitTestIfGprIsNotZeroAndTbExitEx(pReNative, pu32CodeBuf, off, ARMV8_A64_REG_X4, true /*f64Bit*/, 6256 kIemNativeExitReason_NonZeroRetOrPassUp); 6180 6257 6181 6258 #else … … 6287 6364 6288 6365 off = iemNativeEmitCmpGpr32WithGpr(pReNative, off, idxAddrReg, idxRegCsLim); 6289 off = iemNativeEmitJaT oNewLabel(pReNative, off, kIemNativeLabelType_RaiseGp0);6366 off = iemNativeEmitJaTbExit(pReNative, off, kIemNativeExitReason_RaiseGp0); 6290 6367 6291 6368 iemNativeRegFreeTmp(pReNative, idxRegCsLim); … … 6495 6572 6496 6573 /** 6574 * Worker for iemNativeEmitViaLookupDoOne and iemNativeRecompileAttachExecMemChunkCtx. 6575 */ 6576 static uint32_t 6577 iemNativeEmitCoreViaLookupDoOne(PIEMRECOMPILERSTATE pReNative, uint32_t off, uint32_t offReturnBreak, uintptr_t pfnHelper) 6578 { 6579 off = iemNativeEmitLoadGprFromGpr(pReNative, off, IEMNATIVE_CALL_ARG0_GREG, IEMNATIVE_REG_FIXED_PVMCPU); 6580 off = iemNativeEmitCallImm(pReNative, off, pfnHelper); 6581 6582 /* Jump to ReturnBreak if the return register is NULL. */ 6583 off = iemNativeEmitTestIfGprIsZeroAndJmpToFixed(pReNative, off, IEMNATIVE_CALL_RET_GREG, 6584 true /*f64Bit*/, offReturnBreak); 6585 6586 /* Okay, continue executing the next TB. */ 6587 off = iemNativeEmitJmpViaGpr(pReNative, off, IEMNATIVE_CALL_RET_GREG); 6588 return off; 6589 } 6590 6591 #ifndef IEMNATIVE_WITH_RECOMPILER_PER_CHUNK_TAIL_CODE 6592 6593 /** 6497 6594 * Worker for iemNativeEmitReturnBreakViaLookup. 6498 6595 */ 6499 static uint32_t iemNativeEmitViaLookupDoOne(PIEMRECOMPILERSTATE pReNative, uint32_t off, uint32_t idxLabelReturnBreak,6596 static uint32_t iemNativeEmitViaLookupDoOne(PIEMRECOMPILERSTATE pReNative, uint32_t off, uint32_t offReturnBreak, 6500 6597 IEMNATIVELABELTYPE enmLabel, uintptr_t pfnHelper) 6501 6598 { … … 6504 6601 { 6505 6602 iemNativeLabelDefine(pReNative, idxLabel, off); 6506 6507 off = iemNativeEmitLoadGprFromGpr(pReNative, off, IEMNATIVE_CALL_ARG0_GREG, IEMNATIVE_REG_FIXED_PVMCPU); 6508 off = iemNativeEmitCallImm(pReNative, off, pfnHelper); 6509 6510 /* Jump to ReturnBreak if the return register is NULL. */ 6511 off = iemNativeEmitTestIfGprIsZeroAndJmpToLabel(pReNative, off, IEMNATIVE_CALL_RET_GREG, 6512 true /*f64Bit*/, idxLabelReturnBreak); 6513 6514 /* Okay, continue executing the next TB. */ 6515 off = iemNativeEmitJmpViaGpr(pReNative, off, IEMNATIVE_CALL_RET_GREG); 6603 off = iemNativeEmitCoreViaLookupDoOne(pReNative, off, offReturnBreak, pfnHelper); 6516 6604 } 6517 6605 return off; 6518 6606 } 6607 6519 6608 6520 6609 /** … … 6523 6612 * (returns VINF_IEM_REEXEC_FINISH_WITH_FLAGS or jumps to the next TB). 6524 6613 */ 6525 static uint32_t iemNativeEmitReturnBreakViaLookup(PIEMRECOMPILERSTATE pReNative, uint32_t off) 6526 { 6527 uint32_t const idxLabelReturnBreak = iemNativeLabelCreate(pReNative, kIemNativeLabelType_ReturnBreak); 6614 static uint32_t iemNativeEmitReturnBreakViaLookup(PIEMRECOMPILERSTATE pReNative, uint32_t off, uint32_t idxReturnBreakLabel) 6615 { 6616 uint32_t const offReturnBreak = pReNative->paLabels[idxReturnBreakLabel].off; 6617 Assert(offReturnBreak < off); 6528 6618 6529 6619 /* … … 6531 6621 * The GCPhysPc is in IEMNATIVE_CALL_ARG2_GREG for ReturnBreakViaLookupWithPc. 6532 6622 */ 6533 off = iemNativeEmitViaLookupDoOne(pReNative, off, idxLabelReturnBreak, kIemNativeLabelType_ReturnBreakViaLookup,6623 off = iemNativeEmitViaLookupDoOne(pReNative, off, offReturnBreak, kIemNativeLabelType_ReturnBreakViaLookup, 6534 6624 (uintptr_t)iemNativeHlpReturnBreakViaLookup<false /*a_fWithIrqCheck*/>); 6535 off = iemNativeEmitViaLookupDoOne(pReNative, off, idxLabelReturnBreak, kIemNativeLabelType_ReturnBreakViaLookupWithIrq,6625 off = iemNativeEmitViaLookupDoOne(pReNative, off, offReturnBreak, kIemNativeLabelType_ReturnBreakViaLookupWithIrq, 6536 6626 (uintptr_t)iemNativeHlpReturnBreakViaLookup<true /*a_fWithIrqCheck*/>); 6537 off = iemNativeEmitViaLookupDoOne(pReNative, off, idxLabelReturnBreak, kIemNativeLabelType_ReturnBreakViaLookupWithTlb,6627 off = iemNativeEmitViaLookupDoOne(pReNative, off, offReturnBreak, kIemNativeLabelType_ReturnBreakViaLookupWithTlb, 6538 6628 (uintptr_t)iemNativeHlpReturnBreakViaLookupWithTlb<false /*a_fWithIrqCheck*/>); 6539 off = iemNativeEmitViaLookupDoOne(pReNative, off, idxLabelReturnBreak, kIemNativeLabelType_ReturnBreakViaLookupWithTlbAndIrq,6629 off = iemNativeEmitViaLookupDoOne(pReNative, off, offReturnBreak, kIemNativeLabelType_ReturnBreakViaLookupWithTlbAndIrq, 6540 6630 (uintptr_t)iemNativeHlpReturnBreakViaLookupWithTlb<true /*a_fWithIrqCheck*/>); 6541 6631 return off; 6542 6632 } 6543 6633 6544 6634 #endif /* !IEMNATIVE_WITH_RECOMPILER_PER_CHUNK_TAIL_CODE */ 6635 6636 /** 6637 * Emits the code at the ReturnWithFlags label (returns VINF_IEM_REEXEC_FINISH_WITH_FLAGS). 6638 */ 6639 static uint32_t iemNativeEmitCoreReturnWithFlags(PIEMRECOMPILERSTATE pReNative, uint32_t off) 6640 { 6641 /* set the return status */ 6642 return iemNativeEmitLoadGprImm64(pReNative, off, IEMNATIVE_CALL_RET_GREG, VINF_IEM_REEXEC_FINISH_WITH_FLAGS); 6643 } 6644 6645 6646 #ifndef IEMNATIVE_WITH_RECOMPILER_PER_CHUNK_TAIL_CODE 6545 6647 /** 6546 6648 * Emits the code at the ReturnWithFlags label (returns VINF_IEM_REEXEC_FINISH_WITH_FLAGS). … … 6553 6655 iemNativeLabelDefine(pReNative, idxLabel, off); 6554 6656 /* set the return status */ 6555 off = iemNativeEmit LoadGprImm64(pReNative, off, IEMNATIVE_CALL_RET_GREG, VINF_IEM_REEXEC_FINISH_WITH_FLAGS);6657 off = iemNativeEmitCoreReturnWithFlags(pReNative, off); 6556 6658 /* jump back to the return sequence. */ 6557 6659 off = iemNativeEmitJmpToLabel(pReNative, off, idxReturnLabel); … … 6559 6661 return off; 6560 6662 } 6561 6562 6663 #endif 6664 6665 6666 /** 6667 * Emits the code at the ReturnBreakFF label (returns VINF_IEM_REEXEC_BREAK_FF). 6668 */ 6669 static uint32_t iemNativeEmitCoreReturnBreakFF(PIEMRECOMPILERSTATE pReNative, uint32_t off) 6670 { 6671 /* set the return status */ 6672 return iemNativeEmitLoadGprImm64(pReNative, off, IEMNATIVE_CALL_RET_GREG, VINF_IEM_REEXEC_BREAK_FF); 6673 } 6674 6675 6676 #ifndef IEMNATIVE_WITH_RECOMPILER_PER_CHUNK_TAIL_CODE 6563 6677 /** 6564 6678 * Emits the code at the ReturnBreakFF label (returns VINF_IEM_REEXEC_BREAK_FF). … … 6571 6685 iemNativeLabelDefine(pReNative, idxLabel, off); 6572 6686 /* set the return status */ 6573 off = iemNativeEmit LoadGprImm64(pReNative, off, IEMNATIVE_CALL_RET_GREG, VINF_IEM_REEXEC_BREAK_FF);6687 off = iemNativeEmitCoreReturnBreakFF(pReNative, off); 6574 6688 /* jump back to the return sequence. */ 6575 6689 off = iemNativeEmitJmpToLabel(pReNative, off, idxReturnLabel); … … 6577 6691 return off; 6578 6692 } 6579 6580 6693 #endif 6694 6695 6696 /** 6697 * Emits the code at the ReturnBreak label (returns VINF_IEM_REEXEC_BREAK). 6698 */ 6699 static uint32_t iemNativeEmitCoreReturnBreak(PIEMRECOMPILERSTATE pReNative, uint32_t off) 6700 { 6701 /* set the return status */ 6702 return iemNativeEmitLoadGprImm64(pReNative, off, IEMNATIVE_CALL_RET_GREG, VINF_IEM_REEXEC_BREAK); 6703 } 6704 6705 6706 #ifndef IEMNATIVE_WITH_RECOMPILER_PER_CHUNK_TAIL_CODE 6581 6707 /** 6582 6708 * Emits the code at the ReturnBreak label (returns VINF_IEM_REEXEC_BREAK). … … 6589 6715 iemNativeLabelDefine(pReNative, idxLabel, off); 6590 6716 /* set the return status */ 6591 off = iemNativeEmit LoadGprImm64(pReNative, off, IEMNATIVE_CALL_RET_GREG, VINF_IEM_REEXEC_BREAK);6717 off = iemNativeEmitCoreReturnBreak(pReNative, off); 6592 6718 /* jump back to the return sequence. */ 6593 6719 off = iemNativeEmitJmpToLabel(pReNative, off, idxReturnLabel); … … 6595 6721 return off; 6596 6722 } 6597 6598 6723 #endif 6724 6725 6726 /** 6727 * Emits the RC fiddling code for handling non-zero return code or rcPassUp. 6728 */ 6729 static uint32_t iemNativeEmitCoreRcFiddling(PIEMRECOMPILERSTATE pReNative, uint32_t off) 6730 { 6731 /* 6732 * Generate the rc + rcPassUp fiddling code. 6733 */ 6734 /* iemNativeHlpExecStatusCodeFiddling(PVMCPUCC pVCpu, int rc, uint8_t idxInstr) */ 6735 #ifdef RT_ARCH_AMD64 6736 # ifdef RT_OS_WINDOWS 6737 # ifdef IEMNATIVE_WITH_INSTRUCTION_COUNTING 6738 off = iemNativeEmitLoadGprFromGpr(pReNative, off, X86_GREG_x8, X86_GREG_xCX); /* cl = instruction number */ 6739 # endif 6740 off = iemNativeEmitLoadGprFromGpr(pReNative, off, X86_GREG_xCX, IEMNATIVE_REG_FIXED_PVMCPU); 6741 off = iemNativeEmitLoadGprFromGpr(pReNative, off, X86_GREG_xDX, X86_GREG_xAX); 6742 # else 6743 off = iemNativeEmitLoadGprFromGpr(pReNative, off, X86_GREG_xDI, IEMNATIVE_REG_FIXED_PVMCPU); 6744 off = iemNativeEmitLoadGprFromGpr(pReNative, off, X86_GREG_xSI, X86_GREG_xAX); 6745 # ifdef IEMNATIVE_WITH_INSTRUCTION_COUNTING 6746 off = iemNativeEmitLoadGprFromGpr(pReNative, off, X86_GREG_xDX, X86_GREG_xCX); /* cl = instruction number */ 6747 # endif 6748 # endif 6749 # ifndef IEMNATIVE_WITH_INSTRUCTION_COUNTING 6750 off = iemNativeEmitLoadGpr8Imm(pReNative, off, X86_GREG_xCX, 0); 6751 # endif 6752 6753 #else 6754 off = iemNativeEmitLoadGprFromGpr(pReNative, off, IEMNATIVE_CALL_ARG1_GREG, IEMNATIVE_CALL_RET_GREG); 6755 off = iemNativeEmitLoadGprFromGpr(pReNative, off, IEMNATIVE_CALL_ARG0_GREG, IEMNATIVE_REG_FIXED_PVMCPU); 6756 /* IEMNATIVE_CALL_ARG2_GREG is already set. */ 6757 #endif 6758 6759 off = iemNativeEmitCallImm(pReNative, off, (uintptr_t)iemNativeHlpExecStatusCodeFiddling); 6760 return off; 6761 } 6762 6763 6764 #ifndef IEMNATIVE_WITH_RECOMPILER_PER_CHUNK_TAIL_CODE 6599 6765 /** 6600 6766 * Emits the RC fiddling code for handling non-zero return code or rcPassUp. … … 6609 6775 { 6610 6776 iemNativeLabelDefine(pReNative, idxLabel, off); 6611 6612 /* iemNativeHlpExecStatusCodeFiddling(PVMCPUCC pVCpu, int rc, uint8_t idxInstr) */ 6613 #ifdef RT_ARCH_AMD64 6614 # ifdef RT_OS_WINDOWS 6615 # ifdef IEMNATIVE_WITH_INSTRUCTION_COUNTING 6616 off = iemNativeEmitLoadGprFromGpr(pReNative, off, X86_GREG_x8, X86_GREG_xCX); /* cl = instruction number */ 6617 # endif 6618 off = iemNativeEmitLoadGprFromGpr(pReNative, off, X86_GREG_xCX, IEMNATIVE_REG_FIXED_PVMCPU); 6619 off = iemNativeEmitLoadGprFromGpr(pReNative, off, X86_GREG_xDX, X86_GREG_xAX); 6620 # else 6621 off = iemNativeEmitLoadGprFromGpr(pReNative, off, X86_GREG_xDI, IEMNATIVE_REG_FIXED_PVMCPU); 6622 off = iemNativeEmitLoadGprFromGpr(pReNative, off, X86_GREG_xSI, X86_GREG_xAX); 6623 # ifdef IEMNATIVE_WITH_INSTRUCTION_COUNTING 6624 off = iemNativeEmitLoadGprFromGpr(pReNative, off, X86_GREG_xDX, X86_GREG_xCX); /* cl = instruction number */ 6625 # endif 6626 # endif 6627 # ifndef IEMNATIVE_WITH_INSTRUCTION_COUNTING 6628 off = iemNativeEmitLoadGpr8Imm(pReNative, off, X86_GREG_xCX, 0); 6629 # endif 6630 6631 #else 6632 off = iemNativeEmitLoadGprFromGpr(pReNative, off, IEMNATIVE_CALL_ARG1_GREG, IEMNATIVE_CALL_RET_GREG); 6633 off = iemNativeEmitLoadGprFromGpr(pReNative, off, IEMNATIVE_CALL_ARG0_GREG, IEMNATIVE_REG_FIXED_PVMCPU); 6634 /* IEMNATIVE_CALL_ARG2_GREG is already set. */ 6635 #endif 6636 6637 off = iemNativeEmitCallImm(pReNative, off, (uintptr_t)iemNativeHlpExecStatusCodeFiddling); 6777 off = iemNativeEmitCoreRcFiddling(pReNative, off); 6638 6778 off = iemNativeEmitJmpToLabel(pReNative, off, idxReturnLabel); 6639 6779 } 6640 6780 return off; 6641 6781 } 6782 #endif 6642 6783 6643 6784 … … 6645 6786 * Emits a standard epilog. 6646 6787 */ 6647 static uint32_t iemNativeEmitEpilog(PIEMRECOMPILERSTATE pReNative, uint32_t off, uint32_t *pidxReturnLabel) 6648 { 6649 *pidxReturnLabel = UINT32_MAX; 6650 6651 /* Flush any pending writes before returning from the last instruction (RIP updates, etc.). */ 6652 off = iemNativeRegFlushPendingWrites(pReNative, off); 6653 6654 /* 6655 * Successful return, so clear the return register (eax, w0). 6656 */ 6657 pReNative->Core.bmHstRegs |= RT_BIT_32(IEMNATIVE_CALL_RET_GREG); /* HACK: For IEMNATIVE_STRICT_EFLAGS_SKIPPING_EMIT_CHECK. */ 6658 off = iemNativeEmitGprZero(pReNative, off, IEMNATIVE_CALL_RET_GREG); 6659 6660 /* 6661 * Define label for common return point. 6662 */ 6663 uint32_t const idxReturn = iemNativeLabelCreate(pReNative, kIemNativeLabelType_Return, off); 6664 *pidxReturnLabel = idxReturn; 6788 static uint32_t iemNativeEmitCoreEpilog(PIEMRECOMPILERSTATE pReNative, uint32_t off) 6789 { 6790 pReNative->Core.bmHstRegs |= RT_BIT_32(IEMNATIVE_CALL_RET_GREG); /* HACK: For IEMNATIVE_STRICT_EFLAGS_SKIPPING_EMIT_CHECK (return register is already set to status code). */ 6665 6791 6666 6792 IEMNATIVE_STRICT_EFLAGS_SKIPPING_EMIT_CHECK(pReNative, off, X86_EFL_STATUS_BITS); 6667 6793 6668 #ifdef IEMNATIVE_WITH_RECOMPILER_EPILOGUE_SINGLETON 6669 //off = iemNativeEmitBrk(pReNative, off, 0x7777); 6670 off = iemNativeEmitJmpImm(pReNative, off, (uintptr_t)iemNativeTbEpilog); 6671 #else 6794 /* HACK: For IEMNATIVE_STRICT_EFLAGS_SKIPPING_EMIT_CHECK (return register is already set to status code). */ 6795 pReNative->Core.bmHstRegs &= ~RT_BIT_32(IEMNATIVE_CALL_RET_GREG); 6796 6672 6797 /* 6673 6798 * Restore registers and return. 6674 6799 */ 6675 # 6800 #ifdef RT_ARCH_AMD64 6676 6801 uint8_t * const pbCodeBuf = iemNativeInstrBufEnsure(pReNative, off, 20); 6677 6802 … … 6691 6816 pbCodeBuf[off++] = X86_OP_REX_B; /* pop r12 */ 6692 6817 pbCodeBuf[off++] = 0x58 + X86_GREG_x12 - 8; 6693 # 6818 # ifdef RT_OS_WINDOWS 6694 6819 pbCodeBuf[off++] = 0x58 + X86_GREG_xDI; /* pop rdi */ 6695 6820 pbCodeBuf[off++] = 0x58 + X86_GREG_xSI; /* pop rsi */ 6696 # 6821 # endif 6697 6822 pbCodeBuf[off++] = 0x58 + X86_GREG_xBX; /* pop rbx */ 6698 6823 pbCodeBuf[off++] = 0xc9; /* leave */ … … 6700 6825 pbCodeBuf[off++] = 0xcc; /* int3 poison */ 6701 6826 6702 # 6827 #elif RT_ARCH_ARM64 6703 6828 uint32_t * const pu32CodeBuf = iemNativeInstrBufEnsure(pReNative, off, 10); 6704 6829 … … 6727 6852 6728 6853 /* retab / ret */ 6729 # 6854 # ifdef RT_OS_DARWIN /** @todo See todo on pacibsp in the prolog. */ 6730 6855 if (1) 6731 6856 pu32CodeBuf[off++] = ARMV8_A64_INSTR_RETAB; 6732 6857 else 6733 # 6858 # endif 6734 6859 pu32CodeBuf[off++] = ARMV8_A64_INSTR_RET; 6735 6860 6736 # 6737 # 6738 # 6861 #else 6862 # error "port me" 6863 #endif 6739 6864 IEMNATIVE_ASSERT_INSTR_BUF_ENSURE(pReNative, off); 6740 #endif /* IEMNATIVE_WITH_RECOMPILER_EPILOGUE_SINGLETON */6741 6865 6742 6866 /* HACK: For IEMNATIVE_STRICT_EFLAGS_SKIPPING_EMIT_CHECK. */ 6743 6867 pReNative->Core.bmHstRegs &= ~RT_BIT_32(IEMNATIVE_CALL_RET_GREG); 6744 6868 6745 return iemNativeEmitRcFiddling(pReNative, off, idxReturn); 6746 } 6869 return off; 6870 } 6871 6872 6873 #ifndef IEMNATIVE_WITH_RECOMPILER_PER_CHUNK_TAIL_CODE 6874 /** 6875 * Emits a standard epilog. 6876 */ 6877 static uint32_t iemNativeEmitEpilog(PIEMRECOMPILERSTATE pReNative, uint32_t off, uint32_t *pidxReturnLabel) 6878 { 6879 /* 6880 * Define label for common return point. 6881 */ 6882 *pidxReturnLabel = UINT32_MAX; 6883 uint32_t const idxReturn = iemNativeLabelCreate(pReNative, kIemNativeLabelType_Return, off); 6884 *pidxReturnLabel = idxReturn; 6885 6886 /* 6887 * Emit the code. 6888 */ 6889 return iemNativeEmitCoreEpilog(pReNative, off); 6890 } 6891 #endif 6747 6892 6748 6893 … … 8768 8913 8769 8914 8770 DECLHIDDEN(void) iemNativeDisassembleTb(PCIEMTB pTb, PCDBGFINFOHLP pHlp) RT_NOEXCEPT 8915 /** 8916 * Translates a label to a name. 8917 */ 8918 static const char *iemNativeGetLabelName(IEMNATIVELABELTYPE enmLabel, bool fCommonCode /*= false*/) 8919 { 8920 switch (enmLabel) 8921 { 8922 #define STR_CASE_CMN(a_Label) case kIemNativeLabelType_ ## a_Label: return fCommonCode ? "Chunk_" #a_Label : #a_Label; 8923 STR_CASE_CMN(Invalid); 8924 STR_CASE_CMN(RaiseDe); 8925 STR_CASE_CMN(RaiseUd); 8926 STR_CASE_CMN(RaiseSseRelated); 8927 STR_CASE_CMN(RaiseAvxRelated); 8928 STR_CASE_CMN(RaiseSseAvxFpRelated); 8929 STR_CASE_CMN(RaiseNm); 8930 STR_CASE_CMN(RaiseGp0); 8931 STR_CASE_CMN(RaiseMf); 8932 STR_CASE_CMN(RaiseXf); 8933 STR_CASE_CMN(ObsoleteTb); 8934 STR_CASE_CMN(NeedCsLimChecking); 8935 STR_CASE_CMN(CheckBranchMiss); 8936 STR_CASE_CMN(Return); 8937 STR_CASE_CMN(ReturnBreak); 8938 STR_CASE_CMN(ReturnBreakFF); 8939 STR_CASE_CMN(ReturnWithFlags); 8940 STR_CASE_CMN(ReturnBreakViaLookup); 8941 STR_CASE_CMN(ReturnBreakViaLookupWithIrq); 8942 STR_CASE_CMN(ReturnBreakViaLookupWithTlb); 8943 STR_CASE_CMN(ReturnBreakViaLookupWithTlbAndIrq); 8944 STR_CASE_CMN(NonZeroRetOrPassUp); 8945 #undef STR_CASE_CMN 8946 #define STR_CASE_LBL(a_Label) case kIemNativeLabelType_ ## a_Label: return #a_Label; 8947 STR_CASE_LBL(If); 8948 STR_CASE_LBL(Else); 8949 STR_CASE_LBL(Endif); 8950 STR_CASE_LBL(CheckIrq); 8951 STR_CASE_LBL(TlbLookup); 8952 STR_CASE_LBL(TlbMiss); 8953 STR_CASE_LBL(TlbDone); 8954 case kIemNativeLabelType_End: break; 8955 } 8956 return NULL; 8957 } 8958 8959 8960 /** Info for the symbols resolver used when disassembling. */ 8961 typedef struct IEMNATIVDISASMSYMCTX 8962 { 8963 PVMCPU pVCpu; 8964 # ifdef IEMNATIVE_WITH_RECOMPILER_PER_CHUNK_TAIL_CODE 8965 PCIEMNATIVEPERCHUNKCTX pCtx; 8966 # endif 8967 } IEMNATIVDISASMSYMCTX; 8968 typedef IEMNATIVDISASMSYMCTX *PIEMNATIVDISASMSYMCTX; 8969 8970 8971 /** 8972 * Resolve address to symbol, if we can. 8973 */ 8974 static const char *iemNativeDisasmGetSymbol(PIEMNATIVDISASMSYMCTX pSymCtx, uintptr_t uAddress) 8975 { 8976 #ifdef IEMNATIVE_WITH_RECOMPILER_PER_CHUNK_TAIL_CODE 8977 PCIEMNATIVEPERCHUNKCTX pChunkCtx = pSymCtx->pCtx; 8978 if (pChunkCtx) 8979 for (uint32_t i = 1; i < RT_ELEMENTS(pChunkCtx->apExitLabels); i++) 8980 if ((PIEMNATIVEINSTR)uAddress == pChunkCtx->apExitLabels[i]) 8981 return iemNativeGetLabelName((IEMNATIVELABELTYPE)i, true /*fCommonCode*/); 8982 #endif 8983 return NULL; 8984 } 8985 8986 #ifndef VBOX_WITH_IEM_USING_CAPSTONE_DISASSEMBLER 8987 8988 /** 8989 * @callback_method_impl{FNDISGETSYMBOL} 8990 */ 8991 static DECLCALLBACK(int) iemNativeDisasmGetSymbolCb(PCDISSTATE pDis, uint32_t u32Sel, RTUINTPTR uAddress, 8992 char *pszBuf, size_t cchBuf, RTINTPTR *poff, void *pvUser) 8993 { 8994 const char * const pszSym = iemNativeDisasmGetSymbol((PIEMNATIVDISASMSYMCTX)pvUser, uAddress); 8995 if (pszSym) 8996 { 8997 *poff = 0; 8998 return RTStrCopy(pszBuf, cchBuf, pszSym); 8999 } 9000 RT_NOREF(pDis, u32Sel); 9001 return VERR_SYMBOL_NOT_FOUND; 9002 } 9003 9004 #else /* VBOX_WITH_IEM_USING_CAPSTONE_DISASSEMBLER */ 9005 9006 /** 9007 * Annotates an instruction decoded by the capstone disassembler. 9008 */ 9009 static const char * 9010 iemNativeDisasmAnnotateCapstone(PIEMNATIVDISASMSYMCTX pSymCtx, cs_insn const *pInstr, char *pszBuf, size_t cchBuf) 9011 { 9012 # if defined(RT_ARCH_ARM64) 9013 if ( (pInstr->id >= ARM64_INS_LD1 && pInstr->id < ARM64_INS_LSL) 9014 || (pInstr->id >= ARM64_INS_ST1 && pInstr->id < ARM64_INS_SUB)) 9015 { 9016 /* This is bit crappy, but the disassembler provides incomplete addressing details. */ 9017 AssertCompile(IEMNATIVE_REG_FIXED_PVMCPU == 28 && IEMNATIVE_REG_FIXED_PCPUMCTX == 27); 9018 char const *psz = strchr(pInstr->op_str, '['); 9019 if (psz && psz[1] == 'x' && psz[2] == '2' && (psz[3] == '7' || psz[3] == '8')) 9020 { 9021 uint32_t const offVCpu = psz[3] == '8'? 0 : RT_UOFFSETOF(VMCPU, cpum.GstCtx); 9022 int32_t off = -1; 9023 psz += 4; 9024 if (*psz == ']') 9025 off = 0; 9026 else if (*psz == ',') 9027 { 9028 psz = RTStrStripL(psz + 1); 9029 if (*psz == '#') 9030 off = RTStrToInt32(&psz[1]); 9031 /** @todo deal with index registers and LSL as well... */ 9032 } 9033 if (off >= 0) 9034 return iemNativeDbgVCpuOffsetToName(offVCpu + (uint32_t)off); 9035 } 9036 } 9037 else if (pInstr->id == ARM64_INS_B || pInstr->id == ARM64_INS_BL) 9038 { 9039 const char *pszAddr = strchr(pInstr->op_str, '#'); 9040 if (pszAddr) 9041 { 9042 uint64_t uAddr = RTStrToUInt64(pszAddr + 1); 9043 if (uAddr != 0) 9044 return iemNativeDisasmGetSymbol(pSymCtx, uAddr); 9045 } 9046 } 9047 # endif 9048 RT_NOREF(pszBuf, cchBuf); 9049 return NULL; 9050 } 9051 #endif /* VBOX_WITH_IEM_USING_CAPSTONE_DISASSEMBLER */ 9052 9053 9054 DECLHIDDEN(void) iemNativeDisassembleTb(PVMCPU pVCpu, PCIEMTB pTb, PCDBGFINFOHLP pHlp) RT_NOEXCEPT 8771 9055 { 8772 9056 AssertReturnVoid((pTb->fFlags & IEMTB_F_TYPE_MASK) == IEMTB_F_TYPE_NATIVE); … … 8790 9074 : (pTb->fFlags & IEM_F_MODE_CPUMODE_MASK) == IEMMODE_32BIT ? DISCPUMODE_32BIT 8791 9075 : DISCPUMODE_64BIT; 9076 #ifdef IEMNATIVE_WITH_RECOMPILER_PER_CHUNK_TAIL_CODE 9077 IEMNATIVDISASMSYMCTX SymCtx = { pVCpu, iemExecMemGetTbChunkCtx(pVCpu, pTb) }; 9078 #else 9079 IEMNATIVDISASMSYMCTX SymCtx = { pVCpu }; 9080 #endif 8792 9081 #if defined(RT_ARCH_AMD64) && !defined(VBOX_WITH_IEM_USING_CAPSTONE_DISASSEMBLER) 8793 9082 DISCPUMODE const enmHstCpuMode = DISCPUMODE_64BIT; … … 8980 9269 case kIemTbDbgEntryType_Label: 8981 9270 { 8982 const char *pszName = "what_the_fudge"; 8983 const char *pszComment = ""; 8984 bool fNumbered = pDbgInfo->aEntries[iDbgEntry].Label.uData != 0; 8985 switch ((IEMNATIVELABELTYPE)pDbgInfo->aEntries[iDbgEntry].Label.enmLabel) 9271 const char *pszName = iemNativeGetLabelName((IEMNATIVELABELTYPE)pDbgInfo->aEntries[iDbgEntry].Label.enmLabel); 9272 if (pDbgInfo->aEntries[iDbgEntry].Label.enmLabel >= kIemNativeLabelType_FirstWithMultipleInstances) 8986 9273 { 8987 case kIemNativeLabelType_Return: pszName = "Return"; break; 8988 case kIemNativeLabelType_ReturnBreak: pszName = "ReturnBreak"; break; 8989 case kIemNativeLabelType_ReturnBreakFF: pszName = "ReturnBreakFF"; break; 8990 case kIemNativeLabelType_ReturnWithFlags: pszName = "ReturnWithFlags"; break; 8991 case kIemNativeLabelType_ReturnBreakViaLookup: pszName = "ReturnBreakViaLookup"; break; 8992 case kIemNativeLabelType_ReturnBreakViaLookupWithIrq: pszName = "ReturnBreakViaLookupWithIrq"; break; 8993 case kIemNativeLabelType_ReturnBreakViaLookupWithTlb: pszName = "ReturnBreakViaLookupWithTlb"; break; 8994 case kIemNativeLabelType_ReturnBreakViaLookupWithTlbAndIrq: pszName = "ReturnBreakViaLookupWithTlbAndIrq"; break; 8995 case kIemNativeLabelType_NonZeroRetOrPassUp: pszName = "NonZeroRetOrPassUp"; break; 8996 case kIemNativeLabelType_RaiseDe: pszName = "RaiseDe"; break; 8997 case kIemNativeLabelType_RaiseUd: pszName = "RaiseUd"; break; 8998 case kIemNativeLabelType_RaiseSseRelated: pszName = "RaiseSseRelated"; break; 8999 case kIemNativeLabelType_RaiseAvxRelated: pszName = "RaiseAvxRelated"; break; 9000 case kIemNativeLabelType_RaiseSseAvxFpRelated: pszName = "RaiseSseAvxFpRelated"; break; 9001 case kIemNativeLabelType_RaiseNm: pszName = "RaiseNm"; break; 9002 case kIemNativeLabelType_RaiseGp0: pszName = "RaiseGp0"; break; 9003 case kIemNativeLabelType_RaiseMf: pszName = "RaiseMf"; break; 9004 case kIemNativeLabelType_RaiseXf: pszName = "RaiseXf"; break; 9005 case kIemNativeLabelType_ObsoleteTb: pszName = "ObsoleteTb"; break; 9006 case kIemNativeLabelType_NeedCsLimChecking: pszName = "NeedCsLimChecking"; break; 9007 case kIemNativeLabelType_CheckBranchMiss: pszName = "CheckBranchMiss"; break; 9008 case kIemNativeLabelType_If: 9009 pszName = "If"; 9010 fNumbered = true; 9011 break; 9012 case kIemNativeLabelType_Else: 9013 pszName = "Else"; 9014 fNumbered = true; 9015 pszComment = " ; regs state restored pre-if-block"; 9016 break; 9017 case kIemNativeLabelType_Endif: 9018 pszName = "Endif"; 9019 fNumbered = true; 9020 break; 9021 case kIemNativeLabelType_CheckIrq: 9022 pszName = "CheckIrq_CheckVM"; 9023 fNumbered = true; 9024 break; 9025 case kIemNativeLabelType_TlbLookup: 9026 pszName = "TlbLookup"; 9027 fNumbered = true; 9028 break; 9029 case kIemNativeLabelType_TlbMiss: 9030 pszName = "TlbMiss"; 9031 fNumbered = true; 9032 break; 9033 case kIemNativeLabelType_TlbDone: 9034 pszName = "TlbDone"; 9035 fNumbered = true; 9036 break; 9037 case kIemNativeLabelType_Invalid: 9038 case kIemNativeLabelType_End: 9039 break; 9274 const char *pszComment = pDbgInfo->aEntries[iDbgEntry].Label.enmLabel == kIemNativeLabelType_Else 9275 ? " ; regs state restored pre-if-block" : ""; 9276 pHlp->pfnPrintf(pHlp, " %s_%u:%s\n", pszName, pDbgInfo->aEntries[iDbgEntry].Label.uData, pszComment); 9040 9277 } 9041 if (fNumbered)9042 pHlp->pfnPrintf(pHlp, " %s_%u:%s\n", pszName, pDbgInfo->aEntries[iDbgEntry].Label.uData, pszComment);9043 9278 else 9044 9279 pHlp->pfnPrintf(pHlp, " %s:\n", pszName); … … 9121 9356 DIS_FMT_FLAGS_BYTES_WIDTH_MAKE(10) | DIS_FMT_FLAGS_BYTES_LEFT 9122 9357 | DIS_FMT_FLAGS_RELATIVE_BRANCH | DIS_FMT_FLAGS_C_HEX, 9123 NULL /*pfnGetSymbol*/, NULL /*pvUser*/);9358 iemNativeDisasmGetSymbolCb, &SymCtx); 9124 9359 PCDISOPPARAM pMemOp; 9125 9360 if (DISUSE_IS_EFFECTIVE_ADDR(Dis.Param1.fUse)) … … 9186 9421 { 9187 9422 Assert(cInstrs == 1); 9188 const char *pszAnnotation = NULL; 9189 # if defined(RT_ARCH_ARM64) 9190 if ( (pInstr->id >= ARM64_INS_LD1 && pInstr->id < ARM64_INS_LSL) 9191 || (pInstr->id >= ARM64_INS_ST1 && pInstr->id < ARM64_INS_SUB)) 9192 { 9193 /* This is bit crappy, but the disassembler provides incomplete addressing details. */ 9194 AssertCompile(IEMNATIVE_REG_FIXED_PVMCPU == 28 && IEMNATIVE_REG_FIXED_PCPUMCTX == 27); 9195 char *psz = strchr(pInstr->op_str, '['); 9196 if (psz && psz[1] == 'x' && psz[2] == '2' && (psz[3] == '7' || psz[3] == '8')) 9197 { 9198 uint32_t const offVCpu = psz[3] == '8'? 0 : RT_UOFFSETOF(VMCPU, cpum.GstCtx); 9199 int32_t off = -1; 9200 psz += 4; 9201 if (*psz == ']') 9202 off = 0; 9203 else if (*psz == ',') 9204 { 9205 psz = RTStrStripL(psz + 1); 9206 if (*psz == '#') 9207 off = RTStrToInt32(&psz[1]); 9208 /** @todo deal with index registers and LSL as well... */ 9209 } 9210 if (off >= 0) 9211 pszAnnotation = iemNativeDbgVCpuOffsetToName(offVCpu + (uint32_t)off); 9212 } 9213 } 9214 # endif 9215 9216 size_t const cchOp = strlen(pInstr->op_str); 9423 const char * const pszAnnotation = iemNativeDisasmAnnotateCapstone(&SymCtx, pInstr, szDisBuf, sizeof(szDisBuf)); 9424 size_t const cchOp = strlen(pInstr->op_str); 9217 9425 # if defined(RT_ARCH_AMD64) 9218 9426 if (pszAnnotation) … … 9326 9534 DIS_FMT_FLAGS_BYTES_WIDTH_MAKE(10) | DIS_FMT_FLAGS_BYTES_LEFT 9327 9535 | DIS_FMT_FLAGS_RELATIVE_BRANCH | DIS_FMT_FLAGS_C_HEX, 9328 NULL /*pfnGetSymbol*/, NULL /*pvUser*/);9536 iemNativeDisasmGetSymbolCb, &SymCtx); 9329 9537 # elif defined(RT_ARCH_ARM64) 9330 9538 DISFormatArmV8Ex(&Dis, szDisBuf, sizeof(szDisBuf), 9331 9539 DIS_FMT_FLAGS_BYTES_LEFT | DIS_FMT_FLAGS_RELATIVE_BRANCH | DIS_FMT_FLAGS_C_HEX, 9332 NULL /*pfnGetSymbol*/, NULL /*pvUser*/);9540 iemNativeDisasmGetSymbolCb, &SymCtx); 9333 9541 # else 9334 9542 # error "Port me" … … 9356 9564 { 9357 9565 Assert(cInstrs == 1); 9566 const char * const pszAnnotation = iemNativeDisasmAnnotateCapstone(&SymCtx, pInstr, szDisBuf, sizeof(szDisBuf)); 9567 size_t const cchOp = strlen(pInstr->op_str); 9358 9568 # if defined(RT_ARCH_AMD64) 9359 pHlp->pfnPrintf(pHlp, " %p: %.*Rhxs %-7s %s\n", 9360 pNativeCur, pInstr->size, pNativeCur, pInstr->mnemonic, pInstr->op_str); 9569 if (pszAnnotation) 9570 pHlp->pfnPrintf(pHlp, " %p: %.*Rhxs %-7s %s%*s ; %s\n", 9571 pNativeCur, pInstr->size, pNativeCur, pInstr->mnemonic, pInstr->op_str, 9572 cchOp < 55 ? 55 - cchOp : 0, "", pszAnnotation); 9573 else 9574 pHlp->pfnPrintf(pHlp, " %p: %.*Rhxs %-7s %s\n", 9575 pNativeCur, pInstr->size, pNativeCur, pInstr->mnemonic, pInstr->op_str); 9576 9361 9577 # else 9362 pHlp->pfnPrintf(pHlp, " %p: %#010RX32 %-7s %s\n", 9363 pNativeCur, *pNativeCur, pInstr->mnemonic, pInstr->op_str); 9578 if (pszAnnotation) 9579 pHlp->pfnPrintf(pHlp, " %p: %#010RX32 %-7s %s%*s ; %s\n", 9580 pNativeCur, *pNativeCur, pInstr->mnemonic, pInstr->op_str, 9581 cchOp < 55 ? 55 - cchOp : 0, "", pszAnnotation); 9582 else 9583 pHlp->pfnPrintf(pHlp, " %p: %#010RX32 %-7s %s\n", 9584 pNativeCur, *pNativeCur, pInstr->mnemonic, pInstr->op_str); 9364 9585 # endif 9365 9586 offNative += pInstr->size / sizeof(*pNativeCur); … … 9387 9608 9388 9609 9610 #ifdef IEMNATIVE_WITH_RECOMPILER_PER_CHUNK_TAIL_CODE 9611 9612 /** Emit alignment padding between labels / functions. */ 9613 DECL_INLINE_THROW(uint32_t) 9614 iemNativeRecompileEmitAlignmentPadding(PIEMRECOMPILERSTATE pReNative, uint32_t off, uint32_t fAlignMask) 9615 { 9616 if (off & fAlignMask) 9617 { 9618 PIEMNATIVEINSTR pCodeBuf = iemNativeInstrBufEnsure(pReNative, off, fAlignMask + 1); 9619 while (off & fAlignMask) 9620 # if defined(RT_ARCH_AMD64) 9621 pCodeBuf[off++] = 0xcc; 9622 # elif defined(RT_ARCH_ARM64) 9623 pCodeBuf[off++] = Armv8A64MkInstrBrk(0xcccc); 9624 # else 9625 # error "port me" 9626 # endif 9627 } 9628 return off; 9629 } 9630 9631 9632 /** 9633 * Called when a new chunk is allocate to emit common per-chunk code. 9634 * 9635 * Allocates a per-chunk context directly from the chunk itself and place the 9636 * common code there. 9637 * 9638 * @returns Pointer to the chunk context start. 9639 * @param pVCpu The cross context virtual CPU structure of the calling 9640 * thread. 9641 * @param idxChunk The index of the chunk being added and requiring a 9642 * common code context. 9643 */ 9644 DECLHIDDEN(PCIEMNATIVEPERCHUNKCTX) iemNativeRecompileAttachExecMemChunkCtx(PVMCPU pVCpu, uint32_t idxChunk) 9645 { 9646 /* 9647 * Allocate a new recompiler state (since we're likely to be called while 9648 * the default one is fully loaded already with a recompiled TB). 9649 * 9650 * This is a bit of overkill, but this isn't a frequently used code path. 9651 */ 9652 PIEMRECOMPILERSTATE pReNative = iemNativeInit(pVCpu, NULL); 9653 AssertReturn(pReNative, NULL); 9654 9655 # if defined(RT_ARCH_AMD64) 9656 uint32_t const fAlignMask = 15; 9657 # elif defined(RT_ARCH_ARM64) 9658 uint32_t const fAlignMask = 31 / 4; 9659 # else 9660 # error "port me" 9661 # endif 9662 uint32_t aoffLabels[kIemNativeExitReason_Max] = {0}; 9663 int rc = VINF_SUCCESS; 9664 uint32_t off = 0; 9665 9666 IEMNATIVE_TRY_SETJMP(pReNative, rc) 9667 { 9668 /* 9669 * Emit the epilog code. 9670 */ 9671 aoffLabels[kIemNativeExitReason_Return] = off; 9672 off = iemNativeEmitCoreEpilog(pReNative, off); 9673 9674 /* 9675 * Generate special jump labels. All of these gets a copy of the epilog code. 9676 */ 9677 static struct 9678 { 9679 IEMNATIVEEXITREASON enmExitReason; 9680 uint32_t (*pfnEmitCore)(PIEMRECOMPILERSTATE pReNative, uint32_t off); 9681 } const s_aSpecialWithEpilogs[] = 9682 { 9683 { kIemNativeExitReason_NonZeroRetOrPassUp, iemNativeEmitCoreRcFiddling }, 9684 { kIemNativeExitReason_ReturnBreak, iemNativeEmitCoreReturnBreak }, 9685 { kIemNativeExitReason_ReturnBreakFF, iemNativeEmitCoreReturnBreakFF }, 9686 { kIemNativeExitReason_ReturnWithFlags, iemNativeEmitCoreReturnWithFlags }, 9687 }; 9688 for (uint32_t i = 0; i < RT_ELEMENTS(s_aSpecialWithEpilogs); i++) 9689 { 9690 off = iemNativeRecompileEmitAlignmentPadding(pReNative, off, fAlignMask); 9691 Assert(aoffLabels[s_aSpecialWithEpilogs[i].enmExitReason] == 0); 9692 aoffLabels[s_aSpecialWithEpilogs[i].enmExitReason] = off; 9693 off = s_aSpecialWithEpilogs[i].pfnEmitCore(pReNative, off); 9694 off = iemNativeEmitCoreEpilog(pReNative, off); 9695 } 9696 9697 /* 9698 * Do what iemNativeEmitReturnBreakViaLookup does. 9699 */ 9700 static struct 9701 { 9702 IEMNATIVEEXITREASON enmExitReason; 9703 uintptr_t pfnHelper; 9704 } const s_aViaLookup[] = 9705 { 9706 { kIemNativeExitReason_ReturnBreakViaLookup, 9707 (uintptr_t)iemNativeHlpReturnBreakViaLookup<false /*a_fWithIrqCheck*/> }, 9708 { kIemNativeExitReason_ReturnBreakViaLookupWithIrq, 9709 (uintptr_t)iemNativeHlpReturnBreakViaLookup<true /*a_fWithIrqCheck*/> }, 9710 { kIemNativeExitReason_ReturnBreakViaLookupWithTlb, 9711 (uintptr_t)iemNativeHlpReturnBreakViaLookupWithTlb<false /*a_fWithIrqCheck*/> }, 9712 { kIemNativeExitReason_ReturnBreakViaLookupWithTlbAndIrq, 9713 (uintptr_t)iemNativeHlpReturnBreakViaLookupWithTlb<true /*a_fWithIrqCheck*/> }, 9714 }; 9715 uint32_t const offReturnBreak = aoffLabels[kIemNativeExitReason_ReturnBreak]; Assert(offReturnBreak != 0); 9716 for (uint32_t i = 0; i < RT_ELEMENTS(s_aViaLookup); i++) 9717 { 9718 off = iemNativeRecompileEmitAlignmentPadding(pReNative, off, fAlignMask); 9719 Assert(aoffLabels[s_aViaLookup[i].enmExitReason] == 0); 9720 aoffLabels[s_aViaLookup[i].enmExitReason] = off; 9721 off = iemNativeEmitCoreViaLookupDoOne(pReNative, off, offReturnBreak, s_aViaLookup[i].pfnHelper); 9722 } 9723 9724 /* 9725 * Generate simple TB tail labels that just calls a help with a pVCpu 9726 * arg and either return or longjmps/throws a non-zero status. 9727 */ 9728 typedef IEM_DECL_NATIVE_HLP_PTR(int, PFNIEMNATIVESIMPLETAILLABELCALL,(PVMCPUCC pVCpu)); 9729 static struct 9730 { 9731 IEMNATIVEEXITREASON enmExitReason; 9732 bool fWithEpilog; 9733 PFNIEMNATIVESIMPLETAILLABELCALL pfnCallback; 9734 } const s_aSimpleTailLabels[] = 9735 { 9736 { kIemNativeExitReason_RaiseDe, false, iemNativeHlpExecRaiseDe }, 9737 { kIemNativeExitReason_RaiseUd, false, iemNativeHlpExecRaiseUd }, 9738 { kIemNativeExitReason_RaiseSseRelated, false, iemNativeHlpExecRaiseSseRelated }, 9739 { kIemNativeExitReason_RaiseAvxRelated, false, iemNativeHlpExecRaiseAvxRelated }, 9740 { kIemNativeExitReason_RaiseSseAvxFpRelated, false, iemNativeHlpExecRaiseSseAvxFpRelated }, 9741 { kIemNativeExitReason_RaiseNm, false, iemNativeHlpExecRaiseNm }, 9742 { kIemNativeExitReason_RaiseGp0, false, iemNativeHlpExecRaiseGp0 }, 9743 { kIemNativeExitReason_RaiseMf, false, iemNativeHlpExecRaiseMf }, 9744 { kIemNativeExitReason_RaiseXf, false, iemNativeHlpExecRaiseXf }, 9745 { kIemNativeExitReason_ObsoleteTb, true, iemNativeHlpObsoleteTb }, 9746 { kIemNativeExitReason_NeedCsLimChecking, true, iemNativeHlpNeedCsLimChecking }, 9747 { kIemNativeExitReason_CheckBranchMiss, true, iemNativeHlpCheckBranchMiss }, 9748 }; 9749 for (uint32_t i = 0; i < RT_ELEMENTS(s_aSimpleTailLabels); i++) 9750 { 9751 off = iemNativeRecompileEmitAlignmentPadding(pReNative, off, fAlignMask); 9752 Assert(!aoffLabels[s_aSimpleTailLabels[i].enmExitReason]); 9753 aoffLabels[s_aSimpleTailLabels[i].enmExitReason] = off; 9754 9755 /* int pfnCallback(PVMCPUCC pVCpu) */ 9756 off = iemNativeEmitLoadGprFromGpr(pReNative, off, IEMNATIVE_CALL_ARG0_GREG, IEMNATIVE_REG_FIXED_PVMCPU); 9757 off = iemNativeEmitCallImm(pReNative, off, (uintptr_t)s_aSimpleTailLabels[i].pfnCallback); 9758 9759 /* jump back to the return sequence / generate a return sequence. */ 9760 if (!s_aSimpleTailLabels[i].fWithEpilog) 9761 off = iemNativeEmitJmpToFixed(pReNative, off, aoffLabels[kIemNativeExitReason_Return]); 9762 else 9763 off = iemNativeEmitCoreEpilog(pReNative, off); 9764 } 9765 9766 9767 # ifdef VBOX_STRICT 9768 /* Make sure we've generate code for all labels. */ 9769 for (uint32_t i = kIemNativeExitReason_Invalid + 1; i < RT_ELEMENTS(aoffLabels); i++) 9770 Assert(aoffLabels[i] != 0 || i == kIemNativeExitReason_Return); 9771 #endif 9772 } 9773 IEMNATIVE_CATCH_LONGJMP_BEGIN(pReNative, rc); 9774 { 9775 Log(("iemNativeRecompileAttachExecMemChunkCtx: Caught %Rrc while recompiling!\n", rc)); 9776 iemNativeTerm(pReNative); 9777 return NULL; 9778 } 9779 IEMNATIVE_CATCH_LONGJMP_END(pReNative); 9780 9781 /* 9782 * Allocate memory for the context (first) and the common code (last). 9783 */ 9784 PIEMNATIVEPERCHUNKCTX pCtx; 9785 uint32_t const cbCtx = RT_ALIGN_32(sizeof(*pCtx), 64); 9786 uint32_t const cbCode = off * sizeof(IEMNATIVEINSTR); 9787 PIEMNATIVEINSTR paFinalCommonCodeRx = NULL; 9788 pCtx = (PIEMNATIVEPERCHUNKCTX)iemExecMemAllocatorAllocFromChunk(pVCpu, idxChunk, cbCtx + cbCode, &paFinalCommonCodeRx); 9789 AssertLogRelMsgReturn(pCtx, ("cbCtx=%#x cbCode=%#x idxChunk=%#x\n", cbCtx, cbCode, idxChunk), NULL); 9790 9791 /* 9792 * Copy over the generated code. 9793 * There should be no fixups or labels defined here. 9794 */ 9795 paFinalCommonCodeRx = (PIEMNATIVEINSTR)((uintptr_t)paFinalCommonCodeRx + cbCtx); 9796 memcpy((PIEMNATIVEINSTR)((uintptr_t)pCtx + cbCtx), pReNative->pInstrBuf, cbCode); 9797 9798 Assert(pReNative->cFixups == 0); 9799 Assert(pReNative->cLabels == 0); 9800 9801 /* 9802 * Initialize the context. 9803 */ 9804 AssertCompile(kIemNativeExitReason_Invalid == 0); 9805 AssertCompile(RT_ELEMENTS(pCtx->apExitLabels) == RT_ELEMENTS(aoffLabels)); 9806 pCtx->apExitLabels[kIemNativeExitReason_Invalid] = 0; 9807 for (uint32_t i = kIemNativeExitReason_Invalid + 1; i < RT_ELEMENTS(pCtx->apExitLabels); i++) 9808 { 9809 Assert(aoffLabels[i] != 0 || i == kIemNativeExitReason_Return); 9810 pCtx->apExitLabels[i] = &paFinalCommonCodeRx[aoffLabels[i]]; 9811 Log10((" apExitLabels[%u]=%p %s\n", i, pCtx->apExitLabels[i], iemNativeGetLabelName((IEMNATIVELABELTYPE)i, true))); 9812 } 9813 9814 iemExecMemAllocatorReadyForUse(pVCpu, pCtx, cbCtx + cbCode); 9815 9816 iemNativeTerm(pReNative); 9817 return pCtx; 9818 } 9819 9820 #endif /* IEMNATIVE_WITH_RECOMPILER_PER_CHUNK_TAIL_CODE */ 9821 9389 9822 /** 9390 9823 * Recompiles the given threaded TB into a native one. … … 9405 9838 9406 9839 /* 9407 * The first time thru, we allocate the recompiler state , the other times9408 * we just need to reset it before using it again.9840 * The first time thru, we allocate the recompiler state and save it, 9841 * all the other times we'll just reuse the saved one after a quick reset. 9409 9842 */ 9410 9843 PIEMRECOMPILERSTATE pReNative = pVCpu->iem.s.pNativeRecompilerStateR3; … … 9415 9848 pReNative = iemNativeInit(pVCpu, pTb); 9416 9849 AssertReturn(pReNative, pTb); 9850 pVCpu->iem.s.pNativeRecompilerStateR3 = pReNative; /* save it */ 9417 9851 } 9418 9852 … … 9532 9966 #ifdef VBOX_WITH_STATISTICS 9533 9967 off = iemNativeEmitThreadCallStats(pReNative, off, pCallEntry); 9968 #endif 9969 9970 #if 0 9971 if ( pTb->GCPhysPc == 0x00000000000c1240 9972 && idxCurCall == 67) 9973 off = iemNativeEmitBrk(pReNative, off, 0xf000); 9534 9974 #endif 9535 9975 … … 9609 10049 #endif 9610 10050 10051 /* Flush any pending writes before returning from the last instruction (RIP updates, etc.). */ 10052 off = iemNativeRegFlushPendingWrites(pReNative, off); 10053 10054 /* 10055 * Successful return, so clear the return register (eax, w0). 10056 */ 10057 off = iemNativeEmitGprZero(pReNative, off, IEMNATIVE_CALL_RET_GREG); 10058 10059 #ifndef IEMNATIVE_WITH_RECOMPILER_PER_CHUNK_TAIL_CODE 9611 10060 /* 9612 10061 * Emit the epilog code. … … 9614 10063 uint32_t idxReturnLabel; 9615 10064 off = iemNativeEmitEpilog(pReNative, off, &idxReturnLabel); 9616 10065 #else 10066 /* 10067 * Jump to the common per-chunk epilog code. 10068 */ 10069 //off = iemNativeEmitBrk(pReNative, off, 0x1227); 10070 off = iemNativeEmitTbExit(pReNative, off, kIemNativeExitReason_Return); 10071 #endif 10072 10073 #ifndef IEMNATIVE_WITH_RECOMPILER_PER_CHUNK_TAIL_CODE 9617 10074 /* 9618 10075 * Generate special jump labels. 9619 10076 */ 9620 if (pReNative->bmLabelTypes & ( RT_BIT_64(kIemNativeLabelType_ReturnBreakViaLookup) 9621 | RT_BIT_64(kIemNativeLabelType_ReturnBreakViaLookupWithIrq) 9622 | RT_BIT_64(kIemNativeLabelType_ReturnBreakViaLookupWithTlb) 9623 | RT_BIT_64(kIemNativeLabelType_ReturnBreakViaLookupWithTlbAndIrq) )) 9624 off = iemNativeEmitReturnBreakViaLookup(pReNative, off); /* Must come before ReturnBreak! */ 9625 9626 if (pReNative->bmLabelTypes & RT_BIT_64(kIemNativeLabelType_ReturnBreak)) 10077 off = iemNativeEmitRcFiddling(pReNative, off, idxReturnLabel); 10078 10079 bool const fReturnBreakViaLookup = RT_BOOL( pReNative->bmLabelTypes 10080 & ( RT_BIT_64(kIemNativeLabelType_ReturnBreakViaLookup) 10081 | RT_BIT_64(kIemNativeLabelType_ReturnBreakViaLookupWithIrq) 10082 | RT_BIT_64(kIemNativeLabelType_ReturnBreakViaLookupWithTlb) 10083 | RT_BIT_64(kIemNativeLabelType_ReturnBreakViaLookupWithTlbAndIrq))); 10084 if (fReturnBreakViaLookup) 10085 { 10086 uint32_t const idxReturnBreakLabel = iemNativeLabelCreate(pReNative, kIemNativeLabelType_ReturnBreak); 10087 off = iemNativeEmitReturnBreak(pReNative, off, idxReturnLabel); 10088 off = iemNativeEmitReturnBreakViaLookup(pReNative, off, idxReturnBreakLabel); 10089 } 10090 else if (pReNative->bmLabelTypes & RT_BIT_64(kIemNativeLabelType_ReturnBreak)) 9627 10091 off = iemNativeEmitReturnBreak(pReNative, off, idxReturnLabel); 9628 10092 … … 9689 10153 } while (fTailLabels); 9690 10154 } 10155 10156 #else /* IEMNATIVE_WITH_RECOMPILER_PER_CHUNK_TAIL_CODE */ 10157 /* 10158 * Generate tail labels with jumps to the common per-chunk code. 10159 */ 10160 # ifndef RT_ARCH_AMD64 10161 Assert(!(pReNative->bmLabelTypes & (RT_BIT_64(kIemNativeLabelType_Return) | RT_BIT_64(kIemNativeLabelType_Invalid)))); 10162 AssertCompile(kIemNativeLabelType_Invalid == 0); 10163 uint64_t fTailLabels = pReNative->bmLabelTypes & (RT_BIT_64(kIemNativeLabelType_LastTbExit + 1U) - 2U); 10164 if (fTailLabels) 10165 { 10166 do 10167 { 10168 IEMNATIVELABELTYPE const enmLabel = (IEMNATIVELABELTYPE)(ASMBitFirstSetU64(fTailLabels) - 1U); 10169 fTailLabels &= ~RT_BIT_64(enmLabel); 10170 10171 uint32_t const idxLabel = iemNativeLabelFind(pReNative, enmLabel); 10172 AssertContinue(idxLabel != UINT32_MAX); 10173 iemNativeLabelDefine(pReNative, idxLabel, off); 10174 off = iemNativeEmitTbExit(pReNative, off, (IEMNATIVEEXITREASON)enmLabel); 10175 } while (fTailLabels); 10176 } 10177 # else 10178 Assert(!(pReNative->bmLabelTypes & (RT_BIT_64(kIemNativeLabelType_LastTbExit + 1) - 1U))); /* Should not be used! */ 10179 # endif 10180 #endif /* IEMNATIVE_WITH_RECOMPILER_PER_CHUNK_TAIL_CODE */ 9691 10181 } 9692 10182 IEMNATIVE_CATCH_LONGJMP_BEGIN(pReNative, rc); … … 9723 10213 iemTbAllocatorProcessDelayedFrees(pVCpu, pVCpu->iem.s.pTbAllocatorR3); 9724 10214 9725 PIEMNATIVEINSTR paFinalInstrBufRx = NULL; 9726 PIEMNATIVEINSTR const paFinalInstrBuf = (PIEMNATIVEINSTR)iemExecMemAllocatorAlloc(pVCpu, off * sizeof(IEMNATIVEINSTR), pTb, (void **)&paFinalInstrBufRx); 10215 PIEMNATIVEINSTR paFinalInstrBufRx = NULL; 10216 #ifdef IEMNATIVE_WITH_RECOMPILER_PER_CHUNK_TAIL_CODE 10217 PCIEMNATIVEPERCHUNKCTX pCtx = NULL; 10218 PIEMNATIVEINSTR const paFinalInstrBuf = iemExecMemAllocatorAlloc(pVCpu, off * sizeof(IEMNATIVEINSTR), pTb, 10219 &paFinalInstrBufRx, &pCtx); 10220 10221 #else 10222 PIEMNATIVEINSTR const paFinalInstrBuf = iemExecMemAllocatorAlloc(pVCpu, off * sizeof(IEMNATIVEINSTR), pTb, 10223 &paFinalInstrBufRx, NULL); 10224 #endif 9727 10225 AssertReturn(paFinalInstrBuf, pTb); 9728 10226 memcpy(paFinalInstrBuf, pReNative->pInstrBuf, off * sizeof(paFinalInstrBuf[0])); … … 9754 10252 Assert(paFixups[i].off < off); 9755 10253 int32_t const offDisp = paLabels[paFixups[i].idxLabel].off - paFixups[i].off + paFixups[i].offAddend; 9756 Assert(offDisp >= - 262144 && offDisp < 262144);10254 Assert(offDisp >= -33554432 && offDisp < 33554432); 9757 10255 *Ptr.pu32 = (*Ptr.pu32 & UINT32_C(0xfc000000)) | ((uint32_t)offDisp & UINT32_C(0x03ffffff)); 9758 10256 continue; … … 9784 10282 AssertFailed(); 9785 10283 } 10284 10285 #ifdef IEMNATIVE_WITH_RECOMPILER_PER_CHUNK_TAIL_CODE 10286 /* 10287 * Apply TB exit fixups. 10288 */ 10289 PIEMNATIVEEXITFIXUP const paTbExitFixups = pReNative->paTbExitFixups; 10290 uint32_t const cTbExitFixups = pReNative->cTbExitFixups; 10291 for (uint32_t i = 0; i < cTbExitFixups; i++) 10292 { 10293 Assert(paTbExitFixups[i].off < off); 10294 Assert( paTbExitFixups[i].enmExitReason < kIemNativeExitReason_Max 10295 && paTbExitFixups[i].enmExitReason > kIemNativeExitReason_Invalid); 10296 RTPTRUNION const Ptr = { &paFinalInstrBuf[paTbExitFixups[i].off] }; 10297 10298 # if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86) 10299 Assert(paTbExitFixups[i].off + 4 <= off); 10300 intptr_t const offDisp = pCtx->apExitLabels[paTbExitFixups[i].enmExitReason] - &paFinalInstrBufRx[paTbExitFixups[i].off + 4]; 10301 Assert(offDisp >= INT32_MIN && offDisp <= INT32_MAX); 10302 *Ptr.pi32 = (int32_t)offDisp; 10303 10304 # elif defined(RT_ARCH_ARM64) 10305 intptr_t const offDisp = pCtx->apExitLabels[paTbExitFixups[i].enmExitReason] - &paFinalInstrBufRx[paTbExitFixups[i].off]; 10306 Assert(offDisp >= -33554432 && offDisp < 33554432); 10307 *Ptr.pu32 = (*Ptr.pu32 & UINT32_C(0xfc000000)) | ((uint32_t)offDisp & UINT32_C(0x03ffffff)); 10308 10309 # else 10310 # error "Port me!" 10311 # endif 10312 } 10313 #endif 9786 10314 9787 10315 iemExecMemAllocatorReadyForUse(pVCpu, paFinalInstrBufRx, off * sizeof(IEMNATIVEINSTR)); … … 9812 10340 { 9813 10341 Log3(("----------------------------------------- %d calls ---------------------------------------\n", cCallsOrg)); 9814 iemNativeDisassembleTb(p Tb, DBGFR3InfoLogHlp());10342 iemNativeDisassembleTb(pVCpu, pTb, DBGFR3InfoLogHlp()); 9815 10343 # if defined(DEBUG_bird) || defined(DEBUG_aeichner) 9816 10344 RTLogFlush(NULL); -
trunk/src/VBox/VMM/VMMR3/IEMR3.cpp
r105177 r105261 1403 1403 case IEMTB_F_TYPE_NATIVE: 1404 1404 pHlp->pfnPrintf(pHlp, "PC=%RGp fFlags=%#x on #%u: %p - native\n", GCPhysPc, fFlags, pVCpu->idCpu, pTb); 1405 iemNativeDisassembleTb(p Tb, pHlp);1405 iemNativeDisassembleTb(pVCpu, pTb, pHlp); 1406 1406 break; 1407 1407 # endif -
trunk/src/VBox/VMM/include/IEMInternal.h
r105253 r105261 6378 6378 6379 6379 /* Native recompiler public bits: */ 6380 6380 6381 DECLHIDDEN(PIEMTB) iemNativeRecompile(PVMCPUCC pVCpu, PIEMTB pTb) RT_NOEXCEPT; 6381 DECLHIDDEN(void) iemNativeDisassembleTb(P CIEMTB pTb, PCDBGFINFOHLP pHlp) RT_NOEXCEPT;6382 DECLHIDDEN(void) iemNativeDisassembleTb(PVMCPU pVCpu, PCIEMTB pTb, PCDBGFINFOHLP pHlp) RT_NOEXCEPT; 6382 6383 int iemExecMemAllocatorInit(PVMCPU pVCpu, uint64_t cbMax, uint64_t cbInitial, uint32_t cbChunk) RT_NOEXCEPT; 6383 DECLHIDDEN(void *) iemExecMemAllocatorAlloc(PVMCPU pVCpu, uint32_t cbReq, PIEMTB pTb, void **ppvExec) RT_NOEXCEPT; 6384 DECLHIDDEN(PIEMNATIVEINSTR) iemExecMemAllocatorAlloc(PVMCPU pVCpu, uint32_t cbReq, PIEMTB pTb, PIEMNATIVEINSTR *ppaExec, 6385 struct IEMNATIVEPERCHUNKCTX const **ppChunkCtx) RT_NOEXCEPT; 6386 DECLHIDDEN(PIEMNATIVEINSTR) iemExecMemAllocatorAllocFromChunk(PVMCPU pVCpu, uint32_t idxChunk, uint32_t cbReq, 6387 PIEMNATIVEINSTR *ppaExec); 6384 6388 DECLHIDDEN(void) iemExecMemAllocatorReadyForUse(PVMCPUCC pVCpu, void *pv, size_t cb) RT_NOEXCEPT; 6385 6389 void iemExecMemAllocatorFree(PVMCPU pVCpu, void *pv, size_t cb) RT_NOEXCEPT; 6386 6390 DECLASM(DECL_NO_RETURN(void)) iemNativeTbLongJmp(void *pvFramePointer, int rc) RT_NOEXCEPT; 6391 DECLHIDDEN(struct IEMNATIVEPERCHUNKCTX const *) iemExecMemGetTbChunkCtx(PVMCPU pVCpu, PCIEMTB pTb); 6392 DECLHIDDEN(struct IEMNATIVEPERCHUNKCTX const *) iemNativeRecompileAttachExecMemChunkCtx(PVMCPU pVCpu, uint32_t idxChunk); 6387 6393 6388 6394 #endif /* !RT_IN_ASSEMBLER - ASM-NOINC-END */ -
trunk/src/VBox/VMM/include/IEMN8veRecompiler.h
r104802 r105261 58 58 # define IEMNATIVE_WITH_EFLAGS_SKIPPING 59 59 #endif 60 61 60 62 61 /** @def IEMNATIVE_STRICT_EFLAGS_SKIPPING … … 82 81 #endif 83 82 84 /** @def IEMNATIVE_WITH_RECOMPILER_EPILOGUE_SINGLETON 85 * Enables having only a single epilogue for native TBs. */ 86 #if defined(RT_ARCH_ARM64) || defined(DOXYGEN_RUNNING) 87 # define IEMNATIVE_WITH_RECOMPILER_EPILOGUE_SINGLETON 88 #endif 83 /** @def IEMNATIVE_WITH_RECOMPILER_PER_CHUNK_TAIL_CODE 84 * Enable this to use common epilogue and tail code for all TBs in a chunk. */ 85 #if 1 || defined(DOXYGEN_RUNNING) 86 # define IEMNATIVE_WITH_RECOMPILER_PER_CHUNK_TAIL_CODE 87 #endif 88 89 89 90 90 /** @name Stack Frame Layout … … 466 466 kIemNativeExitReason_NeedCsLimChecking, 467 467 kIemNativeExitReason_CheckBranchMiss, 468 kIemNativeExitReason_Return, /** @todo Eliminate (needed for the compile assertion below). */469 468 kIemNativeExitReason_ReturnBreak, 470 469 kIemNativeExitReason_ReturnBreakFF, … … 475 474 kIemNativeExitReason_ReturnWithFlags, 476 475 kIemNativeExitReason_NonZeroRetOrPassUp, 476 kIemNativeExitReason_Return, /**< This is a little bit special, but needs to be included here. */ 477 kIemNativeExitReason_Max 477 478 } IEMNATIVEEXITREASON; 478 479 … … 503 504 kIemNativeLabelType_LastSimple = kIemNativeLabelType_CheckBranchMiss, 504 505 /* Manually defined labels. */ 505 kIemNativeLabelType_Return,506 506 kIemNativeLabelType_ReturnBreak, 507 507 kIemNativeLabelType_ReturnBreakFF, … … 512 512 kIemNativeLabelType_ReturnWithFlags, 513 513 kIemNativeLabelType_NonZeroRetOrPassUp, 514 /** The last fixup for branches that can span almost the whole TB length. */ 515 kIemNativeLabelType_LastWholeTbBranch = kIemNativeLabelType_NonZeroRetOrPassUp, 514 kIemNativeLabelType_Return, 515 /** The last fixup for branches that can span almost the whole TB length. 516 * @note Whether kIemNativeLabelType_Return needs to be one of these is 517 * a bit questionable, since nobody jumps to it except other tail code. */ 518 kIemNativeLabelType_LastWholeTbBranch = kIemNativeLabelType_Return, 519 /** The last fixup for branches that exits the TB. */ 520 kIemNativeLabelType_LastTbExit = kIemNativeLabelType_Return, 516 521 517 522 /* … … 531 536 } IEMNATIVELABELTYPE; 532 537 533 /* Temporary kludge until all jumps to TB exit labels are converted to the new TB exiting style, 534 * see @bugref{10677}. */ 538 /** Temporary kludge until all jumps to TB exit labels are converted to the new TB exiting style, 539 * see @bugref{10677}. 540 * @note update bird: This won't happen, unfortunately, since we'll keep using 541 * the local labels on arm64 so we can avoid inverting branch conditions 542 * and inserting extra of unconditional branches in order to reach the 543 * common code. Instead we'll have everyone jump to the same tail lable 544 * which then jumps to the common (per chunk) code. */ 535 545 #define IEM_N8VE_RECOMP_LABELTYPE_EQ_EXITREASON(a_Reason) \ 536 546 ((int)kIemNativeLabelType_ ## a_Reason == (int)kIemNativeExitReason_ ## a_Reason) … … 547 557 && IEM_N8VE_RECOMP_LABELTYPE_EQ_EXITREASON(NeedCsLimChecking) 548 558 && IEM_N8VE_RECOMP_LABELTYPE_EQ_EXITREASON(CheckBranchMiss) 549 && IEM_N8VE_RECOMP_LABELTYPE_EQ_EXITREASON(Return)550 559 && IEM_N8VE_RECOMP_LABELTYPE_EQ_EXITREASON(ReturnBreak) 551 560 && IEM_N8VE_RECOMP_LABELTYPE_EQ_EXITREASON(ReturnBreakFF) … … 555 564 && IEM_N8VE_RECOMP_LABELTYPE_EQ_EXITREASON(ReturnBreakViaLookupWithTlbAndIrq) 556 565 && IEM_N8VE_RECOMP_LABELTYPE_EQ_EXITREASON(ReturnWithFlags) 557 && IEM_N8VE_RECOMP_LABELTYPE_EQ_EXITREASON(NonZeroRetOrPassUp)); 566 && IEM_N8VE_RECOMP_LABELTYPE_EQ_EXITREASON(NonZeroRetOrPassUp) 567 && IEM_N8VE_RECOMP_LABELTYPE_EQ_EXITREASON(Return)); 568 AssertCompile((int)kIemNativeExitReason_Max == (int)kIemNativeLabelType_LastTbExit + 1); 558 569 559 570 … … 605 616 /** Pointer to a native code generator fixup. */ 606 617 typedef IEMNATIVEFIXUP *PIEMNATIVEFIXUP; 618 619 #ifdef IEMNATIVE_WITH_RECOMPILER_PER_CHUNK_TAIL_CODE 620 621 /** Native code generator fixup to per chunk TB tail code. */ 622 typedef struct IEMNATIVEEXITFIXUP 623 { 624 /** Code offset of the fixup location. */ 625 uint32_t off; 626 /** The exit reason (IEMNATIVEEXITREASON). */ 627 uint32_t enmExitReason; 628 } IEMNATIVEEXITFIXUP; 629 /** Pointer to a native code generator TB exit fixup. */ 630 typedef IEMNATIVEEXITFIXUP *PIEMNATIVEEXITFIXUP; 631 632 /** 633 * Per executable memory chunk context with addresses for common code. 634 */ 635 typedef struct IEMNATIVEPERCHUNKCTX 636 { 637 /** Pointers to the exit labels */ 638 PIEMNATIVEINSTR apExitLabels[kIemNativeExitReason_Max]; 639 } IEMNATIVEPERCHUNKCTX; 640 /** Pointer to per-chunk recompiler context. */ 641 typedef IEMNATIVEPERCHUNKCTX *PIEMNATIVEPERCHUNKCTX; 642 /** Pointer to const per-chunk recompiler context. */ 643 typedef const IEMNATIVEPERCHUNKCTX *PCIEMNATIVEPERCHUNKCTX; 644 645 #endif /* IEMNATIVE_WITH_RECOMPILER_PER_CHUNK_TAIL_CODE */ 607 646 608 647 … … 1426 1465 PIEMNATIVEFIXUP paFixups; 1427 1466 1467 #ifdef IEMNATIVE_WITH_RECOMPILER_PER_CHUNK_TAIL_CODE 1468 /** Actual number of fixups in paTbExitFixups. */ 1469 uint32_t cTbExitFixups; 1470 /** Max number of entries allowed in paTbExitFixups before reallocating it. */ 1471 uint32_t cTbExitFixupsAlloc; 1472 /** Buffer used by the recompiler for recording fixups when generating code. */ 1473 PIEMNATIVEEXITFIXUP paTbExitFixups; 1474 #endif 1475 1428 1476 #ifdef IEMNATIVE_WITH_TB_DEBUG_INFO 1429 1477 /** Number of debug info entries allocated for pDbgInfo. */ … … 1638 1686 DECL_HIDDEN_THROW(void) iemNativeAddFixup(PIEMRECOMPILERSTATE pReNative, uint32_t offWhere, uint32_t idxLabel, 1639 1687 IEMNATIVEFIXUPTYPE enmType, int8_t offAddend = 0); 1688 #ifdef IEMNATIVE_WITH_RECOMPILER_PER_CHUNK_TAIL_CODE 1689 DECL_HIDDEN_THROW(void) iemNativeAddTbExitFixup(PIEMRECOMPILERSTATE pReNative, uint32_t offWhere, IEMNATIVEEXITREASON enmExitReason); 1690 #endif 1640 1691 DECL_HIDDEN_THROW(PIEMNATIVEINSTR) iemNativeInstrBufEnsureSlow(PIEMRECOMPILERSTATE pReNative, uint32_t off, uint32_t cInstrReq); 1641 1692 … … 1779 1830 IEM_DECL_NATIVE_HLP_PROTO(int, iemNativeHlpNeedCsLimChecking,(PVMCPUCC pVCpu)); 1780 1831 IEM_DECL_NATIVE_HLP_PROTO(int, iemNativeHlpCheckBranchMiss,(PVMCPUCC pVCpu)); 1832 IEM_DECL_NATIVE_HLP_PROTO(int, iemNativeHlpExecRaiseAvxRelated,(PVMCPUCC pVCpu)); 1833 IEM_DECL_NATIVE_HLP_PROTO(int, iemNativeHlpExecRaiseSseRelated,(PVMCPUCC pVCpu)); 1834 IEM_DECL_NATIVE_HLP_PROTO(int, iemNativeHlpExecRaiseSseAvxFpRelated,(PVMCPUCC pVCpu)); 1781 1835 1782 1836 IEM_DECL_NATIVE_HLP_PROTO(uint64_t, iemNativeHlpMemFetchDataU8,(PVMCPUCC pVCpu, RTGCPTR GCPtrMem, uint8_t iSegReg)); … … 2585 2639 #endif 2586 2640 2587 #ifdef IEMNATIVE_WITH_RECOMPILER_EPILOGUE_SINGLETON2588 /** The common epilog jumped to from a TB.2589 * @note This is not a callable function! */2590 extern "C" IEM_DECL_NATIVE_HLP_DEF(int, iemNativeTbEpilog, (void));2591 #endif2592 2593 2641 #endif /* !RT_IN_ASSEMBLER - ASM-NOINC-END */ 2594 2642 -
trunk/src/VBox/VMM/include/IEMN8veRecompilerEmit.h
r105036 r105261 7491 7491 7492 7492 7493 /** 7494 * Emits code that jumps to @a offTarget if @a iGprSrc is not zero. 7495 * 7496 * The operand size is given by @a f64Bit. 7497 */ 7498 DECL_FORCE_INLINE_THROW(uint32_t) 7499 iemNativeEmitTestIfGprIsZeroOrNotZeroAndJmpToFixedEx(PIEMNATIVEINSTR pCodeBuf, uint32_t off, 7500 uint8_t iGprSrc, bool f64Bit, bool fJmpIfNotZero, uint32_t offTarget) 7501 { 7502 #ifdef RT_ARCH_AMD64 7503 /* test reg32,reg32 / test reg64,reg64 */ 7504 if (f64Bit) 7505 pCodeBuf[off++] = X86_OP_REX_W | (iGprSrc < 8 ? 0 : X86_OP_REX_R | X86_OP_REX_B); 7506 else if (iGprSrc >= 8) 7507 pCodeBuf[off++] = X86_OP_REX_R | X86_OP_REX_B; 7508 pCodeBuf[off++] = 0x85; 7509 pCodeBuf[off++] = X86_MODRM_MAKE(X86_MOD_REG, iGprSrc & 7, iGprSrc & 7); 7510 7511 /* jnz idxLabel */ 7512 off = iemNativeEmitJccToFixedEx(pCodeBuf, off, offTarget, 7513 fJmpIfNotZero ? kIemNativeInstrCond_ne : kIemNativeInstrCond_e); 7514 7515 #elif defined(RT_ARCH_ARM64) 7516 pCodeBuf[off] = Armv8A64MkInstrCbzCbnz(fJmpIfNotZero, (int32_t)(offTarget - off), iGprSrc, f64Bit); 7517 off++; 7518 7519 #else 7520 # error "Port me!" 7521 #endif 7522 return off; 7523 } 7524 7525 7526 /** 7527 * Emits code that jumps to @a offTarget if @a iGprSrc is not zero. 7528 * 7529 * The operand size is given by @a f64Bit. 7530 */ 7531 DECL_FORCE_INLINE_THROW(uint32_t) 7532 iemNativeEmitTestIfGprIsZeroOrNotZeroAndJmpToFixed(PIEMRECOMPILERSTATE pReNative, uint32_t off, uint8_t iGprSrc, 7533 bool f64Bit, bool fJmpIfNotZero, uint32_t offTarget) 7534 { 7535 #ifdef RT_ARCH_AMD64 7536 off = iemNativeEmitTestIfGprIsZeroOrNotZeroAndJmpToFixedEx(iemNativeInstrBufEnsure(pReNative, off, 3 + 6), 7537 off, iGprSrc, f64Bit, fJmpIfNotZero, offTarget); 7538 #elif defined(RT_ARCH_ARM64) 7539 off = iemNativeEmitTestIfGprIsZeroOrNotZeroAndJmpToFixedEx(iemNativeInstrBufEnsure(pReNative, off, 1), 7540 off, iGprSrc, f64Bit, fJmpIfNotZero, offTarget); 7541 #else 7542 # error "Port me!" 7543 #endif 7544 IEMNATIVE_ASSERT_INSTR_BUF_ENSURE(pReNative, off); 7545 return off; 7546 } 7547 7548 7493 7549 /* if (Grp1 == 0) Jmp idxLabel; */ 7494 7550 … … 7530 7586 uint32_t const idxLabel = iemNativeLabelCreate(pReNative, enmLabelType, UINT32_MAX /*offWhere*/, uData); 7531 7587 return iemNativeEmitTestIfGprIsZeroAndJmpToLabel(pReNative, off, iGprSrc, f64Bit, idxLabel); 7588 } 7589 7590 7591 /** 7592 * Emits code that jumps to @a offTarget if @a iGprSrc is zero. 7593 * 7594 * The operand size is given by @a f64Bit. 7595 */ 7596 DECL_INLINE_THROW(uint32_t) iemNativeEmitTestIfGprIsZeroAndJmpToFixed(PIEMRECOMPILERSTATE pReNative, uint32_t off, 7597 uint8_t iGprSrc, bool f64Bit, uint32_t offTarget) 7598 { 7599 return iemNativeEmitTestIfGprIsZeroOrNotZeroAndJmpToFixed(pReNative, off, iGprSrc, f64Bit, false /*fJmpIfNotZero*/, offTarget); 7532 7600 } 7533 7601 … … 7937 8005 *********************************************************************************************************************************/ 7938 8006 8007 /** 8008 * Emits a Jcc rel32 / B.cc imm19 to the given label (ASSUMED requiring fixup). 8009 */ 8010 DECL_FORCE_INLINE_THROW(uint32_t) 8011 iemNativeEmitJccTbExitEx(PIEMRECOMPILERSTATE pReNative, PIEMNATIVEINSTR pCodeBuf, uint32_t off, 8012 IEMNATIVEEXITREASON enmExitReason, IEMNATIVEINSTRCOND enmCond) 8013 { 8014 #if defined(IEMNATIVE_WITH_RECOMPILER_PER_CHUNK_TAIL_CODE) && defined(RT_ARCH_AMD64) 8015 /* jcc rel32 */ 8016 pCodeBuf[off++] = 0x0f; 8017 pCodeBuf[off++] = (uint8_t)enmCond | 0x80; 8018 iemNativeAddTbExitFixup(pReNative, off, enmExitReason); 8019 pCodeBuf[off++] = 0x00; 8020 pCodeBuf[off++] = 0x00; 8021 pCodeBuf[off++] = 0x00; 8022 pCodeBuf[off++] = 0x00; 8023 8024 #else 8025 /* ARM64 doesn't have the necessary jump range, so we jump via local label 8026 just like when we keep everything local. */ 8027 uint32_t const idxLabel = iemNativeLabelCreate(pReNative, (IEMNATIVELABELTYPE)enmExitReason, UINT32_MAX /*offWhere*/, 0 /*uData*/); 8028 off = iemNativeEmitJccToLabelEx(pReNative, pCodeBuf, off, idxLabel, enmCond); 8029 #endif 8030 return off; 8031 } 8032 7939 8033 7940 8034 /** … … 7945 8039 IEMNATIVEEXITREASON enmExitReason, IEMNATIVEINSTRCOND enmCond) 7946 8040 { 8041 #ifdef IEMNATIVE_WITH_RECOMPILER_PER_CHUNK_TAIL_CODE 8042 # ifdef RT_ARCH_AMD64 8043 PIEMNATIVEINSTR pCodeBuf = iemNativeInstrBufEnsure(pReNative, off, 6); 8044 # elif defined(RT_ARCH_ARM64) 8045 PIEMNATIVEINSTR pCodeBuf = iemNativeInstrBufEnsure(pReNative, off, 2); 8046 # else 8047 # error "Port me!" 8048 # endif 8049 return iemNativeEmitJccTbExitEx(pReNative, pCodeBuf, off, enmExitReason, enmCond); 8050 #else 7947 8051 return iemNativeEmitJccToNewLabel(pReNative, off, (IEMNATIVELABELTYPE)enmExitReason, 0 /*uData*/, enmCond); 8052 #endif 7948 8053 } 7949 8054 … … 8014 8119 8015 8120 DECL_INLINE_THROW(uint32_t) 8016 iemNativeEmitTbExit(PIEMRECOMPILERSTATE pReNative, uint32_t off, IEMNATIVEEXITREASON enmExitReason)8017 {8018 return iemNativeEmitJmpToNewLabel(pReNative, off, (IEMNATIVELABELTYPE)enmExitReason);8019 }8020 8021 8022 DECL_INLINE_THROW(uint32_t)8023 8121 iemNativeEmitTbExitEx(PIEMRECOMPILERSTATE pReNative, PIEMNATIVEINSTR pCodeBuf, uint32_t off, IEMNATIVEEXITREASON enmExitReason) 8024 8122 { 8123 #ifdef IEMNATIVE_WITH_RECOMPILER_PER_CHUNK_TAIL_CODE 8124 # ifdef RT_ARCH_AMD64 8125 /* jmp rel32 */ 8126 pCodeBuf[off++] = 0xe9; 8127 iemNativeAddTbExitFixup(pReNative, off, enmExitReason); 8128 pCodeBuf[off++] = 0xfe; 8129 pCodeBuf[off++] = 0xff; 8130 pCodeBuf[off++] = 0xff; 8131 pCodeBuf[off++] = 0xff; 8132 8133 # elif defined(RT_ARCH_ARM64) 8134 iemNativeAddTbExitFixup(pReNative, off, enmExitReason); 8135 pCodeBuf[off++] = Armv8A64MkInstrB(-1); 8136 8137 # else 8138 # error "Port me!" 8139 # endif 8140 return off; 8141 8142 #else 8025 8143 uint32_t const idxLabel = iemNativeLabelCreate(pReNative, (IEMNATIVELABELTYPE)enmExitReason, UINT32_MAX /*offWhere*/, 0 /*uData*/); 8026 8144 return iemNativeEmitJmpToLabelEx(pReNative, pCodeBuf, off, idxLabel); 8145 #endif 8146 } 8147 8148 8149 DECL_INLINE_THROW(uint32_t) 8150 iemNativeEmitTbExit(PIEMRECOMPILERSTATE pReNative, uint32_t off, IEMNATIVEEXITREASON enmExitReason) 8151 { 8152 #ifdef IEMNATIVE_WITH_RECOMPILER_PER_CHUNK_TAIL_CODE 8153 # ifdef RT_ARCH_AMD64 8154 PIEMNATIVEINSTR pCodeBuf = iemNativeInstrBufEnsure(pReNative, off, 6); 8155 8156 /* jmp rel32 */ 8157 pCodeBuf[off++] = 0xe9; 8158 iemNativeAddTbExitFixup(pReNative, off, enmExitReason); 8159 pCodeBuf[off++] = 0xfe; 8160 pCodeBuf[off++] = 0xff; 8161 pCodeBuf[off++] = 0xff; 8162 pCodeBuf[off++] = 0xff; 8163 8164 # elif defined(RT_ARCH_ARM64) 8165 PIEMNATIVEINSTR pCodeBuf = iemNativeInstrBufEnsure(pReNative, off, 1); 8166 iemNativeAddTbExitFixup(pReNative, off, enmExitReason); 8167 pCodeBuf[off++] = Armv8A64MkInstrB(-1); 8168 8169 # else 8170 # error "Port me!" 8171 # endif 8172 IEMNATIVE_ASSERT_INSTR_BUF_ENSURE(pReNative, off); 8173 return off; 8174 8175 #else 8176 return iemNativeEmitJmpToNewLabel(pReNative, off, (IEMNATIVELABELTYPE)enmExitReason); 8177 #endif 8027 8178 } 8028 8179 … … 8101 8252 * Emits code that exits the current TB with the given reason if 32-bit @a iGprSrc equals @a uImm. 8102 8253 */ 8103 DECL_INLINE_THROW(uint32_t) iemNativeEmitTestIfGpr32EqualsImmAndTbExit(PIEMRECOMPILERSTATE pReNative, uint32_t off, 8104 uint8_t iGprSrc, uint32_t uImm, IEMNATIVEEXITREASON enmExitReason) 8254 DECL_INLINE_THROW(uint32_t) 8255 iemNativeEmitTestIfGpr32EqualsImmAndTbExit(PIEMRECOMPILERSTATE pReNative, uint32_t off, 8256 uint8_t iGprSrc, uint32_t uImm, IEMNATIVEEXITREASON enmExitReason) 8105 8257 { 8106 8258 off = iemNativeEmitCmpGpr32WithImm(pReNative, off, iGprSrc, uImm); … … 8116 8268 * @note On ARM64 the range is only +/-8191 instructions. 8117 8269 */ 8118 DECL_INLINE_THROW(uint32_t) iemNativeEmitTestBitInGprAndTbExitIfSet(PIEMRECOMPILERSTATE pReNative, uint32_t off, 8119 uint8_t iGprSrc, uint8_t iBitNo, IEMNATIVEEXITREASON enmExitReason) 8120 { 8270 DECL_INLINE_THROW(uint32_t) 8271 iemNativeEmitTestBitInGprAndTbExitIfSet(PIEMRECOMPILERSTATE pReNative, uint32_t off, 8272 uint8_t iGprSrc, uint8_t iBitNo, IEMNATIVEEXITREASON enmExitReason) 8273 { 8274 #if defined(IEMNATIVE_WITH_RECOMPILER_PER_CHUNK_TAIL_CODE) && defined(RT_ARCH_AMD64) 8275 Assert(iBitNo < 64); 8276 uint8_t * const pbCodeBuf = iemNativeInstrBufEnsure(pReNative, off, 5); 8277 if (iBitNo < 8) 8278 { 8279 /* test Eb, imm8 */ 8280 if (iGprSrc >= 4) 8281 pbCodeBuf[off++] = iGprSrc >= 8 ? X86_OP_REX_B : X86_OP_REX; 8282 pbCodeBuf[off++] = 0xf6; 8283 pbCodeBuf[off++] = X86_MODRM_MAKE(X86_MOD_REG, 0, iGprSrc & 7); 8284 pbCodeBuf[off++] = (uint8_t)1 << iBitNo; 8285 off = iemNativeEmitJccTbExit(pReNative, off, enmExitReason, kIemNativeInstrCond_ne); 8286 } 8287 else 8288 { 8289 /* bt Ev, imm8 */ 8290 if (iBitNo >= 32) 8291 pbCodeBuf[off++] = X86_OP_REX_W | (iGprSrc < 8 ? 0 : X86_OP_REX_B); 8292 else if (iGprSrc >= 8) 8293 pbCodeBuf[off++] = X86_OP_REX_B; 8294 pbCodeBuf[off++] = 0x0f; 8295 pbCodeBuf[off++] = 0xba; 8296 pbCodeBuf[off++] = X86_MODRM_MAKE(X86_MOD_REG, 4, iGprSrc & 7); 8297 pbCodeBuf[off++] = iBitNo; 8298 off = iemNativeEmitJccTbExit(pReNative, off, enmExitReason, kIemNativeInstrCond_c); 8299 } 8300 IEMNATIVE_ASSERT_INSTR_BUF_ENSURE(pReNative, off); 8301 return off; 8302 8303 #else 8304 /* ARM64 doesn't have the necessary jump range, so we jump via local label 8305 just like when we keep everything local. */ 8121 8306 uint32_t const idxLabel = iemNativeLabelCreate(pReNative, (IEMNATIVELABELTYPE)enmExitReason, UINT32_MAX /*offWhere*/, 0 /*uData*/); 8122 8307 return iemNativeEmitTestBitInGprAndJmpToLabelIfCc(pReNative, off, iGprSrc, iBitNo, idxLabel, true /*fJmpIfSet*/); 8308 #endif 8123 8309 } 8124 8310 … … 8133 8319 uint8_t iGprSrc, bool f64Bit, IEMNATIVEEXITREASON enmExitReason) 8134 8320 { 8321 #if defined(IEMNATIVE_WITH_RECOMPILER_PER_CHUNK_TAIL_CODE) && defined(RT_ARCH_AMD64) 8322 /* test reg32,reg32 / test reg64,reg64 */ 8323 if (f64Bit) 8324 pCodeBuf[off++] = X86_OP_REX_W | (iGprSrc < 8 ? 0 : X86_OP_REX_R | X86_OP_REX_B); 8325 else if (iGprSrc >= 8) 8326 pCodeBuf[off++] = X86_OP_REX_R | X86_OP_REX_B; 8327 pCodeBuf[off++] = 0x85; 8328 pCodeBuf[off++] = X86_MODRM_MAKE(X86_MOD_REG, iGprSrc & 7, iGprSrc & 7); 8329 8330 /* jnz idxLabel */ 8331 return iemNativeEmitJccTbExitEx(pReNative, pCodeBuf, off, enmExitReason, kIemNativeInstrCond_ne); 8332 8333 #else 8334 /* ARM64 doesn't have the necessary jump range, so we jump via local label 8335 just like when we keep everything local. */ 8135 8336 uint32_t const idxLabel = iemNativeLabelCreate(pReNative, (IEMNATIVELABELTYPE)enmExitReason, UINT32_MAX /*offWhere*/, 0 /*uData*/); 8136 8337 return iemNativeEmitTestIfGprIsZeroOrNotZeroAndJmpToLabelEx(pReNative, pCodeBuf, off, iGprSrc, 8137 8338 f64Bit, true /*fJmpIfNotZero*/, idxLabel); 8138 } 8139 8140 8141 /** 8142 * Emits code to exit the current TB on the given condition. 8143 */ 8144 DECL_INLINE_THROW(uint32_t) 8145 iemNativeEmitJccTbExitEx(PIEMRECOMPILERSTATE pReNative, PIEMNATIVEINSTR pCodeBuf, uint32_t off, IEMNATIVEEXITREASON enmExitReason, IEMNATIVEINSTRCOND enmCond) 8146 { 8147 uint32_t const idxLabel = iemNativeLabelCreate(pReNative, (IEMNATIVELABELTYPE)enmExitReason, UINT32_MAX /*offWhere*/, 0 /*uData*/); 8148 #ifdef RT_ARCH_AMD64 8149 off = iemNativeEmitJccToLabelEx(pReNative, pCodeBuf, off, idxLabel, enmCond); 8150 #elif defined(RT_ARCH_ARM64) 8151 off = iemNativeEmitJccToLabelEx(pReNative, pCodeBuf, off, idxLabel, enmCond); 8152 #else 8153 # error "Port me!" 8154 #endif 8155 IEMNATIVE_ASSERT_INSTR_BUF_ENSURE(pReNative, off); 8156 return off; 8339 #endif 8157 8340 } 8158 8341 … … 8166 8349 uint8_t iGprSrc, bool f64Bit, IEMNATIVEEXITREASON enmExitReason) 8167 8350 { 8351 #if defined(IEMNATIVE_WITH_RECOMPILER_PER_CHUNK_TAIL_CODE) && defined(RT_ARCH_AMD64) 8352 off = iemNativeEmitTestIfGprIsNotZeroAndTbExitEx(pReNative, iemNativeInstrBufEnsure(pReNative, off, 3 + 6), 8353 off, iGprSrc, f64Bit, enmExitReason); 8354 IEMNATIVE_ASSERT_INSTR_BUF_ENSURE(pReNative, off); 8355 return off; 8356 #else 8168 8357 uint32_t const idxLabel = iemNativeLabelCreate(pReNative, (IEMNATIVELABELTYPE)enmExitReason, UINT32_MAX /*offWhere*/, 0 /*uData*/); 8169 8358 return iemNativeEmitTestIfGprIsZeroOrNotZeroAndJmpToLabel(pReNative, off, iGprSrc, f64Bit, true /*fJmpIfNotZero*/, idxLabel); 8359 #endif 8170 8360 } 8171 8361
Note:
See TracChangeset
for help on using the changeset viewer.