Changeset 103743 in vbox for trunk/src/VBox/VMM/VMMAll
- Timestamp:
- Mar 9, 2024 2:42:29 AM (9 months ago)
- Location:
- trunk/src/VBox/VMM/VMMAll
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/VMMAll/IEMAllInstOneByte.cpp.h
r103742 r103743 1493 1493 { 1494 1494 IEMOP_MNEMONIC2(FIXED, SBB, sbb, AL, Ib, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZES); 1495 IEMOP_BODY_BINARY_AL_Ib(sbb, 0);1495 IEMOP_BODY_BINARY_AL_Ib(sbb, RT_ARCH_VAL_AMD64 | RT_ARCH_VAL_ARM64); 1496 1496 } 1497 1497 … … 1505 1505 { 1506 1506 IEMOP_MNEMONIC2(FIXED, SBB, sbb, rAX, Iz, DISOPTYPE_HARMLESS, 0); 1507 IEMOP_BODY_BINARY_rAX_Iz_RW(sbb, 0);1507 IEMOP_BODY_BINARY_rAX_Iz_RW(sbb, RT_ARCH_VAL_AMD64 | RT_ARCH_VAL_ARM64); 1508 1508 } 1509 1509 … … 4416 4416 { 4417 4417 IEMOP_MNEMONIC(sbb_Eb_Ib, "sbb Eb,Ib"); 4418 IEMOP_BODY_BINARY_Eb_Ib_RW(sbb, 0, 0);4418 IEMOP_BODY_BINARY_Eb_Ib_RW(sbb, RT_ARCH_VAL_AMD64 | RT_ARCH_VAL_ARM64, 0); 4419 4419 } 4420 4420 … … 4989 4989 { 4990 4990 IEMOP_MNEMONIC(sbb_Ev_Iz, "sbb Ev,Iz"); 4991 IEMOP_BODY_BINARY_Ev_Iz_RW(sbb, 0, 0);4991 IEMOP_BODY_BINARY_Ev_Iz_RW(sbb, RT_ARCH_VAL_AMD64 | RT_ARCH_VAL_ARM64, 0); 4992 4992 } 4993 4993 -
trunk/src/VBox/VMM/VMMAll/target-x86/IEMAllN8veEmit-x86.h
r103742 r103743 364 364 pCodeBuf[off++] = Armv8A64MkInstrBfxil(idxRegEfl, idxRegResult, cOpBits, 1, false /*f64Bit*/); 365 365 366 /* The overflow flag is more work. See IEM_EFL_UPDATE_STATUS_BITS_FOR_ARITHMETIC. 367 It is a bit simpler when the right side is constant. */ 366 /* The overflow flag is more work as we have to compare the signed bits for 367 both inputs and the result. See IEM_EFL_UPDATE_STATUS_BITS_FOR_ARITHMETIC. 368 369 Formula: ~(a_uDst ^ a_uSrcOf) & (a_uResult ^ a_uDst) 370 With a_uSrcOf as a_uSrc for additions and ~a_uSrc for subtractions. 371 372 It is a bit simpler when the right (source) side is constant: 373 adc: S D R -> OF sbb: S D R -> OF 374 0 0 0 -> 0 \ 0 0 0 -> 0 \ 375 0 0 1 -> 1 \ 0 0 1 -> 0 \ 376 0 1 0 -> 0 / and not(D), R 0 1 0 -> 1 / and D, not(R) 377 0 1 1 -> 0 / 0 1 1 -> 0 / 378 1 0 0 -> 0 \ 1 0 0 -> 0 \ 379 1 0 1 -> 0 \ and D, not(R) 1 0 1 -> 1 \ and not(D), R 380 1 1 0 -> 1 / 1 1 0 -> 0 / 381 1 1 1 -> 0 / 1 1 1 -> 0 / */ 368 382 if (idxRegSrc != UINT8_MAX) 369 383 { … … 377 391 else if (uImmSrc & RT_BIT_32(cOpBits - 1)) 378 392 { 379 if (fInvertCarry) /* sbb w/ top right 1: ~a_uDst & a_uResult ;HACK ALERT: fInvertCarry == sbb */380 pCodeBuf[off++] = Armv8A64MkInstr Eon(idxTmpReg, idxRegResult, idxRegDstIn, false);381 else /* adc w/ top right 1: a_uDst & ~a_uResult */382 pCodeBuf[off++] = Armv8A64MkInstr Eon(idxTmpReg, idxRegDstIn, idxRegResult, false);393 if (fInvertCarry) /* HACK ALERT: fInvertCarry == sbb */ 394 pCodeBuf[off++] = Armv8A64MkInstrBic(idxTmpReg, idxRegResult, idxRegDstIn, false); 395 else 396 pCodeBuf[off++] = Armv8A64MkInstrBic(idxTmpReg, idxRegDstIn, idxRegResult, false); 383 397 } 384 398 else 385 399 { 386 if (fInvertCarry) /* sbb w/ top right 0: a_uDst & ~a_uResult ;HACK ALERT: fInvertCarry == sbb */387 pCodeBuf[off++] = Armv8A64MkInstr Eon(idxTmpReg, idxRegDstIn, idxRegResult, false);388 else /* adc w/ top right 0: ~a_uDst & a_uResult */389 pCodeBuf[off++] = Armv8A64MkInstr Eon(idxTmpReg, idxRegResult, idxRegDstIn, false);400 if (fInvertCarry) /* HACK ALERT: fInvertCarry == sbb */ 401 pCodeBuf[off++] = Armv8A64MkInstrBic(idxTmpReg, idxRegDstIn, idxRegResult, false); 402 else 403 pCodeBuf[off++] = Armv8A64MkInstrBic(idxTmpReg, idxRegResult, idxRegDstIn, false); 390 404 } 391 405 pCodeBuf[off++] = Armv8A64MkInstrLsrImm(idxTmpReg, idxTmpReg, cOpBits - 1, false /*f64Bit*/); … … 1110 1124 PIEMNATIVEINSTR const pCodeBuf = iemNativeInstrBufEnsure(pReNative, off, 9); 1111 1125 1112 /* Use the BT instruction to set CF according to idxRegEfl. */1113 1126 off = iemNativeEmitAmd64TwoByteModRmInstrRREx(pCodeBuf, off, 0x0f, 0x0b, 0xba, 32 /*cOpBits*/, 4, idxRegEfl); 1114 1127 pCodeBuf[off++] = X86_EFL_CF_BIT; … … 1168 1181 uint8_t idxVarDst, uint64_t uImmOp, uint8_t idxVarEfl, uint8_t cOpBits, uint8_t cImmBits) 1169 1182 { 1170 RT_NOREF(pReNative, off, idxVarDst, uImmOp, idxVarEfl, cOpBits, cImmBits); 1183 uint8_t const idxRegDst = iemNativeVarRegisterAcquire(pReNative, idxVarDst, &off, true /*fInitialized*/); 1184 uint8_t const idxRegEfl = iemNativeVarRegisterAcquire(pReNative, idxVarEfl, &off, true /*fInitialized*/); 1185 1186 #ifdef RT_ARCH_AMD64 1187 /* On AMD64 we use BT to set EFLAGS.CF and then issue an SBB instruction 1188 with matching size to get the correct flags. */ 1189 PIEMNATIVEINSTR const pCodeBuf = iemNativeInstrBufEnsure(pReNative, off, 12); 1190 1191 off = iemNativeEmitAmd64TwoByteModRmInstrRREx(pCodeBuf, off, 0x0f, 0x0b, 0xba, 32 /*cOpBits*/, 4, idxRegEfl); 1192 pCodeBuf[off++] = X86_EFL_CF_BIT; 1193 1194 off = iemNativeEmitAmd64OneByteModRmInstrRIEx(pCodeBuf, off, 0x80, 0x83, 0x81, cOpBits, cImmBits, 3, idxRegDst, uImmOp); 1195 IEMNATIVE_ASSERT_INSTR_BUF_ENSURE(pReNative, off); 1196 1197 iemNativeVarRegisterRelease(pReNative, idxVarDst); 1198 1199 off = iemNativeEmitEFlagsForArithmetic(pReNative, off, UINT8_MAX, idxRegEfl); 1200 1201 #elif defined(RT_ARCH_ARM64) 1202 /* On ARM64 we use the RMIF+CFINV instructions to load PSTATE.CF from 1203 idxRegEfl and then SBCS for the calculation. We need all inputs and 1204 result for the two flags (AF,PF) that can't be directly derived from 1205 PSTATE.NZCV. */ 1206 uint8_t const idxRegDstIn = iemNativeRegAllocTmp(pReNative, &off); 1207 uint8_t const idxRegImm = iemNativeRegAllocTmpImm(pReNative, &off, uImmOp); 1208 PIEMNATIVEINSTR const pCodeBuf = iemNativeInstrBufEnsure(pReNative, off, 5); 1209 1210 pCodeBuf[off++] = Armv8A64MkInstrRmif(idxRegEfl, (X86_EFL_CF_BIT - 1) & 63, RT_BIT_32(1) /*fMask=C*/); 1211 pCodeBuf[off++] = ARMV8_A64_INSTR_CFINV; 1212 off = iemNativeEmitLoadGprFromGprEx(pCodeBuf, off, idxRegDstIn, idxRegDst); 1213 if (cOpBits >= 32) 1214 pCodeBuf[off++] = Armv8A64MkInstrSbcs(idxRegDst, idxRegDst, idxRegImm, cOpBits > 32 /*f64Bit*/); 1215 else 1216 { 1217 /* Since we're also adding in the carry flag here, shifting operands up 1218 doesn't work. So, we have to calculate carry & overflow manually. */ 1219 pCodeBuf[off++] = Armv8A64MkInstrSbc(idxRegDst, idxRegDst, idxRegImm, false /*f64Bit*/); 1220 pCodeBuf[off++] = Armv8A64MkInstrSetF8SetF16(idxRegDst, cOpBits > 8); /* NZ are okay, CV aren't.*/ 1221 } 1222 IEMNATIVE_ASSERT_INSTR_BUF_ENSURE(pReNative, off); 1223 1224 iemNativeRegFreeTmp(pReNative, idxRegImm); 1225 1226 off = iemNativeEmitEFlagsForArithmetic(pReNative, off, UINT8_MAX, idxRegEfl, cOpBits, idxRegDst, 1227 idxRegDstIn, UINT8_MAX, true /*fInvertCarry*/, uImmOp); 1228 1229 iemNativeRegFreeTmp(pReNative, idxRegDstIn); 1230 if (cOpBits < 32) 1231 off = iemNativeEmitAndGpr32ByImm(pReNative, off, idxRegDst, RT_BIT_32(cOpBits) - 1U); 1232 iemNativeVarRegisterRelease(pReNative, idxVarDst); 1233 RT_NOREF(cImmBits); 1234 1235 #else 1236 # error "port me" 1237 #endif 1238 iemNativeVarRegisterRelease(pReNative, idxVarEfl); 1171 1239 return off; 1172 1240 }
Note:
See TracChangeset
for help on using the changeset viewer.