| 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 1191 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1202 : Location::RegisterOrConstant(value())); | 1202 : Location::RegisterOrConstant(value())); |
| 1203 break; | 1203 break; |
| 1204 case kExternalTypedDataUint8ArrayCid: | 1204 case kExternalTypedDataUint8ArrayCid: |
| 1205 case kExternalTypedDataUint8ClampedArrayCid: | 1205 case kExternalTypedDataUint8ClampedArrayCid: |
| 1206 case kTypedDataInt8ArrayCid: | 1206 case kTypedDataInt8ArrayCid: |
| 1207 case kTypedDataUint8ArrayCid: | 1207 case kTypedDataUint8ArrayCid: |
| 1208 case kTypedDataUint8ClampedArrayCid: | 1208 case kTypedDataUint8ClampedArrayCid: |
| 1209 case kOneByteStringCid: | 1209 case kOneByteStringCid: |
| 1210 case kTypedDataInt16ArrayCid: | 1210 case kTypedDataInt16ArrayCid: |
| 1211 case kTypedDataUint16ArrayCid: | 1211 case kTypedDataUint16ArrayCid: |
| 1212 locs->set_in(2, Location::WritableRegister()); | |
| 1213 break; | |
| 1214 case kTypedDataInt32ArrayCid: | 1212 case kTypedDataInt32ArrayCid: |
| 1215 case kTypedDataUint32ArrayCid: | 1213 case kTypedDataUint32ArrayCid: |
| 1216 locs->set_in(2, Location::WritableRegister()); | 1214 locs->set_in(2, Location::RequiresRegister()); |
| 1217 break; | 1215 break; |
| 1218 case kTypedDataFloat32ArrayCid: | 1216 case kTypedDataFloat32ArrayCid: |
| 1219 case kTypedDataFloat64ArrayCid: // TODO(srdjan): Support Float64 constants. | 1217 case kTypedDataFloat64ArrayCid: // TODO(srdjan): Support Float64 constants. |
| 1220 locs->set_in(2, Location::RequiresFpuRegister()); | 1218 locs->set_in(2, Location::RequiresFpuRegister()); |
| 1221 break; | 1219 break; |
| 1222 case kTypedDataInt32x4ArrayCid: | 1220 case kTypedDataInt32x4ArrayCid: |
| 1223 case kTypedDataFloat32x4ArrayCid: | 1221 case kTypedDataFloat32x4ArrayCid: |
| 1224 case kTypedDataFloat64x2ArrayCid: | 1222 case kTypedDataFloat64x2ArrayCid: |
| 1225 locs->set_in(2, Location::RequiresFpuRegister()); | 1223 locs->set_in(2, Location::RequiresFpuRegister()); |
| 1226 break; | 1224 break; |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1261 case kTypedDataInt8ArrayCid: | 1259 case kTypedDataInt8ArrayCid: |
| 1262 case kTypedDataUint8ArrayCid: | 1260 case kTypedDataUint8ArrayCid: |
| 1263 case kExternalTypedDataUint8ArrayCid: | 1261 case kExternalTypedDataUint8ArrayCid: |
| 1264 case kOneByteStringCid: { | 1262 case kOneByteStringCid: { |
| 1265 if (locs()->in(2).IsConstant()) { | 1263 if (locs()->in(2).IsConstant()) { |
| 1266 const Smi& constant = Smi::Cast(locs()->in(2).constant()); | 1264 const Smi& constant = Smi::Cast(locs()->in(2).constant()); |
| 1267 __ LoadImmediate(TMP, static_cast<int8_t>(constant.Value()), PP); | 1265 __ LoadImmediate(TMP, static_cast<int8_t>(constant.Value()), PP); |
| 1268 __ str(TMP, element_address, kUnsignedByte); | 1266 __ str(TMP, element_address, kUnsignedByte); |
| 1269 } else { | 1267 } else { |
| 1270 const Register value = locs()->in(2).reg(); | 1268 const Register value = locs()->in(2).reg(); |
| 1271 __ SmiUntag(value); | 1269 __ SmiUntag(TMP, value); |
| 1272 __ str(value, element_address, kUnsignedByte); | 1270 __ str(TMP, element_address, kUnsignedByte); |
| 1273 } | 1271 } |
| 1274 break; | 1272 break; |
| 1275 } | 1273 } |
| 1276 case kTypedDataUint8ClampedArrayCid: | 1274 case kTypedDataUint8ClampedArrayCid: |
| 1277 case kExternalTypedDataUint8ClampedArrayCid: { | 1275 case kExternalTypedDataUint8ClampedArrayCid: { |
| 1278 if (locs()->in(2).IsConstant()) { | 1276 if (locs()->in(2).IsConstant()) { |
| 1279 const Smi& constant = Smi::Cast(locs()->in(2).constant()); | 1277 const Smi& constant = Smi::Cast(locs()->in(2).constant()); |
| 1280 intptr_t value = constant.Value(); | 1278 intptr_t value = constant.Value(); |
| 1281 // Clamp to 0x0 or 0xFF respectively. | 1279 // Clamp to 0x0 or 0xFF respectively. |
| 1282 if (value > 0xFF) { | 1280 if (value > 0xFF) { |
| 1283 value = 0xFF; | 1281 value = 0xFF; |
| 1284 } else if (value < 0) { | 1282 } else if (value < 0) { |
| 1285 value = 0; | 1283 value = 0; |
| 1286 } | 1284 } |
| 1287 __ LoadImmediate(TMP, static_cast<int8_t>(value), PP); | 1285 __ LoadImmediate(TMP, static_cast<int8_t>(value), PP); |
| 1288 __ str(TMP, element_address, kUnsignedByte); | 1286 __ str(TMP, element_address, kUnsignedByte); |
| 1289 } else { | 1287 } else { |
| 1290 const Register value = locs()->in(2).reg(); | 1288 const Register value = locs()->in(2).reg(); |
| 1291 Label store_value; | 1289 __ CompareImmediate(value, 0x1FE, PP); // Smi value and smi 0xFF. |
| 1292 __ SmiUntag(value); | |
| 1293 __ CompareImmediate(value, 0xFF, PP); | |
| 1294 // Clamp to 0x00 or 0xFF respectively. | 1290 // Clamp to 0x00 or 0xFF respectively. |
| 1295 __ b(&store_value, LS); | 1291 __ csetm(TMP, GT); // TMP = value > 0x1FE ? -1 : 0. |
| 1296 __ LoadImmediate(TMP, 0x00, PP); | 1292 __ csel(TMP, value, TMP, LS); // TMP = value in range ? value : TMP. |
| 1297 __ LoadImmediate(TMP2, 0xFF, PP); | 1293 __ SmiUntag(TMP); |
| 1298 __ csel(value, TMP, value, LE); | 1294 __ str(TMP, element_address, kUnsignedByte); |
| 1299 __ csel(value, TMP2, value, GT); | |
| 1300 __ Bind(&store_value); | |
| 1301 __ str(value, element_address, kUnsignedByte); | |
| 1302 } | 1295 } |
| 1303 break; | 1296 break; |
| 1304 } | 1297 } |
| 1305 case kTypedDataInt16ArrayCid: | 1298 case kTypedDataInt16ArrayCid: |
| 1306 case kTypedDataUint16ArrayCid: { | 1299 case kTypedDataUint16ArrayCid: { |
| 1307 const Register value = locs()->in(2).reg(); | 1300 const Register value = locs()->in(2).reg(); |
| 1308 __ SmiUntag(value); | 1301 __ SmiUntag(TMP, value); |
| 1309 __ str(value, element_address, kUnsignedHalfword); | 1302 __ str(TMP, element_address, kUnsignedHalfword); |
| 1310 break; | 1303 break; |
| 1311 } | 1304 } |
| 1312 case kTypedDataInt32ArrayCid: | 1305 case kTypedDataInt32ArrayCid: |
| 1313 case kTypedDataUint32ArrayCid: { | 1306 case kTypedDataUint32ArrayCid: { |
| 1314 const Register value = locs()->in(2).reg(); | 1307 const Register value = locs()->in(2).reg(); |
| 1315 __ SmiUntag(value); | 1308 __ SmiUntag(TMP, value); |
| 1316 __ str(value, element_address, kUnsignedWord); | 1309 __ str(TMP, element_address, kUnsignedWord); |
| 1317 break; | 1310 break; |
| 1318 } | 1311 } |
| 1319 case kTypedDataFloat32ArrayCid: { | 1312 case kTypedDataFloat32ArrayCid: { |
| 1320 const VRegister value_reg = locs()->in(2).fpu_reg(); | 1313 const VRegister value_reg = locs()->in(2).fpu_reg(); |
| 1321 __ fstrs(value_reg, element_address); | 1314 __ fstrs(value_reg, element_address); |
| 1322 break; | 1315 break; |
| 1323 } | 1316 } |
| 1324 case kTypedDataFloat64ArrayCid: { | 1317 case kTypedDataFloat64ArrayCid: { |
| 1325 const VRegister value_reg = locs()->in(2).fpu_reg(); | 1318 const VRegister value_reg = locs()->in(2).fpu_reg(); |
| 1326 __ fstrd(value_reg, element_address); | 1319 __ fstrd(value_reg, element_address); |
| (...skipping 1309 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2636 } | 2629 } |
| 2637 const intptr_t max_right = kSmiBits - Utils::HighestBit(left_int); | 2630 const intptr_t max_right = kSmiBits - Utils::HighestBit(left_int); |
| 2638 const bool right_needs_check = | 2631 const bool right_needs_check = |
| 2639 (right_range == NULL) || | 2632 (right_range == NULL) || |
| 2640 !right_range->IsWithin(0, max_right - 1); | 2633 !right_range->IsWithin(0, max_right - 1); |
| 2641 if (right_needs_check) { | 2634 if (right_needs_check) { |
| 2642 __ CompareImmediate(right, | 2635 __ CompareImmediate(right, |
| 2643 reinterpret_cast<int64_t>(Smi::New(max_right)), PP); | 2636 reinterpret_cast<int64_t>(Smi::New(max_right)), PP); |
| 2644 __ b(deopt, CS); | 2637 __ b(deopt, CS); |
| 2645 } | 2638 } |
| 2646 __ Asr(TMP, right, kSmiTagSize); // SmiUntag right into TMP. | 2639 __ SmiUntag(TMP, right); |
| 2647 __ lslv(result, left, TMP); | 2640 __ lslv(result, left, TMP); |
| 2648 } | 2641 } |
| 2649 if (FLAG_throw_on_javascript_int_overflow) { | 2642 if (FLAG_throw_on_javascript_int_overflow) { |
| 2650 EmitJavascriptOverflowCheck(compiler, shift_left->range(), deopt, result); | 2643 EmitJavascriptOverflowCheck(compiler, shift_left->range(), deopt, result); |
| 2651 } | 2644 } |
| 2652 return; | 2645 return; |
| 2653 } | 2646 } |
| 2654 | 2647 |
| 2655 const bool right_needs_check = | 2648 const bool right_needs_check = |
| 2656 (right_range == NULL) || !right_range->IsWithin(0, (Smi::kBits - 1)); | 2649 (right_range == NULL) || !right_range->IsWithin(0, (Smi::kBits - 1)); |
| 2657 if (is_truncating) { | 2650 if (is_truncating) { |
| 2658 if (right_needs_check) { | 2651 if (right_needs_check) { |
| 2659 const bool right_may_be_negative = | 2652 const bool right_may_be_negative = |
| 2660 (right_range == NULL) || | 2653 (right_range == NULL) || |
| 2661 !right_range->IsWithin(0, RangeBoundary::kPlusInfinity); | 2654 !right_range->IsWithin(0, RangeBoundary::kPlusInfinity); |
| 2662 if (right_may_be_negative) { | 2655 if (right_may_be_negative) { |
| 2663 ASSERT(shift_left->CanDeoptimize()); | 2656 ASSERT(shift_left->CanDeoptimize()); |
| 2664 __ CompareRegisters(right, ZR); | 2657 __ CompareRegisters(right, ZR); |
| 2665 __ b(deopt, MI); | 2658 __ b(deopt, MI); |
| 2666 } | 2659 } |
| 2667 | 2660 |
| 2668 __ CompareImmediate( | 2661 __ CompareImmediate( |
| 2669 right, reinterpret_cast<int64_t>(Smi::New(Smi::kBits)), PP); | 2662 right, reinterpret_cast<int64_t>(Smi::New(Smi::kBits)), PP); |
| 2670 __ csel(result, ZR, result, CS); | 2663 __ csel(result, ZR, result, CS); |
| 2671 __ Asr(TMP, right, kSmiTagSize); // SmiUntag right into TMP. | 2664 __ SmiUntag(TMP, right); |
| 2672 __ lslv(TMP, left, TMP); | 2665 __ lslv(TMP, left, TMP); |
| 2673 __ csel(result, TMP, result, CC); | 2666 __ csel(result, TMP, result, CC); |
| 2674 } else { | 2667 } else { |
| 2675 __ Asr(TMP, right, kSmiTagSize); // SmiUntag right into TMP. | 2668 __ SmiUntag(TMP, right); |
| 2676 __ lslv(result, left, TMP); | 2669 __ lslv(result, left, TMP); |
| 2677 } | 2670 } |
| 2678 } else { | 2671 } else { |
| 2679 if (right_needs_check) { | 2672 if (right_needs_check) { |
| 2680 ASSERT(shift_left->CanDeoptimize()); | 2673 ASSERT(shift_left->CanDeoptimize()); |
| 2681 __ CompareImmediate( | 2674 __ CompareImmediate( |
| 2682 right, reinterpret_cast<int64_t>(Smi::New(Smi::kBits)), PP); | 2675 right, reinterpret_cast<int64_t>(Smi::New(Smi::kBits)), PP); |
| 2683 __ b(deopt, CS); | 2676 __ b(deopt, CS); |
| 2684 } | 2677 } |
| 2685 // Left is not a constant. | 2678 // Left is not a constant. |
| 2686 // Check if count too large for handling it inlined. | 2679 // Check if count too large for handling it inlined. |
| 2687 __ Asr(TMP, right, kSmiTagSize); // SmiUntag right into TMP. | 2680 __ SmiUntag(TMP, right); |
| 2688 // Overflow test (preserve left, right, and TMP); | 2681 // Overflow test (preserve left, right, and TMP); |
| 2689 const Register temp = locs.temp(0).reg(); | 2682 const Register temp = locs.temp(0).reg(); |
| 2690 __ lslv(temp, left, TMP); | 2683 __ lslv(temp, left, TMP); |
| 2691 __ asrv(TMP2, temp, TMP); | 2684 __ asrv(TMP2, temp, TMP); |
| 2692 __ CompareRegisters(left, TMP2); | 2685 __ CompareRegisters(left, TMP2); |
| 2693 __ b(deopt, NE); // Overflow. | 2686 __ b(deopt, NE); // Overflow. |
| 2694 // Shift for result now we know there is no overflow. | 2687 // Shift for result now we know there is no overflow. |
| 2695 __ lslv(result, left, TMP); | 2688 __ lslv(result, left, TMP); |
| 2696 } | 2689 } |
| 2697 if (FLAG_throw_on_javascript_int_overflow) { | 2690 if (FLAG_throw_on_javascript_int_overflow) { |
| (...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2893 case Token::kSUB: { | 2886 case Token::kSUB: { |
| 2894 if (deopt == NULL) { | 2887 if (deopt == NULL) { |
| 2895 __ sub(result, left, Operand(right)); | 2888 __ sub(result, left, Operand(right)); |
| 2896 } else { | 2889 } else { |
| 2897 __ subs(result, left, Operand(right)); | 2890 __ subs(result, left, Operand(right)); |
| 2898 __ b(deopt, VS); | 2891 __ b(deopt, VS); |
| 2899 } | 2892 } |
| 2900 break; | 2893 break; |
| 2901 } | 2894 } |
| 2902 case Token::kMUL: { | 2895 case Token::kMUL: { |
| 2903 __ Asr(TMP, left, kSmiTagSize); // SmiUntag left into TMP. | 2896 __ SmiUntag(TMP, left); |
| 2904 if (deopt == NULL) { | 2897 if (deopt == NULL) { |
| 2905 __ mul(result, TMP, right); | 2898 __ mul(result, TMP, right); |
| 2906 } else { | 2899 } else { |
| 2907 __ mul(result, TMP, right); | 2900 __ mul(result, TMP, right); |
| 2908 __ smulh(TMP, TMP, right); | 2901 __ smulh(TMP, TMP, right); |
| 2909 // TMP: result bits 64..127. | 2902 // TMP: result bits 64..127. |
| 2910 __ cmp(TMP, Operand(result, ASR, 63)); | 2903 __ cmp(TMP, Operand(result, ASR, 63)); |
| 2911 __ b(deopt, NE); | 2904 __ b(deopt, NE); |
| 2912 } | 2905 } |
| 2913 break; | 2906 break; |
| (...skipping 13 matching lines...) Expand all Loading... |
| 2927 __ eor(result, left, Operand(right)); | 2920 __ eor(result, left, Operand(right)); |
| 2928 break; | 2921 break; |
| 2929 } | 2922 } |
| 2930 case Token::kTRUNCDIV: { | 2923 case Token::kTRUNCDIV: { |
| 2931 if ((right_range == NULL) || right_range->Overlaps(0, 0)) { | 2924 if ((right_range == NULL) || right_range->Overlaps(0, 0)) { |
| 2932 // Handle divide by zero in runtime. | 2925 // Handle divide by zero in runtime. |
| 2933 __ CompareRegisters(right, ZR); | 2926 __ CompareRegisters(right, ZR); |
| 2934 __ b(deopt, EQ); | 2927 __ b(deopt, EQ); |
| 2935 } | 2928 } |
| 2936 const Register temp = TMP2; | 2929 const Register temp = TMP2; |
| 2937 __ Asr(temp, left, kSmiTagSize); // SmiUntag left into temp. | 2930 __ SmiUntag(temp, left); |
| 2938 __ Asr(TMP, right, kSmiTagSize); // SmiUntag right into IP. | 2931 __ SmiUntag(TMP, right); |
| 2939 | 2932 |
| 2940 __ sdiv(result, temp, TMP); | 2933 __ sdiv(result, temp, TMP); |
| 2941 | 2934 |
| 2942 // Check the corner case of dividing the 'MIN_SMI' with -1, in which | 2935 // Check the corner case of dividing the 'MIN_SMI' with -1, in which |
| 2943 // case we cannot tag the result. | 2936 // case we cannot tag the result. |
| 2944 __ CompareImmediate(result, 0x4000000000000000LL, kNoPP); | 2937 __ CompareImmediate(result, 0x4000000000000000LL, kNoPP); |
| 2945 __ b(deopt, EQ); | 2938 __ b(deopt, EQ); |
| 2946 __ SmiTag(result); | 2939 __ SmiTag(result); |
| 2947 break; | 2940 break; |
| 2948 } | 2941 } |
| 2949 case Token::kMOD: { | 2942 case Token::kMOD: { |
| 2950 if ((right_range == NULL) || right_range->Overlaps(0, 0)) { | 2943 if ((right_range == NULL) || right_range->Overlaps(0, 0)) { |
| 2951 // Handle divide by zero in runtime. | 2944 // Handle divide by zero in runtime. |
| 2952 __ CompareRegisters(right, ZR); | 2945 __ CompareRegisters(right, ZR); |
| 2953 __ b(deopt, EQ); | 2946 __ b(deopt, EQ); |
| 2954 } | 2947 } |
| 2955 const Register temp = TMP2; | 2948 const Register temp = TMP2; |
| 2956 __ Asr(temp, left, kSmiTagSize); // SmiUntag left into temp. | 2949 __ SmiUntag(temp, left); |
| 2957 __ Asr(TMP, right, kSmiTagSize); // SmiUntag right into IP. | 2950 __ SmiUntag(TMP, right); |
| 2958 | 2951 |
| 2959 __ sdiv(result, temp, TMP); | 2952 __ sdiv(result, temp, TMP); |
| 2960 | 2953 |
| 2961 __ Asr(TMP, right, kSmiTagSize); // SmiUntag right into IP. | 2954 __ SmiUntag(TMP, right); |
| 2962 __ msub(result, TMP, result, temp); // result <- left - right * result | 2955 __ msub(result, TMP, result, temp); // result <- left - right * result |
| 2963 __ SmiTag(result); | 2956 __ SmiTag(result); |
| 2964 // res = left % right; | 2957 // res = left % right; |
| 2965 // if (res < 0) { | 2958 // if (res < 0) { |
| 2966 // if (right < 0) { | 2959 // if (right < 0) { |
| 2967 // res = res - right; | 2960 // res = res - right; |
| 2968 // } else { | 2961 // } else { |
| 2969 // res = res + right; | 2962 // res = res + right; |
| 2970 // } | 2963 // } |
| 2971 // } | 2964 // } |
| 2972 Label done; | 2965 Label done; |
| 2973 __ CompareRegisters(result, ZR); | 2966 __ CompareRegisters(result, ZR); |
| 2974 __ b(&done, GE); | 2967 __ b(&done, GE); |
| 2975 // Result is negative, adjust it. | 2968 // Result is negative, adjust it. |
| 2976 __ CompareRegisters(right, ZR); | 2969 __ CompareRegisters(right, ZR); |
| 2977 __ sub(TMP, result, Operand(right)); | 2970 __ sub(TMP, result, Operand(right)); |
| 2978 __ add(result, result, Operand(right)); | 2971 __ add(result, result, Operand(right)); |
| 2979 __ csel(result, TMP, result, LT); | 2972 __ csel(result, TMP, result, LT); |
| 2980 __ Bind(&done); | 2973 __ Bind(&done); |
| 2981 break; | 2974 break; |
| 2982 } | 2975 } |
| 2983 case Token::kSHR: { | 2976 case Token::kSHR: { |
| 2984 if (CanDeoptimize()) { | 2977 if (CanDeoptimize()) { |
| 2985 __ CompareRegisters(right, ZR); | 2978 __ CompareRegisters(right, ZR); |
| 2986 __ b(deopt, LT); | 2979 __ b(deopt, LT); |
| 2987 } | 2980 } |
| 2988 __ Asr(TMP, right, kSmiTagSize); // SmiUntag right into TMP. | 2981 __ SmiUntag(TMP, right); |
| 2989 // sarl operation masks the count to 6 bits. | 2982 // sarl operation masks the count to 6 bits. |
| 2990 const intptr_t kCountLimit = 0x3F; | 2983 const intptr_t kCountLimit = 0x3F; |
| 2991 if ((right_range == NULL) || | 2984 if ((right_range == NULL) || |
| 2992 !right_range->IsWithin(RangeBoundary::kMinusInfinity, kCountLimit)) { | 2985 !right_range->IsWithin(RangeBoundary::kMinusInfinity, kCountLimit)) { |
| 2993 __ LoadImmediate(TMP2, kCountLimit, PP); | 2986 __ LoadImmediate(TMP2, kCountLimit, PP); |
| 2994 __ CompareRegisters(TMP, TMP2); | 2987 __ CompareRegisters(TMP, TMP2); |
| 2995 __ csel(TMP, TMP2, TMP, GT); | 2988 __ csel(TMP, TMP2, TMP, GT); |
| 2996 } | 2989 } |
| 2997 const Register temp = locs()->temp(0).reg(); | 2990 const Register temp = locs()->temp(0).reg(); |
| 2998 __ Asr(temp, left, kSmiTagSize); // SmiUntag left into temp. | 2991 __ SmiUntag(temp, left); |
| 2999 __ asrv(result, temp, TMP); | 2992 __ asrv(result, temp, TMP); |
| 3000 __ SmiTag(result); | 2993 __ SmiTag(result); |
| 3001 break; | 2994 break; |
| 3002 } | 2995 } |
| 3003 case Token::kDIV: { | 2996 case Token::kDIV: { |
| 3004 // Dispatches to 'Double./'. | 2997 // Dispatches to 'Double./'. |
| 3005 // TODO(srdjan): Implement as conversion to double and double division. | 2998 // TODO(srdjan): Implement as conversion to double and double division. |
| 3006 UNREACHABLE(); | 2999 UNREACHABLE(); |
| 3007 break; | 3000 break; |
| 3008 } | 3001 } |
| (...skipping 1498 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4507 __ fnegd(result, value); | 4500 __ fnegd(result, value); |
| 4508 } | 4501 } |
| 4509 | 4502 |
| 4510 | 4503 |
| 4511 LocationSummary* SmiToDoubleInstr::MakeLocationSummary(Isolate* isolate, | 4504 LocationSummary* SmiToDoubleInstr::MakeLocationSummary(Isolate* isolate, |
| 4512 bool opt) const { | 4505 bool opt) const { |
| 4513 const intptr_t kNumInputs = 1; | 4506 const intptr_t kNumInputs = 1; |
| 4514 const intptr_t kNumTemps = 0; | 4507 const intptr_t kNumTemps = 0; |
| 4515 LocationSummary* result = new(isolate) LocationSummary( | 4508 LocationSummary* result = new(isolate) LocationSummary( |
| 4516 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4509 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4517 result->set_in(0, Location::WritableRegister()); | 4510 result->set_in(0, Location::RequiresRegister()); |
| 4518 result->set_out(0, Location::RequiresFpuRegister()); | 4511 result->set_out(0, Location::RequiresFpuRegister()); |
| 4519 return result; | 4512 return result; |
| 4520 } | 4513 } |
| 4521 | 4514 |
| 4522 | 4515 |
| 4523 void SmiToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4516 void SmiToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4524 const Register value = locs()->in(0).reg(); | 4517 const Register value = locs()->in(0).reg(); |
| 4525 const VRegister result = locs()->out(0).fpu_reg(); | 4518 const VRegister result = locs()->out(0).fpu_reg(); |
| 4526 __ SmiUntag(value); | 4519 __ SmiUntag(TMP, value); |
| 4527 __ scvtfd(result, value); | 4520 __ scvtfd(result, TMP); |
| 4528 } | 4521 } |
| 4529 | 4522 |
| 4530 | 4523 |
| 4531 LocationSummary* DoubleToIntegerInstr::MakeLocationSummary(Isolate* isolate, | 4524 LocationSummary* DoubleToIntegerInstr::MakeLocationSummary(Isolate* isolate, |
| 4532 bool opt) const { | 4525 bool opt) const { |
| 4533 const intptr_t kNumInputs = 1; | 4526 const intptr_t kNumInputs = 1; |
| 4534 const intptr_t kNumTemps = 0; | 4527 const intptr_t kNumTemps = 0; |
| 4535 LocationSummary* result = new(isolate) LocationSummary( | 4528 LocationSummary* result = new(isolate) LocationSummary( |
| 4536 isolate, kNumInputs, kNumTemps, LocationSummary::kCall); | 4529 isolate, kNumInputs, kNumTemps, LocationSummary::kCall); |
| 4537 result->set_in(0, Location::RegisterLocation(R1)); | 4530 result->set_in(0, Location::RegisterLocation(R1)); |
| (...skipping 348 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4886 const PairLocation* pair = locs()->out(0).AsPairLocation(); | 4879 const PairLocation* pair = locs()->out(0).AsPairLocation(); |
| 4887 const Register result_div = pair->At(0).reg(); | 4880 const Register result_div = pair->At(0).reg(); |
| 4888 const Register result_mod = pair->At(1).reg(); | 4881 const Register result_mod = pair->At(1).reg(); |
| 4889 const Range* right_range = InputAt(1)->definition()->range(); | 4882 const Range* right_range = InputAt(1)->definition()->range(); |
| 4890 if ((right_range == NULL) || right_range->Overlaps(0, 0)) { | 4883 if ((right_range == NULL) || right_range->Overlaps(0, 0)) { |
| 4891 // Handle divide by zero in runtime. | 4884 // Handle divide by zero in runtime. |
| 4892 __ CompareRegisters(right, ZR); | 4885 __ CompareRegisters(right, ZR); |
| 4893 __ b(deopt, EQ); | 4886 __ b(deopt, EQ); |
| 4894 } | 4887 } |
| 4895 | 4888 |
| 4896 __ Asr(result_mod, left, kSmiTagSize); // SmiUntag left. | 4889 __ SmiUntag(result_mod, left); |
| 4897 __ Asr(TMP, right, kSmiTagSize); // SmiUntag right. | 4890 __ SmiUntag(TMP, right); |
| 4898 | 4891 |
| 4899 __ sdiv(result_div, result_mod, TMP); | 4892 __ sdiv(result_div, result_mod, TMP); |
| 4900 | 4893 |
| 4901 // Check the corner case of dividing the 'MIN_SMI' with -1, in which | 4894 // Check the corner case of dividing the 'MIN_SMI' with -1, in which |
| 4902 // case we cannot tag the result. | 4895 // case we cannot tag the result. |
| 4903 __ CompareImmediate(result_div, 0x4000000000000000, PP); | 4896 __ CompareImmediate(result_div, 0x4000000000000000, PP); |
| 4904 __ b(deopt, EQ); | 4897 __ b(deopt, EQ); |
| 4905 // result_mod <- left - right * result_div. | 4898 // result_mod <- left - right * result_div. |
| 4906 __ msub(result_mod, TMP, result_div, result_mod); | 4899 __ msub(result_mod, TMP, result_div, result_mod); |
| 4907 __ SmiTag(result_div); | 4900 __ SmiTag(result_div); |
| (...skipping 493 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5401 compiler->GenerateCall(token_pos(), | 5394 compiler->GenerateCall(token_pos(), |
| 5402 &label, | 5395 &label, |
| 5403 PcDescriptors::kOther, | 5396 PcDescriptors::kOther, |
| 5404 locs()); | 5397 locs()); |
| 5405 __ Drop(ArgumentCount()); // Discard arguments. | 5398 __ Drop(ArgumentCount()); // Discard arguments. |
| 5406 } | 5399 } |
| 5407 | 5400 |
| 5408 } // namespace dart | 5401 } // namespace dart |
| 5409 | 5402 |
| 5410 #endif // defined TARGET_ARCH_ARM64 | 5403 #endif // defined TARGET_ARCH_ARM64 |
| OLD | NEW |