| OLD | NEW |
| 1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/compiler/code-generator.h" | 5 #include "src/compiler/code-generator.h" |
| 6 #include "src/compiler/code-generator-impl.h" | 6 #include "src/compiler/code-generator-impl.h" |
| 7 #include "src/compiler/gap-resolver.h" | 7 #include "src/compiler/gap-resolver.h" |
| 8 #include "src/compiler/node-matchers.h" | 8 #include "src/compiler/node-matchers.h" |
| 9 #include "src/compiler/node-properties-inl.h" | 9 #include "src/compiler/node-properties-inl.h" |
| 10 #include "src/mips/macro-assembler-mips.h" | 10 #include "src/mips/macro-assembler-mips.h" |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 95 *first_index += 2; | 95 *first_index += 2; |
| 96 return MemOperand(InputRegister(index + 0), InputInt32(index + 1)); | 96 return MemOperand(InputRegister(index + 0), InputInt32(index + 1)); |
| 97 case kMode_MRR: | 97 case kMode_MRR: |
| 98 // TODO(plind): r6 address mode, to be implemented ... | 98 // TODO(plind): r6 address mode, to be implemented ... |
| 99 UNREACHABLE(); | 99 UNREACHABLE(); |
| 100 } | 100 } |
| 101 UNREACHABLE(); | 101 UNREACHABLE(); |
| 102 return MemOperand(no_reg); | 102 return MemOperand(no_reg); |
| 103 } | 103 } |
| 104 | 104 |
| 105 MemOperand MemoryOperand() { | 105 MemOperand MemoryOperand(int index = 0) { return MemoryOperand(&index); } |
| 106 int index = 0; | |
| 107 return MemoryOperand(&index); | |
| 108 } | |
| 109 | 106 |
| 110 MemOperand ToMemOperand(InstructionOperand* op) const { | 107 MemOperand ToMemOperand(InstructionOperand* op) const { |
| 111 DCHECK(op != NULL); | 108 DCHECK(op != NULL); |
| 112 DCHECK(!op->IsRegister()); | 109 DCHECK(!op->IsRegister()); |
| 113 DCHECK(!op->IsDoubleRegister()); | 110 DCHECK(!op->IsDoubleRegister()); |
| 114 DCHECK(op->IsStackSlot() || op->IsDoubleStackSlot()); | 111 DCHECK(op->IsStackSlot() || op->IsDoubleStackSlot()); |
| 115 // The linkage computes where all spill slots are located. | 112 // The linkage computes where all spill slots are located. |
| 116 FrameOffset offset = linkage()->GetFrameOffset(op->index(), frame(), 0); | 113 FrameOffset offset = linkage()->GetFrameOffset(op->index(), frame(), 0); |
| 117 return MemOperand(offset.from_stack_pointer() ? sp : fp, offset.offset()); | 114 return MemOperand(offset.from_stack_pointer() ? sp : fp, offset.offset()); |
| 118 } | 115 } |
| 119 }; | 116 }; |
| 120 | 117 |
| 121 | 118 |
| 122 static inline bool HasRegisterInput(Instruction* instr, int index) { | 119 static inline bool HasRegisterInput(Instruction* instr, int index) { |
| 123 return instr->InputAt(index)->IsRegister(); | 120 return instr->InputAt(index)->IsRegister(); |
| 124 } | 121 } |
| 125 | 122 |
| 126 | 123 |
| 124 namespace { |
| 125 |
| 126 class OutOfLineLoadSingle FINAL : public OutOfLineCode { |
| 127 public: |
| 128 OutOfLineLoadSingle(CodeGenerator* gen, FloatRegister result) |
| 129 : OutOfLineCode(gen), result_(result) {} |
| 130 |
| 131 void Generate() FINAL { |
| 132 __ Move(result_, std::numeric_limits<float>::quiet_NaN()); |
| 133 } |
| 134 |
| 135 private: |
| 136 FloatRegister const result_; |
| 137 }; |
| 138 |
| 139 |
| 140 class OutOfLineLoadDouble FINAL : public OutOfLineCode { |
| 141 public: |
| 142 OutOfLineLoadDouble(CodeGenerator* gen, DoubleRegister result) |
| 143 : OutOfLineCode(gen), result_(result) {} |
| 144 |
| 145 void Generate() FINAL { |
| 146 __ Move(result_, std::numeric_limits<double>::quiet_NaN()); |
| 147 } |
| 148 |
| 149 private: |
| 150 DoubleRegister const result_; |
| 151 }; |
| 152 |
| 153 |
| 154 class OutOfLineLoadInteger FINAL : public OutOfLineCode { |
| 155 public: |
| 156 OutOfLineLoadInteger(CodeGenerator* gen, Register result) |
| 157 : OutOfLineCode(gen), result_(result) {} |
| 158 |
| 159 void Generate() FINAL { __ mov(result_, zero_reg); } |
| 160 |
| 161 private: |
| 162 Register const result_; |
| 163 }; |
| 164 |
| 165 } // namespace |
| 166 |
| 167 |
| 168 #define ASSEMBLE_CHECKED_LOAD_FLOAT(width, asm_instr) \ |
| 169 do { \ |
| 170 auto result = i.Output##width##Register(); \ |
| 171 auto offset = i.InputRegister(0); \ |
| 172 auto ool = new (zone()) OutOfLineLoad##width(this, result); \ |
| 173 __ Branch(ool->entry(), hs, offset, Operand(i.InputRegister(1))); \ |
| 174 __ addu(at, i.InputRegister(2), offset); \ |
| 175 __ asm_instr(result, MemOperand(at, 0)); \ |
| 176 __ bind(ool->exit()); \ |
| 177 } while (0) |
| 178 |
| 179 |
| 180 #define ASSEMBLE_CHECKED_LOAD_INTEGER(asm_instr) \ |
| 181 do { \ |
| 182 auto result = i.OutputRegister(); \ |
| 183 auto offset = i.InputRegister(0); \ |
| 184 auto ool = new (zone()) OutOfLineLoadInteger(this, result); \ |
| 185 __ Branch(ool->entry(), hs, offset, Operand(i.InputRegister(1))); \ |
| 186 __ addu(at, i.InputRegister(2), offset); \ |
| 187 __ asm_instr(result, MemOperand(at, 0)); \ |
| 188 __ bind(ool->exit()); \ |
| 189 } while (0) |
| 190 |
| 191 |
| 192 #define ASSEMBLE_CHECKED_STORE_FLOAT(width, asm_instr) \ |
| 193 do { \ |
| 194 auto offset = i.InputRegister(0); \ |
| 195 Label done; \ |
| 196 __ Branch(&done, hs, offset, Operand(i.InputRegister(1))); \ |
| 197 auto value = i.Input##width##Register(2); \ |
| 198 __ addu(at, i.InputRegister(3), offset); \ |
| 199 __ asm_instr(value, MemOperand(at, 0)); \ |
| 200 __ bind(&done); \ |
| 201 } while (0) |
| 202 |
| 203 |
| 204 #define ASSEMBLE_CHECKED_STORE_INTEGER(asm_instr) \ |
| 205 do { \ |
| 206 auto offset = i.InputRegister(0); \ |
| 207 Label done; \ |
| 208 __ Branch(&done, hs, offset, Operand(i.InputRegister(1))); \ |
| 209 auto value = i.InputRegister(2); \ |
| 210 __ addu(at, i.InputRegister(3), offset); \ |
| 211 __ asm_instr(value, MemOperand(at, 0)); \ |
| 212 __ bind(&done); \ |
| 213 } while (0) |
| 214 |
| 215 |
| 127 // Assembles an instruction after register allocation, producing machine code. | 216 // Assembles an instruction after register allocation, producing machine code. |
| 128 void CodeGenerator::AssembleArchInstruction(Instruction* instr) { | 217 void CodeGenerator::AssembleArchInstruction(Instruction* instr) { |
| 129 MipsOperandConverter i(this, instr); | 218 MipsOperandConverter i(this, instr); |
| 130 InstructionCode opcode = instr->opcode(); | 219 InstructionCode opcode = instr->opcode(); |
| 131 | 220 |
| 132 switch (ArchOpcodeField::decode(opcode)) { | 221 switch (ArchOpcodeField::decode(opcode)) { |
| 133 case kArchCallCodeObject: { | 222 case kArchCallCodeObject: { |
| 134 EnsureSpaceForLazyDeopt(); | 223 EnsureSpaceForLazyDeopt(); |
| 135 if (instr->InputAt(0)->IsImmediate()) { | 224 if (instr->InputAt(0)->IsImmediate()) { |
| 136 __ Call(Handle<Code>::cast(i.InputHeapObject(0)), | 225 __ Call(Handle<Code>::cast(i.InputHeapObject(0)), |
| (...skipping 229 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 366 } | 455 } |
| 367 case kMipsLdc1: | 456 case kMipsLdc1: |
| 368 __ ldc1(i.OutputDoubleRegister(), i.MemoryOperand()); | 457 __ ldc1(i.OutputDoubleRegister(), i.MemoryOperand()); |
| 369 break; | 458 break; |
| 370 case kMipsSdc1: | 459 case kMipsSdc1: |
| 371 __ sdc1(i.InputDoubleRegister(2), i.MemoryOperand()); | 460 __ sdc1(i.InputDoubleRegister(2), i.MemoryOperand()); |
| 372 break; | 461 break; |
| 373 case kMipsPush: | 462 case kMipsPush: |
| 374 __ Push(i.InputRegister(0)); | 463 __ Push(i.InputRegister(0)); |
| 375 break; | 464 break; |
| 376 case kMipsStoreWriteBarrier: | 465 case kMipsStoreWriteBarrier: { |
| 377 Register object = i.InputRegister(0); | 466 Register object = i.InputRegister(0); |
| 378 Register index = i.InputRegister(1); | 467 Register index = i.InputRegister(1); |
| 379 Register value = i.InputRegister(2); | 468 Register value = i.InputRegister(2); |
| 380 __ addu(index, object, index); | 469 __ addu(index, object, index); |
| 381 __ sw(value, MemOperand(index)); | 470 __ sw(value, MemOperand(index)); |
| 382 SaveFPRegsMode mode = | 471 SaveFPRegsMode mode = |
| 383 frame()->DidAllocateDoubleRegisters() ? kSaveFPRegs : kDontSaveFPRegs; | 472 frame()->DidAllocateDoubleRegisters() ? kSaveFPRegs : kDontSaveFPRegs; |
| 384 RAStatus ra_status = kRAHasNotBeenSaved; | 473 RAStatus ra_status = kRAHasNotBeenSaved; |
| 385 __ RecordWrite(object, index, value, ra_status, mode); | 474 __ RecordWrite(object, index, value, ra_status, mode); |
| 386 break; | 475 break; |
| 476 } |
| 477 case kCheckedLoadInt8: |
| 478 ASSEMBLE_CHECKED_LOAD_INTEGER(lb); |
| 479 break; |
| 480 case kCheckedLoadUint8: |
| 481 ASSEMBLE_CHECKED_LOAD_INTEGER(lbu); |
| 482 break; |
| 483 case kCheckedLoadInt16: |
| 484 ASSEMBLE_CHECKED_LOAD_INTEGER(lh); |
| 485 break; |
| 486 case kCheckedLoadUint16: |
| 487 ASSEMBLE_CHECKED_LOAD_INTEGER(lhu); |
| 488 break; |
| 489 case kCheckedLoadWord32: |
| 490 ASSEMBLE_CHECKED_LOAD_INTEGER(lw); |
| 491 break; |
| 492 case kCheckedLoadFloat32: |
| 493 ASSEMBLE_CHECKED_LOAD_FLOAT(Single, lwc1); |
| 494 break; |
| 495 case kCheckedLoadFloat64: |
| 496 ASSEMBLE_CHECKED_LOAD_FLOAT(Double, ldc1); |
| 497 break; |
| 498 case kCheckedStoreWord8: |
| 499 ASSEMBLE_CHECKED_STORE_INTEGER(sb); |
| 500 break; |
| 501 case kCheckedStoreWord16: |
| 502 ASSEMBLE_CHECKED_STORE_INTEGER(sh); |
| 503 break; |
| 504 case kCheckedStoreWord32: |
| 505 ASSEMBLE_CHECKED_STORE_INTEGER(sw); |
| 506 break; |
| 507 case kCheckedStoreFloat32: |
| 508 ASSEMBLE_CHECKED_STORE_FLOAT(Single, swc1); |
| 509 break; |
| 510 case kCheckedStoreFloat64: |
| 511 ASSEMBLE_CHECKED_STORE_FLOAT(Double, sdc1); |
| 512 break; |
| 387 } | 513 } |
| 388 } | 514 } |
| 389 | 515 |
| 390 | 516 |
| 391 #define UNSUPPORTED_COND(opcode, condition) \ | 517 #define UNSUPPORTED_COND(opcode, condition) \ |
| 392 OFStream out(stdout); \ | 518 OFStream out(stdout); \ |
| 393 out << "Unsupported " << #opcode << " condition: \"" << condition << "\""; \ | 519 out << "Unsupported " << #opcode << " condition: \"" << condition << "\""; \ |
| 394 UNIMPLEMENTED(); | 520 UNIMPLEMENTED(); |
| 395 | 521 |
| 396 // Assembles branches after an instruction. | 522 // Assembles branches after an instruction. |
| (...skipping 401 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 798 break; | 924 break; |
| 799 case Constant::kHeapObject: | 925 case Constant::kHeapObject: |
| 800 __ li(dst, src.ToHeapObject()); | 926 __ li(dst, src.ToHeapObject()); |
| 801 break; | 927 break; |
| 802 case Constant::kRpoNumber: | 928 case Constant::kRpoNumber: |
| 803 UNREACHABLE(); // TODO(titzer): loading RPO numbers on mips. | 929 UNREACHABLE(); // TODO(titzer): loading RPO numbers on mips. |
| 804 break; | 930 break; |
| 805 } | 931 } |
| 806 if (destination->IsStackSlot()) __ sw(dst, g.ToMemOperand(destination)); | 932 if (destination->IsStackSlot()) __ sw(dst, g.ToMemOperand(destination)); |
| 807 } else if (src.type() == Constant::kFloat32) { | 933 } else if (src.type() == Constant::kFloat32) { |
| 808 FPURegister dst = destination->IsDoubleRegister() | |
| 809 ? g.ToDoubleRegister(destination) | |
| 810 : kScratchDoubleReg.low(); | |
| 811 // TODO(turbofan): Can we do better here? | |
| 812 __ li(at, Operand(bit_cast<int32_t>(src.ToFloat32()))); | |
| 813 __ mtc1(at, dst); | |
| 814 if (destination->IsDoubleStackSlot()) { | 934 if (destination->IsDoubleStackSlot()) { |
| 815 __ swc1(dst, g.ToMemOperand(destination)); | 935 MemOperand dst = g.ToMemOperand(destination); |
| 936 __ li(at, Operand(bit_cast<int32_t>(src.ToFloat32()))); |
| 937 __ sw(at, dst); |
| 938 } else { |
| 939 FloatRegister dst = g.ToSingleRegister(destination); |
| 940 __ Move(dst, src.ToFloat32()); |
| 816 } | 941 } |
| 817 } else { | 942 } else { |
| 818 DCHECK_EQ(Constant::kFloat64, src.type()); | 943 DCHECK_EQ(Constant::kFloat64, src.type()); |
| 819 DoubleRegister dst = destination->IsDoubleRegister() | 944 DoubleRegister dst = destination->IsDoubleRegister() |
| 820 ? g.ToDoubleRegister(destination) | 945 ? g.ToDoubleRegister(destination) |
| 821 : kScratchDoubleReg; | 946 : kScratchDoubleReg; |
| 822 __ Move(dst, src.ToFloat64()); | 947 __ Move(dst, src.ToFloat64()); |
| 823 if (destination->IsDoubleStackSlot()) { | 948 if (destination->IsDoubleStackSlot()) { |
| 824 __ sdc1(dst, g.ToMemOperand(destination)); | 949 __ sdc1(dst, g.ToMemOperand(destination)); |
| 825 } | 950 } |
| (...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 942 } | 1067 } |
| 943 } | 1068 } |
| 944 MarkLazyDeoptSite(); | 1069 MarkLazyDeoptSite(); |
| 945 } | 1070 } |
| 946 | 1071 |
| 947 #undef __ | 1072 #undef __ |
| 948 | 1073 |
| 949 } // namespace compiler | 1074 } // namespace compiler |
| 950 } // namespace internal | 1075 } // namespace internal |
| 951 } // namespace v8 | 1076 } // namespace v8 |
| OLD | NEW |