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