lithium-gap-resolver-arm.cc revision 3ef787dbeca8a5fb1086949cda830dccee07bfbd
1692be65d6b06edd9ff4cfc4c308555b7c99c1191Ben Murdoch// Copyright 2012 the V8 project authors. All rights reserved.
2e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// Redistribution and use in source and binary forms, with or without
3e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// modification, are permitted provided that the following conditions are
4e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// met:
5e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch//
6e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch//     * Redistributions of source code must retain the above copyright
7e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch//       notice, this list of conditions and the following disclaimer.
8e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch//     * Redistributions in binary form must reproduce the above
9e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch//       copyright notice, this list of conditions and the following
10e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch//       disclaimer in the documentation and/or other materials provided
11e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch//       with the distribution.
12e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch//     * Neither the name of Google Inc. nor the names of its
13e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch//       contributors may be used to endorse or promote products derived
14e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch//       from this software without specific prior written permission.
15e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch//
16e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2844f0eee88ff00398ff7f715fab053374d808c90dSteve Block#include "v8.h"
2944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
30e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch#include "arm/lithium-gap-resolver-arm.h"
31e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch#include "arm/lithium-codegen-arm.h"
32e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
33e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochnamespace v8 {
34e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochnamespace internal {
35e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
36e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochstatic const Register kSavedValueRegister = { 9 };
37e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
38e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochLGapResolver::LGapResolver(LCodeGen* owner)
39e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    : cgen_(owner), moves_(32), root_index_(0), in_cycle_(false),
40e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      saved_destination_(NULL) { }
41e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
42e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
43e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid LGapResolver::Resolve(LParallelMove* parallel_move) {
44e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT(moves_.is_empty());
45e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Build up a worklist of moves.
46e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  BuildInitialMoveList(parallel_move);
47e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
48e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  for (int i = 0; i < moves_.length(); ++i) {
49e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    LMoveOperands move = moves_[i];
50e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // Skip constants to perform them last.  They don't block other moves
51e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // and skipping such moves with register destinations keeps those
52e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // registers free for the whole algorithm.
53e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    if (!move.IsEliminated() && !move.source()->IsConstantOperand()) {
54e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      root_index_ = i;  // Any cycle is found when by reaching this move again.
55e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      PerformMove(i);
56e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      if (in_cycle_) {
57e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        RestoreValue();
58e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      }
59e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    }
60e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
61e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
62e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Perform the moves with constant sources.
63e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  for (int i = 0; i < moves_.length(); ++i) {
64e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    if (!moves_[i].IsEliminated()) {
65e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      ASSERT(moves_[i].source()->IsConstantOperand());
66e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      EmitMove(i);
67e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    }
68e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
69e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
70e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  moves_.Rewind(0);
71e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
72e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
73e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
74e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid LGapResolver::BuildInitialMoveList(LParallelMove* parallel_move) {
75e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Perform a linear sweep of the moves to add them to the initial list of
76e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // moves to perform, ignoring any move that is redundant (the source is
77e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // the same as the destination, the destination is ignored and
78e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // unallocated, or the move was already eliminated).
79e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  const ZoneList<LMoveOperands>* moves = parallel_move->move_operands();
80e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  for (int i = 0; i < moves->length(); ++i) {
81e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    LMoveOperands move = moves->at(i);
82e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    if (!move.IsRedundant()) moves_.Add(move);
83e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
84e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  Verify();
85e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
86e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
87e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
88e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid LGapResolver::PerformMove(int index) {
89e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Each call to this function performs a move and deletes it from the move
90e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // graph.  We first recursively perform any move blocking this one.  We
91e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // mark a move as "pending" on entry to PerformMove in order to detect
92e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // cycles in the move graph.
93e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
94e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // We can only find a cycle, when doing a depth-first traversal of moves,
95e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // be encountering the starting move again. So by spilling the source of
96e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // the starting move, we break the cycle.  All moves are then unblocked,
97e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // and the starting move is completed by writing the spilled value to
98e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // its destination.  All other moves from the spilled source have been
99e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // completed prior to breaking the cycle.
100e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // An additional complication is that moves to MemOperands with large
101e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // offsets (more than 1K or 4K) require us to spill this spilled value to
102e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // the stack, to free up the register.
103e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT(!moves_[index].IsPending());
104e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT(!moves_[index].IsRedundant());
105e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
106e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Clear this move's destination to indicate a pending move.  The actual
107e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // destination is saved in a stack allocated local.  Multiple moves can
108e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // be pending because this function is recursive.
109e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT(moves_[index].source() != NULL);  // Or else it will look eliminated.
110e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  LOperand* destination = moves_[index].destination();
111e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  moves_[index].set_destination(NULL);
112e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
113e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Perform a depth-first traversal of the move graph to resolve
114e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // dependencies.  Any unperformed, unpending move with a source the same
115e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // as this one's destination blocks this one so recursively perform all
116e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // such moves.
117e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  for (int i = 0; i < moves_.length(); ++i) {
118e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    LMoveOperands other_move = moves_[i];
119e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    if (other_move.Blocks(destination) && !other_move.IsPending()) {
120e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      PerformMove(i);
121e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      // If there is a blocking, pending move it must be moves_[root_index_]
122e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      // and all other moves with the same source as moves_[root_index_] are
123e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      // sucessfully executed (because they are cycle-free) by this loop.
124e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    }
125e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
126e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
127e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // We are about to resolve this move and don't need it marked as
128e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // pending, so restore its destination.
129e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  moves_[index].set_destination(destination);
130e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
131e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // The move may be blocked on a pending move, which must be the starting move.
132e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // In this case, we have a cycle, and we save the source of this move to
133e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // a scratch register to break it.
134e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  LMoveOperands other_move = moves_[root_index_];
135e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (other_move.Blocks(destination)) {
136e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    ASSERT(other_move.IsPending());
137e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    BreakCycle(index);
138e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    return;
139e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
140e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
141e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // This move is no longer blocked.
142e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  EmitMove(index);
143e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
144e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
145e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
146e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid LGapResolver::Verify() {
147e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch#ifdef ENABLE_SLOW_ASSERTS
148e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // No operand should be the destination for more than one move.
149e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  for (int i = 0; i < moves_.length(); ++i) {
150e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    LOperand* destination = moves_[i].destination();
151e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    for (int j = i + 1; j < moves_.length(); ++j) {
152e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      SLOW_ASSERT(!destination->Equals(moves_[j].destination()));
153e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    }
154e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
155e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch#endif
156e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
157e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
158e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch#define __ ACCESS_MASM(cgen_->masm())
159e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
160e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid LGapResolver::BreakCycle(int index) {
161e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // We save in a register the value that should end up in the source of
162e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // moves_[root_index].  After performing all moves in the tree rooted
163e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // in that move, we save the value to that source.
164e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT(moves_[index].destination()->Equals(moves_[root_index_].source()));
165e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT(!in_cycle_);
166e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  in_cycle_ = true;
167e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  LOperand* source = moves_[index].source();
168e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  saved_destination_ = moves_[index].destination();
169e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (source->IsRegister()) {
170e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    __ mov(kSavedValueRegister, cgen_->ToRegister(source));
171e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  } else if (source->IsStackSlot()) {
172e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    __ ldr(kSavedValueRegister, cgen_->ToMemOperand(source));
173e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  } else if (source->IsDoubleRegister()) {
174692be65d6b06edd9ff4cfc4c308555b7c99c1191Ben Murdoch    __ vmov(kScratchDoubleReg, cgen_->ToDoubleRegister(source));
175e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  } else if (source->IsDoubleStackSlot()) {
176692be65d6b06edd9ff4cfc4c308555b7c99c1191Ben Murdoch    __ vldr(kScratchDoubleReg, cgen_->ToMemOperand(source));
177e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  } else {
178e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    UNREACHABLE();
179e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
180e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // This move will be done by restoring the saved value to the destination.
181e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  moves_[index].Eliminate();
182e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
183e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
184e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
185e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid LGapResolver::RestoreValue() {
186e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT(in_cycle_);
187e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT(saved_destination_ != NULL);
188e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
189e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Spilled value is in kSavedValueRegister or kSavedDoubleValueRegister.
190e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (saved_destination_->IsRegister()) {
191e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    __ mov(cgen_->ToRegister(saved_destination_), kSavedValueRegister);
192e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  } else if (saved_destination_->IsStackSlot()) {
193e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    __ str(kSavedValueRegister, cgen_->ToMemOperand(saved_destination_));
194e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  } else if (saved_destination_->IsDoubleRegister()) {
195692be65d6b06edd9ff4cfc4c308555b7c99c1191Ben Murdoch    __ vmov(cgen_->ToDoubleRegister(saved_destination_), kScratchDoubleReg);
196e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  } else if (saved_destination_->IsDoubleStackSlot()) {
197692be65d6b06edd9ff4cfc4c308555b7c99c1191Ben Murdoch    __ vstr(kScratchDoubleReg, cgen_->ToMemOperand(saved_destination_));
198e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  } else {
199e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    UNREACHABLE();
200e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
201e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
202e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  in_cycle_ = false;
203e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  saved_destination_ = NULL;
204e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
205e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
206e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
207e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid LGapResolver::EmitMove(int index) {
208e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  LOperand* source = moves_[index].source();
209e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  LOperand* destination = moves_[index].destination();
210e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
211e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Dispatch on the source and destination operand kinds.  Not all
212e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // combinations are possible.
213e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
214e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (source->IsRegister()) {
215e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    Register source_register = cgen_->ToRegister(source);
216e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    if (destination->IsRegister()) {
217e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      __ mov(cgen_->ToRegister(destination), source_register);
218e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    } else {
219e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      ASSERT(destination->IsStackSlot());
220e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      __ str(source_register, cgen_->ToMemOperand(destination));
221e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    }
222e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
223e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  } else if (source->IsStackSlot()) {
224e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    MemOperand source_operand = cgen_->ToMemOperand(source);
225e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    if (destination->IsRegister()) {
226e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      __ ldr(cgen_->ToRegister(destination), source_operand);
227e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    } else {
228e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      ASSERT(destination->IsStackSlot());
229e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      MemOperand destination_operand = cgen_->ToMemOperand(destination);
230e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      if (in_cycle_) {
231e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        if (!destination_operand.OffsetIsUint12Encodable()) {
232e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          // ip is overwritten while saving the value to the destination.
233e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          // Therefore we can't use ip.  It is OK if the read from the source
234e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          // destroys ip, since that happens before the value is read.
235692be65d6b06edd9ff4cfc4c308555b7c99c1191Ben Murdoch          __ vldr(kScratchDoubleReg.low(), source_operand);
236692be65d6b06edd9ff4cfc4c308555b7c99c1191Ben Murdoch          __ vstr(kScratchDoubleReg.low(), destination_operand);
237e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        } else {
238e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          __ ldr(ip, source_operand);
239e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          __ str(ip, destination_operand);
240e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        }
241e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      } else {
242e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        __ ldr(kSavedValueRegister, source_operand);
243e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        __ str(kSavedValueRegister, destination_operand);
244e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      }
245e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    }
246e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
247e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  } else if (source->IsConstantOperand()) {
2483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    LConstantOperand* constant_source = LConstantOperand::cast(source);
249e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    if (destination->IsRegister()) {
2503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Register dst = cgen_->ToRegister(destination);
2513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (cgen_->IsInteger32(constant_source)) {
2523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ mov(dst, Operand(cgen_->ToInteger32(constant_source)));
2533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      } else {
2543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ LoadObject(dst, cgen_->ToHandle(constant_source));
2553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
256e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    } else {
257e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      ASSERT(destination->IsStackSlot());
258e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      ASSERT(!in_cycle_);  // Constant moves happen after all cycles are gone.
2593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (cgen_->IsInteger32(constant_source)) {
2603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ mov(kSavedValueRegister,
2613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch               Operand(cgen_->ToInteger32(constant_source)));
2623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      } else {
2633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ LoadObject(kSavedValueRegister,
2643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      cgen_->ToHandle(constant_source));
2653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
266e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      __ str(kSavedValueRegister, cgen_->ToMemOperand(destination));
267e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    }
268e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
269e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  } else if (source->IsDoubleRegister()) {
270e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    DoubleRegister source_register = cgen_->ToDoubleRegister(source);
271e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    if (destination->IsDoubleRegister()) {
272e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      __ vmov(cgen_->ToDoubleRegister(destination), source_register);
273e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    } else {
274e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      ASSERT(destination->IsDoubleStackSlot());
27569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      __ vstr(source_register, cgen_->ToMemOperand(destination));
276e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    }
277e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
278e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  } else if (source->IsDoubleStackSlot()) {
279e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    MemOperand source_operand = cgen_->ToMemOperand(source);
280e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    if (destination->IsDoubleRegister()) {
281e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      __ vldr(cgen_->ToDoubleRegister(destination), source_operand);
282e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    } else {
283e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      ASSERT(destination->IsDoubleStackSlot());
284e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      MemOperand destination_operand = cgen_->ToMemOperand(destination);
285e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      if (in_cycle_) {
286e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        // kSavedDoubleValueRegister was used to break the cycle,
287e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        // but kSavedValueRegister is free.
288e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        MemOperand source_high_operand =
289e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch            cgen_->ToHighMemOperand(source);
290e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        MemOperand destination_high_operand =
291e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch            cgen_->ToHighMemOperand(destination);
292e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        __ ldr(kSavedValueRegister, source_operand);
293e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        __ str(kSavedValueRegister, destination_operand);
294e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        __ ldr(kSavedValueRegister, source_high_operand);
295e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        __ str(kSavedValueRegister, destination_high_operand);
296e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      } else {
297692be65d6b06edd9ff4cfc4c308555b7c99c1191Ben Murdoch        __ vldr(kScratchDoubleReg, source_operand);
298692be65d6b06edd9ff4cfc4c308555b7c99c1191Ben Murdoch        __ vstr(kScratchDoubleReg, destination_operand);
299e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      }
300e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    }
301e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  } else {
302e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    UNREACHABLE();
303e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
304e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
305e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  moves_[index].Eliminate();
306e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
307e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
308e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
309e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch#undef __
310e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
311e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch} }  // namespace v8::internal
312