| 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 542 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 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. |
| 555 switch (load_rep.representation()) { | 555 switch (load_rep.representation()) { |
| 556 case MachineRepresentation::kFloat32: { | 556 case MachineRepresentation::kFloat32: { |
| 557 InstructionOperand temp = g.TempRegister(); | 557 InstructionOperand temp = g.TempRegister(); |
| 558 EmitLoad(this, opcode, &temp, base, index); | 558 EmitLoad(this, opcode, &temp, base, index); |
| 559 Emit(kArmVmovF32U32, g.DefineAsRegister(node), temp); | 559 Emit(kArmVmovF32U32, g.DefineAsRegister(node), temp); |
| 560 return; | 560 return; |
| 561 } | 561 } |
| 562 case MachineRepresentation::kFloat64: { | 562 case MachineRepresentation::kFloat64: { |
| 563 // TODO(arm): use vld1.8 for this when NEON is available. | 563 if (CpuFeatures::IsSupported(NEON)) { |
| 564 // Compute the address of the least-significant half of the FP value. | 564 InstructionOperand output = g.DefineAsRegister(node); |
| 565 // We assume that the base node is unlikely to be an encodable immediate | 565 EmitLoad(this, kArmVld1F64, &output, base, index); |
| 566 // or the result of a shift operation, so only consider the addressing | 566 } else { |
| 567 // mode that should be used for the index node. | 567 // Compute the address of the least-significant half of the FP value. |
| 568 InstructionCode add_opcode = kArmAdd; | 568 // We assume that the base node is unlikely to be an encodable immediate |
| 569 InstructionOperand inputs[3]; | 569 // or the result of a shift operation, so only consider the addressing |
| 570 inputs[0] = g.UseRegister(base); | 570 // mode that should be used for the index node. |
| 571 InstructionCode add_opcode = kArmAdd; |
| 572 InstructionOperand inputs[3]; |
| 573 inputs[0] = g.UseRegister(base); |
| 571 | 574 |
| 572 size_t input_count; | 575 size_t input_count; |
| 573 if (TryMatchImmediateOrShift(this, &add_opcode, index, &input_count, | 576 if (TryMatchImmediateOrShift(this, &add_opcode, index, &input_count, |
| 574 &inputs[1])) { | 577 &inputs[1])) { |
| 575 // input_count has been set by TryMatchImmediateOrShift(), so increment | 578 // input_count has been set by TryMatchImmediateOrShift(), so |
| 576 // it to account for the base register in inputs[0]. | 579 // increment it to account for the base register in inputs[0]. |
| 577 input_count++; | 580 input_count++; |
| 578 } else { | 581 } else { |
| 579 add_opcode |= AddressingModeField::encode(kMode_Operand2_R); | 582 add_opcode |= AddressingModeField::encode(kMode_Operand2_R); |
| 580 inputs[1] = g.UseRegister(index); | 583 inputs[1] = g.UseRegister(index); |
| 581 input_count = 2; // Base register and index. | 584 input_count = 2; // Base register and index. |
| 585 } |
| 586 |
| 587 InstructionOperand addr = g.TempRegister(); |
| 588 Emit(add_opcode, 1, &addr, input_count, inputs); |
| 589 |
| 590 // Load both halves and move to an FP register. |
| 591 InstructionOperand fp_lo = g.TempRegister(); |
| 592 InstructionOperand fp_hi = g.TempRegister(); |
| 593 opcode |= AddressingModeField::encode(kMode_Offset_RI); |
| 594 Emit(opcode, fp_lo, addr, g.TempImmediate(0)); |
| 595 Emit(opcode, fp_hi, addr, g.TempImmediate(4)); |
| 596 Emit(kArmVmovF64U32U32, g.DefineAsRegister(node), fp_lo, fp_hi); |
| 582 } | 597 } |
| 583 | |
| 584 InstructionOperand addr = g.TempRegister(); | |
| 585 Emit(add_opcode, 1, &addr, input_count, inputs); | |
| 586 | |
| 587 // Load both halves and move to an FP register. | |
| 588 InstructionOperand fp_lo = g.TempRegister(); | |
| 589 InstructionOperand fp_hi = g.TempRegister(); | |
| 590 opcode |= AddressingModeField::encode(kMode_Offset_RI); | |
| 591 Emit(opcode, fp_lo, addr, g.TempImmediate(0)); | |
| 592 Emit(opcode, fp_hi, addr, g.TempImmediate(4)); | |
| 593 Emit(kArmVmovF64U32U32, g.DefineAsRegister(node), fp_lo, fp_hi); | |
| 594 return; | 598 return; |
| 595 } | 599 } |
| 596 default: | 600 default: |
| 597 // All other cases should support unaligned accesses. | 601 // All other cases should support unaligned accesses. |
| 598 UNREACHABLE(); | 602 UNREACHABLE(); |
| 599 return; | 603 return; |
| 600 } | 604 } |
| 601 } | 605 } |
| 602 | 606 |
| 603 void InstructionSelector::VisitUnalignedStore(Node* node) { | 607 void InstructionSelector::VisitUnalignedStore(Node* node) { |
| (...skipping 13 matching lines...) Expand all Loading... |
| 617 // value to integer registers first, then storing to the destination address. | 621 // value to integer registers first, then storing to the destination address. |
| 618 switch (store_rep) { | 622 switch (store_rep) { |
| 619 case MachineRepresentation::kFloat32: { | 623 case MachineRepresentation::kFloat32: { |
| 620 inputs[input_count++] = g.TempRegister(); | 624 inputs[input_count++] = g.TempRegister(); |
| 621 Emit(kArmVmovU32F32, inputs[0], g.UseRegister(value)); | 625 Emit(kArmVmovU32F32, inputs[0], g.UseRegister(value)); |
| 622 inputs[input_count++] = g.UseRegister(base); | 626 inputs[input_count++] = g.UseRegister(base); |
| 623 EmitStore(this, kArmStr, input_count, inputs, index); | 627 EmitStore(this, kArmStr, input_count, inputs, index); |
| 624 return; | 628 return; |
| 625 } | 629 } |
| 626 case MachineRepresentation::kFloat64: { | 630 case MachineRepresentation::kFloat64: { |
| 627 // TODO(arm): use vst1.8 for this when NEON is available. | 631 if (CpuFeatures::IsSupported(NEON)) { |
| 628 // Store a 64-bit floating point value using two 32-bit integer stores. | 632 inputs[input_count++] = g.UseRegister(value); |
| 629 // Computing the store address here would require three live temporary | 633 inputs[input_count++] = g.UseRegister(base); |
| 630 // registers (fp<63:32>, fp<31:0>, address), so compute base + 4 after | 634 EmitStore(this, kArmVst1F64, input_count, inputs, index); |
| 631 // storing the least-significant half of the value. | 635 } else { |
| 636 // Store a 64-bit floating point value using two 32-bit integer stores. |
| 637 // Computing the store address here would require three live temporary |
| 638 // registers (fp<63:32>, fp<31:0>, address), so compute base + 4 after |
| 639 // storing the least-significant half of the value. |
| 632 | 640 |
| 633 // First, move the 64-bit FP value into two temporary integer registers. | 641 // First, move the 64-bit FP value into two temporary integer registers. |
| 634 InstructionOperand fp[] = {g.TempRegister(), g.TempRegister()}; | 642 InstructionOperand fp[] = {g.TempRegister(), g.TempRegister()}; |
| 635 inputs[input_count++] = g.UseRegister(value); | 643 inputs[input_count++] = g.UseRegister(value); |
| 636 Emit(kArmVmovU32U32F64, arraysize(fp), fp, input_count, | 644 Emit(kArmVmovU32U32F64, arraysize(fp), fp, input_count, inputs); |
| 637 inputs); | |
| 638 | 645 |
| 639 // Store the least-significant half. | 646 // Store the least-significant half. |
| 640 inputs[0] = fp[0]; // Low 32-bits of FP value. | 647 inputs[0] = fp[0]; // Low 32-bits of FP value. |
| 641 inputs[input_count++] = g.UseRegister(base); // First store base address. | 648 inputs[input_count++] = |
| 642 EmitStore(this, kArmStr, input_count, inputs, index); | 649 g.UseRegister(base); // First store base address. |
| 650 EmitStore(this, kArmStr, input_count, inputs, index); |
| 643 | 651 |
| 644 // Store the most-significant half. | 652 // Store the most-significant half. |
| 645 InstructionOperand base4 = g.TempRegister(); | 653 InstructionOperand base4 = g.TempRegister(); |
| 646 Emit(kArmAdd | AddressingModeField::encode(kMode_Operand2_I), base4, | 654 Emit(kArmAdd | AddressingModeField::encode(kMode_Operand2_I), base4, |
| 647 g.UseRegister(base), g.TempImmediate(4)); // Compute base + 4. | 655 g.UseRegister(base), g.TempImmediate(4)); // Compute base + 4. |
| 648 inputs[0] = fp[1]; // High 32-bits of FP value. | 656 inputs[0] = fp[1]; // High 32-bits of FP value. |
| 649 inputs[1] = base4; // Second store base + 4 address. | 657 inputs[1] = base4; // Second store base + 4 address. |
| 650 EmitStore(this, kArmStr, input_count, inputs, index); | 658 EmitStore(this, kArmStr, input_count, inputs, index); |
| 659 } |
| 651 return; | 660 return; |
| 652 } | 661 } |
| 653 default: | 662 default: |
| 654 // All other cases should support unaligned accesses. | 663 // All other cases should support unaligned accesses. |
| 655 UNREACHABLE(); | 664 UNREACHABLE(); |
| 656 return; | 665 return; |
| 657 } | 666 } |
| 658 } | 667 } |
| 659 | 668 |
| 660 void InstructionSelector::VisitCheckedLoad(Node* node) { | 669 void InstructionSelector::VisitCheckedLoad(Node* node) { |
| (...skipping 1812 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2473 Vector<MachineType> req_aligned = Vector<MachineType>::New(2); | 2482 Vector<MachineType> req_aligned = Vector<MachineType>::New(2); |
| 2474 req_aligned[0] = MachineType::Float32(); | 2483 req_aligned[0] = MachineType::Float32(); |
| 2475 req_aligned[1] = MachineType::Float64(); | 2484 req_aligned[1] = MachineType::Float64(); |
| 2476 return MachineOperatorBuilder::AlignmentRequirements:: | 2485 return MachineOperatorBuilder::AlignmentRequirements:: |
| 2477 SomeUnalignedAccessUnsupported(req_aligned, req_aligned); | 2486 SomeUnalignedAccessUnsupported(req_aligned, req_aligned); |
| 2478 } | 2487 } |
| 2479 | 2488 |
| 2480 } // namespace compiler | 2489 } // namespace compiler |
| 2481 } // namespace internal | 2490 } // namespace internal |
| 2482 } // namespace v8 | 2491 } // namespace v8 |
| OLD | NEW |