| 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 |