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/base/bits.h" | 5 #include "src/base/bits.h" |
6 #include "src/compiler/instruction-selector-impl.h" | 6 #include "src/compiler/instruction-selector-impl.h" |
7 #include "src/compiler/node-matchers.h" | 7 #include "src/compiler/node-matchers.h" |
8 #include "src/compiler/node-properties.h" | 8 #include "src/compiler/node-properties.h" |
9 | 9 |
10 namespace v8 { | 10 namespace v8 { |
11 namespace internal { | 11 namespace internal { |
12 namespace compiler { | 12 namespace compiler { |
13 | 13 |
14 #define TRACE_UNIMPL() \ | 14 #define TRACE_UNIMPL() \ |
15 PrintF("UNIMPLEMENTED instr_sel: %s at line %d\n", __FUNCTION__, __LINE__) | 15 PrintF("UNIMPLEMENTED instr_sel: %s at line %d\n", __FUNCTION__, __LINE__) |
16 | 16 |
17 #define TRACE() PrintF("instr_sel: %s at line %d\n", __FUNCTION__, __LINE__) | 17 #define TRACE() PrintF("instr_sel: %s at line %d\n", __FUNCTION__, __LINE__) |
18 | 18 |
19 | 19 |
20 // Adds Mips-specific methods for generating InstructionOperands. | 20 // Adds Mips-specific methods for generating InstructionOperands. |
21 class Mips64OperandGenerator FINAL : public OperandGenerator { | 21 class Mips64OperandGenerator FINAL : public OperandGenerator { |
22 public: | 22 public: |
23 explicit Mips64OperandGenerator(InstructionSelector* selector) | 23 explicit Mips64OperandGenerator(InstructionSelector* selector) |
24 : OperandGenerator(selector) {} | 24 : OperandGenerator(selector) {} |
25 | 25 |
26 InstructionOperand* UseOperand(Node* node, InstructionCode opcode) { | 26 InstructionOperand UseOperand(Node* node, InstructionCode opcode) { |
27 if (CanBeImmediate(node, opcode)) { | 27 if (CanBeImmediate(node, opcode)) { |
28 return UseImmediate(node); | 28 return UseImmediate(node); |
29 } | 29 } |
30 return UseRegister(node); | 30 return UseRegister(node); |
31 } | 31 } |
32 | 32 |
33 bool CanBeImmediate(Node* node, InstructionCode opcode) { | 33 bool CanBeImmediate(Node* node, InstructionCode opcode) { |
34 int64_t value; | 34 int64_t value; |
35 if (node->opcode() == IrOpcode::kInt32Constant) | 35 if (node->opcode() == IrOpcode::kInt32Constant) |
36 value = OpParameter<int32_t>(node); | 36 value = OpParameter<int32_t>(node); |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
117 selector->Emit(opcode, g.DefineAsRegister(node), | 117 selector->Emit(opcode, g.DefineAsRegister(node), |
118 g.UseRegister(node->InputAt(0)), | 118 g.UseRegister(node->InputAt(0)), |
119 g.UseOperand(node->InputAt(1), opcode)); | 119 g.UseOperand(node->InputAt(1), opcode)); |
120 } | 120 } |
121 | 121 |
122 | 122 |
123 static void VisitBinop(InstructionSelector* selector, Node* node, | 123 static void VisitBinop(InstructionSelector* selector, Node* node, |
124 InstructionCode opcode, FlagsContinuation* cont) { | 124 InstructionCode opcode, FlagsContinuation* cont) { |
125 Mips64OperandGenerator g(selector); | 125 Mips64OperandGenerator g(selector); |
126 Int32BinopMatcher m(node); | 126 Int32BinopMatcher m(node); |
127 InstructionOperand* inputs[4]; | 127 InstructionOperand inputs[4]; |
128 size_t input_count = 0; | 128 size_t input_count = 0; |
129 InstructionOperand* outputs[2]; | 129 InstructionOperand outputs[2]; |
130 size_t output_count = 0; | 130 size_t output_count = 0; |
131 | 131 |
132 inputs[input_count++] = g.UseRegister(m.left().node()); | 132 inputs[input_count++] = g.UseRegister(m.left().node()); |
133 inputs[input_count++] = g.UseOperand(m.right().node(), opcode); | 133 inputs[input_count++] = g.UseOperand(m.right().node(), opcode); |
134 | 134 |
135 if (cont->IsBranch()) { | 135 if (cont->IsBranch()) { |
136 inputs[input_count++] = g.Label(cont->true_block()); | 136 inputs[input_count++] = g.Label(cont->true_block()); |
137 inputs[input_count++] = g.Label(cont->false_block()); | 137 inputs[input_count++] = g.Label(cont->false_block()); |
138 } | 138 } |
139 | 139 |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
191 break; | 191 break; |
192 default: | 192 default: |
193 UNREACHABLE(); | 193 UNREACHABLE(); |
194 return; | 194 return; |
195 } | 195 } |
196 | 196 |
197 if (g.CanBeImmediate(index, opcode)) { | 197 if (g.CanBeImmediate(index, opcode)) { |
198 Emit(opcode | AddressingModeField::encode(kMode_MRI), | 198 Emit(opcode | AddressingModeField::encode(kMode_MRI), |
199 g.DefineAsRegister(node), g.UseRegister(base), g.UseImmediate(index)); | 199 g.DefineAsRegister(node), g.UseRegister(base), g.UseImmediate(index)); |
200 } else { | 200 } else { |
201 InstructionOperand* addr_reg = g.TempRegister(); | 201 InstructionOperand addr_reg = g.TempRegister(); |
202 Emit(kMips64Dadd | AddressingModeField::encode(kMode_None), addr_reg, | 202 Emit(kMips64Dadd | AddressingModeField::encode(kMode_None), addr_reg, |
203 g.UseRegister(index), g.UseRegister(base)); | 203 g.UseRegister(index), g.UseRegister(base)); |
204 // Emit desired load opcode, using temp addr_reg. | 204 // Emit desired load opcode, using temp addr_reg. |
205 Emit(opcode | AddressingModeField::encode(kMode_MRI), | 205 Emit(opcode | AddressingModeField::encode(kMode_MRI), |
206 g.DefineAsRegister(node), addr_reg, g.TempImmediate(0)); | 206 g.DefineAsRegister(node), addr_reg, g.TempImmediate(0)); |
207 } | 207 } |
208 } | 208 } |
209 | 209 |
210 | 210 |
211 void InstructionSelector::VisitStore(Node* node) { | 211 void InstructionSelector::VisitStore(Node* node) { |
212 Mips64OperandGenerator g(this); | 212 Mips64OperandGenerator g(this); |
213 Node* base = node->InputAt(0); | 213 Node* base = node->InputAt(0); |
214 Node* index = node->InputAt(1); | 214 Node* index = node->InputAt(1); |
215 Node* value = node->InputAt(2); | 215 Node* value = node->InputAt(2); |
216 | 216 |
217 StoreRepresentation store_rep = OpParameter<StoreRepresentation>(node); | 217 StoreRepresentation store_rep = OpParameter<StoreRepresentation>(node); |
218 MachineType rep = RepresentationOf(store_rep.machine_type()); | 218 MachineType rep = RepresentationOf(store_rep.machine_type()); |
219 if (store_rep.write_barrier_kind() == kFullWriteBarrier) { | 219 if (store_rep.write_barrier_kind() == kFullWriteBarrier) { |
220 DCHECK(rep == kRepTagged); | 220 DCHECK(rep == kRepTagged); |
221 // TODO(dcarney): refactor RecordWrite function to take temp registers | 221 // TODO(dcarney): refactor RecordWrite function to take temp registers |
222 // and pass them here instead of using fixed regs | 222 // and pass them here instead of using fixed regs |
223 // TODO(dcarney): handle immediate indices. | 223 // TODO(dcarney): handle immediate indices. |
224 InstructionOperand* temps[] = {g.TempRegister(t1), g.TempRegister(t2)}; | 224 InstructionOperand temps[] = {g.TempRegister(t1), g.TempRegister(t2)}; |
225 Emit(kMips64StoreWriteBarrier, NULL, g.UseFixed(base, t0), | 225 Emit(kMips64StoreWriteBarrier, g.NoOutput(), g.UseFixed(base, t0), |
226 g.UseFixed(index, t1), g.UseFixed(value, t2), arraysize(temps), temps); | 226 g.UseFixed(index, t1), g.UseFixed(value, t2), arraysize(temps), temps); |
227 return; | 227 return; |
228 } | 228 } |
229 DCHECK_EQ(kNoWriteBarrier, store_rep.write_barrier_kind()); | 229 DCHECK_EQ(kNoWriteBarrier, store_rep.write_barrier_kind()); |
230 | 230 |
231 ArchOpcode opcode; | 231 ArchOpcode opcode; |
232 switch (rep) { | 232 switch (rep) { |
233 case kRepFloat32: | 233 case kRepFloat32: |
234 opcode = kMips64Swc1; | 234 opcode = kMips64Swc1; |
235 break; | 235 break; |
(...skipping 13 matching lines...) Expand all Loading... |
249 case kRepTagged: // Fall through. | 249 case kRepTagged: // Fall through. |
250 case kRepWord64: | 250 case kRepWord64: |
251 opcode = kMips64Sd; | 251 opcode = kMips64Sd; |
252 break; | 252 break; |
253 default: | 253 default: |
254 UNREACHABLE(); | 254 UNREACHABLE(); |
255 return; | 255 return; |
256 } | 256 } |
257 | 257 |
258 if (g.CanBeImmediate(index, opcode)) { | 258 if (g.CanBeImmediate(index, opcode)) { |
259 Emit(opcode | AddressingModeField::encode(kMode_MRI), NULL, | 259 Emit(opcode | AddressingModeField::encode(kMode_MRI), g.NoOutput(), |
260 g.UseRegister(base), g.UseImmediate(index), g.UseRegister(value)); | 260 g.UseRegister(base), g.UseImmediate(index), g.UseRegister(value)); |
261 } else { | 261 } else { |
262 InstructionOperand* addr_reg = g.TempRegister(); | 262 InstructionOperand addr_reg = g.TempRegister(); |
263 Emit(kMips64Dadd | AddressingModeField::encode(kMode_None), addr_reg, | 263 Emit(kMips64Dadd | AddressingModeField::encode(kMode_None), addr_reg, |
264 g.UseRegister(index), g.UseRegister(base)); | 264 g.UseRegister(index), g.UseRegister(base)); |
265 // Emit desired store opcode, using temp addr_reg. | 265 // Emit desired store opcode, using temp addr_reg. |
266 Emit(opcode | AddressingModeField::encode(kMode_MRI), NULL, addr_reg, | 266 Emit(opcode | AddressingModeField::encode(kMode_MRI), g.NoOutput(), |
267 g.TempImmediate(0), g.UseRegister(value)); | 267 addr_reg, g.TempImmediate(0), g.UseRegister(value)); |
268 } | 268 } |
269 } | 269 } |
270 | 270 |
271 | 271 |
272 void InstructionSelector::VisitWord32And(Node* node) { | 272 void InstructionSelector::VisitWord32And(Node* node) { |
273 VisitBinop(this, node, kMips64And); | 273 VisitBinop(this, node, kMips64And); |
274 } | 274 } |
275 | 275 |
276 | 276 |
277 void InstructionSelector::VisitWord64And(Node* node) { | 277 void InstructionSelector::VisitWord64And(Node* node) { |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
368 Int32BinopMatcher m(node); | 368 Int32BinopMatcher m(node); |
369 if (m.right().HasValue() && m.right().Value() > 0) { | 369 if (m.right().HasValue() && m.right().Value() > 0) { |
370 int32_t value = m.right().Value(); | 370 int32_t value = m.right().Value(); |
371 if (base::bits::IsPowerOfTwo32(value)) { | 371 if (base::bits::IsPowerOfTwo32(value)) { |
372 Emit(kMips64Shl | AddressingModeField::encode(kMode_None), | 372 Emit(kMips64Shl | AddressingModeField::encode(kMode_None), |
373 g.DefineAsRegister(node), g.UseRegister(m.left().node()), | 373 g.DefineAsRegister(node), g.UseRegister(m.left().node()), |
374 g.TempImmediate(WhichPowerOf2(value))); | 374 g.TempImmediate(WhichPowerOf2(value))); |
375 return; | 375 return; |
376 } | 376 } |
377 if (base::bits::IsPowerOfTwo32(value - 1)) { | 377 if (base::bits::IsPowerOfTwo32(value - 1)) { |
378 InstructionOperand* temp = g.TempRegister(); | 378 InstructionOperand temp = g.TempRegister(); |
379 Emit(kMips64Shl | AddressingModeField::encode(kMode_None), temp, | 379 Emit(kMips64Shl | AddressingModeField::encode(kMode_None), temp, |
380 g.UseRegister(m.left().node()), | 380 g.UseRegister(m.left().node()), |
381 g.TempImmediate(WhichPowerOf2(value - 1))); | 381 g.TempImmediate(WhichPowerOf2(value - 1))); |
382 Emit(kMips64Add | AddressingModeField::encode(kMode_None), | 382 Emit(kMips64Add | AddressingModeField::encode(kMode_None), |
383 g.DefineAsRegister(node), g.UseRegister(m.left().node()), temp); | 383 g.DefineAsRegister(node), g.UseRegister(m.left().node()), temp); |
384 return; | 384 return; |
385 } | 385 } |
386 if (base::bits::IsPowerOfTwo32(value + 1)) { | 386 if (base::bits::IsPowerOfTwo32(value + 1)) { |
387 InstructionOperand* temp = g.TempRegister(); | 387 InstructionOperand temp = g.TempRegister(); |
388 Emit(kMips64Shl | AddressingModeField::encode(kMode_None), temp, | 388 Emit(kMips64Shl | AddressingModeField::encode(kMode_None), temp, |
389 g.UseRegister(m.left().node()), | 389 g.UseRegister(m.left().node()), |
390 g.TempImmediate(WhichPowerOf2(value + 1))); | 390 g.TempImmediate(WhichPowerOf2(value + 1))); |
391 Emit(kMips64Sub | AddressingModeField::encode(kMode_None), | 391 Emit(kMips64Sub | AddressingModeField::encode(kMode_None), |
392 g.DefineAsRegister(node), temp, g.UseRegister(m.left().node())); | 392 g.DefineAsRegister(node), temp, g.UseRegister(m.left().node())); |
393 return; | 393 return; |
394 } | 394 } |
395 } | 395 } |
396 Emit(kMips64Mul, g.DefineAsRegister(node), g.UseRegister(m.left().node()), | 396 Emit(kMips64Mul, g.DefineAsRegister(node), g.UseRegister(m.left().node()), |
397 g.UseRegister(m.right().node())); | 397 g.UseRegister(m.right().node())); |
398 } | 398 } |
399 | 399 |
400 | 400 |
401 void InstructionSelector::VisitInt32MulHigh(Node* node) { | 401 void InstructionSelector::VisitInt32MulHigh(Node* node) { |
402 Mips64OperandGenerator g(this); | 402 Mips64OperandGenerator g(this); |
403 Emit(kMips64MulHigh, g.DefineAsRegister(node), | 403 Emit(kMips64MulHigh, g.DefineAsRegister(node), |
404 g.UseRegister(node->InputAt(0)), g.UseRegister(node->InputAt(1))); | 404 g.UseRegister(node->InputAt(0)), g.UseRegister(node->InputAt(1))); |
405 } | 405 } |
406 | 406 |
407 | 407 |
408 void InstructionSelector::VisitUint32MulHigh(Node* node) { | 408 void InstructionSelector::VisitUint32MulHigh(Node* node) { |
409 Mips64OperandGenerator g(this); | 409 Mips64OperandGenerator g(this); |
410 InstructionOperand* const dmul_operand = g.TempRegister(); | 410 InstructionOperand const dmul_operand = g.TempRegister(); |
411 Emit(kMips64MulHighU, dmul_operand, g.UseRegister(node->InputAt(0)), | 411 Emit(kMips64MulHighU, dmul_operand, g.UseRegister(node->InputAt(0)), |
412 g.UseRegister(node->InputAt(1))); | 412 g.UseRegister(node->InputAt(1))); |
413 Emit(kMips64Ext, g.DefineAsRegister(node), dmul_operand, g.TempImmediate(0), | 413 Emit(kMips64Ext, g.DefineAsRegister(node), dmul_operand, g.TempImmediate(0), |
414 g.TempImmediate(32)); | 414 g.TempImmediate(32)); |
415 } | 415 } |
416 | 416 |
417 | 417 |
418 void InstructionSelector::VisitInt64Mul(Node* node) { | 418 void InstructionSelector::VisitInt64Mul(Node* node) { |
419 Mips64OperandGenerator g(this); | 419 Mips64OperandGenerator g(this); |
420 Int64BinopMatcher m(node); | 420 Int64BinopMatcher m(node); |
421 // TODO(dusmil): Add optimization for shifts larger than 32. | 421 // TODO(dusmil): Add optimization for shifts larger than 32. |
422 if (m.right().HasValue() && m.right().Value() > 0) { | 422 if (m.right().HasValue() && m.right().Value() > 0) { |
423 int64_t value = m.right().Value(); | 423 int64_t value = m.right().Value(); |
424 if (base::bits::IsPowerOfTwo32(value)) { | 424 if (base::bits::IsPowerOfTwo32(value)) { |
425 Emit(kMips64Dshl | AddressingModeField::encode(kMode_None), | 425 Emit(kMips64Dshl | AddressingModeField::encode(kMode_None), |
426 g.DefineAsRegister(node), g.UseRegister(m.left().node()), | 426 g.DefineAsRegister(node), g.UseRegister(m.left().node()), |
427 g.TempImmediate(WhichPowerOf2(value))); | 427 g.TempImmediate(WhichPowerOf2(value))); |
428 return; | 428 return; |
429 } | 429 } |
430 if (base::bits::IsPowerOfTwo32(value - 1)) { | 430 if (base::bits::IsPowerOfTwo32(value - 1)) { |
431 InstructionOperand* temp = g.TempRegister(); | 431 InstructionOperand temp = g.TempRegister(); |
432 Emit(kMips64Dshl | AddressingModeField::encode(kMode_None), temp, | 432 Emit(kMips64Dshl | AddressingModeField::encode(kMode_None), temp, |
433 g.UseRegister(m.left().node()), | 433 g.UseRegister(m.left().node()), |
434 g.TempImmediate(WhichPowerOf2(value - 1))); | 434 g.TempImmediate(WhichPowerOf2(value - 1))); |
435 Emit(kMips64Dadd | AddressingModeField::encode(kMode_None), | 435 Emit(kMips64Dadd | AddressingModeField::encode(kMode_None), |
436 g.DefineAsRegister(node), g.UseRegister(m.left().node()), temp); | 436 g.DefineAsRegister(node), g.UseRegister(m.left().node()), temp); |
437 return; | 437 return; |
438 } | 438 } |
439 if (base::bits::IsPowerOfTwo32(value + 1)) { | 439 if (base::bits::IsPowerOfTwo32(value + 1)) { |
440 InstructionOperand* temp = g.TempRegister(); | 440 InstructionOperand temp = g.TempRegister(); |
441 Emit(kMips64Dshl | AddressingModeField::encode(kMode_None), temp, | 441 Emit(kMips64Dshl | AddressingModeField::encode(kMode_None), temp, |
442 g.UseRegister(m.left().node()), | 442 g.UseRegister(m.left().node()), |
443 g.TempImmediate(WhichPowerOf2(value + 1))); | 443 g.TempImmediate(WhichPowerOf2(value + 1))); |
444 Emit(kMips64Dsub | AddressingModeField::encode(kMode_None), | 444 Emit(kMips64Dsub | AddressingModeField::encode(kMode_None), |
445 g.DefineAsRegister(node), temp, g.UseRegister(m.left().node())); | 445 g.DefineAsRegister(node), temp, g.UseRegister(m.left().node())); |
446 return; | 446 return; |
447 } | 447 } |
448 } | 448 } |
449 Emit(kMips64Dmul, g.DefineAsRegister(node), g.UseRegister(m.left().node()), | 449 Emit(kMips64Dmul, g.DefineAsRegister(node), g.UseRegister(m.left().node()), |
450 g.UseRegister(m.right().node())); | 450 g.UseRegister(m.right().node())); |
(...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
639 GetFrameStateDescriptor(node->InputAt(descriptor->InputCount())); | 639 GetFrameStateDescriptor(node->InputAt(descriptor->InputCount())); |
640 } | 640 } |
641 | 641 |
642 CallBuffer buffer(zone(), descriptor, frame_state_descriptor); | 642 CallBuffer buffer(zone(), descriptor, frame_state_descriptor); |
643 | 643 |
644 // Compute InstructionOperands for inputs and outputs. | 644 // Compute InstructionOperands for inputs and outputs. |
645 InitializeCallBuffer(node, &buffer, true, false); | 645 InitializeCallBuffer(node, &buffer, true, false); |
646 | 646 |
647 int push_count = buffer.pushed_nodes.size(); | 647 int push_count = buffer.pushed_nodes.size(); |
648 if (push_count > 0) { | 648 if (push_count > 0) { |
649 Emit(kMips64StackClaim | MiscField::encode(push_count), NULL); | 649 Emit(kMips64StackClaim | MiscField::encode(push_count), g.NoOutput()); |
650 } | 650 } |
651 int slot = buffer.pushed_nodes.size() - 1; | 651 int slot = buffer.pushed_nodes.size() - 1; |
652 for (auto i = buffer.pushed_nodes.rbegin(); i != buffer.pushed_nodes.rend(); | 652 for (auto i = buffer.pushed_nodes.rbegin(); i != buffer.pushed_nodes.rend(); |
653 ++i) { | 653 ++i) { |
654 Emit(kMips64StoreToStackSlot | MiscField::encode(slot), nullptr, | 654 Emit(kMips64StoreToStackSlot | MiscField::encode(slot), g.NoOutput(), |
655 g.UseRegister(*i)); | 655 g.UseRegister(*i)); |
656 slot--; | 656 slot--; |
657 } | 657 } |
658 | 658 |
659 // Select the appropriate opcode based on the call type. | 659 // Select the appropriate opcode based on the call type. |
660 InstructionCode opcode; | 660 InstructionCode opcode; |
661 switch (descriptor->kind()) { | 661 switch (descriptor->kind()) { |
662 case CallDescriptor::kCallCodeObject: { | 662 case CallDescriptor::kCallCodeObject: { |
663 opcode = kArchCallCodeObject; | 663 opcode = kArchCallCodeObject; |
664 break; | 664 break; |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
702 case kRepFloat32: | 702 case kRepFloat32: |
703 opcode = kCheckedLoadFloat32; | 703 opcode = kCheckedLoadFloat32; |
704 break; | 704 break; |
705 case kRepFloat64: | 705 case kRepFloat64: |
706 opcode = kCheckedLoadFloat64; | 706 opcode = kCheckedLoadFloat64; |
707 break; | 707 break; |
708 default: | 708 default: |
709 UNREACHABLE(); | 709 UNREACHABLE(); |
710 return; | 710 return; |
711 } | 711 } |
712 InstructionOperand* offset_operand = g.CanBeImmediate(offset, opcode) | 712 InstructionOperand offset_operand = g.CanBeImmediate(offset, opcode) |
713 ? g.UseImmediate(offset) | 713 ? g.UseImmediate(offset) |
714 : g.UseRegister(offset); | 714 : g.UseRegister(offset); |
715 | 715 |
716 InstructionOperand* length_operand = | 716 InstructionOperand length_operand = (!g.CanBeImmediate(offset, opcode)) |
717 (!g.CanBeImmediate(offset, opcode)) ? g.CanBeImmediate(length, opcode) | 717 ? g.CanBeImmediate(length, opcode) |
718 ? g.UseImmediate(length) | 718 ? g.UseImmediate(length) |
719 : g.UseRegister(length) | 719 : g.UseRegister(length) |
720 : g.UseRegister(length); | 720 : g.UseRegister(length); |
721 | 721 |
722 Emit(opcode | AddressingModeField::encode(kMode_MRI), | 722 Emit(opcode | AddressingModeField::encode(kMode_MRI), |
723 g.DefineAsRegister(node), offset_operand, length_operand, | 723 g.DefineAsRegister(node), offset_operand, length_operand, |
724 g.UseRegister(buffer)); | 724 g.UseRegister(buffer)); |
725 } | 725 } |
726 | 726 |
727 | 727 |
728 void InstructionSelector::VisitCheckedStore(Node* node) { | 728 void InstructionSelector::VisitCheckedStore(Node* node) { |
729 MachineType rep = RepresentationOf(OpParameter<MachineType>(node)); | 729 MachineType rep = RepresentationOf(OpParameter<MachineType>(node)); |
730 Mips64OperandGenerator g(this); | 730 Mips64OperandGenerator g(this); |
(...skipping 15 matching lines...) Expand all Loading... |
746 case kRepFloat32: | 746 case kRepFloat32: |
747 opcode = kCheckedStoreFloat32; | 747 opcode = kCheckedStoreFloat32; |
748 break; | 748 break; |
749 case kRepFloat64: | 749 case kRepFloat64: |
750 opcode = kCheckedStoreFloat64; | 750 opcode = kCheckedStoreFloat64; |
751 break; | 751 break; |
752 default: | 752 default: |
753 UNREACHABLE(); | 753 UNREACHABLE(); |
754 return; | 754 return; |
755 } | 755 } |
756 InstructionOperand* offset_operand = g.CanBeImmediate(offset, opcode) | 756 InstructionOperand offset_operand = g.CanBeImmediate(offset, opcode) |
757 ? g.UseImmediate(offset) | 757 ? g.UseImmediate(offset) |
758 : g.UseRegister(offset); | 758 : g.UseRegister(offset); |
759 | 759 |
760 InstructionOperand* length_operand = | 760 InstructionOperand length_operand = (!g.CanBeImmediate(offset, opcode)) |
761 (!g.CanBeImmediate(offset, opcode)) ? g.CanBeImmediate(length, opcode) | 761 ? g.CanBeImmediate(length, opcode) |
762 ? g.UseImmediate(length) | 762 ? g.UseImmediate(length) |
763 : g.UseRegister(length) | 763 : g.UseRegister(length) |
764 : g.UseRegister(length); | 764 : g.UseRegister(length); |
765 | 765 |
766 Emit(opcode | AddressingModeField::encode(kMode_MRI), nullptr, offset_operand, | 766 Emit(opcode | AddressingModeField::encode(kMode_MRI), g.NoOutput(), |
767 length_operand, g.UseRegister(value), g.UseRegister(buffer)); | 767 offset_operand, length_operand, g.UseRegister(value), |
| 768 g.UseRegister(buffer)); |
768 } | 769 } |
769 | 770 |
770 | 771 |
771 namespace { | 772 namespace { |
772 | 773 |
773 // Shared routine for multiple compare operations. | 774 // Shared routine for multiple compare operations. |
774 static void VisitCompare(InstructionSelector* selector, InstructionCode opcode, | 775 static void VisitCompare(InstructionSelector* selector, InstructionCode opcode, |
775 InstructionOperand* left, InstructionOperand* right, | 776 InstructionOperand left, InstructionOperand right, |
776 FlagsContinuation* cont) { | 777 FlagsContinuation* cont) { |
777 Mips64OperandGenerator g(selector); | 778 Mips64OperandGenerator g(selector); |
778 opcode = cont->Encode(opcode); | 779 opcode = cont->Encode(opcode); |
779 if (cont->IsBranch()) { | 780 if (cont->IsBranch()) { |
780 selector->Emit(opcode, NULL, left, right, g.Label(cont->true_block()), | 781 selector->Emit(opcode, g.NoOutput(), left, right, |
| 782 g.Label(cont->true_block()), |
781 g.Label(cont->false_block()))->MarkAsControl(); | 783 g.Label(cont->false_block()))->MarkAsControl(); |
782 } else { | 784 } else { |
783 DCHECK(cont->IsSet()); | 785 DCHECK(cont->IsSet()); |
784 selector->Emit(opcode, g.DefineAsRegister(cont->result()), left, right); | 786 selector->Emit(opcode, g.DefineAsRegister(cont->result()), left, right); |
785 } | 787 } |
786 } | 788 } |
787 | 789 |
788 | 790 |
789 // Shared routine for multiple float compare operations. | 791 // Shared routine for multiple float compare operations. |
790 void VisitFloat64Compare(InstructionSelector* selector, Node* node, | 792 void VisitFloat64Compare(InstructionSelector* selector, Node* node, |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
831 VisitWordCompare(selector, node, kMips64Cmp, cont, false); | 833 VisitWordCompare(selector, node, kMips64Cmp, cont, false); |
832 } | 834 } |
833 | 835 |
834 } // namespace | 836 } // namespace |
835 | 837 |
836 | 838 |
837 void EmitWordCompareZero(InstructionSelector* selector, InstructionCode opcode, | 839 void EmitWordCompareZero(InstructionSelector* selector, InstructionCode opcode, |
838 Node* value, FlagsContinuation* cont) { | 840 Node* value, FlagsContinuation* cont) { |
839 Mips64OperandGenerator g(selector); | 841 Mips64OperandGenerator g(selector); |
840 opcode = cont->Encode(opcode); | 842 opcode = cont->Encode(opcode); |
841 InstructionOperand* const value_operand = g.UseRegister(value); | 843 InstructionOperand const value_operand = g.UseRegister(value); |
842 if (cont->IsBranch()) { | 844 if (cont->IsBranch()) { |
843 selector->Emit(opcode, nullptr, value_operand, g.TempImmediate(0), | 845 selector->Emit(opcode, g.NoOutput(), value_operand, g.TempImmediate(0), |
844 g.Label(cont->true_block()), | 846 g.Label(cont->true_block()), |
845 g.Label(cont->false_block()))->MarkAsControl(); | 847 g.Label(cont->false_block()))->MarkAsControl(); |
846 } else { | 848 } else { |
847 selector->Emit(opcode, g.DefineAsRegister(cont->result()), value_operand, | 849 selector->Emit(opcode, g.DefineAsRegister(cont->result()), value_operand, |
848 g.TempImmediate(0)); | 850 g.TempImmediate(0)); |
849 } | 851 } |
850 } | 852 } |
851 | 853 |
852 | 854 |
853 // Shared routine for word comparisons against zero. | 855 // Shared routine for word comparisons against zero. |
(...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1071 MachineOperatorBuilder::Flags | 1073 MachineOperatorBuilder::Flags |
1072 InstructionSelector::SupportedMachineOperatorFlags() { | 1074 InstructionSelector::SupportedMachineOperatorFlags() { |
1073 return MachineOperatorBuilder::kFloat64Floor | | 1075 return MachineOperatorBuilder::kFloat64Floor | |
1074 MachineOperatorBuilder::kFloat64Ceil | | 1076 MachineOperatorBuilder::kFloat64Ceil | |
1075 MachineOperatorBuilder::kFloat64RoundTruncate; | 1077 MachineOperatorBuilder::kFloat64RoundTruncate; |
1076 } | 1078 } |
1077 | 1079 |
1078 } // namespace compiler | 1080 } // namespace compiler |
1079 } // namespace internal | 1081 } // namespace internal |
1080 } // namespace v8 | 1082 } // namespace v8 |
OLD | NEW |