Index: src/mips/macro-assembler-mips.cc |
diff --git a/src/mips/macro-assembler-mips.cc b/src/mips/macro-assembler-mips.cc |
index 108c0d9803ed2e3ece0796ff9478deaf0cefccc3..02f7bee24811f9280148137a2df53782e9508855 100644 |
--- a/src/mips/macro-assembler-mips.cc |
+++ b/src/mips/macro-assembler-mips.cc |
@@ -1881,6 +1881,185 @@ void MacroAssembler::Movf(Register rd, Register rs, uint16_t cc) { |
} |
} |
+#define __ masm-> |
+ |
+static bool ZeroHelper_d(MacroAssembler* masm, MaxMinKind kind, FPURegister dst, |
+ FPURegister src1, FPURegister src2, Label* equal) { |
+ if (src1.is(src2)) { |
+ __ Move(dst, src1); |
+ return true; |
+ } |
+ |
+ Label other, compare_not_equal; |
+ FPURegister left, right; |
+ if (kind == MaxMinKind::kMin) { |
+ left = src1; |
+ right = src2; |
+ } else { |
+ left = src2; |
+ right = src1; |
+ } |
+ |
+ __ BranchF64(&compare_not_equal, nullptr, ne, src1, src2); |
+ // Left and right hand side are equal, check for -0 vs. +0. |
+ __ FmoveHigh(t8, src1); |
+ __ Branch(&other, eq, t8, Operand(0x80000000)); |
+ __ Move_d(dst, right); |
+ __ Branch(equal); |
+ __ bind(&other); |
+ __ Move_d(dst, left); |
+ __ Branch(equal); |
+ __ bind(&compare_not_equal); |
+ return false; |
+} |
+ |
+static bool ZeroHelper_s(MacroAssembler* masm, MaxMinKind kind, FPURegister dst, |
+ FPURegister src1, FPURegister src2, Label* equal) { |
+ if (src1.is(src2)) { |
+ __ Move(dst, src1); |
+ return true; |
+ } |
+ |
+ Label other, compare_not_equal; |
+ FPURegister left, right; |
+ if (kind == MaxMinKind::kMin) { |
+ left = src1; |
+ right = src2; |
+ } else { |
+ left = src2; |
+ right = src1; |
+ } |
+ |
+ __ BranchF32(&compare_not_equal, nullptr, ne, src1, src2); |
+ // Left and right hand side are equal, check for -0 vs. +0. |
+ __ FmoveLow(t8, src1); |
+ __ Branch(&other, eq, t8, Operand(0x80000000)); |
+ __ Move_s(dst, right); |
+ __ Branch(equal); |
+ __ bind(&other); |
+ __ Move_s(dst, left); |
+ __ Branch(equal); |
+ __ bind(&compare_not_equal); |
+ return false; |
+} |
+ |
+#undef __ |
+ |
+void MacroAssembler::MinNaNCheck_d(FPURegister dst, FPURegister src1, |
+ FPURegister src2, Label* nan) { |
+ if (nan) { |
+ BranchF64(nullptr, nan, eq, src1, src2); |
+ } |
+ if (IsMipsArchVariant(kMips32r6)) { |
+ min_d(dst, src1, src2); |
+ } else { |
+ Label skip; |
+ if (!ZeroHelper_d(this, MaxMinKind::kMin, dst, src1, src2, &skip)) { |
+ if (dst.is(src1)) { |
+ BranchF64(&skip, nullptr, le, src1, src2); |
+ Move_d(dst, src2); |
+ } else if (dst.is(src2)) { |
+ BranchF64(&skip, nullptr, ge, src1, src2); |
+ Move_d(dst, src1); |
+ } else { |
+ Label right; |
+ BranchF64(&right, nullptr, gt, src1, src2); |
+ Move_d(dst, src1); |
+ Branch(&skip); |
+ bind(&right); |
+ Move_d(dst, src2); |
+ } |
+ } |
+ bind(&skip); |
+ } |
+} |
+ |
+void MacroAssembler::MaxNaNCheck_d(FPURegister dst, FPURegister src1, |
+ FPURegister src2, Label* nan) { |
+ if (nan) { |
+ BranchF64(nullptr, nan, eq, src1, src2); |
+ } |
+ if (IsMipsArchVariant(kMips32r6)) { |
+ max_d(dst, src1, src2); |
+ } else { |
+ Label skip; |
+ if (!ZeroHelper_d(this, MaxMinKind::kMax, dst, src1, src2, &skip)) { |
+ if (dst.is(src1)) { |
+ BranchF64(&skip, nullptr, ge, src1, src2); |
+ Move_d(dst, src2); |
+ } else if (dst.is(src2)) { |
+ BranchF64(&skip, nullptr, le, src1, src2); |
+ Move_d(dst, src1); |
+ } else { |
+ Label right; |
+ BranchF64(&right, nullptr, lt, src1, src2); |
+ Move_d(dst, src1); |
+ Branch(&skip); |
+ bind(&right); |
+ Move_d(dst, src2); |
+ } |
+ } |
+ bind(&skip); |
+ } |
+} |
+ |
+void MacroAssembler::MinNaNCheck_s(FPURegister dst, FPURegister src1, |
+ FPURegister src2, Label* nan) { |
+ if (nan) { |
+ BranchF32(nullptr, nan, eq, src1, src2); |
+ } |
+ if (IsMipsArchVariant(kMips32r6)) { |
+ min_s(dst, src1, src2); |
+ } else { |
+ Label skip; |
+ if (!ZeroHelper_s(this, MaxMinKind::kMin, dst, src1, src2, &skip)) { |
+ if (dst.is(src1)) { |
+ BranchF32(&skip, nullptr, le, src1, src2); |
+ Move_s(dst, src2); |
+ } else if (dst.is(src2)) { |
+ BranchF32(&skip, nullptr, ge, src1, src2); |
+ Move_s(dst, src1); |
+ } else { |
+ Label right; |
+ BranchF32(&right, nullptr, gt, src1, src2); |
+ Move_s(dst, src1); |
+ Branch(&skip); |
+ bind(&right); |
+ Move_s(dst, src2); |
+ } |
+ } |
+ bind(&skip); |
+ } |
+} |
+ |
+void MacroAssembler::MaxNaNCheck_s(FPURegister dst, FPURegister src1, |
+ FPURegister src2, Label* nan) { |
+ if (nan) { |
+ BranchF32(nullptr, nan, eq, src1, src2); |
+ } |
+ if (IsMipsArchVariant(kMips32r6)) { |
+ max_s(dst, src1, src2); |
+ } else { |
+ Label skip; |
+ if (!ZeroHelper_s(this, MaxMinKind::kMax, dst, src1, src2, &skip)) { |
+ if (dst.is(src1)) { |
+ BranchF32(&skip, nullptr, ge, src1, src2); |
+ Move_s(dst, src2); |
+ } else if (dst.is(src2)) { |
+ BranchF32(&skip, nullptr, le, src1, src2); |
+ Move_s(dst, src1); |
+ } else { |
+ Label right; |
+ BranchF32(&right, nullptr, lt, src1, src2); |
+ Move_s(dst, src1); |
+ Branch(&skip); |
+ bind(&right); |
+ Move_s(dst, src2); |
+ } |
+ } |
+ bind(&skip); |
+ } |
+} |
void MacroAssembler::Clz(Register rd, Register rs) { |
if (IsMipsArchVariant(kLoongson)) { |