| 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 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 154 if (true_value == 0) { | 154 if (true_value == 0) { |
| 155 // Swap values so that false_value is zero. | 155 // Swap values so that false_value is zero. |
| 156 intptr_t temp = true_value; | 156 intptr_t temp = true_value; |
| 157 true_value = false_value; | 157 true_value = false_value; |
| 158 false_value = temp; | 158 false_value = temp; |
| 159 } else { | 159 } else { |
| 160 true_condition = NegateCondition(true_condition); | 160 true_condition = NegateCondition(true_condition); |
| 161 } | 161 } |
| 162 } | 162 } |
| 163 | 163 |
| 164 // TODO(zra): replace with cinc(result, ZR, ZR, true_condition) | 164 __ cset(result, true_condition); |
| 165 __ LoadImmediate(TMP, 1, kNoPP); | |
| 166 __ csel(result, TMP, ZR, true_condition); | |
| 167 | 165 |
| 168 if (is_power_of_two_kind) { | 166 if (is_power_of_two_kind) { |
| 169 const intptr_t shift = | 167 const intptr_t shift = |
| 170 Utils::ShiftForPowerOfTwo(Utils::Maximum(true_value, false_value)); | 168 Utils::ShiftForPowerOfTwo(Utils::Maximum(true_value, false_value)); |
| 171 __ Lsl(result, result, shift + kSmiTagSize); | 169 __ Lsl(result, result, shift + kSmiTagSize); |
| 172 } else { | 170 } else { |
| 173 __ sub(result, result, Operand(1)); | 171 __ sub(result, result, Operand(1)); |
| 174 const int32_t val = | 172 const int32_t val = |
| 175 Smi::RawValue(true_value) - Smi::RawValue(false_value); | 173 Smi::RawValue(true_value) - Smi::RawValue(false_value); |
| 176 __ AndImmediate(result, result, val, PP); | 174 __ AndImmediate(result, result, val, PP); |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 277 | 275 |
| 278 LocationSummary* UnboxedConstantInstr::MakeLocationSummary(bool opt) const { | 276 LocationSummary* UnboxedConstantInstr::MakeLocationSummary(bool opt) const { |
| 279 const intptr_t kNumInputs = 0; | 277 const intptr_t kNumInputs = 0; |
| 280 return LocationSummary::Make(kNumInputs, | 278 return LocationSummary::Make(kNumInputs, |
| 281 Location::RequiresFpuRegister(), | 279 Location::RequiresFpuRegister(), |
| 282 LocationSummary::kNoCall); | 280 LocationSummary::kNoCall); |
| 283 } | 281 } |
| 284 | 282 |
| 285 | 283 |
| 286 void UnboxedConstantInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 284 void UnboxedConstantInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 287 UNIMPLEMENTED(); | 285 if (!locs()->out(0).IsInvalid()) { |
| 286 const VRegister dst = locs()->out(0).fpu_reg(); |
| 287 __ LoadDImmediate(dst, Double::Cast(value()).value(), PP); |
| 288 } |
| 288 } | 289 } |
| 289 | 290 |
| 290 | 291 |
| 291 LocationSummary* AssertAssignableInstr::MakeLocationSummary(bool opt) const { | 292 LocationSummary* AssertAssignableInstr::MakeLocationSummary(bool opt) const { |
| 292 const intptr_t kNumInputs = 3; | 293 const intptr_t kNumInputs = 3; |
| 293 const intptr_t kNumTemps = 0; | 294 const intptr_t kNumTemps = 0; |
| 294 LocationSummary* summary = | 295 LocationSummary* summary = |
| 295 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); | 296 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); |
| 296 summary->set_in(0, Location::RegisterLocation(R0)); // Value. | 297 summary->set_in(0, Location::RegisterLocation(R0)); // Value. |
| 297 summary->set_in(1, Location::RegisterLocation(R2)); // Instantiator. | 298 summary->set_in(1, Location::RegisterLocation(R2)); // Instantiator. |
| (...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 444 ? Location::RequiresRegister() | 445 ? Location::RequiresRegister() |
| 445 : Location::RegisterOrConstant(right())); | 446 : Location::RegisterOrConstant(right())); |
| 446 locs->set_out(0, Location::RequiresRegister()); | 447 locs->set_out(0, Location::RequiresRegister()); |
| 447 return locs; | 448 return locs; |
| 448 } | 449 } |
| 449 UNREACHABLE(); | 450 UNREACHABLE(); |
| 450 return NULL; | 451 return NULL; |
| 451 } | 452 } |
| 452 | 453 |
| 453 | 454 |
| 455 static Condition TokenKindToDoubleCondition(Token::Kind kind) { |
| 456 switch (kind) { |
| 457 case Token::kEQ: return EQ; |
| 458 case Token::kNE: return NE; |
| 459 case Token::kLT: return LT; |
| 460 case Token::kGT: return GT; |
| 461 case Token::kLTE: return LE; |
| 462 case Token::kGTE: return GE; |
| 463 default: |
| 464 UNREACHABLE(); |
| 465 return VS; |
| 466 } |
| 467 } |
| 468 |
| 469 |
| 470 static Condition EmitDoubleComparisonOp(FlowGraphCompiler* compiler, |
| 471 LocationSummary* locs, |
| 472 Token::Kind kind) { |
| 473 VRegister left = locs->in(0).fpu_reg(); |
| 474 VRegister right = locs->in(1).fpu_reg(); |
| 475 __ fcmpd(left, right); |
| 476 Condition true_condition = TokenKindToDoubleCondition(kind); |
| 477 return true_condition; |
| 478 } |
| 479 |
| 480 |
| 454 Condition EqualityCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler, | 481 Condition EqualityCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
| 455 BranchLabels labels) { | 482 BranchLabels labels) { |
| 456 if (operation_cid() == kSmiCid) { | 483 if (operation_cid() == kSmiCid) { |
| 457 return EmitSmiComparisonOp(compiler, locs(), kind()); | 484 return EmitSmiComparisonOp(compiler, locs(), kind()); |
| 458 } else { | 485 } else { |
| 459 UNIMPLEMENTED(); | 486 ASSERT(operation_cid() == kDoubleCid); |
| 460 return VS; | 487 return EmitDoubleComparisonOp(compiler, locs(), kind()); |
| 461 } | 488 } |
| 462 } | 489 } |
| 463 | 490 |
| 464 | 491 |
| 465 void EqualityCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 492 void EqualityCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 466 ASSERT((kind() == Token::kEQ) || (kind() == Token::kNE)); | 493 ASSERT((kind() == Token::kEQ) || (kind() == Token::kNE)); |
| 467 | 494 |
| 468 Label is_true, is_false; | 495 Label is_true, is_false; |
| 469 BranchLabels labels = { &is_true, &is_false, &is_false }; | 496 BranchLabels labels = { &is_true, &is_false, &is_false }; |
| 470 Condition true_condition = EmitComparisonCode(compiler, labels); | 497 Condition true_condition = EmitComparisonCode(compiler, labels); |
| (...skipping 552 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1023 case kTwoByteStringCid: | 1050 case kTwoByteStringCid: |
| 1024 __ ldr(result, element_address, kUnsignedHalfword); | 1051 __ ldr(result, element_address, kUnsignedHalfword); |
| 1025 __ SmiTag(result); | 1052 __ SmiTag(result); |
| 1026 break; | 1053 break; |
| 1027 case kTypedDataInt32ArrayCid: | 1054 case kTypedDataInt32ArrayCid: |
| 1028 __ ldr(result, element_address, kWord); | 1055 __ ldr(result, element_address, kWord); |
| 1029 __ SmiTag(result); | 1056 __ SmiTag(result); |
| 1030 break; | 1057 break; |
| 1031 case kTypedDataUint32ArrayCid: | 1058 case kTypedDataUint32ArrayCid: |
| 1032 __ ldr(result, element_address, kUnsignedWord); | 1059 __ ldr(result, element_address, kUnsignedWord); |
| 1060 __ SmiTag(result); |
| 1033 break; | 1061 break; |
| 1034 default: | 1062 default: |
| 1035 ASSERT((class_id() == kArrayCid) || (class_id() == kImmutableArrayCid)); | 1063 ASSERT((class_id() == kArrayCid) || (class_id() == kImmutableArrayCid)); |
| 1036 __ ldr(result, element_address); | 1064 __ ldr(result, element_address); |
| 1037 break; | 1065 break; |
| 1038 } | 1066 } |
| 1039 } | 1067 } |
| 1040 | 1068 |
| 1041 | 1069 |
| 1042 Representation StoreIndexedInstr::RequiredInputRepresentation( | 1070 Representation StoreIndexedInstr::RequiredInputRepresentation( |
| (...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1250 } | 1278 } |
| 1251 break; | 1279 break; |
| 1252 } | 1280 } |
| 1253 case kTypedDataFloat32ArrayCid: | 1281 case kTypedDataFloat32ArrayCid: |
| 1254 // TODO(zra): Implement when we add float store. | 1282 // TODO(zra): Implement when we add float store. |
| 1255 UNIMPLEMENTED(); | 1283 UNIMPLEMENTED(); |
| 1256 break; | 1284 break; |
| 1257 case kTypedDataFloat64ArrayCid: { | 1285 case kTypedDataFloat64ArrayCid: { |
| 1258 VRegister in2 = locs()->in(2).fpu_reg(); | 1286 VRegister in2 = locs()->in(2).fpu_reg(); |
| 1259 __ add(index.reg(), index.reg(), Operand(array)); | 1287 __ add(index.reg(), index.reg(), Operand(array)); |
| 1260 __ StoreDFieldToOffset(in2, index.reg(), 0); | 1288 __ StoreDToOffset(in2, index.reg(), 0); |
| 1261 break; | 1289 break; |
| 1262 } | 1290 } |
| 1263 case kTypedDataFloat64x2ArrayCid: | 1291 case kTypedDataFloat64x2ArrayCid: |
| 1264 case kTypedDataInt32x4ArrayCid: | 1292 case kTypedDataInt32x4ArrayCid: |
| 1265 case kTypedDataFloat32x4ArrayCid: { | 1293 case kTypedDataFloat32x4ArrayCid: { |
| 1266 // TODO(zra): Implement when we add simd loads and stores. | 1294 // TODO(zra): Implement when we add simd loads and stores. |
| 1267 UNIMPLEMENTED(); | 1295 UNIMPLEMENTED(); |
| 1268 break; | 1296 break; |
| 1269 } | 1297 } |
| 1270 default: | 1298 default: |
| (...skipping 1512 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2783 break; | 2811 break; |
| 2784 } | 2812 } |
| 2785 default: | 2813 default: |
| 2786 UNREACHABLE(); | 2814 UNREACHABLE(); |
| 2787 break; | 2815 break; |
| 2788 } | 2816 } |
| 2789 } | 2817 } |
| 2790 | 2818 |
| 2791 | 2819 |
| 2792 LocationSummary* CheckEitherNonSmiInstr::MakeLocationSummary(bool opt) const { | 2820 LocationSummary* CheckEitherNonSmiInstr::MakeLocationSummary(bool opt) const { |
| 2793 UNIMPLEMENTED(); | 2821 intptr_t left_cid = left()->Type()->ToCid(); |
| 2794 return NULL; | 2822 intptr_t right_cid = right()->Type()->ToCid(); |
| 2823 ASSERT((left_cid != kDoubleCid) && (right_cid != kDoubleCid)); |
| 2824 const intptr_t kNumInputs = 2; |
| 2825 const intptr_t kNumTemps = 0; |
| 2826 LocationSummary* summary = |
| 2827 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 2828 summary->set_in(0, Location::RequiresRegister()); |
| 2829 summary->set_in(1, Location::RequiresRegister()); |
| 2830 return summary; |
| 2795 } | 2831 } |
| 2796 | 2832 |
| 2797 | 2833 |
| 2798 void CheckEitherNonSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2834 void CheckEitherNonSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2799 UNIMPLEMENTED(); | 2835 Label* deopt = compiler->AddDeoptStub(deopt_id(), |
| 2836 ICData::kDeoptBinaryDoubleOp); |
| 2837 intptr_t left_cid = left()->Type()->ToCid(); |
| 2838 intptr_t right_cid = right()->Type()->ToCid(); |
| 2839 Register left = locs()->in(0).reg(); |
| 2840 Register right = locs()->in(1).reg(); |
| 2841 if (left_cid == kSmiCid) { |
| 2842 __ tsti(right, kSmiTagMask); |
| 2843 } else if (right_cid == kSmiCid) { |
| 2844 __ tsti(left, kSmiTagMask); |
| 2845 } else { |
| 2846 __ orr(TMP, left, Operand(right)); |
| 2847 __ tsti(TMP, kSmiTagMask); |
| 2848 } |
| 2849 __ b(deopt, EQ); |
| 2800 } | 2850 } |
| 2801 | 2851 |
| 2802 | 2852 |
| 2803 LocationSummary* BoxDoubleInstr::MakeLocationSummary(bool opt) const { | 2853 LocationSummary* BoxDoubleInstr::MakeLocationSummary(bool opt) const { |
| 2804 const intptr_t kNumInputs = 1; | 2854 const intptr_t kNumInputs = 1; |
| 2805 const intptr_t kNumTemps = 1; | 2855 const intptr_t kNumTemps = 1; |
| 2806 LocationSummary* summary = | 2856 LocationSummary* summary = |
| 2807 new LocationSummary(kNumInputs, | 2857 new LocationSummary(kNumInputs, |
| 2808 kNumTemps, | 2858 kNumTemps, |
| 2809 LocationSummary::kCallOnSlowPath); | 2859 LocationSummary::kCallOnSlowPath); |
| (...skipping 15 matching lines...) Expand all Loading... |
| 2825 slow_path->entry_label(), | 2875 slow_path->entry_label(), |
| 2826 out_reg, | 2876 out_reg, |
| 2827 locs()->temp(0).reg(), | 2877 locs()->temp(0).reg(), |
| 2828 PP); | 2878 PP); |
| 2829 __ Bind(slow_path->exit_label()); | 2879 __ Bind(slow_path->exit_label()); |
| 2830 __ StoreDFieldToOffset(value, out_reg, Double::value_offset()); | 2880 __ StoreDFieldToOffset(value, out_reg, Double::value_offset()); |
| 2831 } | 2881 } |
| 2832 | 2882 |
| 2833 | 2883 |
| 2834 LocationSummary* UnboxDoubleInstr::MakeLocationSummary(bool opt) const { | 2884 LocationSummary* UnboxDoubleInstr::MakeLocationSummary(bool opt) const { |
| 2835 UNIMPLEMENTED(); | 2885 const intptr_t kNumInputs = 1; |
| 2836 return NULL; | 2886 const intptr_t kNumTemps = 0; |
| 2887 LocationSummary* summary = |
| 2888 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 2889 summary->set_in(0, Location::RequiresRegister()); |
| 2890 summary->set_out(0, Location::RequiresFpuRegister()); |
| 2891 return summary; |
| 2837 } | 2892 } |
| 2838 | 2893 |
| 2839 | 2894 |
| 2840 void UnboxDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2895 void UnboxDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2841 UNIMPLEMENTED(); | 2896 CompileType* value_type = value()->Type(); |
| 2897 const intptr_t value_cid = value_type->ToCid(); |
| 2898 const Register value = locs()->in(0).reg(); |
| 2899 const VRegister result = locs()->out(0).fpu_reg(); |
| 2900 |
| 2901 if (value_cid == kDoubleCid) { |
| 2902 __ LoadDFieldFromOffset(result, value, Double::value_offset()); |
| 2903 } else if (value_cid == kSmiCid) { |
| 2904 __ Asr(TMP, value, kSmiTagSize); // Untag input before conversion. |
| 2905 __ scvtfd(result, TMP); |
| 2906 } else { |
| 2907 Label* deopt = compiler->AddDeoptStub(deopt_id_, |
| 2908 ICData::kDeoptBinaryDoubleOp); |
| 2909 if (value_type->is_nullable() && |
| 2910 (value_type->ToNullableCid() == kDoubleCid)) { |
| 2911 __ CompareObject(value, Object::null_object(), PP); |
| 2912 __ b(deopt, EQ); |
| 2913 // It must be double now. |
| 2914 __ LoadDFieldFromOffset(result, value, Double::value_offset()); |
| 2915 } else { |
| 2916 Label is_smi, done; |
| 2917 __ tsti(value, kSmiTagMask); |
| 2918 __ b(&is_smi, EQ); |
| 2919 __ CompareClassId(value, kDoubleCid); |
| 2920 __ b(deopt, NE); |
| 2921 __ LoadDFieldFromOffset(result, value, Double::value_offset()); |
| 2922 __ b(&done); |
| 2923 __ Bind(&is_smi); |
| 2924 __ Asr(TMP, value, kSmiTagSize); // Copy and untag. |
| 2925 __ scvtfd(result, TMP); |
| 2926 __ Bind(&done); |
| 2927 } |
| 2928 } |
| 2842 } | 2929 } |
| 2843 | 2930 |
| 2844 | 2931 |
| 2845 LocationSummary* BoxFloat32x4Instr::MakeLocationSummary(bool opt) const { | 2932 LocationSummary* BoxFloat32x4Instr::MakeLocationSummary(bool opt) const { |
| 2846 UNIMPLEMENTED(); | 2933 UNIMPLEMENTED(); |
| 2847 return NULL; | 2934 return NULL; |
| 2848 } | 2935 } |
| 2849 | 2936 |
| 2850 | 2937 |
| 2851 void BoxFloat32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2938 void BoxFloat32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2902 return NULL; | 2989 return NULL; |
| 2903 } | 2990 } |
| 2904 | 2991 |
| 2905 | 2992 |
| 2906 void UnboxInt32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2993 void UnboxInt32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2907 UNIMPLEMENTED(); | 2994 UNIMPLEMENTED(); |
| 2908 } | 2995 } |
| 2909 | 2996 |
| 2910 | 2997 |
| 2911 LocationSummary* BinaryDoubleOpInstr::MakeLocationSummary(bool opt) const { | 2998 LocationSummary* BinaryDoubleOpInstr::MakeLocationSummary(bool opt) const { |
| 2912 UNIMPLEMENTED(); | 2999 const intptr_t kNumInputs = 2; |
| 2913 return NULL; | 3000 const intptr_t kNumTemps = 0; |
| 3001 LocationSummary* summary = |
| 3002 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 3003 summary->set_in(0, Location::RequiresFpuRegister()); |
| 3004 summary->set_in(1, Location::RequiresFpuRegister()); |
| 3005 summary->set_out(0, Location::RequiresFpuRegister()); |
| 3006 return summary; |
| 2914 } | 3007 } |
| 2915 | 3008 |
| 2916 | 3009 |
| 2917 void BinaryDoubleOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3010 void BinaryDoubleOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2918 UNIMPLEMENTED(); | 3011 const VRegister left = locs()->in(0).fpu_reg(); |
| 3012 const VRegister right = locs()->in(1).fpu_reg(); |
| 3013 const VRegister result = locs()->out(0).fpu_reg(); |
| 3014 switch (op_kind()) { |
| 3015 case Token::kADD: __ faddd(result, left, right); break; |
| 3016 case Token::kSUB: __ fsubd(result, left, right); break; |
| 3017 case Token::kMUL: __ fmuld(result, left, right); break; |
| 3018 case Token::kDIV: __ fdivd(result, left, right); break; |
| 3019 default: UNREACHABLE(); |
| 3020 } |
| 2919 } | 3021 } |
| 2920 | 3022 |
| 2921 | 3023 |
| 2922 LocationSummary* BinaryFloat32x4OpInstr::MakeLocationSummary(bool opt) const { | 3024 LocationSummary* BinaryFloat32x4OpInstr::MakeLocationSummary(bool opt) const { |
| 2923 UNIMPLEMENTED(); | 3025 UNIMPLEMENTED(); |
| 2924 return NULL; | 3026 return NULL; |
| 2925 } | 3027 } |
| 2926 | 3028 |
| 2927 | 3029 |
| 2928 void BinaryFloat32x4OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3030 void BinaryFloat32x4OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| (...skipping 972 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3901 compiler->GenerateCall(token_pos(), | 4003 compiler->GenerateCall(token_pos(), |
| 3902 &label, | 4004 &label, |
| 3903 PcDescriptors::kOther, | 4005 PcDescriptors::kOther, |
| 3904 locs()); | 4006 locs()); |
| 3905 __ Drop(ArgumentCount()); // Discard arguments. | 4007 __ Drop(ArgumentCount()); // Discard arguments. |
| 3906 } | 4008 } |
| 3907 | 4009 |
| 3908 } // namespace dart | 4010 } // namespace dart |
| 3909 | 4011 |
| 3910 #endif // defined TARGET_ARCH_ARM64 | 4012 #endif // defined TARGET_ARCH_ARM64 |
| OLD | NEW |