OpcodeDispatcher: Improve output of MULX

We can cut down on a few of the generated moves. For
the case where both destinations alias one another,
we can just calculate the high part instead of both of them.
This commit is contained in:
Lioncache committed 2023-09-15 20:52:02 -04:00
1 parent 647629ac23
commit d4f87c7db1
2 files changed
+74 -9

No files matched your search

@@ -2711,15 +2711,29 @@ void OpDispatchBuilder::RORX(OpcodeArgs) {
void OpDispatchBuilder::MULX(OpcodeArgs) {
// RDX is the implied source operand in the instruction
const auto OperandSize = GetSrcSize(Op);
const auto OpSize = IR::SizeToOpSize(OperandSize);
OrderedNode* Src1 = LoadSource(GPRClass, Op, Op->Src[1], Op->Flags, -1);
OrderedNode* Src2 = LoadGPRRegister(X86State::REG_RDX, OperandSize);
// Src1 can be a memory operand, so ensure we constrain to the
// absolute width of the access in that scenario.
const auto GPRSize = CTX->GetGPRSize();
const auto Src1Size = Op->Src[1].IsGPR() ? GPRSize : OperandSize;
OrderedNode* ResultLo = _UMul(IR::SizeToOpSize(OperandSize), Src1, Src2);
OrderedNode* ResultHi = _UMulH(IR::SizeToOpSize(OperandSize), Src1, Src2);
OrderedNode* Src1 = LoadSource_WithOpSize(GPRClass, Op, Op->Src[1], Src1Size, Op->Flags, -1);
OrderedNode* Src2 = LoadGPRRegister(X86State::REG_RDX, GPRSize);
StoreResult(GPRClass, Op, Op->Src[0], ResultLo, -1);
StoreResult(GPRClass, Op, Op->Dest, ResultHi, -1);
// As per the Intel Software Development Manual, if the destination and
// first operand correspond to the same register, then the result
// will be the high half of the multiplication result.
if (Op->Dest.Data.GPR.GPR == Op->Src[0].Data.GPR.GPR) {
OrderedNode* ResultHi = _UMulH(OpSize, Src1, Src2);
StoreResult(GPRClass, Op, Op->Dest, ResultHi, -1);
} else {
OrderedNode* ResultLo = _UMul(OpSize, Src1, Src2);
OrderedNode* ResultHi = _UMulH(OpSize, Src1, Src2);
StoreResult(GPRClass, Op, Op->Src[0], ResultLo, -1);
StoreResult(GPRClass, Op, Op->Dest, ResultHi, -1);
}
}
void OpDispatchBuilder::PDEP(OpcodeArgs) {