Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012, 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/flow_graph_compiler.h" | 8 #include "vm/flow_graph_compiler.h" |
| 9 | 9 |
| 10 #include "lib/error.h" | 10 #include "lib/error.h" |
| 11 #include "vm/ast_printer.h" | 11 #include "vm/ast_printer.h" |
| (...skipping 1276 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1288 __ Drop(1); | 1288 __ Drop(1); |
| 1289 __ jmp(skip_call); | 1289 __ jmp(skip_call); |
| 1290 __ Bind(&is_false); | 1290 __ Bind(&is_false); |
| 1291 __ LoadObject(result, Bool::False()); | 1291 __ LoadObject(result, Bool::False()); |
| 1292 __ Drop(1); | 1292 __ Drop(1); |
| 1293 __ jmp(skip_call); | 1293 __ jmp(skip_call); |
| 1294 __ Bind(&fall_through); | 1294 __ Bind(&fall_through); |
| 1295 } | 1295 } |
| 1296 | 1296 |
| 1297 | 1297 |
| 1298 void FlowGraphCompiler::LoadDoubleOrSmiToXmm(XmmRegister result, | 1298 void FlowGraphCompiler::LoadDoubleOrSmiToFpu(XmmRegister result, |
|
Ivan Posva
2013/01/16 01:17:56
ditto
regis
2013/01/16 01:55:07
Done.
| |
| 1299 Register reg, | 1299 Register reg, |
| 1300 Register temp, | 1300 Register temp, |
| 1301 Label* not_double_or_smi) { | 1301 Label* not_double_or_smi) { |
| 1302 Label is_smi, done; | 1302 Label is_smi, done; |
| 1303 __ testq(reg, Immediate(kSmiTagMask)); | 1303 __ testq(reg, Immediate(kSmiTagMask)); |
| 1304 __ j(ZERO, &is_smi); | 1304 __ j(ZERO, &is_smi); |
| 1305 __ CompareClassId(reg, kDoubleCid); | 1305 __ CompareClassId(reg, kDoubleCid); |
| 1306 __ j(NOT_EQUAL, not_double_or_smi); | 1306 __ j(NOT_EQUAL, not_double_or_smi); |
| 1307 __ movsd(result, FieldAddress(reg, Double::value_offset())); | 1307 __ movsd(result, FieldAddress(reg, Double::value_offset())); |
| 1308 __ jmp(&done); | 1308 __ jmp(&done); |
| 1309 __ Bind(&is_smi); | 1309 __ Bind(&is_smi); |
| 1310 __ movq(temp, reg); | 1310 __ movq(temp, reg); |
| 1311 __ SmiUntag(temp); | 1311 __ SmiUntag(temp); |
| 1312 __ cvtsi2sd(result, temp); | 1312 __ cvtsi2sd(result, temp); |
| 1313 __ Bind(&done); | 1313 __ Bind(&done); |
| 1314 } | 1314 } |
| 1315 | 1315 |
| 1316 | 1316 |
| 1317 void FlowGraphCompiler::SaveLiveRegisters(LocationSummary* locs) { | 1317 void FlowGraphCompiler::SaveLiveRegisters(LocationSummary* locs) { |
| 1318 // TODO(vegorov): consider saving only caller save (volatile) registers. | 1318 // TODO(vegorov): consider saving only caller save (volatile) registers. |
| 1319 const intptr_t xmm_regs_count = locs->live_registers()->xmm_regs_count(); | 1319 const intptr_t xmm_regs_count = locs->live_registers()->fpu_regs_count(); |
| 1320 if (xmm_regs_count > 0) { | 1320 if (xmm_regs_count > 0) { |
| 1321 __ subq(RSP, Immediate(xmm_regs_count * kDoubleSize)); | 1321 __ subq(RSP, Immediate(xmm_regs_count * kDoubleSize)); |
| 1322 // Store XMM registers with the lowest register number at the lowest | 1322 // Store XMM registers with the lowest register number at the lowest |
| 1323 // address. | 1323 // address. |
| 1324 intptr_t offset = 0; | 1324 intptr_t offset = 0; |
| 1325 for (intptr_t reg_idx = 0; reg_idx < kNumberOfXmmRegisters; ++reg_idx) { | 1325 for (intptr_t reg_idx = 0; reg_idx < kNumberOfXmmRegisters; ++reg_idx) { |
| 1326 XmmRegister xmm_reg = static_cast<XmmRegister>(reg_idx); | 1326 XmmRegister xmm_reg = static_cast<XmmRegister>(reg_idx); |
| 1327 if (locs->live_registers()->ContainsXmmRegister(xmm_reg)) { | 1327 if (locs->live_registers()->ContainsFpuRegister(xmm_reg)) { |
| 1328 __ movsd(Address(RSP, offset), xmm_reg); | 1328 __ movsd(Address(RSP, offset), xmm_reg); |
| 1329 offset += kDoubleSize; | 1329 offset += kDoubleSize; |
| 1330 } | 1330 } |
| 1331 } | 1331 } |
| 1332 ASSERT(offset == (xmm_regs_count * kDoubleSize)); | 1332 ASSERT(offset == (xmm_regs_count * kDoubleSize)); |
| 1333 } | 1333 } |
| 1334 | 1334 |
| 1335 // Store general purpose registers with the highest register number at the | 1335 // Store general purpose registers with the highest register number at the |
| 1336 // lowest address. | 1336 // lowest address. |
| 1337 for (intptr_t reg_idx = 0; reg_idx < kNumberOfCpuRegisters; ++reg_idx) { | 1337 for (intptr_t reg_idx = 0; reg_idx < kNumberOfCpuRegisters; ++reg_idx) { |
| 1338 Register reg = static_cast<Register>(reg_idx); | 1338 Register reg = static_cast<Register>(reg_idx); |
| 1339 if (locs->live_registers()->ContainsRegister(reg)) { | 1339 if (locs->live_registers()->ContainsRegister(reg)) { |
| 1340 __ pushq(reg); | 1340 __ pushq(reg); |
| 1341 } | 1341 } |
| 1342 } | 1342 } |
| 1343 } | 1343 } |
| 1344 | 1344 |
| 1345 | 1345 |
| 1346 void FlowGraphCompiler::RestoreLiveRegisters(LocationSummary* locs) { | 1346 void FlowGraphCompiler::RestoreLiveRegisters(LocationSummary* locs) { |
| 1347 // General purpose registers have the highest register number at the | 1347 // General purpose registers have the highest register number at the |
| 1348 // lowest address. | 1348 // lowest address. |
| 1349 for (intptr_t reg_idx = kNumberOfCpuRegisters - 1; reg_idx >= 0; --reg_idx) { | 1349 for (intptr_t reg_idx = kNumberOfCpuRegisters - 1; reg_idx >= 0; --reg_idx) { |
| 1350 Register reg = static_cast<Register>(reg_idx); | 1350 Register reg = static_cast<Register>(reg_idx); |
| 1351 if (locs->live_registers()->ContainsRegister(reg)) { | 1351 if (locs->live_registers()->ContainsRegister(reg)) { |
| 1352 __ popq(reg); | 1352 __ popq(reg); |
| 1353 } | 1353 } |
| 1354 } | 1354 } |
| 1355 | 1355 |
| 1356 const intptr_t xmm_regs_count = locs->live_registers()->xmm_regs_count(); | 1356 const intptr_t xmm_regs_count = locs->live_registers()->fpu_regs_count(); |
| 1357 if (xmm_regs_count > 0) { | 1357 if (xmm_regs_count > 0) { |
| 1358 // XMM registers have the lowest register number at the lowest address. | 1358 // XMM registers have the lowest register number at the lowest address. |
| 1359 intptr_t offset = 0; | 1359 intptr_t offset = 0; |
| 1360 for (intptr_t reg_idx = 0; reg_idx < kNumberOfXmmRegisters; ++reg_idx) { | 1360 for (intptr_t reg_idx = 0; reg_idx < kNumberOfXmmRegisters; ++reg_idx) { |
| 1361 XmmRegister xmm_reg = static_cast<XmmRegister>(reg_idx); | 1361 XmmRegister xmm_reg = static_cast<XmmRegister>(reg_idx); |
| 1362 if (locs->live_registers()->ContainsXmmRegister(xmm_reg)) { | 1362 if (locs->live_registers()->ContainsFpuRegister(xmm_reg)) { |
| 1363 __ movsd(xmm_reg, Address(RSP, offset)); | 1363 __ movsd(xmm_reg, Address(RSP, offset)); |
| 1364 offset += kDoubleSize; | 1364 offset += kDoubleSize; |
| 1365 } | 1365 } |
| 1366 } | 1366 } |
| 1367 ASSERT(offset == (xmm_regs_count * kDoubleSize)); | 1367 ASSERT(offset == (xmm_regs_count * kDoubleSize)); |
| 1368 __ addq(RSP, Immediate(offset)); | 1368 __ addq(RSP, Immediate(offset)); |
| 1369 } | 1369 } |
| 1370 } | 1370 } |
| 1371 | 1371 |
| 1372 | 1372 |
| 1373 struct CidTarget { | |
| 1374 intptr_t cid; | |
| 1375 Function* target; | |
| 1376 intptr_t count; | |
| 1377 CidTarget(intptr_t cid_arg, | |
| 1378 Function* target_arg, | |
| 1379 intptr_t count_arg) | |
| 1380 : cid(cid_arg), target(target_arg), count(count_arg) {} | |
| 1381 }; | |
| 1382 | |
| 1383 | |
| 1384 // Returns 'sorted' array in decreasing count order. | |
| 1385 // The expected number of elements to sort is less than 10. | |
| 1386 static void SortICDataByCount(const ICData& ic_data, | |
| 1387 GrowableArray<CidTarget>* sorted) { | |
| 1388 ASSERT(ic_data.num_args_tested() == 1); | |
| 1389 const intptr_t len = ic_data.NumberOfChecks(); | |
| 1390 sorted->Clear(); | |
| 1391 | |
| 1392 for (int i = 0; i < len; i++) { | |
| 1393 sorted->Add(CidTarget(ic_data.GetReceiverClassIdAt(i), | |
| 1394 &Function::ZoneHandle(ic_data.GetTargetAt(i)), | |
| 1395 ic_data.GetCountAt(i))); | |
| 1396 } | |
| 1397 for (int i = 0; i < len; i++) { | |
| 1398 intptr_t largest_ix = i; | |
| 1399 for (int k = i + 1; k < len; k++) { | |
| 1400 if ((*sorted)[largest_ix].count < (*sorted)[k].count) { | |
| 1401 largest_ix = k; | |
| 1402 } | |
| 1403 } | |
| 1404 if (i != largest_ix) { | |
| 1405 // Swap. | |
| 1406 CidTarget temp = (*sorted)[i]; | |
| 1407 (*sorted)[i] = (*sorted)[largest_ix]; | |
| 1408 (*sorted)[largest_ix] = temp; | |
| 1409 } | |
| 1410 } | |
| 1411 } | |
| 1412 | |
| 1413 | |
| 1414 void FlowGraphCompiler::EmitTestAndCall(const ICData& ic_data, | |
| 1415 Register class_id_reg, | |
| 1416 intptr_t arg_count, | |
| 1417 const Array& arg_names, | |
| 1418 Label* deopt, | |
| 1419 intptr_t deopt_id, | |
| 1420 intptr_t token_index, | |
| 1421 LocationSummary* locs) { | |
| 1422 ASSERT(!ic_data.IsNull() && (ic_data.NumberOfChecks() > 0)); | |
| 1423 Label match_found; | |
| 1424 const intptr_t len = ic_data.NumberOfChecks(); | |
| 1425 GrowableArray<CidTarget> sorted(len); | |
| 1426 SortICDataByCount(ic_data, &sorted); | |
| 1427 for (intptr_t i = 0; i < len; i++) { | |
| 1428 const bool is_last_check = (i == (len - 1)); | |
| 1429 Label next_test; | |
| 1430 assembler()->cmpl(class_id_reg, Immediate(sorted[i].cid)); | |
| 1431 if (is_last_check) { | |
| 1432 assembler()->j(NOT_EQUAL, deopt); | |
| 1433 } else { | |
| 1434 assembler()->j(NOT_EQUAL, &next_test); | |
| 1435 } | |
| 1436 GenerateStaticCall(deopt_id, | |
| 1437 token_index, | |
| 1438 *sorted[i].target, | |
| 1439 arg_count, | |
| 1440 arg_names, | |
| 1441 locs); | |
| 1442 if (!is_last_check) { | |
| 1443 assembler()->jmp(&match_found); | |
| 1444 } | |
| 1445 assembler()->Bind(&next_test); | |
| 1446 } | |
| 1447 assembler()->Bind(&match_found); | |
| 1448 } | |
| 1449 | |
| 1450 | |
| 1451 void FlowGraphCompiler::EmitDoubleCompareBranch(Condition true_condition, | |
| 1452 FpuRegister left, | |
| 1453 FpuRegister right, | |
| 1454 BranchInstr* branch) { | |
| 1455 ASSERT(branch != NULL); | |
| 1456 assembler()->comisd(left, right); | |
| 1457 BlockEntryInstr* nan_result = (true_condition == NOT_EQUAL) ? | |
| 1458 branch->true_successor() : branch->false_successor(); | |
| 1459 assembler()->j(PARITY_EVEN, GetBlockLabel(nan_result)); | |
| 1460 branch->EmitBranchOnCondition(this, true_condition); | |
| 1461 } | |
| 1462 | |
| 1463 | |
| 1464 | |
| 1465 void FlowGraphCompiler::EmitDoubleCompareBool(Condition true_condition, | |
| 1466 FpuRegister left, | |
| 1467 FpuRegister right, | |
| 1468 Register result) { | |
| 1469 assembler()->comisd(left, right); | |
| 1470 Label is_false, is_true, done; | |
| 1471 assembler()->j(PARITY_EVEN, &is_false, Assembler::kNearJump); // NaN false; | |
| 1472 assembler()->j(true_condition, &is_true, Assembler::kNearJump); | |
| 1473 assembler()->Bind(&is_false); | |
| 1474 assembler()->LoadObject(result, Bool::False()); | |
| 1475 assembler()->jmp(&done); | |
| 1476 assembler()->Bind(&is_true); | |
| 1477 assembler()->LoadObject(result, Bool::True()); | |
| 1478 assembler()->Bind(&done); | |
| 1479 } | |
| 1480 | |
| 1481 | |
| 1482 Condition FlowGraphCompiler::FlipCondition(Condition condition) { | |
| 1483 switch (condition) { | |
| 1484 case EQUAL: return EQUAL; | |
| 1485 case NOT_EQUAL: return NOT_EQUAL; | |
| 1486 case LESS: return GREATER; | |
| 1487 case LESS_EQUAL: return GREATER_EQUAL; | |
| 1488 case GREATER: return LESS; | |
| 1489 case GREATER_EQUAL: return LESS_EQUAL; | |
| 1490 case BELOW: return ABOVE; | |
| 1491 case BELOW_EQUAL: return ABOVE_EQUAL; | |
| 1492 case ABOVE: return BELOW; | |
| 1493 case ABOVE_EQUAL: return BELOW_EQUAL; | |
| 1494 default: | |
| 1495 UNIMPLEMENTED(); | |
| 1496 return EQUAL; | |
| 1497 } | |
| 1498 } | |
| 1499 | |
| 1500 | |
| 1501 bool FlowGraphCompiler::EvaluateCondition(Condition condition, | |
| 1502 intptr_t left, | |
| 1503 intptr_t right) { | |
| 1504 const uintptr_t unsigned_left = static_cast<uintptr_t>(left); | |
| 1505 const uintptr_t unsigned_right = static_cast<uintptr_t>(right); | |
| 1506 switch (condition) { | |
| 1507 case EQUAL: return left == right; | |
| 1508 case NOT_EQUAL: return left != right; | |
| 1509 case LESS: return left < right; | |
| 1510 case LESS_EQUAL: return left <= right; | |
| 1511 case GREATER: return left > right; | |
| 1512 case GREATER_EQUAL: return left >= right; | |
| 1513 case BELOW: return unsigned_left < unsigned_right; | |
| 1514 case BELOW_EQUAL: return unsigned_left <= unsigned_right; | |
| 1515 case ABOVE: return unsigned_left > unsigned_right; | |
| 1516 case ABOVE_EQUAL: return unsigned_left >= unsigned_right; | |
| 1517 default: | |
| 1518 UNIMPLEMENTED(); | |
| 1519 return false; | |
| 1520 } | |
| 1521 } | |
| 1522 | |
| 1523 | |
| 1524 FieldAddress FlowGraphCompiler::ElementAddressForIntIndex(intptr_t cid, | |
| 1525 Register array, | |
| 1526 intptr_t index) { | |
| 1527 const int64_t disp = | |
| 1528 static_cast<int64_t>(index) * ElementSizeFor(cid) + DataOffsetFor(cid); | |
| 1529 ASSERT(Utils::IsInt(32, disp)); | |
| 1530 return FieldAddress(array, static_cast<int32_t>(disp)); | |
| 1531 } | |
| 1532 | |
| 1533 | |
| 1534 FieldAddress FlowGraphCompiler::ElementAddressForRegIndex(intptr_t cid, | |
| 1535 Register array, | |
| 1536 Register index) { | |
| 1537 // Note that index is smi-tagged, (i.e, times 2) for all arrays with element | |
| 1538 // size > 1. For Uint8Array and OneByteString the index is expected to be | |
| 1539 // untagged before accessing. | |
| 1540 ASSERT(kSmiTagShift == 1); | |
| 1541 switch (cid) { | |
| 1542 case kArrayCid: | |
| 1543 case kImmutableArrayCid: | |
| 1544 return FieldAddress( | |
| 1545 array, index, TIMES_HALF_WORD_SIZE, Array::data_offset()); | |
| 1546 case kFloat32ArrayCid: | |
| 1547 return FieldAddress(array, index, TIMES_2, Float32Array::data_offset()); | |
| 1548 case kFloat64ArrayCid: | |
| 1549 return FieldAddress(array, index, TIMES_4, Float64Array::data_offset()); | |
| 1550 case kUint8ArrayCid: | |
| 1551 return FieldAddress(array, index, TIMES_1, Uint8Array::data_offset()); | |
| 1552 case kUint8ClampedArrayCid: | |
| 1553 return | |
| 1554 FieldAddress(array, index, TIMES_1, Uint8ClampedArray::data_offset()); | |
| 1555 case kOneByteStringCid: | |
| 1556 return FieldAddress(array, index, TIMES_1, OneByteString::data_offset()); | |
| 1557 case kTwoByteStringCid: | |
| 1558 return FieldAddress(array, index, TIMES_1, TwoByteString::data_offset()); | |
| 1559 default: | |
| 1560 UNIMPLEMENTED(); | |
| 1561 return FieldAddress(SPREG, 0); | |
| 1562 } | |
| 1563 } | |
| 1564 | |
| 1565 | |
| 1373 #undef __ | 1566 #undef __ |
| 1374 #define __ compiler_->assembler()-> | 1567 #define __ compiler_->assembler()-> |
| 1375 | 1568 |
| 1376 | 1569 |
| 1377 void ParallelMoveResolver::EmitMove(int index) { | 1570 void ParallelMoveResolver::EmitMove(int index) { |
| 1378 MoveOperands* move = moves_[index]; | 1571 MoveOperands* move = moves_[index]; |
| 1379 const Location source = move->src(); | 1572 const Location source = move->src(); |
| 1380 const Location destination = move->dest(); | 1573 const Location destination = move->dest(); |
| 1381 | 1574 |
| 1382 if (source.IsRegister()) { | 1575 if (source.IsRegister()) { |
| 1383 if (destination.IsRegister()) { | 1576 if (destination.IsRegister()) { |
| 1384 __ movq(destination.reg(), source.reg()); | 1577 __ movq(destination.reg(), source.reg()); |
| 1385 } else { | 1578 } else { |
| 1386 ASSERT(destination.IsStackSlot()); | 1579 ASSERT(destination.IsStackSlot()); |
| 1387 __ movq(destination.ToStackSlotAddress(), source.reg()); | 1580 __ movq(destination.ToStackSlotAddress(), source.reg()); |
| 1388 } | 1581 } |
| 1389 } else if (source.IsStackSlot()) { | 1582 } else if (source.IsStackSlot()) { |
| 1390 if (destination.IsRegister()) { | 1583 if (destination.IsRegister()) { |
| 1391 __ movq(destination.reg(), source.ToStackSlotAddress()); | 1584 __ movq(destination.reg(), source.ToStackSlotAddress()); |
| 1392 } else { | 1585 } else { |
| 1393 ASSERT(destination.IsStackSlot()); | 1586 ASSERT(destination.IsStackSlot()); |
| 1394 MoveMemoryToMemory(destination.ToStackSlotAddress(), | 1587 MoveMemoryToMemory(destination.ToStackSlotAddress(), |
| 1395 source.ToStackSlotAddress()); | 1588 source.ToStackSlotAddress()); |
| 1396 } | 1589 } |
| 1397 } else if (source.IsXmmRegister()) { | 1590 } else if (source.IsFpuRegister()) { |
| 1398 if (destination.IsXmmRegister()) { | 1591 if (destination.IsFpuRegister()) { |
| 1399 // Optimization manual recommends using MOVAPS for register | 1592 // Optimization manual recommends using MOVAPS for register |
| 1400 // to register moves. | 1593 // to register moves. |
| 1401 __ movaps(destination.xmm_reg(), source.xmm_reg()); | 1594 __ movaps(destination.fpu_reg(), source.fpu_reg()); |
| 1402 } else { | 1595 } else { |
| 1403 ASSERT(destination.IsDoubleStackSlot()); | 1596 ASSERT(destination.IsDoubleStackSlot()); |
| 1404 __ movsd(destination.ToStackSlotAddress(), source.xmm_reg()); | 1597 __ movsd(destination.ToStackSlotAddress(), source.fpu_reg()); |
| 1405 } | 1598 } |
| 1406 } else if (source.IsDoubleStackSlot()) { | 1599 } else if (source.IsDoubleStackSlot()) { |
| 1407 if (destination.IsXmmRegister()) { | 1600 if (destination.IsFpuRegister()) { |
| 1408 __ movsd(destination.xmm_reg(), source.ToStackSlotAddress()); | 1601 __ movsd(destination.fpu_reg(), source.ToStackSlotAddress()); |
| 1409 } else { | 1602 } else { |
| 1410 ASSERT(destination.IsDoubleStackSlot()); | 1603 ASSERT(destination.IsDoubleStackSlot()); |
| 1411 __ movsd(XMM0, source.ToStackSlotAddress()); | 1604 __ movsd(XMM0, source.ToStackSlotAddress()); |
| 1412 __ movsd(destination.ToStackSlotAddress(), XMM0); | 1605 __ movsd(destination.ToStackSlotAddress(), XMM0); |
| 1413 } | 1606 } |
| 1414 } else { | 1607 } else { |
| 1415 ASSERT(source.IsConstant()); | 1608 ASSERT(source.IsConstant()); |
| 1416 if (destination.IsRegister()) { | 1609 if (destination.IsRegister()) { |
| 1417 const Object& constant = source.constant(); | 1610 const Object& constant = source.constant(); |
| 1418 if (constant.IsSmi() && (Smi::Cast(constant).Value() == 0)) { | 1611 if (constant.IsSmi() && (Smi::Cast(constant).Value() == 0)) { |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 1436 const Location destination = move->dest(); | 1629 const Location destination = move->dest(); |
| 1437 | 1630 |
| 1438 if (source.IsRegister() && destination.IsRegister()) { | 1631 if (source.IsRegister() && destination.IsRegister()) { |
| 1439 __ xchgq(destination.reg(), source.reg()); | 1632 __ xchgq(destination.reg(), source.reg()); |
| 1440 } else if (source.IsRegister() && destination.IsStackSlot()) { | 1633 } else if (source.IsRegister() && destination.IsStackSlot()) { |
| 1441 Exchange(source.reg(), destination.ToStackSlotAddress()); | 1634 Exchange(source.reg(), destination.ToStackSlotAddress()); |
| 1442 } else if (source.IsStackSlot() && destination.IsRegister()) { | 1635 } else if (source.IsStackSlot() && destination.IsRegister()) { |
| 1443 Exchange(destination.reg(), source.ToStackSlotAddress()); | 1636 Exchange(destination.reg(), source.ToStackSlotAddress()); |
| 1444 } else if (source.IsStackSlot() && destination.IsStackSlot()) { | 1637 } else if (source.IsStackSlot() && destination.IsStackSlot()) { |
| 1445 Exchange(destination.ToStackSlotAddress(), source.ToStackSlotAddress()); | 1638 Exchange(destination.ToStackSlotAddress(), source.ToStackSlotAddress()); |
| 1446 } else if (source.IsXmmRegister() && destination.IsXmmRegister()) { | 1639 } else if (source.IsFpuRegister() && destination.IsFpuRegister()) { |
| 1447 __ movaps(XMM0, source.xmm_reg()); | 1640 __ movaps(XMM0, source.fpu_reg()); |
| 1448 __ movaps(source.xmm_reg(), destination.xmm_reg()); | 1641 __ movaps(source.fpu_reg(), destination.fpu_reg()); |
| 1449 __ movaps(destination.xmm_reg(), XMM0); | 1642 __ movaps(destination.fpu_reg(), XMM0); |
| 1450 } else if (source.IsXmmRegister() || destination.IsXmmRegister()) { | 1643 } else if (source.IsFpuRegister() || destination.IsFpuRegister()) { |
| 1451 ASSERT(destination.IsDoubleStackSlot() || source.IsDoubleStackSlot()); | 1644 ASSERT(destination.IsDoubleStackSlot() || source.IsDoubleStackSlot()); |
| 1452 XmmRegister reg = source.IsXmmRegister() ? source.xmm_reg() | 1645 XmmRegister reg = source.IsFpuRegister() ? source.fpu_reg() |
| 1453 : destination.xmm_reg(); | 1646 : destination.fpu_reg(); |
| 1454 Address slot_address = source.IsXmmRegister() | 1647 Address slot_address = source.IsFpuRegister() |
| 1455 ? destination.ToStackSlotAddress() | 1648 ? destination.ToStackSlotAddress() |
| 1456 : source.ToStackSlotAddress(); | 1649 : source.ToStackSlotAddress(); |
| 1457 | 1650 |
| 1458 __ movsd(XMM0, slot_address); | 1651 __ movsd(XMM0, slot_address); |
| 1459 __ movsd(slot_address, reg); | 1652 __ movsd(slot_address, reg); |
| 1460 __ movaps(reg, XMM0); | 1653 __ movaps(reg, XMM0); |
| 1461 } else { | 1654 } else { |
| 1462 UNREACHABLE(); | 1655 UNREACHABLE(); |
| 1463 } | 1656 } |
| 1464 | 1657 |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1499 void ParallelMoveResolver::Exchange(const Address& mem1, const Address& mem2) { | 1692 void ParallelMoveResolver::Exchange(const Address& mem1, const Address& mem2) { |
| 1500 __ Exchange(mem1, mem2); | 1693 __ Exchange(mem1, mem2); |
| 1501 } | 1694 } |
| 1502 | 1695 |
| 1503 | 1696 |
| 1504 #undef __ | 1697 #undef __ |
| 1505 | 1698 |
| 1506 } // namespace dart | 1699 } // namespace dart |
| 1507 | 1700 |
| 1508 #endif // defined TARGET_ARCH_X64 | 1701 #endif // defined TARGET_ARCH_X64 |
| OLD | NEW |