| 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_X64. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_X64. |
| 6 #if defined(TARGET_ARCH_X64) | 6 #if defined(TARGET_ARCH_X64) |
| 7 | 7 |
| 8 #include "vm/intrinsifier.h" | 8 #include "vm/intrinsifier.h" |
| 9 | 9 |
| 10 #include "vm/assembler.h" | 10 #include "vm/assembler.h" |
| (...skipping 1178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1189 __ ret(); | 1189 __ ret(); |
| 1190 __ Bind(&is_zero); | 1190 __ Bind(&is_zero); |
| 1191 // Check for negative zero (get the sign bit). | 1191 // Check for negative zero (get the sign bit). |
| 1192 __ movmskpd(RAX, XMM0); | 1192 __ movmskpd(RAX, XMM0); |
| 1193 __ testq(RAX, Immediate(1)); | 1193 __ testq(RAX, Immediate(1)); |
| 1194 __ j(NOT_ZERO, &is_true, Assembler::kNearJump); | 1194 __ j(NOT_ZERO, &is_true, Assembler::kNearJump); |
| 1195 __ jmp(&is_false, Assembler::kNearJump); | 1195 __ jmp(&is_false, Assembler::kNearJump); |
| 1196 } | 1196 } |
| 1197 | 1197 |
| 1198 | 1198 |
| 1199 enum TrigonometricFunctions { | |
| 1200 kSine, | |
| 1201 kCosine, | |
| 1202 }; | |
| 1203 | |
| 1204 | |
| 1205 static void EmitTrigonometric(Assembler* assembler, | |
| 1206 TrigonometricFunctions kind) { | |
| 1207 Label fall_through, is_smi, double_op; | |
| 1208 TestLastArgumentIsDouble(assembler, &is_smi, &fall_through); | |
| 1209 // Argument is double and is in EAX. | |
| 1210 __ fldl(FieldAddress(RAX, Double::value_offset())); | |
| 1211 __ Bind(&double_op); | |
| 1212 switch (kind) { | |
| 1213 case kSine: __ fsin(); break; | |
| 1214 case kCosine: __ fcos(); break; | |
| 1215 default: | |
| 1216 UNREACHABLE(); | |
| 1217 } | |
| 1218 const Class& double_class = Class::Handle( | |
| 1219 Isolate::Current()->object_store()->double_class()); | |
| 1220 Label alloc_failed; | |
| 1221 __ TryAllocate(double_class, | |
| 1222 &alloc_failed, | |
| 1223 Assembler::kNearJump, | |
| 1224 RAX, // Result register. | |
| 1225 kNoRegister); // Pool pointer might not be loaded. | |
| 1226 __ fstpl(FieldAddress(RAX, Double::value_offset())); | |
| 1227 __ ret(); | |
| 1228 | |
| 1229 __ Bind(&is_smi); // smi -> double. | |
| 1230 __ SmiUntag(RAX); | |
| 1231 __ pushq(RAX); | |
| 1232 __ fildl(Address(RSP, 0)); | |
| 1233 __ popq(RAX); | |
| 1234 __ jmp(&double_op); | |
| 1235 | |
| 1236 __ Bind(&alloc_failed); | |
| 1237 __ ffree(0); | |
| 1238 __ fincstp(); | |
| 1239 | |
| 1240 __ Bind(&fall_through); | |
| 1241 } | |
| 1242 | |
| 1243 | |
| 1244 void Intrinsifier::Double_toInt(Assembler* assembler) { | 1199 void Intrinsifier::Double_toInt(Assembler* assembler) { |
| 1245 __ movq(RAX, Address(RSP, +1 * kWordSize)); | 1200 __ movq(RAX, Address(RSP, +1 * kWordSize)); |
| 1246 __ movsd(XMM0, FieldAddress(RAX, Double::value_offset())); | 1201 __ movsd(XMM0, FieldAddress(RAX, Double::value_offset())); |
| 1247 __ cvttsd2siq(RAX, XMM0); | 1202 __ cvttsd2siq(RAX, XMM0); |
| 1248 // Overflow is signalled with minint. | 1203 // Overflow is signalled with minint. |
| 1249 Label fall_through; | 1204 Label fall_through; |
| 1250 // Check for overflow and that it fits into Smi. | 1205 // Check for overflow and that it fits into Smi. |
| 1251 __ movq(RCX, RAX); | 1206 __ movq(RCX, RAX); |
| 1252 __ shlq(RCX, Immediate(1)); | 1207 __ shlq(RCX, Immediate(1)); |
| 1253 __ j(OVERFLOW, &fall_through, Assembler::kNearJump); | 1208 __ j(OVERFLOW, &fall_through, Assembler::kNearJump); |
| (...skipping 20 matching lines...) Expand all Loading... |
| 1274 __ movsd(FieldAddress(RAX, Double::value_offset()), XMM0); | 1229 __ movsd(FieldAddress(RAX, Double::value_offset()), XMM0); |
| 1275 __ ret(); | 1230 __ ret(); |
| 1276 __ Bind(&is_smi); | 1231 __ Bind(&is_smi); |
| 1277 __ SmiUntag(RAX); | 1232 __ SmiUntag(RAX); |
| 1278 __ cvtsi2sd(XMM1, RAX); | 1233 __ cvtsi2sd(XMM1, RAX); |
| 1279 __ jmp(&double_op); | 1234 __ jmp(&double_op); |
| 1280 __ Bind(&fall_through); | 1235 __ Bind(&fall_through); |
| 1281 } | 1236 } |
| 1282 | 1237 |
| 1283 | 1238 |
| 1284 void Intrinsifier::Math_sin(Assembler* assembler) { | |
| 1285 EmitTrigonometric(assembler, kSine); | |
| 1286 } | |
| 1287 | |
| 1288 | |
| 1289 void Intrinsifier::Math_cos(Assembler* assembler) { | |
| 1290 EmitTrigonometric(assembler, kCosine); | |
| 1291 } | |
| 1292 | |
| 1293 | |
| 1294 // var state = ((_A * (_state[kSTATE_LO])) + _state[kSTATE_HI]) & _MASK_64; | 1239 // var state = ((_A * (_state[kSTATE_LO])) + _state[kSTATE_HI]) & _MASK_64; |
| 1295 // _state[kSTATE_LO] = state & _MASK_32; | 1240 // _state[kSTATE_LO] = state & _MASK_32; |
| 1296 // _state[kSTATE_HI] = state >> 32; | 1241 // _state[kSTATE_HI] = state >> 32; |
| 1297 void Intrinsifier::Random_nextState(Assembler* assembler) { | 1242 void Intrinsifier::Random_nextState(Assembler* assembler) { |
| 1298 const Library& math_lib = Library::Handle(Library::MathLibrary()); | 1243 const Library& math_lib = Library::Handle(Library::MathLibrary()); |
| 1299 ASSERT(!math_lib.IsNull()); | 1244 ASSERT(!math_lib.IsNull()); |
| 1300 const Class& random_class = Class::Handle( | 1245 const Class& random_class = Class::Handle( |
| 1301 math_lib.LookupClassAllowPrivate(Symbols::_Random())); | 1246 math_lib.LookupClassAllowPrivate(Symbols::_Random())); |
| 1302 ASSERT(!random_class.IsNull()); | 1247 ASSERT(!random_class.IsNull()); |
| 1303 const Field& state_field = Field::ZoneHandle( | 1248 const Field& state_field = Field::ZoneHandle( |
| (...skipping 394 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1698 | 1643 |
| 1699 void Intrinsifier::TwoByteString_equality(Assembler* assembler) { | 1644 void Intrinsifier::TwoByteString_equality(Assembler* assembler) { |
| 1700 StringEquality(assembler, kTwoByteStringCid); | 1645 StringEquality(assembler, kTwoByteStringCid); |
| 1701 } | 1646 } |
| 1702 | 1647 |
| 1703 #undef __ | 1648 #undef __ |
| 1704 | 1649 |
| 1705 } // namespace dart | 1650 } // namespace dart |
| 1706 | 1651 |
| 1707 #endif // defined TARGET_ARCH_X64 | 1652 #endif // defined TARGET_ARCH_X64 |
| OLD | NEW |