10511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com// Copyright 2011 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. 40511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com 5196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/v8.h" 6ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org 793a47f4837f2137c8d8349250fd8e91da3108126jkummerow@chromium.org#if V8_TARGET_ARCH_IA32 8c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org 9196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/ia32/lithium-codegen-ia32.h" 104b0feeef5d01dbc2948080b4f69daa37e1083461machenbach@chromium.org#include "src/ia32/lithium-gap-resolver-ia32.h" 110511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com 120511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.comnamespace v8 { 130511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.comnamespace internal { 140511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com 150511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.comLGapResolver::LGapResolver(LCodeGen* owner) 160ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org : cgen_(owner), 177028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org moves_(32, owner->zone()), 180ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org source_uses_(), 190ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org destination_uses_(), 200ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org spilled_register_(-1) {} 210511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com 220511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com 230511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.comvoid LGapResolver::Resolve(LParallelMove* parallel_move) { 24e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(HasBeenReset()); 250511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com // Build up a worklist of moves. 260511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com BuildInitialMoveList(parallel_move); 270511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com 280511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com for (int i = 0; i < moves_.length(); ++i) { 290511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com LMoveOperands move = moves_[i]; 300511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com // Skip constants to perform them last. They don't block other moves 310511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com // and skipping such moves with register destinations keeps those 320511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com // registers free for the whole algorithm. 330511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com if (!move.IsEliminated() && !move.source()->IsConstantOperand()) { 340511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com PerformMove(i); 350511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com } 360511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com } 370511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com 380511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com // Perform the moves with constant sources. 390511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com for (int i = 0; i < moves_.length(); ++i) { 400511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com if (!moves_[i].IsEliminated()) { 41e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(moves_[i].source()->IsConstantOperand()); 420511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com EmitMove(i); 430511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com } 440511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com } 450511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com 460511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com Finish(); 47e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(HasBeenReset()); 480511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com} 490511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com 500511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com 510511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.comvoid LGapResolver::BuildInitialMoveList(LParallelMove* parallel_move) { 520511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com // Perform a linear sweep of the moves to add them to the initial list of 530511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com // moves to perform, ignoring any move that is redundant (the source is 540511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com // the same as the destination, the destination is ignored and 550511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com // unallocated, or the move was already eliminated). 560511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com const ZoneList<LMoveOperands>* moves = parallel_move->move_operands(); 570511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com for (int i = 0; i < moves->length(); ++i) { 580511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com LMoveOperands move = moves->at(i); 590511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com if (!move.IsRedundant()) AddMove(move); 600511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com } 610511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com Verify(); 620511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com} 630511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com 640511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com 650511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.comvoid LGapResolver::PerformMove(int index) { 660511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com // Each call to this function performs a move and deletes it from the move 670511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com // graph. We first recursively perform any move blocking this one. We 680511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com // mark a move as "pending" on entry to PerformMove in order to detect 690511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com // cycles in the move graph. We use operand swaps to resolve cycles, 700511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com // which means that a call to PerformMove could change any source operand 710511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com // in the move graph. 720511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com 73e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(!moves_[index].IsPending()); 74e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(!moves_[index].IsRedundant()); 750511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com 760511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com // Clear this move's destination to indicate a pending move. The actual 770511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com // destination is saved on the side. 78e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(moves_[index].source() != NULL); // Or else it will look eliminated. 790511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com LOperand* destination = moves_[index].destination(); 800511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com moves_[index].set_destination(NULL); 810511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com 820511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com // Perform a depth-first traversal of the move graph to resolve 830511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com // dependencies. Any unperformed, unpending move with a source the same 840511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com // as this one's destination blocks this one so recursively perform all 850511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com // such moves. 860511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com for (int i = 0; i < moves_.length(); ++i) { 870511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com LMoveOperands other_move = moves_[i]; 880511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com if (other_move.Blocks(destination) && !other_move.IsPending()) { 890511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com // Though PerformMove can change any source operand in the move graph, 900511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com // this call cannot create a blocking move via a swap (this loop does 910511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com // not miss any). Assume there is a non-blocking move with source A 920511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com // and this move is blocked on source B and there is a swap of A and 930511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com // B. Then A and B must be involved in the same cycle (or they would 940511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com // not be swapped). Since this move's destination is B and there is 950511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com // only a single incoming edge to an operand, this move must also be 960511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com // involved in the same cycle. In that case, the blocking move will 970511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com // be created but will be "pending" when we return from PerformMove. 980511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com PerformMove(i); 990511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com } 1000511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com } 1010511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com 1020511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com // We are about to resolve this move and don't need it marked as 1030511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com // pending, so restore its destination. 1040511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com moves_[index].set_destination(destination); 1050511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com 1060511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com // This move's source may have changed due to swaps to resolve cycles and 1070511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com // so it may now be the last move in the cycle. If so remove it. 1080511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com if (moves_[index].source()->Equals(destination)) { 1090511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com RemoveMove(index); 1100511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com return; 1110511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com } 1120511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com 1130511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com // The move may be blocked on a (at most one) pending move, in which case 1140511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com // we have a cycle. Search for such a blocking move and perform a swap to 1150511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com // resolve it. 1160511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com for (int i = 0; i < moves_.length(); ++i) { 1170511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com LMoveOperands other_move = moves_[i]; 1180511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com if (other_move.Blocks(destination)) { 119e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(other_move.IsPending()); 1200511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com EmitSwap(index); 1210511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com return; 1220511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com } 1230511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com } 1240511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com 1250511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com // This move is not blocked. 1260511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com EmitMove(index); 1270511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com} 1280511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com 1290511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com 1300511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.comvoid LGapResolver::AddMove(LMoveOperands move) { 1310511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com LOperand* source = move.source(); 1320511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com if (source->IsRegister()) ++source_uses_[source->index()]; 1330511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com 1340511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com LOperand* destination = move.destination(); 1350511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com if (destination->IsRegister()) ++destination_uses_[destination->index()]; 1360511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com 1377028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org moves_.Add(move, cgen_->zone()); 1380511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com} 1390511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com 1400511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com 1410511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.comvoid LGapResolver::RemoveMove(int index) { 1420511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com LOperand* source = moves_[index].source(); 1430511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com if (source->IsRegister()) { 1440511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com --source_uses_[source->index()]; 145e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(source_uses_[source->index()] >= 0); 1460511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com } 1470511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com 1480511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com LOperand* destination = moves_[index].destination(); 1490511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com if (destination->IsRegister()) { 1500511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com --destination_uses_[destination->index()]; 151e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(destination_uses_[destination->index()] >= 0); 1520511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com } 1530511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com 1540511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com moves_[index].Eliminate(); 1550511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com} 1560511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com 1570511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com 1580511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.comint LGapResolver::CountSourceUses(LOperand* operand) { 1590511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com int count = 0; 1600511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com for (int i = 0; i < moves_.length(); ++i) { 1610511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com if (!moves_[i].IsEliminated() && moves_[i].source()->Equals(operand)) { 1620511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com ++count; 1630511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com } 1640511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com } 1650511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com return count; 1660511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com} 1670511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com 1680511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com 1690511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.comRegister LGapResolver::GetFreeRegisterNot(Register reg) { 1700511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com int skip_index = reg.is(no_reg) ? -1 : Register::ToAllocationIndex(reg); 171a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org for (int i = 0; i < Register::NumAllocatableRegisters(); ++i) { 1720511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com if (source_uses_[i] == 0 && destination_uses_[i] > 0 && i != skip_index) { 1730511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com return Register::FromAllocationIndex(i); 1740511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com } 1750511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com } 1760511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com return no_reg; 1770511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com} 1780511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com 1790511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com 1800511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.combool LGapResolver::HasBeenReset() { 1810511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com if (!moves_.is_empty()) return false; 1820511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com if (spilled_register_ >= 0) return false; 1830511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com 184a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org for (int i = 0; i < Register::NumAllocatableRegisters(); ++i) { 1850511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com if (source_uses_[i] != 0) return false; 1860511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com if (destination_uses_[i] != 0) return false; 1870511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com } 1880511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com return true; 1890511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com} 1900511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com 1910511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com 1920511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.comvoid LGapResolver::Verify() { 193e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org#ifdef ENABLE_SLOW_DCHECKS 1940511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com // No operand should be the destination for more than one move. 1950511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com for (int i = 0; i < moves_.length(); ++i) { 1960511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com LOperand* destination = moves_[i].destination(); 1970511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com for (int j = i + 1; j < moves_.length(); ++j) { 198e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org SLOW_DCHECK(!destination->Equals(moves_[j].destination())); 1990511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com } 2000511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com } 2010511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com#endif 2020511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com} 2030511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com 2040511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com 2050511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com#define __ ACCESS_MASM(cgen_->masm()) 2060511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com 2070511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.comvoid LGapResolver::Finish() { 2080511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com if (spilled_register_ >= 0) { 2090511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com __ pop(Register::FromAllocationIndex(spilled_register_)); 2100511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com spilled_register_ = -1; 2110511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com } 2120511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com moves_.Rewind(0); 2130511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com} 2140511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com 2150511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com 2160511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.comvoid LGapResolver::EnsureRestored(LOperand* operand) { 2170511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com if (operand->IsRegister() && operand->index() == spilled_register_) { 2180511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com __ pop(Register::FromAllocationIndex(spilled_register_)); 2190511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com spilled_register_ = -1; 2200511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com } 2210511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com} 2220511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com 2230511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com 2240511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.comRegister LGapResolver::EnsureTempRegister() { 2250511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com // 1. We may have already spilled to create a temp register. 2260511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com if (spilled_register_ >= 0) { 2270511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com return Register::FromAllocationIndex(spilled_register_); 2280511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com } 2290511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com 2300511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com // 2. We may have a free register that we can use without spilling. 2310511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com Register free = GetFreeRegisterNot(no_reg); 2320511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com if (!free.is(no_reg)) return free; 2330511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com 2340511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com // 3. Prefer to spill a register that is not used in any remaining move 2350511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com // because it will not need to be restored until the end. 236a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org for (int i = 0; i < Register::NumAllocatableRegisters(); ++i) { 2370511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com if (source_uses_[i] == 0 && destination_uses_[i] == 0) { 2380511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com Register scratch = Register::FromAllocationIndex(i); 2390511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com __ push(scratch); 2400511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com spilled_register_ = i; 2410511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com return scratch; 2420511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com } 2430511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com } 2440511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com 2450511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com // 4. Use an arbitrary register. Register 0 is as arbitrary as any other. 2460511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com Register scratch = Register::FromAllocationIndex(0); 2470511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com __ push(scratch); 2480511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com spilled_register_ = 0; 2490511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com return scratch; 2500511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com} 2510511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com 2520511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com 2530511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.comvoid LGapResolver::EmitMove(int index) { 2540511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com LOperand* source = moves_[index].source(); 2550511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com LOperand* destination = moves_[index].destination(); 2560511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com EnsureRestored(source); 2570511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com EnsureRestored(destination); 2580511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com 2590511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com // Dispatch on the source and destination operand kinds. Not all 2600511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com // combinations are possible. 2610511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com if (source->IsRegister()) { 262e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(destination->IsRegister() || destination->IsStackSlot()); 2630511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com Register src = cgen_->ToRegister(source); 2640511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com Operand dst = cgen_->ToOperand(destination); 2650511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com __ mov(dst, src); 2660511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com 2670511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com } else if (source->IsStackSlot()) { 268e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(destination->IsRegister() || destination->IsStackSlot()); 2690511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com Operand src = cgen_->ToOperand(source); 2700511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com if (destination->IsRegister()) { 2710511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com Register dst = cgen_->ToRegister(destination); 2720511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com __ mov(dst, src); 2730511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com } else { 2740511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com // Spill on demand to use a temporary register for memory-to-memory 2750511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com // moves. 2760511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com Register tmp = EnsureTempRegister(); 2770511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com Operand dst = cgen_->ToOperand(destination); 2780511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com __ mov(tmp, src); 2790511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com __ mov(dst, tmp); 2800511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com } 2810511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com 2820511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com } else if (source->IsConstantOperand()) { 283bf0c820d028452571c8c744ddd212c32c6d6a996danno@chromium.org LConstantOperand* constant_source = LConstantOperand::cast(source); 2846db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org if (destination->IsRegister()) { 2856db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org Register dst = cgen_->ToRegister(destination); 286fb732b17922ea75830be4db6b80534c4827d8a55jkummerow@chromium.org Representation r = cgen_->IsSmi(constant_source) 287fb732b17922ea75830be4db6b80534c4827d8a55jkummerow@chromium.org ? Representation::Smi() : Representation::Integer32(); 288fb732b17922ea75830be4db6b80534c4827d8a55jkummerow@chromium.org if (cgen_->IsInteger32(constant_source)) { 289a221880197f38ff22d942851060daffa5d036bdfmachenbach@chromium.org __ Move(dst, cgen_->ToImmediate(constant_source, r)); 290bf0c820d028452571c8c744ddd212c32c6d6a996danno@chromium.org } else { 291bf0c820d028452571c8c744ddd212c32c6d6a996danno@chromium.org __ LoadObject(dst, cgen_->ToHandle(constant_source)); 292bf0c820d028452571c8c744ddd212c32c6d6a996danno@chromium.org } 293e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org } else if (destination->IsDoubleRegister()) { 294e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org double v = cgen_->ToDouble(constant_source); 295e20e19efeef112c26d0e63b1e5118e695b42d855machenbach@chromium.org uint64_t int_val = bit_cast<uint64_t, double>(v); 296e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org int32_t lower = static_cast<int32_t>(int_val); 297e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org int32_t upper = static_cast<int32_t>(int_val >> kBitsPerInt); 2983c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org XMMRegister dst = cgen_->ToDoubleRegister(destination); 2993c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org if (int_val == 0) { 3003c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org __ xorps(dst, dst); 301e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org } else { 302e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org __ push(Immediate(upper)); 303e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org __ push(Immediate(lower)); 3043c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org __ movsd(dst, Operand(esp, 0)); 305e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org __ add(esp, Immediate(kDoubleSize)); 306e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org } 3076db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org } else { 308e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(destination->IsStackSlot()); 3096db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org Operand dst = cgen_->ToOperand(destination); 310fb732b17922ea75830be4db6b80534c4827d8a55jkummerow@chromium.org Representation r = cgen_->IsSmi(constant_source) 311fb732b17922ea75830be4db6b80534c4827d8a55jkummerow@chromium.org ? Representation::Smi() : Representation::Integer32(); 312fb732b17922ea75830be4db6b80534c4827d8a55jkummerow@chromium.org if (cgen_->IsInteger32(constant_source)) { 313a221880197f38ff22d942851060daffa5d036bdfmachenbach@chromium.org __ Move(dst, cgen_->ToImmediate(constant_source, r)); 314bf0c820d028452571c8c744ddd212c32c6d6a996danno@chromium.org } else { 315bf0c820d028452571c8c744ddd212c32c6d6a996danno@chromium.org Register tmp = EnsureTempRegister(); 316bf0c820d028452571c8c744ddd212c32c6d6a996danno@chromium.org __ LoadObject(tmp, cgen_->ToHandle(constant_source)); 317bf0c820d028452571c8c744ddd212c32c6d6a996danno@chromium.org __ mov(dst, tmp); 318bf0c820d028452571c8c744ddd212c32c6d6a996danno@chromium.org } 3196db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org } 3200511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com 3210511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com } else if (source->IsDoubleRegister()) { 3223c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org XMMRegister src = cgen_->ToDoubleRegister(source); 3233c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org if (destination->IsDoubleRegister()) { 3243c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org XMMRegister dst = cgen_->ToDoubleRegister(destination); 3253c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org __ movaps(dst, src); 326dcebac0f4c6c0da579b7cc91a0cbba8f3c820c8dricow@chromium.org } else { 327e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(destination->IsDoubleStackSlot()); 3284121f23c2a08f8ef03858df1477b81a0450b94a0ulan@chromium.org Operand dst = cgen_->ToOperand(destination); 3293c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org __ movsd(dst, src); 330dcebac0f4c6c0da579b7cc91a0cbba8f3c820c8dricow@chromium.org } 3310511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com } else if (source->IsDoubleStackSlot()) { 332e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(destination->IsDoubleRegister() || 3333c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org destination->IsDoubleStackSlot()); 3343c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org Operand src = cgen_->ToOperand(source); 3353c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org if (destination->IsDoubleRegister()) { 3363c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org XMMRegister dst = cgen_->ToDoubleRegister(destination); 3373c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org __ movsd(dst, src); 3380511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com } else { 3393c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org // We rely on having xmm0 available as a fixed scratch register. 3403c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org Operand dst = cgen_->ToOperand(destination); 3413c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org __ movsd(xmm0, src); 3423c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org __ movsd(dst, xmm0); 3430511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com } 3440511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com } else { 3450511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com UNREACHABLE(); 3460511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com } 3470511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com 3480511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com RemoveMove(index); 3490511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com} 3500511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com 3510511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com 3520511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.comvoid LGapResolver::EmitSwap(int index) { 3530511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com LOperand* source = moves_[index].source(); 3540511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com LOperand* destination = moves_[index].destination(); 3550511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com EnsureRestored(source); 3560511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com EnsureRestored(destination); 3570511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com 3580511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com // Dispatch on the source and destination operand kinds. Not all 3590511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com // combinations are possible. 3600511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com if (source->IsRegister() && destination->IsRegister()) { 3610511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com // Register-register. 3620511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com Register src = cgen_->ToRegister(source); 3630511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com Register dst = cgen_->ToRegister(destination); 3640511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com __ xchg(dst, src); 3650511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com 3660511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com } else if ((source->IsRegister() && destination->IsStackSlot()) || 3670511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com (source->IsStackSlot() && destination->IsRegister())) { 3680511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com // Register-memory. Use a free register as a temp if possible. Do not 3690511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com // spill on demand because the simple spill implementation cannot avoid 3700511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com // spilling src at this point. 3710511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com Register tmp = GetFreeRegisterNot(no_reg); 3720511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com Register reg = 3730511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com cgen_->ToRegister(source->IsRegister() ? source : destination); 3740511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com Operand mem = 3750511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com cgen_->ToOperand(source->IsRegister() ? destination : source); 3760511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com if (tmp.is(no_reg)) { 3770511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com __ xor_(reg, mem); 3780511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com __ xor_(mem, reg); 3790511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com __ xor_(reg, mem); 3800511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com } else { 3810511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com __ mov(tmp, mem); 3820511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com __ mov(mem, reg); 3830511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com __ mov(reg, tmp); 3840511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com } 3850511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com 3860511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com } else if (source->IsStackSlot() && destination->IsStackSlot()) { 3870511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com // Memory-memory. Spill on demand to use a temporary. If there is a 3880511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com // free register after that, use it as a second temporary. 3890511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com Register tmp0 = EnsureTempRegister(); 3900511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com Register tmp1 = GetFreeRegisterNot(tmp0); 3910511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com Operand src = cgen_->ToOperand(source); 3920511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com Operand dst = cgen_->ToOperand(destination); 3930511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com if (tmp1.is(no_reg)) { 3940511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com // Only one temp register available to us. 3950511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com __ mov(tmp0, dst); 3960511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com __ xor_(tmp0, src); 3970511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com __ xor_(src, tmp0); 3980511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com __ xor_(tmp0, src); 3990511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com __ mov(dst, tmp0); 4000511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com } else { 4010511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com __ mov(tmp0, dst); 4020511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com __ mov(tmp1, src); 4030511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com __ mov(dst, tmp1); 4040511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com __ mov(src, tmp0); 4050511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com } 406dcebac0f4c6c0da579b7cc91a0cbba8f3c820c8dricow@chromium.org } else if (source->IsDoubleRegister() && destination->IsDoubleRegister()) { 407dcebac0f4c6c0da579b7cc91a0cbba8f3c820c8dricow@chromium.org // XMM register-register swap. We rely on having xmm0 408dcebac0f4c6c0da579b7cc91a0cbba8f3c820c8dricow@chromium.org // available as a fixed scratch register. 409dcebac0f4c6c0da579b7cc91a0cbba8f3c820c8dricow@chromium.org XMMRegister src = cgen_->ToDoubleRegister(source); 410dcebac0f4c6c0da579b7cc91a0cbba8f3c820c8dricow@chromium.org XMMRegister dst = cgen_->ToDoubleRegister(destination); 411dcebac0f4c6c0da579b7cc91a0cbba8f3c820c8dricow@chromium.org __ movaps(xmm0, src); 412dcebac0f4c6c0da579b7cc91a0cbba8f3c820c8dricow@chromium.org __ movaps(src, dst); 413dcebac0f4c6c0da579b7cc91a0cbba8f3c820c8dricow@chromium.org __ movaps(dst, xmm0); 4140511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com } else if (source->IsDoubleRegister() || destination->IsDoubleRegister()) { 415dcebac0f4c6c0da579b7cc91a0cbba8f3c820c8dricow@chromium.org // XMM register-memory swap. We rely on having xmm0 4160511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com // available as a fixed scratch register. 417e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(source->IsDoubleStackSlot() || destination->IsDoubleStackSlot()); 4180511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com XMMRegister reg = cgen_->ToDoubleRegister(source->IsDoubleRegister() 419e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org ? source 420e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org : destination); 4210511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com Operand other = 4220511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com cgen_->ToOperand(source->IsDoubleRegister() ? destination : source); 4230fdb2a65d0f07bb7f6d6ce2f8337e00e5c9c323dbmeurer@chromium.org __ movsd(xmm0, other); 4240fdb2a65d0f07bb7f6d6ce2f8337e00e5c9c323dbmeurer@chromium.org __ movsd(other, reg); 425057bd50c2c2d15923523777a296cddee5c8ba63bverwaest@chromium.org __ movaps(reg, xmm0); 4260511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com } else if (source->IsDoubleStackSlot() && destination->IsDoubleStackSlot()) { 4270511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com // Double-width memory-to-memory. Spill on demand to use a general 4280511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com // purpose temporary register and also rely on having xmm0 available as 4290511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com // a fixed scratch register. 4300511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com Register tmp = EnsureTempRegister(); 4310511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com Operand src0 = cgen_->ToOperand(source); 4320511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com Operand src1 = cgen_->HighOperand(source); 4330511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com Operand dst0 = cgen_->ToOperand(destination); 4340511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com Operand dst1 = cgen_->HighOperand(destination); 4350fdb2a65d0f07bb7f6d6ce2f8337e00e5c9c323dbmeurer@chromium.org __ movsd(xmm0, dst0); // Save destination in xmm0. 4360511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com __ mov(tmp, src0); // Then use tmp to copy source to destination. 4370511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com __ mov(dst0, tmp); 4380511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com __ mov(tmp, src1); 4390511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com __ mov(dst1, tmp); 4400fdb2a65d0f07bb7f6d6ce2f8337e00e5c9c323dbmeurer@chromium.org __ movsd(src0, xmm0); 4410511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com 4420511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com } else { 4430511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com // No other combinations are possible. 4440511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com UNREACHABLE(); 4450511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com } 4460511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com 4470511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com // The swap of source and destination has executed a move from source to 4480511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com // destination. 4490511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com RemoveMove(index); 4500511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com 4510511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com // Any unperformed (including pending) move with a source of either 4520511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com // this move's source or destination needs to have their source 4530511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com // changed to reflect the state of affairs after the swap. 4540511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com for (int i = 0; i < moves_.length(); ++i) { 4550511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com LMoveOperands other_move = moves_[i]; 4560511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com if (other_move.Blocks(source)) { 4570511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com moves_[i].set_source(destination); 4580511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com } else if (other_move.Blocks(destination)) { 4590511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com moves_[i].set_source(source); 4600511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com } 4610511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com } 4620511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com 4630511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com // In addition to swapping the actual uses as sources, we need to update 4640511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com // the use counts. 4650511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com if (source->IsRegister() && destination->IsRegister()) { 4660511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com int temp = source_uses_[source->index()]; 4670511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com source_uses_[source->index()] = source_uses_[destination->index()]; 4680511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com source_uses_[destination->index()] = temp; 4690511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com } else if (source->IsRegister()) { 4700511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com // We don't have use counts for non-register operands like destination. 4710511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com // Compute those counts now. 4720511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com source_uses_[source->index()] = CountSourceUses(source); 4730511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com } else if (destination->IsRegister()) { 4740511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com source_uses_[destination->index()] = CountSourceUses(destination); 4750511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com } 4760511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com} 4770511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com 4780511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com#undef __ 4790511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com 4800511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com} } // namespace v8::internal 481c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org 482c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org#endif // V8_TARGET_ARCH_IA32 483