js/src/jit/mips/MoveEmitter-mips.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
     2  * vim: set ts=8 sts=4 et sw=4 tw=99:
     3  * This Source Code Form is subject to the terms of the Mozilla Public
     4  * License, v. 2.0. If a copy of the MPL was not distributed with this
     5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     7 #include "jit/mips/MoveEmitter-mips.h"
     9 using namespace js;
    10 using namespace js::jit;
    12 MoveEmitterMIPS::MoveEmitterMIPS(MacroAssemblerMIPSCompat &masm)
    13   : inCycle_(false),
    14     masm(masm),
    15     pushedAtCycle_(-1),
    16     pushedAtSpill_(-1),
    17     spilledReg_(InvalidReg),
    18     spilledFloatReg_(InvalidFloatReg)
    19 {
    20     pushedAtStart_ = masm.framePushed();
    21 }
    23 void
    24 MoveEmitterMIPS::emit(const MoveResolver &moves)
    25 {
    26     if (moves.hasCycles()) {
    27         // Reserve stack for cycle resolution
    28         masm.reserveStack(sizeof(double));
    29         pushedAtCycle_ = masm.framePushed();
    30     }
    32     for (size_t i = 0; i < moves.numMoves(); i++)
    33         emit(moves.getMove(i));
    34 }
    36 MoveEmitterMIPS::~MoveEmitterMIPS()
    37 {
    38     assertDone();
    39 }
    41 Address
    42 MoveEmitterMIPS::cycleSlot() const
    43 {
    44     int offset = masm.framePushed() - pushedAtCycle_;
    45     MOZ_ASSERT(Imm16::isInSignedRange(offset));
    46     return Address(StackPointer, offset);
    47 }
    49 int32_t
    50 MoveEmitterMIPS::getAdjustedOffset(const MoveOperand &operand)
    51 {
    52     MOZ_ASSERT(operand.isMemoryOrEffectiveAddress());
    53     if (operand.base() != StackPointer)
    54         return operand.disp();
    56     // Adjust offset if stack pointer has been moved.
    57     return operand.disp() + masm.framePushed() - pushedAtStart_;
    58 }
    60 Address
    61 MoveEmitterMIPS::getAdjustedAddress(const MoveOperand &operand)
    62 {
    63     return Address(operand.base(), getAdjustedOffset(operand));
    64 }
    67 Register
    68 MoveEmitterMIPS::tempReg()
    69 {
    70     spilledReg_ = SecondScratchReg;
    71     return SecondScratchReg;
    72 }
    74 void
    75 MoveEmitterMIPS::breakCycle(const MoveOperand &from, const MoveOperand &to, MoveOp::Type type)
    76 {
    77     // There is some pattern:
    78     //   (A -> B)
    79     //   (B -> A)
    80     //
    81     // This case handles (A -> B), which we reach first. We save B, then allow
    82     // the original move to continue.
    83     switch (type) {
    84       case MoveOp::FLOAT32:
    85         if (to.isMemory()) {
    86             FloatRegister temp = ScratchFloatReg;
    87             masm.loadFloat32(getAdjustedAddress(to), temp);
    88             masm.storeFloat32(temp, cycleSlot());
    89         } else {
    90             masm.storeFloat32(to.floatReg(), cycleSlot());
    91         }
    92         break;
    93       case MoveOp::DOUBLE:
    94         if (to.isMemory()) {
    95             FloatRegister temp = ScratchFloatReg;
    96             masm.loadDouble(getAdjustedAddress(to), temp);
    97             masm.storeDouble(temp, cycleSlot());
    98         } else {
    99             masm.storeDouble(to.floatReg(), cycleSlot());
   100         }
   101         break;
   102       case MoveOp::INT32:
   103         MOZ_ASSERT(sizeof(uintptr_t) == sizeof(int32_t));
   104       case MoveOp::GENERAL:
   105         if (to.isMemory()) {
   106             Register temp = tempReg();
   107             masm.loadPtr(getAdjustedAddress(to), temp);
   108             masm.storePtr(temp, cycleSlot());
   109         } else {
   110             // Second scratch register should not be moved by MoveEmitter.
   111             MOZ_ASSERT(to.reg() != spilledReg_);
   112             masm.storePtr(to.reg(), cycleSlot());
   113         }
   114         break;
   115       default:
   116         MOZ_ASSUME_UNREACHABLE("Unexpected move type");
   117     }
   118 }
   120 void
   121 MoveEmitterMIPS::completeCycle(const MoveOperand &from, const MoveOperand &to, MoveOp::Type type)
   122 {
   123     // There is some pattern:
   124     //   (A -> B)
   125     //   (B -> A)
   126     //
   127     // This case handles (B -> A), which we reach last. We emit a move from the
   128     // saved value of B, to A.
   129     switch (type) {
   130       case MoveOp::FLOAT32:
   131         if (to.isMemory()) {
   132             FloatRegister temp = ScratchFloatReg;
   133             masm.loadFloat32(cycleSlot(), temp);
   134             masm.storeFloat32(temp, getAdjustedAddress(to));
   135         } else {
   136             masm.loadFloat32(cycleSlot(), to.floatReg());
   137         }
   138         break;
   139       case MoveOp::DOUBLE:
   140         if (to.isMemory()) {
   141             FloatRegister temp = ScratchFloatReg;
   142             masm.loadDouble(cycleSlot(), temp);
   143             masm.storeDouble(temp, getAdjustedAddress(to));
   144         } else {
   145             masm.loadDouble(cycleSlot(), to.floatReg());
   146         }
   147         break;
   148       case MoveOp::INT32:
   149         MOZ_ASSERT(sizeof(uintptr_t) == sizeof(int32_t));
   150       case MoveOp::GENERAL:
   151         if (to.isMemory()) {
   152             Register temp = tempReg();
   153             masm.loadPtr(cycleSlot(), temp);
   154             masm.storePtr(temp, getAdjustedAddress(to));
   155         } else {
   156             // Second scratch register should not be moved by MoveEmitter.
   157             MOZ_ASSERT(to.reg() != spilledReg_);
   158             masm.loadPtr(cycleSlot(), to.reg());
   159         }
   160         break;
   161       default:
   162         MOZ_ASSUME_UNREACHABLE("Unexpected move type");
   163     }
   164 }
   166 void
   167 MoveEmitterMIPS::emitMove(const MoveOperand &from, const MoveOperand &to)
   168 {
   169     if (from.isGeneralReg()) {
   170         // Second scratch register should not be moved by MoveEmitter.
   171         MOZ_ASSERT(from.reg() != spilledReg_);
   173         if (to.isGeneralReg())
   174             masm.movePtr(from.reg(), to.reg());
   175         else if (to.isMemory())
   176             masm.storePtr(from.reg(), getAdjustedAddress(to));
   177         else
   178             MOZ_ASSUME_UNREACHABLE("Invalid emitMove arguments.");
   179     } else if (from.isMemory()) {
   180         if (to.isGeneralReg()) {
   181             masm.loadPtr(getAdjustedAddress(from), to.reg());
   182         } else if (to.isMemory()) {
   183             masm.loadPtr(getAdjustedAddress(from), tempReg());
   184             masm.storePtr(tempReg(), getAdjustedAddress(to));
   185         } else {
   186             MOZ_ASSUME_UNREACHABLE("Invalid emitMove arguments.");
   187         }
   188     } else if (from.isEffectiveAddress()) {
   189         if (to.isGeneralReg()) {
   190             masm.computeEffectiveAddress(getAdjustedAddress(from), to.reg());
   191         } else if (to.isMemory()) {
   192             masm.computeEffectiveAddress(getAdjustedAddress(from), tempReg());
   193             masm.storePtr(tempReg(), getAdjustedAddress(to));
   194         } else {
   195             MOZ_ASSUME_UNREACHABLE("Invalid emitMove arguments.");
   196         }
   197     } else {
   198         MOZ_ASSUME_UNREACHABLE("Invalid emitMove arguments.");
   199     }
   200 }
   202 void
   203 MoveEmitterMIPS::emitFloat32Move(const MoveOperand &from, const MoveOperand &to)
   204 {
   205     // Ensure that we can use ScratchFloatReg in memory move.
   206     MOZ_ASSERT_IF(from.isFloatReg(), from.floatReg() != ScratchFloatReg);
   207     MOZ_ASSERT_IF(to.isFloatReg(), to.floatReg() != ScratchFloatReg);
   209     if (from.isFloatReg()) {
   210         if (to.isFloatReg()) {
   211             masm.moveFloat32(from.floatReg(), to.floatReg());
   212         } else if (to.isGeneralReg()) {
   213             // This should only be used when passing float parameter in a1,a2,a3
   214             MOZ_ASSERT(to.reg() == a1 || to.reg() == a2 || to.reg() == a3);
   215             masm.moveFromFloat32(from.floatReg(), to.reg());
   216         } else {
   217             MOZ_ASSERT(to.isMemory());
   218             masm.storeFloat32(from.floatReg(), getAdjustedAddress(to));
   219         }
   220     } else if (to.isFloatReg()) {
   221         MOZ_ASSERT(from.isMemory());
   222         masm.loadFloat32(getAdjustedAddress(from), to.floatReg());
   223     } else if (to.isGeneralReg()) {
   224         MOZ_ASSERT(from.isMemory());
   225         // This should only be used when passing float parameter in a1,a2,a3
   226         MOZ_ASSERT(to.reg() == a1 || to.reg() == a2 || to.reg() == a3);
   227         masm.loadPtr(getAdjustedAddress(from), to.reg());
   228     } else {
   229         MOZ_ASSERT(from.isMemory());
   230         MOZ_ASSERT(to.isMemory());
   231         masm.loadFloat32(getAdjustedAddress(from), ScratchFloatReg);
   232         masm.storeFloat32(ScratchFloatReg, getAdjustedAddress(to));
   233     }
   234 }
   236 void
   237 MoveEmitterMIPS::emitDoubleMove(const MoveOperand &from, const MoveOperand &to)
   238 {
   239     // Ensure that we can use ScratchFloatReg in memory move.
   240     MOZ_ASSERT_IF(from.isFloatReg(), from.floatReg() != ScratchFloatReg);
   241     MOZ_ASSERT_IF(to.isFloatReg(), to.floatReg() != ScratchFloatReg);
   243     if (from.isFloatReg()) {
   244         if (to.isFloatReg()) {
   245             masm.moveDouble(from.floatReg(), to.floatReg());
   246         } else if (to.isGeneralReg()) {
   247             // Used for passing double parameter in a2,a3 register pair.
   248             // Two moves are added for one double parameter by
   249             // MacroAssemblerMIPSCompat::passABIArg
   250             if(to.reg() == a2)
   251                 masm.moveFromDoubleLo(from.floatReg(), a2);
   252             else if(to.reg() == a3)
   253                 masm.moveFromDoubleHi(from.floatReg(), a3);
   254             else
   255                 MOZ_ASSUME_UNREACHABLE("Invalid emitDoubleMove arguments.");
   256         } else {
   257             MOZ_ASSERT(to.isMemory());
   258             masm.storeDouble(from.floatReg(), getAdjustedAddress(to));
   259         }
   260     } else if (to.isFloatReg()) {
   261         MOZ_ASSERT(from.isMemory());
   262         masm.loadDouble(getAdjustedAddress(from), to.floatReg());
   263     } else if (to.isGeneralReg()) {
   264         MOZ_ASSERT(from.isMemory());
   265         // Used for passing double parameter in a2,a3 register pair.
   266         // Two moves are added for one double parameter by
   267         // MacroAssemblerMIPSCompat::passABIArg
   268         if(to.reg() == a2)
   269             masm.loadPtr(getAdjustedAddress(from), a2);
   270         else if(to.reg() == a3)
   271             masm.loadPtr(Address(from.base(), getAdjustedOffset(from) + sizeof(uint32_t)), a3);
   272         else
   273             MOZ_ASSUME_UNREACHABLE("Invalid emitDoubleMove arguments.");
   274     } else {
   275         MOZ_ASSERT(from.isMemory());
   276         MOZ_ASSERT(to.isMemory());
   277         masm.loadDouble(getAdjustedAddress(from), ScratchFloatReg);
   278         masm.storeDouble(ScratchFloatReg, getAdjustedAddress(to));
   279     }
   280 }
   282 void
   283 MoveEmitterMIPS::emit(const MoveOp &move)
   284 {
   285     const MoveOperand &from = move.from();
   286     const MoveOperand &to = move.to();
   288     if (move.isCycleEnd()) {
   289         MOZ_ASSERT(inCycle_);
   290         completeCycle(from, to, move.type());
   291         inCycle_ = false;
   292         return;
   293     }
   295     if (move.isCycleBegin()) {
   296         MOZ_ASSERT(!inCycle_);
   297         breakCycle(from, to, move.endCycleType());
   298         inCycle_ = true;
   299     }
   301     switch (move.type()) {
   302       case MoveOp::FLOAT32:
   303         emitFloat32Move(from, to);
   304         break;
   305       case MoveOp::DOUBLE:
   306         emitDoubleMove(from, to);
   307         break;
   308       case MoveOp::INT32:
   309         MOZ_ASSERT(sizeof(uintptr_t) == sizeof(int32_t));
   310       case MoveOp::GENERAL:
   311         emitMove(from, to);
   312         break;
   313       default:
   314         MOZ_ASSUME_UNREACHABLE("Unexpected move type");
   315     }
   316 }
   318 void
   319 MoveEmitterMIPS::assertDone()
   320 {
   321     MOZ_ASSERT(!inCycle_);
   322 }
   324 void
   325 MoveEmitterMIPS::finish()
   326 {
   327     assertDone();
   329     masm.freeStack(masm.framePushed() - pushedAtStart_);
   330 }

mercurial