12efb900e7350b14be905abdeab077f3a64c583cfulan@chromium.org// Copyright 2012 the V8 project authors. All rights reserved.
23484964a86451e86dcf04be9bd8c0d76ee04f081rossberg@chromium.org// Use of this source code is governed by a BSD-style license that can be
33484964a86451e86dcf04be9bd8c0d76ee04f081rossberg@chromium.org// found in the LICENSE file.
4c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org
5196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/v8.h"
6c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org
7196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/mips/lithium-codegen-mips.h"
84b0feeef5d01dbc2948080b4f69daa37e1083461machenbach@chromium.org#include "src/mips/lithium-gap-resolver-mips.h"
9c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org
10c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.orgnamespace v8 {
11c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.orgnamespace internal {
12c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org
13c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.orgLGapResolver::LGapResolver(LCodeGen* owner)
14c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    : cgen_(owner),
157028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org      moves_(32, owner->zone()),
16c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org      root_index_(0),
17c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org      in_cycle_(false),
18c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org      saved_destination_(NULL) {}
19c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org
20c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org
21c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.orgvoid LGapResolver::Resolve(LParallelMove* parallel_move) {
22e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(moves_.is_empty());
23c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  // Build up a worklist of moves.
24c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  BuildInitialMoveList(parallel_move);
25c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org
26c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  for (int i = 0; i < moves_.length(); ++i) {
27c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    LMoveOperands move = moves_[i];
28c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    // Skip constants to perform them last.  They don't block other moves
29c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    // and skipping such moves with register destinations keeps those
30c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    // registers free for the whole algorithm.
31c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    if (!move.IsEliminated() && !move.source()->IsConstantOperand()) {
32c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org      root_index_ = i;  // Any cycle is found when by reaching this move again.
33c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org      PerformMove(i);
34c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org      if (in_cycle_) {
35c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org        RestoreValue();
36c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org      }
37c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    }
38c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  }
39c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org
40c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  // Perform the moves with constant sources.
41c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  for (int i = 0; i < moves_.length(); ++i) {
42c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    if (!moves_[i].IsEliminated()) {
43e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org      DCHECK(moves_[i].source()->IsConstantOperand());
44c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org      EmitMove(i);
45c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    }
46c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  }
47c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org
48c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  moves_.Rewind(0);
49c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org}
50c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org
51c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org
52c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.orgvoid LGapResolver::BuildInitialMoveList(LParallelMove* parallel_move) {
53c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  // Perform a linear sweep of the moves to add them to the initial list of
54c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  // moves to perform, ignoring any move that is redundant (the source is
55c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  // the same as the destination, the destination is ignored and
56c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  // unallocated, or the move was already eliminated).
57c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  const ZoneList<LMoveOperands>* moves = parallel_move->move_operands();
58c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  for (int i = 0; i < moves->length(); ++i) {
59c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    LMoveOperands move = moves->at(i);
607028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org    if (!move.IsRedundant()) moves_.Add(move, cgen_->zone());
61c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  }
62c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  Verify();
63c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org}
64c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org
65c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org
66c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.orgvoid LGapResolver::PerformMove(int index) {
67c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  // Each call to this function performs a move and deletes it from the move
68c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  // graph.  We first recursively perform any move blocking this one.  We
69c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  // mark a move as "pending" on entry to PerformMove in order to detect
70c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  // cycles in the move graph.
71c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org
72c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  // We can only find a cycle, when doing a depth-first traversal of moves,
73c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  // be encountering the starting move again. So by spilling the source of
74c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  // the starting move, we break the cycle.  All moves are then unblocked,
75c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  // and the starting move is completed by writing the spilled value to
76c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  // its destination.  All other moves from the spilled source have been
77c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  // completed prior to breaking the cycle.
78c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  // An additional complication is that moves to MemOperands with large
79c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  // offsets (more than 1K or 4K) require us to spill this spilled value to
80c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  // the stack, to free up the register.
81e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(!moves_[index].IsPending());
82e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(!moves_[index].IsRedundant());
83c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org
84c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  // Clear this move's destination to indicate a pending move.  The actual
85c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  // destination is saved in a stack allocated local.  Multiple moves can
86c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  // be pending because this function is recursive.
87e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(moves_[index].source() != NULL);  // Or else it will look eliminated.
88c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  LOperand* destination = moves_[index].destination();
89c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  moves_[index].set_destination(NULL);
90c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org
91c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  // Perform a depth-first traversal of the move graph to resolve
92c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  // dependencies.  Any unperformed, unpending move with a source the same
93c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  // as this one's destination blocks this one so recursively perform all
94c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  // such moves.
95c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  for (int i = 0; i < moves_.length(); ++i) {
96c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    LMoveOperands other_move = moves_[i];
97c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    if (other_move.Blocks(destination) && !other_move.IsPending()) {
98c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org      PerformMove(i);
99c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org      // If there is a blocking, pending move it must be moves_[root_index_]
100c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org      // and all other moves with the same source as moves_[root_index_] are
101c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org      // sucessfully executed (because they are cycle-free) by this loop.
102c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    }
103c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  }
104c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org
105c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  // We are about to resolve this move and don't need it marked as
106c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  // pending, so restore its destination.
107c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  moves_[index].set_destination(destination);
108c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org
109c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  // The move may be blocked on a pending move, which must be the starting move.
110c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  // In this case, we have a cycle, and we save the source of this move to
111c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  // a scratch register to break it.
112c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  LMoveOperands other_move = moves_[root_index_];
113c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  if (other_move.Blocks(destination)) {
114e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(other_move.IsPending());
115c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    BreakCycle(index);
116c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    return;
117c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  }
118c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org
119c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  // This move is no longer blocked.
120c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  EmitMove(index);
121c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org}
122c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org
123c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org
124c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.orgvoid LGapResolver::Verify() {
125e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org#ifdef ENABLE_SLOW_DCHECKS
126c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  // No operand should be the destination for more than one move.
127c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  for (int i = 0; i < moves_.length(); ++i) {
128c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    LOperand* destination = moves_[i].destination();
129c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    for (int j = i + 1; j < moves_.length(); ++j) {
130e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org      SLOW_DCHECK(!destination->Equals(moves_[j].destination()));
131c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    }
132c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  }
133c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org#endif
134c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org}
135c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org
136c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org#define __ ACCESS_MASM(cgen_->masm())
137c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org
138c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.orgvoid LGapResolver::BreakCycle(int index) {
139c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  // We save in a register the value that should end up in the source of
140c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  // moves_[root_index].  After performing all moves in the tree rooted
141c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@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_);
144c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  in_cycle_ = true;
145c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  LOperand* source = moves_[index].source();
146c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  saved_destination_ = moves_[index].destination();
147c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  if (source->IsRegister()) {
1487d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org    __ mov(kLithiumScratchReg, cgen_->ToRegister(source));
149c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  } else if (source->IsStackSlot()) {
1507d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org    __ lw(kLithiumScratchReg, cgen_->ToMemOperand(source));
151c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  } else if (source->IsDoubleRegister()) {
1522efb900e7350b14be905abdeab077f3a64c583cfulan@chromium.org    __ mov_d(kLithiumScratchDouble, cgen_->ToDoubleRegister(source));
153c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  } else if (source->IsDoubleStackSlot()) {
1542efb900e7350b14be905abdeab077f3a64c583cfulan@chromium.org    __ ldc1(kLithiumScratchDouble, cgen_->ToMemOperand(source));
155c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  } else {
156c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    UNREACHABLE();
157c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  }
158c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  // This move will be done by restoring the saved value to the destination.
159c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  moves_[index].Eliminate();
160c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org}
161c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org
162c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org
163c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.orgvoid LGapResolver::RestoreValue() {
164e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(in_cycle_);
165e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(saved_destination_ != NULL);
166c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org
1677d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org  // Spilled value is in kLithiumScratchReg or kLithiumScratchDouble.
168c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  if (saved_destination_->IsRegister()) {
1697d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org    __ mov(cgen_->ToRegister(saved_destination_), kLithiumScratchReg);
170c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  } else if (saved_destination_->IsStackSlot()) {
1717d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org    __ sw(kLithiumScratchReg, cgen_->ToMemOperand(saved_destination_));
172c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  } else if (saved_destination_->IsDoubleRegister()) {
173c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    __ mov_d(cgen_->ToDoubleRegister(saved_destination_),
1742efb900e7350b14be905abdeab077f3a64c583cfulan@chromium.org            kLithiumScratchDouble);
175c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  } else if (saved_destination_->IsDoubleStackSlot()) {
1762efb900e7350b14be905abdeab077f3a64c583cfulan@chromium.org    __ sdc1(kLithiumScratchDouble,
177c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org            cgen_->ToMemOperand(saved_destination_));
178c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  } else {
179c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    UNREACHABLE();
180c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  }
181c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org
182c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  in_cycle_ = false;
183c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  saved_destination_ = NULL;
184c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org}
185c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org
186c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org
187c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.orgvoid LGapResolver::EmitMove(int index) {
188c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  LOperand* source = moves_[index].source();
189c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  LOperand* destination = moves_[index].destination();
190c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org
191c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  // Dispatch on the source and destination operand kinds.  Not all
192c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  // combinations are possible.
193c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org
194c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  if (source->IsRegister()) {
195c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    Register source_register = cgen_->ToRegister(source);
196c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    if (destination->IsRegister()) {
197c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org      __ mov(cgen_->ToRegister(destination), source_register);
198c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    } else {
199e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org      DCHECK(destination->IsStackSlot());
200c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org      __ sw(source_register, cgen_->ToMemOperand(destination));
201c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    }
202c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  } else if (source->IsStackSlot()) {
203c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    MemOperand source_operand = cgen_->ToMemOperand(source);
204c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    if (destination->IsRegister()) {
205c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org      __ lw(cgen_->ToRegister(destination), source_operand);
206c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    } else {
207e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org      DCHECK(destination->IsStackSlot());
208c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org      MemOperand destination_operand = cgen_->ToMemOperand(destination);
209c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org      if (in_cycle_) {
210c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org        if (!destination_operand.OffsetIsInt16Encodable()) {
211c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org          // 'at' is overwritten while saving the value to the destination.
212c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org          // Therefore we can't use 'at'.  It is OK if the read from the source
213c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org          // destroys 'at', since that happens before the value is read.
214c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org          // This uses only a single reg of the double reg-pair.
2152efb900e7350b14be905abdeab077f3a64c583cfulan@chromium.org          __ lwc1(kLithiumScratchDouble, source_operand);
2162efb900e7350b14be905abdeab077f3a64c583cfulan@chromium.org          __ swc1(kLithiumScratchDouble, destination_operand);
217c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org        } else {
218c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org          __ lw(at, source_operand);
219c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org          __ sw(at, destination_operand);
220c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org        }
221c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org      } else {
2227d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org        __ lw(kLithiumScratchReg, source_operand);
2237d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org        __ sw(kLithiumScratchReg, destination_operand);
224c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org      }
225c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    }
226c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org
227c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  } else if (source->IsConstantOperand()) {
228fab1498f2f42726c7de46c3ed560d56dd072a8b3rossberg@chromium.org    LConstantOperand* constant_source = LConstantOperand::cast(source);
229c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    if (destination->IsRegister()) {
230fab1498f2f42726c7de46c3ed560d56dd072a8b3rossberg@chromium.org      Register dst = cgen_->ToRegister(destination);
231fb732b17922ea75830be4db6b80534c4827d8a55jkummerow@chromium.org      Representation r = cgen_->IsSmi(constant_source)
232fb732b17922ea75830be4db6b80534c4827d8a55jkummerow@chromium.org          ? Representation::Smi() : Representation::Integer32();
233fb732b17922ea75830be4db6b80534c4827d8a55jkummerow@chromium.org      if (cgen_->IsInteger32(constant_source)) {
234fb732b17922ea75830be4db6b80534c4827d8a55jkummerow@chromium.org        __ li(dst, Operand(cgen_->ToRepresentation(constant_source, r)));
235fab1498f2f42726c7de46c3ed560d56dd072a8b3rossberg@chromium.org      } else {
236057bd50c2c2d15923523777a296cddee5c8ba63bverwaest@chromium.org        __ li(dst, cgen_->ToHandle(constant_source));
237fab1498f2f42726c7de46c3ed560d56dd072a8b3rossberg@chromium.org      }
238594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org    } else if (destination->IsDoubleRegister()) {
239e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org      DoubleRegister result = cgen_->ToDoubleRegister(destination);
240e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org      double v = cgen_->ToDouble(constant_source);
241e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org      __ Move(result, v);
242c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    } else {
243e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org      DCHECK(destination->IsStackSlot());
244e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org      DCHECK(!in_cycle_);  // Constant moves happen after all cycles are gone.
245fb732b17922ea75830be4db6b80534c4827d8a55jkummerow@chromium.org      Representation r = cgen_->IsSmi(constant_source)
246fb732b17922ea75830be4db6b80534c4827d8a55jkummerow@chromium.org          ? Representation::Smi() : Representation::Integer32();
247fb732b17922ea75830be4db6b80534c4827d8a55jkummerow@chromium.org      if (cgen_->IsInteger32(constant_source)) {
2487d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org        __ li(kLithiumScratchReg,
249fb732b17922ea75830be4db6b80534c4827d8a55jkummerow@chromium.org              Operand(cgen_->ToRepresentation(constant_source, r)));
250fab1498f2f42726c7de46c3ed560d56dd072a8b3rossberg@chromium.org      } else {
251057bd50c2c2d15923523777a296cddee5c8ba63bverwaest@chromium.org        __ li(kLithiumScratchReg, cgen_->ToHandle(constant_source));
252fab1498f2f42726c7de46c3ed560d56dd072a8b3rossberg@chromium.org      }
2537d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org      __ sw(kLithiumScratchReg, cgen_->ToMemOperand(destination));
254c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    }
255c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org
256c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  } else if (source->IsDoubleRegister()) {
257c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    DoubleRegister source_register = cgen_->ToDoubleRegister(source);
258c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    if (destination->IsDoubleRegister()) {
259c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org      __ mov_d(cgen_->ToDoubleRegister(destination), source_register);
260c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    } else {
261e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org      DCHECK(destination->IsDoubleStackSlot());
262c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org      MemOperand destination_operand = cgen_->ToMemOperand(destination);
263c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org      __ sdc1(source_register, destination_operand);
264c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    }
265c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org
266c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  } else if (source->IsDoubleStackSlot()) {
267c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    MemOperand source_operand = cgen_->ToMemOperand(source);
268c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    if (destination->IsDoubleRegister()) {
269c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org      __ ldc1(cgen_->ToDoubleRegister(destination), source_operand);
270c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    } else {
271e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org      DCHECK(destination->IsDoubleStackSlot());
272c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org      MemOperand destination_operand = cgen_->ToMemOperand(destination);
273c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org      if (in_cycle_) {
2742efb900e7350b14be905abdeab077f3a64c583cfulan@chromium.org        // kLithiumScratchDouble was used to break the cycle,
2757d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org        // but kLithiumScratchReg is free.
276c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org        MemOperand source_high_operand =
277c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org            cgen_->ToHighMemOperand(source);
278c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org        MemOperand destination_high_operand =
279c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org            cgen_->ToHighMemOperand(destination);
2807d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org        __ lw(kLithiumScratchReg, source_operand);
2817d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org        __ sw(kLithiumScratchReg, destination_operand);
2827d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org        __ lw(kLithiumScratchReg, source_high_operand);
2837d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org        __ sw(kLithiumScratchReg, destination_high_operand);
284c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org      } else {
2852efb900e7350b14be905abdeab077f3a64c583cfulan@chromium.org        __ ldc1(kLithiumScratchDouble, source_operand);
2862efb900e7350b14be905abdeab077f3a64c583cfulan@chromium.org        __ sdc1(kLithiumScratchDouble, destination_operand);
287c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org      }
288c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    }
289c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  } else {
290c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    UNREACHABLE();
291c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  }
292c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org
293c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  moves_[index].Eliminate();
294c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org}
295c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org
296c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org
297c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org#undef __
298c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org
299c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org} }  // namespace v8::internal
300