Index: src/compiler/mips64/code-generator-mips64.cc |
diff --git a/src/compiler/mips64/code-generator-mips64.cc b/src/compiler/mips64/code-generator-mips64.cc |
index 8e94ceed2126841ab08b5e5897ccb4621b2be0c9..dee7705f055fba49a715a610a6aa8ef73f78f26c 100644 |
--- a/src/compiler/mips64/code-generator-mips64.cc |
+++ b/src/compiler/mips64/code-generator-mips64.cc |
@@ -163,6 +163,46 @@ class OutOfLineLoadInteger FINAL : public OutOfLineCode { |
Register const result_; |
}; |
+ |
+class OutOfLineRound : public OutOfLineCode { |
+ public: |
+ OutOfLineRound(CodeGenerator* gen, DoubleRegister result) |
+ : OutOfLineCode(gen), result_(result) {} |
+ |
+ void Generate() FINAL { |
+ // Handle rounding to zero case where sign has to be preserved. |
+ // High bits of double input already in kScratchReg. |
+ __ dsrl(at, kScratchReg, 31); |
+ __ dsll(at, at, 31); |
+ __ mthc1(at, result_); |
+ } |
+ |
+ private: |
+ DoubleRegister const result_; |
+}; |
+ |
+ |
+class OutOfLineTruncate FINAL : public OutOfLineRound { |
+ public: |
+ OutOfLineTruncate(CodeGenerator* gen, DoubleRegister result) |
+ : OutOfLineRound(gen, result) {} |
+}; |
+ |
+ |
+class OutOfLineFloor FINAL : public OutOfLineRound { |
+ public: |
+ OutOfLineFloor(CodeGenerator* gen, DoubleRegister result) |
+ : OutOfLineRound(gen, result) {} |
+}; |
+ |
+ |
+class OutOfLineCeil FINAL : public OutOfLineRound { |
+ public: |
+ OutOfLineCeil(CodeGenerator* gen, DoubleRegister result) |
+ : OutOfLineRound(gen, result) {} |
+}; |
+ |
+ |
} // namespace |
@@ -240,6 +280,26 @@ class OutOfLineLoadInteger FINAL : public OutOfLineCode { |
} while (0) |
+#define ASSEMBLE_ROUND_DOUBLE_TO_DOUBLE(asm_instr, operation) \ |
+ do { \ |
+ auto ool = \ |
+ new (zone()) OutOfLine##operation(this, i.OutputDoubleRegister()); \ |
+ Label done; \ |
+ __ mfhc1(kScratchReg, i.InputDoubleRegister(0)); \ |
+ __ Ext(at, kScratchReg, HeapNumber::kExponentShift, \ |
+ HeapNumber::kExponentBits); \ |
+ __ Branch(USE_DELAY_SLOT, &done, hs, at, \ |
+ Operand(HeapNumber::kExponentBias + HeapNumber::kMantissaBits)); \ |
+ __ mov_d(i.OutputDoubleRegister(), i.InputDoubleRegister(0)); \ |
+ __ asm_instr(i.OutputDoubleRegister(), i.InputDoubleRegister(0)); \ |
+ __ dmfc1(at, i.OutputDoubleRegister()); \ |
+ __ Branch(USE_DELAY_SLOT, ool->entry(), eq, at, Operand(zero_reg)); \ |
+ __ cvt_d_l(i.OutputDoubleRegister(), i.OutputDoubleRegister()); \ |
+ __ bind(ool->exit()); \ |
+ __ bind(&done); \ |
+ } while (0) |
+ |
+ |
// Assembles an instruction after register allocation, producing machine code. |
void CodeGenerator::AssembleArchInstruction(Instruction* instr) { |
MipsOperandConverter i(this, instr); |
@@ -472,19 +532,16 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) { |
__ MovFromFloatResult(i.OutputDoubleRegister()); |
break; |
} |
- case kMips64FloorD: { |
- __ floor_l_d(i.OutputDoubleRegister(), i.InputDoubleRegister(0)); |
- __ cvt_d_l(i.OutputDoubleRegister(), i.OutputDoubleRegister()); |
+ case kMips64Float64Floor: { |
+ ASSEMBLE_ROUND_DOUBLE_TO_DOUBLE(floor_l_d, Floor); |
break; |
} |
- case kMips64CeilD: { |
- __ ceil_l_d(i.OutputDoubleRegister(), i.InputDoubleRegister(0)); |
- __ cvt_d_l(i.OutputDoubleRegister(), i.OutputDoubleRegister()); |
+ case kMips64Float64Ceil: { |
+ ASSEMBLE_ROUND_DOUBLE_TO_DOUBLE(ceil_l_d, Ceil); |
break; |
} |
- case kMips64RoundTruncateD: { |
- __ trunc_l_d(i.OutputDoubleRegister(), i.InputDoubleRegister(0)); |
- __ cvt_d_l(i.OutputDoubleRegister(), i.OutputDoubleRegister()); |
+ case kMips64Float64RoundTruncate: { |
+ ASSEMBLE_ROUND_DOUBLE_TO_DOUBLE(trunc_l_d, Truncate); |
break; |
} |
case kMips64SqrtD: { |