136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines//===-- MipsNaClELFStreamer.cpp - ELF Object Output for Mips NaCl ---------===//
236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines//
336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines//                     The LLVM Compiler Infrastructure
436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines//
536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines// This file is distributed under the University of Illinois Open Source
636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines// License. See LICENSE.TXT for details.
736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines//
836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines//===----------------------------------------------------------------------===//
936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines//
1036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines// This file implements MCELFStreamer for Mips NaCl.  It emits .o object files
1136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines// as required by NaCl's SFI sandbox.  It inserts address-masking instructions
1236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines// before dangerous control-flow and memory access instructions.  It inserts
1336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines// address-masking instructions after instructions that change the stack
1436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines// pointer.  It ensures that the mask and the dangerous instruction are always
1536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines// emitted in the same bundle.  It aligns call + branch delay to the bundle end,
1636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines// so that return address is always aligned to the start of next bundle.
1736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines//
1836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines//===----------------------------------------------------------------------===//
1936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
2036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines#include "Mips.h"
2136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines#include "MipsELFStreamer.h"
2236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines#include "MipsMCNaCl.h"
2336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines#include "llvm/MC/MCELFStreamer.h"
2436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
2536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesusing namespace llvm;
2636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
27dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines#define DEBUG_TYPE "mips-mc-nacl"
28dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines
2936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesnamespace {
3036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
3136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesconst unsigned IndirectBranchMaskReg = Mips::T6;
3236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesconst unsigned LoadStoreStackMaskReg = Mips::T7;
3336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
3436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines/// Extend the generic MCELFStreamer class so that it can mask dangerous
3536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines/// instructions.
3636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
3736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesclass MipsNaClELFStreamer : public MipsELFStreamer {
3836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinespublic:
392c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar  MipsNaClELFStreamer(MCContext &Context, MCAsmBackend &TAB,
402c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar                      raw_pwrite_stream &OS, MCCodeEmitter *Emitter)
414c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar      : MipsELFStreamer(Context, TAB, OS, Emitter), PendingCall(false) {}
4236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
432c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar  ~MipsNaClELFStreamer() override {}
4436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
4536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesprivate:
4636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  // Whether we started the sandboxing sequence for calls.  Calls are bundled
4736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  // with branch delays and aligned to the bundle end.
4836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  bool PendingCall;
4936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
5036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  bool isIndirectJump(const MCInst &MI) {
51c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines    if (MI.getOpcode() == Mips::JALR) {
52c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines      // MIPS32r6/MIPS64r6 doesn't have a JR instruction and uses JALR instead.
53c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines      // JALR is an indirect branch if the link register is $0.
54c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines      assert(MI.getOperand(0).isReg());
55c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines      return MI.getOperand(0).getReg() == Mips::ZERO;
56c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines    }
57c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines    return MI.getOpcode() == Mips::JR;
5836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  }
5936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
6036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  bool isStackPointerFirstOperand(const MCInst &MI) {
6136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    return (MI.getNumOperands() > 0 && MI.getOperand(0).isReg()
6236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines            && MI.getOperand(0).getReg() == Mips::SP);
6336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  }
6436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
65c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines  bool isCall(const MCInst &MI, bool *IsIndirectCall) {
66c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines    unsigned Opcode = MI.getOpcode();
67c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines
6836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    *IsIndirectCall = false;
6936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
7036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    switch (Opcode) {
7136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    default:
7236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      return false;
7336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
7436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    case Mips::JAL:
75c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines    case Mips::BAL:
7636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    case Mips::BAL_BR:
7736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    case Mips::BLTZAL:
7836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    case Mips::BGEZAL:
7936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      return true;
8036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
8136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    case Mips::JALR:
82c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines      // JALR is only a call if the link register is not $0. Otherwise it's an
83c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines      // indirect branch.
84c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines      assert(MI.getOperand(0).isReg());
85c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines      if (MI.getOperand(0).getReg() == Mips::ZERO)
86c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines        return false;
87c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines
8836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      *IsIndirectCall = true;
8936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      return true;
9036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    }
9136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  }
9236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
9336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  void emitMask(unsigned AddrReg, unsigned MaskReg,
9436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines                const MCSubtargetInfo &STI) {
9536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    MCInst MaskInst;
9636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    MaskInst.setOpcode(Mips::AND);
9736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    MaskInst.addOperand(MCOperand::CreateReg(AddrReg));
9836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    MaskInst.addOperand(MCOperand::CreateReg(AddrReg));
9936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    MaskInst.addOperand(MCOperand::CreateReg(MaskReg));
10036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    MipsELFStreamer::EmitInstruction(MaskInst, STI);
10136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  }
10236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
10336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  // Sandbox indirect branch or return instruction by inserting mask operation
10436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  // before it.
10536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  void sandboxIndirectJump(const MCInst &MI, const MCSubtargetInfo &STI) {
10636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    unsigned AddrReg = MI.getOperand(0).getReg();
10736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
10836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    EmitBundleLock(false);
10936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    emitMask(AddrReg, IndirectBranchMaskReg, STI);
11036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    MipsELFStreamer::EmitInstruction(MI, STI);
11136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    EmitBundleUnlock();
11236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  }
11336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
11436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  // Sandbox memory access or SP change.  Insert mask operation before and/or
11536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  // after the instruction.
11636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  void sandboxLoadStoreStackChange(const MCInst &MI, unsigned AddrIdx,
11736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines                                   const MCSubtargetInfo &STI, bool MaskBefore,
11836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines                                   bool MaskAfter) {
11936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    EmitBundleLock(false);
12036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    if (MaskBefore) {
12136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      // Sandbox memory access.
12236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      unsigned BaseReg = MI.getOperand(AddrIdx).getReg();
12336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      emitMask(BaseReg, LoadStoreStackMaskReg, STI);
12436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    }
12536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    MipsELFStreamer::EmitInstruction(MI, STI);
12636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    if (MaskAfter) {
12736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      // Sandbox SP change.
12836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      unsigned SPReg = MI.getOperand(0).getReg();
12936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      assert((Mips::SP == SPReg) && "Unexpected stack-pointer register.");
13036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      emitMask(SPReg, LoadStoreStackMaskReg, STI);
13136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    }
13236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    EmitBundleUnlock();
13336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  }
13436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
13536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinespublic:
13636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  /// This function is the one used to emit instruction data into the ELF
13736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  /// streamer.  We override it to mask dangerous instructions.
138dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  void EmitInstruction(const MCInst &Inst,
139dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                       const MCSubtargetInfo &STI) override {
14036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    // Sandbox indirect jumps.
14136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    if (isIndirectJump(Inst)) {
14236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      if (PendingCall)
14336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines        report_fatal_error("Dangerous instruction in branch delay slot!");
14436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      sandboxIndirectJump(Inst, STI);
14536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      return;
14636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    }
14736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
14836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    // Sandbox loads, stores and SP changes.
14936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    unsigned AddrIdx;
15036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    bool IsStore;
15136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    bool IsMemAccess = isBasePlusOffsetMemoryAccess(Inst.getOpcode(), &AddrIdx,
15236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines                                                    &IsStore);
15336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    bool IsSPFirstOperand = isStackPointerFirstOperand(Inst);
15436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    if (IsMemAccess || IsSPFirstOperand) {
15536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      bool MaskBefore = (IsMemAccess
15636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines                         && baseRegNeedsLoadStoreMask(Inst.getOperand(AddrIdx)
15736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines                                                          .getReg()));
15836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      bool MaskAfter = IsSPFirstOperand && !IsStore;
159c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines      if (MaskBefore || MaskAfter) {
160c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines        if (PendingCall)
161c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines          report_fatal_error("Dangerous instruction in branch delay slot!");
16236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines        sandboxLoadStoreStackChange(Inst, AddrIdx, STI, MaskBefore, MaskAfter);
163c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines        return;
164c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines      }
165c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines      // fallthrough
16636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    }
16736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
16836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    // Sandbox calls by aligning call and branch delay to the bundle end.
16936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    // For indirect calls, emit the mask before the call.
17036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    bool IsIndirectCall;
171c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines    if (isCall(Inst, &IsIndirectCall)) {
17236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      if (PendingCall)
17336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines        report_fatal_error("Dangerous instruction in branch delay slot!");
17436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
17536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      // Start the sandboxing sequence by emitting call.
17636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      EmitBundleLock(true);
17736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      if (IsIndirectCall) {
17836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines        unsigned TargetReg = Inst.getOperand(1).getReg();
17936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines        emitMask(TargetReg, IndirectBranchMaskReg, STI);
18036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      }
18136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      MipsELFStreamer::EmitInstruction(Inst, STI);
18236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      PendingCall = true;
18336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      return;
18436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    }
18536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    if (PendingCall) {
18636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      // Finish the sandboxing sequence by emitting branch delay.
18736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      MipsELFStreamer::EmitInstruction(Inst, STI);
18836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      EmitBundleUnlock();
18936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      PendingCall = false;
19036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      return;
19136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    }
19236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
19336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    // None of the sandboxing applies, just emit the instruction.
19436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    MipsELFStreamer::EmitInstruction(Inst, STI);
19536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  }
19636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines};
19736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
19836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines} // end anonymous namespace
19936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
20036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesnamespace llvm {
20136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
20236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesbool isBasePlusOffsetMemoryAccess(unsigned Opcode, unsigned *AddrIdx,
20336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines                                  bool *IsStore) {
20436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  if (IsStore)
20536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    *IsStore = false;
20636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
20736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  switch (Opcode) {
20836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  default:
20936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    return false;
21036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
21136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  // Load instructions with base address register in position 1.
21236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  case Mips::LB:
21336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  case Mips::LBu:
21436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  case Mips::LH:
21536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  case Mips::LHu:
21636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  case Mips::LW:
21736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  case Mips::LWC1:
21836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  case Mips::LDC1:
21936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  case Mips::LL:
220c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines  case Mips::LL_R6:
22136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  case Mips::LWL:
22236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  case Mips::LWR:
22336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    *AddrIdx = 1;
22436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    return true;
22536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
22636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  // Store instructions with base address register in position 1.
22736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  case Mips::SB:
22836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  case Mips::SH:
22936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  case Mips::SW:
23036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  case Mips::SWC1:
23136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  case Mips::SDC1:
23236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  case Mips::SWL:
23336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  case Mips::SWR:
23436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    *AddrIdx = 1;
23536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    if (IsStore)
23636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      *IsStore = true;
23736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    return true;
23836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
23936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  // Store instructions with base address register in position 2.
24036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  case Mips::SC:
241c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines  case Mips::SC_R6:
24236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    *AddrIdx = 2;
24336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    if (IsStore)
24436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      *IsStore = true;
24536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    return true;
24636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  }
24736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines}
24836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
24936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesbool baseRegNeedsLoadStoreMask(unsigned Reg) {
25036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  // The contents of SP and thread pointer register do not require masking.
25136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  return Reg != Mips::SP && Reg != Mips::T8;
25236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines}
25336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
25436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen HinesMCELFStreamer *createMipsNaClELFStreamer(MCContext &Context, MCAsmBackend &TAB,
2552c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar                                         raw_pwrite_stream &OS,
25636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines                                         MCCodeEmitter *Emitter,
25737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines                                         bool RelaxAll) {
2584c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar  MipsNaClELFStreamer *S = new MipsNaClELFStreamer(Context, TAB, OS, Emitter);
25936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  if (RelaxAll)
26036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    S->getAssembler().setRelaxAll(true);
26136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
26236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  // Set bundle-alignment as required by the NaCl ABI for the target.
26336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  S->EmitBundleAlignMode(MIPS_NACL_BUNDLE_ALIGN);
26436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
26536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  return S;
26636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines}
26736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
26836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines}
269