Changeset 101172 in vbox for trunk/src/VBox/VMM/VMMAll
- Timestamp:
- Sep 19, 2023 3:14:43 PM (15 months ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/VMMAll/IEMAllN8veRecompiler.cpp
r101163 r101172 59 59 #include <iprt/mem.h> 60 60 #include <iprt/string.h> 61 61 62 #ifdef RT_OS_WINDOWS 62 /** @todo */ 63 # include <iprt/formats/pecoff.h> /* this is incomaptible with windows.h, thus: */ 64 extern "C" DECLIMPORT(uint8_t) __cdecl RtlAddFunctionTable(void *pvFunctionTable, uint32_t cEntries, uintptr_t uBaseAddress); 65 extern "C" DECLIMPORT(uint8_t) __cdecl RtlDelFunctionTable(void *pvFunctionTable); 63 66 #else 64 67 # include <iprt/formats/dwarf.h> 65 extern "C" void __register_frame_info(void *begin, void *ob); 68 extern "C" void __register_frame_info(void *begin, void *ob); /* found no header for these two */ 66 69 #endif 67 70 … … 86 89 # error The setjmp approach must be enabled for the recompiler. 87 90 #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 /** @} */ 88 149 89 150 … … 118 179 /** Pointer to the chunk. */ 119 180 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 121 188 /** Exception handling frame information for proper unwinding during C++ 122 189 * throws and (possibly) longjmp(). */ 123 190 PIEMEXECMEMCHUNKEHFRAME pEhFrame; 124 # endif125 # ifdef IN_RING0191 # endif 192 #elif defined(IN_RING0) 126 193 /** Allocation handle. */ 127 194 RTR0MEMOBJ hMemObj; … … 171 238 /** @} */ 172 239 173 #if defined(IN_RING3) && defined(RT_OS_WINDOWS) && (defined(RT_ARCH_AMD64) || defined(RT_ARCH_ARM64))174 PRUNTIME_FUNCTION paUnwindFunctions;175 #endif176 177 240 /** The allocation chunks. */ 178 241 RT_FLEXIBLE_ARRAY_EXTENSION … … 186 249 187 250 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 */ 257 static 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 */ 189 342 190 343 /** … … 272 425 273 426 /** 274 * Init alizes the unwind info section for non-windows hosts.427 * Initializes the unwind info section for non-windows hosts. 275 428 */ 276 429 static void iemExecMemAllocatorInitEhFrameForChunk(PIEMEXECMEMALLOCATOR pExecMemAllocator, … … 327 480 } 328 481 329 #endif /* IN_RING3 && !RT_OS_WINDOWS */ 482 # endif /* !RT_OS_WINDOWS */ 483 #endif /* IN_RING3 */ 330 484 331 485 … … 401 555 # ifdef RT_OS_WINDOWS 402 556 /* 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. 405 562 */ 406 /** @todo */ 563 void *pvUnwindInfo = iemExecMemAllocatorInitAndRegisterUnwindInfoForChunk(pExecMemAllocator, hHeap, pvChunk); 564 AssertStmt(pvUnwindInfo, rc = VERR_INTERNAL_ERROR_3); 407 565 # else 408 566 /* … … 427 585 * Finalize the adding of the chunk. 428 586 */ 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 433 595 #endif 434 596 … … 505 667 * Allocate and initialize the allocatore instance. 506 668 */ 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])); 515 671 AssertReturn(pExecMemAllocator, VERR_NO_MEMORY); 516 672 pExecMemAllocator->uMagic = IEMEXECMEMALLOCATOR_MAGIC; … … 523 679 pExecMemAllocator->cbFree = 0; 524 680 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 #endif529 681 for (uint32_t i = 0; i < cMaxChunks; i++) 530 682 { … … 727 879 int8_t offAddend; 728 880 } IEMNATIVEFIXUP; 729 881 /** Pointer to a native code generator fixup. */ 730 882 typedef IEMNATIVEFIXUP *PIEMNATIVEFIXUP; 731 883 … … 973 1125 AssertReturn(pbCodeBuf, UINT32_MAX); 974 1126 if (iGpr >= 8) 975 pbCodeBuf[off++] = X86_OP_REX_ R;1127 pbCodeBuf[off++] = X86_OP_REX_B; 976 1128 pbCodeBuf[off++] = 0xb8 + (iGpr & 7); 977 1129 pbCodeBuf[off++] = RT_BYTE1(uImm64); … … 988 1140 pbCodeBuf[off++] = X86_OP_REX_W; 989 1141 else 990 pbCodeBuf[off++] = X86_OP_REX_W | X86_OP_REX_ R;1142 pbCodeBuf[off++] = X86_OP_REX_W | X86_OP_REX_B; 991 1143 pbCodeBuf[off++] = 0xb8 + (iGpr & 7); 992 1144 pbCodeBuf[off++] = RT_BYTE1(uImm64); … … 1071 1223 } 1072 1224 1073 1225 #ifdef RT_ARCH_AMD64 1226 /** 1227 * Common bit of iemNativeEmitLoadGprByBp and friends. 1228 */ 1229 DECL_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 */ 1253 static 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 */ 1271 static 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 */ 1287 static 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 */ 1305 static 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 */ 1323 static 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 */ 1074 1355 static uint32_t iemNativeEmitCheckCallRetAndPassUp(PVMCPUCC pVCpu, uint32_t off, uint8_t idxInstr) 1075 1356 { … … 1115 1396 1116 1397 1398 /** 1399 * Emits a call to a threaded worker function. 1400 */ 1117 1401 static uint32_t iemNativeEmitThreadedCall(PVMCPUCC pVCpu, uint32_t off, PCIEMTHRDEDCALLENTRY pCallEntry) 1118 1402 { … … 1125 1409 /* Load the parameters and emit the call. */ 1126 1410 # ifdef RT_OS_WINDOWS 1411 # ifndef VBOXSTRICTRC_STRICT_ENABLED 1127 1412 off = iemNativeEmitLoadGprFromGpr(pVCpu, off, X86_GREG_xCX, X86_GREG_xBX); 1128 1413 AssertReturn(off != UINT32_MAX, UINT32_MAX); … … 1133 1418 off = iemNativeEmitLoadGprImm64(pVCpu, off, X86_GREG_x9, pCallEntry->auParams[2]); 1134 1419 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 */ 1135 1434 # else 1136 1435 off = iemNativeEmitLoadGprFromGpr(pVCpu, off, X86_GREG_xDI, X86_GREG_xBX); … … 1151 1450 pbCodeBuf[off++] = X86_MODRM_MAKE(X86_MOD_REG, 2, X86_GREG_xAX); 1152 1451 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 1153 1456 /* Check the status code. */ 1154 1457 off = iemNativeEmitCheckCallRetAndPassUp(pVCpu, off, pCallEntry->idxInstr); … … 1167 1470 1168 1471 1472 /** 1473 * Emits a standard epilog. 1474 */ 1169 1475 static uint32_t iemNativeEmitEpilog(PVMCPUCC pVCpu, uint32_t off) 1170 1476 { … … 1189 1495 pbCodeBuf[off++] = 0x8d; /* lea rsp, [rbp - (gcc ? 5 : 7) * 8] */ 1190 1496 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; 1196 1498 1197 1499 /* Pop non-volatile registers and return */ … … 1224 1526 /* Call helper and jump to return point. */ 1225 1527 # ifdef RT_OS_WINDOWS 1226 off = iemNativeEmitLoadGprFromGpr(pVCpu, off, X86_GREG_x R8,X86_GREG_xCX); /* cl = instruction number */1528 off = iemNativeEmitLoadGprFromGpr(pVCpu, off, X86_GREG_x8, X86_GREG_xCX); /* cl = instruction number */ 1227 1529 AssertReturn(off != UINT32_MAX, UINT32_MAX); 1228 1530 off = iemNativeEmitLoadGprFromGpr(pVCpu, off, X86_GREG_xCX, X86_GREG_xBX); … … 1277 1579 1278 1580 1581 /** 1582 * Emits a standard prolog. 1583 */ 1279 1584 static uint32_t iemNativeEmitProlog(PVMCPUCC pVCpu, uint32_t off) 1280 1585 { … … 1315 1620 pbCodeBuf[off++] = 0x50 + X86_GREG_x15 - 8; 1316 1621 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)); 1327 1631 1328 1632 #elif RT_ARCH_ARM64
Note:
See TracChangeset
for help on using the changeset viewer.