Merge pull request #65 from Sonicadvance1/comiss

Implements the COMISS instructions
This commit is contained in:
Stefanos Kornilios Mitsis Poiitidis authored and GitHub committed 2020-03-22 08:57:17 +02:00
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
View File
@@ -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; }