Changeset 103675 in vbox for trunk/src/VBox/VMM/VMMAll/target-x86
- Timestamp:
- Mar 5, 2024 2:10:37 AM (11 months ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/VMMAll/target-x86/IEMAllN8veEmit-x86.h
r103657 r103675 33 33 34 34 35 #ifdef RT_ARCH_AMD64 36 DECL_FORCE_INLINE(uint32_t) 37 iemNativeEmitAmd64ModRmInstrRREx(PIEMNATIVEINSTR pCodeBuf, uint32_t off, uint8_t bOpcode8, uint8_t bOpcodeOther, 38 uint8_t cOpBits, uint8_t idxRegReg, uint8_t idxRegRm) 39 { 40 Assert(idxRegReg < 16); Assert(idxRegRm < 16); 41 switch (cOpBits) 42 { 43 case 16: 44 pCodeBuf[off++] = X86_OP_PRF_SIZE_OP; 45 RT_FALL_THRU(); 46 case 32: 47 if (idxRegReg >= 8 || idxRegRm >= 8) 48 pCodeBuf[off++] = (idxRegReg >= 8 ? X86_OP_REX_R : 0) | (idxRegRm >= 8 ? X86_OP_REX_B : 0); 49 pCodeBuf[off++] = bOpcodeOther; 50 break; 51 52 default: AssertFailed(); RT_FALL_THRU(); 53 case 64: 54 pCodeBuf[off++] = X86_OP_REX_W | (idxRegReg >= 8 ? X86_OP_REX_R : 0) | (idxRegRm >= 8 ? X86_OP_REX_B : 0); 55 pCodeBuf[off++] = bOpcodeOther; 56 break; 57 58 case 8: 59 if (idxRegReg >= 8 || idxRegRm >= 8) 60 pCodeBuf[off++] = (idxRegReg >= 8 ? X86_OP_REX_R : 0) | (idxRegRm >= 8 ? X86_OP_REX_B : 0); 61 else if (idxRegReg >= 4 || idxRegRm >= 4) 62 pCodeBuf[off++] = X86_OP_REX; 63 pCodeBuf[off++] = bOpcode8; 64 break; 65 } 66 pCodeBuf[off++] = X86_MODRM_MAKE(X86_MOD_REG, idxRegReg & 7, idxRegRm & 7); 67 return off; 68 } 69 #endif /* RT_ARCH_AMD64 */ 70 71 35 72 /** 36 * This is an implementation of IEM_EFL_UPDATE_STATUS_BITS_FOR_LOGICAL 37 * and friends. 73 * This is an implementation of IEM_EFL_UPDATE_STATUS_BITS_FOR_LOGICAL. 38 74 * 39 75 * It takes liveness stuff into account. … … 121 157 } 122 158 return off; 159 } 160 161 162 /** 163 * This is an implementation of IEM_EFL_UPDATE_STATUS_BITS_FOR_ARITHMETIC. 164 * 165 * It takes liveness stuff into account. 166 */ 167 DECL_FORCE_INLINE_THROW(uint32_t) 168 iemNativeEmitEFlagsForArithmetic(PIEMRECOMPILERSTATE pReNative, uint32_t off, uint8_t idxVarEfl 169 #ifndef RT_ARCH_AMD64 170 , uint8_t cOpBits, uint8_t idxRegResult, uint8_t idxRegDstIn, uint8_t idxRegSrc, bool fNativeFlags 171 #endif 172 ) 173 { 174 #ifdef IEMNATIVE_WITH_LIVENESS_ANALYSIS 175 if (1) /** @todo check if all bits are clobbered. */ 176 #endif 177 { 178 #ifdef RT_ARCH_AMD64 179 /* 180 * Collect flags and merge them with eflags. 181 */ 182 PIEMNATIVEINSTR pCodeBuf = iemNativeInstrBufEnsure(pReNative, off, 1); 183 /* pushf - do this before any reg allocations as they may emit instructions too. */ 184 pCodeBuf[off++] = 0x9c; 185 186 uint8_t const idxRegEfl = iemNativeVarRegisterAcquire(pReNative, idxVarEfl, &off, true /*fInitialized*/); 187 uint8_t const idxTmpReg = iemNativeRegAllocTmp(pReNative, &off); 188 pCodeBuf = iemNativeInstrBufEnsure(pReNative, off, 2 + 7 + 7 + 3); 189 /* pop tmp */ 190 if (idxTmpReg >= 8) 191 pCodeBuf[off++] = X86_OP_REX_B; 192 pCodeBuf[off++] = 0x58 + (idxTmpReg & 7); 193 /* Isolate the flags we want. */ 194 off = iemNativeEmitAndGpr32ByImmEx(pCodeBuf, off, idxTmpReg, X86_EFL_STATUS_BITS); 195 /* Clear the status bits in EFLs. */ 196 off = iemNativeEmitAndGpr32ByImmEx(pCodeBuf, off, idxRegEfl, ~X86_EFL_STATUS_BITS); 197 /* OR in the flags we collected. */ 198 off = iemNativeEmitOrGpr32ByGprEx(pCodeBuf, off, idxRegEfl, idxTmpReg); 199 iemNativeVarRegisterRelease(pReNative, idxVarEfl); 200 iemNativeRegFreeTmp(pReNative, idxTmpReg); 201 202 #elif defined(RT_ARCH_ARM64) 203 /* 204 * Calculate flags. 205 */ 206 uint8_t const idxRegEfl = iemNativeVarRegisterAcquire(pReNative, idxVarEfl, &off, true /*fInitialized*/); 207 uint8_t const idxTmpReg = iemNativeRegAllocTmp(pReNative, &off); 208 PIEMNATIVEINSTR const pCodeBuf = iemNativeInstrBufEnsure(pReNative, off, 18); 209 210 if (fNativeFlags && cOpBits >= 32) 211 { 212 /* Invert CF (stored inved on ARM) and load the flags into the temporary register. */ 213 pCodeBuf[off++] = ARMV8_A64_INSTR_CFINV; 214 pCodeBuf[off++] = Armv8A64MkInstrMrs(idxTmpReg, ARMV8_AARCH64_SYSREG_NZCV); /* Bits: 31=N; 30=Z; 29=C; 28=V; */ 215 216 /* V -> OF */ 217 pCodeBuf[off++] = Armv8A64MkInstrLsrImm(idxTmpReg, idxTmpReg, 28); 218 pCodeBuf[off++] = Armv8A64MkInstrBfi(idxRegEfl, idxTmpReg, X86_EFL_OF_BIT, 1, false /*f64Bit*/); 219 220 /* C -> CF */ 221 pCodeBuf[off++] = Armv8A64MkInstrLsrImm(idxTmpReg, idxTmpReg, 1); 222 pCodeBuf[off++] = Armv8A64MkInstrBfi(idxRegEfl, idxTmpReg, X86_EFL_CF_BIT, 1, false /*f64Bit*/); 223 224 /* N,Z -> SF,ZF */ 225 pCodeBuf[off++] = Armv8A64MkInstrLsrImm(idxTmpReg, idxTmpReg, 1); 226 pCodeBuf[off++] = Armv8A64MkInstrBfi(idxRegEfl, idxTmpReg, X86_EFL_ZF_BIT, 2, false /*f64Bit*/); 227 } 228 else 229 { 230 #if 0 231 pCodeBuf[off++] = Armv8A64MkInstrSetF8SetF16(idxRegResult, cOpBits > 8); 232 pCodeBuf[off++] = Armv8A64MkInstrMrs(idxTmpReg, ARMV8_AARCH64_SYSREG_NZCV); /* Bits: 31=N; 30=Z; 29=C; 28=V; */ 233 234 /* V -> OF */ 235 pCodeBuf[off++] = Armv8A64MkInstrLsrImm(idxTmpReg, idxTmpReg, 28); 236 pCodeBuf[off++] = Armv8A64MkInstrBfi(idxRegEfl, idxTmpReg, X86_EFL_OF_BIT, 1, false /*f64Bit*/); 237 238 /* N,Z -> SF,ZF */ 239 pCodeBuf[off++] = Armv8A64MkInstrLsrImm(idxTmpReg, idxTmpReg, 2); 240 pCodeBuf[off++] = Armv8A64MkInstrBfi(idxRegEfl, idxTmpReg, X86_EFL_ZF_BIT, 2, false /*f64Bit*/); 241 #else 242 pCodeBuf[off++] = Armv8A64MkInstrBrk(0x1010); 243 #endif 244 } 245 246 /* Calculate 8-bit parity of the result. */ 247 pCodeBuf[off++] = Armv8A64MkInstrEor(idxTmpReg, idxRegResult, idxRegResult, false /*f64Bit*/, 248 4 /*offShift6*/, kArmv8A64InstrShift_Lsr); 249 pCodeBuf[off++] = Armv8A64MkInstrEor(idxTmpReg, idxTmpReg, idxTmpReg, false /*f64Bit*/, 250 2 /*offShift6*/, kArmv8A64InstrShift_Lsr); 251 pCodeBuf[off++] = Armv8A64MkInstrEor(idxTmpReg, idxTmpReg, idxTmpReg, false /*f64Bit*/, 252 1 /*offShift6*/, kArmv8A64InstrShift_Lsr); 253 Assert(Armv8A64ConvertImmRImmS2Mask32(0, 0) == 1); 254 pCodeBuf[off++] = Armv8A64MkInstrEorImm(idxTmpReg, idxTmpReg, 0, 0, false /*f64Bit*/); 255 pCodeBuf[off++] = Armv8A64MkInstrBfi(idxRegEfl, idxTmpReg, X86_EFL_PF_BIT, 1, false /*f64Bit*/); 256 257 /* Calculate auxilary carry/borrow. This is related to 8-bit BCD.*/ 258 pCodeBuf[off++] = Armv8A64MkInstrEor(idxTmpReg, idxRegDstIn, idxRegSrc, false /*f64Bit*/); 259 pCodeBuf[off++] = Armv8A64MkInstrEor(idxTmpReg, idxTmpReg, idxRegResult, false /*f64Bit*/); 260 pCodeBuf[off++] = Armv8A64MkInstrLsrImm(idxTmpReg, idxTmpReg, X86_EFL_AF_BIT, false /*f64Bit*/); 261 pCodeBuf[off++] = Armv8A64MkInstrBfi(idxRegEfl, idxTmpReg, X86_EFL_AF_BIT, 1, false /*f64Bit*/); 262 263 iemNativeVarRegisterRelease(pReNative, idxVarEfl); 264 iemNativeRegFreeTmp(pReNative, idxTmpReg); 265 #else 266 # error "port me" 267 #endif 268 IEMNATIVE_ASSERT_INSTR_BUF_ENSURE(pReNative, off); 269 } 270 return off; 271 123 272 } 124 273 … … 405 554 uint8_t idxVarDst, uint8_t idxVarSrc, uint8_t idxVarEfl, uint8_t cOpBits) 406 555 { 407 RT_NOREF(idxVarDst, idxVarSrc, idxVarEfl, cOpBits); 408 AssertFailed(); 409 return iemNativeEmitBrk(pReNative, off, 0x666); 556 /* 557 * The SUB instruction will set all flags. 558 */ 559 uint8_t const idxRegDst = iemNativeVarRegisterAcquire(pReNative, idxVarDst, &off, true /*fInitialized*/); 560 uint8_t const idxRegSrc = iemNativeVarRegisterAcquire(pReNative, idxVarSrc, &off, true /*fInitialized*/); 561 562 #ifdef RT_ARCH_ARM64 563 /* On ARM64 we'll need the two input operands as well as the result in order 564 to calculate the right flags, even if we use SUBS and translates NZCV into 565 OF, CF, ZF and SF. */ 566 567 /* Copy idxRegDst. */ 568 uint8_t const idxRegDstIn = iemNativeRegAllocTmp(pReNative, &off); 569 PIEMNATIVEINSTR const pCodeBuf = iemNativeInstrBufEnsure(pReNative, off, 4); 570 571 /* Do the SUB setting flags. */ 572 if (cOpBits >= 32) 573 { 574 off = iemNativeEmitLoadGprFromGprEx(pCodeBuf, off, idxRegDstIn, idxRegDst); 575 pCodeBuf[off++] = Armv8A64MkInstrSubReg(idxRegDst, idxRegDst, idxRegSrc, cOpBits > 32 /*f64Bit*/, true /*fSetFlags*/); 576 } 577 else 578 { 579 /* Shift the operands up so we can perform a 32-bit operation and get all four flags. */ 580 uint32_t const cShift = 32 - cOpBits; 581 pCodeBuf[off++] = Armv8A64MkInstrOrr(idxRegDstIn, ARMV8_A64_REG_XZR, idxRegDst, false /*f64Bit*/, cShift); 582 pCodeBuf[off++] = Armv8A64MkInstrSubReg(idxRegDst, idxRegDstIn, idxRegSrc, cOpBits > 32 /*f64Bit*/, 583 true /*fSetFlags*/, cShift); 584 pCodeBuf[off++] = Armv8A64MkInstrLsrImm(idxRegDstIn, idxRegDstIn, cShift, false /*f64Bit*/); 585 pCodeBuf[off++] = Armv8A64MkInstrLsrImm(idxRegDst, idxRegDst, cShift, false /*f64Bit*/); 586 } 587 588 IEMNATIVE_ASSERT_INSTR_BUF_ENSURE(pReNative, off); 589 590 off = iemNativeEmitEFlagsForArithmetic(pReNative, off, idxVarEfl, RT_MAX(cOpBits, 32), idxRegDst, 591 idxRegDstIn, idxRegSrc, true /*fNativeFlags*/); 592 593 iemNativeRegFreeTmp(pReNative, idxRegDstIn); 594 iemNativeVarRegisterRelease(pReNative, idxVarSrc); 595 iemNativeVarRegisterRelease(pReNative, idxVarDst); 596 597 #elif defined(RT_ARCH_AMD64) 598 /* On AMD64 we must use the correctly sized AND instructions to get the 599 right EFLAGS.SF value, while the rest will just lump 16-bit and 8-bit 600 in the 32-bit ones. */ 601 off = iemNativeEmitAmd64ModRmInstrRREx(iemNativeInstrBufEnsure(pReNative, off, 4), off, 602 0x2a, 0x2b, cOpBits, idxRegDst, idxRegSrc); 603 IEMNATIVE_ASSERT_INSTR_BUF_ENSURE(pReNative, off); 604 605 iemNativeVarRegisterRelease(pReNative, idxVarSrc); 606 iemNativeVarRegisterRelease(pReNative, idxVarDst); 607 608 off = iemNativeEmitEFlagsForArithmetic(pReNative, off, idxVarEfl); 609 610 #else 611 # error "port me" 612 #endif 613 return off; 410 614 } 411 615
Note:
See TracChangeset
for help on using the changeset viewer.