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 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
96 *first_index += 2; | 96 *first_index += 2; |
97 return MemOperand(InputRegister(index + 0), InputInt32(index + 1)); | 97 return MemOperand(InputRegister(index + 0), InputInt32(index + 1)); |
98 case kMode_MRR: | 98 case kMode_MRR: |
99 // TODO(plind): r6 address mode, to be implemented ... | 99 // TODO(plind): r6 address mode, to be implemented ... |
100 UNREACHABLE(); | 100 UNREACHABLE(); |
101 } | 101 } |
102 UNREACHABLE(); | 102 UNREACHABLE(); |
103 return MemOperand(no_reg); | 103 return MemOperand(no_reg); |
104 } | 104 } |
105 | 105 |
106 MemOperand MemoryOperand() { | 106 MemOperand MemoryOperand(int index = 0) { return MemoryOperand(&index); } |
107 int index = 0; | |
108 return MemoryOperand(&index); | |
109 } | |
110 | 107 |
111 MemOperand ToMemOperand(InstructionOperand* op) const { | 108 MemOperand ToMemOperand(InstructionOperand* op) const { |
112 DCHECK(op != NULL); | 109 DCHECK(op != NULL); |
113 DCHECK(!op->IsRegister()); | 110 DCHECK(!op->IsRegister()); |
114 DCHECK(!op->IsDoubleRegister()); | 111 DCHECK(!op->IsDoubleRegister()); |
115 DCHECK(op->IsStackSlot() || op->IsDoubleStackSlot()); | 112 DCHECK(op->IsStackSlot() || op->IsDoubleStackSlot()); |
116 // The linkage computes where all spill slots are located. | 113 // The linkage computes where all spill slots are located. |
117 FrameOffset offset = linkage()->GetFrameOffset(op->index(), frame(), 0); | 114 FrameOffset offset = linkage()->GetFrameOffset(op->index(), frame(), 0); |
118 return MemOperand(offset.from_stack_pointer() ? sp : fp, offset.offset()); | 115 return MemOperand(offset.from_stack_pointer() ? sp : fp, offset.offset()); |
119 } | 116 } |
120 }; | 117 }; |
121 | 118 |
122 | 119 |
123 static inline bool HasRegisterInput(Instruction* instr, int index) { | 120 static inline bool HasRegisterInput(Instruction* instr, int index) { |
124 return instr->InputAt(index)->IsRegister(); | 121 return instr->InputAt(index)->IsRegister(); |
125 } | 122 } |
126 | 123 |
127 | 124 |
| 125 namespace { |
| 126 |
| 127 class OutOfLineLoadSingle FINAL : public OutOfLineCode { |
| 128 public: |
| 129 OutOfLineLoadSingle(CodeGenerator* gen, FloatRegister result) |
| 130 : OutOfLineCode(gen), result_(result) {} |
| 131 |
| 132 void Generate() FINAL { |
| 133 __ Move(result_, std::numeric_limits<float>::quiet_NaN()); |
| 134 } |
| 135 |
| 136 private: |
| 137 FloatRegister const result_; |
| 138 }; |
| 139 |
| 140 |
| 141 class OutOfLineLoadDouble FINAL : public OutOfLineCode { |
| 142 public: |
| 143 OutOfLineLoadDouble(CodeGenerator* gen, DoubleRegister result) |
| 144 : OutOfLineCode(gen), result_(result) {} |
| 145 |
| 146 void Generate() FINAL { |
| 147 __ Move(result_, std::numeric_limits<double>::quiet_NaN()); |
| 148 } |
| 149 |
| 150 private: |
| 151 DoubleRegister const result_; |
| 152 }; |
| 153 |
| 154 |
| 155 class OutOfLineLoadInteger FINAL : public OutOfLineCode { |
| 156 public: |
| 157 OutOfLineLoadInteger(CodeGenerator* gen, Register result) |
| 158 : OutOfLineCode(gen), result_(result) {} |
| 159 |
| 160 void Generate() FINAL { __ mov(result_, zero_reg); } |
| 161 |
| 162 private: |
| 163 Register const result_; |
| 164 }; |
| 165 |
| 166 } // namespace |
| 167 |
| 168 |
| 169 #define ASSEMBLE_CHECKED_LOAD_FLOAT(width, asm_instr) \ |
| 170 do { \ |
| 171 auto result = i.Output##width##Register(); \ |
| 172 auto offset = i.InputRegister(0); \ |
| 173 auto ool = new (zone()) OutOfLineLoad##width(this, result); \ |
| 174 __ Branch(ool->entry(), hs, offset, Operand(i.InputRegister(1))); \ |
| 175 __ Daddu(at, i.InputRegister(2), offset); \ |
| 176 __ asm_instr(result, MemOperand(at, 0)); \ |
| 177 __ bind(ool->exit()); \ |
| 178 } while (0) |
| 179 |
| 180 |
| 181 #define ASSEMBLE_CHECKED_LOAD_INTEGER(asm_instr) \ |
| 182 do { \ |
| 183 auto result = i.OutputRegister(); \ |
| 184 auto offset = i.InputRegister(0); \ |
| 185 auto ool = new (zone()) OutOfLineLoadInteger(this, result); \ |
| 186 __ Branch(ool->entry(), hs, offset, Operand(i.InputRegister(1))); \ |
| 187 __ Daddu(at, i.InputRegister(2), offset); \ |
| 188 __ asm_instr(result, MemOperand(at, 0)); \ |
| 189 __ bind(ool->exit()); \ |
| 190 } while (0) |
| 191 |
| 192 |
| 193 #define ASSEMBLE_CHECKED_STORE_FLOAT(width, asm_instr) \ |
| 194 do { \ |
| 195 auto offset = i.InputRegister(0); \ |
| 196 Label done; \ |
| 197 __ Branch(&done, hs, offset, Operand(i.InputRegister(1))); \ |
| 198 auto value = i.Input##width##Register(2); \ |
| 199 __ Daddu(at, i.InputRegister(3), offset); \ |
| 200 __ asm_instr(value, MemOperand(at, 0)); \ |
| 201 __ bind(&done); \ |
| 202 } while (0) |
| 203 |
| 204 |
| 205 #define ASSEMBLE_CHECKED_STORE_INTEGER(asm_instr) \ |
| 206 do { \ |
| 207 auto offset = i.InputRegister(0); \ |
| 208 Label done; \ |
| 209 __ Branch(&done, hs, offset, Operand(i.InputRegister(1))); \ |
| 210 auto value = i.InputRegister(2); \ |
| 211 __ Daddu(at, i.InputRegister(3), offset); \ |
| 212 __ asm_instr(value, MemOperand(at, 0)); \ |
| 213 __ bind(&done); \ |
| 214 } while (0) |
| 215 |
| 216 |
128 // Assembles an instruction after register allocation, producing machine code. | 217 // Assembles an instruction after register allocation, producing machine code. |
129 void CodeGenerator::AssembleArchInstruction(Instruction* instr) { | 218 void CodeGenerator::AssembleArchInstruction(Instruction* instr) { |
130 MipsOperandConverter i(this, instr); | 219 MipsOperandConverter i(this, instr); |
131 InstructionCode opcode = instr->opcode(); | 220 InstructionCode opcode = instr->opcode(); |
132 | 221 |
133 switch (ArchOpcodeField::decode(opcode)) { | 222 switch (ArchOpcodeField::decode(opcode)) { |
134 case kArchCallCodeObject: { | 223 case kArchCallCodeObject: { |
135 EnsureSpaceForLazyDeopt(); | 224 EnsureSpaceForLazyDeopt(); |
136 if (instr->InputAt(0)->IsImmediate()) { | 225 if (instr->InputAt(0)->IsImmediate()) { |
137 __ Call(Handle<Code>::cast(i.InputHeapObject(0)), | 226 __ Call(Handle<Code>::cast(i.InputHeapObject(0)), |
(...skipping 324 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
462 case kMips64StackClaim: { | 551 case kMips64StackClaim: { |
463 int words = MiscField::decode(instr->opcode()); | 552 int words = MiscField::decode(instr->opcode()); |
464 __ Dsubu(sp, sp, Operand(words << kPointerSizeLog2)); | 553 __ Dsubu(sp, sp, Operand(words << kPointerSizeLog2)); |
465 break; | 554 break; |
466 } | 555 } |
467 case kMips64StoreToStackSlot: { | 556 case kMips64StoreToStackSlot: { |
468 int slot = MiscField::decode(instr->opcode()); | 557 int slot = MiscField::decode(instr->opcode()); |
469 __ sd(i.InputRegister(0), MemOperand(sp, slot << kPointerSizeLog2)); | 558 __ sd(i.InputRegister(0), MemOperand(sp, slot << kPointerSizeLog2)); |
470 break; | 559 break; |
471 } | 560 } |
472 case kMips64StoreWriteBarrier: | 561 case kMips64StoreWriteBarrier: { |
473 Register object = i.InputRegister(0); | 562 Register object = i.InputRegister(0); |
474 Register index = i.InputRegister(1); | 563 Register index = i.InputRegister(1); |
475 Register value = i.InputRegister(2); | 564 Register value = i.InputRegister(2); |
476 __ daddu(index, object, index); | 565 __ daddu(index, object, index); |
477 __ sd(value, MemOperand(index)); | 566 __ sd(value, MemOperand(index)); |
478 SaveFPRegsMode mode = | 567 SaveFPRegsMode mode = |
479 frame()->DidAllocateDoubleRegisters() ? kSaveFPRegs : kDontSaveFPRegs; | 568 frame()->DidAllocateDoubleRegisters() ? kSaveFPRegs : kDontSaveFPRegs; |
480 RAStatus ra_status = kRAHasNotBeenSaved; | 569 RAStatus ra_status = kRAHasNotBeenSaved; |
481 __ RecordWrite(object, index, value, ra_status, mode); | 570 __ RecordWrite(object, index, value, ra_status, mode); |
482 break; | 571 break; |
| 572 } |
| 573 case kCheckedLoadInt8: |
| 574 ASSEMBLE_CHECKED_LOAD_INTEGER(lb); |
| 575 break; |
| 576 case kCheckedLoadUint8: |
| 577 ASSEMBLE_CHECKED_LOAD_INTEGER(lbu); |
| 578 break; |
| 579 case kCheckedLoadInt16: |
| 580 ASSEMBLE_CHECKED_LOAD_INTEGER(lh); |
| 581 break; |
| 582 case kCheckedLoadUint16: |
| 583 ASSEMBLE_CHECKED_LOAD_INTEGER(lhu); |
| 584 break; |
| 585 case kCheckedLoadWord32: |
| 586 ASSEMBLE_CHECKED_LOAD_INTEGER(lw); |
| 587 break; |
| 588 case kCheckedLoadFloat32: |
| 589 ASSEMBLE_CHECKED_LOAD_FLOAT(Single, lwc1); |
| 590 break; |
| 591 case kCheckedLoadFloat64: |
| 592 ASSEMBLE_CHECKED_LOAD_FLOAT(Double, ldc1); |
| 593 break; |
| 594 case kCheckedStoreWord8: |
| 595 ASSEMBLE_CHECKED_STORE_INTEGER(sb); |
| 596 break; |
| 597 case kCheckedStoreWord16: |
| 598 ASSEMBLE_CHECKED_STORE_INTEGER(sh); |
| 599 break; |
| 600 case kCheckedStoreWord32: |
| 601 ASSEMBLE_CHECKED_STORE_INTEGER(sw); |
| 602 break; |
| 603 case kCheckedStoreFloat32: |
| 604 ASSEMBLE_CHECKED_STORE_FLOAT(Single, swc1); |
| 605 break; |
| 606 case kCheckedStoreFloat64: |
| 607 ASSEMBLE_CHECKED_STORE_FLOAT(Double, sdc1); |
| 608 break; |
483 } | 609 } |
484 } | 610 } |
485 | 611 |
486 | 612 |
487 #define UNSUPPORTED_COND(opcode, condition) \ | 613 #define UNSUPPORTED_COND(opcode, condition) \ |
488 OFStream out(stdout); \ | 614 OFStream out(stdout); \ |
489 out << "Unsupported " << #opcode << " condition: \"" << condition << "\""; \ | 615 out << "Unsupported " << #opcode << " condition: \"" << condition << "\""; \ |
490 UNIMPLEMENTED(); | 616 UNIMPLEMENTED(); |
491 | 617 |
492 // Assembles branches after an instruction. | 618 // Assembles branches after an instruction. |
(...skipping 590 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1083 break; | 1209 break; |
1084 case Constant::kHeapObject: | 1210 case Constant::kHeapObject: |
1085 __ li(dst, src.ToHeapObject()); | 1211 __ li(dst, src.ToHeapObject()); |
1086 break; | 1212 break; |
1087 case Constant::kRpoNumber: | 1213 case Constant::kRpoNumber: |
1088 UNREACHABLE(); // TODO(titzer): loading RPO numbers on mips64. | 1214 UNREACHABLE(); // TODO(titzer): loading RPO numbers on mips64. |
1089 break; | 1215 break; |
1090 } | 1216 } |
1091 if (destination->IsStackSlot()) __ sd(dst, g.ToMemOperand(destination)); | 1217 if (destination->IsStackSlot()) __ sd(dst, g.ToMemOperand(destination)); |
1092 } else if (src.type() == Constant::kFloat32) { | 1218 } else if (src.type() == Constant::kFloat32) { |
1093 FPURegister dst = destination->IsDoubleRegister() | |
1094 ? g.ToDoubleRegister(destination) | |
1095 : kScratchDoubleReg.low(); | |
1096 // TODO(turbofan): Can we do better here? | |
1097 __ li(at, Operand(bit_cast<int32_t>(src.ToFloat32()))); | |
1098 __ mtc1(at, dst); | |
1099 if (destination->IsDoubleStackSlot()) { | 1219 if (destination->IsDoubleStackSlot()) { |
1100 __ swc1(dst, g.ToMemOperand(destination)); | 1220 MemOperand dst = g.ToMemOperand(destination); |
| 1221 __ li(at, Operand(bit_cast<int32_t>(src.ToFloat32()))); |
| 1222 __ sw(at, dst); |
| 1223 } else { |
| 1224 FloatRegister dst = g.ToSingleRegister(destination); |
| 1225 __ Move(dst, src.ToFloat32()); |
1101 } | 1226 } |
1102 } else { | 1227 } else { |
1103 DCHECK_EQ(Constant::kFloat64, src.type()); | 1228 DCHECK_EQ(Constant::kFloat64, src.type()); |
1104 DoubleRegister dst = destination->IsDoubleRegister() | 1229 DoubleRegister dst = destination->IsDoubleRegister() |
1105 ? g.ToDoubleRegister(destination) | 1230 ? g.ToDoubleRegister(destination) |
1106 : kScratchDoubleReg; | 1231 : kScratchDoubleReg; |
1107 __ Move(dst, src.ToFloat64()); | 1232 __ Move(dst, src.ToFloat64()); |
1108 if (destination->IsDoubleStackSlot()) { | 1233 if (destination->IsDoubleStackSlot()) { |
1109 __ sdc1(dst, g.ToMemOperand(destination)); | 1234 __ sdc1(dst, g.ToMemOperand(destination)); |
1110 } | 1235 } |
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1227 } | 1352 } |
1228 } | 1353 } |
1229 MarkLazyDeoptSite(); | 1354 MarkLazyDeoptSite(); |
1230 } | 1355 } |
1231 | 1356 |
1232 #undef __ | 1357 #undef __ |
1233 | 1358 |
1234 } // namespace compiler | 1359 } // namespace compiler |
1235 } // namespace internal | 1360 } // namespace internal |
1236 } // namespace v8 | 1361 } // namespace v8 |
OLD | NEW |