Index: src/mips64/macro-assembler-mips64.cc |
diff --git a/src/mips64/macro-assembler-mips64.cc b/src/mips64/macro-assembler-mips64.cc |
index 701420bfd653869cd172ad680538d9012411ba1a..3c068ad0dac0f630ad0a5efac3e864376919b0a6 100644 |
--- a/src/mips64/macro-assembler-mips64.cc |
+++ b/src/mips64/macro-assembler-mips64.cc |
@@ -2362,6 +2362,186 @@ void MacroAssembler::Movf(Register rd, Register rs, uint16_t cc) { |
movf(rd, rs, 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. |
+ __ dmfc1(t8, src1); |
+ __ Branch(&other, eq, t8, Operand(0x8000000000000000)); |
+ __ 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); |
+ __ dsll32(t8, t8, 0); |
+ __ Branch(&other, eq, t8, Operand(0x8000000000000000)); |
+ __ 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 (kArchVariant >= kMips64r6) { |
+ 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 (kArchVariant >= kMips64r6) { |
+ 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 (kArchVariant >= kMips64r6) { |
+ 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 (kArchVariant >= kMips64r6) { |
+ 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) { |
clz(rd, rs); |