| OLD | NEW |
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, 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_ARM64. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_ARM64. |
| 6 #if defined(TARGET_ARCH_ARM64) | 6 #if defined(TARGET_ARCH_ARM64) |
| 7 | 7 |
| 8 #include "vm/intermediate_language.h" | 8 #include "vm/intermediate_language.h" |
| 9 | 9 |
| 10 #include "vm/dart_entry.h" | 10 #include "vm/dart_entry.h" |
| (...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 172 } else { | 172 } else { |
| 173 true_condition = NegateCondition(true_condition); | 173 true_condition = NegateCondition(true_condition); |
| 174 } | 174 } |
| 175 } | 175 } |
| 176 | 176 |
| 177 __ cset(result, true_condition); | 177 __ cset(result, true_condition); |
| 178 | 178 |
| 179 if (is_power_of_two_kind) { | 179 if (is_power_of_two_kind) { |
| 180 const intptr_t shift = | 180 const intptr_t shift = |
| 181 Utils::ShiftForPowerOfTwo(Utils::Maximum(true_value, false_value)); | 181 Utils::ShiftForPowerOfTwo(Utils::Maximum(true_value, false_value)); |
| 182 __ Lsl(result, result, shift + kSmiTagSize); | 182 __ LslImmediate(result, result, shift + kSmiTagSize); |
| 183 } else { | 183 } else { |
| 184 __ sub(result, result, Operand(1)); | 184 __ sub(result, result, Operand(1)); |
| 185 const int64_t val = | 185 const int64_t val = |
| 186 Smi::RawValue(true_value) - Smi::RawValue(false_value); | 186 Smi::RawValue(true_value) - Smi::RawValue(false_value); |
| 187 __ AndImmediate(result, result, val, PP); | 187 __ AndImmediate(result, result, val, PP); |
| 188 if (false_value != 0) { | 188 if (false_value != 0) { |
| 189 __ AddImmediate(result, result, Smi::RawValue(false_value), PP); | 189 __ AddImmediate(result, result, Smi::RawValue(false_value), PP); |
| 190 } | 190 } |
| 191 } | 191 } |
| 192 } | 192 } |
| (...skipping 648 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 841 } | 841 } |
| 842 | 842 |
| 843 | 843 |
| 844 void StringFromCharCodeInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 844 void StringFromCharCodeInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 845 const Register char_code = locs()->in(0).reg(); | 845 const Register char_code = locs()->in(0).reg(); |
| 846 const Register result = locs()->out(0).reg(); | 846 const Register result = locs()->out(0).reg(); |
| 847 __ LoadImmediate( | 847 __ LoadImmediate( |
| 848 result, reinterpret_cast<uword>(Symbols::PredefinedAddress()), PP); | 848 result, reinterpret_cast<uword>(Symbols::PredefinedAddress()), PP); |
| 849 __ AddImmediate( | 849 __ AddImmediate( |
| 850 result, result, Symbols::kNullCharCodeSymbolOffset * kWordSize, PP); | 850 result, result, Symbols::kNullCharCodeSymbolOffset * kWordSize, PP); |
| 851 __ Asr(TMP, char_code, kSmiTagShift); // Untag to use scaled adress mode. | 851 __ SmiUntag(TMP, char_code); // Untag to use scaled adress mode. |
| 852 __ ldr(result, Address(result, TMP, UXTX, Address::Scaled)); | 852 __ ldr(result, Address(result, TMP, UXTX, Address::Scaled)); |
| 853 } | 853 } |
| 854 | 854 |
| 855 | 855 |
| 856 LocationSummary* StringToCharCodeInstr::MakeLocationSummary(Isolate* isolate, | 856 LocationSummary* StringToCharCodeInstr::MakeLocationSummary(Isolate* isolate, |
| 857 bool opt) const { | 857 bool opt) const { |
| 858 const intptr_t kNumInputs = 1; | 858 const intptr_t kNumInputs = 1; |
| 859 return LocationSummary::Make(isolate, | 859 return LocationSummary::Make(isolate, |
| 860 kNumInputs, | 860 kNumInputs, |
| 861 Location::RequiresRegister(), | 861 Location::RequiresRegister(), |
| (...skipping 1678 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2540 : NULL; | 2540 : NULL; |
| 2541 if (locs.in(1).IsConstant()) { | 2541 if (locs.in(1).IsConstant()) { |
| 2542 const Object& constant = locs.in(1).constant(); | 2542 const Object& constant = locs.in(1).constant(); |
| 2543 ASSERT(constant.IsSmi()); | 2543 ASSERT(constant.IsSmi()); |
| 2544 // Immediate shift operation takes 6 bits for the count. | 2544 // Immediate shift operation takes 6 bits for the count. |
| 2545 const intptr_t kCountLimit = 0x3F; | 2545 const intptr_t kCountLimit = 0x3F; |
| 2546 const intptr_t value = Smi::Cast(constant).Value(); | 2546 const intptr_t value = Smi::Cast(constant).Value(); |
| 2547 ASSERT((0 < value) && (value < kCountLimit)); | 2547 ASSERT((0 < value) && (value < kCountLimit)); |
| 2548 if (shift_left->can_overflow()) { | 2548 if (shift_left->can_overflow()) { |
| 2549 // Check for overflow (preserve left). | 2549 // Check for overflow (preserve left). |
| 2550 __ Lsl(TMP, left, value); | 2550 __ LslImmediate(TMP, left, value); |
| 2551 __ cmp(left, Operand(TMP, ASR, value)); | 2551 __ cmp(left, Operand(TMP, ASR, value)); |
| 2552 __ b(deopt, NE); // Overflow. | 2552 __ b(deopt, NE); // Overflow. |
| 2553 } | 2553 } |
| 2554 // Shift for result now we know there is no overflow. | 2554 // Shift for result now we know there is no overflow. |
| 2555 __ Lsl(result, left, value); | 2555 __ LslImmediate(result, left, value); |
| 2556 if (FLAG_throw_on_javascript_int_overflow) { | 2556 if (FLAG_throw_on_javascript_int_overflow) { |
| 2557 EmitJavascriptOverflowCheck(compiler, shift_left->range(), deopt, result); | 2557 EmitJavascriptOverflowCheck(compiler, shift_left->range(), deopt, result); |
| 2558 } | 2558 } |
| 2559 return; | 2559 return; |
| 2560 } | 2560 } |
| 2561 | 2561 |
| 2562 // Right (locs.in(1)) is not constant. | 2562 // Right (locs.in(1)) is not constant. |
| 2563 const Register right = locs.in(1).reg(); | 2563 const Register right = locs.in(1).reg(); |
| 2564 Range* right_range = shift_left->right()->definition()->range(); | 2564 Range* right_range = shift_left->right()->definition()->range(); |
| 2565 if (shift_left->left()->BindsToConstant() && shift_left->can_overflow()) { | 2565 if (shift_left->left()->BindsToConstant() && shift_left->can_overflow()) { |
| (...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2726 __ b(deopt, NE); | 2726 __ b(deopt, NE); |
| 2727 } | 2727 } |
| 2728 break; | 2728 break; |
| 2729 } | 2729 } |
| 2730 case Token::kTRUNCDIV: { | 2730 case Token::kTRUNCDIV: { |
| 2731 const intptr_t value = Smi::Cast(constant).Value(); | 2731 const intptr_t value = Smi::Cast(constant).Value(); |
| 2732 ASSERT(Utils::IsPowerOfTwo(Utils::Abs(value))); | 2732 ASSERT(Utils::IsPowerOfTwo(Utils::Abs(value))); |
| 2733 const intptr_t shift_count = | 2733 const intptr_t shift_count = |
| 2734 Utils::ShiftForPowerOfTwo(Utils::Abs(value)) + kSmiTagSize; | 2734 Utils::ShiftForPowerOfTwo(Utils::Abs(value)) + kSmiTagSize; |
| 2735 ASSERT(kSmiTagSize == 1); | 2735 ASSERT(kSmiTagSize == 1); |
| 2736 __ Asr(TMP, left, 63); | 2736 __ AsrImmediate(TMP, left, 63); |
| 2737 ASSERT(shift_count > 1); // 1, -1 case handled above. | 2737 ASSERT(shift_count > 1); // 1, -1 case handled above. |
| 2738 const Register temp = TMP2; | 2738 const Register temp = TMP2; |
| 2739 __ add(temp, left, Operand(TMP, LSR, 64 - shift_count)); | 2739 __ add(temp, left, Operand(TMP, LSR, 64 - shift_count)); |
| 2740 ASSERT(shift_count > 0); | 2740 ASSERT(shift_count > 0); |
| 2741 __ Asr(result, temp, shift_count); | 2741 __ AsrImmediate(result, temp, shift_count); |
| 2742 if (value < 0) { | 2742 if (value < 0) { |
| 2743 __ sub(result, ZR, Operand(result)); | 2743 __ sub(result, ZR, Operand(result)); |
| 2744 } | 2744 } |
| 2745 __ SmiTag(result); | 2745 __ SmiTag(result); |
| 2746 break; | 2746 break; |
| 2747 } | 2747 } |
| 2748 case Token::kBIT_AND: | 2748 case Token::kBIT_AND: |
| 2749 // No overflow check. | 2749 // No overflow check. |
| 2750 __ AndImmediate(result, left, imm, PP); | 2750 __ AndImmediate(result, left, imm, PP); |
| 2751 break; | 2751 break; |
| 2752 case Token::kBIT_OR: | 2752 case Token::kBIT_OR: |
| 2753 // No overflow check. | 2753 // No overflow check. |
| 2754 __ OrImmediate(result, left, imm, PP); | 2754 __ OrImmediate(result, left, imm, PP); |
| 2755 break; | 2755 break; |
| 2756 case Token::kBIT_XOR: | 2756 case Token::kBIT_XOR: |
| 2757 // No overflow check. | 2757 // No overflow check. |
| 2758 __ XorImmediate(result, left, imm, PP); | 2758 __ XorImmediate(result, left, imm, PP); |
| 2759 break; | 2759 break; |
| 2760 case Token::kSHR: { | 2760 case Token::kSHR: { |
| 2761 // Asr operation masks the count to 6 bits. | 2761 // Asr operation masks the count to 6 bits. |
| 2762 const intptr_t kCountLimit = 0x3F; | 2762 const intptr_t kCountLimit = 0x3F; |
| 2763 intptr_t value = Smi::Cast(constant).Value(); | 2763 intptr_t value = Smi::Cast(constant).Value(); |
| 2764 __ Asr(result, left, Utils::Minimum(value + kSmiTagSize, kCountLimit)); | 2764 __ AsrImmediate( |
| 2765 result, left, Utils::Minimum(value + kSmiTagSize, kCountLimit)); |
| 2765 __ SmiTag(result); | 2766 __ SmiTag(result); |
| 2766 break; | 2767 break; |
| 2767 } | 2768 } |
| 2768 default: | 2769 default: |
| 2769 UNREACHABLE(); | 2770 UNREACHABLE(); |
| 2770 break; | 2771 break; |
| 2771 } | 2772 } |
| 2772 if (FLAG_throw_on_javascript_int_overflow) { | 2773 if (FLAG_throw_on_javascript_int_overflow) { |
| 2773 EmitJavascriptOverflowCheck(compiler, range(), deopt, result); | 2774 EmitJavascriptOverflowCheck(compiler, range(), deopt, result); |
| 2774 } | 2775 } |
| (...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2992 | 2993 |
| 2993 void UnboxDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2994 void UnboxDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2994 CompileType* value_type = value()->Type(); | 2995 CompileType* value_type = value()->Type(); |
| 2995 const intptr_t value_cid = value_type->ToCid(); | 2996 const intptr_t value_cid = value_type->ToCid(); |
| 2996 const Register value = locs()->in(0).reg(); | 2997 const Register value = locs()->in(0).reg(); |
| 2997 const VRegister result = locs()->out(0).fpu_reg(); | 2998 const VRegister result = locs()->out(0).fpu_reg(); |
| 2998 | 2999 |
| 2999 if (value_cid == kDoubleCid) { | 3000 if (value_cid == kDoubleCid) { |
| 3000 __ LoadDFieldFromOffset(result, value, Double::value_offset(), PP); | 3001 __ LoadDFieldFromOffset(result, value, Double::value_offset(), PP); |
| 3001 } else if (value_cid == kSmiCid) { | 3002 } else if (value_cid == kSmiCid) { |
| 3002 __ Asr(TMP, value, kSmiTagSize); // Untag input before conversion. | 3003 __ SmiUntag(TMP, value); // Untag input before conversion. |
| 3003 __ scvtfd(result, TMP); | 3004 __ scvtfd(result, TMP); |
| 3004 } else { | 3005 } else { |
| 3005 Label* deopt = compiler->AddDeoptStub(deopt_id_, | 3006 Label* deopt = compiler->AddDeoptStub(deopt_id_, |
| 3006 ICData::kDeoptBinaryDoubleOp); | 3007 ICData::kDeoptBinaryDoubleOp); |
| 3007 if (value_type->is_nullable() && | 3008 if (value_type->is_nullable() && |
| 3008 (value_type->ToNullableCid() == kDoubleCid)) { | 3009 (value_type->ToNullableCid() == kDoubleCid)) { |
| 3009 __ CompareObject(value, Object::null_object(), PP); | 3010 __ CompareObject(value, Object::null_object(), PP); |
| 3010 __ b(deopt, EQ); | 3011 __ b(deopt, EQ); |
| 3011 // It must be double now. | 3012 // It must be double now. |
| 3012 __ LoadDFieldFromOffset(result, value, Double::value_offset(), PP); | 3013 __ LoadDFieldFromOffset(result, value, Double::value_offset(), PP); |
| 3013 } else { | 3014 } else { |
| 3014 Label is_smi, done; | 3015 Label is_smi, done; |
| 3015 __ tsti(value, kSmiTagMask); | 3016 __ tsti(value, kSmiTagMask); |
| 3016 __ b(&is_smi, EQ); | 3017 __ b(&is_smi, EQ); |
| 3017 __ CompareClassId(value, kDoubleCid, PP); | 3018 __ CompareClassId(value, kDoubleCid, PP); |
| 3018 __ b(deopt, NE); | 3019 __ b(deopt, NE); |
| 3019 __ LoadDFieldFromOffset(result, value, Double::value_offset(), PP); | 3020 __ LoadDFieldFromOffset(result, value, Double::value_offset(), PP); |
| 3020 __ b(&done); | 3021 __ b(&done); |
| 3021 __ Bind(&is_smi); | 3022 __ Bind(&is_smi); |
| 3022 __ Asr(TMP, value, kSmiTagSize); // Copy and untag. | 3023 __ SmiUntag(TMP, value); // Copy and untag. |
| 3023 __ scvtfd(result, TMP); | 3024 __ scvtfd(result, TMP); |
| 3024 __ Bind(&done); | 3025 __ Bind(&done); |
| 3025 } | 3026 } |
| 3026 } | 3027 } |
| 3027 } | 3028 } |
| 3028 | 3029 |
| 3029 | 3030 |
| 3030 LocationSummary* BoxFloat32x4Instr::MakeLocationSummary(Isolate* isolate, | 3031 LocationSummary* BoxFloat32x4Instr::MakeLocationSummary(Isolate* isolate, |
| 3031 bool opt) const { | 3032 bool opt) const { |
| 3032 const intptr_t kNumInputs = 1; | 3033 const intptr_t kNumInputs = 1; |
| (...skipping 334 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3367 } | 3368 } |
| 3368 | 3369 |
| 3369 | 3370 |
| 3370 void Simd32x4GetSignMaskInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3371 void Simd32x4GetSignMaskInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3371 const VRegister value = locs()->in(0).fpu_reg(); | 3372 const VRegister value = locs()->in(0).fpu_reg(); |
| 3372 const Register out = locs()->out(0).reg(); | 3373 const Register out = locs()->out(0).reg(); |
| 3373 const Register temp = locs()->temp(0).reg(); | 3374 const Register temp = locs()->temp(0).reg(); |
| 3374 | 3375 |
| 3375 // X lane. | 3376 // X lane. |
| 3376 __ vmovrs(out, value, 0); | 3377 __ vmovrs(out, value, 0); |
| 3377 __ Lsr(out, out, 31); | 3378 __ LsrImmediate(out, out, 31); |
| 3378 // Y lane. | 3379 // Y lane. |
| 3379 __ vmovrs(temp, value, 1); | 3380 __ vmovrs(temp, value, 1); |
| 3380 __ Lsr(temp, temp, 31); | 3381 __ LsrImmediate(temp, temp, 31); |
| 3381 __ orr(out, out, Operand(temp, LSL, 1)); | 3382 __ orr(out, out, Operand(temp, LSL, 1)); |
| 3382 // Z lane. | 3383 // Z lane. |
| 3383 __ vmovrs(temp, value, 2); | 3384 __ vmovrs(temp, value, 2); |
| 3384 __ Lsr(temp, temp, 31); | 3385 __ LsrImmediate(temp, temp, 31); |
| 3385 __ orr(out, out, Operand(temp, LSL, 2)); | 3386 __ orr(out, out, Operand(temp, LSL, 2)); |
| 3386 // W lane. | 3387 // W lane. |
| 3387 __ vmovrs(temp, value, 3); | 3388 __ vmovrs(temp, value, 3); |
| 3388 __ Lsr(temp, temp, 31); | 3389 __ LsrImmediate(temp, temp, 31); |
| 3389 __ orr(out, out, Operand(temp, LSL, 3)); | 3390 __ orr(out, out, Operand(temp, LSL, 3)); |
| 3390 // Tag. | 3391 // Tag. |
| 3391 __ SmiTag(out); | 3392 __ SmiTag(out); |
| 3392 } | 3393 } |
| 3393 | 3394 |
| 3394 | 3395 |
| 3395 LocationSummary* Float32x4ConstructorInstr::MakeLocationSummary( | 3396 LocationSummary* Float32x4ConstructorInstr::MakeLocationSummary( |
| 3396 Isolate* isolate, bool opt) const { | 3397 Isolate* isolate, bool opt) const { |
| 3397 const intptr_t kNumInputs = 4; | 3398 const intptr_t kNumInputs = 4; |
| 3398 const intptr_t kNumTemps = 0; | 3399 const intptr_t kNumTemps = 0; |
| (...skipping 479 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3878 | 3879 |
| 3879 | 3880 |
| 3880 void Float64x2ZeroArgInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3881 void Float64x2ZeroArgInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3881 const VRegister value = locs()->in(0).fpu_reg(); | 3882 const VRegister value = locs()->in(0).fpu_reg(); |
| 3882 | 3883 |
| 3883 if ((op_kind() == MethodRecognizer::kFloat64x2GetSignMask)) { | 3884 if ((op_kind() == MethodRecognizer::kFloat64x2GetSignMask)) { |
| 3884 const Register out = locs()->out(0).reg(); | 3885 const Register out = locs()->out(0).reg(); |
| 3885 | 3886 |
| 3886 // Bits of X lane. | 3887 // Bits of X lane. |
| 3887 __ vmovrd(out, value, 0); | 3888 __ vmovrd(out, value, 0); |
| 3888 __ Lsr(out, out, 63); | 3889 __ LsrImmediate(out, out, 63); |
| 3889 // Bits of Y lane. | 3890 // Bits of Y lane. |
| 3890 __ vmovrd(TMP, value, 1); | 3891 __ vmovrd(TMP, value, 1); |
| 3891 __ Lsr(TMP, TMP, 63); | 3892 __ LsrImmediate(TMP, TMP, 63); |
| 3892 __ orr(out, out, Operand(TMP, LSL, 1)); | 3893 __ orr(out, out, Operand(TMP, LSL, 1)); |
| 3893 // Tag. | 3894 // Tag. |
| 3894 __ SmiTag(out); | 3895 __ SmiTag(out); |
| 3895 return; | 3896 return; |
| 3896 } | 3897 } |
| 3897 ASSERT(representation() == kUnboxedFloat64x2); | 3898 ASSERT(representation() == kUnboxedFloat64x2); |
| 3898 const VRegister result = locs()->out(0).fpu_reg(); | 3899 const VRegister result = locs()->out(0).fpu_reg(); |
| 3899 | 3900 |
| 3900 switch (op_kind()) { | 3901 switch (op_kind()) { |
| 3901 case MethodRecognizer::kFloat64x2Negate: | 3902 case MethodRecognizer::kFloat64x2Negate: |
| (...skipping 1018 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4920 __ AddImmediate(temp, temp, -cids_[0], PP); | 4921 __ AddImmediate(temp, temp, -cids_[0], PP); |
| 4921 __ CompareImmediate(temp, cids_[cids_.length() - 1] - cids_[0], PP); | 4922 __ CompareImmediate(temp, cids_[cids_.length() - 1] - cids_[0], PP); |
| 4922 __ b(deopt, HI); | 4923 __ b(deopt, HI); |
| 4923 | 4924 |
| 4924 intptr_t mask = ComputeCidMask(); | 4925 intptr_t mask = ComputeCidMask(); |
| 4925 if (!IsDenseMask(mask)) { | 4926 if (!IsDenseMask(mask)) { |
| 4926 // Only need mask if there are missing numbers in the range. | 4927 // Only need mask if there are missing numbers in the range. |
| 4927 ASSERT(cids_.length() > 2); | 4928 ASSERT(cids_.length() > 2); |
| 4928 Register mask_reg = locs()->temp(1).reg(); | 4929 Register mask_reg = locs()->temp(1).reg(); |
| 4929 __ LoadImmediate(mask_reg, 1, PP); | 4930 __ LoadImmediate(mask_reg, 1, PP); |
| 4930 __ Lsl(mask_reg, mask_reg, temp); | 4931 __ lslv(mask_reg, mask_reg, temp); |
| 4931 __ TestImmediate(mask_reg, mask, PP); | 4932 __ TestImmediate(mask_reg, mask, PP); |
| 4932 __ b(deopt, EQ); | 4933 __ b(deopt, EQ); |
| 4933 } | 4934 } |
| 4934 | 4935 |
| 4935 } else { | 4936 } else { |
| 4936 const intptr_t num_checks = unary_checks().NumberOfChecks(); | 4937 const intptr_t num_checks = unary_checks().NumberOfChecks(); |
| 4937 for (intptr_t i = cix; i < num_checks; i++) { | 4938 for (intptr_t i = cix; i < num_checks; i++) { |
| 4938 ASSERT(unary_checks().GetReceiverClassIdAt(i) != kSmiCid); | 4939 ASSERT(unary_checks().GetReceiverClassIdAt(i) != kSmiCid); |
| 4939 __ CompareImmediate(temp, unary_checks().GetReceiverClassIdAt(i), PP); | 4940 __ CompareImmediate(temp, unary_checks().GetReceiverClassIdAt(i), PP); |
| 4940 if (i == (num_checks - 1)) { | 4941 if (i == (num_checks - 1)) { |
| (...skipping 248 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5189 } | 5190 } |
| 5190 | 5191 |
| 5191 | 5192 |
| 5192 void BoxIntNInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5193 void BoxIntNInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5193 Register value = locs()->in(0).reg(); | 5194 Register value = locs()->in(0).reg(); |
| 5194 Register out = locs()->out(0).reg(); | 5195 Register out = locs()->out(0).reg(); |
| 5195 ASSERT(value != out); | 5196 ASSERT(value != out); |
| 5196 | 5197 |
| 5197 ASSERT(kSmiTagSize == 1); | 5198 ASSERT(kSmiTagSize == 1); |
| 5198 // TODO(vegorov) implement and use UBFM/SBFM for this. | 5199 // TODO(vegorov) implement and use UBFM/SBFM for this. |
| 5199 __ Lsl(out, value, 32); | 5200 __ LslImmediate(out, value, 32); |
| 5200 if (from_representation() == kUnboxedInt32) { | 5201 if (from_representation() == kUnboxedInt32) { |
| 5201 __ Asr(out, out, 32 - kSmiTagSize); | 5202 __ AsrImmediate(out, out, 32 - kSmiTagSize); |
| 5202 } else { | 5203 } else { |
| 5203 ASSERT(from_representation() == kUnboxedUint32); | 5204 ASSERT(from_representation() == kUnboxedUint32); |
| 5204 __ Lsr(out, out, 32 - kSmiTagSize); | 5205 __ LsrImmediate(out, out, 32 - kSmiTagSize); |
| 5205 } | 5206 } |
| 5206 } | 5207 } |
| 5207 | 5208 |
| 5208 | 5209 |
| 5209 LocationSummary* UnboxedIntConverterInstr::MakeLocationSummary(Isolate* isolate, | 5210 LocationSummary* UnboxedIntConverterInstr::MakeLocationSummary(Isolate* isolate, |
| 5210 bool opt) const { | 5211 bool opt) const { |
| 5211 const intptr_t kNumInputs = 1; | 5212 const intptr_t kNumInputs = 1; |
| 5212 const intptr_t kNumTemps = 0; | 5213 const intptr_t kNumTemps = 0; |
| 5213 LocationSummary* summary = new(isolate) LocationSummary( | 5214 LocationSummary* summary = new(isolate) LocationSummary( |
| 5214 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5215 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 5228 | 5229 |
| 5229 void UnboxedIntConverterInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5230 void UnboxedIntConverterInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5230 if (from() == kUnboxedInt32 && to() == kUnboxedUint32) { | 5231 if (from() == kUnboxedInt32 && to() == kUnboxedUint32) { |
| 5231 const Register value = locs()->in(0).reg(); | 5232 const Register value = locs()->in(0).reg(); |
| 5232 const Register out = locs()->out(0).reg(); | 5233 const Register out = locs()->out(0).reg(); |
| 5233 // Representations are bitwise equivalent but we want to normalize | 5234 // Representations are bitwise equivalent but we want to normalize |
| 5234 // upperbits for safety reasons. | 5235 // upperbits for safety reasons. |
| 5235 // TODO(vegorov) if we ensure that we never use kDoubleWord size | 5236 // TODO(vegorov) if we ensure that we never use kDoubleWord size |
| 5236 // with it then we could avoid this. | 5237 // with it then we could avoid this. |
| 5237 // TODO(vegorov) implement and use UBFM for zero extension. | 5238 // TODO(vegorov) implement and use UBFM for zero extension. |
| 5238 __ Lsl(out, value, 32); | 5239 __ LslImmediate(out, value, 32); |
| 5239 __ Lsr(out, out, 32); | 5240 __ LsrImmediate(out, out, 32); |
| 5240 } else if (from() == kUnboxedUint32 && to() == kUnboxedInt32) { | 5241 } else if (from() == kUnboxedUint32 && to() == kUnboxedInt32) { |
| 5241 // Representations are bitwise equivalent. | 5242 // Representations are bitwise equivalent. |
| 5242 // TODO(vegorov) if we ensure that we never use kDoubleWord size | 5243 // TODO(vegorov) if we ensure that we never use kDoubleWord size |
| 5243 // with it then we could avoid this. | 5244 // with it then we could avoid this. |
| 5244 // TODO(vegorov) implement and use SBFM for sign extension. | 5245 // TODO(vegorov) implement and use SBFM for sign extension. |
| 5245 const Register value = locs()->in(0).reg(); | 5246 const Register value = locs()->in(0).reg(); |
| 5246 const Register out = locs()->out(0).reg(); | 5247 const Register out = locs()->out(0).reg(); |
| 5247 __ Lsl(out, value, 32); | 5248 __ LslImmediate(out, value, 32); |
| 5248 __ Asr(out, out, 32); | 5249 __ AsrImmediate(out, out, 32); |
| 5249 if (CanDeoptimize()) { | 5250 if (CanDeoptimize()) { |
| 5250 Label* deopt = | 5251 Label* deopt = |
| 5251 compiler->AddDeoptStub(deopt_id(), ICData::kDeoptUnboxInteger); | 5252 compiler->AddDeoptStub(deopt_id(), ICData::kDeoptUnboxInteger); |
| 5252 __ cmp(out, Operand(value, UXTW, 0)); | 5253 __ cmp(out, Operand(value, UXTW, 0)); |
| 5253 __ b(deopt, NE); | 5254 __ b(deopt, NE); |
| 5254 } | 5255 } |
| 5255 } else if (from() == kUnboxedMint) { | 5256 } else if (from() == kUnboxedMint) { |
| 5256 UNREACHABLE(); | 5257 UNREACHABLE(); |
| 5257 } else if (to() == kUnboxedMint) { | 5258 } else if (to() == kUnboxedMint) { |
| 5258 ASSERT((from() == kUnboxedUint32) || (from() == kUnboxedInt32)); | 5259 ASSERT((from() == kUnboxedUint32) || (from() == kUnboxedInt32)); |
| (...skipping 218 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5477 compiler->GenerateCall(token_pos(), &label, stub_kind_, locs()); | 5478 compiler->GenerateCall(token_pos(), &label, stub_kind_, locs()); |
| 5478 #if defined(DEBUG) | 5479 #if defined(DEBUG) |
| 5479 __ LoadImmediate(R4, kInvalidObjectPointer, kNoPP); | 5480 __ LoadImmediate(R4, kInvalidObjectPointer, kNoPP); |
| 5480 __ LoadImmediate(R5, kInvalidObjectPointer, kNoPP); | 5481 __ LoadImmediate(R5, kInvalidObjectPointer, kNoPP); |
| 5481 #endif | 5482 #endif |
| 5482 } | 5483 } |
| 5483 | 5484 |
| 5484 } // namespace dart | 5485 } // namespace dart |
| 5485 | 5486 |
| 5486 #endif // defined TARGET_ARCH_ARM64 | 5487 #endif // defined TARGET_ARCH_ARM64 |
| OLD | NEW |