mirror of
https://github.com/FEX-Emu/FEX.git
synced 2026-10-06 19:00:17 +02:00
Merge pull request #1153 from Sonicadvance1/split_opdispatcher
OpcodeDispatcher: Split the opcode handling to multiple files
This commit is contained in:
21 files changed
+4589
-3941
No files matched your search
+4
@@ -81,6 +81,10 @@ set (SRCS
|
||||
Interface/Core/Frontend.cpp
|
||||
Interface/Core/GdbServer.cpp
|
||||
Interface/Core/HostFeatures.cpp
|
||||
Interface/Core/OpcodeDispatcher/Crypto.cpp
|
||||
Interface/Core/OpcodeDispatcher/Flags.cpp
|
||||
Interface/Core/OpcodeDispatcher/Vector.cpp
|
||||
Interface/Core/OpcodeDispatcher/X87.cpp
|
||||
Interface/Core/OpcodeDispatcher.cpp
|
||||
Interface/Core/X86Tables.cpp
|
||||
Interface/Core/X86DebugInfo.cpp
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#include "Interface/Context/Context.h"
|
||||
#include "Interface/Core/Core.h"
|
||||
#include "Interface/Core/OpcodeDispatcher.h"
|
||||
#include "Interface/Core/X86Tables/X86Tables.h"
|
||||
|
||||
#include <FEXCore/Config/Config.h>
|
||||
#include <FEXCore/Core/CoreState.h>
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#include "Interface/Core/LookupCache.h"
|
||||
|
||||
#include "Interface/Core/ArchHelpers/MContext.h"
|
||||
#include "Interface/Core/Dispatcher/Arm64Dispatcher.h"
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#include "Interface/Core/LookupCache.h"
|
||||
|
||||
#include "Interface/Core/Dispatcher/X86Dispatcher.h"
|
||||
|
||||
#include "Interface/Core/Interpreter/InterpreterClass.h"
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include "Interface/Core/LookupCache.h"
|
||||
#include "Interface/Core/InternalThreadState.h"
|
||||
#include "Interface/Core/Dispatcher/Dispatcher.h"
|
||||
|
||||
|
||||
@@ -4,6 +4,8 @@ tags: backend|arm64
|
||||
$end_info$
|
||||
*/
|
||||
|
||||
#include "Interface/Core/LookupCache.h"
|
||||
|
||||
#include "Interface/Core/JIT/Arm64/JITClass.h"
|
||||
#include "Interface/Core/InternalThreadState.h"
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ $end_info$
|
||||
*/
|
||||
|
||||
#include "Interface/Context/Context.h"
|
||||
#include "Interface/Core/LookupCache.h"
|
||||
|
||||
#include "Interface/Core/ArchHelpers/Arm64.h"
|
||||
#include "Interface/Core/ArchHelpers/MContext.h"
|
||||
|
||||
@@ -6,7 +6,6 @@ $end_info$
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Interface/Core/LookupCache.h"
|
||||
#include "Interface/Core/ArchHelpers/Arm64Emitter.h"
|
||||
#include "Interface/Core/Dispatcher/Dispatcher.h"
|
||||
|
||||
|
||||
@@ -4,6 +4,8 @@ tags: backend|x86-64
|
||||
$end_info$
|
||||
*/
|
||||
|
||||
#include "Interface/Core/LookupCache.h"
|
||||
|
||||
#include "Interface/Core/JIT/x86_64/JITClass.h"
|
||||
#include "Interface/IR/Passes/RegisterAllocationPass.h"
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ $end_info$
|
||||
*/
|
||||
|
||||
#include "Interface/Context/Context.h"
|
||||
#include "Interface/Core/LookupCache.h"
|
||||
|
||||
#include "Interface/Core/Dispatcher/X86Dispatcher.h"
|
||||
#include "Interface/Core/JIT/x86_64/JITClass.h"
|
||||
|
||||
@@ -6,7 +6,6 @@ $end_info$
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Interface/Core/LookupCache.h"
|
||||
#include "Interface/Core/BlockSamplingData.h"
|
||||
#include "Interface/Core/Dispatcher/Dispatcher.h"
|
||||
|
||||
|
||||
+23
-3926
File diff suppressed because it is too large.
Load diff
+18
-8
@@ -270,15 +270,15 @@ public:
|
||||
template<size_t ElementSize, bool HalfSize, bool Low>
|
||||
void PSHUFDOp(OpcodeArgs);
|
||||
void MOVDOp(OpcodeArgs);
|
||||
template<size_t ElementSize, bool Scalar, uint32_t SrcIndex>
|
||||
template<size_t ElementSize>
|
||||
void PSRLDOp(OpcodeArgs);
|
||||
template<size_t ElementSize>
|
||||
void PSRLI(OpcodeArgs);
|
||||
template<size_t ElementSize>
|
||||
void PSLLI(OpcodeArgs);
|
||||
template<size_t ElementSize, bool Scalar, uint32_t SrcIndex>
|
||||
template<size_t ElementSize>
|
||||
void PSLL(OpcodeArgs);
|
||||
template<size_t ElementSize, bool Scalar, uint32_t SrcIndex>
|
||||
template<size_t ElementSize>
|
||||
void PSRAOp(OpcodeArgs);
|
||||
void PSRLDQ(OpcodeArgs);
|
||||
void PSLLDQ(OpcodeArgs);
|
||||
@@ -299,9 +299,9 @@ public:
|
||||
void Vector_CVT_Float_To_Float(OpcodeArgs);
|
||||
template<size_t SrcElementSize, bool Narrow, bool HostRoundingMode>
|
||||
void Vector_CVT_Float_To_Int(OpcodeArgs);
|
||||
template<size_t SrcElementSize, bool Signed, bool Widen>
|
||||
template<size_t SrcElementSize, bool Widen>
|
||||
void MMX_To_XMM_Vector_CVT_Int_To_Float(OpcodeArgs);
|
||||
template<size_t SrcElementSize, bool Narrow, bool HostRoundingMode>
|
||||
template<size_t SrcElementSize, bool HostRoundingMode>
|
||||
void XMM_To_MMX_Vector_CVT_Float_To_Int(OpcodeArgs);
|
||||
void MASKMOVOp(OpcodeArgs);
|
||||
void MOVBetweenGPR_FPR(OpcodeArgs);
|
||||
@@ -501,9 +501,19 @@ private:
|
||||
uint8_t GetSrcSize(FEXCore::X86Tables::DecodedOp Op) const;
|
||||
|
||||
template<unsigned BitOffset>
|
||||
void SetRFLAG(OrderedNode *Value);
|
||||
void SetRFLAG(OrderedNode *Value, unsigned BitOffset);
|
||||
OrderedNode *GetRFLAG(unsigned BitOffset);
|
||||
void SetRFLAG(OrderedNode *Value) {
|
||||
flagsOp = FLAGS_OP_NONE;
|
||||
_StoreFlag(_Bfe(1, 0, Value), BitOffset);
|
||||
}
|
||||
|
||||
void SetRFLAG(OrderedNode *Value, unsigned BitOffset) {
|
||||
flagsOp = FLAGS_OP_NONE;
|
||||
_StoreFlag(_Bfe(1, 0, Value), BitOffset);
|
||||
}
|
||||
|
||||
OrderedNode *GetRFLAG(unsigned BitOffset) {
|
||||
return _LoadFlag(BitOffset);
|
||||
}
|
||||
|
||||
OrderedNode *SelectCC(uint8_t OP, OrderedNode *TrueValue, OrderedNode *FalseValue);
|
||||
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
$info$
|
||||
tags: frontend|x86-to-ir, opcodes|dispatcher-implementations
|
||||
desc: Handles x86/64 Crypto instructions to IR
|
||||
$end_info$
|
||||
*/
|
||||
|
||||
#include "Interface/Core/OpcodeDispatcher.h"
|
||||
|
||||
#include <FEXCore/Core/X86Enums.h>
|
||||
|
||||
namespace FEXCore::IR {
|
||||
#define OpcodeArgs [[maybe_unused]] FEXCore::X86Tables::DecodedOp Op
|
||||
|
||||
void OpDispatchBuilder::AESImcOp(OpcodeArgs) {
|
||||
OrderedNode *Src = LoadSource(FPRClass, Op, Op->Src[0], Op->Flags, -1);
|
||||
auto Res = _VAESImc(Src);
|
||||
StoreResult(FPRClass, Op, Res, -1);
|
||||
}
|
||||
|
||||
void OpDispatchBuilder::AESEncOp(OpcodeArgs) {
|
||||
OrderedNode *Dest = LoadSource(FPRClass, Op, Op->Dest, Op->Flags, -1);
|
||||
OrderedNode *Src = LoadSource(FPRClass, Op, Op->Src[0], Op->Flags, -1);
|
||||
auto Res = _VAESEnc(Dest, Src);
|
||||
StoreResult(FPRClass, Op, Res, -1);
|
||||
}
|
||||
|
||||
void OpDispatchBuilder::AESEncLastOp(OpcodeArgs) {
|
||||
OrderedNode *Dest = LoadSource(FPRClass, Op, Op->Dest, Op->Flags, -1);
|
||||
OrderedNode *Src = LoadSource(FPRClass, Op, Op->Src[0], Op->Flags, -1);
|
||||
auto Res = _VAESEncLast(Dest, Src);
|
||||
StoreResult(FPRClass, Op, Res, -1);
|
||||
}
|
||||
|
||||
void OpDispatchBuilder::AESDecOp(OpcodeArgs) {
|
||||
OrderedNode *Dest = LoadSource(FPRClass, Op, Op->Dest, Op->Flags, -1);
|
||||
OrderedNode *Src = LoadSource(FPRClass, Op, Op->Src[0], Op->Flags, -1);
|
||||
auto Res = _VAESDec(Dest, Src);
|
||||
StoreResult(FPRClass, Op, Res, -1);
|
||||
}
|
||||
|
||||
void OpDispatchBuilder::AESDecLastOp(OpcodeArgs) {
|
||||
OrderedNode *Dest = LoadSource(FPRClass, Op, Op->Dest, Op->Flags, -1);
|
||||
OrderedNode *Src = LoadSource(FPRClass, Op, Op->Src[0], Op->Flags, -1);
|
||||
auto Res = _VAESDecLast(Dest, Src);
|
||||
StoreResult(FPRClass, Op, Res, -1);
|
||||
}
|
||||
|
||||
void OpDispatchBuilder::AESKeyGenAssist(OpcodeArgs) {
|
||||
OrderedNode *Src = LoadSource(FPRClass, Op, Op->Src[0], Op->Flags, -1);
|
||||
LOGMAN_THROW_A(Op->Src[1].IsLiteral(), "Src1 needs to be literal here");
|
||||
uint64_t RCON = Op->Src[1].Data.Literal.Value;
|
||||
|
||||
auto Res = _VAESKeyGenAssist(Src, RCON);
|
||||
StoreResult(FPRClass, Op, Res, -1);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,810 @@
|
||||
/*
|
||||
$info$
|
||||
tags: frontend|x86-to-ir, opcodes|dispatcher-implementations
|
||||
desc: Handles x86/64 flag generation
|
||||
$end_info$
|
||||
*/
|
||||
|
||||
#include "Interface/Core/OpcodeDispatcher.h"
|
||||
|
||||
#include <FEXCore/Core/X86Enums.h>
|
||||
|
||||
namespace FEXCore::IR {
|
||||
constexpr std::array<uint32_t, 17> FlagOffsets = {
|
||||
FEXCore::X86State::RFLAG_CF_LOC,
|
||||
FEXCore::X86State::RFLAG_PF_LOC,
|
||||
FEXCore::X86State::RFLAG_AF_LOC,
|
||||
FEXCore::X86State::RFLAG_ZF_LOC,
|
||||
FEXCore::X86State::RFLAG_SF_LOC,
|
||||
FEXCore::X86State::RFLAG_TF_LOC,
|
||||
FEXCore::X86State::RFLAG_IF_LOC,
|
||||
FEXCore::X86State::RFLAG_DF_LOC,
|
||||
FEXCore::X86State::RFLAG_OF_LOC,
|
||||
FEXCore::X86State::RFLAG_IOPL_LOC,
|
||||
FEXCore::X86State::RFLAG_NT_LOC,
|
||||
FEXCore::X86State::RFLAG_RF_LOC,
|
||||
FEXCore::X86State::RFLAG_VM_LOC,
|
||||
FEXCore::X86State::RFLAG_AC_LOC,
|
||||
FEXCore::X86State::RFLAG_VIF_LOC,
|
||||
FEXCore::X86State::RFLAG_VIP_LOC,
|
||||
FEXCore::X86State::RFLAG_ID_LOC,
|
||||
};
|
||||
|
||||
void OpDispatchBuilder::SetPackedRFLAG(bool Lower8, OrderedNode *Src) {
|
||||
uint8_t NumFlags = FlagOffsets.size();
|
||||
if (Lower8) {
|
||||
NumFlags = 5;
|
||||
}
|
||||
auto OneConst = _Constant(1);
|
||||
for (int i = 0; i < NumFlags; ++i) {
|
||||
auto Tmp = _And(_Lshr(Src, _Constant(FlagOffsets[i])), OneConst);
|
||||
SetRFLAG(Tmp, FlagOffsets[i]);
|
||||
}
|
||||
}
|
||||
|
||||
OrderedNode *OpDispatchBuilder::GetPackedRFLAG(bool Lower8) {
|
||||
OrderedNode *Original = _Constant(2);
|
||||
uint8_t NumFlags = FlagOffsets.size();
|
||||
if (Lower8) {
|
||||
NumFlags = 5;
|
||||
}
|
||||
|
||||
for (int i = 0; i < NumFlags; ++i) {
|
||||
OrderedNode *Flag = _LoadFlag(FlagOffsets[i]);
|
||||
Flag = _Bfe(4, 32, 0, Flag);
|
||||
Flag = _Lshl(Flag, _Constant(FlagOffsets[i]));
|
||||
Original = _Or(Original, Flag);
|
||||
}
|
||||
return Original;
|
||||
}
|
||||
|
||||
void OpDispatchBuilder::GenerateFlags_ADC(FEXCore::X86Tables::DecodedOp Op, OrderedNode *Res, OrderedNode *Src1, OrderedNode *Src2, OrderedNode *CF) {
|
||||
auto Size = GetSrcSize(Op) * 8;
|
||||
// AF
|
||||
{
|
||||
OrderedNode *AFRes = _Xor(_Xor(Src1, Src2), Res);
|
||||
AFRes = _Bfe(1, 4, AFRes);
|
||||
SetRFLAG<FEXCore::X86State::RFLAG_AF_LOC>(AFRes);
|
||||
}
|
||||
|
||||
// SF
|
||||
{
|
||||
auto SignBitConst = _Constant(GetSrcSize(Op) * 8 - 1);
|
||||
|
||||
auto LshrOp = _Lshr(Res, SignBitConst);
|
||||
SetRFLAG<FEXCore::X86State::RFLAG_SF_LOC>(LshrOp);
|
||||
}
|
||||
|
||||
// PF
|
||||
if (!CTX->Config.ABINoPF) {
|
||||
auto PopCountOp = _Popcount(_And(Res, _Constant(0xFF)));
|
||||
|
||||
auto XorOp = _Xor(PopCountOp, _Constant(1));
|
||||
SetRFLAG<FEXCore::X86State::RFLAG_PF_LOC>(XorOp);
|
||||
} else {
|
||||
_InvalidateFlags(1UL << FEXCore::X86State::RFLAG_PF_LOC);
|
||||
}
|
||||
|
||||
// ZF
|
||||
{
|
||||
auto SelectOp = _Select(FEXCore::IR::COND_EQ,
|
||||
Res, _Constant(0), _Constant(1), _Constant(0));
|
||||
SetRFLAG<FEXCore::X86State::RFLAG_ZF_LOC>(SelectOp);
|
||||
}
|
||||
|
||||
// CF
|
||||
// Unsigned
|
||||
{
|
||||
auto SelectOpLT = _Select(FEXCore::IR::COND_ULT, Res, Src2, _Constant(1), _Constant(0));
|
||||
auto SelectOpLE = _Select(FEXCore::IR::COND_ULE, Res, Src2, _Constant(1), _Constant(0));
|
||||
auto SelectCF = _Select(FEXCore::IR::COND_EQ, CF, _Constant(1), SelectOpLE, SelectOpLT);
|
||||
SetRFLAG<FEXCore::X86State::RFLAG_CF_LOC>(SelectCF);
|
||||
}
|
||||
|
||||
// OF
|
||||
// Signed
|
||||
{
|
||||
auto NegOne = _Constant(~0ULL);
|
||||
auto XorOp1 = _Xor(_Xor(Src1, Src2), NegOne);
|
||||
auto XorOp2 = _Xor(Res, Src1);
|
||||
OrderedNode *AndOp1 = _And(XorOp1, XorOp2);
|
||||
|
||||
switch (Size) {
|
||||
case 8:
|
||||
AndOp1 = _Bfe(1, 7, AndOp1);
|
||||
break;
|
||||
case 16:
|
||||
AndOp1 = _Bfe(1, 15, AndOp1);
|
||||
break;
|
||||
case 32:
|
||||
AndOp1 = _Bfe(1, 31, AndOp1);
|
||||
break;
|
||||
case 64:
|
||||
AndOp1 = _Bfe(1, 63, AndOp1);
|
||||
break;
|
||||
default: LOGMAN_MSG_A("Unknown BFESize: %d", Size); break;
|
||||
}
|
||||
SetRFLAG<FEXCore::X86State::RFLAG_OF_LOC>(AndOp1);
|
||||
}
|
||||
}
|
||||
|
||||
void OpDispatchBuilder::GenerateFlags_SBB(FEXCore::X86Tables::DecodedOp Op, OrderedNode *Res, OrderedNode *Src1, OrderedNode *Src2, OrderedNode *CF) {
|
||||
// AF
|
||||
{
|
||||
OrderedNode *AFRes = _Xor(_Xor(Src1, Src2), Res);
|
||||
AFRes = _Bfe(1, 4, AFRes);
|
||||
SetRFLAG<FEXCore::X86State::RFLAG_AF_LOC>(AFRes);
|
||||
}
|
||||
|
||||
// SF
|
||||
{
|
||||
auto SignBitConst = _Constant(GetSrcSize(Op) * 8 - 1);
|
||||
|
||||
auto LshrOp = _Lshr(Res, SignBitConst);
|
||||
SetRFLAG<FEXCore::X86State::RFLAG_SF_LOC>(LshrOp);
|
||||
}
|
||||
|
||||
// PF
|
||||
if (!CTX->Config.ABINoPF) {
|
||||
auto PopCountOp = _Popcount(_And(Res, _Constant(0xFF)));
|
||||
|
||||
auto XorOp = _Xor(PopCountOp, _Constant(1));
|
||||
SetRFLAG<FEXCore::X86State::RFLAG_PF_LOC>(XorOp);
|
||||
} else {
|
||||
_InvalidateFlags(1UL << FEXCore::X86State::RFLAG_PF_LOC);
|
||||
}
|
||||
|
||||
// ZF
|
||||
{
|
||||
auto SelectOp = _Select(FEXCore::IR::COND_EQ,
|
||||
Res, _Constant(0), _Constant(1), _Constant(0));
|
||||
SetRFLAG<FEXCore::X86State::RFLAG_ZF_LOC>(SelectOp);
|
||||
}
|
||||
|
||||
// CF
|
||||
// Unsigned
|
||||
{
|
||||
auto SelectOpLT = _Select(FEXCore::IR::COND_UGT, Res, Src1, _Constant(1), _Constant(0));
|
||||
auto SelectOpLE = _Select(FEXCore::IR::COND_UGE, Res, Src1, _Constant(1), _Constant(0));
|
||||
auto SelectCF = _Select(FEXCore::IR::COND_EQ, CF, _Constant(1), SelectOpLE, SelectOpLT);
|
||||
SetRFLAG<FEXCore::X86State::RFLAG_CF_LOC>(SelectCF);
|
||||
}
|
||||
|
||||
// OF
|
||||
// Signed
|
||||
{
|
||||
auto XorOp1 = _Xor(Src1, Src2);
|
||||
auto XorOp2 = _Xor(Res, Src1);
|
||||
OrderedNode *AndOp1 = _And(XorOp1, XorOp2);
|
||||
|
||||
switch (GetSrcSize(Op)) {
|
||||
case 1:
|
||||
AndOp1 = _Bfe(1, 7, AndOp1);
|
||||
break;
|
||||
case 2:
|
||||
AndOp1 = _Bfe(1, 15, AndOp1);
|
||||
break;
|
||||
case 4:
|
||||
AndOp1 = _Bfe(1, 31, AndOp1);
|
||||
break;
|
||||
case 8:
|
||||
AndOp1 = _Bfe(1, 63, AndOp1);
|
||||
break;
|
||||
default: LOGMAN_MSG_A("Unknown BFESize: %d", GetSrcSize(Op)); break;
|
||||
}
|
||||
SetRFLAG<FEXCore::X86State::RFLAG_OF_LOC>(AndOp1);
|
||||
}
|
||||
}
|
||||
|
||||
void OpDispatchBuilder::GenerateFlags_SUB(FEXCore::X86Tables::DecodedOp Op, OrderedNode *Res, OrderedNode *Src1, OrderedNode *Src2, bool UpdateCF) {
|
||||
// AF
|
||||
{
|
||||
OrderedNode *AFRes = _Xor(_Xor(Src1, Src2), Res);
|
||||
AFRes = _Bfe(1, 4, AFRes);
|
||||
SetRFLAG<FEXCore::X86State::RFLAG_AF_LOC>(AFRes);
|
||||
}
|
||||
|
||||
// SF
|
||||
{
|
||||
auto SignBitConst = _Constant(GetSrcSize(Op) * 8 - 1);
|
||||
|
||||
auto LshrOp = _Lshr(Res, SignBitConst);
|
||||
SetRFLAG<FEXCore::X86State::RFLAG_SF_LOC>(LshrOp);
|
||||
}
|
||||
|
||||
// PF
|
||||
if (!CTX->Config.ABINoPF) {
|
||||
auto EightBitMask = _Constant(0xFF);
|
||||
auto PopCountOp = _Popcount(_And(Res, EightBitMask));
|
||||
auto XorOp = _Xor(PopCountOp, _Constant(1));
|
||||
SetRFLAG<FEXCore::X86State::RFLAG_PF_LOC>(XorOp);
|
||||
} else {
|
||||
_InvalidateFlags(1UL << FEXCore::X86State::RFLAG_PF_LOC);
|
||||
}
|
||||
|
||||
// ZF
|
||||
{
|
||||
auto ZeroConst = _Constant(0);
|
||||
auto OneConst = _Constant(1);
|
||||
auto SelectOp = _Select(FEXCore::IR::COND_EQ,
|
||||
Res, ZeroConst, OneConst, ZeroConst);
|
||||
SetRFLAG<FEXCore::X86State::RFLAG_ZF_LOC>(SelectOp);
|
||||
}
|
||||
|
||||
// CF
|
||||
if (UpdateCF) {
|
||||
auto ZeroConst = _Constant(0);
|
||||
auto OneConst = _Constant(1);
|
||||
|
||||
auto SelectOp = _Select(FEXCore::IR::COND_ULT,
|
||||
Src1, Src2, OneConst, ZeroConst);
|
||||
|
||||
SetRFLAG<FEXCore::X86State::RFLAG_CF_LOC>(SelectOp);
|
||||
}
|
||||
// OF
|
||||
{
|
||||
auto XorOp1 = _Xor(Src1, Src2);
|
||||
auto XorOp2 = _Xor(Res, Src1);
|
||||
OrderedNode *FinalAnd = _And(XorOp1, XorOp2);
|
||||
|
||||
FinalAnd = _Bfe(1, GetSrcSize(Op) * 8 - 1, FinalAnd);
|
||||
|
||||
SetRFLAG<FEXCore::X86State::RFLAG_OF_LOC>(FinalAnd);
|
||||
}
|
||||
}
|
||||
|
||||
void OpDispatchBuilder::GenerateFlags_ADD(FEXCore::X86Tables::DecodedOp Op, OrderedNode *Res, OrderedNode *Src1, OrderedNode *Src2, bool UpdateCF) {
|
||||
// AF
|
||||
{
|
||||
OrderedNode *AFRes = _Xor(_Xor(Src1, Src2), Res);
|
||||
AFRes = _Bfe(1, 4, AFRes);
|
||||
SetRFLAG<FEXCore::X86State::RFLAG_AF_LOC>(AFRes);
|
||||
}
|
||||
|
||||
// SF
|
||||
{
|
||||
auto SignBitConst = _Constant(GetSrcSize(Op) * 8 - 1);
|
||||
|
||||
auto LshrOp = _Lshr(Res, SignBitConst);
|
||||
SetRFLAG<FEXCore::X86State::RFLAG_SF_LOC>(LshrOp);
|
||||
}
|
||||
|
||||
// PF
|
||||
if (!CTX->Config.ABINoPF) {
|
||||
auto EightBitMask = _Constant(0xFF);
|
||||
auto PopCountOp = _Popcount(_And(Res, EightBitMask));
|
||||
auto XorOp = _Xor(PopCountOp, _Constant(1));
|
||||
SetRFLAG<FEXCore::X86State::RFLAG_PF_LOC>(XorOp);
|
||||
} else {
|
||||
_InvalidateFlags(1UL << FEXCore::X86State::RFLAG_PF_LOC);
|
||||
}
|
||||
|
||||
// ZF
|
||||
{
|
||||
auto SelectOp = _Select(FEXCore::IR::COND_EQ,
|
||||
Res, _Constant(0), _Constant(1), _Constant(0));
|
||||
SetRFLAG<FEXCore::X86State::RFLAG_ZF_LOC>(SelectOp);
|
||||
}
|
||||
// CF
|
||||
if (UpdateCF) {
|
||||
auto SelectOp = _Select(FEXCore::IR::COND_ULT, Res, Src2, _Constant(1), _Constant(0));
|
||||
|
||||
SetRFLAG<FEXCore::X86State::RFLAG_CF_LOC>(SelectOp);
|
||||
}
|
||||
|
||||
// OF
|
||||
{
|
||||
auto NegOne = _Constant(~0ULL);
|
||||
auto XorOp1 = _Xor(_Xor(Src1, Src2), NegOne);
|
||||
auto XorOp2 = _Xor(Res, Src1);
|
||||
|
||||
OrderedNode *AndOp1 = _And(XorOp1, XorOp2);
|
||||
|
||||
switch (GetSrcSize(Op)) {
|
||||
case 1:
|
||||
AndOp1 = _Bfe(1, 7, AndOp1);
|
||||
break;
|
||||
case 2:
|
||||
AndOp1 = _Bfe(1, 15, AndOp1);
|
||||
break;
|
||||
case 4:
|
||||
AndOp1 = _Bfe(1, 31, AndOp1);
|
||||
break;
|
||||
case 8:
|
||||
AndOp1 = _Bfe(1, 63, AndOp1);
|
||||
break;
|
||||
default: LOGMAN_MSG_A("Unknown BFESize: %d", GetSrcSize(Op)); break;
|
||||
}
|
||||
SetRFLAG<FEXCore::X86State::RFLAG_OF_LOC>(AndOp1);
|
||||
}
|
||||
}
|
||||
|
||||
void OpDispatchBuilder::GenerateFlags_MUL(FEXCore::X86Tables::DecodedOp Op, OrderedNode *Res, OrderedNode *High) {
|
||||
// PF/AF/ZF/SF
|
||||
// Undefined
|
||||
{
|
||||
SetRFLAG<FEXCore::X86State::RFLAG_PF_LOC>(_Constant(0));
|
||||
SetRFLAG<FEXCore::X86State::RFLAG_AF_LOC>(_Constant(0));
|
||||
SetRFLAG<FEXCore::X86State::RFLAG_ZF_LOC>(_Constant(0));
|
||||
SetRFLAG<FEXCore::X86State::RFLAG_SF_LOC>(_Constant(0));
|
||||
}
|
||||
|
||||
// CF/OF
|
||||
{
|
||||
// CF and OF are set if the result of the operation can't be fit in to the destination register
|
||||
// If the value can fit then the top bits will be zero
|
||||
|
||||
auto SignBit = _Sbfe(1, GetSrcSize(Op) * 8 - 1, Res);
|
||||
|
||||
auto SelectOp = _Select(FEXCore::IR::COND_EQ, High, SignBit, _Constant(0), _Constant(1));
|
||||
|
||||
SetRFLAG<FEXCore::X86State::RFLAG_CF_LOC>(SelectOp);
|
||||
SetRFLAG<FEXCore::X86State::RFLAG_OF_LOC>(SelectOp);
|
||||
}
|
||||
}
|
||||
|
||||
void OpDispatchBuilder::GenerateFlags_UMUL(FEXCore::X86Tables::DecodedOp Op, OrderedNode *High) {
|
||||
// AF/SF/PF/ZF
|
||||
// Undefined
|
||||
{
|
||||
SetRFLAG<FEXCore::X86State::RFLAG_AF_LOC>(_Constant(0));
|
||||
SetRFLAG<FEXCore::X86State::RFLAG_SF_LOC>(_Constant(0));
|
||||
SetRFLAG<FEXCore::X86State::RFLAG_PF_LOC>(_Constant(0));
|
||||
SetRFLAG<FEXCore::X86State::RFLAG_ZF_LOC>(_Constant(0));
|
||||
}
|
||||
|
||||
// CF/OF
|
||||
{
|
||||
// CF and OF are set if the result of the operation can't be fit in to the destination register
|
||||
// The result register will be all zero if it can't fit due to how multiplication behaves
|
||||
|
||||
auto SelectOp = _Select(FEXCore::IR::COND_EQ, High, _Constant(0), _Constant(0), _Constant(1));
|
||||
|
||||
SetRFLAG<FEXCore::X86State::RFLAG_CF_LOC>(SelectOp);
|
||||
SetRFLAG<FEXCore::X86State::RFLAG_OF_LOC>(SelectOp);
|
||||
}
|
||||
}
|
||||
|
||||
void OpDispatchBuilder::GenerateFlags_Logical(FEXCore::X86Tables::DecodedOp Op, OrderedNode *Res, OrderedNode *Src1, OrderedNode *Src2) {
|
||||
// AF
|
||||
{
|
||||
// Undefined
|
||||
// Set to zero anyway
|
||||
SetRFLAG<FEXCore::X86State::RFLAG_AF_LOC>(_Constant(0));
|
||||
}
|
||||
|
||||
// SF
|
||||
{
|
||||
auto SignBitConst = _Constant(GetSrcSize(Op) * 8 - 1);
|
||||
|
||||
auto LshrOp = _Lshr(Res, SignBitConst);
|
||||
SetRFLAG<FEXCore::X86State::RFLAG_SF_LOC>(LshrOp);
|
||||
}
|
||||
|
||||
// PF
|
||||
if (!CTX->Config.ABINoPF) {
|
||||
auto EightBitMask = _Constant(0xFF);
|
||||
auto PopCountOp = _Popcount(_And(Res, EightBitMask));
|
||||
auto XorOp = _Xor(PopCountOp, _Constant(1));
|
||||
SetRFLAG<FEXCore::X86State::RFLAG_PF_LOC>(XorOp);
|
||||
} else {
|
||||
_InvalidateFlags(1UL << FEXCore::X86State::RFLAG_PF_LOC);
|
||||
}
|
||||
|
||||
// ZF
|
||||
{
|
||||
auto SelectOp = _Select(FEXCore::IR::COND_EQ,
|
||||
Res, _Constant(0), _Constant(1), _Constant(0));
|
||||
SetRFLAG<FEXCore::X86State::RFLAG_ZF_LOC>(SelectOp);
|
||||
}
|
||||
|
||||
// CF/OF
|
||||
{
|
||||
SetRFLAG<FEXCore::X86State::RFLAG_CF_LOC>(_Constant(0));
|
||||
SetRFLAG<FEXCore::X86State::RFLAG_OF_LOC>(_Constant(0));
|
||||
}
|
||||
}
|
||||
|
||||
#define COND_FLAG_SET(cond, flag, newflag) \
|
||||
auto oldflag = GetRFLAG(FEXCore::X86State::flag);\
|
||||
auto newval = _Select(FEXCore::IR::COND_EQ, cond, _Constant(0), oldflag, newflag);\
|
||||
SetRFLAG<FEXCore::X86State::flag>(newval);
|
||||
|
||||
void OpDispatchBuilder::GenerateFlags_ShiftLeft(FEXCore::X86Tables::DecodedOp Op, OrderedNode *Res, OrderedNode *Src1, OrderedNode *Src2) {
|
||||
// CF
|
||||
{
|
||||
// Extract the last bit shifted in to CF
|
||||
auto Size = _Constant(GetSrcSize(Op) * 8);
|
||||
auto ShiftAmt = _Sub(Size, Src2);
|
||||
auto LastBit = _And(_Lshr(Src1, ShiftAmt), _Constant(1));
|
||||
COND_FLAG_SET(Src2, RFLAG_CF_LOC, LastBit);
|
||||
}
|
||||
|
||||
// PF
|
||||
if (!CTX->Config.ABINoPF) {
|
||||
auto EightBitMask = _Constant(0xFF);
|
||||
auto PopCountOp = _Popcount(_And(Res, EightBitMask));
|
||||
auto XorOp = _Xor(PopCountOp, _Constant(1));
|
||||
COND_FLAG_SET(Src2, RFLAG_PF_LOC, XorOp);
|
||||
} else {
|
||||
_InvalidateFlags(1UL << FEXCore::X86State::RFLAG_PF_LOC);
|
||||
}
|
||||
|
||||
// AF
|
||||
{
|
||||
// Undefined
|
||||
// Set to zero anyway
|
||||
COND_FLAG_SET(Src2, RFLAG_AF_LOC, _Constant(0));
|
||||
}
|
||||
|
||||
// ZF
|
||||
{
|
||||
auto SelectOp = _Select(FEXCore::IR::COND_EQ,
|
||||
Res, _Constant(0), _Constant(1), _Constant(0));
|
||||
COND_FLAG_SET(Src2, RFLAG_ZF_LOC, SelectOp);
|
||||
}
|
||||
|
||||
// SF
|
||||
{
|
||||
auto val = _Bfe(1, GetSrcSize(Op) * 8 - 1, Res);
|
||||
COND_FLAG_SET(Src2, RFLAG_SF_LOC, val);
|
||||
}
|
||||
|
||||
// OF
|
||||
{
|
||||
// In the case of left shift. OF is only set from the result of <Top Source Bit> XOR <Top Result Bit>
|
||||
// When Shift > 1 then OF is undefined
|
||||
auto val = _Bfe(1, GetSrcSize(Op) * 8 - 1, _Xor(Src1, Res));
|
||||
COND_FLAG_SET(Src2, RFLAG_OF_LOC, val);
|
||||
}
|
||||
}
|
||||
|
||||
void OpDispatchBuilder::GenerateFlags_ShiftRight(FEXCore::X86Tables::DecodedOp Op, OrderedNode *Res, OrderedNode *Src1, OrderedNode *Src2) {
|
||||
// CF
|
||||
{
|
||||
// Extract the last bit shifted in to CF
|
||||
auto ShiftAmt = _Sub(Src2, _Constant(1));
|
||||
auto LastBit = _And(_Lshr(Src1, ShiftAmt), _Constant(1));
|
||||
COND_FLAG_SET(Src2, RFLAG_CF_LOC, LastBit);
|
||||
}
|
||||
|
||||
// PF
|
||||
if (!CTX->Config.ABINoPF) {
|
||||
auto EightBitMask = _Constant(0xFF);
|
||||
auto PopCountOp = _Popcount(_And(Res, EightBitMask));
|
||||
auto XorOp = _Xor(PopCountOp, _Constant(1));
|
||||
COND_FLAG_SET(Src2, RFLAG_PF_LOC, XorOp);
|
||||
} else {
|
||||
_InvalidateFlags(1UL << FEXCore::X86State::RFLAG_PF_LOC);
|
||||
}
|
||||
|
||||
// AF
|
||||
{
|
||||
// Undefined
|
||||
// Set to zero anyway
|
||||
COND_FLAG_SET(Src2, RFLAG_AF_LOC, _Constant(0));
|
||||
}
|
||||
|
||||
// ZF
|
||||
{
|
||||
auto SelectOp = _Select(FEXCore::IR::COND_EQ,
|
||||
Res, _Constant(0), _Constant(1), _Constant(0));
|
||||
COND_FLAG_SET(Src2, RFLAG_ZF_LOC, SelectOp);
|
||||
}
|
||||
|
||||
// SF
|
||||
{
|
||||
auto val =_Bfe(1, GetSrcSize(Op) * 8 - 1, Res);
|
||||
COND_FLAG_SET(Src2, RFLAG_SF_LOC, val);
|
||||
}
|
||||
|
||||
// OF
|
||||
{
|
||||
// Only defined when Shift is 1 else undefined
|
||||
// OF flag is set if a sign change occurred
|
||||
auto val = _Bfe(1, GetSrcSize(Op) * 8 - 1, _Xor(Src1, Res));
|
||||
COND_FLAG_SET(Src2, RFLAG_OF_LOC, val);
|
||||
}
|
||||
}
|
||||
|
||||
void OpDispatchBuilder::GenerateFlags_SignShiftRight(FEXCore::X86Tables::DecodedOp Op, OrderedNode *Res, OrderedNode *Src1, OrderedNode *Src2) {
|
||||
// CF
|
||||
{
|
||||
// Extract the last bit shifted in to CF
|
||||
auto ShiftAmt = _Sub(Src2, _Constant(1));
|
||||
auto LastBit = _And(_Lshr(Src1, ShiftAmt), _Constant(1));
|
||||
COND_FLAG_SET(Src2, RFLAG_CF_LOC, LastBit);
|
||||
}
|
||||
|
||||
// PF
|
||||
if (!CTX->Config.ABINoPF) {
|
||||
auto EightBitMask = _Constant(0xFF);
|
||||
auto PopCountOp = _Popcount(_And(Res, EightBitMask));
|
||||
auto XorOp = _Xor(PopCountOp, _Constant(1));
|
||||
COND_FLAG_SET(Src2, RFLAG_PF_LOC, XorOp);
|
||||
} else {
|
||||
_InvalidateFlags(1UL << FEXCore::X86State::RFLAG_PF_LOC);
|
||||
}
|
||||
|
||||
// AF
|
||||
{
|
||||
// Undefined
|
||||
// Set to zero anyway
|
||||
COND_FLAG_SET(Src2, RFLAG_AF_LOC, _Constant(0));
|
||||
}
|
||||
|
||||
// ZF
|
||||
{
|
||||
auto SelectOp = _Select(FEXCore::IR::COND_EQ,
|
||||
Res, _Constant(0), _Constant(1), _Constant(0));
|
||||
COND_FLAG_SET(Src2, RFLAG_ZF_LOC, SelectOp);
|
||||
}
|
||||
|
||||
// SF
|
||||
{
|
||||
auto SignBitConst = _Constant(GetSrcSize(Op) * 8 - 1);
|
||||
|
||||
auto LshrOp = _Lshr(Res, SignBitConst);
|
||||
COND_FLAG_SET(Src2, RFLAG_SF_LOC, LshrOp);
|
||||
}
|
||||
|
||||
// OF
|
||||
{
|
||||
COND_FLAG_SET(Src2, RFLAG_OF_LOC, _Constant(0));
|
||||
}
|
||||
}
|
||||
|
||||
void OpDispatchBuilder::GenerateFlags_ShiftLeftImmediate(FEXCore::X86Tables::DecodedOp Op, OrderedNode *Res, OrderedNode *Src1, uint64_t Shift) {
|
||||
// No flags changed if shift is zero
|
||||
if (Shift == 0) return;
|
||||
|
||||
// CF
|
||||
{
|
||||
// Extract the last bit shifted in to CF
|
||||
SetRFLAG<FEXCore::X86State::RFLAG_CF_LOC>(_Bfe(1, GetSrcSize(Op) * 8 - Shift, Src1));
|
||||
}
|
||||
|
||||
// PF
|
||||
if (!CTX->Config.ABINoPF) {
|
||||
auto EightBitMask = _Constant(0xFF);
|
||||
auto PopCountOp = _Popcount(_And(Res, EightBitMask));
|
||||
auto XorOp = _Xor(PopCountOp, _Constant(1));
|
||||
SetRFLAG<FEXCore::X86State::RFLAG_PF_LOC>(XorOp);
|
||||
} else {
|
||||
_InvalidateFlags(1UL << FEXCore::X86State::RFLAG_PF_LOC);
|
||||
}
|
||||
|
||||
// AF
|
||||
{
|
||||
// Undefined
|
||||
// Set to zero anyway
|
||||
SetRFLAG<FEXCore::X86State::RFLAG_AF_LOC>(_Constant(0));
|
||||
}
|
||||
|
||||
// ZF
|
||||
{
|
||||
auto SelectOp = _Select(FEXCore::IR::COND_EQ,
|
||||
Res, _Constant(0), _Constant(1), _Constant(0));
|
||||
SetRFLAG<FEXCore::X86State::RFLAG_ZF_LOC>(SelectOp);
|
||||
}
|
||||
|
||||
// SF
|
||||
{
|
||||
auto LshrOp = _Bfe(1, GetSrcSize(Op) * 8 - 1, Res);
|
||||
|
||||
SetRFLAG<FEXCore::X86State::RFLAG_SF_LOC>(LshrOp);
|
||||
|
||||
// OF
|
||||
// In the case of left shift. OF is only set from the result of <Top Source Bit> XOR <Top Result Bit>
|
||||
if (Shift == 1) {
|
||||
auto SourceBit = _Bfe(1, GetSrcSize(Op) * 8 - 1, Src1);
|
||||
SetRFLAG<FEXCore::X86State::RFLAG_OF_LOC>(_Xor(SourceBit, LshrOp));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void OpDispatchBuilder::GenerateFlags_SignShiftRightImmediate(FEXCore::X86Tables::DecodedOp Op, OrderedNode *Res, OrderedNode *Src1, uint64_t Shift) {
|
||||
// No flags changed if shift is zero
|
||||
if (Shift == 0) return;
|
||||
|
||||
// CF
|
||||
{
|
||||
// Extract the last bit shifted in to CF
|
||||
SetRFLAG<FEXCore::X86State::RFLAG_CF_LOC>(_Bfe(1, Shift-1, Src1));
|
||||
}
|
||||
|
||||
// PF
|
||||
if (!CTX->Config.ABINoPF) {
|
||||
auto EightBitMask = _Constant(0xFF);
|
||||
auto PopCountOp = _Popcount(_And(Res, EightBitMask));
|
||||
auto XorOp = _Xor(PopCountOp, _Constant(1));
|
||||
SetRFLAG<FEXCore::X86State::RFLAG_PF_LOC>(XorOp);
|
||||
} else {
|
||||
_InvalidateFlags(1UL << FEXCore::X86State::RFLAG_PF_LOC);
|
||||
}
|
||||
|
||||
// AF
|
||||
{
|
||||
// Undefined
|
||||
// Set to zero anyway
|
||||
SetRFLAG<FEXCore::X86State::RFLAG_AF_LOC>(_Constant(0));
|
||||
}
|
||||
|
||||
// ZF
|
||||
{
|
||||
auto SelectOp = _Select(FEXCore::IR::COND_EQ,
|
||||
Res, _Constant(0), _Constant(1), _Constant(0));
|
||||
SetRFLAG<FEXCore::X86State::RFLAG_ZF_LOC>(SelectOp);
|
||||
}
|
||||
|
||||
// SF
|
||||
{
|
||||
auto SignBitConst = _Constant(GetSrcSize(Op) * 8 - 1);
|
||||
|
||||
auto LshrOp = _Lshr(Res, SignBitConst);
|
||||
SetRFLAG<FEXCore::X86State::RFLAG_SF_LOC>(LshrOp);
|
||||
|
||||
// OF
|
||||
// Only defined when Shift is 1 else undefined
|
||||
// Only is set if the top bit was set to 1 when shifted
|
||||
// So it is set to same value as SF
|
||||
if (Shift == 1) {
|
||||
SetRFLAG<FEXCore::X86State::RFLAG_OF_LOC>(_Constant(0));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void OpDispatchBuilder::GenerateFlags_ShiftRightImmediate(FEXCore::X86Tables::DecodedOp Op, OrderedNode *Res, OrderedNode *Src1, uint64_t Shift) {
|
||||
// No flags changed if shift is zero
|
||||
if (Shift == 0) return;
|
||||
|
||||
// CF
|
||||
{
|
||||
// Extract the last bit shifted in to CF
|
||||
SetRFLAG<FEXCore::X86State::RFLAG_CF_LOC>(_Bfe(1, Shift-1, Src1));
|
||||
}
|
||||
|
||||
// PF
|
||||
if (!CTX->Config.ABINoPF) {
|
||||
auto EightBitMask = _Constant(0xFF);
|
||||
auto PopCountOp = _Popcount(_And(Res, EightBitMask));
|
||||
auto XorOp = _Xor(PopCountOp, _Constant(1));
|
||||
SetRFLAG<FEXCore::X86State::RFLAG_PF_LOC>(XorOp);
|
||||
} else {
|
||||
_InvalidateFlags(1UL << FEXCore::X86State::RFLAG_PF_LOC);
|
||||
}
|
||||
|
||||
// AF
|
||||
{
|
||||
// Undefined
|
||||
// Set to zero anyway
|
||||
SetRFLAG<FEXCore::X86State::RFLAG_AF_LOC>(_Constant(0));
|
||||
}
|
||||
|
||||
// ZF
|
||||
{
|
||||
auto SelectOp = _Select(FEXCore::IR::COND_EQ,
|
||||
Res, _Constant(0), _Constant(1), _Constant(0));
|
||||
SetRFLAG<FEXCore::X86State::RFLAG_ZF_LOC>(SelectOp);
|
||||
}
|
||||
|
||||
// SF
|
||||
{
|
||||
auto SignBitConst = _Constant(GetSrcSize(Op) * 8 - 1);
|
||||
|
||||
auto LshrOp = _Lshr(Res, SignBitConst);
|
||||
SetRFLAG<FEXCore::X86State::RFLAG_SF_LOC>(LshrOp);
|
||||
}
|
||||
|
||||
// OF
|
||||
{
|
||||
// Only defined when Shift is 1 else undefined
|
||||
// Is set to the MSB of the original value
|
||||
if (Shift == 1) {
|
||||
SetRFLAG<FEXCore::X86State::RFLAG_OF_LOC>(_Bfe(1, GetSrcSize(Op) * 8 - 1, Src1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void OpDispatchBuilder::GenerateFlags_RotateRight(FEXCore::X86Tables::DecodedOp Op, OrderedNode *Res, OrderedNode *Src1, OrderedNode *Src2) {
|
||||
auto OpSize = GetSrcSize(Op) * 8;
|
||||
|
||||
// Extract the last bit shifted in to CF
|
||||
auto NewCF = _Bfe(1, OpSize - 1, Res);
|
||||
|
||||
// CF
|
||||
{
|
||||
auto OldCF = GetRFLAG(FEXCore::X86State::RFLAG_CF_LOC);
|
||||
auto CF = _Select(FEXCore::IR::COND_EQ, Src2, _Constant(0), OldCF, NewCF);
|
||||
|
||||
// Extract the last bit shifted in to CF
|
||||
SetRFLAG<FEXCore::X86State::RFLAG_CF_LOC>(CF);
|
||||
}
|
||||
|
||||
// OF
|
||||
{
|
||||
auto OldOF = GetRFLAG(FEXCore::X86State::RFLAG_OF_LOC);
|
||||
|
||||
// OF is set to the XOR of the new CF bit and the most significant bit of the result
|
||||
auto NewOF = _Xor(_Bfe(1, OpSize - 2, Res), NewCF);
|
||||
|
||||
// If shift == 0, don't update flags
|
||||
auto OF = _Select(FEXCore::IR::COND_EQ, Src2, _Constant(0), OldOF, NewOF);
|
||||
|
||||
SetRFLAG<FEXCore::X86State::RFLAG_OF_LOC>(OF);
|
||||
}
|
||||
}
|
||||
|
||||
void OpDispatchBuilder::GenerateFlags_RotateLeft(FEXCore::X86Tables::DecodedOp Op, OrderedNode *Res, OrderedNode *Src1, OrderedNode *Src2) {
|
||||
auto OpSize = GetSrcSize(Op) * 8;
|
||||
|
||||
// Extract the last bit shifted in to CF
|
||||
//auto Size = _Constant(GetSrcSize(Res) * 8);
|
||||
//auto ShiftAmt = _Sub(Size, Src2);
|
||||
auto NewCF = _Bfe(1, 0, Res);
|
||||
|
||||
// CF
|
||||
{
|
||||
auto OldCF = GetRFLAG(FEXCore::X86State::RFLAG_CF_LOC);
|
||||
auto CF = _Select(FEXCore::IR::COND_EQ, Src2, _Constant(0), OldCF, NewCF);
|
||||
|
||||
// Extract the last bit shifted in to CF
|
||||
SetRFLAG<FEXCore::X86State::RFLAG_CF_LOC>(CF);
|
||||
}
|
||||
|
||||
// OF
|
||||
{
|
||||
auto OldOF = GetRFLAG(FEXCore::X86State::RFLAG_OF_LOC);
|
||||
// OF is set to the XOR of the new CF bit and the most significant bit of the result
|
||||
auto NewOF = _Xor(_Bfe(1, OpSize - 1, Res), NewCF);
|
||||
|
||||
auto OF = _Select(FEXCore::IR::COND_EQ, Src2, _Constant(0), OldOF, NewOF);
|
||||
|
||||
// If shift == 0, don't update flags
|
||||
SetRFLAG<FEXCore::X86State::RFLAG_OF_LOC>(OF);
|
||||
}
|
||||
}
|
||||
|
||||
void OpDispatchBuilder::GenerateFlags_RotateRightImmediate(FEXCore::X86Tables::DecodedOp Op, OrderedNode *Res, OrderedNode *Src1, uint64_t Shift) {
|
||||
if (Shift == 0) return;
|
||||
|
||||
auto OpSize = GetSrcSize(Op) * 8;
|
||||
|
||||
auto NewCF = _Bfe(1, OpSize - Shift, Src1);
|
||||
|
||||
// CF
|
||||
{
|
||||
// Extract the last bit shifted in to CF
|
||||
SetRFLAG<FEXCore::X86State::RFLAG_CF_LOC>(NewCF);
|
||||
}
|
||||
|
||||
// OF
|
||||
{
|
||||
if (Shift == 1) {
|
||||
// OF is set to the XOR of the new CF bit and the most significant bit of the result
|
||||
SetRFLAG<FEXCore::X86State::RFLAG_OF_LOC>(_Xor(_Bfe(1, OpSize - 1, Res), NewCF));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void OpDispatchBuilder::GenerateFlags_RotateLeftImmediate(FEXCore::X86Tables::DecodedOp Op, OrderedNode *Res, OrderedNode *Src1, uint64_t Shift) {
|
||||
if (Shift == 0) return;
|
||||
|
||||
auto OpSize = GetSrcSize(Op) * 8;
|
||||
|
||||
// CF
|
||||
{
|
||||
// Extract the last bit shifted in to CF
|
||||
SetRFLAG<FEXCore::X86State::RFLAG_CF_LOC>(_Bfe(1, Shift, Src1));
|
||||
}
|
||||
|
||||
// OF
|
||||
{
|
||||
if (Shift == 1) {
|
||||
// OF is the top two MSBs XOR'd together
|
||||
SetRFLAG<FEXCore::X86State::RFLAG_OF_LOC>(_Xor(_Bfe(1, OpSize - 1, Src1), _Bfe(1, OpSize - 2, Src1)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
@@ -4,6 +4,8 @@ tags: frontend|x86-tables
|
||||
$end_info$
|
||||
*/
|
||||
|
||||
#include <FEXCore/Core/Context.h>
|
||||
|
||||
#include "Interface/Core/X86Tables/X86Tables.h"
|
||||
|
||||
namespace FEXCore::X86Tables {
|
||||
|
||||
@@ -6,6 +6,7 @@ $end_info$
|
||||
|
||||
#pragma once
|
||||
#include <FEXCore/Debug/X86Tables.h>
|
||||
#include <FEXCore/Core/Context.h>
|
||||
|
||||
#include <FEXCore/Utils/LogManager.h>
|
||||
|
||||
@@ -113,5 +114,7 @@ static inline void GenerateX87Table(X86InstInfo *FinalTable, U16U8InfoStruct con
|
||||
}
|
||||
};
|
||||
|
||||
void InitializeInfoTables(Context::OperatingMode Mode);
|
||||
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include <FEXCore/Core/Context.h>
|
||||
#include <FEXCore/Utils/CompilerDefs.h>
|
||||
|
||||
#include <cstdint>
|
||||
@@ -500,6 +499,4 @@ extern FEX_DEFAULT_VISIBILITY X86InstInfo XOPTableGroupOps[MAX_XOP_GROUP_TABLE_S
|
||||
|
||||
// EVEX
|
||||
extern FEX_DEFAULT_VISIBILITY X86InstInfo EVEXTableOps[MAX_EVEX_TABLE_SIZE];
|
||||
|
||||
FEX_DEFAULT_VISIBILITY void InitializeInfoTables(Context::OperatingMode Mode);
|
||||
}
|
||||
@@ -2407,7 +2407,7 @@ int main(int argc, char **argv, char **const envp) {
|
||||
|
||||
LOGMAN_THROW_A(!Args.empty(), "Not enough arguments");
|
||||
|
||||
FEXCore::X86Tables::InitializeInfoTables(FEXCore::Context::MODE_64BIT);
|
||||
FEXCore::Context::InitializeStaticTables(FEXCore::Context::MODE_64BIT);
|
||||
|
||||
Code.reserve(4096*128);
|
||||
Filepath = Args[0];
|
||||
|
||||
Reference in new issue
Block a user