Modified: trunk/Source/_javascript_Core/assembler/MacroAssemblerARM64.h (258037 => 258038)
--- trunk/Source/_javascript_Core/assembler/MacroAssemblerARM64.h 2020-03-07 01:14:23 UTC (rev 258037)
+++ trunk/Source/_javascript_Core/assembler/MacroAssemblerARM64.h 2020-03-07 01:16:14 UTC (rev 258038)
@@ -2028,18 +2028,35 @@
void moveConditionallyAfterFloatingPointCompare(DoubleCondition cond, RegisterID thenCase, RegisterID elseCase, RegisterID dest)
{
if (cond == DoubleNotEqual) {
- Jump unordered = makeBranch(Assembler::ConditionVS);
- m_assembler.csel<datasize>(dest, thenCase, elseCase, Assembler::ConditionNE);
- unordered.link(this);
+ if (dest == thenCase) {
+ // If the compare is unordered, elseCase is copied to thenCase and the
+ // next csel has all arguments equal to elseCase.
+ // If the compare is ordered, dest is unchanged and NE decides
+ // what value to set.
+ m_assembler.csel<datasize>(thenCase, elseCase, thenCase, Assembler::ConditionNE);
+ m_assembler.csel<datasize>(dest, thenCase, elseCase, Assembler::ConditionNE);
+ } else {
+ move(elseCase, dest);
+ Jump unordered = makeBranch(Assembler::ConditionVS);
+ m_assembler.csel<datasize>(dest, thenCase, elseCase, Assembler::ConditionNE);
+ unordered.link(this);
+ }
return;
}
if (cond == DoubleEqualOrUnordered) {
- // If the compare is unordered, thenCase is copied to elseCase and the
- // next csel has all arguments equal to thenCase.
- // If the compare is ordered, dest is unchanged and EQ decides
- // what value to set.
- m_assembler.csel<datasize>(elseCase, thenCase, elseCase, Assembler::ConditionVS);
- m_assembler.csel<datasize>(dest, thenCase, elseCase, Assembler::ConditionEQ);
+ if (dest == elseCase) {
+ // If the compare is unordered, thenCase is copied to elseCase and the
+ // next csel has all arguments equal to thenCase.
+ // If the compare is ordered, dest is unchanged and EQ decides
+ // what value to set.
+ m_assembler.csel<datasize>(elseCase, thenCase, elseCase, Assembler::ConditionVS);
+ m_assembler.csel<datasize>(dest, thenCase, elseCase, Assembler::ConditionEQ);
+ } else {
+ move(thenCase, dest);
+ Jump unordered = makeBranch(Assembler::ConditionVS);
+ m_assembler.csel<datasize>(dest, thenCase, elseCase, Assembler::ConditionEQ);
+ unordered.link(this);
+ }
return;
}
m_assembler.csel<datasize>(dest, thenCase, elseCase, ARM64Condition(cond));
@@ -2049,18 +2066,35 @@
void moveDoubleConditionallyAfterFloatingPointCompare(DoubleCondition cond, FPRegisterID thenCase, FPRegisterID elseCase, FPRegisterID dest)
{
if (cond == DoubleNotEqual) {
- Jump unordered = makeBranch(Assembler::ConditionVS);
- m_assembler.fcsel<datasize>(dest, thenCase, elseCase, Assembler::ConditionNE);
- unordered.link(this);
+ if (dest == thenCase) {
+ // If the compare is unordered, elseCase is copied to thenCase and the
+ // next fcsel has all arguments equal to elseCase.
+ // If the compare is ordered, dest is unchanged and NE decides
+ // what value to set.
+ m_assembler.fcsel<datasize>(thenCase, elseCase, thenCase, Assembler::ConditionVS);
+ m_assembler.fcsel<datasize>(dest, thenCase, elseCase, Assembler::ConditionNE);
+ } else {
+ m_assembler.fmov<64>(dest, elseCase);
+ Jump unordered = makeBranch(Assembler::ConditionVS);
+ m_assembler.fcsel<datasize>(dest, thenCase, elseCase, Assembler::ConditionNE);
+ unordered.link(this);
+ }
return;
}
if (cond == DoubleEqualOrUnordered) {
- // If the compare is unordered, thenCase is copied to elseCase and the
- // next csel has all arguments equal to thenCase.
- // If the compare is ordered, dest is unchanged and EQ decides
- // what value to set.
- m_assembler.fcsel<datasize>(elseCase, thenCase, elseCase, Assembler::ConditionVS);
- m_assembler.fcsel<datasize>(dest, thenCase, elseCase, Assembler::ConditionEQ);
+ if (dest == elseCase) {
+ // If the compare is unordered, thenCase is copied to elseCase and the
+ // next csel has all arguments equal to thenCase.
+ // If the compare is ordered, dest is unchanged and EQ decides
+ // what value to set.
+ m_assembler.fcsel<datasize>(elseCase, thenCase, elseCase, Assembler::ConditionVS);
+ m_assembler.fcsel<datasize>(dest, thenCase, elseCase, Assembler::ConditionEQ);
+ } else {
+ m_assembler.fmov<64>(dest, thenCase);
+ Jump unordered = makeBranch(Assembler::ConditionVS);
+ m_assembler.fcsel<datasize>(dest, thenCase, elseCase, Assembler::ConditionEQ);
+ unordered.link(this);
+ }
return;
}
m_assembler.fcsel<datasize>(dest, thenCase, elseCase, ARM64Condition(cond));
Modified: trunk/Source/_javascript_Core/assembler/testmasm.cpp (258037 => 258038)
--- trunk/Source/_javascript_Core/assembler/testmasm.cpp 2020-03-07 01:14:23 UTC (rev 258037)
+++ trunk/Source/_javascript_Core/assembler/testmasm.cpp 2020-03-07 01:16:14 UTC (rev 258038)
@@ -499,16 +499,117 @@
jit.ret();
});
+ auto expectedResult = [&, condition] (double a, double b) -> int {
+ auto isUnordered = [] (double x) {
+ return x != x;
+ };
+ switch (condition) {
+ case MacroAssembler::DoubleEqual:
+ return !isUnordered(a) && !isUnordered(b) && (a == b);
+ case MacroAssembler::DoubleNotEqual:
+ return !isUnordered(a) && !isUnordered(b) && (a != b);
+ case MacroAssembler::DoubleGreaterThan:
+ return !isUnordered(a) && !isUnordered(b) && (a > b);
+ case MacroAssembler::DoubleGreaterThanOrEqual:
+ return !isUnordered(a) && !isUnordered(b) && (a >= b);
+ case MacroAssembler::DoubleLessThan:
+ return !isUnordered(a) && !isUnordered(b) && (a < b);
+ case MacroAssembler::DoubleLessThanOrEqual:
+ return !isUnordered(a) && !isUnordered(b) && (a <= b);
+ case MacroAssembler::DoubleEqualOrUnordered:
+ return isUnordered(a) || isUnordered(b) || (a == b);
+ case MacroAssembler::DoubleNotEqualOrUnordered:
+ return isUnordered(a) || isUnordered(b) || (a != b);
+ case MacroAssembler::DoubleGreaterThanOrUnordered:
+ return isUnordered(a) || isUnordered(b) || (a > b);
+ case MacroAssembler::DoubleGreaterThanOrEqualOrUnordered:
+ return isUnordered(a) || isUnordered(b) || (a >= b);
+ case MacroAssembler::DoubleLessThanOrUnordered:
+ return isUnordered(a) || isUnordered(b) || (a < b);
+ case MacroAssembler::DoubleLessThanOrEqualOrUnordered:
+ return isUnordered(a) || isUnordered(b) || (a <= b);
+ } // switch
+ };
+
auto operands = doubleOperands();
for (auto a : operands) {
for (auto b : operands) {
arg1 = a;
arg2 = b;
- CHECK_EQ(invoke<int>(compareDouble), invoke<int>(compareDoubleGeneric));
+ CHECK_EQ(invoke<int>(compareDouble), expectedResult(a, b));
+ CHECK_EQ(invoke<int>(compareDoubleGeneric), expectedResult(a, b));
}
}
}
+void testCompareDoubleSameArg(MacroAssembler::DoubleCondition condition)
+{
+ double arg1 = 0;
+
+ auto compareDouble = compile([&, condition] (CCallHelpers& jit) {
+ emitFunctionPrologue(jit);
+
+ jit.loadDouble(CCallHelpers::TrustedImmPtr(&arg1), FPRInfo::fpRegT0);
+ jit.move(CCallHelpers::TrustedImm32(-1), GPRInfo::returnValueGPR);
+ jit.compareDouble(condition, FPRInfo::fpRegT0, FPRInfo::fpRegT0, GPRInfo::returnValueGPR);
+
+ emitFunctionEpilogue(jit);
+ jit.ret();
+ });
+
+ auto compareDoubleGeneric = compile([&, condition] (CCallHelpers& jit) {
+ emitFunctionPrologue(jit);
+
+ jit.loadDouble(CCallHelpers::TrustedImmPtr(&arg1), FPRInfo::fpRegT0);
+ jit.move(CCallHelpers::TrustedImm32(1), GPRInfo::returnValueGPR);
+ auto jump = jit.branchDouble(condition, FPRInfo::fpRegT0, FPRInfo::fpRegT0);
+ jit.move(CCallHelpers::TrustedImm32(0), GPRInfo::returnValueGPR);
+ jump.link(&jit);
+
+ emitFunctionEpilogue(jit);
+ jit.ret();
+ });
+
+ auto expectedResult = [&, condition] (double a) -> int {
+ auto isUnordered = [] (double x) {
+ return x != x;
+ };
+ switch (condition) {
+ case MacroAssembler::DoubleEqual:
+ return !isUnordered(a) && (a == a);
+ case MacroAssembler::DoubleNotEqual:
+ return !isUnordered(a) && (a != a);
+ case MacroAssembler::DoubleGreaterThan:
+ return !isUnordered(a) && (a > a);
+ case MacroAssembler::DoubleGreaterThanOrEqual:
+ return !isUnordered(a) && (a >= a);
+ case MacroAssembler::DoubleLessThan:
+ return !isUnordered(a) && (a < a);
+ case MacroAssembler::DoubleLessThanOrEqual:
+ return !isUnordered(a) && (a <= a);
+ case MacroAssembler::DoubleEqualOrUnordered:
+ return isUnordered(a) || (a == a);
+ case MacroAssembler::DoubleNotEqualOrUnordered:
+ return isUnordered(a) || (a != a);
+ case MacroAssembler::DoubleGreaterThanOrUnordered:
+ return isUnordered(a) || (a > a);
+ case MacroAssembler::DoubleGreaterThanOrEqualOrUnordered:
+ return isUnordered(a) || (a >= a);
+ case MacroAssembler::DoubleLessThanOrUnordered:
+ return isUnordered(a) || (a < a);
+ case MacroAssembler::DoubleLessThanOrEqualOrUnordered:
+ return isUnordered(a) || (a <= a);
+ } // switch
+ };
+
+ auto operands = doubleOperands();
+ for (auto a : operands) {
+ arg1 = a;
+ CHECK_EQ(invoke<int>(compareDouble), expectedResult(a));
+ CHECK_EQ(invoke<int>(compareDoubleGeneric), expectedResult(a));
+ }
+}
+
void testMul32WithImmediates()
{
for (auto immediate : int32Operands()) {
@@ -586,8 +687,769 @@
}
}
}
-#endif
+#endif // CPU(X86) || CPU(X86_64) || CPU(ARM64)
+#if CPU(X86_64) || CPU(ARM64)
+
+template<typename T, typename SelectionType>
+void testMoveConditionallyFloatingPoint(MacroAssembler::DoubleCondition condition, const MacroAssemblerCodeRef<JSEntryPtrTag>& testCode, T& arg1, T& arg2, const Vector<T> operands, SelectionType selectionA, SelectionType selectionB)
+{
+ auto expectedResult = [&, condition] (T a, T b) -> SelectionType {
+ auto isUnordered = [] (double x) {
+ return x != x;
+ };
+ switch (condition) {
+ case MacroAssembler::DoubleEqual:
+ return !isUnordered(a) && !isUnordered(b) && (a == b) ? selectionA : selectionB;
+ case MacroAssembler::DoubleNotEqual:
+ return !isUnordered(a) && !isUnordered(b) && (a != b) ? selectionA : selectionB;
+ case MacroAssembler::DoubleGreaterThan:
+ return !isUnordered(a) && !isUnordered(b) && (a > b) ? selectionA : selectionB;
+ case MacroAssembler::DoubleGreaterThanOrEqual:
+ return !isUnordered(a) && !isUnordered(b) && (a >= b) ? selectionA : selectionB;
+ case MacroAssembler::DoubleLessThan:
+ return !isUnordered(a) && !isUnordered(b) && (a < b) ? selectionA : selectionB;
+ case MacroAssembler::DoubleLessThanOrEqual:
+ return !isUnordered(a) && !isUnordered(b) && (a <= b) ? selectionA : selectionB;
+ case MacroAssembler::DoubleEqualOrUnordered:
+ return isUnordered(a) || isUnordered(b) || (a == b) ? selectionA : selectionB;
+ case MacroAssembler::DoubleNotEqualOrUnordered:
+ return isUnordered(a) || isUnordered(b) || (a != b) ? selectionA : selectionB;
+ case MacroAssembler::DoubleGreaterThanOrUnordered:
+ return isUnordered(a) || isUnordered(b) || (a > b) ? selectionA : selectionB;
+ case MacroAssembler::DoubleGreaterThanOrEqualOrUnordered:
+ return isUnordered(a) || isUnordered(b) || (a >= b) ? selectionA : selectionB;
+ case MacroAssembler::DoubleLessThanOrUnordered:
+ return isUnordered(a) || isUnordered(b) || (a < b) ? selectionA : selectionB;
+ case MacroAssembler::DoubleLessThanOrEqualOrUnordered:
+ return isUnordered(a) || isUnordered(b) || (a <= b) ? selectionA : selectionB;
+ } // switch
+ };
+
+ for (auto a : operands) {
+ for (auto b : operands) {
+ arg1 = a;
+ arg2 = b;
+ CHECK_EQ(invoke<SelectionType>(testCode), expectedResult(a, b));
+ }
+ }
+}
+
+void testMoveConditionallyDouble2(MacroAssembler::DoubleCondition condition)
+{
+ double arg1 = 0;
+ double arg2 = 0;
+ unsigned selectionA = 42;
+ unsigned selectionB = 17;
+
+ auto testCode = compile([&, condition] (CCallHelpers& jit) {
+ emitFunctionPrologue(jit);
+
+ GPRReg destGPR = GPRInfo::returnValueGPR;
+ GPRReg selectionAGPR = GPRInfo::argumentGPR2;
+ RELEASE_ASSERT(destGPR != selectionAGPR);
+ jit.move(CCallHelpers::TrustedImm32(selectionA), selectionAGPR);
+ jit.move(CCallHelpers::TrustedImm32(selectionB), destGPR);
+
+ jit.loadDouble(CCallHelpers::TrustedImmPtr(&arg1), FPRInfo::fpRegT0);
+ jit.loadDouble(CCallHelpers::TrustedImmPtr(&arg2), FPRInfo::fpRegT1);
+ jit.moveConditionallyDouble(condition, FPRInfo::fpRegT0, FPRInfo::fpRegT1, selectionAGPR, destGPR);
+
+ emitFunctionEpilogue(jit);
+ jit.ret();
+ });
+
+ testMoveConditionallyFloatingPoint(condition, testCode, arg1, arg2, doubleOperands(), selectionA, selectionB);
+}
+
+void testMoveConditionallyDouble3(MacroAssembler::DoubleCondition condition)
+{
+ double arg1 = 0;
+ double arg2 = 0;
+ unsigned selectionA = 42;
+ unsigned selectionB = 17;
+ unsigned corruptedSelectionA = 0xbbad000a;
+ unsigned corruptedSelectionB = 0xbbad000b;
+
+ auto testCode = compile([&, condition] (CCallHelpers& jit) {
+ emitFunctionPrologue(jit);
+
+ GPRReg destGPR = GPRInfo::returnValueGPR;
+ GPRReg selectionAGPR = GPRInfo::argumentGPR2;
+ GPRReg selectionBGPR = GPRInfo::argumentGPR3;
+ RELEASE_ASSERT(destGPR != selectionAGPR);
+ RELEASE_ASSERT(destGPR != selectionBGPR);
+ jit.move(CCallHelpers::TrustedImm32(selectionA), selectionAGPR);
+ jit.move(CCallHelpers::TrustedImm32(selectionB), selectionBGPR);
+ jit.move(CCallHelpers::TrustedImm32(-1), destGPR);
+
+ jit.loadDouble(CCallHelpers::TrustedImmPtr(&arg1), FPRInfo::fpRegT0);
+ jit.loadDouble(CCallHelpers::TrustedImmPtr(&arg2), FPRInfo::fpRegT1);
+ jit.moveConditionallyDouble(condition, FPRInfo::fpRegT0, FPRInfo::fpRegT1, selectionAGPR, selectionBGPR, destGPR);
+
+ auto aIsUnchanged = jit.branch32(CCallHelpers::Equal, selectionAGPR, CCallHelpers::TrustedImm32(selectionA));
+ jit.move(CCallHelpers::TrustedImm32(corruptedSelectionA), destGPR);
+ aIsUnchanged.link(&jit);
+
+ auto bIsUnchanged = jit.branch32(CCallHelpers::Equal, selectionBGPR, CCallHelpers::TrustedImm32(selectionB));
+ jit.move(CCallHelpers::TrustedImm32(corruptedSelectionB), destGPR);
+ bIsUnchanged.link(&jit);
+
+ emitFunctionEpilogue(jit);
+ jit.ret();
+ });
+
+ testMoveConditionallyFloatingPoint(condition, testCode, arg1, arg2, doubleOperands(), selectionA, selectionB);
+}
+
+void testMoveConditionallyDouble3DestSameAsThenCase(MacroAssembler::DoubleCondition condition)
+{
+ double arg1 = 0;
+ double arg2 = 0;
+ unsigned selectionA = 42;
+ unsigned selectionB = 17;
+ unsigned corruptedSelectionB = 0xbbad000b;
+
+ auto testCode = compile([&, condition] (CCallHelpers& jit) {
+ emitFunctionPrologue(jit);
+
+ GPRReg destGPR = GPRInfo::returnValueGPR;
+ GPRReg selectionAGPR = destGPR;
+ GPRReg selectionBGPR = GPRInfo::argumentGPR3;
+ RELEASE_ASSERT(destGPR == selectionAGPR);
+ RELEASE_ASSERT(destGPR != selectionBGPR);
+ jit.move(CCallHelpers::TrustedImm32(selectionA), selectionAGPR);
+ jit.move(CCallHelpers::TrustedImm32(selectionB), selectionBGPR);
+
+ jit.loadDouble(CCallHelpers::TrustedImmPtr(&arg1), FPRInfo::fpRegT0);
+ jit.loadDouble(CCallHelpers::TrustedImmPtr(&arg2), FPRInfo::fpRegT1);
+ jit.moveConditionallyDouble(condition, FPRInfo::fpRegT0, FPRInfo::fpRegT1, selectionAGPR, selectionBGPR, destGPR);
+
+ auto bIsUnchanged = jit.branch32(CCallHelpers::Equal, selectionBGPR, CCallHelpers::TrustedImm32(selectionB));
+ jit.move(CCallHelpers::TrustedImm32(corruptedSelectionB), destGPR);
+ bIsUnchanged.link(&jit);
+
+ emitFunctionEpilogue(jit);
+ jit.ret();
+ });
+
+ testMoveConditionallyFloatingPoint(condition, testCode, arg1, arg2, doubleOperands(), selectionA, selectionB);
+}
+
+void testMoveConditionallyDouble3DestSameAsElseCase(MacroAssembler::DoubleCondition condition)
+{
+ double arg1 = 0;
+ double arg2 = 0;
+ unsigned selectionA = 42;
+ unsigned selectionB = 17;
+ unsigned corruptedSelectionA = 0xbbad000a;
+
+ auto testCode = compile([&, condition] (CCallHelpers& jit) {
+ emitFunctionPrologue(jit);
+
+ GPRReg destGPR = GPRInfo::returnValueGPR;
+ GPRReg selectionAGPR = GPRInfo::argumentGPR2;
+ GPRReg selectionBGPR = destGPR;
+ RELEASE_ASSERT(destGPR != selectionAGPR);
+ RELEASE_ASSERT(destGPR == selectionBGPR);
+ jit.move(CCallHelpers::TrustedImm32(selectionA), selectionAGPR);
+ jit.move(CCallHelpers::TrustedImm32(selectionB), selectionBGPR);
+
+ jit.loadDouble(CCallHelpers::TrustedImmPtr(&arg1), FPRInfo::fpRegT0);
+ jit.loadDouble(CCallHelpers::TrustedImmPtr(&arg2), FPRInfo::fpRegT1);
+ jit.moveConditionallyDouble(condition, FPRInfo::fpRegT0, FPRInfo::fpRegT1, selectionAGPR, selectionBGPR, destGPR);
+
+ auto aIsUnchanged = jit.branch32(CCallHelpers::Equal, selectionAGPR, CCallHelpers::TrustedImm32(selectionA));
+ jit.move(CCallHelpers::TrustedImm32(corruptedSelectionA), destGPR);
+ aIsUnchanged.link(&jit);
+
+ emitFunctionEpilogue(jit);
+ jit.ret();
+ });
+
+ testMoveConditionallyFloatingPoint(condition, testCode, arg1, arg2, doubleOperands(), selectionA, selectionB);
+}
+
+void testMoveConditionallyFloat2(MacroAssembler::DoubleCondition condition)
+{
+ float arg1 = 0;
+ float arg2 = 0;
+ unsigned selectionA = 42;
+ unsigned selectionB = 17;
+
+ auto testCode = compile([&, condition] (CCallHelpers& jit) {
+ emitFunctionPrologue(jit);
+
+ GPRReg destGPR = GPRInfo::returnValueGPR;
+ GPRReg selectionAGPR = GPRInfo::argumentGPR2;
+ RELEASE_ASSERT(destGPR != selectionAGPR);
+ jit.move(CCallHelpers::TrustedImm32(selectionA), selectionAGPR);
+ jit.move(CCallHelpers::TrustedImm32(selectionB), GPRInfo::returnValueGPR);
+
+ jit.loadFloat(CCallHelpers::TrustedImmPtr(&arg1), FPRInfo::fpRegT0);
+ jit.loadFloat(CCallHelpers::TrustedImmPtr(&arg2), FPRInfo::fpRegT1);
+ jit.moveConditionallyFloat(condition, FPRInfo::fpRegT0, FPRInfo::fpRegT1, selectionAGPR, destGPR);
+
+ emitFunctionEpilogue(jit);
+ jit.ret();
+ });
+
+ testMoveConditionallyFloatingPoint(condition, testCode, arg1, arg2, floatOperands(), selectionA, selectionB);
+}
+
+void testMoveConditionallyFloat3(MacroAssembler::DoubleCondition condition)
+{
+ float arg1 = 0;
+ float arg2 = 0;
+ unsigned selectionA = 42;
+ unsigned selectionB = 17;
+ unsigned corruptedSelectionA = 0xbbad000a;
+ unsigned corruptedSelectionB = 0xbbad000b;
+
+ auto testCode = compile([&, condition] (CCallHelpers& jit) {
+ emitFunctionPrologue(jit);
+
+ GPRReg destGPR = GPRInfo::returnValueGPR;
+ GPRReg selectionAGPR = GPRInfo::argumentGPR2;
+ GPRReg selectionBGPR = GPRInfo::argumentGPR3;
+ RELEASE_ASSERT(destGPR != selectionAGPR);
+ RELEASE_ASSERT(destGPR != selectionBGPR);
+ jit.move(CCallHelpers::TrustedImm32(selectionA), selectionAGPR);
+ jit.move(CCallHelpers::TrustedImm32(selectionB), selectionBGPR);
+ jit.move(CCallHelpers::TrustedImm32(-1), destGPR);
+
+ jit.loadFloat(CCallHelpers::TrustedImmPtr(&arg1), FPRInfo::fpRegT0);
+ jit.loadFloat(CCallHelpers::TrustedImmPtr(&arg2), FPRInfo::fpRegT1);
+ jit.moveConditionallyFloat(condition, FPRInfo::fpRegT0, FPRInfo::fpRegT1, selectionAGPR, selectionBGPR, destGPR);
+
+ auto aIsUnchanged = jit.branch32(CCallHelpers::Equal, selectionAGPR, CCallHelpers::TrustedImm32(selectionA));
+ jit.move(CCallHelpers::TrustedImm32(corruptedSelectionA), destGPR);
+ aIsUnchanged.link(&jit);
+
+ auto bIsUnchanged = jit.branch32(CCallHelpers::Equal, selectionBGPR, CCallHelpers::TrustedImm32(selectionB));
+ jit.move(CCallHelpers::TrustedImm32(corruptedSelectionB), destGPR);
+ bIsUnchanged.link(&jit);
+
+ emitFunctionEpilogue(jit);
+ jit.ret();
+ });
+
+ testMoveConditionallyFloatingPoint(condition, testCode, arg1, arg2, floatOperands(), selectionA, selectionB);
+}
+
+void testMoveConditionallyFloat3DestSameAsThenCase(MacroAssembler::DoubleCondition condition)
+{
+ float arg1 = 0;
+ float arg2 = 0;
+ unsigned selectionA = 42;
+ unsigned selectionB = 17;
+ unsigned corruptedSelectionB = 0xbbad000b;
+
+ auto testCode = compile([&, condition] (CCallHelpers& jit) {
+ emitFunctionPrologue(jit);
+
+ GPRReg destGPR = GPRInfo::returnValueGPR;
+ GPRReg selectionAGPR = destGPR;
+ GPRReg selectionBGPR = GPRInfo::argumentGPR3;
+ RELEASE_ASSERT(destGPR == selectionAGPR);
+ RELEASE_ASSERT(destGPR != selectionBGPR);
+ jit.move(CCallHelpers::TrustedImm32(selectionA), selectionAGPR);
+ jit.move(CCallHelpers::TrustedImm32(selectionB), selectionBGPR);
+
+ jit.loadFloat(CCallHelpers::TrustedImmPtr(&arg1), FPRInfo::fpRegT0);
+ jit.loadFloat(CCallHelpers::TrustedImmPtr(&arg2), FPRInfo::fpRegT1);
+ jit.moveConditionallyFloat(condition, FPRInfo::fpRegT0, FPRInfo::fpRegT1, selectionAGPR, selectionBGPR, destGPR);
+
+ auto bIsUnchanged = jit.branch32(CCallHelpers::Equal, selectionBGPR, CCallHelpers::TrustedImm32(selectionB));
+ jit.move(CCallHelpers::TrustedImm32(corruptedSelectionB), destGPR);
+ bIsUnchanged.link(&jit);
+
+ emitFunctionEpilogue(jit);
+ jit.ret();
+ });
+
+ testMoveConditionallyFloatingPoint(condition, testCode, arg1, arg2, floatOperands(), selectionA, selectionB);
+}
+
+void testMoveConditionallyFloat3DestSameAsElseCase(MacroAssembler::DoubleCondition condition)
+{
+ float arg1 = 0;
+ float arg2 = 0;
+ unsigned selectionA = 42;
+ unsigned selectionB = 17;
+ unsigned corruptedSelectionA = 0xbbad000a;
+
+ auto testCode = compile([&, condition] (CCallHelpers& jit) {
+ emitFunctionPrologue(jit);
+
+ GPRReg destGPR = GPRInfo::returnValueGPR;
+ GPRReg selectionAGPR = GPRInfo::argumentGPR2;
+ GPRReg selectionBGPR = destGPR;
+ RELEASE_ASSERT(destGPR != selectionAGPR);
+ RELEASE_ASSERT(destGPR == selectionBGPR);
+ jit.move(CCallHelpers::TrustedImm32(selectionA), selectionAGPR);
+ jit.move(CCallHelpers::TrustedImm32(selectionB), selectionBGPR);
+
+ jit.loadFloat(CCallHelpers::TrustedImmPtr(&arg1), FPRInfo::fpRegT0);
+ jit.loadFloat(CCallHelpers::TrustedImmPtr(&arg2), FPRInfo::fpRegT1);
+ jit.moveConditionallyFloat(condition, FPRInfo::fpRegT0, FPRInfo::fpRegT1, selectionAGPR, selectionBGPR, destGPR);
+
+ auto aIsUnchanged = jit.branch32(CCallHelpers::Equal, selectionAGPR, CCallHelpers::TrustedImm32(selectionA));
+ jit.move(CCallHelpers::TrustedImm32(corruptedSelectionA), destGPR);
+ aIsUnchanged.link(&jit);
+
+ emitFunctionEpilogue(jit);
+ jit.ret();
+ });
+
+ testMoveConditionallyFloatingPoint(condition, testCode, arg1, arg2, floatOperands(), selectionA, selectionB);
+}
+
+void testMoveDoubleConditionallyDouble(MacroAssembler::DoubleCondition condition)
+{
+ double arg1 = 0;
+ double arg2 = 0;
+ double selectionA = 42.0;
+ double selectionB = 17.0;
+ double corruptedSelectionA = 55555;
+ double corruptedSelectionB = 66666;
+
+ auto testCode = compile([&, condition] (CCallHelpers& jit) {
+ emitFunctionPrologue(jit);
+
+ FPRReg destFPR = FPRInfo::returnValueFPR;
+ FPRReg selectionAFPR = FPRInfo::fpRegT1;
+ FPRReg selectionBFPR = FPRInfo::fpRegT2;
+ FPRReg arg1FPR = FPRInfo::fpRegT3;
+ FPRReg arg2FPR = FPRInfo::fpRegT4;
+
+ RELEASE_ASSERT(destFPR != selectionAFPR);
+ RELEASE_ASSERT(destFPR != selectionBFPR);
+ RELEASE_ASSERT(destFPR != arg1FPR);
+ RELEASE_ASSERT(destFPR != arg2FPR);
+
+ jit.loadDouble(CCallHelpers::TrustedImmPtr(&arg1), arg1FPR);
+ jit.loadDouble(CCallHelpers::TrustedImmPtr(&arg2), arg2FPR);
+ jit.loadDouble(CCallHelpers::TrustedImmPtr(&selectionA), selectionAFPR);
+ jit.loadDouble(CCallHelpers::TrustedImmPtr(&selectionB), selectionBFPR);
+ jit.moveDoubleConditionallyDouble(condition, arg1FPR, arg2FPR, selectionAFPR, selectionBFPR, destFPR);
+
+ FPRReg tempFPR = FPRInfo::fpRegT5;
+ jit.loadDouble(CCallHelpers::TrustedImmPtr(&selectionA), tempFPR);
+ auto aIsUnchanged = jit.branchDouble(CCallHelpers::DoubleEqual, selectionAFPR, tempFPR);
+ jit.loadDouble(CCallHelpers::TrustedImmPtr(&corruptedSelectionA), destFPR);
+ aIsUnchanged.link(&jit);
+
+ jit.loadDouble(CCallHelpers::TrustedImmPtr(&selectionB), tempFPR);
+ auto bIsUnchanged = jit.branchDouble(CCallHelpers::DoubleEqual, selectionBFPR, tempFPR);
+ jit.loadDouble(CCallHelpers::TrustedImmPtr(&corruptedSelectionB), destFPR);
+ bIsUnchanged.link(&jit);
+
+ emitFunctionEpilogue(jit);
+ jit.ret();
+ });
+
+ testMoveConditionallyFloatingPoint(condition, testCode, arg1, arg2, doubleOperands(), selectionA, selectionB);
+}
+
+void testMoveDoubleConditionallyDoubleDestSameAsThenCase(MacroAssembler::DoubleCondition condition)
+{
+ double arg1 = 0;
+ double arg2 = 0;
+ double selectionA = 42.0;
+ double selectionB = 17.0;
+ double corruptedSelectionB = 66666;
+
+ auto testCode = compile([&, condition] (CCallHelpers& jit) {
+ emitFunctionPrologue(jit);
+
+ FPRReg destFPR = FPRInfo::returnValueFPR;
+ FPRReg selectionAFPR = destFPR;
+ FPRReg selectionBFPR = FPRInfo::fpRegT2;
+ FPRReg arg1FPR = FPRInfo::fpRegT3;
+ FPRReg arg2FPR = FPRInfo::fpRegT4;
+
+ RELEASE_ASSERT(destFPR == selectionAFPR);
+ RELEASE_ASSERT(destFPR != selectionBFPR);
+ RELEASE_ASSERT(destFPR != arg1FPR);
+ RELEASE_ASSERT(destFPR != arg2FPR);
+
+ jit.loadDouble(CCallHelpers::TrustedImmPtr(&arg1), arg1FPR);
+ jit.loadDouble(CCallHelpers::TrustedImmPtr(&arg2), arg2FPR);
+ jit.loadDouble(CCallHelpers::TrustedImmPtr(&selectionA), selectionAFPR);
+ jit.loadDouble(CCallHelpers::TrustedImmPtr(&selectionB), selectionBFPR);
+ jit.moveDoubleConditionallyDouble(condition, arg1FPR, arg2FPR, selectionAFPR, selectionBFPR, destFPR);
+
+ FPRReg tempFPR = FPRInfo::fpRegT5;
+ jit.loadDouble(CCallHelpers::TrustedImmPtr(&selectionB), tempFPR);
+ auto bIsUnchanged = jit.branchDouble(CCallHelpers::DoubleEqual, selectionBFPR, tempFPR);
+ jit.loadDouble(CCallHelpers::TrustedImmPtr(&corruptedSelectionB), destFPR);
+ bIsUnchanged.link(&jit);
+
+ emitFunctionEpilogue(jit);
+ jit.ret();
+ });
+
+ testMoveConditionallyFloatingPoint(condition, testCode, arg1, arg2, doubleOperands(), selectionA, selectionB);
+}
+
+void testMoveDoubleConditionallyDoubleDestSameAsElseCase(MacroAssembler::DoubleCondition condition)
+{
+ double arg1 = 0;
+ double arg2 = 0;
+ double selectionA = 42.0;
+ double selectionB = 17.0;
+ double corruptedSelectionA = 55555;
+
+ auto testCode = compile([&, condition] (CCallHelpers& jit) {
+ emitFunctionPrologue(jit);
+
+ FPRReg destFPR = FPRInfo::returnValueFPR;
+ FPRReg selectionAFPR = FPRInfo::fpRegT1;
+ FPRReg selectionBFPR = destFPR;
+ FPRReg arg1FPR = FPRInfo::fpRegT3;
+ FPRReg arg2FPR = FPRInfo::fpRegT4;
+
+ RELEASE_ASSERT(destFPR != selectionAFPR);
+ RELEASE_ASSERT(destFPR == selectionBFPR);
+ RELEASE_ASSERT(destFPR != arg1FPR);
+ RELEASE_ASSERT(destFPR != arg2FPR);
+
+ jit.loadDouble(CCallHelpers::TrustedImmPtr(&arg1), arg1FPR);
+ jit.loadDouble(CCallHelpers::TrustedImmPtr(&arg2), arg2FPR);
+ jit.loadDouble(CCallHelpers::TrustedImmPtr(&selectionA), selectionAFPR);
+ jit.loadDouble(CCallHelpers::TrustedImmPtr(&selectionB), selectionBFPR);
+ jit.moveDoubleConditionallyDouble(condition, arg1FPR, arg2FPR, selectionAFPR, selectionBFPR, destFPR);
+
+ FPRReg tempFPR = FPRInfo::fpRegT5;
+ jit.loadDouble(CCallHelpers::TrustedImmPtr(&selectionA), tempFPR);
+ auto aIsUnchanged = jit.branchDouble(CCallHelpers::DoubleEqual, selectionAFPR, tempFPR);
+ jit.loadDouble(CCallHelpers::TrustedImmPtr(&corruptedSelectionA), destFPR);
+ aIsUnchanged.link(&jit);
+
+ emitFunctionEpilogue(jit);
+ jit.ret();
+ });
+
+ testMoveConditionallyFloatingPoint(condition, testCode, arg1, arg2, doubleOperands(), selectionA, selectionB);
+}
+
+void testMoveDoubleConditionallyFloat(MacroAssembler::DoubleCondition condition)
+{
+ float arg1 = 0;
+ float arg2 = 0;
+ double selectionA = 42.0;
+ double selectionB = 17.0;
+ double corruptedSelectionA = 55555;
+ double corruptedSelectionB = 66666;
+
+ auto testCode = compile([&, condition] (CCallHelpers& jit) {
+ emitFunctionPrologue(jit);
+
+ FPRReg destFPR = FPRInfo::returnValueFPR;
+ FPRReg selectionAFPR = FPRInfo::fpRegT1;
+ FPRReg selectionBFPR = FPRInfo::fpRegT2;
+ FPRReg arg1FPR = FPRInfo::fpRegT3;
+ FPRReg arg2FPR = FPRInfo::fpRegT4;
+
+ RELEASE_ASSERT(destFPR != selectionAFPR);
+ RELEASE_ASSERT(destFPR != selectionBFPR);
+ RELEASE_ASSERT(destFPR != arg1FPR);
+ RELEASE_ASSERT(destFPR != arg2FPR);
+
+ jit.loadFloat(CCallHelpers::TrustedImmPtr(&arg1), arg1FPR);
+ jit.loadFloat(CCallHelpers::TrustedImmPtr(&arg2), arg2FPR);
+ jit.loadDouble(CCallHelpers::TrustedImmPtr(&selectionA), selectionAFPR);
+ jit.loadDouble(CCallHelpers::TrustedImmPtr(&selectionB), selectionBFPR);
+ jit.moveDoubleConditionallyFloat(condition, arg1FPR, arg2FPR, selectionAFPR, selectionBFPR, destFPR);
+
+ FPRReg tempFPR = FPRInfo::fpRegT5;
+ jit.loadDouble(CCallHelpers::TrustedImmPtr(&selectionA), tempFPR);
+ auto aIsUnchanged = jit.branchDouble(CCallHelpers::DoubleEqual, selectionAFPR, tempFPR);
+ jit.loadDouble(CCallHelpers::TrustedImmPtr(&corruptedSelectionA), destFPR);
+ aIsUnchanged.link(&jit);
+
+ jit.loadDouble(CCallHelpers::TrustedImmPtr(&selectionB), tempFPR);
+ auto bIsUnchanged = jit.branchDouble(CCallHelpers::DoubleEqual, selectionBFPR, tempFPR);
+ jit.loadDouble(CCallHelpers::TrustedImmPtr(&corruptedSelectionB), destFPR);
+ bIsUnchanged.link(&jit);
+
+ emitFunctionEpilogue(jit);
+ jit.ret();
+ });
+
+ testMoveConditionallyFloatingPoint(condition, testCode, arg1, arg2, floatOperands(), selectionA, selectionB);
+}
+
+void testMoveDoubleConditionallyFloatDestSameAsThenCase(MacroAssembler::DoubleCondition condition)
+{
+ float arg1 = 0;
+ float arg2 = 0;
+ double selectionA = 42.0;
+ double selectionB = 17.0;
+ double corruptedSelectionB = 66666;
+
+ auto testCode = compile([&, condition] (CCallHelpers& jit) {
+ emitFunctionPrologue(jit);
+
+ FPRReg destFPR = FPRInfo::returnValueFPR;
+ FPRReg selectionAFPR = destFPR;
+ FPRReg selectionBFPR = FPRInfo::fpRegT2;
+ FPRReg arg1FPR = FPRInfo::fpRegT3;
+ FPRReg arg2FPR = FPRInfo::fpRegT4;
+
+ RELEASE_ASSERT(destFPR == selectionAFPR);
+ RELEASE_ASSERT(destFPR != selectionBFPR);
+ RELEASE_ASSERT(destFPR != arg1FPR);
+ RELEASE_ASSERT(destFPR != arg2FPR);
+
+ jit.loadFloat(CCallHelpers::TrustedImmPtr(&arg1), arg1FPR);
+ jit.loadFloat(CCallHelpers::TrustedImmPtr(&arg2), arg2FPR);
+ jit.loadDouble(CCallHelpers::TrustedImmPtr(&selectionA), selectionAFPR);
+ jit.loadDouble(CCallHelpers::TrustedImmPtr(&selectionB), selectionBFPR);
+ jit.moveDoubleConditionallyFloat(condition, arg1FPR, arg2FPR, selectionAFPR, selectionBFPR, destFPR);
+
+ FPRReg tempFPR = FPRInfo::fpRegT5;
+ jit.loadDouble(CCallHelpers::TrustedImmPtr(&selectionB), tempFPR);
+ auto bIsUnchanged = jit.branchDouble(CCallHelpers::DoubleEqual, selectionBFPR, tempFPR);
+ jit.loadDouble(CCallHelpers::TrustedImmPtr(&corruptedSelectionB), destFPR);
+ bIsUnchanged.link(&jit);
+
+ emitFunctionEpilogue(jit);
+ jit.ret();
+ });
+
+ testMoveConditionallyFloatingPoint(condition, testCode, arg1, arg2, floatOperands(), selectionA, selectionB);
+}
+
+void testMoveDoubleConditionallyFloatDestSameAsElseCase(MacroAssembler::DoubleCondition condition)
+{
+ float arg1 = 0;
+ float arg2 = 0;
+ double selectionA = 42.0;
+ double selectionB = 17.0;
+ double corruptedSelectionA = 55555;
+
+ auto testCode = compile([&, condition] (CCallHelpers& jit) {
+ emitFunctionPrologue(jit);
+
+ FPRReg destFPR = FPRInfo::returnValueFPR;
+ FPRReg selectionAFPR = FPRInfo::fpRegT1;
+ FPRReg selectionBFPR = destFPR;
+ FPRReg arg1FPR = FPRInfo::fpRegT3;
+ FPRReg arg2FPR = FPRInfo::fpRegT4;
+
+ RELEASE_ASSERT(destFPR != selectionAFPR);
+ RELEASE_ASSERT(destFPR == selectionBFPR);
+ RELEASE_ASSERT(destFPR != arg1FPR);
+ RELEASE_ASSERT(destFPR != arg2FPR);
+
+ jit.loadFloat(CCallHelpers::TrustedImmPtr(&arg1), arg1FPR);
+ jit.loadFloat(CCallHelpers::TrustedImmPtr(&arg2), arg2FPR);
+ jit.loadDouble(CCallHelpers::TrustedImmPtr(&selectionA), selectionAFPR);
+ jit.loadDouble(CCallHelpers::TrustedImmPtr(&selectionB), selectionBFPR);
+ jit.moveDoubleConditionallyFloat(condition, arg1FPR, arg2FPR, selectionAFPR, selectionBFPR, destFPR);
+
+ FPRReg tempFPR = FPRInfo::fpRegT5;
+ jit.loadDouble(CCallHelpers::TrustedImmPtr(&selectionA), tempFPR);
+ auto aIsUnchanged = jit.branchDouble(CCallHelpers::DoubleEqual, selectionAFPR, tempFPR);
+ jit.loadDouble(CCallHelpers::TrustedImmPtr(&corruptedSelectionA), destFPR);
+ aIsUnchanged.link(&jit);
+
+ emitFunctionEpilogue(jit);
+ jit.ret();
+ });
+
+ testMoveConditionallyFloatingPoint(condition, testCode, arg1, arg2, floatOperands(), selectionA, selectionB);
+}
+
+template<typename T, typename SelectionType>
+void testMoveConditionallyFloatingPointSameArg(MacroAssembler::DoubleCondition condition, const MacroAssemblerCodeRef<JSEntryPtrTag>& testCode, T& arg1, const Vector<T> operands, SelectionType selectionA, SelectionType selectionB)
+{
+ auto expectedResult = [&, condition] (T a) -> SelectionType {
+ auto isUnordered = [] (double x) {
+ return x != x;
+ };
+ switch (condition) {
+ case MacroAssembler::DoubleEqual:
+ return !isUnordered(a) && (a == a) ? selectionA : selectionB;
+ case MacroAssembler::DoubleNotEqual:
+ return !isUnordered(a) && (a != a) ? selectionA : selectionB;
+ case MacroAssembler::DoubleGreaterThan:
+ return !isUnordered(a) && (a > a) ? selectionA : selectionB;
+ case MacroAssembler::DoubleGreaterThanOrEqual:
+ return !isUnordered(a) && (a >= a) ? selectionA : selectionB;
+ case MacroAssembler::DoubleLessThan:
+ return !isUnordered(a) && (a < a) ? selectionA : selectionB;
+ case MacroAssembler::DoubleLessThanOrEqual:
+ return !isUnordered(a) && (a <= a) ? selectionA : selectionB;
+ case MacroAssembler::DoubleEqualOrUnordered:
+ return isUnordered(a) || (a == a) ? selectionA : selectionB;
+ case MacroAssembler::DoubleNotEqualOrUnordered:
+ return isUnordered(a) || (a != a) ? selectionA : selectionB;
+ case MacroAssembler::DoubleGreaterThanOrUnordered:
+ return isUnordered(a) || (a > a) ? selectionA : selectionB;
+ case MacroAssembler::DoubleGreaterThanOrEqualOrUnordered:
+ return isUnordered(a) || (a >= a) ? selectionA : selectionB;
+ case MacroAssembler::DoubleLessThanOrUnordered:
+ return isUnordered(a) || (a < a) ? selectionA : selectionB;
+ case MacroAssembler::DoubleLessThanOrEqualOrUnordered:
+ return isUnordered(a) || (a <= a) ? selectionA : selectionB;
+ } // switch
+ };
+
+ for (auto a : operands) {
+ arg1 = a;
+ CHECK_EQ(invoke<SelectionType>(testCode), expectedResult(a));
+ }
+}
+
+void testMoveConditionallyDouble2SameArg(MacroAssembler::DoubleCondition condition)
+{
+ double arg1 = 0;
+ unsigned selectionA = 42;
+ unsigned selectionB = 17;
+
+ auto testCode = compile([&, condition] (CCallHelpers& jit) {
+ emitFunctionPrologue(jit);
+
+ GPRReg selectionAGPR = GPRInfo::argumentGPR2;
+ RELEASE_ASSERT(GPRInfo::returnValueGPR != selectionAGPR);
+ jit.move(CCallHelpers::TrustedImm32(selectionA), selectionAGPR);
+ jit.move(CCallHelpers::TrustedImm32(selectionB), GPRInfo::returnValueGPR);
+
+ jit.loadDouble(CCallHelpers::TrustedImmPtr(&arg1), FPRInfo::fpRegT0);
+ jit.moveConditionallyDouble(condition, FPRInfo::fpRegT0, FPRInfo::fpRegT0, selectionAGPR, GPRInfo::returnValueGPR);
+
+ emitFunctionEpilogue(jit);
+ jit.ret();
+ });
+
+ testMoveConditionallyFloatingPointSameArg(condition, testCode, arg1, doubleOperands(), selectionA, selectionB);
+}
+
+void testMoveConditionallyDouble3SameArg(MacroAssembler::DoubleCondition condition)
+{
+ double arg1 = 0;
+ unsigned selectionA = 42;
+ unsigned selectionB = 17;
+
+ auto testCode = compile([&, condition] (CCallHelpers& jit) {
+ emitFunctionPrologue(jit);
+
+ GPRReg selectionAGPR = GPRInfo::argumentGPR2;
+ GPRReg selectionBGPR = GPRInfo::argumentGPR3;
+ RELEASE_ASSERT(GPRInfo::returnValueGPR != selectionAGPR);
+ RELEASE_ASSERT(GPRInfo::returnValueGPR != selectionBGPR);
+ jit.move(CCallHelpers::TrustedImm32(selectionA), selectionAGPR);
+ jit.move(CCallHelpers::TrustedImm32(selectionB), selectionBGPR);
+ jit.move(CCallHelpers::TrustedImm32(-1), GPRInfo::returnValueGPR);
+
+ jit.loadDouble(CCallHelpers::TrustedImmPtr(&arg1), FPRInfo::fpRegT0);
+ jit.moveConditionallyDouble(condition, FPRInfo::fpRegT0, FPRInfo::fpRegT0, selectionAGPR, selectionBGPR, GPRInfo::returnValueGPR);
+
+ emitFunctionEpilogue(jit);
+ jit.ret();
+ });
+
+ testMoveConditionallyFloatingPointSameArg(condition, testCode, arg1, doubleOperands(), selectionA, selectionB);
+}
+
+void testMoveConditionallyFloat2SameArg(MacroAssembler::DoubleCondition condition)
+{
+ float arg1 = 0;
+ unsigned selectionA = 42;
+ unsigned selectionB = 17;
+
+ auto testCode = compile([&, condition] (CCallHelpers& jit) {
+ emitFunctionPrologue(jit);
+
+ GPRReg selectionAGPR = GPRInfo::argumentGPR2;
+ RELEASE_ASSERT(GPRInfo::returnValueGPR != selectionAGPR);
+ jit.move(CCallHelpers::TrustedImm32(selectionA), selectionAGPR);
+ jit.move(CCallHelpers::TrustedImm32(selectionB), GPRInfo::returnValueGPR);
+
+ jit.loadFloat(CCallHelpers::TrustedImmPtr(&arg1), FPRInfo::fpRegT0);
+ jit.moveConditionallyFloat(condition, FPRInfo::fpRegT0, FPRInfo::fpRegT0, selectionAGPR, GPRInfo::returnValueGPR);
+
+ emitFunctionEpilogue(jit);
+ jit.ret();
+ });
+
+ testMoveConditionallyFloatingPointSameArg(condition, testCode, arg1, floatOperands(), selectionA, selectionB);
+}
+
+void testMoveConditionallyFloat3SameArg(MacroAssembler::DoubleCondition condition)
+{
+ float arg1 = 0;
+ unsigned selectionA = 42;
+ unsigned selectionB = 17;
+
+ auto testCode = compile([&, condition] (CCallHelpers& jit) {
+ emitFunctionPrologue(jit);
+
+ GPRReg selectionAGPR = GPRInfo::argumentGPR2;
+ GPRReg selectionBGPR = GPRInfo::argumentGPR3;
+ RELEASE_ASSERT(GPRInfo::returnValueGPR != selectionAGPR);
+ RELEASE_ASSERT(GPRInfo::returnValueGPR != selectionBGPR);
+ jit.move(CCallHelpers::TrustedImm32(selectionA), selectionAGPR);
+ jit.move(CCallHelpers::TrustedImm32(selectionB), selectionBGPR);
+ jit.move(CCallHelpers::TrustedImm32(-1), GPRInfo::returnValueGPR);
+
+ jit.loadFloat(CCallHelpers::TrustedImmPtr(&arg1), FPRInfo::fpRegT0);
+ jit.moveConditionallyFloat(condition, FPRInfo::fpRegT0, FPRInfo::fpRegT0, selectionAGPR, selectionBGPR, GPRInfo::returnValueGPR);
+
+ emitFunctionEpilogue(jit);
+ jit.ret();
+ });
+
+ testMoveConditionallyFloatingPointSameArg(condition, testCode, arg1, floatOperands(), selectionA, selectionB);
+}
+
+void testMoveDoubleConditionallyDoubleSameArg(MacroAssembler::DoubleCondition condition)
+{
+ double arg1 = 0;
+ double selectionA = 42.0;
+ double selectionB = 17.0;
+
+ auto testCode = compile([&, condition] (CCallHelpers& jit) {
+ emitFunctionPrologue(jit);
+
+ jit.loadDouble(CCallHelpers::TrustedImmPtr(&arg1), FPRInfo::fpRegT0);
+ jit.loadDouble(CCallHelpers::TrustedImmPtr(&selectionA), FPRInfo::fpRegT2);
+ jit.loadDouble(CCallHelpers::TrustedImmPtr(&selectionB), FPRInfo::fpRegT3);
+ jit.moveDoubleConditionallyDouble(condition, FPRInfo::fpRegT0, FPRInfo::fpRegT0, FPRInfo::fpRegT2, FPRInfo::fpRegT3, FPRInfo::returnValueFPR);
+
+ emitFunctionEpilogue(jit);
+ jit.ret();
+ });
+
+ testMoveConditionallyFloatingPointSameArg(condition, testCode, arg1, doubleOperands(), selectionA, selectionB);
+}
+
+void testMoveDoubleConditionallyFloatSameArg(MacroAssembler::DoubleCondition condition)
+{
+ float arg1 = 0;
+ double selectionA = 42.0;
+ double selectionB = 17.0;
+
+ auto testCode = compile([&, condition] (CCallHelpers& jit) {
+ emitFunctionPrologue(jit);
+
+ jit.loadFloat(CCallHelpers::TrustedImmPtr(&arg1), FPRInfo::fpRegT0);
+ jit.loadDouble(CCallHelpers::TrustedImmPtr(&selectionA), FPRInfo::fpRegT2);
+ jit.loadDouble(CCallHelpers::TrustedImmPtr(&selectionB), FPRInfo::fpRegT3);
+ jit.moveDoubleConditionallyFloat(condition, FPRInfo::fpRegT0, FPRInfo::fpRegT0, FPRInfo::fpRegT2, FPRInfo::fpRegT3, FPRInfo::returnValueFPR);
+
+ emitFunctionEpilogue(jit);
+ jit.ret();
+ });
+
+ testMoveConditionallyFloatingPointSameArg(condition, testCode, arg1, floatOperands(), selectionA, selectionB);
+}
+
+#endif // CPU(X86_64) || CPU(ARM64)
+
#if ENABLE(MASM_PROBE)
void testProbeReadsArgumentRegisters()
{
@@ -1337,18 +2199,25 @@
// reset to check a conversion result
RUN(testBranchTruncateDoubleToInt32(123, 123));
- RUN(testCompareDouble(MacroAssembler::DoubleEqual));
- RUN(testCompareDouble(MacroAssembler::DoubleNotEqual));
- RUN(testCompareDouble(MacroAssembler::DoubleGreaterThan));
- RUN(testCompareDouble(MacroAssembler::DoubleGreaterThanOrEqual));
- RUN(testCompareDouble(MacroAssembler::DoubleLessThan));
- RUN(testCompareDouble(MacroAssembler::DoubleLessThanOrEqual));
- RUN(testCompareDouble(MacroAssembler::DoubleEqualOrUnordered));
- RUN(testCompareDouble(MacroAssembler::DoubleNotEqualOrUnordered));
- RUN(testCompareDouble(MacroAssembler::DoubleGreaterThanOrUnordered));
- RUN(testCompareDouble(MacroAssembler::DoubleGreaterThanOrEqualOrUnordered));
- RUN(testCompareDouble(MacroAssembler::DoubleLessThanOrUnordered));
- RUN(testCompareDouble(MacroAssembler::DoubleLessThanOrEqualOrUnordered));
+#define FOR_EACH_DOUBLE_CONDITION_RUN(__test) \
+ do { \
+ RUN(__test(MacroAssembler::DoubleEqual)); \
+ RUN(__test(MacroAssembler::DoubleNotEqual)); \
+ RUN(__test(MacroAssembler::DoubleGreaterThan)); \
+ RUN(__test(MacroAssembler::DoubleGreaterThanOrEqual)); \
+ RUN(__test(MacroAssembler::DoubleLessThan)); \
+ RUN(__test(MacroAssembler::DoubleLessThanOrEqual)); \
+ RUN(__test(MacroAssembler::DoubleEqualOrUnordered)); \
+ RUN(__test(MacroAssembler::DoubleNotEqualOrUnordered)); \
+ RUN(__test(MacroAssembler::DoubleGreaterThanOrUnordered)); \
+ RUN(__test(MacroAssembler::DoubleGreaterThanOrEqualOrUnordered)); \
+ RUN(__test(MacroAssembler::DoubleLessThanOrUnordered)); \
+ RUN(__test(MacroAssembler::DoubleLessThanOrEqualOrUnordered)); \
+ } while (false)
+
+ FOR_EACH_DOUBLE_CONDITION_RUN(testCompareDouble);
+ FOR_EACH_DOUBLE_CONDITION_RUN(testCompareDoubleSameArg);
+
RUN(testMul32WithImmediates());
#if CPU(X86_64)
@@ -1365,20 +2234,35 @@
#endif
#if CPU(X86) || CPU(X86_64) || CPU(ARM64)
- RUN(testCompareFloat(MacroAssembler::DoubleEqual));
- RUN(testCompareFloat(MacroAssembler::DoubleNotEqual));
- RUN(testCompareFloat(MacroAssembler::DoubleGreaterThan));
- RUN(testCompareFloat(MacroAssembler::DoubleGreaterThanOrEqual));
- RUN(testCompareFloat(MacroAssembler::DoubleLessThan));
- RUN(testCompareFloat(MacroAssembler::DoubleLessThanOrEqual));
- RUN(testCompareFloat(MacroAssembler::DoubleEqualOrUnordered));
- RUN(testCompareFloat(MacroAssembler::DoubleNotEqualOrUnordered));
- RUN(testCompareFloat(MacroAssembler::DoubleGreaterThanOrUnordered));
- RUN(testCompareFloat(MacroAssembler::DoubleGreaterThanOrEqualOrUnordered));
- RUN(testCompareFloat(MacroAssembler::DoubleLessThanOrUnordered));
- RUN(testCompareFloat(MacroAssembler::DoubleLessThanOrEqualOrUnordered));
+ FOR_EACH_DOUBLE_CONDITION_RUN(testCompareFloat);
#endif
+#if CPU(X86_64) || CPU(ARM64)
+ // Comparing 2 different registers.
+ FOR_EACH_DOUBLE_CONDITION_RUN(testMoveConditionallyDouble2);
+ FOR_EACH_DOUBLE_CONDITION_RUN(testMoveConditionallyDouble3);
+ FOR_EACH_DOUBLE_CONDITION_RUN(testMoveConditionallyDouble3DestSameAsThenCase);
+ FOR_EACH_DOUBLE_CONDITION_RUN(testMoveConditionallyDouble3DestSameAsElseCase);
+ FOR_EACH_DOUBLE_CONDITION_RUN(testMoveConditionallyFloat2);
+ FOR_EACH_DOUBLE_CONDITION_RUN(testMoveConditionallyFloat3);
+ FOR_EACH_DOUBLE_CONDITION_RUN(testMoveConditionallyFloat3DestSameAsThenCase);
+ FOR_EACH_DOUBLE_CONDITION_RUN(testMoveConditionallyFloat3DestSameAsElseCase);
+ FOR_EACH_DOUBLE_CONDITION_RUN(testMoveDoubleConditionallyDouble);
+ FOR_EACH_DOUBLE_CONDITION_RUN(testMoveDoubleConditionallyDoubleDestSameAsThenCase);
+ FOR_EACH_DOUBLE_CONDITION_RUN(testMoveDoubleConditionallyDoubleDestSameAsElseCase);
+ FOR_EACH_DOUBLE_CONDITION_RUN(testMoveDoubleConditionallyFloat);
+ FOR_EACH_DOUBLE_CONDITION_RUN(testMoveDoubleConditionallyFloatDestSameAsThenCase);
+ FOR_EACH_DOUBLE_CONDITION_RUN(testMoveDoubleConditionallyFloatDestSameAsElseCase);
+
+ // Comparing the same register against itself.
+ FOR_EACH_DOUBLE_CONDITION_RUN(testMoveConditionallyDouble2SameArg);
+ FOR_EACH_DOUBLE_CONDITION_RUN(testMoveConditionallyDouble3SameArg);
+ FOR_EACH_DOUBLE_CONDITION_RUN(testMoveConditionallyFloat2SameArg);
+ FOR_EACH_DOUBLE_CONDITION_RUN(testMoveConditionallyFloat3SameArg);
+ FOR_EACH_DOUBLE_CONDITION_RUN(testMoveDoubleConditionallyDoubleSameArg);
+ FOR_EACH_DOUBLE_CONDITION_RUN(testMoveDoubleConditionallyFloatSameArg);
+#endif
+
#if ENABLE(MASM_PROBE)
RUN(testProbeReadsArgumentRegisters());
RUN(testProbeWritesArgumentRegisters());