tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

MoveEmitter-mips-shared.cpp (6752B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
      2 * vim: set ts=8 sts=2 et sw=2 tw=80:
      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/. */
      6 
      7 #include "jit/mips-shared/MoveEmitter-mips-shared.h"
      8 
      9 #include "jit/MacroAssembler-inl.h"
     10 
     11 using namespace js;
     12 using namespace js::jit;
     13 
     14 void MoveEmitterMIPSShared::emit(const MoveResolver& moves) {
     15  if (moves.numCycles()) {
     16    // Reserve stack for cycle resolution
     17    static_assert(SpillSlotSize == 8);
     18    masm.reserveStack(moves.numCycles() * SpillSlotSize);
     19    pushedAtCycle_ = masm.framePushed();
     20  }
     21 
     22  for (size_t i = 0; i < moves.numMoves(); i++) {
     23    emit(moves.getMove(i));
     24  }
     25 }
     26 
     27 Address MoveEmitterMIPSShared::cycleSlot(uint32_t slot,
     28                                         uint32_t subslot) const {
     29  int32_t offset = masm.framePushed() - pushedAtCycle_;
     30  MOZ_ASSERT(Imm16::IsInSignedRange(offset));
     31  return Address(StackPointer, offset + slot * sizeof(double) + subslot);
     32 }
     33 
     34 int32_t MoveEmitterMIPSShared::getAdjustedOffset(const MoveOperand& operand) {
     35  MOZ_ASSERT(operand.isMemoryOrEffectiveAddress());
     36  if (operand.base() != StackPointer) {
     37    return operand.disp();
     38  }
     39 
     40  // Adjust offset if stack pointer has been moved.
     41  return operand.disp() + masm.framePushed() - pushedAtStart_;
     42 }
     43 
     44 Address MoveEmitterMIPSShared::getAdjustedAddress(const MoveOperand& operand) {
     45  return Address(operand.base(), getAdjustedOffset(operand));
     46 }
     47 
     48 Register MoveEmitterMIPSShared::tempReg() {
     49  spilledReg_ = ScratchRegister;
     50  return ScratchRegister;
     51 }
     52 
     53 void MoveEmitterMIPSShared::emitMove(const MoveOperand& from,
     54                                     const MoveOperand& to) {
     55  if (from.isGeneralReg()) {
     56    // Second scratch register should not be moved by MoveEmitter.
     57    MOZ_ASSERT(from.reg() != spilledReg_);
     58 
     59    if (to.isGeneralReg()) {
     60      masm.movePtr(from.reg(), to.reg());
     61    } else if (to.isMemory()) {
     62      masm.storePtr(from.reg(), getAdjustedAddress(to));
     63    } else {
     64      MOZ_CRASH("Invalid emitMove arguments.");
     65    }
     66  } else if (from.isMemory()) {
     67    if (to.isGeneralReg()) {
     68      masm.loadPtr(getAdjustedAddress(from), to.reg());
     69    } else if (to.isMemory()) {
     70      masm.loadPtr(getAdjustedAddress(from), tempReg());
     71      masm.storePtr(tempReg(), getAdjustedAddress(to));
     72    } else {
     73      MOZ_CRASH("Invalid emitMove arguments.");
     74    }
     75  } else if (from.isEffectiveAddress()) {
     76    if (to.isGeneralReg()) {
     77      masm.computeEffectiveAddress(getAdjustedAddress(from), to.reg());
     78    } else if (to.isMemory()) {
     79      masm.computeEffectiveAddress(getAdjustedAddress(from), tempReg());
     80      masm.storePtr(tempReg(), getAdjustedAddress(to));
     81    } else {
     82      MOZ_CRASH("Invalid emitMove arguments.");
     83    }
     84  } else {
     85    MOZ_CRASH("Invalid emitMove arguments.");
     86  }
     87 }
     88 
     89 void MoveEmitterMIPSShared::emitInt32Move(const MoveOperand& from,
     90                                          const MoveOperand& to) {
     91  if (from.isGeneralReg()) {
     92    // Second scratch register should not be moved by MoveEmitter.
     93    MOZ_ASSERT(from.reg() != spilledReg_);
     94 
     95    if (to.isGeneralReg()) {
     96      masm.move32(from.reg(), to.reg());
     97    } else if (to.isMemory()) {
     98      masm.store32(from.reg(), getAdjustedAddress(to));
     99    } else {
    100      MOZ_CRASH("Invalid emitInt32Move arguments.");
    101    }
    102  } else if (from.isMemory()) {
    103    if (to.isGeneralReg()) {
    104      masm.load32(getAdjustedAddress(from), to.reg());
    105    } else if (to.isMemory()) {
    106      masm.load32(getAdjustedAddress(from), tempReg());
    107      masm.store32(tempReg(), getAdjustedAddress(to));
    108    } else {
    109      MOZ_CRASH("Invalid emitInt32Move arguments.");
    110    }
    111  } else if (from.isEffectiveAddress()) {
    112    if (to.isGeneralReg()) {
    113      masm.computeEffectiveAddress(getAdjustedAddress(from), to.reg());
    114    } else if (to.isMemory()) {
    115      masm.computeEffectiveAddress(getAdjustedAddress(from), tempReg());
    116      masm.store32(tempReg(), getAdjustedAddress(to));
    117    } else {
    118      MOZ_CRASH("Invalid emitInt32Move arguments.");
    119    }
    120  } else {
    121    MOZ_CRASH("Invalid emitInt32Move arguments.");
    122  }
    123 }
    124 
    125 void MoveEmitterMIPSShared::emitFloat32Move(const MoveOperand& from,
    126                                            const MoveOperand& to) {
    127  if (from.isFloatReg()) {
    128    if (to.isFloatReg()) {
    129      masm.moveFloat32(from.floatReg(), to.floatReg());
    130    } else if (to.isGeneralReg()) {
    131      // This should only be used when passing float parameter in a1,a2,a3
    132      MOZ_ASSERT(to.reg() == a1 || to.reg() == a2 || to.reg() == a3);
    133      masm.moveFromFloat32(from.floatReg(), to.reg());
    134    } else {
    135      MOZ_ASSERT(to.isMemory());
    136      masm.storeFloat32(from.floatReg(), getAdjustedAddress(to));
    137    }
    138  } else if (to.isFloatReg()) {
    139    MOZ_ASSERT(from.isMemory());
    140    masm.loadFloat32(getAdjustedAddress(from), to.floatReg());
    141  } else if (to.isGeneralReg()) {
    142    MOZ_ASSERT(from.isMemory());
    143    // This should only be used when passing float parameter in a1,a2,a3
    144    MOZ_ASSERT(to.reg() == a1 || to.reg() == a2 || to.reg() == a3);
    145    masm.loadPtr(getAdjustedAddress(from), to.reg());
    146  } else {
    147    MOZ_ASSERT(from.isMemory());
    148    MOZ_ASSERT(to.isMemory());
    149    masm.loadFloat32(getAdjustedAddress(from), ScratchFloat32Reg);
    150    masm.storeFloat32(ScratchFloat32Reg, getAdjustedAddress(to));
    151  }
    152 }
    153 
    154 void MoveEmitterMIPSShared::emit(const MoveOp& move) {
    155  const MoveOperand& from = move.from();
    156  const MoveOperand& to = move.to();
    157 
    158  if (move.isCycleEnd() && move.isCycleBegin()) {
    159    // A fun consequence of aliased registers is you can have multiple
    160    // cycles at once, and one can end exactly where another begins.
    161    breakCycle(from, to, move.endCycleType(), move.cycleBeginSlot());
    162    completeCycle(from, to, move.type(), move.cycleEndSlot());
    163    return;
    164  }
    165 
    166  if (move.isCycleEnd()) {
    167    MOZ_ASSERT(inCycle_);
    168    completeCycle(from, to, move.type(), move.cycleEndSlot());
    169    MOZ_ASSERT(inCycle_ > 0);
    170    inCycle_--;
    171    return;
    172  }
    173 
    174  if (move.isCycleBegin()) {
    175    breakCycle(from, to, move.endCycleType(), move.cycleBeginSlot());
    176    inCycle_++;
    177  }
    178 
    179  switch (move.type()) {
    180    case MoveOp::FLOAT32:
    181      emitFloat32Move(from, to);
    182      break;
    183    case MoveOp::DOUBLE:
    184      emitDoubleMove(from, to);
    185      break;
    186    case MoveOp::INT32:
    187      emitInt32Move(from, to);
    188      break;
    189    case MoveOp::GENERAL:
    190      emitMove(from, to);
    191      break;
    192    default:
    193      MOZ_CRASH("Unexpected move type");
    194  }
    195 }
    196 
    197 void MoveEmitterMIPSShared::assertDone() { MOZ_ASSERT(inCycle_ == 0); }
    198 
    199 void MoveEmitterMIPSShared::finish() {
    200  assertDone();
    201 
    202  masm.freeStack(masm.framePushed() - pushedAtStart_);
    203 }