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 710 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
721 UNREACHABLE(); | 721 UNREACHABLE(); |
722 return VS; | 722 return VS; |
723 } | 723 } |
724 } | 724 } |
725 | 725 |
726 | 726 |
727 static void EmitDoubleComparisonOp(FlowGraphCompiler* compiler, | 727 static void EmitDoubleComparisonOp(FlowGraphCompiler* compiler, |
728 const LocationSummary& locs, | 728 const LocationSummary& locs, |
729 Token::Kind kind, | 729 Token::Kind kind, |
730 BranchInstr* branch) { | 730 BranchInstr* branch) { |
731 DRegister left = locs.in(0).fpu_reg(); | 731 QRegister left = locs.in(0).fpu_reg(); |
732 DRegister right = locs.in(1).fpu_reg(); | 732 QRegister right = locs.in(1).fpu_reg(); |
733 | 733 |
734 Condition true_condition = TokenKindToDoubleCondition(kind); | 734 Condition true_condition = TokenKindToDoubleCondition(kind); |
735 if (branch != NULL) { | 735 if (branch != NULL) { |
736 compiler->EmitDoubleCompareBranch( | 736 compiler->EmitDoubleCompareBranch( |
737 true_condition, left, right, branch); | 737 true_condition, left, right, branch); |
738 } else { | 738 } else { |
739 compiler->EmitDoubleCompareBool( | 739 compiler->EmitDoubleCompareBool( |
740 true_condition, left, right, locs.out().reg()); | 740 true_condition, left, right, locs.out().reg()); |
741 } | 741 } |
742 } | 742 } |
(...skipping 453 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1196 if (!IsExternal()) { | 1196 if (!IsExternal()) { |
1197 ASSERT(this->array()->definition()->representation() == kTagged); | 1197 ASSERT(this->array()->definition()->representation() == kTagged); |
1198 __ AddImmediate(index.reg(), | 1198 __ AddImmediate(index.reg(), |
1199 FlowGraphCompiler::DataOffsetFor(class_id()) - kHeapObjectTag); | 1199 FlowGraphCompiler::DataOffsetFor(class_id()) - kHeapObjectTag); |
1200 } | 1200 } |
1201 element_address = Address(array, index.reg(), LSL, 0); | 1201 element_address = Address(array, index.reg(), LSL, 0); |
1202 | 1202 |
1203 if ((representation() == kUnboxedDouble) || | 1203 if ((representation() == kUnboxedDouble) || |
1204 (representation() == kUnboxedMint) || | 1204 (representation() == kUnboxedMint) || |
1205 (representation() == kUnboxedFloat32x4)) { | 1205 (representation() == kUnboxedFloat32x4)) { |
1206 DRegister result = locs()->out().fpu_reg(); | 1206 QRegister qresult = locs()->out().fpu_reg(); |
| 1207 DRegister result = static_cast<DRegister>(qresult * 2); |
1207 switch (class_id()) { | 1208 switch (class_id()) { |
1208 case kTypedDataInt32ArrayCid: | 1209 case kTypedDataInt32ArrayCid: |
1209 UNIMPLEMENTED(); | 1210 UNIMPLEMENTED(); |
1210 break; | 1211 break; |
1211 case kTypedDataUint32ArrayCid: | 1212 case kTypedDataUint32ArrayCid: |
1212 UNIMPLEMENTED(); | 1213 UNIMPLEMENTED(); |
1213 break; | 1214 break; |
1214 case kTypedDataFloat32ArrayCid: | 1215 case kTypedDataFloat32ArrayCid: |
1215 // Load single precision float and promote to double. | 1216 // Load single precision float and promote to double. |
1216 // vldrs does not support indexed addressing. | 1217 // vldrs does not support indexed addressing. |
(...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1463 if (value()->IsSmiValue()) { | 1464 if (value()->IsSmiValue()) { |
1464 ASSERT(RequiredInputRepresentation(2) == kTagged); | 1465 ASSERT(RequiredInputRepresentation(2) == kTagged); |
1465 Register value = locs()->in(2).reg(); | 1466 Register value = locs()->in(2).reg(); |
1466 __ SmiUntag(value); | 1467 __ SmiUntag(value); |
1467 __ str(value, element_address); | 1468 __ str(value, element_address); |
1468 } else { | 1469 } else { |
1469 UNIMPLEMENTED(); | 1470 UNIMPLEMENTED(); |
1470 } | 1471 } |
1471 break; | 1472 break; |
1472 } | 1473 } |
1473 case kTypedDataFloat32ArrayCid: | 1474 case kTypedDataFloat32ArrayCid: { |
| 1475 DRegister in2 = static_cast<DRegister>(locs()->in(2).fpu_reg() * 2); |
1474 // Convert to single precision. | 1476 // Convert to single precision. |
1475 __ vcvtsd(STMP, locs()->in(2).fpu_reg()); | 1477 __ vcvtsd(STMP, in2); |
1476 // Store. | 1478 // Store. |
1477 __ add(index.reg(), index.reg(), ShifterOperand(array)); | 1479 __ add(index.reg(), index.reg(), ShifterOperand(array)); |
1478 __ StoreSToOffset(STMP, index.reg(), 0); | 1480 __ StoreSToOffset(STMP, index.reg(), 0); |
1479 break; | 1481 break; |
1480 case kTypedDataFloat64ArrayCid: | 1482 } |
| 1483 case kTypedDataFloat64ArrayCid: { |
| 1484 DRegister in2 = static_cast<DRegister>(locs()->in(2).fpu_reg() * 2); |
1481 __ add(index.reg(), index.reg(), ShifterOperand(array)); | 1485 __ add(index.reg(), index.reg(), ShifterOperand(array)); |
1482 __ StoreDToOffset(locs()->in(2).fpu_reg(), index.reg(), 0); | 1486 __ StoreDToOffset(in2, index.reg(), 0); |
1483 break; | 1487 break; |
| 1488 } |
1484 case kTypedDataFloat32x4ArrayCid: | 1489 case kTypedDataFloat32x4ArrayCid: |
1485 UNIMPLEMENTED(); | 1490 UNIMPLEMENTED(); |
1486 break; | 1491 break; |
1487 default: | 1492 default: |
1488 UNREACHABLE(); | 1493 UNREACHABLE(); |
1489 } | 1494 } |
1490 } | 1495 } |
1491 | 1496 |
1492 | 1497 |
1493 LocationSummary* GuardFieldInstr::MakeLocationSummary() const { | 1498 LocationSummary* GuardFieldInstr::MakeLocationSummary() const { |
(...skipping 964 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2458 case Token::kBIT_XOR: { | 2463 case Token::kBIT_XOR: { |
2459 // No overflow check. | 2464 // No overflow check. |
2460 __ eor(result, left, ShifterOperand(right)); | 2465 __ eor(result, left, ShifterOperand(right)); |
2461 break; | 2466 break; |
2462 } | 2467 } |
2463 case Token::kTRUNCDIV: { | 2468 case Token::kTRUNCDIV: { |
2464 // Handle divide by zero in runtime. | 2469 // Handle divide by zero in runtime. |
2465 __ cmp(right, ShifterOperand(0)); | 2470 __ cmp(right, ShifterOperand(0)); |
2466 __ b(deopt, EQ); | 2471 __ b(deopt, EQ); |
2467 Register temp = locs()->temp(0).reg(); | 2472 Register temp = locs()->temp(0).reg(); |
2468 DRegister dtemp = locs()->temp(1).fpu_reg(); | 2473 QRegister qtemp = locs()->temp(1).fpu_reg(); |
| 2474 DRegister dtemp = static_cast<DRegister>(qtemp * 2); |
2469 __ Asr(temp, left, kSmiTagSize); // SmiUntag left into temp. | 2475 __ Asr(temp, left, kSmiTagSize); // SmiUntag left into temp. |
2470 __ Asr(IP, right, kSmiTagSize); // SmiUntag right into IP. | 2476 __ Asr(IP, right, kSmiTagSize); // SmiUntag right into IP. |
2471 | 2477 |
2472 __ IntegerDivide(result, temp, IP, dtemp, DTMP); | 2478 __ IntegerDivide(result, temp, IP, dtemp, DTMP); |
2473 | 2479 |
2474 // Check the corner case of dividing the 'MIN_SMI' with -1, in which | 2480 // Check the corner case of dividing the 'MIN_SMI' with -1, in which |
2475 // case we cannot tag the result. | 2481 // case we cannot tag the result. |
2476 __ CompareImmediate(result, 0x40000000); | 2482 __ CompareImmediate(result, 0x40000000); |
2477 __ b(deopt, EQ); | 2483 __ b(deopt, EQ); |
2478 __ SmiTag(result); | 2484 __ SmiTag(result); |
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2597 | 2603 |
2598 private: | 2604 private: |
2599 BoxDoubleInstr* instruction_; | 2605 BoxDoubleInstr* instruction_; |
2600 }; | 2606 }; |
2601 | 2607 |
2602 | 2608 |
2603 void BoxDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2609 void BoxDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
2604 BoxDoubleSlowPath* slow_path = new BoxDoubleSlowPath(this); | 2610 BoxDoubleSlowPath* slow_path = new BoxDoubleSlowPath(this); |
2605 compiler->AddSlowPathCode(slow_path); | 2611 compiler->AddSlowPathCode(slow_path); |
2606 | 2612 |
2607 Register out_reg = locs()->out().reg(); | 2613 const Register out_reg = locs()->out().reg(); |
2608 DRegister value = locs()->in(0).fpu_reg(); | 2614 const QRegister qvalue = locs()->in(0).fpu_reg(); |
| 2615 const DRegister value = static_cast<DRegister>(qvalue * 2); |
2609 | 2616 |
2610 __ TryAllocate(compiler->double_class(), | 2617 __ TryAllocate(compiler->double_class(), |
2611 slow_path->entry_label(), | 2618 slow_path->entry_label(), |
2612 out_reg); | 2619 out_reg); |
2613 __ Bind(slow_path->exit_label()); | 2620 __ Bind(slow_path->exit_label()); |
2614 __ StoreDToOffset(value, out_reg, Double::value_offset() - kHeapObjectTag); | 2621 __ StoreDToOffset(value, out_reg, Double::value_offset() - kHeapObjectTag); |
2615 } | 2622 } |
2616 | 2623 |
2617 | 2624 |
2618 LocationSummary* UnboxDoubleInstr::MakeLocationSummary() const { | 2625 LocationSummary* UnboxDoubleInstr::MakeLocationSummary() const { |
2619 const intptr_t kNumInputs = 1; | 2626 const intptr_t kNumInputs = 1; |
2620 const intptr_t value_cid = value()->Type()->ToCid(); | 2627 const intptr_t value_cid = value()->Type()->ToCid(); |
2621 const bool needs_temp = ((value_cid != kSmiCid) && (value_cid != kDoubleCid)); | 2628 const bool needs_temp = ((value_cid != kSmiCid) && (value_cid != kDoubleCid)); |
2622 const bool needs_writable_input = (value_cid == kSmiCid); | 2629 const bool needs_writable_input = (value_cid == kSmiCid); |
2623 const intptr_t kNumTemps = needs_temp ? 1 : 0; | 2630 const intptr_t kNumTemps = needs_temp ? 1 : 0; |
2624 LocationSummary* summary = | 2631 LocationSummary* summary = |
2625 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 2632 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
2626 summary->set_in(0, needs_writable_input | 2633 summary->set_in(0, needs_writable_input |
2627 ? Location::WritableRegister() | 2634 ? Location::WritableRegister() |
2628 : Location::RequiresRegister()); | 2635 : Location::RequiresRegister()); |
2629 if (needs_temp) summary->set_temp(0, Location::RequiresRegister()); | 2636 if (needs_temp) summary->set_temp(0, Location::RequiresRegister()); |
2630 summary->set_out(Location::RequiresFpuRegister()); | 2637 summary->set_out(Location::RequiresFpuRegister()); |
2631 return summary; | 2638 return summary; |
2632 } | 2639 } |
2633 | 2640 |
2634 | 2641 |
2635 void UnboxDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2642 void UnboxDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
2636 const intptr_t value_cid = value()->Type()->ToCid(); | 2643 const intptr_t value_cid = value()->Type()->ToCid(); |
2637 const Register value = locs()->in(0).reg(); | 2644 const Register value = locs()->in(0).reg(); |
2638 const DRegister result = locs()->out().fpu_reg(); | 2645 const DRegister result = static_cast<DRegister>(locs()->out().fpu_reg() * 2); |
2639 | 2646 |
2640 if (value_cid == kDoubleCid) { | 2647 if (value_cid == kDoubleCid) { |
2641 __ LoadDFromOffset(result, value, Double::value_offset() - kHeapObjectTag); | 2648 __ LoadDFromOffset(result, value, Double::value_offset() - kHeapObjectTag); |
2642 } else if (value_cid == kSmiCid) { | 2649 } else if (value_cid == kSmiCid) { |
2643 __ SmiUntag(value); // Untag input before conversion. | 2650 __ SmiUntag(value); // Untag input before conversion. |
2644 __ vmovsr(STMP, value); | 2651 __ vmovsr(STMP, value); |
2645 __ vcvtdi(result, STMP); | 2652 __ vcvtdi(result, STMP); |
2646 } else { | 2653 } else { |
2647 Label* deopt = compiler->AddDeoptStub(deopt_id_, kDeoptBinaryDoubleOp); | 2654 Label* deopt = compiler->AddDeoptStub(deopt_id_, kDeoptBinaryDoubleOp); |
2648 Register temp = locs()->temp(0).reg(); | 2655 Register temp = locs()->temp(0).reg(); |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2713 LocationSummary* summary = | 2720 LocationSummary* summary = |
2714 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 2721 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
2715 summary->set_in(0, Location::RequiresFpuRegister()); | 2722 summary->set_in(0, Location::RequiresFpuRegister()); |
2716 summary->set_in(1, Location::RequiresFpuRegister()); | 2723 summary->set_in(1, Location::RequiresFpuRegister()); |
2717 summary->set_out(Location::RequiresFpuRegister()); | 2724 summary->set_out(Location::RequiresFpuRegister()); |
2718 return summary; | 2725 return summary; |
2719 } | 2726 } |
2720 | 2727 |
2721 | 2728 |
2722 void BinaryDoubleOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2729 void BinaryDoubleOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
2723 DRegister left = locs()->in(0).fpu_reg(); | 2730 DRegister left = static_cast<DRegister>(locs()->in(0).fpu_reg() * 2); |
2724 DRegister right = locs()->in(1).fpu_reg(); | 2731 DRegister right = static_cast<DRegister>(locs()->in(1).fpu_reg() * 2); |
2725 DRegister result = locs()->out().fpu_reg(); | 2732 DRegister result = static_cast<DRegister>(locs()->out().fpu_reg() * 2); |
2726 switch (op_kind()) { | 2733 switch (op_kind()) { |
2727 case Token::kADD: __ vaddd(result, left, right); break; | 2734 case Token::kADD: __ vaddd(result, left, right); break; |
2728 case Token::kSUB: __ vsubd(result, left, right); break; | 2735 case Token::kSUB: __ vsubd(result, left, right); break; |
2729 case Token::kMUL: __ vmuld(result, left, right); break; | 2736 case Token::kMUL: __ vmuld(result, left, right); break; |
2730 case Token::kDIV: __ vdivd(result, left, right); break; | 2737 case Token::kDIV: __ vdivd(result, left, right); break; |
2731 default: UNREACHABLE(); | 2738 default: UNREACHABLE(); |
2732 } | 2739 } |
2733 } | 2740 } |
2734 | 2741 |
2735 | 2742 |
(...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2946 const intptr_t kNumTemps = 0; | 2953 const intptr_t kNumTemps = 0; |
2947 LocationSummary* summary = | 2954 LocationSummary* summary = |
2948 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 2955 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
2949 summary->set_in(0, Location::RequiresFpuRegister()); | 2956 summary->set_in(0, Location::RequiresFpuRegister()); |
2950 summary->set_out(Location::RequiresFpuRegister()); | 2957 summary->set_out(Location::RequiresFpuRegister()); |
2951 return summary; | 2958 return summary; |
2952 } | 2959 } |
2953 | 2960 |
2954 | 2961 |
2955 void MathSqrtInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2962 void MathSqrtInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
2956 __ vsqrtd(locs()->out().fpu_reg(), locs()->in(0).fpu_reg()); | 2963 DRegister val = static_cast<DRegister>(locs()->in(0).fpu_reg() * 2); |
| 2964 DRegister result = static_cast<DRegister>(locs()->out().fpu_reg() * 2); |
| 2965 __ vsqrtd(result, val); |
2957 } | 2966 } |
2958 | 2967 |
2959 | 2968 |
2960 LocationSummary* UnarySmiOpInstr::MakeLocationSummary() const { | 2969 LocationSummary* UnarySmiOpInstr::MakeLocationSummary() const { |
2961 const intptr_t kNumInputs = 1; | 2970 const intptr_t kNumInputs = 1; |
2962 const intptr_t kNumTemps = 0; | 2971 const intptr_t kNumTemps = 0; |
2963 LocationSummary* summary = | 2972 LocationSummary* summary = |
2964 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 2973 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
2965 summary->set_in(0, Location::RequiresRegister()); | 2974 summary->set_in(0, Location::RequiresRegister()); |
2966 // We make use of 3-operand instructions by not requiring result register | 2975 // We make use of 3-operand instructions by not requiring result register |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2998 LocationSummary* result = | 3007 LocationSummary* result = |
2999 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3008 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
3000 result->set_in(0, Location::WritableRegister()); | 3009 result->set_in(0, Location::WritableRegister()); |
3001 result->set_out(Location::RequiresFpuRegister()); | 3010 result->set_out(Location::RequiresFpuRegister()); |
3002 return result; | 3011 return result; |
3003 } | 3012 } |
3004 | 3013 |
3005 | 3014 |
3006 void SmiToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3015 void SmiToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
3007 Register value = locs()->in(0).reg(); | 3016 Register value = locs()->in(0).reg(); |
3008 FpuRegister result = locs()->out().fpu_reg(); | 3017 DRegister result = static_cast<DRegister>(locs()->out().fpu_reg() * 2); |
3009 __ SmiUntag(value); | 3018 __ SmiUntag(value); |
3010 __ vmovsr(STMP, value); | 3019 __ vmovsr(STMP, value); |
3011 __ vcvtdi(result, STMP); | 3020 __ vcvtdi(result, STMP); |
3012 } | 3021 } |
3013 | 3022 |
3014 | 3023 |
3015 LocationSummary* DoubleToIntegerInstr::MakeLocationSummary() const { | 3024 LocationSummary* DoubleToIntegerInstr::MakeLocationSummary() const { |
3016 const intptr_t kNumInputs = 1; | 3025 const intptr_t kNumInputs = 1; |
3017 const intptr_t kNumTemps = 0; | 3026 const intptr_t kNumTemps = 0; |
3018 LocationSummary* result = | 3027 LocationSummary* result = |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3063 kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3072 kNumInputs, kNumTemps, LocationSummary::kNoCall); |
3064 result->set_in(0, Location::RequiresFpuRegister()); | 3073 result->set_in(0, Location::RequiresFpuRegister()); |
3065 result->set_out(Location::RequiresRegister()); | 3074 result->set_out(Location::RequiresRegister()); |
3066 return result; | 3075 return result; |
3067 } | 3076 } |
3068 | 3077 |
3069 | 3078 |
3070 void DoubleToSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3079 void DoubleToSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
3071 Label* deopt = compiler->AddDeoptStub(deopt_id(), kDeoptDoubleToSmi); | 3080 Label* deopt = compiler->AddDeoptStub(deopt_id(), kDeoptDoubleToSmi); |
3072 Register result = locs()->out().reg(); | 3081 Register result = locs()->out().reg(); |
3073 DRegister value = locs()->in(0).fpu_reg(); | 3082 QRegister qvalue = locs()->in(0).fpu_reg(); |
| 3083 DRegister value = static_cast<DRegister>(qvalue * 2); |
3074 __ vcvtid(STMP, value); | 3084 __ vcvtid(STMP, value); |
3075 __ vmovrs(result, STMP); | 3085 __ vmovrs(result, STMP); |
3076 // Check for overflow and that it fits into Smi. | 3086 // Check for overflow and that it fits into Smi. |
3077 __ CompareImmediate(result, 0xC0000000); | 3087 __ CompareImmediate(result, 0xC0000000); |
3078 __ b(deopt, MI); | 3088 __ b(deopt, MI); |
3079 __ SmiTag(result); | 3089 __ SmiTag(result); |
3080 } | 3090 } |
3081 | 3091 |
3082 | 3092 |
3083 LocationSummary* DoubleToDoubleInstr::MakeLocationSummary() const { | 3093 LocationSummary* DoubleToDoubleInstr::MakeLocationSummary() const { |
3084 const intptr_t kNumInputs = 1; | 3094 const intptr_t kNumInputs = 1; |
3085 const intptr_t kNumTemps = 0; | 3095 const intptr_t kNumTemps = 0; |
3086 LocationSummary* result = | 3096 LocationSummary* result = |
3087 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3097 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
3088 result->set_in(0, Location::RequiresFpuRegister()); | 3098 result->set_in(0, Location::RequiresFpuRegister()); |
3089 result->set_out(Location::RequiresFpuRegister()); | 3099 result->set_out(Location::RequiresFpuRegister()); |
3090 return result; | 3100 return result; |
3091 } | 3101 } |
3092 | 3102 |
3093 | 3103 |
3094 void DoubleToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3104 void DoubleToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
3095 // DRegister value = locs()->in(0).fpu_reg(); | 3105 // QRegister value = locs()->in(0).fpu_reg(); |
3096 // DRegister result = locs()->out().fpu_reg(); | 3106 // QRegister result = locs()->out().fpu_reg(); |
3097 switch (recognized_kind()) { | 3107 switch (recognized_kind()) { |
3098 case MethodRecognizer::kDoubleTruncate: | 3108 case MethodRecognizer::kDoubleTruncate: |
3099 UNIMPLEMENTED(); | 3109 UNIMPLEMENTED(); |
3100 // __ roundsd(result, value, Assembler::kRoundToZero); | 3110 // __ roundsd(result, value, Assembler::kRoundToZero); |
3101 break; | 3111 break; |
3102 case MethodRecognizer::kDoubleFloor: | 3112 case MethodRecognizer::kDoubleFloor: |
3103 UNIMPLEMENTED(); | 3113 UNIMPLEMENTED(); |
3104 // __ roundsd(result, value, Assembler::kRoundDown); | 3114 // __ roundsd(result, value, Assembler::kRoundDown); |
3105 break; | 3115 break; |
3106 case MethodRecognizer::kDoubleCeil: | 3116 case MethodRecognizer::kDoubleCeil: |
3107 UNIMPLEMENTED(); | 3117 UNIMPLEMENTED(); |
3108 // __ roundsd(result, value, Assembler::kRoundUp); | 3118 // __ roundsd(result, value, Assembler::kRoundUp); |
3109 break; | 3119 break; |
3110 default: | 3120 default: |
3111 UNREACHABLE(); | 3121 UNREACHABLE(); |
3112 } | 3122 } |
3113 } | 3123 } |
3114 | 3124 |
3115 | 3125 |
3116 LocationSummary* InvokeMathCFunctionInstr::MakeLocationSummary() const { | 3126 LocationSummary* InvokeMathCFunctionInstr::MakeLocationSummary() const { |
3117 ASSERT((InputCount() == 1) || (InputCount() == 2)); | 3127 ASSERT((InputCount() == 1) || (InputCount() == 2)); |
3118 const intptr_t kNumTemps = 0; | 3128 const intptr_t kNumTemps = 0; |
3119 LocationSummary* result = | 3129 LocationSummary* result = |
3120 new LocationSummary(InputCount(), kNumTemps, LocationSummary::kCall); | 3130 new LocationSummary(InputCount(), kNumTemps, LocationSummary::kCall); |
3121 result->set_in(0, Location::FpuRegisterLocation(D0)); | 3131 result->set_in(0, Location::FpuRegisterLocation(Q0)); |
3122 if (InputCount() == 2) { | 3132 if (InputCount() == 2) { |
3123 result->set_in(1, Location::FpuRegisterLocation(D1)); | 3133 result->set_in(1, Location::FpuRegisterLocation(Q1)); |
3124 } | 3134 } |
3125 result->set_out(Location::FpuRegisterLocation(D0)); | 3135 result->set_out(Location::FpuRegisterLocation(Q0)); |
3126 return result; | 3136 return result; |
3127 } | 3137 } |
3128 | 3138 |
3129 | 3139 |
3130 void InvokeMathCFunctionInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3140 void InvokeMathCFunctionInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
3131 // For pow-function return NAN if exponent is NAN. | 3141 // For pow-function return NAN if exponent is NAN. |
3132 Label do_call, skip_call; | 3142 Label do_call, skip_call; |
3133 if (recognized_kind() == MethodRecognizer::kDoublePow) { | 3143 if (recognized_kind() == MethodRecognizer::kDoublePow) { |
3134 DRegister exp = locs()->in(1).fpu_reg(); | 3144 DRegister exp = static_cast<DRegister>(locs()->in(1).fpu_reg() * 2); |
| 3145 DRegister result = static_cast<DRegister>(locs()->out().fpu_reg() * 2); |
3135 __ vcmpd(exp, exp); | 3146 __ vcmpd(exp, exp); |
3136 __ vmstat(); | 3147 __ vmstat(); |
3137 __ b(&do_call, VC); // NaN -> false; | 3148 __ b(&do_call, VC); // NaN -> false; |
3138 // Exponent is NaN, return NaN. | 3149 // Exponent is NaN, return NaN. |
3139 __ vmovd(locs()->out().fpu_reg(), exp); | 3150 __ vmovd(result, exp); |
3140 __ b(&skip_call); | 3151 __ b(&skip_call); |
3141 } | 3152 } |
3142 __ Bind(&do_call); | 3153 __ Bind(&do_call); |
3143 // We currently use 'hardfp' ('gnueabihf') rather than 'softfp' | 3154 // We currently use 'hardfp' ('gnueabihf') rather than 'softfp' |
3144 // ('gnueabi') float ABI for leaf runtime calls, i.e. double values | 3155 // ('gnueabi') float ABI for leaf runtime calls, i.e. double values |
3145 // are passed and returned in vfp registers rather than in integer | 3156 // are passed and returned in vfp registers rather than in integer |
3146 // register pairs. | 3157 // register pairs. |
| 3158 if (InputCount() == 2) { |
| 3159 // Args must be in D0 and D1, so move arg from Q1(== D3:D2) to D1. |
| 3160 __ vmovd(D1, D2); |
| 3161 } |
3147 __ CallRuntime(TargetFunction()); | 3162 __ CallRuntime(TargetFunction()); |
3148 __ Bind(&skip_call); | 3163 __ Bind(&skip_call); |
3149 } | 3164 } |
3150 | 3165 |
3151 | 3166 |
3152 LocationSummary* PolymorphicInstanceCallInstr::MakeLocationSummary() const { | 3167 LocationSummary* PolymorphicInstanceCallInstr::MakeLocationSummary() const { |
3153 return MakeCallSummary(); | 3168 return MakeCallSummary(); |
3154 } | 3169 } |
3155 | 3170 |
3156 | 3171 |
(...skipping 491 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3648 compiler->GenerateCall(token_pos(), | 3663 compiler->GenerateCall(token_pos(), |
3649 &label, | 3664 &label, |
3650 PcDescriptors::kOther, | 3665 PcDescriptors::kOther, |
3651 locs()); | 3666 locs()); |
3652 __ Drop(2); // Discard type arguments and receiver. | 3667 __ Drop(2); // Discard type arguments and receiver. |
3653 } | 3668 } |
3654 | 3669 |
3655 } // namespace dart | 3670 } // namespace dart |
3656 | 3671 |
3657 #endif // defined TARGET_ARCH_ARM | 3672 #endif // defined TARGET_ARCH_ARM |
OLD | NEW |