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 |