Changeset 103911 in vbox for trunk/src/VBox/VMM/include/IEMN8veRecompilerEmit.h
- Timestamp:
- Mar 19, 2024 9:28:05 AM (11 months ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/include/IEMN8veRecompilerEmit.h
r103894 r103911 2854 2854 2855 2855 2856 #ifdef IEMNATIVE_WITH_SIMD_REG_ALLOCATOR 2857 /** 2858 * Emits a 128-bit vector register load via a GPR base address with a displacement. 2859 * 2860 * @note ARM64: Misaligned @a offDisp values and values not in the 2861 * -0x7ff8...0x7ff8 range will require a temporary register (@a iGprTmp) if 2862 * @a iGprReg and @a iGprBase are the same. Will assert / throw if caller 2863 * does not heed this. 2864 */ 2865 DECL_FORCE_INLINE_THROW(uint32_t) 2866 iemNativeEmitLoadVecRegByGprU128Ex(PIEMNATIVEINSTR pCodeBuf, uint32_t off, uint8_t iVecRegDst, uint8_t iGprBase, 2867 int32_t offDisp = 0, uint8_t iGprTmp = UINT8_MAX) 2868 { 2869 #ifdef RT_ARCH_AMD64 2870 /* movdqu reg128, mem128 */ 2871 pCodeBuf[off++] = 0xf3; 2872 if (iVecRegDst >= 8 || iGprBase >= 8) 2873 pCodeBuf[off++] = (iVecRegDst < 8 ? 0 : X86_OP_REX_R) | (iGprBase < 8 ? 0 : X86_OP_REX_B); 2874 pCodeBuf[off++] = 0x0f; 2875 pCodeBuf[off++] = 0x6f; 2876 off = iemNativeEmitGprByGprDisp(pCodeBuf, off, iVecRegDst, iGprBase, offDisp); 2877 RT_NOREF(iGprTmp); 2878 2879 #elif defined(RT_ARCH_ARM64) 2880 off = iemNativeEmitGprByGprLdStEx(pCodeBuf, off, iVecRegDst, iGprBase, offDisp, 2881 kArmv8A64InstrLdStType_Ld_Vr_128, sizeof(RTUINT128U), iGprTmp); 2882 2883 #else 2884 # error "port me" 2885 #endif 2886 return off; 2887 } 2888 2889 2890 /** 2891 * Emits a 128-bit GPR load via a GPR base address with a displacement. 2892 */ 2893 DECL_INLINE_THROW(uint32_t) 2894 iemNativeEmitLoadVecRegByGprU128(PIEMRECOMPILERSTATE pReNative, uint32_t off, uint8_t iVecRegDst, uint8_t iGprBase, int32_t offDisp) 2895 { 2896 #ifdef RT_ARCH_AMD64 2897 off = iemNativeEmitLoadVecRegByGprU128Ex(iemNativeInstrBufEnsure(pReNative, off, 8), off, iVecRegDst, iGprBase, offDisp); 2898 IEMNATIVE_ASSERT_INSTR_BUF_ENSURE(pReNative, off); 2899 2900 #elif defined(RT_ARCH_ARM64) 2901 off = iemNativeEmitGprByGprLdSt(pReNative, off, iVecRegDst, iGprBase, offDisp, kArmv8A64InstrLdStType_Ld_Vr_128, sizeof(RTUINT128U)); 2902 2903 #else 2904 # error "port me" 2905 #endif 2906 return off; 2907 } 2908 #endif 2909 2910 2856 2911 /** 2857 2912 * Emits a 64-bit GPR store via a GPR base address with a displacement. … … 7305 7360 || pVar->enmKind == kIemNativeVarKind_Stack, 7306 7361 IEMNATIVE_DO_LONGJMP(pReNative, VERR_IEM_VAR_UNEXPECTED_KIND)); 7362 AssertStmt(!pVar->fSimdReg, 7363 IEMNATIVE_DO_LONGJMP(pReNative, VERR_IEM_VAR_UNEXPECTED_KIND)); 7307 7364 7308 7365 uint8_t const idxStackSlot = iemNativeVarGetStackSlot(pReNative, idxVar); … … 7310 7367 7311 7368 uint8_t const idxRegVar = pVar->idxReg; 7369 if (idxRegVar < RT_ELEMENTS(pReNative->Core.aHstRegs)) 7370 { 7371 off = iemNativeEmitStoreGprByBp(pReNative, off, offBpDisp, idxRegVar); 7372 iemNativeRegFreeVar(pReNative, idxRegVar, fFlushShadows); 7373 Assert(pVar->idxReg == UINT8_MAX); 7374 } 7375 Assert( pVar->idxStackSlot != UINT8_MAX 7376 && pVar->idxReg == UINT8_MAX); 7377 7378 return iemNativeEmitLeaGprByBp(pReNative, off, idxRegArg, offBpDisp); 7379 } 7380 7381 7312 7382 #ifdef IEMNATIVE_WITH_SIMD_REG_ALLOCATOR 7313 if ( idxRegVar != UINT8_MAX 7314 && pVar->fSimdReg) 7315 { 7316 Assert(idxRegVar < RT_ELEMENTS(pReNative->Core.aHstSimdRegs)); 7317 Assert(pVar->cbVar == sizeof(RTUINT128U) || pVar->cbVar == sizeof(RTUINT256U)); 7318 7383 /** 7384 * Emits code to load the variable address into an argument GPR. 7385 * 7386 * This is a special variant intended for SIMD variables only and only called 7387 * by the TLB miss path in the memory fetch/store code because there we pass 7388 * the value by reference and need both the register and stack depending on which 7389 * path is taken (TLB hit vs. miss). 7390 */ 7391 DECL_FORCE_INLINE_THROW(uint32_t) 7392 iemNativeEmitLoadArgGregWithSimdVarAddrForMemAccess(PIEMRECOMPILERSTATE pReNative, uint32_t off, uint8_t idxRegArg, uint8_t idxVar, 7393 bool fSyncRegWithStack = true) 7394 { 7395 IEMNATIVE_ASSERT_VAR_IDX(pReNative, idxVar); 7396 PIEMNATIVEVAR const pVar = &pReNative->Core.aVars[IEMNATIVE_VAR_IDX_UNPACK(idxVar)]; 7397 AssertStmt( pVar->enmKind == kIemNativeVarKind_Invalid 7398 || pVar->enmKind == kIemNativeVarKind_Stack, 7399 IEMNATIVE_DO_LONGJMP(pReNative, VERR_IEM_VAR_UNEXPECTED_KIND)); 7400 AssertStmt(pVar->fSimdReg, 7401 IEMNATIVE_DO_LONGJMP(pReNative, VERR_IEM_VAR_UNEXPECTED_KIND)); 7402 Assert( pVar->idxStackSlot != UINT8_MAX 7403 && pVar->idxReg != UINT8_MAX); 7404 7405 uint8_t const idxStackSlot = iemNativeVarGetStackSlot(pReNative, idxVar); 7406 int32_t const offBpDisp = iemNativeStackCalcBpDisp(idxStackSlot); 7407 7408 uint8_t const idxRegVar = pVar->idxReg; 7409 Assert(idxRegVar < RT_ELEMENTS(pReNative->Core.aHstSimdRegs)); 7410 Assert(pVar->cbVar == sizeof(RTUINT128U) || pVar->cbVar == sizeof(RTUINT256U)); 7411 7412 if (fSyncRegWithStack) 7413 { 7319 7414 if (pVar->cbVar == sizeof(RTUINT128U)) 7320 7415 off = iemNativeEmitStoreVecRegByBpU128(pReNative, off, offBpDisp, idxRegVar); 7321 7416 else 7322 7417 off = iemNativeEmitStoreVecRegByBpU256(pReNative, off, offBpDisp, idxRegVar); 7323 7324 iemNativeSimdRegFreeVar(pReNative, idxRegVar, fFlushShadows); 7325 Assert(pVar->idxReg == UINT8_MAX); 7326 } 7327 else 7328 #endif 7329 if (idxRegVar < RT_ELEMENTS(pReNative->Core.aHstRegs)) 7330 { 7331 off = iemNativeEmitStoreGprByBp(pReNative, off, offBpDisp, idxRegVar); 7332 iemNativeRegFreeVar(pReNative, idxRegVar, fFlushShadows); 7333 Assert(pVar->idxReg == UINT8_MAX); 7334 } 7418 } 7419 7420 return iemNativeEmitLeaGprByBp(pReNative, off, idxRegArg, offBpDisp); 7421 } 7422 7423 7424 /** 7425 * Emits code to sync the host SIMD register assigned to the given SIMD variable. 7426 * 7427 * This is a special helper and only called 7428 * by the TLB miss path in the memory fetch/store code because there we pass 7429 * the value by reference and need to sync the value on the stack with the assigned host register 7430 * after a TLB miss where the value ends up on the stack. 7431 */ 7432 DECL_FORCE_INLINE_THROW(uint32_t) 7433 iemNativeEmitSimdVarSyncStackToRegister(PIEMRECOMPILERSTATE pReNative, uint32_t off, uint8_t idxVar) 7434 { 7435 IEMNATIVE_ASSERT_VAR_IDX(pReNative, idxVar); 7436 PIEMNATIVEVAR const pVar = &pReNative->Core.aVars[IEMNATIVE_VAR_IDX_UNPACK(idxVar)]; 7437 AssertStmt( pVar->enmKind == kIemNativeVarKind_Invalid 7438 || pVar->enmKind == kIemNativeVarKind_Stack, 7439 IEMNATIVE_DO_LONGJMP(pReNative, VERR_IEM_VAR_UNEXPECTED_KIND)); 7440 AssertStmt(pVar->fSimdReg, 7441 IEMNATIVE_DO_LONGJMP(pReNative, VERR_IEM_VAR_UNEXPECTED_KIND)); 7335 7442 Assert( pVar->idxStackSlot != UINT8_MAX 7336 && pVar->idxReg == UINT8_MAX); 7337 7338 return iemNativeEmitLeaGprByBp(pReNative, off, idxRegArg, offBpDisp); 7339 } 7340 7341 7342 #ifdef IEMNATIVE_WITH_SIMD_REG_ALLOCATOR 7443 && pVar->idxReg != UINT8_MAX); 7444 7445 uint8_t const idxStackSlot = iemNativeVarGetStackSlot(pReNative, idxVar); 7446 int32_t const offBpDisp = iemNativeStackCalcBpDisp(idxStackSlot); 7447 7448 uint8_t const idxRegVar = pVar->idxReg; 7449 Assert(idxRegVar < RT_ELEMENTS(pReNative->Core.aHstSimdRegs)); 7450 Assert(pVar->cbVar == sizeof(RTUINT128U) || pVar->cbVar == sizeof(RTUINT256U)); 7451 7452 if (pVar->cbVar == sizeof(RTUINT128U)) 7453 off = iemNativeEmitLoadVecRegByBpU128(pReNative, off, idxRegVar, offBpDisp); 7454 else 7455 off = iemNativeEmitLoadVecRegByBpU256(pReNative, off, idxRegVar, offBpDisp); 7456 7457 return off; 7458 } 7459 7343 7460 7344 7461 /**
Note:
See TracChangeset
for help on using the changeset viewer.