1b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Copyright 2013 the V8 project authors. All rights reserved.
2b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// found in the LICENSE file.
4b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/crankshaft/arm64/delayed-masm-arm64-inl.h"
6014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/crankshaft/arm64/lithium-codegen-arm64.h"
7014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/crankshaft/arm64/lithium-gap-resolver-arm64.h"
8b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
9b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace v8 {
10b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace internal {
11b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
12b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define __ ACCESS_MASM((&masm_))
13b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
14b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
15b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid DelayedGapMasm::EndDelayedUse() {
16b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DelayedMasm::EndDelayedUse();
17b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (scratch_register_used()) {
18b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(ScratchRegister().Is(root));
19b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!pending());
20b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    InitializeRootRegister();
21b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    reset_scratch_register_used();
22b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
23b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
24b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
25b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
26b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochLGapResolver::LGapResolver(LCodeGen* owner)
27b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    : cgen_(owner), masm_(owner, owner->masm()), moves_(32, owner->zone()),
28b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      root_index_(0), in_cycle_(false), saved_destination_(NULL) {
29b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
30b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
31b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
32b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LGapResolver::Resolve(LParallelMove* parallel_move) {
33b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(moves_.is_empty());
34b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!masm_.pending());
35b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
36b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Build up a worklist of moves.
37b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  BuildInitialMoveList(parallel_move);
38b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
39b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (int i = 0; i < moves_.length(); ++i) {
40b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    LMoveOperands move = moves_[i];
41b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
42b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Skip constants to perform them last. They don't block other moves
43b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // and skipping such moves with register destinations keeps those
44b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // registers free for the whole algorithm.
45b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (!move.IsEliminated() && !move.source()->IsConstantOperand()) {
46b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      root_index_ = i;  // Any cycle is found when we reach this move again.
47b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      PerformMove(i);
48b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (in_cycle_) RestoreValue();
49b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
50b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
51b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
52b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Perform the moves with constant sources.
53b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (int i = 0; i < moves_.length(); ++i) {
54b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    LMoveOperands move = moves_[i];
55b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
56b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (!move.IsEliminated()) {
57b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(move.source()->IsConstantOperand());
58b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      EmitMove(i);
59b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
60b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
61b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
62b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ EndDelayedUse();
63b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
64b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  moves_.Rewind(0);
65b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
66b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
67b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
68b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LGapResolver::BuildInitialMoveList(LParallelMove* parallel_move) {
69b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Perform a linear sweep of the moves to add them to the initial list of
70b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // moves to perform, ignoring any move that is redundant (the source is
71b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // the same as the destination, the destination is ignored and
72b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // unallocated, or the move was already eliminated).
73b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const ZoneList<LMoveOperands>* moves = parallel_move->move_operands();
74b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (int i = 0; i < moves->length(); ++i) {
75b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    LMoveOperands move = moves->at(i);
76b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (!move.IsRedundant()) moves_.Add(move, cgen_->zone());
77b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
78b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Verify();
79b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
80b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
81b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
82b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LGapResolver::PerformMove(int index) {
83b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Each call to this function performs a move and deletes it from the move
84b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // graph. We first recursively perform any move blocking this one. We
85b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // mark a move as "pending" on entry to PerformMove in order to detect
86b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // cycles in the move graph.
87b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LMoveOperands& current_move = moves_[index];
88b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
89b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!current_move.IsPending());
90b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!current_move.IsRedundant());
91b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
92b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Clear this move's destination to indicate a pending move.  The actual
93b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // destination is saved in a stack allocated local. Multiple moves can
94b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // be pending because this function is recursive.
95b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(current_move.source() != NULL);  // Otherwise it will look eliminated.
96b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LOperand* destination = current_move.destination();
97b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  current_move.set_destination(NULL);
98b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
99b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Perform a depth-first traversal of the move graph to resolve
100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // dependencies. Any unperformed, unpending move with a source the same
101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // as this one's destination blocks this one so recursively perform all
102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // such moves.
103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (int i = 0; i < moves_.length(); ++i) {
104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    LMoveOperands other_move = moves_[i];
105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (other_move.Blocks(destination) && !other_move.IsPending()) {
106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      PerformMove(i);
107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // If there is a blocking, pending move it must be moves_[root_index_]
108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // and all other moves with the same source as moves_[root_index_] are
109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // sucessfully executed (because they are cycle-free) by this loop.
110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // We are about to resolve this move and don't need it marked as
114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // pending, so restore its destination.
115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  current_move.set_destination(destination);
116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // The move may be blocked on a pending move, which must be the starting move.
118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // In this case, we have a cycle, and we save the source of this move to
119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // a scratch register to break it.
120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LMoveOperands other_move = moves_[root_index_];
121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (other_move.Blocks(destination)) {
122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(other_move.IsPending());
123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    BreakCycle(index);
124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return;
125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // This move is no longer blocked.
128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  EmitMove(index);
129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
130b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
131b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LGapResolver::Verify() {
133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifdef ENABLE_SLOW_DCHECKS
134b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // No operand should be the destination for more than one move.
135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (int i = 0; i < moves_.length(); ++i) {
136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    LOperand* destination = moves_[i].destination();
137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    for (int j = i + 1; j < moves_.length(); ++j) {
138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      SLOW_DCHECK(!destination->Equals(moves_[j].destination()));
139b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
141b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif
142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
145b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LGapResolver::BreakCycle(int index) {
146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(moves_[index].destination()->Equals(moves_[root_index_].source()));
147b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!in_cycle_);
148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // We save in a register the source of that move and we remember its
150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // destination. Then we mark this move as resolved so the cycle is
151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // broken and we can perform the other moves.
152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  in_cycle_ = true;
153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LOperand* source = moves_[index].source();
154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  saved_destination_ = moves_[index].destination();
155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (source->IsRegister()) {
157b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    AcquireSavedValueRegister();
158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Mov(SavedValueRegister(), cgen_->ToRegister(source));
159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (source->IsStackSlot()) {
160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    AcquireSavedValueRegister();
161b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Load(SavedValueRegister(), cgen_->ToMemOperand(source));
162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (source->IsDoubleRegister()) {
163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Fmov(SavedFPValueRegister(), cgen_->ToDoubleRegister(source));
164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (source->IsDoubleStackSlot()) {
165b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Load(SavedFPValueRegister(), cgen_->ToMemOperand(source));
166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    UNREACHABLE();
168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
169b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Mark this move as resolved.
171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // This move will be actually performed by moving the saved value to this
172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // move's destination in LGapResolver::RestoreValue().
173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  moves_[index].Eliminate();
174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LGapResolver::RestoreValue() {
178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(in_cycle_);
179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(saved_destination_ != NULL);
180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (saved_destination_->IsRegister()) {
182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Mov(cgen_->ToRegister(saved_destination_), SavedValueRegister());
183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ReleaseSavedValueRegister();
184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (saved_destination_->IsStackSlot()) {
185b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Store(SavedValueRegister(), cgen_->ToMemOperand(saved_destination_));
186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ReleaseSavedValueRegister();
187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (saved_destination_->IsDoubleRegister()) {
188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Fmov(cgen_->ToDoubleRegister(saved_destination_),
189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            SavedFPValueRegister());
190b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (saved_destination_->IsDoubleStackSlot()) {
191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Store(SavedFPValueRegister(), cgen_->ToMemOperand(saved_destination_));
192b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
193b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    UNREACHABLE();
194b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
195b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
196b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  in_cycle_ = false;
197b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  saved_destination_ = NULL;
198b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
199b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
201b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LGapResolver::EmitMove(int index) {
202b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LOperand* source = moves_[index].source();
203b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LOperand* destination = moves_[index].destination();
204b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
205b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Dispatch on the source and destination operand kinds.  Not all
206b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // combinations are possible.
207b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
208b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (source->IsRegister()) {
209b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register source_register = cgen_->ToRegister(source);
210b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (destination->IsRegister()) {
211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Mov(cgen_->ToRegister(destination), source_register);
212b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(destination->IsStackSlot());
214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Store(source_register, cgen_->ToMemOperand(destination));
215b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
216b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
217b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (source->IsStackSlot()) {
218b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    MemOperand source_operand = cgen_->ToMemOperand(source);
219b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (destination->IsRegister()) {
220b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Load(cgen_->ToRegister(destination), source_operand);
221b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
222b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(destination->IsStackSlot());
223b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      EmitStackSlotMove(index);
224b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
225b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (source->IsConstantOperand()) {
227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    LConstantOperand* constant_source = LConstantOperand::cast(source);
228b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (destination->IsRegister()) {
229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Register dst = cgen_->ToRegister(destination);
230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (cgen_->IsSmi(constant_source)) {
231b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ Mov(dst, cgen_->ToSmi(constant_source));
232b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      } else if (cgen_->IsInteger32Constant(constant_source)) {
233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ Mov(dst, cgen_->ToInteger32(constant_source));
234b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      } else {
235b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ LoadObject(dst, cgen_->ToHandle(constant_source));
236b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else if (destination->IsDoubleRegister()) {
238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DoubleRegister result = cgen_->ToDoubleRegister(destination);
239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Fmov(result, cgen_->ToDouble(constant_source));
240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(destination->IsStackSlot());
242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(!in_cycle_);  // Constant moves happen after all cycles are gone.
243b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (cgen_->IsSmi(constant_source)) {
244b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        Smi* smi = cgen_->ToSmi(constant_source);
245b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ StoreConstant(reinterpret_cast<intptr_t>(smi),
246b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         cgen_->ToMemOperand(destination));
247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      } else if (cgen_->IsInteger32Constant(constant_source)) {
248b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ StoreConstant(cgen_->ToInteger32(constant_source),
249b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         cgen_->ToMemOperand(destination));
250b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      } else {
251b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        Handle<Object> handle = cgen_->ToHandle(constant_source);
252b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        AllowDeferredHandleDereference smi_object_check;
253b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        if (handle->IsSmi()) {
254b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          Object* obj = *handle;
255b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          DCHECK(!obj->IsHeapObject());
256b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          __ StoreConstant(reinterpret_cast<intptr_t>(obj),
257b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                           cgen_->ToMemOperand(destination));
258b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        } else {
259b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          AcquireSavedValueRegister();
260b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          __ LoadObject(SavedValueRegister(), handle);
261b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          __ Store(SavedValueRegister(), cgen_->ToMemOperand(destination));
262b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          ReleaseSavedValueRegister();
263b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        }
264b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
265b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
266b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
267b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (source->IsDoubleRegister()) {
268b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DoubleRegister src = cgen_->ToDoubleRegister(source);
269b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (destination->IsDoubleRegister()) {
270b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Fmov(cgen_->ToDoubleRegister(destination), src);
271b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
272b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(destination->IsDoubleStackSlot());
273b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Store(src, cgen_->ToMemOperand(destination));
274b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
275b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (source->IsDoubleStackSlot()) {
277b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    MemOperand src = cgen_->ToMemOperand(source);
278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (destination->IsDoubleRegister()) {
279b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Load(cgen_->ToDoubleRegister(destination), src);
280b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
281b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(destination->IsDoubleStackSlot());
282b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      EmitStackSlotMove(index);
283b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
284b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
285b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
286b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    UNREACHABLE();
287b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
288b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // The move has been emitted, we can eliminate it.
290b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  moves_[index].Eliminate();
291b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
292b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
293014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}  // namespace internal
294014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}  // namespace v8
295