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/adapters.h" | 5 #include "src/base/adapters.h" |
6 #include "src/base/bits.h" | 6 #include "src/base/bits.h" |
7 #include "src/compiler/instruction-selector-impl.h" | 7 #include "src/compiler/instruction-selector-impl.h" |
8 #include "src/compiler/node-matchers.h" | 8 #include "src/compiler/node-matchers.h" |
9 #include "src/compiler/node-properties.h" | 9 #include "src/compiler/node-properties.h" |
10 | 10 |
(...skipping 409 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
420 case MachineRepresentation::kWord16: | 420 case MachineRepresentation::kWord16: |
421 opcode = load_rep.IsUnsigned() ? kArmLdrh : kArmLdrsh; | 421 opcode = load_rep.IsUnsigned() ? kArmLdrh : kArmLdrsh; |
422 break; | 422 break; |
423 case MachineRepresentation::kTaggedSigned: // Fall through. | 423 case MachineRepresentation::kTaggedSigned: // Fall through. |
424 case MachineRepresentation::kTaggedPointer: // Fall through. | 424 case MachineRepresentation::kTaggedPointer: // Fall through. |
425 case MachineRepresentation::kTagged: // Fall through. | 425 case MachineRepresentation::kTagged: // Fall through. |
426 case MachineRepresentation::kWord32: | 426 case MachineRepresentation::kWord32: |
427 opcode = kArmLdr; | 427 opcode = kArmLdr; |
428 break; | 428 break; |
429 case MachineRepresentation::kSimd128: | 429 case MachineRepresentation::kSimd128: |
430 opcode = kArmSimd128Load; | 430 opcode = kArmVld1S128; |
431 break; | 431 break; |
432 case MachineRepresentation::kWord64: // Fall through. | 432 case MachineRepresentation::kWord64: // Fall through. |
433 case MachineRepresentation::kSimd1x4: // Fall through. | 433 case MachineRepresentation::kSimd1x4: // Fall through. |
434 case MachineRepresentation::kSimd1x8: // Fall through. | 434 case MachineRepresentation::kSimd1x8: // Fall through. |
435 case MachineRepresentation::kSimd1x16: // Fall through. | 435 case MachineRepresentation::kSimd1x16: // Fall through. |
436 case MachineRepresentation::kNone: | 436 case MachineRepresentation::kNone: |
437 UNREACHABLE(); | 437 UNREACHABLE(); |
438 return; | 438 return; |
439 } | 439 } |
440 | 440 |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
510 case MachineRepresentation::kWord16: | 510 case MachineRepresentation::kWord16: |
511 opcode = kArmStrh; | 511 opcode = kArmStrh; |
512 break; | 512 break; |
513 case MachineRepresentation::kTaggedSigned: // Fall through. | 513 case MachineRepresentation::kTaggedSigned: // Fall through. |
514 case MachineRepresentation::kTaggedPointer: // Fall through. | 514 case MachineRepresentation::kTaggedPointer: // Fall through. |
515 case MachineRepresentation::kTagged: // Fall through. | 515 case MachineRepresentation::kTagged: // Fall through. |
516 case MachineRepresentation::kWord32: | 516 case MachineRepresentation::kWord32: |
517 opcode = kArmStr; | 517 opcode = kArmStr; |
518 break; | 518 break; |
519 case MachineRepresentation::kSimd128: | 519 case MachineRepresentation::kSimd128: |
520 opcode = kArmSimd128Store; | 520 opcode = kArmVst1S128; |
521 break; | 521 break; |
522 case MachineRepresentation::kWord64: // Fall through. | 522 case MachineRepresentation::kWord64: // Fall through. |
523 case MachineRepresentation::kSimd1x4: // Fall through. | 523 case MachineRepresentation::kSimd1x4: // Fall through. |
524 case MachineRepresentation::kSimd1x8: // Fall through. | 524 case MachineRepresentation::kSimd1x8: // Fall through. |
525 case MachineRepresentation::kSimd1x16: // Fall through. | 525 case MachineRepresentation::kSimd1x16: // Fall through. |
526 case MachineRepresentation::kNone: | 526 case MachineRepresentation::kNone: |
527 UNREACHABLE(); | 527 UNREACHABLE(); |
528 return; | 528 return; |
529 } | 529 } |
530 | 530 |
531 InstructionOperand inputs[4]; | 531 InstructionOperand inputs[4]; |
532 size_t input_count = 0; | 532 size_t input_count = 0; |
533 inputs[input_count++] = g.UseRegister(value); | 533 inputs[input_count++] = g.UseRegister(value); |
534 inputs[input_count++] = g.UseRegister(base); | 534 inputs[input_count++] = g.UseRegister(base); |
535 EmitStore(this, opcode, input_count, inputs, index); | 535 EmitStore(this, opcode, input_count, inputs, index); |
536 } | 536 } |
537 } | 537 } |
538 | 538 |
539 void InstructionSelector::VisitProtectedStore(Node* node) { | 539 void InstructionSelector::VisitProtectedStore(Node* node) { |
540 // TODO(eholk) | 540 // TODO(eholk) |
541 UNIMPLEMENTED(); | 541 UNIMPLEMENTED(); |
542 } | 542 } |
543 | 543 |
544 void InstructionSelector::VisitUnalignedLoad(Node* node) { | 544 void InstructionSelector::VisitUnalignedLoad(Node* node) { |
545 UnalignedLoadRepresentation load_rep = | 545 MachineRepresentation load_rep = |
546 UnalignedLoadRepresentationOf(node->op()); | 546 UnalignedLoadRepresentationOf(node->op()).representation(); |
547 ArmOperandGenerator g(this); | 547 ArmOperandGenerator g(this); |
548 Node* base = node->InputAt(0); | 548 Node* base = node->InputAt(0); |
549 Node* index = node->InputAt(1); | 549 Node* index = node->InputAt(1); |
550 | 550 |
551 InstructionCode opcode = kArmLdr; | 551 InstructionCode opcode = kArmLdr; |
552 // Only floating point loads need to be specially handled; integer loads | 552 // Only floating point loads need to be specially handled; integer loads |
553 // support unaligned access. We support unaligned FP loads by loading to | 553 // support unaligned access. We support unaligned FP loads by loading to |
554 // integer registers first, then moving to the destination FP register. | 554 // integer registers first, then moving to the destination FP register. If |
555 switch (load_rep.representation()) { | 555 // NEON is supported, we use the vld1.8 instruction. |
| 556 switch (load_rep) { |
556 case MachineRepresentation::kFloat32: { | 557 case MachineRepresentation::kFloat32: { |
557 InstructionOperand temp = g.TempRegister(); | 558 InstructionOperand temp = g.TempRegister(); |
558 EmitLoad(this, opcode, &temp, base, index); | 559 EmitLoad(this, opcode, &temp, base, index); |
559 Emit(kArmVmovF32U32, g.DefineAsRegister(node), temp); | 560 Emit(kArmVmovF32U32, g.DefineAsRegister(node), temp); |
560 return; | 561 return; |
561 } | 562 } |
562 case MachineRepresentation::kFloat64: { | 563 case MachineRepresentation::kFloat64: |
563 // Compute the address of the least-significant half of the FP value. | 564 case MachineRepresentation::kSimd128: { |
| 565 // Compute the address of the least-significant byte of the FP value. |
564 // We assume that the base node is unlikely to be an encodable immediate | 566 // We assume that the base node is unlikely to be an encodable immediate |
565 // or the result of a shift operation, so only consider the addressing | 567 // or the result of a shift operation, so only consider the addressing |
566 // mode that should be used for the index node. | 568 // mode that should be used for the index node. |
567 InstructionCode add_opcode = kArmAdd; | 569 InstructionCode add_opcode = kArmAdd; |
568 InstructionOperand inputs[3]; | 570 InstructionOperand inputs[3]; |
569 inputs[0] = g.UseRegister(base); | 571 inputs[0] = g.UseRegister(base); |
570 | 572 |
571 size_t input_count; | 573 size_t input_count; |
572 if (TryMatchImmediateOrShift(this, &add_opcode, index, &input_count, | 574 if (TryMatchImmediateOrShift(this, &add_opcode, index, &input_count, |
573 &inputs[1])) { | 575 &inputs[1])) { |
574 // input_count has been set by TryMatchImmediateOrShift(), so | 576 // input_count has been set by TryMatchImmediateOrShift(), so |
575 // increment it to account for the base register in inputs[0]. | 577 // increment it to account for the base register in inputs[0]. |
576 input_count++; | 578 input_count++; |
577 } else { | 579 } else { |
578 add_opcode |= AddressingModeField::encode(kMode_Operand2_R); | 580 add_opcode |= AddressingModeField::encode(kMode_Operand2_R); |
579 inputs[1] = g.UseRegister(index); | 581 inputs[1] = g.UseRegister(index); |
580 input_count = 2; // Base register and index. | 582 input_count = 2; // Base register and index. |
581 } | 583 } |
582 | 584 |
583 InstructionOperand addr = g.TempRegister(); | 585 InstructionOperand addr = g.TempRegister(); |
584 Emit(add_opcode, 1, &addr, input_count, inputs); | 586 Emit(add_opcode, 1, &addr, input_count, inputs); |
585 | 587 |
586 if (CpuFeatures::IsSupported(NEON)) { | 588 if (CpuFeatures::IsSupported(NEON)) { |
587 // With NEON we can load directly from the calculated address. | 589 // With NEON we can load directly from the calculated address. |
588 Emit(kArmVld1F64, g.DefineAsRegister(node), addr); | 590 ArchOpcode op = load_rep == MachineRepresentation::kFloat64 |
| 591 ? kArmVld1F64 |
| 592 : kArmVld1S128; |
| 593 Emit(op, g.DefineAsRegister(node), addr); |
589 } else { | 594 } else { |
| 595 DCHECK_NE(MachineRepresentation::kSimd128, load_rep); |
590 // Load both halves and move to an FP register. | 596 // Load both halves and move to an FP register. |
591 InstructionOperand fp_lo = g.TempRegister(); | 597 InstructionOperand fp_lo = g.TempRegister(); |
592 InstructionOperand fp_hi = g.TempRegister(); | 598 InstructionOperand fp_hi = g.TempRegister(); |
593 opcode |= AddressingModeField::encode(kMode_Offset_RI); | 599 opcode |= AddressingModeField::encode(kMode_Offset_RI); |
594 Emit(opcode, fp_lo, addr, g.TempImmediate(0)); | 600 Emit(opcode, fp_lo, addr, g.TempImmediate(0)); |
595 Emit(opcode, fp_hi, addr, g.TempImmediate(4)); | 601 Emit(opcode, fp_hi, addr, g.TempImmediate(4)); |
596 Emit(kArmVmovF64U32U32, g.DefineAsRegister(node), fp_lo, fp_hi); | 602 Emit(kArmVmovF64U32U32, g.DefineAsRegister(node), fp_lo, fp_hi); |
597 } | 603 } |
598 return; | 604 return; |
599 } | 605 } |
(...skipping 12 matching lines...) Expand all Loading... |
612 | 618 |
613 InstructionOperand inputs[4]; | 619 InstructionOperand inputs[4]; |
614 size_t input_count = 0; | 620 size_t input_count = 0; |
615 | 621 |
616 UnalignedStoreRepresentation store_rep = | 622 UnalignedStoreRepresentation store_rep = |
617 UnalignedStoreRepresentationOf(node->op()); | 623 UnalignedStoreRepresentationOf(node->op()); |
618 | 624 |
619 // Only floating point stores need to be specially handled; integer stores | 625 // Only floating point stores need to be specially handled; integer stores |
620 // support unaligned access. We support unaligned FP stores by moving the | 626 // support unaligned access. We support unaligned FP stores by moving the |
621 // value to integer registers first, then storing to the destination address. | 627 // value to integer registers first, then storing to the destination address. |
| 628 // If NEON is supported, we use the vst1.8 instruction. |
622 switch (store_rep) { | 629 switch (store_rep) { |
623 case MachineRepresentation::kFloat32: { | 630 case MachineRepresentation::kFloat32: { |
624 inputs[input_count++] = g.TempRegister(); | 631 inputs[input_count++] = g.TempRegister(); |
625 Emit(kArmVmovU32F32, inputs[0], g.UseRegister(value)); | 632 Emit(kArmVmovU32F32, inputs[0], g.UseRegister(value)); |
626 inputs[input_count++] = g.UseRegister(base); | 633 inputs[input_count++] = g.UseRegister(base); |
627 EmitStore(this, kArmStr, input_count, inputs, index); | 634 EmitStore(this, kArmStr, input_count, inputs, index); |
628 return; | 635 return; |
629 } | 636 } |
630 case MachineRepresentation::kFloat64: { | 637 case MachineRepresentation::kFloat64: |
| 638 case MachineRepresentation::kSimd128: { |
631 if (CpuFeatures::IsSupported(NEON)) { | 639 if (CpuFeatures::IsSupported(NEON)) { |
632 InstructionOperand address = g.TempRegister(); | 640 InstructionOperand address = g.TempRegister(); |
633 { | 641 { |
634 // First we have to calculate the actual address. | 642 // First we have to calculate the actual address. |
635 InstructionCode add_opcode = kArmAdd; | 643 InstructionCode add_opcode = kArmAdd; |
636 InstructionOperand inputs[3]; | 644 InstructionOperand inputs[3]; |
637 inputs[0] = g.UseRegister(base); | 645 inputs[0] = g.UseRegister(base); |
638 | 646 |
639 size_t input_count; | 647 size_t input_count; |
640 if (TryMatchImmediateOrShift(this, &add_opcode, index, &input_count, | 648 if (TryMatchImmediateOrShift(this, &add_opcode, index, &input_count, |
641 &inputs[1])) { | 649 &inputs[1])) { |
642 // input_count has been set by TryMatchImmediateOrShift(), so | 650 // input_count has been set by TryMatchImmediateOrShift(), so |
643 // increment it to account for the base register in inputs[0]. | 651 // increment it to account for the base register in inputs[0]. |
644 input_count++; | 652 input_count++; |
645 } else { | 653 } else { |
646 add_opcode |= AddressingModeField::encode(kMode_Operand2_R); | 654 add_opcode |= AddressingModeField::encode(kMode_Operand2_R); |
647 inputs[1] = g.UseRegister(index); | 655 inputs[1] = g.UseRegister(index); |
648 input_count = 2; // Base register and index. | 656 input_count = 2; // Base register and index. |
649 } | 657 } |
650 | 658 |
651 Emit(add_opcode, 1, &address, input_count, inputs); | 659 Emit(add_opcode, 1, &address, input_count, inputs); |
652 } | 660 } |
653 | 661 |
654 inputs[input_count++] = g.UseRegister(value); | 662 inputs[input_count++] = g.UseRegister(value); |
655 inputs[input_count++] = address; | 663 inputs[input_count++] = address; |
656 Emit(kArmVst1F64, 0, nullptr, input_count, inputs); | 664 ArchOpcode op = store_rep == MachineRepresentation::kFloat64 |
| 665 ? kArmVst1F64 |
| 666 : kArmVst1S128; |
| 667 Emit(op, 0, nullptr, input_count, inputs); |
657 } else { | 668 } else { |
| 669 DCHECK_NE(MachineRepresentation::kSimd128, store_rep); |
658 // Store a 64-bit floating point value using two 32-bit integer stores. | 670 // Store a 64-bit floating point value using two 32-bit integer stores. |
659 // Computing the store address here would require three live temporary | 671 // Computing the store address here would require three live temporary |
660 // registers (fp<63:32>, fp<31:0>, address), so compute base + 4 after | 672 // registers (fp<63:32>, fp<31:0>, address), so compute base + 4 after |
661 // storing the least-significant half of the value. | 673 // storing the least-significant half of the value. |
662 | 674 |
663 // First, move the 64-bit FP value into two temporary integer registers. | 675 // First, move the 64-bit FP value into two temporary integer registers. |
664 InstructionOperand fp[] = {g.TempRegister(), g.TempRegister()}; | 676 InstructionOperand fp[] = {g.TempRegister(), g.TempRegister()}; |
665 inputs[input_count++] = g.UseRegister(value); | 677 inputs[input_count++] = g.UseRegister(value); |
666 Emit(kArmVmovU32U32F64, arraysize(fp), fp, input_count, inputs); | 678 Emit(kArmVmovU32U32F64, arraysize(fp), fp, input_count, inputs); |
667 | 679 |
(...skipping 1836 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2504 Vector<MachineType> req_aligned = Vector<MachineType>::New(2); | 2516 Vector<MachineType> req_aligned = Vector<MachineType>::New(2); |
2505 req_aligned[0] = MachineType::Float32(); | 2517 req_aligned[0] = MachineType::Float32(); |
2506 req_aligned[1] = MachineType::Float64(); | 2518 req_aligned[1] = MachineType::Float64(); |
2507 return MachineOperatorBuilder::AlignmentRequirements:: | 2519 return MachineOperatorBuilder::AlignmentRequirements:: |
2508 SomeUnalignedAccessUnsupported(req_aligned, req_aligned); | 2520 SomeUnalignedAccessUnsupported(req_aligned, req_aligned); |
2509 } | 2521 } |
2510 | 2522 |
2511 } // namespace compiler | 2523 } // namespace compiler |
2512 } // namespace internal | 2524 } // namespace internal |
2513 } // namespace v8 | 2525 } // namespace v8 |
OLD | NEW |