112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// Copyright 2012 the V8 project authors. All rights reserved.
212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// Use of this source code is governed by a BSD-style license that can be
312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// found in the LICENSE file.
412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org#include "src/v8.h"
612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org#include "src/mips64/lithium-codegen-mips64.h"
812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org#include "src/mips64/lithium-gap-resolver-mips64.h"
912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
1012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgnamespace v8 {
1112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgnamespace internal {
1212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
1312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgLGapResolver::LGapResolver(LCodeGen* owner)
1412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    : cgen_(owner),
1512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      moves_(32, owner->zone()),
1612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      root_index_(0),
1712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      in_cycle_(false),
1812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      saved_destination_(NULL) {}
1912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
2012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
2112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid LGapResolver::Resolve(LParallelMove* parallel_move) {
22e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(moves_.is_empty());
2312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // Build up a worklist of moves.
2412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  BuildInitialMoveList(parallel_move);
2512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
2612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  for (int i = 0; i < moves_.length(); ++i) {
2712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    LMoveOperands move = moves_[i];
2812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    // Skip constants to perform them last.  They don't block other moves
2912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    // and skipping such moves with register destinations keeps those
3012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    // registers free for the whole algorithm.
3112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    if (!move.IsEliminated() && !move.source()->IsConstantOperand()) {
3212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      root_index_ = i;  // Any cycle is found when by reaching this move again.
3312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      PerformMove(i);
3412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      if (in_cycle_) {
3512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        RestoreValue();
3612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      }
3712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    }
3812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  }
3912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
4012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // Perform the moves with constant sources.
4112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  for (int i = 0; i < moves_.length(); ++i) {
4212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    if (!moves_[i].IsEliminated()) {
43e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org      DCHECK(moves_[i].source()->IsConstantOperand());
4412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      EmitMove(i);
4512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    }
4612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  }
4712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
4812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  moves_.Rewind(0);
4912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org}
5012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
5112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
5212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid LGapResolver::BuildInitialMoveList(LParallelMove* parallel_move) {
5312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // Perform a linear sweep of the moves to add them to the initial list of
5412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // moves to perform, ignoring any move that is redundant (the source is
5512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // the same as the destination, the destination is ignored and
5612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // unallocated, or the move was already eliminated).
5712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  const ZoneList<LMoveOperands>* moves = parallel_move->move_operands();
5812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  for (int i = 0; i < moves->length(); ++i) {
5912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    LMoveOperands move = moves->at(i);
6012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    if (!move.IsRedundant()) moves_.Add(move, cgen_->zone());
6112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  }
6212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  Verify();
6312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org}
6412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
6512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
6612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid LGapResolver::PerformMove(int index) {
6712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // Each call to this function performs a move and deletes it from the move
6812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // graph.  We first recursively perform any move blocking this one.  We
6912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // mark a move as "pending" on entry to PerformMove in order to detect
7012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // cycles in the move graph.
7112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
7212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // We can only find a cycle, when doing a depth-first traversal of moves,
7312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // be encountering the starting move again. So by spilling the source of
7412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // the starting move, we break the cycle.  All moves are then unblocked,
7512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // and the starting move is completed by writing the spilled value to
7612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // its destination.  All other moves from the spilled source have been
7712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // completed prior to breaking the cycle.
7812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // An additional complication is that moves to MemOperands with large
7912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // offsets (more than 1K or 4K) require us to spill this spilled value to
8012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // the stack, to free up the register.
81e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(!moves_[index].IsPending());
82e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(!moves_[index].IsRedundant());
8312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
8412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // Clear this move's destination to indicate a pending move.  The actual
8512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // destination is saved in a stack allocated local.  Multiple moves can
8612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // be pending because this function is recursive.
87e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(moves_[index].source() != NULL);  // Or else it will look eliminated.
8812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  LOperand* destination = moves_[index].destination();
8912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  moves_[index].set_destination(NULL);
9012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
9112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // Perform a depth-first traversal of the move graph to resolve
9212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // dependencies.  Any unperformed, unpending move with a source the same
9312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // as this one's destination blocks this one so recursively perform all
9412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // such moves.
9512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  for (int i = 0; i < moves_.length(); ++i) {
9612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    LMoveOperands other_move = moves_[i];
9712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    if (other_move.Blocks(destination) && !other_move.IsPending()) {
9812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      PerformMove(i);
9912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      // If there is a blocking, pending move it must be moves_[root_index_]
10012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      // and all other moves with the same source as moves_[root_index_] are
10112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      // sucessfully executed (because they are cycle-free) by this loop.
10212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    }
10312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  }
10412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
10512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // We are about to resolve this move and don't need it marked as
10612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // pending, so restore its destination.
10712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  moves_[index].set_destination(destination);
10812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
10912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // The move may be blocked on a pending move, which must be the starting move.
11012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // In this case, we have a cycle, and we save the source of this move to
11112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // a scratch register to break it.
11212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  LMoveOperands other_move = moves_[root_index_];
11312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  if (other_move.Blocks(destination)) {
114e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(other_move.IsPending());
11512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    BreakCycle(index);
11612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    return;
11712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  }
11812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
11912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // This move is no longer blocked.
12012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  EmitMove(index);
12112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org}
12212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
12312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
12412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid LGapResolver::Verify() {
125e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org#ifdef ENABLE_SLOW_DCHECKS
12612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // No operand should be the destination for more than one move.
12712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  for (int i = 0; i < moves_.length(); ++i) {
12812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    LOperand* destination = moves_[i].destination();
12912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    for (int j = i + 1; j < moves_.length(); ++j) {
130e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org      SLOW_DCHECK(!destination->Equals(moves_[j].destination()));
13112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    }
13212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  }
13312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org#endif
13412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org}
13512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
13612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org#define __ ACCESS_MASM(cgen_->masm())
13712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
13812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid LGapResolver::BreakCycle(int index) {
13912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // We save in a register the value that should end up in the source of
14012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // moves_[root_index].  After performing all moves in the tree rooted
14112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // in that move, we save the value to that source.
142e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(moves_[index].destination()->Equals(moves_[root_index_].source()));
143e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(!in_cycle_);
14412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  in_cycle_ = true;
14512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  LOperand* source = moves_[index].source();
14612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  saved_destination_ = moves_[index].destination();
14712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  if (source->IsRegister()) {
14812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    __ mov(kLithiumScratchReg, cgen_->ToRegister(source));
14912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  } else if (source->IsStackSlot()) {
15012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    __ ld(kLithiumScratchReg, cgen_->ToMemOperand(source));
15112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  } else if (source->IsDoubleRegister()) {
15212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    __ mov_d(kLithiumScratchDouble, cgen_->ToDoubleRegister(source));
15312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  } else if (source->IsDoubleStackSlot()) {
15412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    __ ldc1(kLithiumScratchDouble, cgen_->ToMemOperand(source));
15512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  } else {
15612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    UNREACHABLE();
15712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  }
15812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // This move will be done by restoring the saved value to the destination.
15912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  moves_[index].Eliminate();
16012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org}
16112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
16212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
16312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid LGapResolver::RestoreValue() {
164e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(in_cycle_);
165e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(saved_destination_ != NULL);
16612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
16712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // Spilled value is in kLithiumScratchReg or kLithiumScratchDouble.
16812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  if (saved_destination_->IsRegister()) {
16912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    __ mov(cgen_->ToRegister(saved_destination_), kLithiumScratchReg);
17012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  } else if (saved_destination_->IsStackSlot()) {
17112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    __ sd(kLithiumScratchReg, cgen_->ToMemOperand(saved_destination_));
17212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  } else if (saved_destination_->IsDoubleRegister()) {
17312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    __ mov_d(cgen_->ToDoubleRegister(saved_destination_),
17412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            kLithiumScratchDouble);
17512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  } else if (saved_destination_->IsDoubleStackSlot()) {
17612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    __ sdc1(kLithiumScratchDouble,
17712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            cgen_->ToMemOperand(saved_destination_));
17812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  } else {
17912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    UNREACHABLE();
18012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  }
18112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
18212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  in_cycle_ = false;
18312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  saved_destination_ = NULL;
18412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org}
18512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
18612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
18712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid LGapResolver::EmitMove(int index) {
18812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  LOperand* source = moves_[index].source();
18912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  LOperand* destination = moves_[index].destination();
19012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
19112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // Dispatch on the source and destination operand kinds.  Not all
19212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // combinations are possible.
19312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
19412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  if (source->IsRegister()) {
19512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    Register source_register = cgen_->ToRegister(source);
19612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    if (destination->IsRegister()) {
19712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      __ mov(cgen_->ToRegister(destination), source_register);
19812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    } else {
199e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org      DCHECK(destination->IsStackSlot());
20012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      __ sd(source_register, cgen_->ToMemOperand(destination));
20112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    }
20212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  } else if (source->IsStackSlot()) {
20312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    MemOperand source_operand = cgen_->ToMemOperand(source);
20412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    if (destination->IsRegister()) {
20512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      __ ld(cgen_->ToRegister(destination), source_operand);
20612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    } else {
207e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org      DCHECK(destination->IsStackSlot());
20812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      MemOperand destination_operand = cgen_->ToMemOperand(destination);
20912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      if (in_cycle_) {
21012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        if (!destination_operand.OffsetIsInt16Encodable()) {
21112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          // 'at' is overwritten while saving the value to the destination.
21212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          // Therefore we can't use 'at'.  It is OK if the read from the source
21312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          // destroys 'at', since that happens before the value is read.
21412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          // This uses only a single reg of the double reg-pair.
21512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          __ ldc1(kLithiumScratchDouble, source_operand);
21612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          __ sdc1(kLithiumScratchDouble, destination_operand);
21712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        } else {
21812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          __ ld(at, source_operand);
21912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          __ sd(at, destination_operand);
22012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        }
22112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      } else {
22212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        __ ld(kLithiumScratchReg, source_operand);
22312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        __ sd(kLithiumScratchReg, destination_operand);
22412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      }
22512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    }
22612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
22712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  } else if (source->IsConstantOperand()) {
22812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    LConstantOperand* constant_source = LConstantOperand::cast(source);
22912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    if (destination->IsRegister()) {
23012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      Register dst = cgen_->ToRegister(destination);
23112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      if (cgen_->IsSmi(constant_source)) {
23212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org         __ li(dst, Operand(cgen_->ToSmi(constant_source)));
23312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      } else if (cgen_->IsInteger32(constant_source)) {
23412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org         __ li(dst, Operand(cgen_->ToInteger32(constant_source)));
23512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      } else {
23612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org         __ li(dst, cgen_->ToHandle(constant_source));
23712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      }
23812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    } else if (destination->IsDoubleRegister()) {
23912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      DoubleRegister result = cgen_->ToDoubleRegister(destination);
24012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      double v = cgen_->ToDouble(constant_source);
24112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      __ Move(result, v);
24212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    } else {
243e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org      DCHECK(destination->IsStackSlot());
244e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org      DCHECK(!in_cycle_);  // Constant moves happen after all cycles are gone.
24512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      if (cgen_->IsSmi(constant_source)) {
24612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org         __ li(kLithiumScratchReg, Operand(cgen_->ToSmi(constant_source)));
24712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org         __ sd(kLithiumScratchReg, cgen_->ToMemOperand(destination));
24812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      } else if (cgen_->IsInteger32(constant_source)) {
24912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        __ li(kLithiumScratchReg, Operand(cgen_->ToInteger32(constant_source)));
25012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        __ sd(kLithiumScratchReg, cgen_->ToMemOperand(destination));
25112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      } else {
25212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        __ li(kLithiumScratchReg, cgen_->ToHandle(constant_source));
25312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        __ sd(kLithiumScratchReg, cgen_->ToMemOperand(destination));
25412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      }
25512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    }
25612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
25712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  } else if (source->IsDoubleRegister()) {
25812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    DoubleRegister source_register = cgen_->ToDoubleRegister(source);
25912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    if (destination->IsDoubleRegister()) {
26012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      __ mov_d(cgen_->ToDoubleRegister(destination), source_register);
26112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    } else {
262e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org      DCHECK(destination->IsDoubleStackSlot());
26312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      MemOperand destination_operand = cgen_->ToMemOperand(destination);
26412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      __ sdc1(source_register, destination_operand);
26512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    }
26612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
26712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  } else if (source->IsDoubleStackSlot()) {
26812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    MemOperand source_operand = cgen_->ToMemOperand(source);
26912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    if (destination->IsDoubleRegister()) {
27012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      __ ldc1(cgen_->ToDoubleRegister(destination), source_operand);
27112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    } else {
272e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org      DCHECK(destination->IsDoubleStackSlot());
27312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      MemOperand destination_operand = cgen_->ToMemOperand(destination);
27412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      if (in_cycle_) {
27512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        // kLithiumScratchDouble was used to break the cycle,
27612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        // but kLithiumScratchReg is free.
27712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        MemOperand source_high_operand =
27812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            cgen_->ToHighMemOperand(source);
27912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        MemOperand destination_high_operand =
28012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            cgen_->ToHighMemOperand(destination);
28112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        __ lw(kLithiumScratchReg, source_operand);
28212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        __ sw(kLithiumScratchReg, destination_operand);
28312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        __ lw(kLithiumScratchReg, source_high_operand);
28412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        __ sw(kLithiumScratchReg, destination_high_operand);
28512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      } else {
28612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        __ ldc1(kLithiumScratchDouble, source_operand);
28712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        __ sdc1(kLithiumScratchDouble, destination_operand);
28812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      }
28912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    }
29012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  } else {
29112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    UNREACHABLE();
29212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  }
29312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
29412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  moves_[index].Eliminate();
29512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org}
29612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
29712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
29812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org#undef __
29912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
30012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} }  // namespace v8::internal
301