OpcodeDispatcher: Optimize OF calc of immediates

If we know the sign of one of the sources, we can do better when calculating OF.

Signed-off-by: Alyssa Rosenzweig <alyssa@rosenzweig.io>
This commit is contained in:
Alyssa Rosenzweig committed 2023-09-24 18:16:09 -04:00
1 parent e795ec683d
commit ea8b7633eb
1 file changed
+23 -5
@@ -202,11 +202,29 @@ OrderedNode *OpDispatchBuilder::GetPackedRFLAG(uint32_t FlagsMask) {
void OpDispatchBuilder::CalculateOF_Add(uint8_t SrcSize, OrderedNode *Res, OrderedNode *Src1, OrderedNode *Src2) {
auto OpSize = SrcSize == 8 ? OpSize::i64Bit : OpSize::i32Bit;
auto XorOp1 = _Xor(OpSize, Src1, Src2);
auto XorOp2 = _Xor(OpSize, Res, Src1);
OrderedNode *AndOp1 = _Andn(OpSize, XorOp2, XorOp1);
AndOp1 = _Bfe(OpSize, 1, SrcSize * 8 - 1, AndOp1);
SetRFLAG<FEXCore::X86State::RFLAG_OF_LOC>(AndOp1);
uint64_t SignBit = (SrcSize * 8) - 1;
OrderedNode *Anded = nullptr;
// OF is set iff the sources have the same sign but the destination sign
// differs. If we know a source sign, we can simplify the expression: if
// source 2 is known to be positive, we set OF if source 1 is positive and
// source 2 is negative. Similarly if source 2 is known negative.
uint64_t Const;
if (IsValueConstant(WrapNode(Src2), &Const)) {
bool Negative = (Const & (1ull << SignBit)) != 0;
if (Negative)
Anded = _Andn(OpSize, Src1, Res);
else
Anded = _Andn(OpSize, Res, Src1);
} else {
auto XorOp1 = _Xor(OpSize, Src1, Src2);
auto XorOp2 = _Xor(OpSize, Res, Src1);
Anded = _Andn(OpSize, XorOp2, XorOp1);
}
auto OF = _Bfe(OpSize, 1, SrcSize * 8 - 1, Anded);
SetRFLAG<FEXCore::X86State::RFLAG_OF_LOC>(OF);
}
OrderedNode *OpDispatchBuilder::LoadPFRaw() {