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