mirror of
https://github.com/FEX-Emu/FEX.git
synced 2026-10-24 08:00:43 +02:00
Merge pull request #65 from Sonicadvance1/comiss
Implements the COMISS instructions
This commit is contained in:
commit
9ecdfefdd9
10 files changed
+243
-6
No files matched your search
@@ -3206,6 +3206,56 @@ void InterpreterCore::ExecuteCode(FEXCore::Core::InternalThreadState *Thread) {
|
||||
memcpy(GDP, Tmp, Op->RegisterSize);
|
||||
break;
|
||||
}
|
||||
case IR::OP_FCMP: {
|
||||
auto Op = IROp->C<IR::IROp_FCmp>();
|
||||
uint32_t ResultFlags{};
|
||||
if (Op->ElementSize == 4) {
|
||||
float Src1 = *GetSrc<float*>(Op->Header.Args[0]);
|
||||
float Src2 = *GetSrc<float*>(Op->Header.Args[1]);
|
||||
if (Op->Flags & (1 << FCMP_FLAG_LT)) {
|
||||
if (Src1 < Src2) {
|
||||
ResultFlags |= (1 << FCMP_FLAG_LT);
|
||||
}
|
||||
}
|
||||
if (Op->Flags & (1 << FCMP_FLAG_UNORDERED)) {
|
||||
if (std::isnan(Src1) || std::isnan(Src2)) {
|
||||
ResultFlags |= (1 << FCMP_FLAG_UNORDERED);
|
||||
}
|
||||
}
|
||||
if (Op->Flags & (1 << FCMP_FLAG_EQ)) {
|
||||
if (Src1 == Src2) {
|
||||
ResultFlags |= (1 << FCMP_FLAG_EQ);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
double Src1 = *GetSrc<double*>(Op->Header.Args[0]);
|
||||
double Src2 = *GetSrc<double*>(Op->Header.Args[1]);
|
||||
if (Op->Flags & (1 << FCMP_FLAG_LT)) {
|
||||
if (Src1 < Src2) {
|
||||
ResultFlags |= (1 << FCMP_FLAG_LT);
|
||||
}
|
||||
}
|
||||
if (Op->Flags & (1 << FCMP_FLAG_UNORDERED)) {
|
||||
if (std::isnan(Src1) || std::isnan(Src2)) {
|
||||
ResultFlags |= (1 << FCMP_FLAG_UNORDERED);
|
||||
}
|
||||
}
|
||||
if (Op->Flags & (1 << FCMP_FLAG_EQ)) {
|
||||
if (Src1 == Src2) {
|
||||
ResultFlags |= (1 << FCMP_FLAG_EQ);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GD = ResultFlags;
|
||||
break;
|
||||
}
|
||||
case IR::OP_GETHOSTFLAG: {
|
||||
auto Op = IROp->C<IR::IROp_GetHostFlag>();
|
||||
GD = (*GetSrc<uint64_t*>(Op->Header.Args[0]) >> Op->Flag) & 1;
|
||||
break;
|
||||
}
|
||||
#define DO_SCALAR_COMPARE_OP(size, type, type2, func) \
|
||||
case size: { \
|
||||
auto *Dst_d = reinterpret_cast<type2*>(Tmp); \
|
||||
|
||||
@@ -2929,6 +2929,42 @@ void *JITCore::CompileCode([[maybe_unused]] FEXCore::IR::IRListView<true> const
|
||||
}
|
||||
break;
|
||||
}
|
||||
case IR::OP_FCMP: {
|
||||
auto Op = IROp->C<IR::IROp_FCmp>();
|
||||
|
||||
if (Op->ElementSize == 4) {
|
||||
fcmp(GetSrc(Op->Header.Args[0].ID()).S(), GetSrc(Op->Header.Args[1].ID()).S());
|
||||
}
|
||||
else {
|
||||
fcmp(GetSrc(Op->Header.Args[0].ID()).D(), GetSrc(Op->Header.Args[1].ID()).D());
|
||||
}
|
||||
auto Dst = GetSrc<RA_64>(Node);
|
||||
eor(Dst, Dst, Dst);
|
||||
|
||||
if (Op->Flags & (1 << FCMP_FLAG_LT)) {
|
||||
cset(TMP2, Condition::mi);
|
||||
lsl(TMP2, TMP2, FCMP_FLAG_LT);
|
||||
orr(Dst, Dst, TMP2);
|
||||
}
|
||||
if (Op->Flags & (1 << FCMP_FLAG_EQ)) {
|
||||
cset(TMP2, Condition::eq);
|
||||
lsl(TMP2, TMP2, FCMP_FLAG_EQ);
|
||||
orr(Dst, Dst, TMP2);
|
||||
}
|
||||
if (Op->Flags & (1 << FCMP_FLAG_EQ)) {
|
||||
cset(TMP2, Condition::vs);
|
||||
lsl(TMP2, TMP2, FCMP_FLAG_EQ);
|
||||
orr(Dst, Dst, TMP2);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case IR::OP_GETHOSTFLAG: {
|
||||
auto Op = IROp->C<IR::IROp_GetHostFlag>();
|
||||
|
||||
ubfx(GetDst<RA_64>(Node), GetSrc<RA_64>(Op->Header.Args[0].ID()), Op->Flag, 1);
|
||||
break;
|
||||
}
|
||||
case IR::OP_VZIP: {
|
||||
auto Op = IROp->C<IR::IROp_VZip>();
|
||||
LogMan::Throw::A(Op->RegisterSize == 16, "Can't handle register size of: %d", Op->RegisterSize);
|
||||
|
||||
@@ -2796,7 +2796,47 @@ void *JITCore::CompileCode([[maybe_unused]] FEXCore::IR::IRListView<true> const
|
||||
}
|
||||
break;
|
||||
}
|
||||
case IR::OP_FCMP: {
|
||||
auto Op = IROp->C<IR::IROp_FCmp>();
|
||||
|
||||
if (Op->ElementSize == 4) {
|
||||
ucomiss(GetSrc(Op->Header.Args[0].ID()), GetSrc(Op->Header.Args[1].ID()));
|
||||
}
|
||||
else {
|
||||
ucomisd(GetSrc(Op->Header.Args[0].ID()), GetSrc(Op->Header.Args[1].ID()));
|
||||
}
|
||||
mov (rax, 0);
|
||||
|
||||
if (Op->Flags & (1 << FCMP_FLAG_LT)) {
|
||||
mov(rcx, 0);
|
||||
setb(cl);
|
||||
shl(rcx, FCMP_FLAG_LT);
|
||||
or(rax, rcx);
|
||||
}
|
||||
if (Op->Flags & (1 << FCMP_FLAG_UNORDERED)) {
|
||||
mov(rcx, 0);
|
||||
setp(cl);
|
||||
shl(rcx, FCMP_FLAG_UNORDERED);
|
||||
or(rax, rcx);
|
||||
}
|
||||
if (Op->Flags & (1 << FCMP_FLAG_EQ)) {
|
||||
mov(rcx, 0);
|
||||
setz(cl);
|
||||
shl(rcx, FCMP_FLAG_EQ);
|
||||
or(rax, rcx);
|
||||
}
|
||||
mov (GetDst<RA_64>(Node), rax);
|
||||
break;
|
||||
}
|
||||
case IR::OP_GETHOSTFLAG: {
|
||||
auto Op = IROp->C<IR::IROp_GetHostFlag>();
|
||||
|
||||
mov(rax, GetSrc<RA_64>(Op->Header.Args[0].ID()));
|
||||
shr(rax, Op->Flag);
|
||||
and(rax, 1);
|
||||
mov(GetDst<RA_64>(Node), rax);
|
||||
break;
|
||||
}
|
||||
case IR::OP_VZIP: {
|
||||
auto Op = IROp->C<IR::IROp_VZip>();
|
||||
movapd(xmm15, GetSrc(Op->Header.Args[0].ID()));
|
||||
|
||||
@@ -1806,6 +1806,47 @@ void LLVMJITCore::HandleIR(FEXCore::IR::IRListView<true> const *IR, IR::NodeWrap
|
||||
SetDest(*WrapperOp, Result);
|
||||
break;
|
||||
}
|
||||
case IR::OP_FCMP: {
|
||||
auto Op = IROp->C<IR::IROp_FCmp>();
|
||||
auto Src1 = GetSrc(Op->Header.Args[0]);
|
||||
auto Src2 = GetSrc(Op->Header.Args[1]);
|
||||
|
||||
// Cast to the type we want
|
||||
Src1 = CastScalarToType(Src1, false, OpSize * 8, Op->ElementSize);
|
||||
Src2 = CastScalarToType(Src2, false, OpSize * 8, Op->ElementSize);
|
||||
|
||||
llvm::Value *Result = JITState.IRBuilder->getInt64(0);
|
||||
if (Op->Flags & (1 << IR::FCMP_FLAG_LT)) {
|
||||
auto FCmp = JITState.IRBuilder->CreateFCmpOLT(Src1, Src2);
|
||||
FCmp = JITState.IRBuilder->CreateZExt(FCmp, Result->getType());
|
||||
FCmp = JITState.IRBuilder->CreateShl(FCmp, JITState.IRBuilder->getInt64(IR::FCMP_FLAG_LT));
|
||||
Result = JITState.IRBuilder->CreateOr(Result, FCmp);
|
||||
}
|
||||
if (Op->Flags & (1 << IR::FCMP_FLAG_UNORDERED)) {
|
||||
auto FCmp = JITState.IRBuilder->CreateFCmpUNO(Src1, Src2);
|
||||
FCmp = JITState.IRBuilder->CreateZExt(FCmp, Result->getType());
|
||||
FCmp = JITState.IRBuilder->CreateShl(FCmp, JITState.IRBuilder->getInt64(IR::FCMP_FLAG_UNORDERED));
|
||||
Result = JITState.IRBuilder->CreateOr(Result, FCmp);
|
||||
}
|
||||
if (Op->Flags & (1 << IR::FCMP_FLAG_EQ)) {
|
||||
auto FCmp = JITState.IRBuilder->CreateFCmpUEQ(Src1, Src2);
|
||||
FCmp = JITState.IRBuilder->CreateZExt(FCmp, Result->getType());
|
||||
FCmp = JITState.IRBuilder->CreateShl(FCmp, JITState.IRBuilder->getInt64(IR::FCMP_FLAG_EQ));
|
||||
Result = JITState.IRBuilder->CreateOr(Result, FCmp);
|
||||
}
|
||||
|
||||
SetDest(*WrapperOp, Result);
|
||||
break;
|
||||
}
|
||||
case IR::OP_GETHOSTFLAG: {
|
||||
auto Op = IROp->C<IR::IROp_GetHostFlag>();
|
||||
auto Src = GetSrc(Op->Header.Args[0]);
|
||||
auto Result = JITState.IRBuilder->CreateLShr(Src, JITState.IRBuilder->getInt64(Op->Flag));
|
||||
Result = JITState.IRBuilder->CreateAnd(Result, JITState.IRBuilder->getInt64(1));
|
||||
|
||||
SetDest(*WrapperOp, Result);
|
||||
break;
|
||||
}
|
||||
case IR::OP_CREATEVECTOR2: {
|
||||
auto Op = IROp->C<IR::IROp_CreateVector2>();
|
||||
LogMan::Throw::A(OpSize <= 16, "Can't handle a vector of size: %d", OpSize);
|
||||
|
||||
@@ -4409,6 +4409,31 @@ void OpDispatchBuilder::PAlignrOp(OpcodeArgs) {
|
||||
StoreResult(FPRClass, Op, Res, -1);
|
||||
}
|
||||
|
||||
template<size_t ElementSize>
|
||||
void OpDispatchBuilder::UCOMISxOp(OpcodeArgs) {
|
||||
OrderedNode *Src1 = LoadSource(FPRClass, Op, Op->Dest, Op->Flags, -1);
|
||||
OrderedNode *Src2 = LoadSource(FPRClass, Op, Op->Src[0], Op->Flags, -1);
|
||||
OrderedNode *Res = _FCmp(Src1, Src2, ElementSize,
|
||||
(1 << FCMP_FLAG_EQ) |
|
||||
(1 << FCMP_FLAG_LT) |
|
||||
(1 << FCMP_FLAG_UNORDERED));
|
||||
|
||||
OrderedNode *HostFlag_CF = _GetHostFlag(Res, FCMP_FLAG_LT);
|
||||
OrderedNode *HostFlag_ZF = _GetHostFlag(Res, FCMP_FLAG_EQ);
|
||||
OrderedNode *HostFlag_Unordered = _GetHostFlag(Res, FCMP_FLAG_UNORDERED);
|
||||
HostFlag_CF = _Or(HostFlag_CF, HostFlag_Unordered);
|
||||
HostFlag_ZF = _Or(HostFlag_ZF, HostFlag_Unordered);
|
||||
|
||||
SetRFLAG<FEXCore::X86State::RFLAG_CF_LOC>(HostFlag_CF);
|
||||
SetRFLAG<FEXCore::X86State::RFLAG_ZF_LOC>(HostFlag_ZF);
|
||||
SetRFLAG<FEXCore::X86State::RFLAG_PF_LOC>(HostFlag_Unordered);
|
||||
|
||||
auto ZeroConst = _Constant(0);
|
||||
SetRFLAG<FEXCore::X86State::RFLAG_AF_LOC>(ZeroConst);
|
||||
SetRFLAG<FEXCore::X86State::RFLAG_SF_LOC>(ZeroConst);
|
||||
SetRFLAG<FEXCore::X86State::RFLAG_OF_LOC>(ZeroConst);
|
||||
}
|
||||
|
||||
void OpDispatchBuilder::LDMXCSR(OpcodeArgs) {
|
||||
}
|
||||
|
||||
@@ -4647,6 +4672,7 @@ void InstallOpcodeHandlers() {
|
||||
{0x16, 1, &OpDispatchBuilder::MOVLHPSOp},
|
||||
{0x17, 1, &OpDispatchBuilder::MOVUPSOp},
|
||||
{0x28, 2, &OpDispatchBuilder::MOVUPSOp},
|
||||
{0x2E, 2, &OpDispatchBuilder::UCOMISxOp<4>},
|
||||
{0x50, 1, &OpDispatchBuilder::MOVMSKOp<4>},
|
||||
{0x51, 1, &OpDispatchBuilder::VectorUnaryOp<IR::OP_VFSQRT, 4, false>},
|
||||
{0x52, 1, &OpDispatchBuilder::VectorUnaryOp<IR::OP_VFRSQRT, 4, false>},
|
||||
@@ -4831,6 +4857,7 @@ void InstallOpcodeHandlers() {
|
||||
{0x16, 2, &OpDispatchBuilder::MOVHPDOp},
|
||||
{0x19, 7, &OpDispatchBuilder::NOPOp},
|
||||
{0x28, 2, &OpDispatchBuilder::MOVAPSOp},
|
||||
{0x2E, 2, &OpDispatchBuilder::UCOMISxOp<8>},
|
||||
|
||||
{0x40, 16, &OpDispatchBuilder::CMOVOp},
|
||||
{0x50, 1, &OpDispatchBuilder::MOVMSKOp<8>},
|
||||
|
||||
@@ -269,6 +269,8 @@ public:
|
||||
void FXRStoreOp(OpcodeArgs);
|
||||
|
||||
void PAlignrOp(OpcodeArgs);
|
||||
template<size_t ElementSize>
|
||||
void UCOMISxOp(OpcodeArgs);
|
||||
void LDMXCSR(OpcodeArgs);
|
||||
void STMXCSR(OpcodeArgs);
|
||||
|
||||
|
||||
@@ -44,8 +44,8 @@ void InitializeSecondaryTables() {
|
||||
{0x2B, 1, X86InstInfo{"MOVNTPS", TYPE_INST, GenFlagsSameSize(SIZE_128BIT) | FLAGS_MODRM | FLAGS_SF_MOD_MEM_ONLY | FLAGS_SF_MOD_DST | FLAGS_XMM_FLAGS, 0, nullptr}},
|
||||
{0x2C, 1, X86InstInfo{"CVTTPS2PI", TYPE_MMX, GenFlagsSameSize(SIZE_64BIT) | FLAGS_MODRM | FLAGS_XMM_FLAGS, 0, nullptr}},
|
||||
{0x2D, 1, X86InstInfo{"CVTPS2PI", TYPE_MMX, GenFlagsSameSize(SIZE_64BIT) | FLAGS_MODRM | FLAGS_XMM_FLAGS, 0, nullptr}},
|
||||
{0x2E, 1, X86InstInfo{"UCOMISS", TYPE_INST, FLAGS_MODRM | FLAGS_XMM_FLAGS, 0, nullptr}},
|
||||
{0x2F, 1, X86InstInfo{"COMISS", TYPE_INST, FLAGS_MODRM | FLAGS_XMM_FLAGS, 0, nullptr}},
|
||||
{0x2E, 1, X86InstInfo{"UCOMISS", TYPE_INST, GenFlagsSameSize(SIZE_128BIT) | FLAGS_MODRM | FLAGS_XMM_FLAGS, 0, nullptr}},
|
||||
{0x2F, 1, X86InstInfo{"COMISS", TYPE_INST, GenFlagsSameSize(SIZE_128BIT) | FLAGS_MODRM | FLAGS_XMM_FLAGS, 0, nullptr}},
|
||||
|
||||
{0x30, 1, X86InstInfo{"WRMSR", TYPE_PRIV, FLAGS_NO_OVERLAY, 0, nullptr}},
|
||||
{0x31, 1, X86InstInfo{"RDTSC", TYPE_INST, FLAGS_DEBUG | FLAGS_NO_OVERLAY, 0, nullptr}},
|
||||
@@ -426,8 +426,8 @@ void InitializeSecondaryTables() {
|
||||
{0x2B, 1, X86InstInfo{"MOVNTPD", TYPE_INST, GenFlagsSameSize(SIZE_128BIT) | FLAGS_MODRM | FLAGS_SF_MOD_MEM_ONLY | FLAGS_SF_MOD_DST | FLAGS_XMM_FLAGS, 0, nullptr}},
|
||||
{0x2C, 1, X86InstInfo{"CVTTPD2PI", TYPE_MMX, GenFlagsSameSize(SIZE_128BIT) | FLAGS_MODRM | FLAGS_XMM_FLAGS, 0, nullptr}},
|
||||
{0x2D, 1, X86InstInfo{"CVTPD2PI", TYPE_MMX, GenFlagsSameSize(SIZE_128BIT) | FLAGS_MODRM | FLAGS_XMM_FLAGS, 0, nullptr}},
|
||||
{0x2E, 1, X86InstInfo{"UCOMISD", TYPE_INST, GenFlagsSameSize(SIZE_64BIT) | FLAGS_MODRM | FLAGS_XMM_FLAGS, 0, nullptr}},
|
||||
{0x2F, 1, X86InstInfo{"COMISD", TYPE_INST, GenFlagsSameSize(SIZE_64BIT) | FLAGS_MODRM | FLAGS_XMM_FLAGS, 0, nullptr}},
|
||||
{0x2E, 1, X86InstInfo{"UCOMISD", TYPE_INST, GenFlagsSameSize(SIZE_128BIT) | FLAGS_MODRM | FLAGS_XMM_FLAGS, 0, nullptr}},
|
||||
{0x2F, 1, X86InstInfo{"COMISD", TYPE_INST, GenFlagsSameSize(SIZE_128BIT) | FLAGS_MODRM | FLAGS_XMM_FLAGS, 0, nullptr}},
|
||||
|
||||
{0x30, 16, X86InstInfo{"", TYPE_COPY_OTHER, FLAGS_NONE, 0, nullptr}},
|
||||
{0x40, 16, X86InstInfo{"", TYPE_COPY_OTHER, FLAGS_NONE, 0, nullptr}},
|
||||
|
||||
+39
-1
@@ -15,7 +15,11 @@
|
||||
"constexpr static uint8_t COND_SGT = 12",
|
||||
"constexpr static uint8_t COND_SLE = 13",
|
||||
"static constexpr FEXCore::IR::RegisterClassType GPRClass {0}",
|
||||
"static constexpr FEXCore::IR::RegisterClassType FPRClass {1}"
|
||||
"static constexpr FEXCore::IR::RegisterClassType FPRClass {1}",
|
||||
|
||||
"constexpr static uint8_t FCMP_FLAG_EQ = 0",
|
||||
"constexpr static uint8_t FCMP_FLAG_LT = 1",
|
||||
"constexpr static uint8_t FCMP_FLAG_UNORDERED = 2"
|
||||
],
|
||||
|
||||
"Ops": {
|
||||
@@ -562,6 +566,24 @@
|
||||
]
|
||||
},
|
||||
|
||||
"ExtractElement": {
|
||||
"HasDest": true,
|
||||
"DestSize": "GetOpSize(ssa0)",
|
||||
"SSAArgs": "1",
|
||||
"Args": [
|
||||
"uint8_t", "Idx"
|
||||
]
|
||||
},
|
||||
|
||||
"FCmp": {
|
||||
"HasDest": true,
|
||||
"SSAArgs": "2",
|
||||
"Args": [
|
||||
"uint8_t", "ElementSize",
|
||||
"uint32_t", "Flags"
|
||||
]
|
||||
},
|
||||
|
||||
"Print": {
|
||||
"SSAArgs": "1"
|
||||
},
|
||||
@@ -1241,6 +1263,22 @@
|
||||
]
|
||||
},
|
||||
|
||||
"GetHostFlag": {
|
||||
"HasDest": true,
|
||||
"SSAArgs": "1",
|
||||
"Args": [
|
||||
"uint8_t", "Flag"
|
||||
]
|
||||
},
|
||||
|
||||
"CreatesFlags": {
|
||||
"HasDest": true,
|
||||
"SSAArgs": "1",
|
||||
"Args": [
|
||||
"uint32_t", "Flags"
|
||||
]
|
||||
},
|
||||
|
||||
"Last": {
|
||||
"Last": true,
|
||||
"Args": []
|
||||
|
||||
@@ -238,7 +238,9 @@ namespace {
|
||||
return GetRegClassFromNode(ListBegin, DataBegin, Op->PhiBegin);
|
||||
}
|
||||
default:
|
||||
if (IROp->Op > IR::OP_PRINT)
|
||||
if (IROp->Op >= IR::OP_GETHOSTFLAG)
|
||||
return IR::RegisterAllocationPass::FLAGSClass;
|
||||
else if (IROp->Op > IR::OP_PRINT)
|
||||
return IR::RegisterAllocationPass::FPRClass;
|
||||
else
|
||||
return IR::RegisterAllocationPass::GPRClass;
|
||||
|
||||
@@ -9,6 +9,7 @@ class RegisterAllocationPass : public FEXCore::IR::Pass {
|
||||
public:
|
||||
static constexpr uint32_t GPRClass = 0;
|
||||
static constexpr uint32_t FPRClass = 1;
|
||||
static constexpr uint32_t FLAGSClass = 2;
|
||||
|
||||
bool HasFullRA() const { return HadFullRA; }
|
||||
uint32_t SpillSlots() const { return SpillSlotCount; }
|
||||
|
||||
Reference in new issue
Block a user