13ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Copyright 2012 the V8 project authors. All rights reserved.
23ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Redistribution and use in source and binary forms, with or without
33ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// modification, are permitted provided that the following conditions are
43ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// met:
53ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//
63ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//     * Redistributions of source code must retain the above copyright
73ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//       notice, this list of conditions and the following disclaimer.
83ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//     * Redistributions in binary form must reproduce the above
93ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//       copyright notice, this list of conditions and the following
103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//       disclaimer in the documentation and/or other materials provided
113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//       with the distribution.
123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//     * Neither the name of Google Inc. nor the names of its
133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//       contributors may be used to endorse or promote products derived
143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//       from this software without specific prior written permission.
153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//
163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#include "v8.h"
293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#include "mips/lithium-gap-resolver-mips.h"
313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#include "mips/lithium-codegen-mips.h"
323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochnamespace v8 {
343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochnamespace internal {
353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
363ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochLGapResolver::LGapResolver(LCodeGen* owner)
373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    : cgen_(owner),
383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      moves_(32),
393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      root_index_(0),
403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      in_cycle_(false),
413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      saved_destination_(NULL) {}
423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LGapResolver::Resolve(LParallelMove* parallel_move) {
453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(moves_.is_empty());
463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Build up a worklist of moves.
473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  BuildInitialMoveList(parallel_move);
483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  for (int i = 0; i < moves_.length(); ++i) {
503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    LMoveOperands move = moves_[i];
513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Skip constants to perform them last.  They don't block other moves
523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // and skipping such moves with register destinations keeps those
533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // registers free for the whole algorithm.
543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (!move.IsEliminated() && !move.source()->IsConstantOperand()) {
553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      root_index_ = i;  // Any cycle is found when by reaching this move again.
563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      PerformMove(i);
573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (in_cycle_) {
583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        RestoreValue();
593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Perform the moves with constant sources.
643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  for (int i = 0; i < moves_.length(); ++i) {
653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (!moves_[i].IsEliminated()) {
663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ASSERT(moves_[i].source()->IsConstantOperand());
673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      EmitMove(i);
683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  moves_.Rewind(0);
723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LGapResolver::BuildInitialMoveList(LParallelMove* parallel_move) {
763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Perform a linear sweep of the moves to add them to the initial list of
773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // moves to perform, ignoring any move that is redundant (the source is
783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // the same as the destination, the destination is ignored and
793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // unallocated, or the move was already eliminated).
803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  const ZoneList<LMoveOperands>* moves = parallel_move->move_operands();
813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  for (int i = 0; i < moves->length(); ++i) {
823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    LMoveOperands move = moves->at(i);
833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (!move.IsRedundant()) moves_.Add(move);
843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Verify();
863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LGapResolver::PerformMove(int index) {
903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Each call to this function performs a move and deletes it from the move
913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // graph.  We first recursively perform any move blocking this one.  We
923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // mark a move as "pending" on entry to PerformMove in order to detect
933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // cycles in the move graph.
943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // We can only find a cycle, when doing a depth-first traversal of moves,
963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // be encountering the starting move again. So by spilling the source of
973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // the starting move, we break the cycle.  All moves are then unblocked,
983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // and the starting move is completed by writing the spilled value to
993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // its destination.  All other moves from the spilled source have been
1003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // completed prior to breaking the cycle.
1013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // An additional complication is that moves to MemOperands with large
1023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // offsets (more than 1K or 4K) require us to spill this spilled value to
1033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // the stack, to free up the register.
1043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(!moves_[index].IsPending());
1053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(!moves_[index].IsRedundant());
1063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Clear this move's destination to indicate a pending move.  The actual
1083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // destination is saved in a stack allocated local.  Multiple moves can
1093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // be pending because this function is recursive.
1103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(moves_[index].source() != NULL);  // Or else it will look eliminated.
1113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LOperand* destination = moves_[index].destination();
1123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  moves_[index].set_destination(NULL);
1133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Perform a depth-first traversal of the move graph to resolve
1153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // dependencies.  Any unperformed, unpending move with a source the same
1163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // as this one's destination blocks this one so recursively perform all
1173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // such moves.
1183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  for (int i = 0; i < moves_.length(); ++i) {
1193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    LMoveOperands other_move = moves_[i];
1203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (other_move.Blocks(destination) && !other_move.IsPending()) {
1213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      PerformMove(i);
1223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // If there is a blocking, pending move it must be moves_[root_index_]
1233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // and all other moves with the same source as moves_[root_index_] are
1243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // sucessfully executed (because they are cycle-free) by this loop.
1253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
1263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
1273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // We are about to resolve this move and don't need it marked as
1293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // pending, so restore its destination.
1303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  moves_[index].set_destination(destination);
1313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // The move may be blocked on a pending move, which must be the starting move.
1333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // In this case, we have a cycle, and we save the source of this move to
1343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // a scratch register to break it.
1353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LMoveOperands other_move = moves_[root_index_];
1363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (other_move.Blocks(destination)) {
1373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(other_move.IsPending());
1383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    BreakCycle(index);
1393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return;
1403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
1413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // This move is no longer blocked.
1433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  EmitMove(index);
1443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
1453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LGapResolver::Verify() {
1483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#ifdef ENABLE_SLOW_ASSERTS
1493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // No operand should be the destination for more than one move.
1503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  for (int i = 0; i < moves_.length(); ++i) {
1513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    LOperand* destination = moves_[i].destination();
1523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    for (int j = i + 1; j < moves_.length(); ++j) {
1533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      SLOW_ASSERT(!destination->Equals(moves_[j].destination()));
1543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
1553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
1563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#endif
1573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
1583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#define __ ACCESS_MASM(cgen_->masm())
1603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LGapResolver::BreakCycle(int index) {
1623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // We save in a register the value that should end up in the source of
1633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // moves_[root_index].  After performing all moves in the tree rooted
1643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // in that move, we save the value to that source.
1653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(moves_[index].destination()->Equals(moves_[root_index_].source()));
1663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(!in_cycle_);
1673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  in_cycle_ = true;
1683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LOperand* source = moves_[index].source();
1693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  saved_destination_ = moves_[index].destination();
1703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (source->IsRegister()) {
171db1b4389239a7132c9cde0915dbd3f775dc1027aBen Murdoch    __ mov(kLithiumScratchReg, cgen_->ToRegister(source));
1723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else if (source->IsStackSlot()) {
173db1b4389239a7132c9cde0915dbd3f775dc1027aBen Murdoch    __ lw(kLithiumScratchReg, cgen_->ToMemOperand(source));
1743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else if (source->IsDoubleRegister()) {
1753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ mov_d(kLithiumScratchDouble, cgen_->ToDoubleRegister(source));
1763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else if (source->IsDoubleStackSlot()) {
1773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ ldc1(kLithiumScratchDouble, cgen_->ToMemOperand(source));
1783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
1793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    UNREACHABLE();
1803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
1813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // This move will be done by restoring the saved value to the destination.
1823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  moves_[index].Eliminate();
1833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
1843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LGapResolver::RestoreValue() {
1873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(in_cycle_);
1883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(saved_destination_ != NULL);
1893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
190db1b4389239a7132c9cde0915dbd3f775dc1027aBen Murdoch  // Spilled value is in kLithiumScratchReg or kLithiumScratchDouble.
1913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (saved_destination_->IsRegister()) {
192db1b4389239a7132c9cde0915dbd3f775dc1027aBen Murdoch    __ mov(cgen_->ToRegister(saved_destination_), kLithiumScratchReg);
1933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else if (saved_destination_->IsStackSlot()) {
194db1b4389239a7132c9cde0915dbd3f775dc1027aBen Murdoch    __ sw(kLithiumScratchReg, cgen_->ToMemOperand(saved_destination_));
1953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else if (saved_destination_->IsDoubleRegister()) {
1963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ mov_d(cgen_->ToDoubleRegister(saved_destination_),
1973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            kLithiumScratchDouble);
1983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else if (saved_destination_->IsDoubleStackSlot()) {
1993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ sdc1(kLithiumScratchDouble,
2003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            cgen_->ToMemOperand(saved_destination_));
2013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
2023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    UNREACHABLE();
2033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
2043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  in_cycle_ = false;
2063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  saved_destination_ = NULL;
2073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
2083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LGapResolver::EmitMove(int index) {
2113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LOperand* source = moves_[index].source();
2123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LOperand* destination = moves_[index].destination();
2133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Dispatch on the source and destination operand kinds.  Not all
2153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // combinations are possible.
2163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (source->IsRegister()) {
2183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register source_register = cgen_->ToRegister(source);
2193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (destination->IsRegister()) {
2203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ mov(cgen_->ToRegister(destination), source_register);
2213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
2223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ASSERT(destination->IsStackSlot());
2233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ sw(source_register, cgen_->ToMemOperand(destination));
2243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
2253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else if (source->IsStackSlot()) {
2273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    MemOperand source_operand = cgen_->ToMemOperand(source);
2283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (destination->IsRegister()) {
2293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ lw(cgen_->ToRegister(destination), source_operand);
2303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
2313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ASSERT(destination->IsStackSlot());
2323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      MemOperand destination_operand = cgen_->ToMemOperand(destination);
2333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (in_cycle_) {
2343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        if (!destination_operand.OffsetIsInt16Encodable()) {
2353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          // 'at' is overwritten while saving the value to the destination.
2363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          // Therefore we can't use 'at'.  It is OK if the read from the source
2373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          // destroys 'at', since that happens before the value is read.
2383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          // This uses only a single reg of the double reg-pair.
2393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          __ lwc1(kLithiumScratchDouble, source_operand);
2403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          __ swc1(kLithiumScratchDouble, destination_operand);
2413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        } else {
2423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          __ lw(at, source_operand);
2433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          __ sw(at, destination_operand);
2443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        }
2453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      } else {
246db1b4389239a7132c9cde0915dbd3f775dc1027aBen Murdoch        __ lw(kLithiumScratchReg, source_operand);
247db1b4389239a7132c9cde0915dbd3f775dc1027aBen Murdoch        __ sw(kLithiumScratchReg, destination_operand);
2483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
2493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
2503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else if (source->IsConstantOperand()) {
2523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    LConstantOperand* constant_source = LConstantOperand::cast(source);
2533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (destination->IsRegister()) {
2543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Register dst = cgen_->ToRegister(destination);
2553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (cgen_->IsInteger32(constant_source)) {
2563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ li(dst, Operand(cgen_->ToInteger32(constant_source)));
2573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      } else {
2583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ LoadObject(dst, cgen_->ToHandle(constant_source));
2593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
2603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
2613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ASSERT(destination->IsStackSlot());
2623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ASSERT(!in_cycle_);  // Constant moves happen after all cycles are gone.
2633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (cgen_->IsInteger32(constant_source)) {
264db1b4389239a7132c9cde0915dbd3f775dc1027aBen Murdoch        __ li(kLithiumScratchReg,
2653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              Operand(cgen_->ToInteger32(constant_source)));
2663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      } else {
267db1b4389239a7132c9cde0915dbd3f775dc1027aBen Murdoch        __ LoadObject(kLithiumScratchReg,
2683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      cgen_->ToHandle(constant_source));
2693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
270db1b4389239a7132c9cde0915dbd3f775dc1027aBen Murdoch      __ sw(kLithiumScratchReg, cgen_->ToMemOperand(destination));
2713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
2723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else if (source->IsDoubleRegister()) {
2743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    DoubleRegister source_register = cgen_->ToDoubleRegister(source);
2753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (destination->IsDoubleRegister()) {
2763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ mov_d(cgen_->ToDoubleRegister(destination), source_register);
2773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
2783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ASSERT(destination->IsDoubleStackSlot());
2793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      MemOperand destination_operand = cgen_->ToMemOperand(destination);
2803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ sdc1(source_register, destination_operand);
2813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
2823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else if (source->IsDoubleStackSlot()) {
2843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    MemOperand source_operand = cgen_->ToMemOperand(source);
2853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (destination->IsDoubleRegister()) {
2863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ ldc1(cgen_->ToDoubleRegister(destination), source_operand);
2873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
2883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ASSERT(destination->IsDoubleStackSlot());
2893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      MemOperand destination_operand = cgen_->ToMemOperand(destination);
2903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (in_cycle_) {
2913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // kLithiumScratchDouble was used to break the cycle,
292db1b4389239a7132c9cde0915dbd3f775dc1027aBen Murdoch        // but kLithiumScratchReg is free.
2933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        MemOperand source_high_operand =
2943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            cgen_->ToHighMemOperand(source);
2953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        MemOperand destination_high_operand =
2963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            cgen_->ToHighMemOperand(destination);
297db1b4389239a7132c9cde0915dbd3f775dc1027aBen Murdoch        __ lw(kLithiumScratchReg, source_operand);
298db1b4389239a7132c9cde0915dbd3f775dc1027aBen Murdoch        __ sw(kLithiumScratchReg, destination_operand);
299db1b4389239a7132c9cde0915dbd3f775dc1027aBen Murdoch        __ lw(kLithiumScratchReg, source_high_operand);
300db1b4389239a7132c9cde0915dbd3f775dc1027aBen Murdoch        __ sw(kLithiumScratchReg, destination_high_operand);
3013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      } else {
3023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ ldc1(kLithiumScratchDouble, source_operand);
3033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ sdc1(kLithiumScratchDouble, destination_operand);
3043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
3053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
3063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
3073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    UNREACHABLE();
3083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
3093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  moves_[index].Eliminate();
3113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
3123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#undef __
3153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} }  // namespace v8::internal
317