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 9d47f299640c0da0e49632844688ed78bc0b35e0..34ba79aaf767b41d231ef180560bdb616e7149b2 100644 |
--- a/src/compiler/mips64/code-generator-mips64.cc |
+++ b/src/compiler/mips64/code-generator-mips64.cc |
@@ -103,10 +103,7 @@ class MipsOperandConverter FINAL : public InstructionOperandConverter { |
return MemOperand(no_reg); |
} |
- MemOperand MemoryOperand() { |
- int index = 0; |
- return MemoryOperand(&index); |
- } |
+ MemOperand MemoryOperand(int index = 0) { return MemoryOperand(&index); } |
MemOperand ToMemOperand(InstructionOperand* op) const { |
DCHECK(op != NULL); |
@@ -125,6 +122,98 @@ static inline bool HasRegisterInput(Instruction* instr, int index) { |
} |
+namespace { |
+ |
+class OutOfLineLoadSingle FINAL : public OutOfLineCode { |
+ public: |
+ OutOfLineLoadSingle(CodeGenerator* gen, FloatRegister result) |
+ : OutOfLineCode(gen), result_(result) {} |
+ |
+ void Generate() FINAL { |
+ __ Move(result_, std::numeric_limits<float>::quiet_NaN()); |
+ } |
+ |
+ private: |
+ FloatRegister const result_; |
+}; |
+ |
+ |
+class OutOfLineLoadDouble FINAL : public OutOfLineCode { |
+ public: |
+ OutOfLineLoadDouble(CodeGenerator* gen, DoubleRegister result) |
+ : OutOfLineCode(gen), result_(result) {} |
+ |
+ void Generate() FINAL { |
+ __ Move(result_, std::numeric_limits<double>::quiet_NaN()); |
+ } |
+ |
+ private: |
+ DoubleRegister const result_; |
+}; |
+ |
+ |
+class OutOfLineLoadInteger FINAL : public OutOfLineCode { |
+ public: |
+ OutOfLineLoadInteger(CodeGenerator* gen, Register result) |
+ : OutOfLineCode(gen), result_(result) {} |
+ |
+ void Generate() FINAL { __ mov(result_, zero_reg); } |
+ |
+ private: |
+ Register const result_; |
+}; |
+ |
+} // namespace |
+ |
+ |
+#define ASSEMBLE_CHECKED_LOAD_FLOAT(width, asm_instr) \ |
+ do { \ |
+ auto result = i.Output##width##Register(); \ |
+ auto offset = i.InputRegister(0); \ |
+ auto ool = new (zone()) OutOfLineLoad##width(this, result); \ |
+ __ Branch(ool->entry(), hs, offset, Operand(i.InputRegister(1))); \ |
+ __ Daddu(at, i.InputRegister(2), offset); \ |
+ __ asm_instr(result, MemOperand(at, 0)); \ |
+ __ bind(ool->exit()); \ |
+ } while (0) |
+ |
+ |
+#define ASSEMBLE_CHECKED_LOAD_INTEGER(asm_instr) \ |
+ do { \ |
+ auto result = i.OutputRegister(); \ |
+ auto offset = i.InputRegister(0); \ |
+ auto ool = new (zone()) OutOfLineLoadInteger(this, result); \ |
+ __ Branch(ool->entry(), hs, offset, Operand(i.InputRegister(1))); \ |
+ __ Daddu(at, i.InputRegister(2), offset); \ |
+ __ asm_instr(result, MemOperand(at, 0)); \ |
+ __ bind(ool->exit()); \ |
+ } while (0) |
+ |
+ |
+#define ASSEMBLE_CHECKED_STORE_FLOAT(width, asm_instr) \ |
+ do { \ |
+ auto offset = i.InputRegister(0); \ |
+ Label done; \ |
+ __ Branch(&done, hs, offset, Operand(i.InputRegister(1))); \ |
+ auto value = i.Input##width##Register(2); \ |
+ __ Daddu(at, i.InputRegister(3), offset); \ |
+ __ asm_instr(value, MemOperand(at, 0)); \ |
+ __ bind(&done); \ |
+ } while (0) |
+ |
+ |
+#define ASSEMBLE_CHECKED_STORE_INTEGER(asm_instr) \ |
+ do { \ |
+ auto offset = i.InputRegister(0); \ |
+ Label done; \ |
+ __ Branch(&done, hs, offset, Operand(i.InputRegister(1))); \ |
+ auto value = i.InputRegister(2); \ |
+ __ Daddu(at, i.InputRegister(3), offset); \ |
+ __ asm_instr(value, MemOperand(at, 0)); \ |
+ __ bind(&done); \ |
+ } while (0) |
+ |
+ |
// Assembles an instruction after register allocation, producing machine code. |
void CodeGenerator::AssembleArchInstruction(Instruction* instr) { |
MipsOperandConverter i(this, instr); |
@@ -469,7 +558,7 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) { |
__ sd(i.InputRegister(0), MemOperand(sp, slot << kPointerSizeLog2)); |
break; |
} |
- case kMips64StoreWriteBarrier: |
+ case kMips64StoreWriteBarrier: { |
Register object = i.InputRegister(0); |
Register index = i.InputRegister(1); |
Register value = i.InputRegister(2); |
@@ -480,6 +569,43 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) { |
RAStatus ra_status = kRAHasNotBeenSaved; |
__ RecordWrite(object, index, value, ra_status, mode); |
break; |
+ } |
+ case kCheckedLoadInt8: |
+ ASSEMBLE_CHECKED_LOAD_INTEGER(lb); |
+ break; |
+ case kCheckedLoadUint8: |
+ ASSEMBLE_CHECKED_LOAD_INTEGER(lbu); |
+ break; |
+ case kCheckedLoadInt16: |
+ ASSEMBLE_CHECKED_LOAD_INTEGER(lh); |
+ break; |
+ case kCheckedLoadUint16: |
+ ASSEMBLE_CHECKED_LOAD_INTEGER(lhu); |
+ break; |
+ case kCheckedLoadWord32: |
+ ASSEMBLE_CHECKED_LOAD_INTEGER(lw); |
+ break; |
+ case kCheckedLoadFloat32: |
+ ASSEMBLE_CHECKED_LOAD_FLOAT(Single, lwc1); |
+ break; |
+ case kCheckedLoadFloat64: |
+ ASSEMBLE_CHECKED_LOAD_FLOAT(Double, ldc1); |
+ break; |
+ case kCheckedStoreWord8: |
+ ASSEMBLE_CHECKED_STORE_INTEGER(sb); |
+ break; |
+ case kCheckedStoreWord16: |
+ ASSEMBLE_CHECKED_STORE_INTEGER(sh); |
+ break; |
+ case kCheckedStoreWord32: |
+ ASSEMBLE_CHECKED_STORE_INTEGER(sw); |
+ break; |
+ case kCheckedStoreFloat32: |
+ ASSEMBLE_CHECKED_STORE_FLOAT(Single, swc1); |
+ break; |
+ case kCheckedStoreFloat64: |
+ ASSEMBLE_CHECKED_STORE_FLOAT(Double, sdc1); |
+ break; |
} |
} |
@@ -1090,14 +1216,13 @@ void CodeGenerator::AssembleMove(InstructionOperand* source, |
} |
if (destination->IsStackSlot()) __ sd(dst, g.ToMemOperand(destination)); |
} else if (src.type() == Constant::kFloat32) { |
- FPURegister dst = destination->IsDoubleRegister() |
- ? g.ToDoubleRegister(destination) |
- : kScratchDoubleReg.low(); |
- // TODO(turbofan): Can we do better here? |
- __ li(at, Operand(bit_cast<int32_t>(src.ToFloat32()))); |
- __ mtc1(at, dst); |
if (destination->IsDoubleStackSlot()) { |
- __ swc1(dst, g.ToMemOperand(destination)); |
+ MemOperand dst = g.ToMemOperand(destination); |
+ __ li(at, Operand(bit_cast<int32_t>(src.ToFloat32()))); |
+ __ sw(at, dst); |
+ } else { |
+ FloatRegister dst = g.ToSingleRegister(destination); |
+ __ Move(dst, src.ToFloat32()); |
} |
} else { |
DCHECK_EQ(Constant::kFloat64, src.type()); |