OpcodeDispatcher: optimize BLSI

and explain why the suss thing we did before was actually right all along.

Signed-off-by: Alyssa Rosenzweig <alyssa@rosenzweig.io>
This commit is contained in:
Alyssa Rosenzweig 2024-01-23 14:30:41 -04:00
parent 93cef53ec0
commit e8e05252f0

View File

@ -1005,30 +1005,20 @@ void OpDispatchBuilder::CalculateFlags_BEXTR(OrderedNode *Src) {
SetRFLAG<X86State::RFLAG_ZF_RAW_LOC>(ZeroOp);
}
void OpDispatchBuilder::CalculateFlags_BLSI(uint8_t SrcSize, OrderedNode *Src) {
// Now for the flags:
void OpDispatchBuilder::CalculateFlags_BLSI(uint8_t SrcSize, OrderedNode *Result) {
// CF is cleared if Src is zero, otherwise it's set. However, Src is zero iff
// Result is zero, so we can test the result instead. So, CF is just the
// inverted ZF.
//
// Only CF, SF, ZF and OF are defined as being updated
// CF is cleared if Src is zero, otherwise it's set.
// SF is set to the value of the most significant operand bit of Result.
// OF is always cleared
// ZF is set, as usual, if Result is zero or not.
// ZF/SF/OF set as usual.
SetNZ_ZeroCV(SrcSize, Result);
auto Zero = _Constant(0);
auto One = _Constant(1);
SetNZ_ZeroCV(SrcSize, Src);
auto CFOp = GetRFLAG(X86State::RFLAG_ZF_RAW_LOC, true /* Invert */);
SetRFLAG<X86State::RFLAG_CF_RAW_LOC>(CFOp);
// PF/AF undefined
_InvalidateFlags((1UL << X86State::RFLAG_PF_RAW_LOC) |
(1UL << X86State::RFLAG_AF_RAW_LOC));
// CF
{
auto CFOp = _Select(IR::COND_NEQ, Src, Zero, One, Zero);
SetRFLAG<X86State::RFLAG_CF_RAW_LOC>(CFOp);
}
}
void OpDispatchBuilder::CalculateFlags_BLSMSK(uint8_t SrcSize, OrderedNode *Result, OrderedNode *Src) {