| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_ARM. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_ARM. |
| 6 #if defined(TARGET_ARCH_ARM) | 6 #if defined(TARGET_ARCH_ARM) |
| 7 | 7 |
| 8 #include "vm/intermediate_language.h" | 8 #include "vm/intermediate_language.h" |
| 9 | 9 |
| 10 #include "lib/error.h" | 10 #include "lib/error.h" |
| (...skipping 1186 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1197 if (!IsExternal()) { | 1197 if (!IsExternal()) { |
| 1198 ASSERT(this->array()->definition()->representation() == kTagged); | 1198 ASSERT(this->array()->definition()->representation() == kTagged); |
| 1199 __ AddImmediate(index.reg(), | 1199 __ AddImmediate(index.reg(), |
| 1200 FlowGraphCompiler::DataOffsetFor(class_id()) - kHeapObjectTag); | 1200 FlowGraphCompiler::DataOffsetFor(class_id()) - kHeapObjectTag); |
| 1201 } | 1201 } |
| 1202 element_address = Address(array, index.reg(), LSL, 0); | 1202 element_address = Address(array, index.reg(), LSL, 0); |
| 1203 | 1203 |
| 1204 if ((representation() == kUnboxedDouble) || | 1204 if ((representation() == kUnboxedDouble) || |
| 1205 (representation() == kUnboxedMint) || | 1205 (representation() == kUnboxedMint) || |
| 1206 (representation() == kUnboxedFloat32x4)) { | 1206 (representation() == kUnboxedFloat32x4)) { |
| 1207 DRegister result = EvenDRegisterOf(locs()->out().fpu_reg()); | 1207 QRegister result = locs()->out().fpu_reg(); |
| 1208 DRegister dresult0 = EvenDRegisterOf(result); |
| 1209 DRegister dresult1 = OddDRegisterOf(result); |
| 1208 switch (class_id()) { | 1210 switch (class_id()) { |
| 1209 case kTypedDataInt32ArrayCid: | 1211 case kTypedDataInt32ArrayCid: |
| 1210 UNIMPLEMENTED(); | 1212 UNIMPLEMENTED(); |
| 1211 break; | 1213 break; |
| 1212 case kTypedDataUint32ArrayCid: | 1214 case kTypedDataUint32ArrayCid: |
| 1213 UNIMPLEMENTED(); | 1215 UNIMPLEMENTED(); |
| 1214 break; | 1216 break; |
| 1215 case kTypedDataFloat32ArrayCid: | 1217 case kTypedDataFloat32ArrayCid: |
| 1216 // Load single precision float and promote to double. | 1218 // Load single precision float and promote to double. |
| 1217 // vldrs does not support indexed addressing. | 1219 // vldrs does not support indexed addressing. |
| 1218 __ add(index.reg(), index.reg(), ShifterOperand(array)); | 1220 __ add(index.reg(), index.reg(), ShifterOperand(array)); |
| 1219 element_address = Address(index.reg(), 0); | 1221 element_address = Address(index.reg(), 0); |
| 1220 __ vldrs(STMP, element_address); | 1222 __ vldrs(STMP, element_address); |
| 1221 __ vcvtds(result, STMP); | 1223 __ vcvtds(dresult0, STMP); |
| 1222 break; | 1224 break; |
| 1223 case kTypedDataFloat64ArrayCid: | 1225 case kTypedDataFloat64ArrayCid: |
| 1224 // vldrd does not support indexed addressing. | 1226 // vldrd does not support indexed addressing. |
| 1225 __ add(index.reg(), index.reg(), ShifterOperand(array)); | 1227 __ add(index.reg(), index.reg(), ShifterOperand(array)); |
| 1226 element_address = Address(index.reg(), 0); | 1228 element_address = Address(index.reg(), 0); |
| 1227 __ vldrd(result, element_address); | 1229 __ vldrd(dresult0, element_address); |
| 1228 break; | 1230 break; |
| 1229 case kTypedDataFloat32x4ArrayCid: | 1231 case kTypedDataFloat32x4ArrayCid: |
| 1230 UNIMPLEMENTED(); | 1232 __ add(index.reg(), index.reg(), ShifterOperand(array)); |
| 1233 __ LoadDFromOffset(dresult0, index.reg(), 0); |
| 1234 __ LoadDFromOffset(dresult1, index.reg(), 2*kWordSize); |
| 1231 break; | 1235 break; |
| 1232 } | 1236 } |
| 1233 return; | 1237 return; |
| 1234 } | 1238 } |
| 1235 | 1239 |
| 1236 Register result = locs()->out().reg(); | 1240 Register result = locs()->out().reg(); |
| 1237 switch (class_id()) { | 1241 switch (class_id()) { |
| 1238 case kTypedDataInt8ArrayCid: | 1242 case kTypedDataInt8ArrayCid: |
| 1239 ASSERT(index_scale() == 1); | 1243 ASSERT(index_scale() == 1); |
| 1240 __ ldrsb(result, element_address); | 1244 __ ldrsb(result, element_address); |
| (...skipping 238 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1479 __ add(index.reg(), index.reg(), ShifterOperand(array)); | 1483 __ add(index.reg(), index.reg(), ShifterOperand(array)); |
| 1480 __ StoreSToOffset(STMP, index.reg(), 0); | 1484 __ StoreSToOffset(STMP, index.reg(), 0); |
| 1481 break; | 1485 break; |
| 1482 } | 1486 } |
| 1483 case kTypedDataFloat64ArrayCid: { | 1487 case kTypedDataFloat64ArrayCid: { |
| 1484 DRegister in2 = EvenDRegisterOf(locs()->in(2).fpu_reg()); | 1488 DRegister in2 = EvenDRegisterOf(locs()->in(2).fpu_reg()); |
| 1485 __ add(index.reg(), index.reg(), ShifterOperand(array)); | 1489 __ add(index.reg(), index.reg(), ShifterOperand(array)); |
| 1486 __ StoreDToOffset(in2, index.reg(), 0); | 1490 __ StoreDToOffset(in2, index.reg(), 0); |
| 1487 break; | 1491 break; |
| 1488 } | 1492 } |
| 1489 case kTypedDataFloat32x4ArrayCid: | 1493 case kTypedDataFloat32x4ArrayCid: { |
| 1490 UNIMPLEMENTED(); | 1494 QRegister in = locs()->in(2).fpu_reg(); |
| 1495 DRegister din0 = EvenDRegisterOf(in); |
| 1496 DRegister din1 = OddDRegisterOf(in); |
| 1497 __ add(index.reg(), index.reg(), ShifterOperand(array)); |
| 1498 __ StoreDToOffset(din0, index.reg(), 0); |
| 1499 __ StoreDToOffset(din1, index.reg(), 2*kWordSize); |
| 1491 break; | 1500 break; |
| 1501 } |
| 1492 default: | 1502 default: |
| 1493 UNREACHABLE(); | 1503 UNREACHABLE(); |
| 1494 } | 1504 } |
| 1495 } | 1505 } |
| 1496 | 1506 |
| 1497 | 1507 |
| 1498 LocationSummary* GuardFieldInstr::MakeLocationSummary() const { | 1508 LocationSummary* GuardFieldInstr::MakeLocationSummary() const { |
| 1499 const intptr_t kNumInputs = 1; | 1509 const intptr_t kNumInputs = 1; |
| 1500 LocationSummary* summary = | 1510 LocationSummary* summary = |
| 1501 new LocationSummary(kNumInputs, 0, LocationSummary::kNoCall); | 1511 new LocationSummary(kNumInputs, 0, LocationSummary::kNoCall); |
| (...skipping 1160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2662 // TODO(regis): Why do we preserve value here but not above? | 2672 // TODO(regis): Why do we preserve value here but not above? |
| 2663 __ mov(IP, ShifterOperand(value, ASR, 1)); // Copy and untag. | 2673 __ mov(IP, ShifterOperand(value, ASR, 1)); // Copy and untag. |
| 2664 __ vmovsr(STMP, IP); | 2674 __ vmovsr(STMP, IP); |
| 2665 __ vcvtdi(result, STMP); | 2675 __ vcvtdi(result, STMP); |
| 2666 __ Bind(&done); | 2676 __ Bind(&done); |
| 2667 } | 2677 } |
| 2668 } | 2678 } |
| 2669 | 2679 |
| 2670 | 2680 |
| 2671 LocationSummary* BoxFloat32x4Instr::MakeLocationSummary() const { | 2681 LocationSummary* BoxFloat32x4Instr::MakeLocationSummary() const { |
| 2672 UNIMPLEMENTED(); | 2682 const intptr_t kNumInputs = 1; |
| 2673 return NULL; | 2683 const intptr_t kNumTemps = 0; |
| 2674 } | 2684 LocationSummary* summary = |
| 2685 new LocationSummary(kNumInputs, |
| 2686 kNumTemps, |
| 2687 LocationSummary::kCallOnSlowPath); |
| 2688 summary->set_in(0, Location::RequiresFpuRegister()); |
| 2689 summary->set_out(Location::RequiresRegister()); |
| 2690 return summary; |
| 2691 } |
| 2692 |
| 2693 |
| 2694 class BoxFloat32x4SlowPath : public SlowPathCode { |
| 2695 public: |
| 2696 explicit BoxFloat32x4SlowPath(BoxFloat32x4Instr* instruction) |
| 2697 : instruction_(instruction) { } |
| 2698 |
| 2699 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2700 __ Comment("BoxFloat32x4SlowPath"); |
| 2701 __ Bind(entry_label()); |
| 2702 const Class& float32x4_class = compiler->float32x4_class(); |
| 2703 const Code& stub = |
| 2704 Code::Handle(StubCode::GetAllocationStubForClass(float32x4_class)); |
| 2705 const ExternalLabel label(float32x4_class.ToCString(), stub.EntryPoint()); |
| 2706 |
| 2707 LocationSummary* locs = instruction_->locs(); |
| 2708 locs->live_registers()->Remove(locs->out()); |
| 2709 |
| 2710 compiler->SaveLiveRegisters(locs); |
| 2711 compiler->GenerateCall(Scanner::kDummyTokenIndex, // No token position. |
| 2712 &label, |
| 2713 PcDescriptors::kOther, |
| 2714 locs); |
| 2715 __ mov(locs->out().reg(), ShifterOperand(R0)); |
| 2716 compiler->RestoreLiveRegisters(locs); |
| 2717 |
| 2718 __ b(exit_label()); |
| 2719 } |
| 2720 |
| 2721 private: |
| 2722 BoxFloat32x4Instr* instruction_; |
| 2723 }; |
| 2675 | 2724 |
| 2676 | 2725 |
| 2677 void BoxFloat32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2726 void BoxFloat32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2678 UNIMPLEMENTED(); | 2727 BoxFloat32x4SlowPath* slow_path = new BoxFloat32x4SlowPath(this); |
| 2728 compiler->AddSlowPathCode(slow_path); |
| 2729 |
| 2730 Register out_reg = locs()->out().reg(); |
| 2731 QRegister value = locs()->in(0).fpu_reg(); |
| 2732 DRegister value_even = EvenDRegisterOf(value); |
| 2733 DRegister value_odd = OddDRegisterOf(value); |
| 2734 |
| 2735 __ TryAllocate(compiler->float32x4_class(), |
| 2736 slow_path->entry_label(), |
| 2737 out_reg); |
| 2738 __ Bind(slow_path->exit_label()); |
| 2739 |
| 2740 __ StoreDToOffset(value_even, out_reg, |
| 2741 Float32x4::value_offset() - kHeapObjectTag); |
| 2742 __ StoreDToOffset(value_odd, out_reg, |
| 2743 Float32x4::value_offset() + 2*kWordSize - kHeapObjectTag); |
| 2679 } | 2744 } |
| 2680 | 2745 |
| 2681 | 2746 |
| 2682 LocationSummary* UnboxFloat32x4Instr::MakeLocationSummary() const { | 2747 LocationSummary* UnboxFloat32x4Instr::MakeLocationSummary() const { |
| 2683 UNIMPLEMENTED(); | 2748 const intptr_t value_cid = value()->Type()->ToCid(); |
| 2684 return NULL; | 2749 const intptr_t kNumInputs = 1; |
| 2750 const intptr_t kNumTemps = value_cid == kFloat32x4Cid ? 0 : 1; |
| 2751 LocationSummary* summary = |
| 2752 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 2753 summary->set_in(0, Location::RequiresRegister()); |
| 2754 if (kNumTemps > 0) { |
| 2755 ASSERT(kNumTemps == 1); |
| 2756 summary->set_temp(0, Location::RequiresRegister()); |
| 2757 } |
| 2758 summary->set_out(Location::RequiresFpuRegister()); |
| 2759 return summary; |
| 2685 } | 2760 } |
| 2686 | 2761 |
| 2687 | 2762 |
| 2688 void UnboxFloat32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2763 void UnboxFloat32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2689 UNIMPLEMENTED(); | 2764 const intptr_t value_cid = value()->Type()->ToCid(); |
| 2765 const Register value = locs()->in(0).reg(); |
| 2766 const QRegister result = locs()->out().fpu_reg(); |
| 2767 |
| 2768 if (value_cid != kFloat32x4Cid) { |
| 2769 const Register temp = locs()->temp(0).reg(); |
| 2770 Label* deopt = compiler->AddDeoptStub(deopt_id_, kDeoptCheckClass); |
| 2771 __ tst(value, ShifterOperand(kSmiTagMask)); |
| 2772 __ b(deopt, EQ); |
| 2773 __ CompareClassId(value, kFloat32x4Cid, temp); |
| 2774 __ b(deopt, NE); |
| 2775 } |
| 2776 |
| 2777 const DRegister result_even = EvenDRegisterOf(result); |
| 2778 const DRegister result_odd = OddDRegisterOf(result); |
| 2779 __ LoadDFromOffset(result_even, value, |
| 2780 Float32x4::value_offset() - kHeapObjectTag); |
| 2781 __ LoadDFromOffset(result_odd, value, |
| 2782 Float32x4::value_offset() + 2*kWordSize - kHeapObjectTag); |
| 2690 } | 2783 } |
| 2691 | 2784 |
| 2692 | 2785 |
| 2693 LocationSummary* BoxUint32x4Instr::MakeLocationSummary() const { | 2786 LocationSummary* BoxUint32x4Instr::MakeLocationSummary() const { |
| 2694 UNIMPLEMENTED(); | 2787 const intptr_t kNumInputs = 1; |
| 2695 return NULL; | 2788 const intptr_t kNumTemps = 0; |
| 2696 } | 2789 LocationSummary* summary = |
| 2790 new LocationSummary(kNumInputs, |
| 2791 kNumTemps, |
| 2792 LocationSummary::kCallOnSlowPath); |
| 2793 summary->set_in(0, Location::RequiresFpuRegister()); |
| 2794 summary->set_out(Location::RequiresRegister()); |
| 2795 return summary; |
| 2796 } |
| 2797 |
| 2798 |
| 2799 class BoxUint32x4SlowPath : public SlowPathCode { |
| 2800 public: |
| 2801 explicit BoxUint32x4SlowPath(BoxUint32x4Instr* instruction) |
| 2802 : instruction_(instruction) { } |
| 2803 |
| 2804 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2805 __ Comment("BoxUint32x4SlowPath"); |
| 2806 __ Bind(entry_label()); |
| 2807 const Class& uint32x4_class = compiler->uint32x4_class(); |
| 2808 const Code& stub = |
| 2809 Code::Handle(StubCode::GetAllocationStubForClass(uint32x4_class)); |
| 2810 const ExternalLabel label(uint32x4_class.ToCString(), stub.EntryPoint()); |
| 2811 |
| 2812 LocationSummary* locs = instruction_->locs(); |
| 2813 locs->live_registers()->Remove(locs->out()); |
| 2814 |
| 2815 compiler->SaveLiveRegisters(locs); |
| 2816 compiler->GenerateCall(Scanner::kDummyTokenIndex, // No token position. |
| 2817 &label, |
| 2818 PcDescriptors::kOther, |
| 2819 locs); |
| 2820 __ mov(locs->out().reg(), ShifterOperand(R0)); |
| 2821 compiler->RestoreLiveRegisters(locs); |
| 2822 |
| 2823 __ b(exit_label()); |
| 2824 } |
| 2825 |
| 2826 private: |
| 2827 BoxUint32x4Instr* instruction_; |
| 2828 }; |
| 2697 | 2829 |
| 2698 | 2830 |
| 2699 void BoxUint32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2831 void BoxUint32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2700 UNIMPLEMENTED(); | 2832 BoxUint32x4SlowPath* slow_path = new BoxUint32x4SlowPath(this); |
| 2833 compiler->AddSlowPathCode(slow_path); |
| 2834 |
| 2835 Register out_reg = locs()->out().reg(); |
| 2836 QRegister value = locs()->in(0).fpu_reg(); |
| 2837 DRegister value_even = EvenDRegisterOf(value); |
| 2838 DRegister value_odd = OddDRegisterOf(value); |
| 2839 |
| 2840 __ TryAllocate(compiler->uint32x4_class(), |
| 2841 slow_path->entry_label(), |
| 2842 out_reg); |
| 2843 __ Bind(slow_path->exit_label()); |
| 2844 __ StoreDToOffset(value_even, out_reg, |
| 2845 Uint32x4::value_offset() - kHeapObjectTag); |
| 2846 __ StoreDToOffset(value_odd, out_reg, |
| 2847 Uint32x4::value_offset() + 2*kWordSize - kHeapObjectTag); |
| 2701 } | 2848 } |
| 2702 | 2849 |
| 2703 | 2850 |
| 2704 LocationSummary* UnboxUint32x4Instr::MakeLocationSummary() const { | 2851 LocationSummary* UnboxUint32x4Instr::MakeLocationSummary() const { |
| 2705 UNIMPLEMENTED(); | 2852 const intptr_t value_cid = value()->Type()->ToCid(); |
| 2706 return NULL; | 2853 const intptr_t kNumInputs = 1; |
| 2854 const intptr_t kNumTemps = value_cid == kUint32x4Cid ? 0 : 1; |
| 2855 LocationSummary* summary = |
| 2856 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 2857 summary->set_in(0, Location::RequiresRegister()); |
| 2858 if (kNumTemps > 0) { |
| 2859 ASSERT(kNumTemps == 1); |
| 2860 summary->set_temp(0, Location::RequiresRegister()); |
| 2861 } |
| 2862 summary->set_out(Location::RequiresFpuRegister()); |
| 2863 return summary; |
| 2707 } | 2864 } |
| 2708 | 2865 |
| 2709 | 2866 |
| 2710 void UnboxUint32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2867 void UnboxUint32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2711 UNIMPLEMENTED(); | 2868 const intptr_t value_cid = value()->Type()->ToCid(); |
| 2712 } | 2869 const Register value = locs()->in(0).reg(); |
| 2713 | 2870 const QRegister result = locs()->out().fpu_reg(); |
| 2714 | 2871 |
| 2872 if (value_cid != kUint32x4Cid) { |
| 2873 const Register temp = locs()->temp(0).reg(); |
| 2874 Label* deopt = compiler->AddDeoptStub(deopt_id_, kDeoptCheckClass); |
| 2875 __ tst(value, ShifterOperand(kSmiTagMask)); |
| 2876 __ b(deopt, EQ); |
| 2877 __ CompareClassId(value, kUint32x4Cid, temp); |
| 2878 __ b(deopt, NE); |
| 2879 } |
| 2880 |
| 2881 const DRegister result_even = EvenDRegisterOf(result); |
| 2882 const DRegister result_odd = OddDRegisterOf(result); |
| 2883 __ LoadDFromOffset(result_even, value, |
| 2884 Uint32x4::value_offset() - kHeapObjectTag); |
| 2885 __ LoadDFromOffset(result_odd, value, |
| 2886 Uint32x4::value_offset() + 2*kWordSize - kHeapObjectTag); |
| 2887 } |
| 2888 |
| 2889 |
| 2715 LocationSummary* BinaryDoubleOpInstr::MakeLocationSummary() const { | 2890 LocationSummary* BinaryDoubleOpInstr::MakeLocationSummary() const { |
| 2716 const intptr_t kNumInputs = 2; | 2891 const intptr_t kNumInputs = 2; |
| 2717 const intptr_t kNumTemps = 0; | 2892 const intptr_t kNumTemps = 0; |
| 2718 LocationSummary* summary = | 2893 LocationSummary* summary = |
| 2719 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 2894 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 2720 summary->set_in(0, Location::RequiresFpuRegister()); | 2895 summary->set_in(0, Location::RequiresFpuRegister()); |
| 2721 summary->set_in(1, Location::RequiresFpuRegister()); | 2896 summary->set_in(1, Location::RequiresFpuRegister()); |
| 2722 summary->set_out(Location::RequiresFpuRegister()); | 2897 summary->set_out(Location::RequiresFpuRegister()); |
| 2723 return summary; | 2898 return summary; |
| 2724 } | 2899 } |
| 2725 | 2900 |
| 2726 | 2901 |
| 2727 void BinaryDoubleOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2902 void BinaryDoubleOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2728 DRegister left = EvenDRegisterOf(locs()->in(0).fpu_reg()); | 2903 DRegister left = EvenDRegisterOf(locs()->in(0).fpu_reg()); |
| 2729 DRegister right = EvenDRegisterOf(locs()->in(1).fpu_reg()); | 2904 DRegister right = EvenDRegisterOf(locs()->in(1).fpu_reg()); |
| 2730 DRegister result = EvenDRegisterOf(locs()->out().fpu_reg()); | 2905 DRegister result = EvenDRegisterOf(locs()->out().fpu_reg()); |
| 2731 switch (op_kind()) { | 2906 switch (op_kind()) { |
| 2732 case Token::kADD: __ vaddd(result, left, right); break; | 2907 case Token::kADD: __ vaddd(result, left, right); break; |
| 2733 case Token::kSUB: __ vsubd(result, left, right); break; | 2908 case Token::kSUB: __ vsubd(result, left, right); break; |
| 2734 case Token::kMUL: __ vmuld(result, left, right); break; | 2909 case Token::kMUL: __ vmuld(result, left, right); break; |
| 2735 case Token::kDIV: __ vdivd(result, left, right); break; | 2910 case Token::kDIV: __ vdivd(result, left, right); break; |
| 2736 default: UNREACHABLE(); | 2911 default: UNREACHABLE(); |
| 2737 } | 2912 } |
| 2738 } | 2913 } |
| 2739 | 2914 |
| 2740 | 2915 |
| 2741 LocationSummary* BinaryFloat32x4OpInstr::MakeLocationSummary() const { | 2916 LocationSummary* BinaryFloat32x4OpInstr::MakeLocationSummary() const { |
| 2742 UNIMPLEMENTED(); | 2917 const intptr_t kNumInputs = 2; |
| 2743 return NULL; | 2918 const intptr_t kNumTemps = 0; |
| 2919 LocationSummary* summary = |
| 2920 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 2921 summary->set_in(0, Location::RequiresFpuRegister()); |
| 2922 summary->set_in(1, Location::RequiresFpuRegister()); |
| 2923 summary->set_out(Location::RequiresFpuRegister()); |
| 2924 return summary; |
| 2744 } | 2925 } |
| 2745 | 2926 |
| 2746 | 2927 |
| 2747 void BinaryFloat32x4OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2928 void BinaryFloat32x4OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2748 UNIMPLEMENTED(); | 2929 QRegister left = locs()->in(0).fpu_reg(); |
| 2930 QRegister right = locs()->in(1).fpu_reg(); |
| 2931 QRegister result = locs()->out().fpu_reg(); |
| 2932 |
| 2933 switch (op_kind()) { |
| 2934 case Token::kADD: __ vaddqs(result, left, right); break; |
| 2935 case Token::kSUB: __ vsubqs(result, left, right); break; |
| 2936 case Token::kMUL: __ vmulqs(result, left, right); break; |
| 2937 // TODO(zra): Two options for division. Either use vdiv piecewise, or do |
| 2938 // vrecpeqs followed by vmulqs. |
| 2939 case Token::kDIV: UNIMPLEMENTED(); break; |
| 2940 default: UNREACHABLE(); |
| 2941 } |
| 2749 } | 2942 } |
| 2750 | 2943 |
| 2751 | 2944 |
| 2752 LocationSummary* Float32x4ShuffleInstr::MakeLocationSummary() const { | 2945 LocationSummary* Float32x4ShuffleInstr::MakeLocationSummary() const { |
| 2753 UNIMPLEMENTED(); | 2946 const intptr_t kNumInputs = 1; |
| 2754 return NULL; | 2947 const intptr_t kNumTemps = 0; |
| 2948 LocationSummary* summary = |
| 2949 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 2950 summary->set_in(0, Location::RequiresFpuRegister()); |
| 2951 summary->set_out(Location::RequiresFpuRegister()); |
| 2952 return summary; |
| 2755 } | 2953 } |
| 2756 | 2954 |
| 2757 | 2955 |
| 2758 void Float32x4ShuffleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2956 void Float32x4ShuffleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2759 UNIMPLEMENTED(); | 2957 QRegister value = locs()->in(0).fpu_reg(); |
| 2958 QRegister result = locs()->out().fpu_reg(); |
| 2959 DRegister dresult0 = EvenDRegisterOf(result); |
| 2960 SRegister sresult0 = EvenSRegisterOf(dresult0); |
| 2961 |
| 2962 DRegister dvalue0 = EvenDRegisterOf(value); |
| 2963 DRegister dvalue1 = OddDRegisterOf(value); |
| 2964 |
| 2965 // For these cases the vdup instruction requires fewer |
| 2966 // instructions. For arbitrary shuffles, vtbl will be needed. |
| 2967 switch (op_kind()) { |
| 2968 case MethodRecognizer::kFloat32x4ShuffleXXXX: |
| 2969 __ vdup(kWord, result, dvalue0, 0); |
| 2970 break; |
| 2971 case MethodRecognizer::kFloat32x4ShuffleYYYY: |
| 2972 __ vdup(kWord, result, dvalue0, 1); |
| 2973 break; |
| 2974 case MethodRecognizer::kFloat32x4ShuffleZZZZ: |
| 2975 __ vdup(kWord, result, dvalue1, 0); |
| 2976 break; |
| 2977 case MethodRecognizer::kFloat32x4ShuffleWWWW: |
| 2978 __ vdup(kWord, result, dvalue1, 1); |
| 2979 break; |
| 2980 case MethodRecognizer::kFloat32x4ShuffleX: |
| 2981 __ vdup(kWord, result, dvalue0, 0); |
| 2982 __ vcvtds(dresult0, sresult0); |
| 2983 break; |
| 2984 case MethodRecognizer::kFloat32x4ShuffleY: |
| 2985 __ vdup(kWord, result, dvalue0, 1); |
| 2986 __ vcvtds(dresult0, sresult0); |
| 2987 break; |
| 2988 case MethodRecognizer::kFloat32x4ShuffleZ: |
| 2989 __ vdup(kWord, result, dvalue1, 0); |
| 2990 __ vcvtds(dresult0, sresult0); |
| 2991 break; |
| 2992 case MethodRecognizer::kFloat32x4ShuffleW: |
| 2993 __ vdup(kWord, result, dvalue1, 1); |
| 2994 __ vcvtds(dresult0, sresult0); |
| 2995 break; |
| 2996 default: UNREACHABLE(); |
| 2997 } |
| 2760 } | 2998 } |
| 2761 | 2999 |
| 2762 | 3000 |
| 2763 LocationSummary* Float32x4ConstructorInstr::MakeLocationSummary() const { | 3001 LocationSummary* Float32x4ConstructorInstr::MakeLocationSummary() const { |
| 2764 UNIMPLEMENTED(); | 3002 const intptr_t kNumInputs = 4; |
| 2765 return NULL; | 3003 const intptr_t kNumTemps = 0; |
| 3004 LocationSummary* summary = |
| 3005 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 3006 summary->set_in(0, Location::RequiresFpuRegister()); |
| 3007 summary->set_in(1, Location::RequiresFpuRegister()); |
| 3008 summary->set_in(2, Location::RequiresFpuRegister()); |
| 3009 summary->set_in(3, Location::RequiresFpuRegister()); |
| 3010 summary->set_out(Location::RequiresFpuRegister()); |
| 3011 return summary; |
| 2766 } | 3012 } |
| 2767 | 3013 |
| 2768 | 3014 |
| 2769 void Float32x4ConstructorInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3015 void Float32x4ConstructorInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2770 UNIMPLEMENTED(); | 3016 QRegister q0 = locs()->in(0).fpu_reg(); |
| 3017 QRegister q1 = locs()->in(1).fpu_reg(); |
| 3018 QRegister q2 = locs()->in(2).fpu_reg(); |
| 3019 QRegister q3 = locs()->in(3).fpu_reg(); |
| 3020 QRegister r = locs()->out().fpu_reg(); |
| 3021 |
| 3022 DRegister dr0 = EvenDRegisterOf(r); |
| 3023 DRegister dr1 = OddDRegisterOf(r); |
| 3024 |
| 3025 __ vcvtsd(EvenSRegisterOf(dr0), EvenDRegisterOf(q0)); |
| 3026 __ vcvtsd(OddSRegisterOf(dr0), EvenDRegisterOf(q1)); |
| 3027 __ vcvtsd(EvenSRegisterOf(dr1), EvenDRegisterOf(q2)); |
| 3028 __ vcvtsd(OddSRegisterOf(dr1), EvenDRegisterOf(q3)); |
| 2771 } | 3029 } |
| 2772 | 3030 |
| 2773 | 3031 |
| 2774 LocationSummary* Float32x4ZeroInstr::MakeLocationSummary() const { | 3032 LocationSummary* Float32x4ZeroInstr::MakeLocationSummary() const { |
| 2775 UNIMPLEMENTED(); | 3033 const intptr_t kNumInputs = 0; |
| 2776 return NULL; | 3034 const intptr_t kNumTemps = 0; |
| 3035 LocationSummary* summary = |
| 3036 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 3037 summary->set_out(Location::RequiresFpuRegister()); |
| 3038 return summary; |
| 2777 } | 3039 } |
| 2778 | 3040 |
| 2779 | 3041 |
| 2780 void Float32x4ZeroInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3042 void Float32x4ZeroInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2781 UNIMPLEMENTED(); | 3043 QRegister q = locs()->out().fpu_reg(); |
| 3044 __ veorq(q, q, q); |
| 2782 } | 3045 } |
| 2783 | 3046 |
| 2784 | 3047 |
| 2785 LocationSummary* Float32x4SplatInstr::MakeLocationSummary() const { | 3048 LocationSummary* Float32x4SplatInstr::MakeLocationSummary() const { |
| 2786 UNIMPLEMENTED(); | 3049 const intptr_t kNumInputs = 1; |
| 2787 return NULL; | 3050 const intptr_t kNumTemps = 0; |
| 3051 LocationSummary* summary = |
| 3052 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 3053 summary->set_in(0, Location::RequiresFpuRegister()); |
| 3054 summary->set_out(Location::RequiresFpuRegister()); |
| 3055 return summary; |
| 2788 } | 3056 } |
| 2789 | 3057 |
| 2790 | 3058 |
| 2791 void Float32x4SplatInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3059 void Float32x4SplatInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2792 UNIMPLEMENTED(); | 3060 QRegister value = locs()->in(0).fpu_reg(); |
| 3061 QRegister result = locs()->out().fpu_reg(); |
| 3062 |
| 3063 DRegister dvalue0 = EvenDRegisterOf(value); |
| 3064 |
| 3065 // Convert to Float32. |
| 3066 __ vcvtsd(STMP, dvalue0); |
| 3067 |
| 3068 // Splat across all lanes. |
| 3069 __ vdup(kWord, result, DTMP, 0); |
| 2793 } | 3070 } |
| 2794 | 3071 |
| 2795 | 3072 |
| 2796 LocationSummary* Float32x4ComparisonInstr::MakeLocationSummary() const { | 3073 LocationSummary* Float32x4ComparisonInstr::MakeLocationSummary() const { |
| 2797 UNIMPLEMENTED(); | 3074 UNIMPLEMENTED(); |
| 2798 return NULL; | 3075 return NULL; |
| 2799 } | 3076 } |
| 2800 | 3077 |
| 2801 | 3078 |
| 2802 void Float32x4ComparisonInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3079 void Float32x4ComparisonInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| (...skipping 871 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3674 compiler->GenerateCall(token_pos(), | 3951 compiler->GenerateCall(token_pos(), |
| 3675 &label, | 3952 &label, |
| 3676 PcDescriptors::kOther, | 3953 PcDescriptors::kOther, |
| 3677 locs()); | 3954 locs()); |
| 3678 __ Drop(2); // Discard type arguments and receiver. | 3955 __ Drop(2); // Discard type arguments and receiver. |
| 3679 } | 3956 } |
| 3680 | 3957 |
| 3681 } // namespace dart | 3958 } // namespace dart |
| 3682 | 3959 |
| 3683 #endif // defined TARGET_ARCH_ARM | 3960 #endif // defined TARGET_ARCH_ARM |
| OLD | NEW |