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