mirror of
https://github.com/FEX-Emu/FEX.git
synced 2025-01-20 21:37:20 +00:00
Fixes x86 instruction decoding.
In the case of modrm + immediate then the immediate would end up overwriting Src1 due to the the order of the decoding. Changes Src1 and Src2 to an array and use a variable to index the array. Causes a bit of code churn but fixes instruction decoding and allows easier expansion in the future for instructions that have more sources like AVX
This commit is contained in:
parent
9135661861
commit
ed12a8a242
@ -298,7 +298,7 @@ bool Decoder::NormalOp(FEXCore::X86Tables::X86InstInfo const *Info, uint16_t Op)
|
||||
CurrentDest->TypeGPR.Type = DecodedOperand::TYPE_GPR;
|
||||
CurrentDest->TypeGPR.HighBits = false;
|
||||
CurrentDest->TypeGPR.GPR = HAS_NON_XMM_SUBFLAG(Info->Flags, FEXCore::X86Tables::InstFlags::FLAGS_SF_DST_RAX) ? FEXCore::X86State::REG_RAX : FEXCore::X86State::REG_RDX;
|
||||
CurrentDest = &DecodeInst->Src1;
|
||||
CurrentDest = &DecodeInst->Src[0];
|
||||
}
|
||||
|
||||
if (HAS_NON_XMM_SUBFLAG(Info->Flags, FEXCore::X86Tables::InstFlags::FLAGS_SF_REX_IN_BYTE)) {
|
||||
@ -408,36 +408,35 @@ bool Decoder::NormalOp(FEXCore::X86Tables::X86InstInfo const *Info, uint16_t Op)
|
||||
}
|
||||
};
|
||||
|
||||
if (Info->Flags & FEXCore::X86Tables::InstFlags::FLAGS_MODRM &&
|
||||
Info->Flags & FEXCore::X86Tables::InstFlags::FLAGS_SF_MOD_DST) {
|
||||
ModRMOperand(DecodeInst->Src1, DecodeInst->Dest, HasXMMSrc, HasXMMDst, Is8BitSrc, Is8BitDest);
|
||||
size_t CurrentSrc = 0;
|
||||
|
||||
if (Info->Flags & FEXCore::X86Tables::InstFlags::FLAGS_MODRM) {
|
||||
if (Info->Flags & FEXCore::X86Tables::InstFlags::FLAGS_SF_MOD_DST) {
|
||||
ModRMOperand(DecodeInst->Src[CurrentSrc], DecodeInst->Dest, HasXMMSrc, HasXMMDst, Is8BitSrc, Is8BitDest);
|
||||
}
|
||||
else {
|
||||
ModRMOperand(DecodeInst->Dest, DecodeInst->Src[CurrentSrc], HasXMMDst, HasXMMSrc, Is8BitDest, Is8BitSrc);
|
||||
}
|
||||
++CurrentSrc;
|
||||
}
|
||||
|
||||
// This is almost the same as when the ModRM is the destination type
|
||||
// The main different being that Dst and Src flip which bits that use (reg<->rm)
|
||||
auto *CurrentSrc = &DecodeInst->Src1;
|
||||
if (Info->Flags & FEXCore::X86Tables::InstFlags::FLAGS_MODRM &&
|
||||
!(Info->Flags & FEXCore::X86Tables::InstFlags::FLAGS_SF_MOD_DST)) {
|
||||
ModRMOperand(DecodeInst->Dest, DecodeInst->Src1, HasXMMDst, HasXMMSrc, Is8BitDest, Is8BitSrc);
|
||||
CurrentSrc = &DecodeInst->Src2;
|
||||
}
|
||||
else if (HAS_NON_XMM_SUBFLAG(Info->Flags, FEXCore::X86Tables::InstFlags::FLAGS_SF_SRC_RAX)) {
|
||||
CurrentSrc->TypeGPR.Type = DecodedOperand::TYPE_GPR;
|
||||
CurrentSrc->TypeGPR.HighBits = false;
|
||||
CurrentSrc->TypeGPR.GPR = FEXCore::X86State::REG_RAX;
|
||||
CurrentSrc = &DecodeInst->Src2;
|
||||
if (HAS_NON_XMM_SUBFLAG(Info->Flags, FEXCore::X86Tables::InstFlags::FLAGS_SF_SRC_RAX)) {
|
||||
DecodeInst->Src[CurrentSrc].TypeGPR.Type = DecodedOperand::TYPE_GPR;
|
||||
DecodeInst->Src[CurrentSrc].TypeGPR.HighBits = false;
|
||||
DecodeInst->Src[CurrentSrc].TypeGPR.GPR = FEXCore::X86State::REG_RAX;
|
||||
++CurrentSrc;
|
||||
}
|
||||
else if (HAS_NON_XMM_SUBFLAG(Info->Flags, FEXCore::X86Tables::InstFlags::FLAGS_SF_SRC_RCX)) {
|
||||
CurrentSrc->TypeGPR.Type = DecodedOperand::TYPE_GPR;
|
||||
CurrentSrc->TypeGPR.HighBits = false;
|
||||
CurrentSrc->TypeGPR.GPR = FEXCore::X86State::REG_RCX;
|
||||
CurrentSrc = &DecodeInst->Src2;
|
||||
DecodeInst->Src[CurrentSrc].TypeGPR.Type = DecodedOperand::TYPE_GPR;
|
||||
DecodeInst->Src[CurrentSrc].TypeGPR.HighBits = false;
|
||||
DecodeInst->Src[CurrentSrc].TypeGPR.GPR = FEXCore::X86State::REG_RCX;
|
||||
++CurrentSrc;
|
||||
}
|
||||
|
||||
if (Bytes != 0) {
|
||||
LogMan::Throw::A(Bytes <= 8, "Number of bytes should be <= 8 for literal src");
|
||||
|
||||
CurrentSrc->TypeLiteral.Size = Bytes;
|
||||
DecodeInst->Src[CurrentSrc].TypeLiteral.Size = Bytes;
|
||||
|
||||
uint64_t Literal {0};
|
||||
Literal = ReadData(Bytes);
|
||||
@ -455,8 +454,8 @@ bool Decoder::NormalOp(FEXCore::X86Tables::X86InstInfo const *Info, uint16_t Op)
|
||||
}
|
||||
|
||||
Bytes = 0;
|
||||
CurrentSrc->TypeLiteral.Type = DecodedOperand::TYPE_LITERAL;
|
||||
CurrentSrc->TypeLiteral.Literal = Literal;
|
||||
DecodeInst->Src[CurrentSrc].TypeLiteral.Type = DecodedOperand::TYPE_LITERAL;
|
||||
DecodeInst->Src[CurrentSrc].TypeLiteral.Literal = Literal;
|
||||
}
|
||||
|
||||
LogMan::Throw::A(Bytes == 0, "Inst at 0x%lx: 0x%04x '%s' Had an instruction of size %d with %d remaining", DecodeInst->PC, DecodeInst->OP, DecodeInst->TableInfo->Name, InstructionSize, Bytes);
|
||||
@ -835,17 +834,17 @@ void Decoder::BranchTargetInMultiblockRange() {
|
||||
case 0x70 ... 0x7F: // Conditional JUMP
|
||||
case 0x80 ... 0x8F: { // More conditional
|
||||
// Source is a literal
|
||||
// auto RIPOffset = LoadSource(Op, Op->Src1, Op->Flags);
|
||||
// auto RIPOffset = LoadSource(Op, Op->Src[0], Op->Flags);
|
||||
// auto RIPTargetConst = _Constant(Op->PC + Op->InstSize);
|
||||
// Target offset is PC + InstSize + Literal
|
||||
LogMan::Throw::A(DecodeInst->Src1.TypeNone.Type == DecodedOperand::TYPE_LITERAL, "Had wrong operand type");
|
||||
TargetRIP = DecodeInst->PC + DecodeInst->InstSize + DecodeInst->Src1.TypeLiteral.Literal;
|
||||
LogMan::Throw::A(DecodeInst->Src[0].TypeNone.Type == DecodedOperand::TYPE_LITERAL, "Had wrong operand type");
|
||||
TargetRIP = DecodeInst->PC + DecodeInst->InstSize + DecodeInst->Src[0].TypeLiteral.Literal;
|
||||
break;
|
||||
}
|
||||
case 0xE9:
|
||||
case 0xEB: // Both are unconditional JMP instructions
|
||||
LogMan::Throw::A(DecodeInst->Src1.TypeNone.Type == DecodedOperand::TYPE_LITERAL, "Had wrong operand type");
|
||||
TargetRIP = DecodeInst->PC + DecodeInst->InstSize + DecodeInst->Src1.TypeLiteral.Literal;
|
||||
LogMan::Throw::A(DecodeInst->Src[0].TypeNone.Type == DecodedOperand::TYPE_LITERAL, "Had wrong operand type");
|
||||
TargetRIP = DecodeInst->PC + DecodeInst->InstSize + DecodeInst->Src[0].TypeLiteral.Literal;
|
||||
Conditional = false;
|
||||
break;
|
||||
case 0xC2: // RET imm
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -95,16 +95,21 @@ public:
|
||||
// Dispatch builder functions
|
||||
#define OpcodeArgs [[maybe_unused]] FEXCore::X86Tables::DecodedOp Op
|
||||
void UnhandledOp(OpcodeArgs);
|
||||
template<uint32_t SrcIndex>
|
||||
void MOVGPROp(OpcodeArgs);
|
||||
void MOVVectorOp(OpcodeArgs);
|
||||
template<uint32_t SrcIndex>
|
||||
void ALUOp(OpcodeArgs);
|
||||
void INTOp(OpcodeArgs);
|
||||
void SyscallOp(OpcodeArgs);
|
||||
void LEAOp(OpcodeArgs);
|
||||
void NOPOp(OpcodeArgs);
|
||||
void RETOp(OpcodeArgs);
|
||||
template<uint32_t SrcIndex>
|
||||
void SecondaryALUOp(OpcodeArgs);
|
||||
template<uint32_t SrcIndex>
|
||||
void ADCOp(OpcodeArgs);
|
||||
template<uint32_t SrcIndex>
|
||||
void SBBOp(OpcodeArgs);
|
||||
void PUSHOp(OpcodeArgs);
|
||||
void POPOp(OpcodeArgs);
|
||||
@ -114,10 +119,12 @@ public:
|
||||
void CondJUMPOp(OpcodeArgs);
|
||||
void JUMPOp(OpcodeArgs);
|
||||
void JUMPAbsoluteOp(OpcodeArgs);
|
||||
template<uint32_t SrcIndex>
|
||||
void TESTOp(OpcodeArgs);
|
||||
void MOVSXDOp(OpcodeArgs);
|
||||
void MOVSXOp(OpcodeArgs);
|
||||
void MOVZXOp(OpcodeArgs);
|
||||
template<uint32_t SrcIndex>
|
||||
void CMPOp(OpcodeArgs);
|
||||
void SETccOp(OpcodeArgs);
|
||||
void CQOOp(OpcodeArgs);
|
||||
@ -137,11 +144,17 @@ public:
|
||||
void SHLDOp(OpcodeArgs);
|
||||
void SHRDOp(OpcodeArgs);
|
||||
void ASHROp(OpcodeArgs);
|
||||
template<uint32_t SrcIndex>
|
||||
void ROROp(OpcodeArgs);
|
||||
template<uint32_t SrcIndex>
|
||||
void ROLOp(OpcodeArgs);
|
||||
template<uint32_t SrcIndex>
|
||||
void BTOp(OpcodeArgs);
|
||||
template<uint32_t SrcIndex>
|
||||
void BTROp(OpcodeArgs);
|
||||
template<uint32_t SrcIndex>
|
||||
void BTSOp(OpcodeArgs);
|
||||
template<uint32_t SrcIndex>
|
||||
void BTCOp(OpcodeArgs);
|
||||
void IMUL1SrcOp(OpcodeArgs);
|
||||
void IMUL2SrcOp(OpcodeArgs);
|
||||
@ -186,7 +199,9 @@ public:
|
||||
void PMAXUOp(OpcodeArgs);
|
||||
void PMINSWOp(OpcodeArgs);
|
||||
void PMOVMSKBOp(OpcodeArgs);
|
||||
template<size_t ElementSize>
|
||||
void PUNPCKLOp(OpcodeArgs);
|
||||
template<size_t ElementSize>
|
||||
void PUNPCKHOp(OpcodeArgs);
|
||||
template<size_t ElementSize, bool Low>
|
||||
void PSHUFDOp(OpcodeArgs);
|
||||
@ -194,9 +209,9 @@ public:
|
||||
template<size_t ElementSize>
|
||||
void PCMPGTOp(OpcodeArgs);
|
||||
void MOVDOp(OpcodeArgs);
|
||||
template<size_t ElementSize>
|
||||
template<size_t ElementSize, uint32_t SrcIndex>
|
||||
void PSRLD(OpcodeArgs);
|
||||
template<size_t ElementSize, bool Scalar>
|
||||
template<size_t ElementSize, bool Scalar, uint32_t SrcIndex>
|
||||
void PSLL(OpcodeArgs);
|
||||
void PSRLDQ(OpcodeArgs);
|
||||
void PSLLDQ(OpcodeArgs);
|
||||
|
@ -110,8 +110,7 @@ struct DecodedInst {
|
||||
bool DecodedSIB;
|
||||
|
||||
DecodedOperand Dest;
|
||||
DecodedOperand Src1;
|
||||
DecodedOperand Src2;
|
||||
DecodedOperand Src[2];
|
||||
|
||||
// Constains the dispatcher handler pointer
|
||||
X86InstInfo const* TableInfo;
|
||||
|
Loading…
x
Reference in New Issue
Block a user