10511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com// Copyright 2011 the V8 project authors. All rights reserved.
23484964a86451e86dcf04be9bd8c0d76ee04f081rossberg@chromium.org// Use of this source code is governed by a BSD-style license that can be
33484964a86451e86dcf04be9bd8c0d76ee04f081rossberg@chromium.org// found in the LICENSE file.
40511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com
5196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/v8.h"
6ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org
793a47f4837f2137c8d8349250fd8e91da3108126jkummerow@chromium.org#if V8_TARGET_ARCH_IA32
8c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org
9196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/ia32/lithium-codegen-ia32.h"
104b0feeef5d01dbc2948080b4f69daa37e1083461machenbach@chromium.org#include "src/ia32/lithium-gap-resolver-ia32.h"
110511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com
120511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.comnamespace v8 {
130511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.comnamespace internal {
140511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com
150511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.comLGapResolver::LGapResolver(LCodeGen* owner)
160ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org    : cgen_(owner),
177028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org      moves_(32, owner->zone()),
180ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org      source_uses_(),
190ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org      destination_uses_(),
200ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org      spilled_register_(-1) {}
210511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com
220511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com
230511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.comvoid LGapResolver::Resolve(LParallelMove* parallel_move) {
24e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(HasBeenReset());
250511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  // Build up a worklist of moves.
260511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  BuildInitialMoveList(parallel_move);
270511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com
280511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  for (int i = 0; i < moves_.length(); ++i) {
290511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    LMoveOperands move = moves_[i];
300511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    // Skip constants to perform them last.  They don't block other moves
310511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    // and skipping such moves with register destinations keeps those
320511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    // registers free for the whole algorithm.
330511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    if (!move.IsEliminated() && !move.source()->IsConstantOperand()) {
340511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com      PerformMove(i);
350511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    }
360511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  }
370511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com
380511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  // Perform the moves with constant sources.
390511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  for (int i = 0; i < moves_.length(); ++i) {
400511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    if (!moves_[i].IsEliminated()) {
41e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org      DCHECK(moves_[i].source()->IsConstantOperand());
420511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com      EmitMove(i);
430511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    }
440511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  }
450511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com
460511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  Finish();
47e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(HasBeenReset());
480511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com}
490511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com
500511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com
510511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.comvoid LGapResolver::BuildInitialMoveList(LParallelMove* parallel_move) {
520511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  // Perform a linear sweep of the moves to add them to the initial list of
530511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  // moves to perform, ignoring any move that is redundant (the source is
540511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  // the same as the destination, the destination is ignored and
550511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  // unallocated, or the move was already eliminated).
560511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  const ZoneList<LMoveOperands>* moves = parallel_move->move_operands();
570511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  for (int i = 0; i < moves->length(); ++i) {
580511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    LMoveOperands move = moves->at(i);
590511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    if (!move.IsRedundant()) AddMove(move);
600511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  }
610511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  Verify();
620511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com}
630511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com
640511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com
650511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.comvoid LGapResolver::PerformMove(int index) {
660511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  // Each call to this function performs a move and deletes it from the move
670511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  // graph.  We first recursively perform any move blocking this one.  We
680511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  // mark a move as "pending" on entry to PerformMove in order to detect
690511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  // cycles in the move graph.  We use operand swaps to resolve cycles,
700511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  // which means that a call to PerformMove could change any source operand
710511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  // in the move graph.
720511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com
73e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(!moves_[index].IsPending());
74e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(!moves_[index].IsRedundant());
750511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com
760511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  // Clear this move's destination to indicate a pending move.  The actual
770511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  // destination is saved on the side.
78e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(moves_[index].source() != NULL);  // Or else it will look eliminated.
790511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  LOperand* destination = moves_[index].destination();
800511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  moves_[index].set_destination(NULL);
810511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com
820511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  // Perform a depth-first traversal of the move graph to resolve
830511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  // dependencies.  Any unperformed, unpending move with a source the same
840511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  // as this one's destination blocks this one so recursively perform all
850511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  // such moves.
860511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  for (int i = 0; i < moves_.length(); ++i) {
870511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    LMoveOperands other_move = moves_[i];
880511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    if (other_move.Blocks(destination) && !other_move.IsPending()) {
890511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com      // Though PerformMove can change any source operand in the move graph,
900511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com      // this call cannot create a blocking move via a swap (this loop does
910511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com      // not miss any).  Assume there is a non-blocking move with source A
920511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com      // and this move is blocked on source B and there is a swap of A and
930511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com      // B.  Then A and B must be involved in the same cycle (or they would
940511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com      // not be swapped).  Since this move's destination is B and there is
950511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com      // only a single incoming edge to an operand, this move must also be
960511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com      // involved in the same cycle.  In that case, the blocking move will
970511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com      // be created but will be "pending" when we return from PerformMove.
980511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com      PerformMove(i);
990511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    }
1000511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  }
1010511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com
1020511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  // We are about to resolve this move and don't need it marked as
1030511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  // pending, so restore its destination.
1040511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  moves_[index].set_destination(destination);
1050511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com
1060511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  // This move's source may have changed due to swaps to resolve cycles and
1070511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  // so it may now be the last move in the cycle.  If so remove it.
1080511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  if (moves_[index].source()->Equals(destination)) {
1090511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    RemoveMove(index);
1100511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    return;
1110511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  }
1120511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com
1130511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  // The move may be blocked on a (at most one) pending move, in which case
1140511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  // we have a cycle.  Search for such a blocking move and perform a swap to
1150511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  // resolve it.
1160511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  for (int i = 0; i < moves_.length(); ++i) {
1170511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    LMoveOperands other_move = moves_[i];
1180511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    if (other_move.Blocks(destination)) {
119e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org      DCHECK(other_move.IsPending());
1200511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com      EmitSwap(index);
1210511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com      return;
1220511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    }
1230511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  }
1240511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com
1250511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  // This move is not blocked.
1260511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  EmitMove(index);
1270511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com}
1280511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com
1290511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com
1300511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.comvoid LGapResolver::AddMove(LMoveOperands move) {
1310511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  LOperand* source = move.source();
1320511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  if (source->IsRegister()) ++source_uses_[source->index()];
1330511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com
1340511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  LOperand* destination = move.destination();
1350511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  if (destination->IsRegister()) ++destination_uses_[destination->index()];
1360511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com
1377028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org  moves_.Add(move, cgen_->zone());
1380511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com}
1390511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com
1400511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com
1410511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.comvoid LGapResolver::RemoveMove(int index) {
1420511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  LOperand* source = moves_[index].source();
1430511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  if (source->IsRegister()) {
1440511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    --source_uses_[source->index()];
145e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(source_uses_[source->index()] >= 0);
1460511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  }
1470511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com
1480511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  LOperand* destination = moves_[index].destination();
1490511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  if (destination->IsRegister()) {
1500511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    --destination_uses_[destination->index()];
151e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(destination_uses_[destination->index()] >= 0);
1520511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  }
1530511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com
1540511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  moves_[index].Eliminate();
1550511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com}
1560511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com
1570511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com
1580511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.comint LGapResolver::CountSourceUses(LOperand* operand) {
1590511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  int count = 0;
1600511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  for (int i = 0; i < moves_.length(); ++i) {
1610511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    if (!moves_[i].IsEliminated() && moves_[i].source()->Equals(operand)) {
1620511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com      ++count;
1630511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    }
1640511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  }
1650511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  return count;
1660511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com}
1670511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com
1680511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com
1690511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.comRegister LGapResolver::GetFreeRegisterNot(Register reg) {
1700511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  int skip_index = reg.is(no_reg) ? -1 : Register::ToAllocationIndex(reg);
171a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  for (int i = 0; i < Register::NumAllocatableRegisters(); ++i) {
1720511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    if (source_uses_[i] == 0 && destination_uses_[i] > 0 && i != skip_index) {
1730511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com      return Register::FromAllocationIndex(i);
1740511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    }
1750511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  }
1760511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  return no_reg;
1770511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com}
1780511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com
1790511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com
1800511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.combool LGapResolver::HasBeenReset() {
1810511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  if (!moves_.is_empty()) return false;
1820511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  if (spilled_register_ >= 0) return false;
1830511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com
184a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  for (int i = 0; i < Register::NumAllocatableRegisters(); ++i) {
1850511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    if (source_uses_[i] != 0) return false;
1860511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    if (destination_uses_[i] != 0) return false;
1870511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  }
1880511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  return true;
1890511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com}
1900511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com
1910511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com
1920511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.comvoid LGapResolver::Verify() {
193e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org#ifdef ENABLE_SLOW_DCHECKS
1940511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  // No operand should be the destination for more than one move.
1950511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  for (int i = 0; i < moves_.length(); ++i) {
1960511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    LOperand* destination = moves_[i].destination();
1970511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    for (int j = i + 1; j < moves_.length(); ++j) {
198e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org      SLOW_DCHECK(!destination->Equals(moves_[j].destination()));
1990511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    }
2000511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  }
2010511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com#endif
2020511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com}
2030511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com
2040511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com
2050511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com#define __ ACCESS_MASM(cgen_->masm())
2060511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com
2070511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.comvoid LGapResolver::Finish() {
2080511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  if (spilled_register_ >= 0) {
2090511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    __ pop(Register::FromAllocationIndex(spilled_register_));
2100511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    spilled_register_ = -1;
2110511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  }
2120511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  moves_.Rewind(0);
2130511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com}
2140511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com
2150511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com
2160511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.comvoid LGapResolver::EnsureRestored(LOperand* operand) {
2170511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  if (operand->IsRegister() && operand->index() == spilled_register_) {
2180511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    __ pop(Register::FromAllocationIndex(spilled_register_));
2190511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    spilled_register_ = -1;
2200511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  }
2210511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com}
2220511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com
2230511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com
2240511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.comRegister LGapResolver::EnsureTempRegister() {
2250511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  // 1. We may have already spilled to create a temp register.
2260511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  if (spilled_register_ >= 0) {
2270511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    return Register::FromAllocationIndex(spilled_register_);
2280511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  }
2290511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com
2300511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  // 2. We may have a free register that we can use without spilling.
2310511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  Register free = GetFreeRegisterNot(no_reg);
2320511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  if (!free.is(no_reg)) return free;
2330511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com
2340511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  // 3. Prefer to spill a register that is not used in any remaining move
2350511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  // because it will not need to be restored until the end.
236a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  for (int i = 0; i < Register::NumAllocatableRegisters(); ++i) {
2370511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    if (source_uses_[i] == 0 && destination_uses_[i] == 0) {
2380511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com      Register scratch = Register::FromAllocationIndex(i);
2390511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com      __ push(scratch);
2400511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com      spilled_register_ = i;
2410511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com      return scratch;
2420511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    }
2430511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  }
2440511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com
2450511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  // 4. Use an arbitrary register.  Register 0 is as arbitrary as any other.
2460511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  Register scratch = Register::FromAllocationIndex(0);
2470511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  __ push(scratch);
2480511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  spilled_register_ = 0;
2490511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  return scratch;
2500511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com}
2510511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com
2520511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com
2530511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.comvoid LGapResolver::EmitMove(int index) {
2540511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  LOperand* source = moves_[index].source();
2550511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  LOperand* destination = moves_[index].destination();
2560511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  EnsureRestored(source);
2570511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  EnsureRestored(destination);
2580511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com
2590511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  // Dispatch on the source and destination operand kinds.  Not all
2600511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  // combinations are possible.
2610511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  if (source->IsRegister()) {
262e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(destination->IsRegister() || destination->IsStackSlot());
2630511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    Register src = cgen_->ToRegister(source);
2640511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    Operand dst = cgen_->ToOperand(destination);
2650511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    __ mov(dst, src);
2660511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com
2670511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  } else if (source->IsStackSlot()) {
268e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(destination->IsRegister() || destination->IsStackSlot());
2690511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    Operand src = cgen_->ToOperand(source);
2700511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    if (destination->IsRegister()) {
2710511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com      Register dst = cgen_->ToRegister(destination);
2720511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com      __ mov(dst, src);
2730511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    } else {
2740511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com      // Spill on demand to use a temporary register for memory-to-memory
2750511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com      // moves.
2760511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com      Register tmp = EnsureTempRegister();
2770511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com      Operand dst = cgen_->ToOperand(destination);
2780511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com      __ mov(tmp, src);
2790511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com      __ mov(dst, tmp);
2800511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    }
2810511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com
2820511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  } else if (source->IsConstantOperand()) {
283bf0c820d028452571c8c744ddd212c32c6d6a996danno@chromium.org    LConstantOperand* constant_source = LConstantOperand::cast(source);
2846db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org    if (destination->IsRegister()) {
2856db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org      Register dst = cgen_->ToRegister(destination);
286fb732b17922ea75830be4db6b80534c4827d8a55jkummerow@chromium.org      Representation r = cgen_->IsSmi(constant_source)
287fb732b17922ea75830be4db6b80534c4827d8a55jkummerow@chromium.org          ? Representation::Smi() : Representation::Integer32();
288fb732b17922ea75830be4db6b80534c4827d8a55jkummerow@chromium.org      if (cgen_->IsInteger32(constant_source)) {
289a221880197f38ff22d942851060daffa5d036bdfmachenbach@chromium.org        __ Move(dst, cgen_->ToImmediate(constant_source, r));
290bf0c820d028452571c8c744ddd212c32c6d6a996danno@chromium.org      } else {
291bf0c820d028452571c8c744ddd212c32c6d6a996danno@chromium.org        __ LoadObject(dst, cgen_->ToHandle(constant_source));
292bf0c820d028452571c8c744ddd212c32c6d6a996danno@chromium.org      }
293e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org    } else if (destination->IsDoubleRegister()) {
294e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org      double v = cgen_->ToDouble(constant_source);
295e20e19efeef112c26d0e63b1e5118e695b42d855machenbach@chromium.org      uint64_t int_val = bit_cast<uint64_t, double>(v);
296e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org      int32_t lower = static_cast<int32_t>(int_val);
297e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org      int32_t upper = static_cast<int32_t>(int_val >> kBitsPerInt);
2983c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org      XMMRegister dst = cgen_->ToDoubleRegister(destination);
2993c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org      if (int_val == 0) {
3003c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org        __ xorps(dst, dst);
301e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org      } else {
302e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org        __ push(Immediate(upper));
303e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org        __ push(Immediate(lower));
3043c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org        __ movsd(dst, Operand(esp, 0));
305e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org        __ add(esp, Immediate(kDoubleSize));
306e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org      }
3076db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org    } else {
308e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org      DCHECK(destination->IsStackSlot());
3096db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org      Operand dst = cgen_->ToOperand(destination);
310fb732b17922ea75830be4db6b80534c4827d8a55jkummerow@chromium.org      Representation r = cgen_->IsSmi(constant_source)
311fb732b17922ea75830be4db6b80534c4827d8a55jkummerow@chromium.org          ? Representation::Smi() : Representation::Integer32();
312fb732b17922ea75830be4db6b80534c4827d8a55jkummerow@chromium.org      if (cgen_->IsInteger32(constant_source)) {
313a221880197f38ff22d942851060daffa5d036bdfmachenbach@chromium.org        __ Move(dst, cgen_->ToImmediate(constant_source, r));
314bf0c820d028452571c8c744ddd212c32c6d6a996danno@chromium.org      } else {
315bf0c820d028452571c8c744ddd212c32c6d6a996danno@chromium.org        Register tmp = EnsureTempRegister();
316bf0c820d028452571c8c744ddd212c32c6d6a996danno@chromium.org        __ LoadObject(tmp, cgen_->ToHandle(constant_source));
317bf0c820d028452571c8c744ddd212c32c6d6a996danno@chromium.org        __ mov(dst, tmp);
318bf0c820d028452571c8c744ddd212c32c6d6a996danno@chromium.org      }
3196db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org    }
3200511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com
3210511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  } else if (source->IsDoubleRegister()) {
3223c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    XMMRegister src = cgen_->ToDoubleRegister(source);
3233c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    if (destination->IsDoubleRegister()) {
3243c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org      XMMRegister dst = cgen_->ToDoubleRegister(destination);
3253c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org      __ movaps(dst, src);
326dcebac0f4c6c0da579b7cc91a0cbba8f3c820c8dricow@chromium.org    } else {
327e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org      DCHECK(destination->IsDoubleStackSlot());
3284121f23c2a08f8ef03858df1477b81a0450b94a0ulan@chromium.org      Operand dst = cgen_->ToOperand(destination);
3293c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org      __ movsd(dst, src);
330dcebac0f4c6c0da579b7cc91a0cbba8f3c820c8dricow@chromium.org    }
3310511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  } else if (source->IsDoubleStackSlot()) {
332e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(destination->IsDoubleRegister() ||
3333c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org           destination->IsDoubleStackSlot());
3343c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    Operand src = cgen_->ToOperand(source);
3353c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    if (destination->IsDoubleRegister()) {
3363c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org      XMMRegister dst = cgen_->ToDoubleRegister(destination);
3373c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org      __ movsd(dst, src);
3380511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    } else {
3393c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org      // We rely on having xmm0 available as a fixed scratch register.
3403c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org      Operand dst = cgen_->ToOperand(destination);
3413c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org      __ movsd(xmm0, src);
3423c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org      __ movsd(dst, xmm0);
3430511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    }
3440511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  } else {
3450511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    UNREACHABLE();
3460511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  }
3470511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com
3480511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  RemoveMove(index);
3490511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com}
3500511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com
3510511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com
3520511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.comvoid LGapResolver::EmitSwap(int index) {
3530511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  LOperand* source = moves_[index].source();
3540511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  LOperand* destination = moves_[index].destination();
3550511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  EnsureRestored(source);
3560511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  EnsureRestored(destination);
3570511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com
3580511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  // Dispatch on the source and destination operand kinds.  Not all
3590511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  // combinations are possible.
3600511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  if (source->IsRegister() && destination->IsRegister()) {
3610511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    // Register-register.
3620511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    Register src = cgen_->ToRegister(source);
3630511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    Register dst = cgen_->ToRegister(destination);
3640511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    __ xchg(dst, src);
3650511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com
3660511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  } else if ((source->IsRegister() && destination->IsStackSlot()) ||
3670511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com             (source->IsStackSlot() && destination->IsRegister())) {
3680511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    // Register-memory.  Use a free register as a temp if possible.  Do not
3690511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    // spill on demand because the simple spill implementation cannot avoid
3700511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    // spilling src at this point.
3710511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    Register tmp = GetFreeRegisterNot(no_reg);
3720511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    Register reg =
3730511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com        cgen_->ToRegister(source->IsRegister() ? source : destination);
3740511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    Operand mem =
3750511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com        cgen_->ToOperand(source->IsRegister() ? destination : source);
3760511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    if (tmp.is(no_reg)) {
3770511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com      __ xor_(reg, mem);
3780511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com      __ xor_(mem, reg);
3790511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com      __ xor_(reg, mem);
3800511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    } else {
3810511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com      __ mov(tmp, mem);
3820511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com      __ mov(mem, reg);
3830511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com      __ mov(reg, tmp);
3840511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    }
3850511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com
3860511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  } else if (source->IsStackSlot() && destination->IsStackSlot()) {
3870511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    // Memory-memory.  Spill on demand to use a temporary.  If there is a
3880511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    // free register after that, use it as a second temporary.
3890511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    Register tmp0 = EnsureTempRegister();
3900511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    Register tmp1 = GetFreeRegisterNot(tmp0);
3910511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    Operand src = cgen_->ToOperand(source);
3920511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    Operand dst = cgen_->ToOperand(destination);
3930511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    if (tmp1.is(no_reg)) {
3940511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com      // Only one temp register available to us.
3950511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com      __ mov(tmp0, dst);
3960511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com      __ xor_(tmp0, src);
3970511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com      __ xor_(src, tmp0);
3980511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com      __ xor_(tmp0, src);
3990511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com      __ mov(dst, tmp0);
4000511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    } else {
4010511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com      __ mov(tmp0, dst);
4020511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com      __ mov(tmp1, src);
4030511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com      __ mov(dst, tmp1);
4040511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com      __ mov(src, tmp0);
4050511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    }
406dcebac0f4c6c0da579b7cc91a0cbba8f3c820c8dricow@chromium.org  } else if (source->IsDoubleRegister() && destination->IsDoubleRegister()) {
407dcebac0f4c6c0da579b7cc91a0cbba8f3c820c8dricow@chromium.org    // XMM register-register swap. We rely on having xmm0
408dcebac0f4c6c0da579b7cc91a0cbba8f3c820c8dricow@chromium.org    // available as a fixed scratch register.
409dcebac0f4c6c0da579b7cc91a0cbba8f3c820c8dricow@chromium.org    XMMRegister src = cgen_->ToDoubleRegister(source);
410dcebac0f4c6c0da579b7cc91a0cbba8f3c820c8dricow@chromium.org    XMMRegister dst = cgen_->ToDoubleRegister(destination);
411dcebac0f4c6c0da579b7cc91a0cbba8f3c820c8dricow@chromium.org    __ movaps(xmm0, src);
412dcebac0f4c6c0da579b7cc91a0cbba8f3c820c8dricow@chromium.org    __ movaps(src, dst);
413dcebac0f4c6c0da579b7cc91a0cbba8f3c820c8dricow@chromium.org    __ movaps(dst, xmm0);
4140511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  } else if (source->IsDoubleRegister() || destination->IsDoubleRegister()) {
415dcebac0f4c6c0da579b7cc91a0cbba8f3c820c8dricow@chromium.org    // XMM register-memory swap.  We rely on having xmm0
4160511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    // available as a fixed scratch register.
417e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(source->IsDoubleStackSlot() || destination->IsDoubleStackSlot());
4180511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    XMMRegister reg = cgen_->ToDoubleRegister(source->IsDoubleRegister()
419e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org                                              ? source
420e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org                                              : destination);
4210511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    Operand other =
4220511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com        cgen_->ToOperand(source->IsDoubleRegister() ? destination : source);
4230fdb2a65d0f07bb7f6d6ce2f8337e00e5c9c323dbmeurer@chromium.org    __ movsd(xmm0, other);
4240fdb2a65d0f07bb7f6d6ce2f8337e00e5c9c323dbmeurer@chromium.org    __ movsd(other, reg);
425057bd50c2c2d15923523777a296cddee5c8ba63bverwaest@chromium.org    __ movaps(reg, xmm0);
4260511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  } else if (source->IsDoubleStackSlot() && destination->IsDoubleStackSlot()) {
4270511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    // Double-width memory-to-memory.  Spill on demand to use a general
4280511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    // purpose temporary register and also rely on having xmm0 available as
4290511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    // a fixed scratch register.
4300511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    Register tmp = EnsureTempRegister();
4310511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    Operand src0 = cgen_->ToOperand(source);
4320511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    Operand src1 = cgen_->HighOperand(source);
4330511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    Operand dst0 = cgen_->ToOperand(destination);
4340511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    Operand dst1 = cgen_->HighOperand(destination);
4350fdb2a65d0f07bb7f6d6ce2f8337e00e5c9c323dbmeurer@chromium.org    __ movsd(xmm0, dst0);  // Save destination in xmm0.
4360511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    __ mov(tmp, src0);  // Then use tmp to copy source to destination.
4370511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    __ mov(dst0, tmp);
4380511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    __ mov(tmp, src1);
4390511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    __ mov(dst1, tmp);
4400fdb2a65d0f07bb7f6d6ce2f8337e00e5c9c323dbmeurer@chromium.org    __ movsd(src0, xmm0);
4410511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com
4420511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  } else {
4430511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    // No other combinations are possible.
4440511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    UNREACHABLE();
4450511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  }
4460511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com
4470511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  // The swap of source and destination has executed a move from source to
4480511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  // destination.
4490511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  RemoveMove(index);
4500511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com
4510511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  // Any unperformed (including pending) move with a source of either
4520511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  // this move's source or destination needs to have their source
4530511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  // changed to reflect the state of affairs after the swap.
4540511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  for (int i = 0; i < moves_.length(); ++i) {
4550511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    LMoveOperands other_move = moves_[i];
4560511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    if (other_move.Blocks(source)) {
4570511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com      moves_[i].set_source(destination);
4580511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    } else if (other_move.Blocks(destination)) {
4590511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com      moves_[i].set_source(source);
4600511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    }
4610511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  }
4620511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com
4630511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  // In addition to swapping the actual uses as sources, we need to update
4640511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  // the use counts.
4650511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  if (source->IsRegister() && destination->IsRegister()) {
4660511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    int temp = source_uses_[source->index()];
4670511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    source_uses_[source->index()] = source_uses_[destination->index()];
4680511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    source_uses_[destination->index()] = temp;
4690511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  } else if (source->IsRegister()) {
4700511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    // We don't have use counts for non-register operands like destination.
4710511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    // Compute those counts now.
4720511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    source_uses_[source->index()] = CountSourceUses(source);
4730511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  } else if (destination->IsRegister()) {
4740511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    source_uses_[destination->index()] = CountSourceUses(destination);
4750511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  }
4760511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com}
4770511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com
4780511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com#undef __
4790511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com
4800511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com} }  // namespace v8::internal
481c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org
482c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org#endif  // V8_TARGET_ARCH_IA32
483