Changeset 106197 in vbox for trunk/src/VBox
- Timestamp:
- Oct 1, 2024 3:35:13 PM (6 months ago)
- svn:sync-xref-src-repo-rev:
- 164981
- Location:
- trunk/src/VBox/VMM/VMMAll
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/VMMAll/IEMAllN8veRecompiler.cpp
r106192 r106197 3105 3105 * @param off Current code buffer position. 3106 3106 * @param fFlushGstReg The guest register set to flush (default is flush everything). 3107 * @note Must not modify the host status flags! 3107 3108 */ 3108 3109 DECL_HIDDEN_THROW(uint32_t) … … 3137 3138 * @param idxHstReg The host register. 3138 3139 * 3139 * @note This doesn't do any unshadowing of guest registers from the host register. 3140 * @note This doesn't do any unshadowing of guest registers from the host register. 3141 * 3142 * @note Must not modify the host status flags! 3140 3143 */ 3141 3144 DECL_HIDDEN_THROW(uint32_t) iemNativeRegFlushDirtyGuestByHostRegShadow(PIEMRECOMPILERSTATE pReNative, uint32_t off, uint8_t idxHstReg) … … 3178 3181 * recording debug info. Does NOT throw anything if we're out of 3179 3182 * registers, though. 3183 * 3184 * @note Must not modify the host status flags! 3180 3185 */ 3181 3186 static uint8_t iemNativeRegAllocFindFree(PIEMRECOMPILERSTATE pReNative, uint32_t *poff, bool fPreferVolatile, … … 3470 3475 * registers (@c true, default) or the other way around 3471 3476 * (@c false, for iemNativeRegAllocTmpForGuestReg()). 3477 * 3478 * @note Must not modify the host status flags! 3472 3479 */ 3473 3480 DECL_HIDDEN_THROW(uint8_t) iemNativeRegAllocTmp(PIEMRECOMPILERSTATE pReNative, uint32_t *poff, bool fPreferVolatile /*= true*/) … … 7321 7328 * 7322 7329 * @returns The host register number. 7323 * @param pReNative The recompiler state. 7324 * @param idxVar The variable. 7325 * @param poff Pointer to the instruction buffer offset. 7326 * In case a register needs to be freed up or the value 7327 * loaded off the stack. 7328 * @param fInitialized Set if the variable must already have been initialized. 7329 * Will throw VERR_IEM_VAR_NOT_INITIALIZED if this is not 7330 * the case. 7331 * @param idxRegPref Preferred register number or UINT8_MAX. 7330 * @param pReNative The recompiler state. 7331 * @param idxVar The variable. 7332 * @param poff Pointer to the instruction buffer offset. 7333 * In case a register needs to be freed up or the value 7334 * loaded off the stack. 7335 * @param fInitialized Set if the variable must already have been 7336 * initialized. Will throw VERR_IEM_VAR_NOT_INITIALIZED 7337 * if this is not the case. 7338 * @param idxRegPref Preferred register number or UINT8_MAX. 7339 * 7340 * @note Must not modify the host status flags! 7332 7341 */ 7333 7342 DECL_HIDDEN_THROW(uint8_t) iemNativeVarRegisterAcquire(PIEMRECOMPILERSTATE pReNative, uint8_t idxVar, uint32_t *poff, -
trunk/src/VBox/VMM/VMMAll/target-x86/IEMAllN8veEmit-x86.h
r106196 r106197 255 255 pReNative->PostponedEfl.idxReg1 = UINT8_MAX; 256 256 pReNative->PostponedEfl.idxReg2 = UINT8_MAX; 257 # if defined(VBOX_WITH_STATISTICS) || defined(IEMNATIVE_WITH_TB_DEBUG_INFO)257 # if defined(VBOX_WITH_STATISTICS) || defined(IEMNATIVE_WITH_TB_DEBUG_INFO) 258 258 STAM_PROFILE_ADD_PERIOD(&pReNative->pVCpu->iem.s.StatNativeEflPostponedEmits, pReNative->PostponedEfl.cEmits); 259 259 pReNative->PostponedEfl.cEmits = 0; 260 #endif 261 } 262 } 263 260 # endif 261 } 262 } 263 264 #endif /* IEMNATIVE_WITH_EFLAGS_POSTPONING */ 265 266 267 template<bool const a_fDoOp> 264 268 DECL_INLINE_THROW(uint32_t) iemNativeEmitPostponedEFlagsCalcLogical(PIEMNATIVEINSTR pCodeBuf, uint32_t off, uint8_t cOpBits, 265 269 uint8_t idxRegResult, uint8_t idxRegEfl, uint8_t idxRegTmp) 266 270 { 267 271 #ifdef RT_ARCH_AMD64 272 /* Do TEST idxRegResult, idxRegResult to set flags. */ 273 if RT_CONSTEXPR_IF(a_fDoOp) 274 off = iemNativeEmitAmd64OneByteModRmInstrRREx(pCodeBuf, off, 0x84, 0x85, cOpBits, idxRegResult, idxRegResult); 275 268 276 /* 269 * Do an AND and collect flags and merge them with eflags. 277 * Collect the EFLAGS status bits. 278 * We know that the overflow bit will always be cleared, so LAHF can be used. 270 279 */ 271 /* Do TEST idxRegResult, idxRegResult to set flags. */272 off = iemNativeEmitAmd64OneByteModRmInstrRREx(pCodeBuf, off, 0x84, 0x85, cOpBits, idxRegResult, idxRegResult);273 274 280 if (idxRegTmp == X86_GREG_xAX) 275 281 { … … 295 301 else if (idxRegEfl != X86_GREG_xAX) 296 302 { 303 # if 1 /* This is 1 or 4 bytes larger, but avoids the stack. */ 304 /* xchg rax, tmp */ 305 pCodeBuf[off++] = idxRegTmp < 8 ? X86_OP_REX_W : X86_OP_REX_B | X86_OP_REX_W; 306 pCodeBuf[off++] = 0x90 + (idxRegTmp & 7); 307 308 /* lahf ; AH = EFLAGS */ 309 pCodeBuf[off++] = 0x9f; 310 if (idxRegEfl <= X86_GREG_xBX) 311 { 312 /* mov [CDB]L, AH */ 313 pCodeBuf[off++] = 0x88; 314 pCodeBuf[off++] = X86_MODRM_MAKE(X86_MOD_REG, 4 /*AH*/, idxRegEfl); 315 } 316 else 317 { 318 /* mov AL, AH */ 319 pCodeBuf[off++] = 0x88; 320 pCodeBuf[off++] = X86_MODRM_MAKE(X86_MOD_REG, 4 /*AH*/, 0 /*AL*/); 321 /* mov xxL, AL */ 322 pCodeBuf[off++] = idxRegEfl >= 8 ? X86_OP_REX_B : X86_OP_REX; 323 pCodeBuf[off++] = 0x88; 324 pCodeBuf[off++] = X86_MODRM_MAKE(X86_MOD_REG, 0 /*AL*/, idxRegEfl & 7); 325 } 326 327 /* xchg rax, tmp */ 328 pCodeBuf[off++] = idxRegTmp < 8 ? X86_OP_REX_W : X86_OP_REX_B | X86_OP_REX_W; 329 pCodeBuf[off++] = 0x90 + (idxRegTmp & 7); 330 331 # else 297 332 /* pushf */ 298 333 pCodeBuf[off++] = 0x9c; … … 302 337 pCodeBuf[off++] = 0x58 + (idxRegTmp & 7); 303 338 /* mov byte(efl), byte(tmp) */ 304 pCodeBuf[off++] = (idxRegEfl >= 8 ? X86_OP_REX_B : X86_OP_REX) 305 | (idxRegTmp >= 8 ? X86_OP_REX_R : 0); 339 if (idxRegEfl >= 4 || idxRegTmp >= 4) 340 pCodeBuf[off++] = (idxRegEfl >= 8 ? X86_OP_REX_B : X86_OP_REX) 341 | (idxRegTmp >= 8 ? X86_OP_REX_R : 0); 306 342 pCodeBuf[off++] = 0x88; 307 343 pCodeBuf[off++] = X86_MODRM_MAKE(X86_MOD_REG, idxRegTmp & 7, idxRegEfl & 7); 344 # endif 308 345 } 309 346 else … … 318 355 pCodeBuf[off++] = X86_MODRM_MAKE(X86_MOD_REG, 4 /*AH*/, 0 /*AL*/); 319 356 } 320 /* BT CidxEfl, 11; Clear OF */357 /* BTR idxEfl, 11; Clear OF */ 321 358 if (idxRegEfl >= 8) 322 359 pCodeBuf[off++] = X86_OP_REX_B; 323 360 pCodeBuf[off++] = 0xf; 324 361 pCodeBuf[off++] = 0xba; 325 pCodeBuf[off++] = X86_MODRM_MAKE(X86_MOD_REG, 7, idxRegEfl & 7);362 pCodeBuf[off++] = X86_MODRM_MAKE(X86_MOD_REG, 6, idxRegEfl & 7); 326 363 pCodeBuf[off++] = X86_EFL_OF_BIT; 327 364 … … 337 374 if (cOpBits < 32) 338 375 pCodeBuf[off++] = Armv8A64MkInstrSetF8SetF16(idxRegResult, cOpBits > 8); /* sets NZ */ 339 else 376 else if RT_CONSTEXPR_IF(a_fDoOp) 340 377 pCodeBuf[off++] = Armv8A64MkInstrAnds(ARMV8_A64_REG_XZR, idxRegResult, idxRegResult, cOpBits > 32 /*f64Bit*/); 341 378 pCodeBuf[off++] = Armv8A64MkInstrMrs(idxRegTmp, ARMV8_AARCH64_SYSREG_NZCV); /* Bits: 31=N; 30=Z; 29=C; 28=V; */ … … 361 398 } 362 399 400 #ifdef IEMNATIVE_WITH_EFLAGS_POSTPONING 363 401 364 402 template<uint32_t const a_bmInputRegs, bool const a_fTlbMiss = false> … … 366 404 uint32_t bmExtraTlbMissRegs = 0) 367 405 { 368 # ifdef IEMNATIVE_WITH_TB_DEBUG_INFO406 # ifdef IEMNATIVE_WITH_TB_DEBUG_INFO 369 407 iemNativeDbgInfoAddPostponedEFlagsCalc(pReNative, off, pReNative->PostponedEfl.enmOp, pReNative->PostponedEfl.cOpBits, 370 408 pReNative->PostponedEfl.cEmits); 371 # endif409 # endif 372 410 373 411 /* … … 416 454 if RT_CONSTEXPR_IF(!a_fTlbMiss) Assert(bmAvailableRegs & RT_BIT_32(idxRegEfl)); 417 455 bmAvailableRegs &= ~RT_BIT_32(idxRegEfl); 418 # ifdef VBOX_STRICT456 # ifdef VBOX_STRICT 419 457 off = iemNativeEmitGuestRegValueCheckEx(pReNative, pCodeBuf, off, idxRegEfl, kIemNativeGstReg_EFlags); 420 # endif458 # endif 421 459 422 460 idxRegTmp = ASMBitFirstSetU32(bmAvailableRegs) - 1; … … 441 479 case kIemNativePostponedEflOp_Logical: 442 480 Assert(pReNative->PostponedEfl.idxReg2 == UINT8_MAX); 443 off = iemNativeEmitPostponedEFlagsCalcLogical (pCodeBuf, off, pReNative->PostponedEfl.cOpBits,444 pReNative->PostponedEfl.idxReg1, idxRegEfl, idxRegTmp);481 off = iemNativeEmitPostponedEFlagsCalcLogical<true>(pCodeBuf, off, pReNative->PostponedEfl.cOpBits, 482 pReNative->PostponedEfl.idxReg1, idxRegEfl, idxRegTmp); 445 483 break; 446 484 … … 452 490 * Store EFLAGS. 453 491 */ 454 # ifdef VBOX_STRICT492 # ifdef VBOX_STRICT 455 493 /* check that X86_EFL_1 is set. */ 456 494 uint32_t offFixup1; … … 464 502 off = iemNativeEmitBrkEx(pCodeBuf, off, 0x3331); 465 503 iemNativeFixupFixedJump(pReNative, offFixup2, off); 466 # endif504 # endif 467 505 off = iemNativeEmitStoreGprToVCpuU32Ex(pCodeBuf, off, idxRegEfl, RT_UOFFSETOF(VMCPU, cpum.GstCtx.eflags)); 468 506 IEMNATIVE_ASSERT_INSTR_BUF_ENSURE(pReNative, off); 469 507 470 # if defined(VBOX_WITH_STATISTICS) || defined(IEMNATIVE_WITH_TB_DEBUG_INFO)508 # if defined(VBOX_WITH_STATISTICS) || defined(IEMNATIVE_WITH_TB_DEBUG_INFO) 471 509 pReNative->PostponedEfl.cEmits++; 472 # endif510 # endif 473 511 return off; 474 512 } … … 513 551 } 514 552 515 516 553 #endif /* IEMNATIVE_WITH_EFLAGS_POSTPONING */ 517 554 … … 522 559 * It takes liveness stuff into account. 523 560 */ 561 /** @todo make fNativeFlags a template argument. */ 524 562 DECL_INLINE_THROW(uint32_t) 525 563 iemNativeEmitEFlagsForLogical(PIEMRECOMPILERSTATE pReNative, uint32_t off, uint8_t idxVarEfl, … … 577 615 #endif 578 616 { 579 #ifdef RT_ARCH_AMD64 580 /* 581 * Collect flags and merge them with eflags. 582 */ 583 /** @todo we could alternatively use LAHF here when host rax is free since, 584 * OF is cleared. */ 585 PIEMNATIVEINSTR pCodeBuf = iemNativeInstrBufEnsure(pReNative, off, 1); 586 /* pushf - do this before any reg allocations as they may emit instructions too. */ 587 pCodeBuf[off++] = 0x9c; 588 589 uint8_t const idxRegEfl = iemNativeVarRegisterAcquire(pReNative, idxVarEfl, &off, true /*fInitialized*/); 590 uint8_t const idxTmpReg = iemNativeRegAllocTmp(pReNative, &off); 591 pCodeBuf = iemNativeInstrBufEnsure(pReNative, off, 2 + 7 + 7 + 3); 592 /* pop tmp */ 593 if (idxTmpReg >= 8) 594 pCodeBuf[off++] = X86_OP_REX_B; 595 pCodeBuf[off++] = 0x58 + (idxTmpReg & 7); 596 /* and tmp, X86_EFL_PF | X86_EFL_ZF | X86_EFL_SF */ 597 off = iemNativeEmitAndGpr32ByImmEx(pCodeBuf, off, idxTmpReg, X86_EFL_PF | X86_EFL_ZF | X86_EFL_SF); 598 /* Clear the status bits in EFLs. */ 599 off = iemNativeEmitAndGpr32ByImmEx(pCodeBuf, off, idxRegEfl, ~X86_EFL_STATUS_BITS); 600 /* OR in the flags we collected. */ 601 off = iemNativeEmitOrGpr32ByGprEx(pCodeBuf, off, idxRegEfl, idxTmpReg); 617 uint8_t const idxRegEfl = iemNativeVarRegisterAcquire(pReNative, idxVarEfl, &off, true /*fInitialized*/); 618 uint8_t const idxRegTmp = iemNativeRegAllocTmp(pReNative, &off); 619 #ifdef RT_ARCH_AMD64 620 PIEMNATIVEINSTR const pCodeBuf = iemNativeInstrBufEnsure(pReNative, off, 32); 621 #elif defined(RT_ARCH_ARM64) 622 PIEMNATIVEINSTR const pCodeBuf = iemNativeInstrBufEnsure(pReNative, off, 16); 623 #else 624 # error "port me" 625 #endif 626 #ifndef RT_ARCH_AMD64 627 if (!fNativeFlags) 628 off = iemNativeEmitPostponedEFlagsCalcLogical<true>(pCodeBuf, off, cOpBits, idxRegResult, idxRegEfl, idxRegTmp); 629 else 630 #endif 631 off = iemNativeEmitPostponedEFlagsCalcLogical<false>(pCodeBuf, off, cOpBits, idxRegResult, idxRegEfl, idxRegTmp); 632 IEMNATIVE_ASSERT_INSTR_BUF_ENSURE(pReNative, off); 633 602 634 iemNativeVarRegisterRelease(pReNative, idxVarEfl); 603 iemNativeRegFreeTmp(pReNative, idxTmpReg); 604 605 #elif defined(RT_ARCH_ARM64) 606 /* 607 * Calculate flags. 608 */ 609 uint8_t const idxRegEfl = iemNativeVarRegisterAcquire(pReNative, idxVarEfl, &off, true /*fInitialized*/); 610 uint8_t const idxTmpReg = iemNativeRegAllocTmp(pReNative, &off); 611 PIEMNATIVEINSTR const pCodeBuf = iemNativeInstrBufEnsure(pReNative, off, 15); 612 613 /* Clear the status bits. ~0x8D5 (or ~0x8FD) can't be AND immediate, so use idxTmpReg for constant. */ 614 off = iemNativeEmitLoadGpr32ImmEx(pCodeBuf, off, idxTmpReg, ~X86_EFL_STATUS_BITS); 615 off = iemNativeEmitAndGpr32ByGpr32Ex(pCodeBuf, off, idxRegEfl, idxTmpReg); 616 617 /* N,Z -> SF,ZF */ 618 if (cOpBits < 32) 619 pCodeBuf[off++] = Armv8A64MkInstrSetF8SetF16(idxRegResult, cOpBits > 8); /* sets NZ */ 620 else if (!fNativeFlags) 621 pCodeBuf[off++] = Armv8A64MkInstrAnds(ARMV8_A64_REG_XZR, idxRegResult, idxRegResult, cOpBits > 32 /*f64Bit*/); 622 pCodeBuf[off++] = Armv8A64MkInstrMrs(idxTmpReg, ARMV8_AARCH64_SYSREG_NZCV); /* Bits: 31=N; 30=Z; 29=C; 28=V; */ 623 pCodeBuf[off++] = Armv8A64MkInstrLsrImm(idxTmpReg, idxTmpReg, 30); 624 pCodeBuf[off++] = Armv8A64MkInstrBfi(idxRegEfl, idxTmpReg, X86_EFL_ZF_BIT, 2, false /*f64Bit*/); 625 AssertCompile(X86_EFL_ZF_BIT + 1 == X86_EFL_SF_BIT); 626 627 /* Calculate 8-bit parity of the result. */ 628 pCodeBuf[off++] = Armv8A64MkInstrEor(idxTmpReg, idxRegResult, idxRegResult, false /*f64Bit*/, 629 4 /*offShift6*/, kArmv8A64InstrShift_Lsr); 630 pCodeBuf[off++] = Armv8A64MkInstrEor(idxTmpReg, idxTmpReg, idxTmpReg, false /*f64Bit*/, 631 2 /*offShift6*/, kArmv8A64InstrShift_Lsr); 632 pCodeBuf[off++] = Armv8A64MkInstrEor(idxTmpReg, idxTmpReg, idxTmpReg, false /*f64Bit*/, 633 1 /*offShift6*/, kArmv8A64InstrShift_Lsr); 634 Assert(Armv8A64ConvertImmRImmS2Mask32(0, 0) == 1); 635 pCodeBuf[off++] = Armv8A64MkInstrEorImm(idxTmpReg, idxTmpReg, 0, 0, false /*f64Bit*/); 636 pCodeBuf[off++] = Armv8A64MkInstrBfi(idxRegEfl, idxTmpReg, X86_EFL_PF_BIT, 1, false /*f64Bit*/); 637 638 iemNativeVarRegisterRelease(pReNative, idxVarEfl); 639 iemNativeRegFreeTmp(pReNative, idxTmpReg); 640 #else 641 # error "port me" 642 #endif 643 IEMNATIVE_ASSERT_INSTR_BUF_ENSURE(pReNative, off); 635 iemNativeRegFreeTmp(pReNative, idxRegTmp); 644 636 } 645 637
Note:
See TracChangeset
for help on using the changeset viewer.