| 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 MipsOperandGenerator FINAL : public OperandGenerator { | 21 class MipsOperandGenerator FINAL : public OperandGenerator { |
| 22 public: | 22 public: |
| 23 explicit MipsOperandGenerator(InstructionSelector* selector) | 23 explicit MipsOperandGenerator(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 Int32Matcher m(node); | 34 Int32Matcher m(node); |
| 35 if (!m.HasValue()) return false; | 35 if (!m.HasValue()) return false; |
| 36 int32_t value = m.Value(); | 36 int32_t value = m.Value(); |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 84 selector->Emit(opcode, g.DefineAsRegister(node), | 84 selector->Emit(opcode, g.DefineAsRegister(node), |
| 85 g.UseRegister(node->InputAt(0)), | 85 g.UseRegister(node->InputAt(0)), |
| 86 g.UseOperand(node->InputAt(1), opcode)); | 86 g.UseOperand(node->InputAt(1), opcode)); |
| 87 } | 87 } |
| 88 | 88 |
| 89 | 89 |
| 90 static void VisitBinop(InstructionSelector* selector, Node* node, | 90 static void VisitBinop(InstructionSelector* selector, Node* node, |
| 91 InstructionCode opcode, FlagsContinuation* cont) { | 91 InstructionCode opcode, FlagsContinuation* cont) { |
| 92 MipsOperandGenerator g(selector); | 92 MipsOperandGenerator g(selector); |
| 93 Int32BinopMatcher m(node); | 93 Int32BinopMatcher m(node); |
| 94 InstructionOperand* inputs[4]; | 94 InstructionOperand inputs[4]; |
| 95 size_t input_count = 0; | 95 size_t input_count = 0; |
| 96 InstructionOperand* outputs[2]; | 96 InstructionOperand outputs[2]; |
| 97 size_t output_count = 0; | 97 size_t output_count = 0; |
| 98 | 98 |
| 99 inputs[input_count++] = g.UseRegister(m.left().node()); | 99 inputs[input_count++] = g.UseRegister(m.left().node()); |
| 100 inputs[input_count++] = g.UseOperand(m.right().node(), opcode); | 100 inputs[input_count++] = g.UseOperand(m.right().node(), opcode); |
| 101 | 101 |
| 102 if (cont->IsBranch()) { | 102 if (cont->IsBranch()) { |
| 103 inputs[input_count++] = g.Label(cont->true_block()); | 103 inputs[input_count++] = g.Label(cont->true_block()); |
| 104 inputs[input_count++] = g.Label(cont->false_block()); | 104 inputs[input_count++] = g.Label(cont->false_block()); |
| 105 } | 105 } |
| 106 | 106 |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 155 break; | 155 break; |
| 156 default: | 156 default: |
| 157 UNREACHABLE(); | 157 UNREACHABLE(); |
| 158 return; | 158 return; |
| 159 } | 159 } |
| 160 | 160 |
| 161 if (g.CanBeImmediate(index, opcode)) { | 161 if (g.CanBeImmediate(index, opcode)) { |
| 162 Emit(opcode | AddressingModeField::encode(kMode_MRI), | 162 Emit(opcode | AddressingModeField::encode(kMode_MRI), |
| 163 g.DefineAsRegister(node), g.UseRegister(base), g.UseImmediate(index)); | 163 g.DefineAsRegister(node), g.UseRegister(base), g.UseImmediate(index)); |
| 164 } else { | 164 } else { |
| 165 InstructionOperand* addr_reg = g.TempRegister(); | 165 InstructionOperand addr_reg = g.TempRegister(); |
| 166 Emit(kMipsAdd | AddressingModeField::encode(kMode_None), addr_reg, | 166 Emit(kMipsAdd | AddressingModeField::encode(kMode_None), addr_reg, |
| 167 g.UseRegister(index), g.UseRegister(base)); | 167 g.UseRegister(index), g.UseRegister(base)); |
| 168 // Emit desired load opcode, using temp addr_reg. | 168 // Emit desired load opcode, using temp addr_reg. |
| 169 Emit(opcode | AddressingModeField::encode(kMode_MRI), | 169 Emit(opcode | AddressingModeField::encode(kMode_MRI), |
| 170 g.DefineAsRegister(node), addr_reg, g.TempImmediate(0)); | 170 g.DefineAsRegister(node), addr_reg, g.TempImmediate(0)); |
| 171 } | 171 } |
| 172 } | 172 } |
| 173 | 173 |
| 174 | 174 |
| 175 void InstructionSelector::VisitStore(Node* node) { | 175 void InstructionSelector::VisitStore(Node* node) { |
| 176 MipsOperandGenerator g(this); | 176 MipsOperandGenerator g(this); |
| 177 Node* base = node->InputAt(0); | 177 Node* base = node->InputAt(0); |
| 178 Node* index = node->InputAt(1); | 178 Node* index = node->InputAt(1); |
| 179 Node* value = node->InputAt(2); | 179 Node* value = node->InputAt(2); |
| 180 | 180 |
| 181 StoreRepresentation store_rep = OpParameter<StoreRepresentation>(node); | 181 StoreRepresentation store_rep = OpParameter<StoreRepresentation>(node); |
| 182 MachineType rep = RepresentationOf(store_rep.machine_type()); | 182 MachineType rep = RepresentationOf(store_rep.machine_type()); |
| 183 if (store_rep.write_barrier_kind() == kFullWriteBarrier) { | 183 if (store_rep.write_barrier_kind() == kFullWriteBarrier) { |
| 184 DCHECK(rep == kRepTagged); | 184 DCHECK(rep == kRepTagged); |
| 185 // TODO(dcarney): refactor RecordWrite function to take temp registers | 185 // TODO(dcarney): refactor RecordWrite function to take temp registers |
| 186 // and pass them here instead of using fixed regs | 186 // and pass them here instead of using fixed regs |
| 187 // TODO(dcarney): handle immediate indices. | 187 // TODO(dcarney): handle immediate indices. |
| 188 InstructionOperand* temps[] = {g.TempRegister(t1), g.TempRegister(t2)}; | 188 InstructionOperand temps[] = {g.TempRegister(t1), g.TempRegister(t2)}; |
| 189 Emit(kMipsStoreWriteBarrier, NULL, g.UseFixed(base, t0), | 189 Emit(kMipsStoreWriteBarrier, g.NoOutput(), g.UseFixed(base, t0), |
| 190 g.UseFixed(index, t1), g.UseFixed(value, t2), arraysize(temps), temps); | 190 g.UseFixed(index, t1), g.UseFixed(value, t2), arraysize(temps), temps); |
| 191 return; | 191 return; |
| 192 } | 192 } |
| 193 DCHECK_EQ(kNoWriteBarrier, store_rep.write_barrier_kind()); | 193 DCHECK_EQ(kNoWriteBarrier, store_rep.write_barrier_kind()); |
| 194 | 194 |
| 195 ArchOpcode opcode; | 195 ArchOpcode opcode; |
| 196 switch (rep) { | 196 switch (rep) { |
| 197 case kRepFloat32: | 197 case kRepFloat32: |
| 198 opcode = kMipsSwc1; | 198 opcode = kMipsSwc1; |
| 199 break; | 199 break; |
| (...skipping 10 matching lines...) Expand all Loading... |
| 210 case kRepTagged: // Fall through. | 210 case kRepTagged: // Fall through. |
| 211 case kRepWord32: | 211 case kRepWord32: |
| 212 opcode = kMipsSw; | 212 opcode = kMipsSw; |
| 213 break; | 213 break; |
| 214 default: | 214 default: |
| 215 UNREACHABLE(); | 215 UNREACHABLE(); |
| 216 return; | 216 return; |
| 217 } | 217 } |
| 218 | 218 |
| 219 if (g.CanBeImmediate(index, opcode)) { | 219 if (g.CanBeImmediate(index, opcode)) { |
| 220 Emit(opcode | AddressingModeField::encode(kMode_MRI), NULL, | 220 Emit(opcode | AddressingModeField::encode(kMode_MRI), g.NoOutput(), |
| 221 g.UseRegister(base), g.UseImmediate(index), g.UseRegister(value)); | 221 g.UseRegister(base), g.UseImmediate(index), g.UseRegister(value)); |
| 222 } else { | 222 } else { |
| 223 InstructionOperand* addr_reg = g.TempRegister(); | 223 InstructionOperand addr_reg = g.TempRegister(); |
| 224 Emit(kMipsAdd | AddressingModeField::encode(kMode_None), addr_reg, | 224 Emit(kMipsAdd | AddressingModeField::encode(kMode_None), addr_reg, |
| 225 g.UseRegister(index), g.UseRegister(base)); | 225 g.UseRegister(index), g.UseRegister(base)); |
| 226 // Emit desired store opcode, using temp addr_reg. | 226 // Emit desired store opcode, using temp addr_reg. |
| 227 Emit(opcode | AddressingModeField::encode(kMode_MRI), NULL, addr_reg, | 227 Emit(opcode | AddressingModeField::encode(kMode_MRI), g.NoOutput(), |
| 228 g.TempImmediate(0), g.UseRegister(value)); | 228 addr_reg, g.TempImmediate(0), g.UseRegister(value)); |
| 229 } | 229 } |
| 230 } | 230 } |
| 231 | 231 |
| 232 | 232 |
| 233 void InstructionSelector::VisitWord32And(Node* node) { | 233 void InstructionSelector::VisitWord32And(Node* node) { |
| 234 VisitBinop(this, node, kMipsAnd); | 234 VisitBinop(this, node, kMipsAnd); |
| 235 } | 235 } |
| 236 | 236 |
| 237 | 237 |
| 238 void InstructionSelector::VisitWord32Or(Node* node) { | 238 void InstructionSelector::VisitWord32Or(Node* node) { |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 283 Int32BinopMatcher m(node); | 283 Int32BinopMatcher m(node); |
| 284 if (m.right().HasValue() && m.right().Value() > 0) { | 284 if (m.right().HasValue() && m.right().Value() > 0) { |
| 285 int32_t value = m.right().Value(); | 285 int32_t value = m.right().Value(); |
| 286 if (base::bits::IsPowerOfTwo32(value)) { | 286 if (base::bits::IsPowerOfTwo32(value)) { |
| 287 Emit(kMipsShl | AddressingModeField::encode(kMode_None), | 287 Emit(kMipsShl | AddressingModeField::encode(kMode_None), |
| 288 g.DefineAsRegister(node), g.UseRegister(m.left().node()), | 288 g.DefineAsRegister(node), g.UseRegister(m.left().node()), |
| 289 g.TempImmediate(WhichPowerOf2(value))); | 289 g.TempImmediate(WhichPowerOf2(value))); |
| 290 return; | 290 return; |
| 291 } | 291 } |
| 292 if (base::bits::IsPowerOfTwo32(value - 1)) { | 292 if (base::bits::IsPowerOfTwo32(value - 1)) { |
| 293 InstructionOperand* temp = g.TempRegister(); | 293 InstructionOperand temp = g.TempRegister(); |
| 294 Emit(kMipsShl | AddressingModeField::encode(kMode_None), temp, | 294 Emit(kMipsShl | AddressingModeField::encode(kMode_None), temp, |
| 295 g.UseRegister(m.left().node()), | 295 g.UseRegister(m.left().node()), |
| 296 g.TempImmediate(WhichPowerOf2(value - 1))); | 296 g.TempImmediate(WhichPowerOf2(value - 1))); |
| 297 Emit(kMipsAdd | AddressingModeField::encode(kMode_None), | 297 Emit(kMipsAdd | AddressingModeField::encode(kMode_None), |
| 298 g.DefineAsRegister(node), g.UseRegister(m.left().node()), temp); | 298 g.DefineAsRegister(node), g.UseRegister(m.left().node()), temp); |
| 299 return; | 299 return; |
| 300 } | 300 } |
| 301 if (base::bits::IsPowerOfTwo32(value + 1)) { | 301 if (base::bits::IsPowerOfTwo32(value + 1)) { |
| 302 InstructionOperand* temp = g.TempRegister(); | 302 InstructionOperand temp = g.TempRegister(); |
| 303 Emit(kMipsShl | AddressingModeField::encode(kMode_None), temp, | 303 Emit(kMipsShl | AddressingModeField::encode(kMode_None), temp, |
| 304 g.UseRegister(m.left().node()), | 304 g.UseRegister(m.left().node()), |
| 305 g.TempImmediate(WhichPowerOf2(value + 1))); | 305 g.TempImmediate(WhichPowerOf2(value + 1))); |
| 306 Emit(kMipsSub | AddressingModeField::encode(kMode_None), | 306 Emit(kMipsSub | AddressingModeField::encode(kMode_None), |
| 307 g.DefineAsRegister(node), temp, g.UseRegister(m.left().node())); | 307 g.DefineAsRegister(node), temp, g.UseRegister(m.left().node())); |
| 308 return; | 308 return; |
| 309 } | 309 } |
| 310 } | 310 } |
| 311 Emit(kMipsMul, g.DefineAsRegister(node), g.UseRegister(m.left().node()), | 311 Emit(kMipsMul, g.DefineAsRegister(node), g.UseRegister(m.left().node()), |
| 312 g.UseRegister(m.right().node())); | 312 g.UseRegister(m.right().node())); |
| (...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 459 GetFrameStateDescriptor(node->InputAt(descriptor->InputCount())); | 459 GetFrameStateDescriptor(node->InputAt(descriptor->InputCount())); |
| 460 } | 460 } |
| 461 | 461 |
| 462 CallBuffer buffer(zone(), descriptor, frame_state_descriptor); | 462 CallBuffer buffer(zone(), descriptor, frame_state_descriptor); |
| 463 | 463 |
| 464 // Compute InstructionOperands for inputs and outputs. | 464 // Compute InstructionOperands for inputs and outputs. |
| 465 InitializeCallBuffer(node, &buffer, true, false); | 465 InitializeCallBuffer(node, &buffer, true, false); |
| 466 // Possibly align stack here for functions. | 466 // Possibly align stack here for functions. |
| 467 int push_count = buffer.pushed_nodes.size(); | 467 int push_count = buffer.pushed_nodes.size(); |
| 468 if (push_count > 0) { | 468 if (push_count > 0) { |
| 469 Emit(kMipsStackClaim | MiscField::encode(push_count), NULL); | 469 Emit(kMipsStackClaim | MiscField::encode(push_count), g.NoOutput()); |
| 470 } | 470 } |
| 471 int slot = buffer.pushed_nodes.size() - 1; | 471 int slot = buffer.pushed_nodes.size() - 1; |
| 472 for (auto i = buffer.pushed_nodes.rbegin(); i != buffer.pushed_nodes.rend(); | 472 for (auto i = buffer.pushed_nodes.rbegin(); i != buffer.pushed_nodes.rend(); |
| 473 ++i) { | 473 ++i) { |
| 474 Emit(kMipsStoreToStackSlot | MiscField::encode(slot), nullptr, | 474 Emit(kMipsStoreToStackSlot | MiscField::encode(slot), g.NoOutput(), |
| 475 g.UseRegister(*i)); | 475 g.UseRegister(*i)); |
| 476 slot--; | 476 slot--; |
| 477 } | 477 } |
| 478 | 478 |
| 479 // Select the appropriate opcode based on the call type. | 479 // Select the appropriate opcode based on the call type. |
| 480 InstructionCode opcode; | 480 InstructionCode opcode; |
| 481 switch (descriptor->kind()) { | 481 switch (descriptor->kind()) { |
| 482 case CallDescriptor::kCallCodeObject: { | 482 case CallDescriptor::kCallCodeObject: { |
| 483 opcode = kArchCallCodeObject; | 483 opcode = kArchCallCodeObject; |
| 484 break; | 484 break; |
| 485 } | 485 } |
| 486 case CallDescriptor::kCallJSFunction: | 486 case CallDescriptor::kCallJSFunction: |
| 487 opcode = kArchCallJSFunction; | 487 opcode = kArchCallJSFunction; |
| 488 break; | 488 break; |
| 489 default: | 489 default: |
| 490 UNREACHABLE(); | 490 UNREACHABLE(); |
| 491 return; | 491 return; |
| 492 } | 492 } |
| 493 opcode |= MiscField::encode(descriptor->flags()); | 493 opcode |= MiscField::encode(descriptor->flags()); |
| 494 | 494 |
| 495 // Emit the call instruction. | 495 // Emit the call instruction. |
| 496 InstructionOperand** first_output = | 496 InstructionOperand* first_output = |
| 497 buffer.outputs.size() > 0 ? &buffer.outputs.front() : NULL; | 497 buffer.outputs.size() > 0 ? &buffer.outputs.front() : NULL; |
| 498 Instruction* call_instr = | 498 Instruction* call_instr = |
| 499 Emit(opcode, buffer.outputs.size(), first_output, | 499 Emit(opcode, buffer.outputs.size(), first_output, |
| 500 buffer.instruction_args.size(), &buffer.instruction_args.front()); | 500 buffer.instruction_args.size(), &buffer.instruction_args.front()); |
| 501 call_instr->MarkAsCall(); | 501 call_instr->MarkAsCall(); |
| 502 } | 502 } |
| 503 | 503 |
| 504 | 504 |
| 505 void InstructionSelector::VisitCheckedLoad(Node* node) { | 505 void InstructionSelector::VisitCheckedLoad(Node* node) { |
| 506 MachineType rep = RepresentationOf(OpParameter<MachineType>(node)); | 506 MachineType rep = RepresentationOf(OpParameter<MachineType>(node)); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 523 case kRepFloat32: | 523 case kRepFloat32: |
| 524 opcode = kCheckedLoadFloat32; | 524 opcode = kCheckedLoadFloat32; |
| 525 break; | 525 break; |
| 526 case kRepFloat64: | 526 case kRepFloat64: |
| 527 opcode = kCheckedLoadFloat64; | 527 opcode = kCheckedLoadFloat64; |
| 528 break; | 528 break; |
| 529 default: | 529 default: |
| 530 UNREACHABLE(); | 530 UNREACHABLE(); |
| 531 return; | 531 return; |
| 532 } | 532 } |
| 533 InstructionOperand* offset_operand = g.CanBeImmediate(offset, opcode) | 533 InstructionOperand offset_operand = g.CanBeImmediate(offset, opcode) |
| 534 ? g.UseImmediate(offset) | 534 ? g.UseImmediate(offset) |
| 535 : g.UseRegister(offset); | 535 : g.UseRegister(offset); |
| 536 | 536 |
| 537 InstructionOperand* length_operand = | 537 InstructionOperand length_operand = (!g.CanBeImmediate(offset, opcode)) |
| 538 (!g.CanBeImmediate(offset, opcode)) ? g.CanBeImmediate(length, opcode) | 538 ? g.CanBeImmediate(length, opcode) |
| 539 ? g.UseImmediate(length) | 539 ? g.UseImmediate(length) |
| 540 : g.UseRegister(length) | 540 : g.UseRegister(length) |
| 541 : g.UseRegister(length); | 541 : g.UseRegister(length); |
| 542 | 542 |
| 543 Emit(opcode | AddressingModeField::encode(kMode_MRI), | 543 Emit(opcode | AddressingModeField::encode(kMode_MRI), |
| 544 g.DefineAsRegister(node), offset_operand, length_operand, | 544 g.DefineAsRegister(node), offset_operand, length_operand, |
| 545 g.UseRegister(buffer)); | 545 g.UseRegister(buffer)); |
| 546 } | 546 } |
| 547 | 547 |
| 548 | 548 |
| 549 void InstructionSelector::VisitCheckedStore(Node* node) { | 549 void InstructionSelector::VisitCheckedStore(Node* node) { |
| 550 MachineType rep = RepresentationOf(OpParameter<MachineType>(node)); | 550 MachineType rep = RepresentationOf(OpParameter<MachineType>(node)); |
| 551 MipsOperandGenerator g(this); | 551 MipsOperandGenerator g(this); |
| (...skipping 15 matching lines...) Expand all Loading... |
| 567 case kRepFloat32: | 567 case kRepFloat32: |
| 568 opcode = kCheckedStoreFloat32; | 568 opcode = kCheckedStoreFloat32; |
| 569 break; | 569 break; |
| 570 case kRepFloat64: | 570 case kRepFloat64: |
| 571 opcode = kCheckedStoreFloat64; | 571 opcode = kCheckedStoreFloat64; |
| 572 break; | 572 break; |
| 573 default: | 573 default: |
| 574 UNREACHABLE(); | 574 UNREACHABLE(); |
| 575 return; | 575 return; |
| 576 } | 576 } |
| 577 InstructionOperand* offset_operand = g.CanBeImmediate(offset, opcode) | 577 InstructionOperand offset_operand = g.CanBeImmediate(offset, opcode) |
| 578 ? g.UseImmediate(offset) | 578 ? g.UseImmediate(offset) |
| 579 : g.UseRegister(offset); | 579 : g.UseRegister(offset); |
| 580 | 580 |
| 581 InstructionOperand* length_operand = | 581 InstructionOperand length_operand = (!g.CanBeImmediate(offset, opcode)) |
| 582 (!g.CanBeImmediate(offset, opcode)) ? g.CanBeImmediate(length, opcode) | 582 ? g.CanBeImmediate(length, opcode) |
| 583 ? g.UseImmediate(length) | 583 ? g.UseImmediate(length) |
| 584 : g.UseRegister(length) | 584 : g.UseRegister(length) |
| 585 : g.UseRegister(length); | 585 : g.UseRegister(length); |
| 586 | 586 |
| 587 Emit(opcode | AddressingModeField::encode(kMode_MRI), nullptr, offset_operand, | 587 Emit(opcode | AddressingModeField::encode(kMode_MRI), g.NoOutput(), |
| 588 length_operand, g.UseRegister(value), g.UseRegister(buffer)); | 588 offset_operand, length_operand, g.UseRegister(value), |
| 589 g.UseRegister(buffer)); |
| 589 } | 590 } |
| 590 | 591 |
| 591 | 592 |
| 592 namespace { | 593 namespace { |
| 593 | 594 |
| 594 // Shared routine for multiple compare operations. | 595 // Shared routine for multiple compare operations. |
| 595 static void VisitCompare(InstructionSelector* selector, InstructionCode opcode, | 596 static void VisitCompare(InstructionSelector* selector, InstructionCode opcode, |
| 596 InstructionOperand* left, InstructionOperand* right, | 597 InstructionOperand left, InstructionOperand right, |
| 597 FlagsContinuation* cont) { | 598 FlagsContinuation* cont) { |
| 598 MipsOperandGenerator g(selector); | 599 MipsOperandGenerator g(selector); |
| 599 opcode = cont->Encode(opcode); | 600 opcode = cont->Encode(opcode); |
| 600 if (cont->IsBranch()) { | 601 if (cont->IsBranch()) { |
| 601 selector->Emit(opcode, NULL, left, right, g.Label(cont->true_block()), | 602 selector->Emit(opcode, g.NoOutput(), left, right, |
| 603 g.Label(cont->true_block()), |
| 602 g.Label(cont->false_block()))->MarkAsControl(); | 604 g.Label(cont->false_block()))->MarkAsControl(); |
| 603 } else { | 605 } else { |
| 604 DCHECK(cont->IsSet()); | 606 DCHECK(cont->IsSet()); |
| 605 // TODO(plind): Revisit and test this path. | 607 // TODO(plind): Revisit and test this path. |
| 606 selector->Emit(opcode, g.DefineAsRegister(cont->result()), left, right); | 608 selector->Emit(opcode, g.DefineAsRegister(cont->result()), left, right); |
| 607 } | 609 } |
| 608 } | 610 } |
| 609 | 611 |
| 610 | 612 |
| 611 // Shared routine for multiple float compare operations. | 613 // Shared routine for multiple float compare operations. |
| (...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 718 return VisitWordCompare(selector, value, kMipsTst, cont, true); | 720 return VisitWordCompare(selector, value, kMipsTst, cont, true); |
| 719 default: | 721 default: |
| 720 break; | 722 break; |
| 721 } | 723 } |
| 722 break; | 724 break; |
| 723 } | 725 } |
| 724 | 726 |
| 725 // Continuation could not be combined with a compare, emit compare against 0. | 727 // Continuation could not be combined with a compare, emit compare against 0. |
| 726 MipsOperandGenerator g(selector); | 728 MipsOperandGenerator g(selector); |
| 727 InstructionCode const opcode = cont->Encode(kMipsCmp); | 729 InstructionCode const opcode = cont->Encode(kMipsCmp); |
| 728 InstructionOperand* const value_operand = g.UseRegister(value); | 730 InstructionOperand const value_operand = g.UseRegister(value); |
| 729 if (cont->IsBranch()) { | 731 if (cont->IsBranch()) { |
| 730 selector->Emit(opcode, nullptr, value_operand, g.TempImmediate(0), | 732 selector->Emit(opcode, g.NoOutput(), value_operand, g.TempImmediate(0), |
| 731 g.Label(cont->true_block()), | 733 g.Label(cont->true_block()), |
| 732 g.Label(cont->false_block()))->MarkAsControl(); | 734 g.Label(cont->false_block()))->MarkAsControl(); |
| 733 } else { | 735 } else { |
| 734 selector->Emit(opcode, g.DefineAsRegister(cont->result()), value_operand, | 736 selector->Emit(opcode, g.DefineAsRegister(cont->result()), value_operand, |
| 735 g.TempImmediate(0)); | 737 g.TempImmediate(0)); |
| 736 } | 738 } |
| 737 } | 739 } |
| 738 | 740 |
| 739 | 741 |
| 740 void InstructionSelector::VisitBranch(Node* branch, BasicBlock* tbranch, | 742 void InstructionSelector::VisitBranch(Node* branch, BasicBlock* tbranch, |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 823 return MachineOperatorBuilder::kFloat64Floor | | 825 return MachineOperatorBuilder::kFloat64Floor | |
| 824 MachineOperatorBuilder::kFloat64Ceil | | 826 MachineOperatorBuilder::kFloat64Ceil | |
| 825 MachineOperatorBuilder::kFloat64RoundTruncate; | 827 MachineOperatorBuilder::kFloat64RoundTruncate; |
| 826 } | 828 } |
| 827 return MachineOperatorBuilder::kNoFlags; | 829 return MachineOperatorBuilder::kNoFlags; |
| 828 } | 830 } |
| 829 | 831 |
| 830 } // namespace compiler | 832 } // namespace compiler |
| 831 } // namespace internal | 833 } // namespace internal |
| 832 } // namespace v8 | 834 } // namespace v8 |
| OLD | NEW |