mirror of
https://github.com/FEX-Emu/FEX.git
synced 2026-10-14 15:00:53 +02:00
IR: merge div/rem opcodes
it's simpler & faster to calculate both together, matching the x86 semantic. Signed-off-by: Alyssa Rosenzweig <alyssa@rosenzweig.io>
This commit is contained in:
1 parent
1f15a4e35b
commit
1eb470083c
3 files changed
+112
-326
No files matched your search
@@ -2852,9 +2852,10 @@ void OpDispatchBuilder::AASOp(OpcodeArgs) {
|
||||
void OpDispatchBuilder::AAMOp(OpcodeArgs) {
|
||||
auto AL = LoadGPRRegister(X86State::REG_RAX, OpSize::i8Bit);
|
||||
auto Imm8 = _Constant(Op->Src[0].Data.Literal.Value & 0xFF);
|
||||
auto UDivOp = _UDiv(OpSize::i64Bit, AL, Imm8);
|
||||
auto URemOp = _URem(OpSize::i64Bit, AL, Imm8);
|
||||
auto Res = _AddShift(OpSize::i64Bit, URemOp, UDivOp, ShiftType::LSL, 8);
|
||||
Ref Quotient = _AllocateGPR(true);
|
||||
Ref Remainder = _AllocateGPR(true);
|
||||
_UDiv(OpSize::i64Bit, AL, Imm8, Quotient, Remainder);
|
||||
auto Res = _AddShift(OpSize::i64Bit, Remainder, Quotient, ShiftType::LSL, 8);
|
||||
StoreGPRRegister(X86State::REG_RAX, Res, OpSize::i16Bit);
|
||||
|
||||
SetNZ_ZeroCV(OpSize::i8Bit, Res);
|
||||
@@ -3585,48 +3586,39 @@ void OpDispatchBuilder::DIVOp(OpcodeArgs) {
|
||||
Ref Divisor = LoadSource(GPRClass, Op, Op->Dest, Op->Flags);
|
||||
|
||||
const auto GPRSize = CTX->GetGPROpSize();
|
||||
const auto Size = OpSizeFromSrc(Op);
|
||||
auto Size = OpSizeFromSrc(Op);
|
||||
|
||||
if (Size == OpSize::i64Bit && !CTX->Config.Is64BitMode) {
|
||||
LogMan::Msg::EFmt("Doesn't exist in 32bit mode");
|
||||
DecodeFailure = true;
|
||||
return;
|
||||
}
|
||||
|
||||
Ref Quotient = _AllocateGPR(true);
|
||||
Ref Remainder = _AllocateGPR(true);
|
||||
|
||||
if (Size == OpSize::i8Bit) {
|
||||
Ref Src1 = LoadGPRRegister(X86State::REG_RAX, OpSize::i16Bit);
|
||||
|
||||
auto UDivOp = _UDiv(OpSize::i16Bit, Src1, Divisor);
|
||||
auto URemOp = _URem(OpSize::i16Bit, Src1, Divisor);
|
||||
_UDiv(OpSize::i16Bit, Src1, Divisor, Quotient, Remainder);
|
||||
|
||||
// AX[15:0] = concat<URem[7:0]:UDiv[7:0]>
|
||||
auto ResultAX = _Bfi(GPRSize, 8, 8, UDivOp, URemOp);
|
||||
auto ResultAX = _Bfi(GPRSize, 8, 8, Quotient, Remainder);
|
||||
StoreGPRRegister(X86State::REG_RAX, ResultAX, OpSize::i16Bit);
|
||||
} else if (Size == OpSize::i16Bit) {
|
||||
Ref Src1 = LoadGPRRegister(X86State::REG_RAX);
|
||||
Ref Src2 = LoadGPRRegister(X86State::REG_RDX);
|
||||
auto UDivOp = _LUDiv(OpSize::i16Bit, Src1, Src2, Divisor);
|
||||
auto URemOp = _LURem(OpSize::i16Bit, Src1, Src2, Divisor);
|
||||
|
||||
StoreGPRRegister(X86State::REG_RAX, UDivOp, Size);
|
||||
StoreGPRRegister(X86State::REG_RDX, URemOp, Size);
|
||||
} else if (Size == OpSize::i32Bit) {
|
||||
} else {
|
||||
Ref Src1 = LoadGPRRegister(X86State::REG_RAX);
|
||||
Ref Src2 = LoadGPRRegister(X86State::REG_RDX);
|
||||
|
||||
Ref UDivOp = _Bfe(OpSize::i32Bit, IR::OpSizeAsBits(Size), 0, _LUDiv(OpSize::i32Bit, Src1, Src2, Divisor));
|
||||
Ref URemOp = _Bfe(OpSize::i32Bit, IR::OpSizeAsBits(Size), 0, _LURem(OpSize::i32Bit, Src1, Src2, Divisor));
|
||||
_LUDiv(Size, Src1, Src2, Divisor, Quotient, Remainder);
|
||||
|
||||
StoreGPRRegister(X86State::REG_RAX, UDivOp);
|
||||
StoreGPRRegister(X86State::REG_RDX, URemOp);
|
||||
} else if (Size == OpSize::i64Bit) {
|
||||
if (!CTX->Config.Is64BitMode) {
|
||||
LogMan::Msg::EFmt("Doesn't exist in 32bit mode");
|
||||
DecodeFailure = true;
|
||||
return;
|
||||
if (Size == OpSize::i32Bit) {
|
||||
Quotient = _Bfe(OpSize::i32Bit, IR::OpSizeAsBits(Size), 0, Quotient);
|
||||
Remainder = _Bfe(OpSize::i32Bit, IR::OpSizeAsBits(Size), 0, Remainder);
|
||||
Size = OpSize::iInvalid;
|
||||
}
|
||||
Ref Src1 = LoadGPRRegister(X86State::REG_RAX);
|
||||
Ref Src2 = LoadGPRRegister(X86State::REG_RDX);
|
||||
|
||||
auto UDivOp = _LUDiv(OpSize::i64Bit, Src1, Src2, Divisor);
|
||||
auto URemOp = _LURem(OpSize::i64Bit, Src1, Src2, Divisor);
|
||||
|
||||
StoreGPRRegister(X86State::REG_RAX, UDivOp);
|
||||
StoreGPRRegister(X86State::REG_RDX, URemOp);
|
||||
StoreGPRRegister(X86State::REG_RAX, Quotient, Size);
|
||||
StoreGPRRegister(X86State::REG_RDX, Remainder, Size);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3635,50 +3627,41 @@ void OpDispatchBuilder::IDIVOp(OpcodeArgs) {
|
||||
Ref Divisor = LoadSource(GPRClass, Op, Op->Dest, Op->Flags);
|
||||
|
||||
const auto GPRSize = CTX->GetGPROpSize();
|
||||
const auto Size = OpSizeFromSrc(Op);
|
||||
auto Size = OpSizeFromSrc(Op);
|
||||
|
||||
if (Size == OpSize::i64Bit && !CTX->Config.Is64BitMode) {
|
||||
LogMan::Msg::EFmt("Doesn't exist in 32bit mode");
|
||||
DecodeFailure = true;
|
||||
return;
|
||||
}
|
||||
|
||||
Ref Quotient = _AllocateGPR(true);
|
||||
Ref Remainder = _AllocateGPR(true);
|
||||
|
||||
if (Size == OpSize::i8Bit) {
|
||||
Ref Src1 = LoadGPRRegister(X86State::REG_RAX);
|
||||
Src1 = _Sbfe(OpSize::i64Bit, 16, 0, Src1);
|
||||
Divisor = _Sbfe(OpSize::i64Bit, 8, 0, Divisor);
|
||||
|
||||
auto UDivOp = _Div(OpSize::i64Bit, Src1, Divisor);
|
||||
auto URemOp = _Rem(OpSize::i64Bit, Src1, Divisor);
|
||||
_Div(OpSize::i64Bit, Src1, Divisor, Quotient, Remainder);
|
||||
|
||||
// AX[15:0] = concat<URem[7:0]:UDiv[7:0]>
|
||||
auto ResultAX = _Bfi(GPRSize, 8, 8, UDivOp, URemOp);
|
||||
auto ResultAX = _Bfi(GPRSize, 8, 8, Quotient, Remainder);
|
||||
StoreGPRRegister(X86State::REG_RAX, ResultAX, OpSize::i16Bit);
|
||||
} else if (Size == OpSize::i16Bit) {
|
||||
Ref Src1 = LoadGPRRegister(X86State::REG_RAX);
|
||||
Ref Src2 = LoadGPRRegister(X86State::REG_RDX);
|
||||
auto UDivOp = _LDiv(OpSize::i16Bit, Src1, Src2, Divisor);
|
||||
auto URemOp = _LRem(OpSize::i16Bit, Src1, Src2, Divisor);
|
||||
|
||||
StoreGPRRegister(X86State::REG_RAX, UDivOp, Size);
|
||||
StoreGPRRegister(X86State::REG_RDX, URemOp, Size);
|
||||
} else if (Size == OpSize::i32Bit) {
|
||||
} else {
|
||||
Ref Src1 = LoadGPRRegister(X86State::REG_RAX);
|
||||
Ref Src2 = LoadGPRRegister(X86State::REG_RDX);
|
||||
|
||||
Ref UDivOp = _Bfe(OpSize::i32Bit, IR::OpSizeAsBits(Size), 0, _LDiv(OpSize::i32Bit, Src1, Src2, Divisor));
|
||||
Ref URemOp = _Bfe(OpSize::i32Bit, IR::OpSizeAsBits(Size), 0, _LRem(OpSize::i32Bit, Src1, Src2, Divisor));
|
||||
_LDiv(Size, Src1, Src2, Divisor, Quotient, Remainder);
|
||||
|
||||
StoreGPRRegister(X86State::REG_RAX, UDivOp);
|
||||
StoreGPRRegister(X86State::REG_RDX, URemOp);
|
||||
} else if (Size == OpSize::i64Bit) {
|
||||
if (!CTX->Config.Is64BitMode) {
|
||||
LogMan::Msg::EFmt("Doesn't exist in 32bit mode");
|
||||
DecodeFailure = true;
|
||||
return;
|
||||
if (Size == OpSize::i32Bit) {
|
||||
Quotient = _Bfe(OpSize::i32Bit, IR::OpSizeAsBits(Size), 0, Quotient);
|
||||
Remainder = _Bfe(OpSize::i32Bit, IR::OpSizeAsBits(Size), 0, Remainder);
|
||||
Size = OpSize::iInvalid;
|
||||
}
|
||||
Ref Src1 = LoadGPRRegister(X86State::REG_RAX);
|
||||
Ref Src2 = LoadGPRRegister(X86State::REG_RDX);
|
||||
|
||||
auto UDivOp = _LDiv(OpSize::i64Bit, Src1, Src2, Divisor);
|
||||
auto URemOp = _LRem(OpSize::i64Bit, Src1, Src2, Divisor);
|
||||
|
||||
StoreGPRRegister(X86State::REG_RAX, UDivOp);
|
||||
StoreGPRRegister(X86State::REG_RDX, URemOp);
|
||||
StoreGPRRegister(X86State::REG_RAX, Quotient, Size);
|
||||
StoreGPRRegister(X86State::REG_RDX, Remainder, Size);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user