diff options
Diffstat (limited to 'lib/Target/Mips/AsmParser/MipsAsmParser.cpp')
-rw-r--r-- | lib/Target/Mips/AsmParser/MipsAsmParser.cpp | 409 |
1 files changed, 322 insertions, 87 deletions
diff --git a/lib/Target/Mips/AsmParser/MipsAsmParser.cpp b/lib/Target/Mips/AsmParser/MipsAsmParser.cpp index d2fed6861477..1f7d095bf49b 100644 --- a/lib/Target/Mips/AsmParser/MipsAsmParser.cpp +++ b/lib/Target/Mips/AsmParser/MipsAsmParser.cpp @@ -1,9 +1,8 @@ //===-- MipsAsmParser.cpp - Parse Mips assembly to MCInst instructions ----===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// @@ -13,6 +12,7 @@ #include "MCTargetDesc/MipsMCExpr.h" #include "MCTargetDesc/MipsMCTargetDesc.h" #include "MipsTargetStreamer.h" +#include "TargetInfo/MipsTargetInfo.h" #include "llvm/ADT/APFloat.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallVector.h" @@ -29,6 +29,7 @@ #include "llvm/MC/MCParser/MCAsmLexer.h" #include "llvm/MC/MCParser/MCAsmParser.h" #include "llvm/MC/MCParser/MCAsmParserExtension.h" +#include "llvm/MC/MCParser/MCAsmParserUtils.h" #include "llvm/MC/MCParser/MCParsedAsmOperand.h" #include "llvm/MC/MCParser/MCTargetAsmParser.h" #include "llvm/MC/MCSectionELF.h" @@ -65,10 +66,7 @@ class MCInstrInfo; } // end namespace llvm -static cl::opt<bool> -EmitJalrReloc("mips-jalr-reloc", cl::Hidden, - cl::desc("MIPS: Emit R_{MICRO}MIPS_JALR relocation with jalr"), - cl::init(true)); +extern cl::opt<bool> EmitJalrReloc; namespace { @@ -148,6 +146,7 @@ class MipsAsmParser : public MCTargetAsmParser { bool IsPicEnabled; bool IsCpRestoreSet; int CpRestoreOffset; + unsigned GPReg; unsigned CpSaveLocation; /// If true, then CpSaveLocation is a register, otherwise it's an offset. bool CpSaveLocationIsRegister; @@ -277,6 +276,15 @@ class MipsAsmParser : public MCTargetAsmParser { bool expandUxw(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, const MCSubtargetInfo *STI); + bool expandSge(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, + const MCSubtargetInfo *STI); + + bool expandSgeImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, + const MCSubtargetInfo *STI); + + bool expandSgtImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, + const MCSubtargetInfo *STI); + bool expandRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, const MCSubtargetInfo *STI); bool expandRotationImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, @@ -304,6 +312,9 @@ class MipsAsmParser : public MCTargetAsmParser { bool expandLoadStoreDMacro(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, const MCSubtargetInfo *STI, bool IsLoad); + bool expandStoreDM1Macro(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, + const MCSubtargetInfo *STI); + bool expandSeq(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, const MCSubtargetInfo *STI); @@ -324,6 +335,7 @@ class MipsAsmParser : public MCTargetAsmParser { bool parseSetFeature(uint64_t Feature); bool isPicAndNotNxxAbi(); // Used by .cpload, .cprestore, and .cpsetup. bool parseDirectiveCpLoad(SMLoc Loc); + bool parseDirectiveCpLocal(SMLoc Loc); bool parseDirectiveCpRestore(SMLoc Loc); bool parseDirectiveCPSetup(); bool parseDirectiveCPReturn(); @@ -517,6 +529,7 @@ public: IsCpRestoreSet = false; CpRestoreOffset = -1; + GPReg = ABI.GetGlobalPtr(); const Triple &TheTriple = sti.getTargetTriple(); IsLittleEndian = TheTriple.isLittleEndian(); @@ -895,14 +908,6 @@ private: .getRegister(RegIdx.Index); } - /// Coerce the register to FGRH32 and return the real register for the current - /// target. - unsigned getFGRH32Reg() const { - assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!"); - return RegIdx.RegInfo->getRegClass(Mips::FGRH32RegClassID) - .getRegister(RegIdx.Index); - } - /// Coerce the register to FCC and return the real register for the current /// target. unsigned getFCCReg() const { @@ -1100,11 +1105,6 @@ public: "registers"); } - void addFGRH32AsmRegOperands(MCInst &Inst, unsigned N) const { - assert(N == 1 && "Invalid number of operands!"); - Inst.addOperand(MCOperand::createReg(getFGRH32Reg())); - } - void addFCCAsmRegOperands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); Inst.addOperand(MCOperand::createReg(getFCCReg())); @@ -2043,7 +2043,7 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc, const MCExpr *Lo16RelocExpr = MipsMCExpr::create(MipsMCExpr::MEK_LO, JalExpr, getContext()); - TOut.emitRRX(Mips::LW, Mips::T9, Mips::GP, + TOut.emitRRX(Mips::LW, Mips::T9, GPReg, MCOperand::createExpr(Got16RelocExpr), IDLoc, STI); TOut.emitRRX(Mips::ADDiu, Mips::T9, Mips::T9, MCOperand::createExpr(Lo16RelocExpr), IDLoc, STI); @@ -2057,7 +2057,7 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc, MipsMCExpr::create(MipsMCExpr::MEK_GOT_DISP, JalExpr, getContext()); TOut.emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9, - Mips::GP, MCOperand::createExpr(GotDispRelocExpr), IDLoc, + GPReg, MCOperand::createExpr(GotDispRelocExpr), IDLoc, STI); } } else { @@ -2068,7 +2068,7 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc, const MCExpr *Call16RelocExpr = MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, JalExpr, getContext()); - TOut.emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9, Mips::GP, + TOut.emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9, GPReg, MCOperand::createExpr(Call16RelocExpr), IDLoc, STI); } @@ -2485,6 +2485,19 @@ MipsAsmParser::tryExpandInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, case Mips::NORImm: case Mips::NORImm64: return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success; + case Mips::SGE: + case Mips::SGEU: + return expandSge(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success; + case Mips::SGEImm: + case Mips::SGEUImm: + case Mips::SGEImm64: + case Mips::SGEUImm64: + return expandSgeImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success; + case Mips::SGTImm: + case Mips::SGTUImm: + case Mips::SGTImm64: + case Mips::SGTUImm64: + return expandSgtImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success; case Mips::SLTImm64: if (isInt<16>(Inst.getOperand(2).getImm())) { Inst.setOpcode(Mips::SLTi64); @@ -2553,6 +2566,10 @@ MipsAsmParser::tryExpandInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, Inst.getOpcode() == Mips::LDMacro) ? MER_Fail : MER_Success; + case Mips::SDC1_M1: + return expandStoreDM1Macro(Inst, IDLoc, Out, STI) + ? MER_Fail + : MER_Success; case Mips::SEQMacro: return expandSeq(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success; case Mips::SEQIMacro: @@ -2879,8 +2896,8 @@ bool MipsAsmParser::loadAndAddSymbolAddress(const MCExpr *SymExpr, ELF::STB_LOCAL))) { const MCExpr *CallExpr = MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, SymExpr, getContext()); - TOut.emitRRX(Mips::LW, DstReg, ABI.GetGlobalPtr(), - MCOperand::createExpr(CallExpr), IDLoc, STI); + TOut.emitRRX(Mips::LW, DstReg, GPReg, MCOperand::createExpr(CallExpr), + IDLoc, STI); return false; } @@ -2919,8 +2936,8 @@ bool MipsAsmParser::loadAndAddSymbolAddress(const MCExpr *SymExpr, TmpReg = ATReg; } - TOut.emitRRX(Mips::LW, TmpReg, ABI.GetGlobalPtr(), - MCOperand::createExpr(GotExpr), IDLoc, STI); + TOut.emitRRX(Mips::LW, TmpReg, GPReg, MCOperand::createExpr(GotExpr), IDLoc, + STI); if (LoExpr) TOut.emitRRX(Mips::ADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr), @@ -2955,8 +2972,8 @@ bool MipsAsmParser::loadAndAddSymbolAddress(const MCExpr *SymExpr, ELF::STB_LOCAL))) { const MCExpr *CallExpr = MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, SymExpr, getContext()); - TOut.emitRRX(Mips::LD, DstReg, ABI.GetGlobalPtr(), - MCOperand::createExpr(CallExpr), IDLoc, STI); + TOut.emitRRX(Mips::LD, DstReg, GPReg, MCOperand::createExpr(CallExpr), + IDLoc, STI); return false; } @@ -2998,8 +3015,8 @@ bool MipsAsmParser::loadAndAddSymbolAddress(const MCExpr *SymExpr, TmpReg = ATReg; } - TOut.emitRRX(Mips::LD, TmpReg, ABI.GetGlobalPtr(), - MCOperand::createExpr(GotExpr), IDLoc, STI); + TOut.emitRRX(Mips::LD, TmpReg, GPReg, MCOperand::createExpr(GotExpr), IDLoc, + STI); if (LoExpr) TOut.emitRRX(Mips::DADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr), @@ -3229,10 +3246,10 @@ bool MipsAsmParser::emitPartialAddress(MipsTargetStreamer &TOut, SMLoc IDLoc, MipsMCExpr::create(MipsMCExpr::MEK_GOT, GotSym, getContext()); if(isABI_O32() || isABI_N32()) { - TOut.emitRRX(Mips::LW, ATReg, Mips::GP, MCOperand::createExpr(GotExpr), + TOut.emitRRX(Mips::LW, ATReg, GPReg, MCOperand::createExpr(GotExpr), IDLoc, STI); } else { //isABI_N64() - TOut.emitRRX(Mips::LD, ATReg, Mips::GP, MCOperand::createExpr(GotExpr), + TOut.emitRRX(Mips::LD, ATReg, GPReg, MCOperand::createExpr(GotExpr), IDLoc, STI); } } else { //!IsPicEnabled @@ -4293,6 +4310,143 @@ bool MipsAsmParser::expandUxw(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, return false; } +bool MipsAsmParser::expandSge(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, + const MCSubtargetInfo *STI) { + MipsTargetStreamer &TOut = getTargetStreamer(); + + assert(Inst.getNumOperands() == 3 && "Invalid operand count"); + assert(Inst.getOperand(0).isReg() && + Inst.getOperand(1).isReg() && + Inst.getOperand(2).isReg() && "Invalid instruction operand."); + + unsigned DstReg = Inst.getOperand(0).getReg(); + unsigned SrcReg = Inst.getOperand(1).getReg(); + unsigned OpReg = Inst.getOperand(2).getReg(); + unsigned OpCode; + + warnIfNoMacro(IDLoc); + + switch (Inst.getOpcode()) { + case Mips::SGE: + OpCode = Mips::SLT; + break; + case Mips::SGEU: + OpCode = Mips::SLTu; + break; + default: + llvm_unreachable("unexpected 'sge' opcode"); + } + + // $SrcReg >= $OpReg is equal to (not ($SrcReg < $OpReg)) + TOut.emitRRR(OpCode, DstReg, SrcReg, OpReg, IDLoc, STI); + TOut.emitRRI(Mips::XORi, DstReg, DstReg, 1, IDLoc, STI); + + return false; +} + +bool MipsAsmParser::expandSgeImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, + const MCSubtargetInfo *STI) { + MipsTargetStreamer &TOut = getTargetStreamer(); + + assert(Inst.getNumOperands() == 3 && "Invalid operand count"); + assert(Inst.getOperand(0).isReg() && + Inst.getOperand(1).isReg() && + Inst.getOperand(2).isImm() && "Invalid instruction operand."); + + unsigned DstReg = Inst.getOperand(0).getReg(); + unsigned SrcReg = Inst.getOperand(1).getReg(); + int64_t ImmValue = Inst.getOperand(2).getImm(); + unsigned OpRegCode, OpImmCode; + + warnIfNoMacro(IDLoc); + + switch (Inst.getOpcode()) { + case Mips::SGEImm: + case Mips::SGEImm64: + OpRegCode = Mips::SLT; + OpImmCode = Mips::SLTi; + break; + case Mips::SGEUImm: + case Mips::SGEUImm64: + OpRegCode = Mips::SLTu; + OpImmCode = Mips::SLTiu; + break; + default: + llvm_unreachable("unexpected 'sge' opcode with immediate"); + } + + // $SrcReg >= Imm is equal to (not ($SrcReg < Imm)) + if (isInt<16>(ImmValue)) { + // Use immediate version of STL. + TOut.emitRRI(OpImmCode, DstReg, SrcReg, ImmValue, IDLoc, STI); + TOut.emitRRI(Mips::XORi, DstReg, DstReg, 1, IDLoc, STI); + } else { + unsigned ImmReg = DstReg; + if (DstReg == SrcReg) { + unsigned ATReg = getATReg(Inst.getLoc()); + if (!ATReg) + return true; + ImmReg = ATReg; + } + + if (loadImmediate(ImmValue, ImmReg, Mips::NoRegister, isInt<32>(ImmValue), + false, IDLoc, Out, STI)) + return true; + + TOut.emitRRR(OpRegCode, DstReg, SrcReg, ImmReg, IDLoc, STI); + TOut.emitRRI(Mips::XORi, DstReg, DstReg, 1, IDLoc, STI); + } + + return false; +} + +bool MipsAsmParser::expandSgtImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, + const MCSubtargetInfo *STI) { + MipsTargetStreamer &TOut = getTargetStreamer(); + + assert(Inst.getNumOperands() == 3 && "Invalid operand count"); + assert(Inst.getOperand(0).isReg() && + Inst.getOperand(1).isReg() && + Inst.getOperand(2).isImm() && "Invalid instruction operand."); + + unsigned DstReg = Inst.getOperand(0).getReg(); + unsigned SrcReg = Inst.getOperand(1).getReg(); + unsigned ImmReg = DstReg; + int64_t ImmValue = Inst.getOperand(2).getImm(); + unsigned OpCode; + + warnIfNoMacro(IDLoc); + + switch (Inst.getOpcode()) { + case Mips::SGTImm: + case Mips::SGTImm64: + OpCode = Mips::SLT; + break; + case Mips::SGTUImm: + case Mips::SGTUImm64: + OpCode = Mips::SLTu; + break; + default: + llvm_unreachable("unexpected 'sgt' opcode with immediate"); + } + + if (DstReg == SrcReg) { + unsigned ATReg = getATReg(Inst.getLoc()); + if (!ATReg) + return true; + ImmReg = ATReg; + } + + if (loadImmediate(ImmValue, ImmReg, Mips::NoRegister, isInt<32>(ImmValue), + false, IDLoc, Out, STI)) + return true; + + // $SrcReg > $ImmReg is equal to $ImmReg < $SrcReg + TOut.emitRRR(OpCode, DstReg, ImmReg, SrcReg, IDLoc, STI); + + return false; +} + bool MipsAsmParser::expandAliasImmediate(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, const MCSubtargetInfo *STI) { @@ -4859,61 +5013,110 @@ bool MipsAsmParser::expandLoadStoreDMacro(MCInst &Inst, SMLoc IDLoc, return false; } + +// Expand 's.d $<reg> offset($reg2)' to 'swc1 $<reg+1>, offset($reg2); +// swc1 $<reg>, offset+4($reg2)' +// or if little endian to 'swc1 $<reg>, offset($reg2); +// swc1 $<reg+1>, offset+4($reg2)' +// for Mips1. +bool MipsAsmParser::expandStoreDM1Macro(MCInst &Inst, SMLoc IDLoc, + MCStreamer &Out, + const MCSubtargetInfo *STI) { + if (!isABI_O32()) + return true; + + warnIfNoMacro(IDLoc); + + MipsTargetStreamer &TOut = getTargetStreamer(); + unsigned Opcode = Mips::SWC1; + unsigned FirstReg = Inst.getOperand(0).getReg(); + unsigned SecondReg = nextReg(FirstReg); + unsigned BaseReg = Inst.getOperand(1).getReg(); + if (!SecondReg) + return true; + + warnIfRegIndexIsAT(FirstReg, IDLoc); + + assert(Inst.getOperand(2).isImm() && + "Offset for macro is not immediate!"); + + MCOperand &FirstOffset = Inst.getOperand(2); + signed NextOffset = FirstOffset.getImm() + 4; + MCOperand SecondOffset = MCOperand::createImm(NextOffset); + + if (!isInt<16>(FirstOffset.getImm()) || !isInt<16>(NextOffset)) + return true; + + if (!IsLittleEndian) + std::swap(FirstReg, SecondReg); + + TOut.emitRRX(Opcode, FirstReg, BaseReg, FirstOffset, IDLoc, STI); + TOut.emitRRX(Opcode, SecondReg, BaseReg, SecondOffset, IDLoc, STI); + + return false; +} + bool MipsAsmParser::expandSeq(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, const MCSubtargetInfo *STI) { + MipsTargetStreamer &TOut = getTargetStreamer(); + + assert(Inst.getNumOperands() == 3 && "Invalid operand count"); + assert(Inst.getOperand(0).isReg() && + Inst.getOperand(1).isReg() && + Inst.getOperand(2).isReg() && "Invalid instruction operand."); + + unsigned DstReg = Inst.getOperand(0).getReg(); + unsigned SrcReg = Inst.getOperand(1).getReg(); + unsigned OpReg = Inst.getOperand(2).getReg(); warnIfNoMacro(IDLoc); - MipsTargetStreamer &TOut = getTargetStreamer(); - if (Inst.getOperand(1).getReg() != Mips::ZERO && - Inst.getOperand(2).getReg() != Mips::ZERO) { - TOut.emitRRR(Mips::XOR, Inst.getOperand(0).getReg(), - Inst.getOperand(1).getReg(), Inst.getOperand(2).getReg(), - IDLoc, STI); - TOut.emitRRI(Mips::SLTiu, Inst.getOperand(0).getReg(), - Inst.getOperand(0).getReg(), 1, IDLoc, STI); + if (SrcReg != Mips::ZERO && OpReg != Mips::ZERO) { + TOut.emitRRR(Mips::XOR, DstReg, SrcReg, OpReg, IDLoc, STI); + TOut.emitRRI(Mips::SLTiu, DstReg, DstReg, 1, IDLoc, STI); return false; } - unsigned Reg = 0; - if (Inst.getOperand(1).getReg() == Mips::ZERO) { - Reg = Inst.getOperand(2).getReg(); - } else { - Reg = Inst.getOperand(1).getReg(); - } - TOut.emitRRI(Mips::SLTiu, Inst.getOperand(0).getReg(), Reg, 1, IDLoc, STI); + unsigned Reg = SrcReg == Mips::ZERO ? OpReg : SrcReg; + TOut.emitRRI(Mips::SLTiu, DstReg, Reg, 1, IDLoc, STI); return false; } bool MipsAsmParser::expandSeqI(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, const MCSubtargetInfo *STI) { - warnIfNoMacro(IDLoc); MipsTargetStreamer &TOut = getTargetStreamer(); - unsigned Opc; + assert(Inst.getNumOperands() == 3 && "Invalid operand count"); + assert(Inst.getOperand(0).isReg() && + Inst.getOperand(1).isReg() && + Inst.getOperand(2).isImm() && "Invalid instruction operand."); + + unsigned DstReg = Inst.getOperand(0).getReg(); + unsigned SrcReg = Inst.getOperand(1).getReg(); int64_t Imm = Inst.getOperand(2).getImm(); - unsigned Reg = Inst.getOperand(1).getReg(); + + warnIfNoMacro(IDLoc); if (Imm == 0) { - TOut.emitRRI(Mips::SLTiu, Inst.getOperand(0).getReg(), - Inst.getOperand(1).getReg(), 1, IDLoc, STI); + TOut.emitRRI(Mips::SLTiu, DstReg, SrcReg, 1, IDLoc, STI); return false; - } else { + } - if (Reg == Mips::ZERO) { - Warning(IDLoc, "comparison is always false"); - TOut.emitRRR(isGP64bit() ? Mips::DADDu : Mips::ADDu, - Inst.getOperand(0).getReg(), Reg, Reg, IDLoc, STI); - return false; - } + if (SrcReg == Mips::ZERO) { + Warning(IDLoc, "comparison is always false"); + TOut.emitRRR(isGP64bit() ? Mips::DADDu : Mips::ADDu, + DstReg, SrcReg, SrcReg, IDLoc, STI); + return false; + } - if (Imm > -0x8000 && Imm < 0) { - Imm = -Imm; - Opc = isGP64bit() ? Mips::DADDiu : Mips::ADDiu; - } else { - Opc = Mips::XORi; - } + unsigned Opc; + if (Imm > -0x8000 && Imm < 0) { + Imm = -Imm; + Opc = isGP64bit() ? Mips::DADDiu : Mips::ADDiu; + } else { + Opc = Mips::XORi; } + if (!isUInt<16>(Imm)) { unsigned ATReg = getATReg(IDLoc); if (!ATReg) @@ -4923,17 +5126,13 @@ bool MipsAsmParser::expandSeqI(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, Out, STI)) return true; - TOut.emitRRR(Mips::XOR, Inst.getOperand(0).getReg(), - Inst.getOperand(1).getReg(), ATReg, IDLoc, STI); - TOut.emitRRI(Mips::SLTiu, Inst.getOperand(0).getReg(), - Inst.getOperand(0).getReg(), 1, IDLoc, STI); + TOut.emitRRR(Mips::XOR, DstReg, SrcReg, ATReg, IDLoc, STI); + TOut.emitRRI(Mips::SLTiu, DstReg, DstReg, 1, IDLoc, STI); return false; } - TOut.emitRRI(Opc, Inst.getOperand(0).getReg(), Inst.getOperand(1).getReg(), - Imm, IDLoc, STI); - TOut.emitRRI(Mips::SLTiu, Inst.getOperand(0).getReg(), - Inst.getOperand(0).getReg(), 1, IDLoc, STI); + TOut.emitRRI(Opc, DstReg, SrcReg, Imm, IDLoc, STI); + TOut.emitRRI(Mips::SLTiu, DstReg, DstReg, 1, IDLoc, STI); return false; } @@ -6325,7 +6524,7 @@ bool MipsAsmParser::parseBracketSuffix(StringRef Name, return false; } -static std::string MipsMnemonicSpellCheck(StringRef S, uint64_t FBS, +static std::string MipsMnemonicSpellCheck(StringRef S, const FeatureBitset &FBS, unsigned VariantID = 0); bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name, @@ -6338,7 +6537,7 @@ bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name, // Check if we have valid mnemonic if (!mnemonicIsValid(Name, 0)) { - uint64_t FBS = ComputeAvailableFeatures(getSTI().getFeatureBits()); + FeatureBitset FBS = ComputeAvailableFeatures(getSTI().getFeatureBits()); std::string Suggestion = MipsMnemonicSpellCheck(Name, FBS); return Error(NameLoc, "unknown instruction" + Suggestion); } @@ -6807,7 +7006,6 @@ bool MipsAsmParser::parseSetHardFloatDirective() { bool MipsAsmParser::parseSetAssignment() { StringRef Name; - const MCExpr *Value; MCAsmParser &Parser = getParser(); if (Parser.parseIdentifier(Name)) @@ -6825,17 +7023,16 @@ bool MipsAsmParser::parseSetAssignment() { RegisterSets[Name] = Parser.getTok(); Parser.Lex(); // Eat identifier. getContext().getOrCreateSymbol(Name); - } else if (!Parser.parseExpression(Value)) { - // Parse assignment of an expression including - // symbolic registers: - // .set $tmp, $BB0-$BB1 - // .set r2, $f2 - MCSymbol *Sym = getContext().getOrCreateSymbol(Name); - Sym->setVariableValue(Value); - } else { - return reportParseError("expected valid expression after comma"); + return false; } + MCSymbol *Sym; + const MCExpr *Value; + if (MCParserUtils::parseAssignmentExpression(Name, /* allow_redef */ true, + Parser, Sym, Value)) + return true; + Sym->setVariableValue(Value); + return false; } @@ -7047,6 +7244,40 @@ bool MipsAsmParser::parseDirectiveCpLoad(SMLoc Loc) { return false; } +bool MipsAsmParser::parseDirectiveCpLocal(SMLoc Loc) { + if (!isABI_N32() && !isABI_N64()) { + reportParseError(".cplocal is allowed only in N32 or N64 mode"); + return false; + } + + SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg; + OperandMatchResultTy ResTy = parseAnyRegister(Reg); + if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) { + reportParseError("expected register containing global pointer"); + return false; + } + + MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]); + if (!RegOpnd.isGPRAsmReg()) { + reportParseError(RegOpnd.getStartLoc(), "invalid register"); + return false; + } + + // If this is not the end of the statement, report an error. + if (getLexer().isNot(AsmToken::EndOfStatement)) { + reportParseError("unexpected token, expected end of statement"); + return false; + } + getParser().Lex(); // Consume the EndOfStatement. + + unsigned NewReg = RegOpnd.getGPR32Reg(); + if (IsPicEnabled) + GPReg = NewReg; + + getTargetStreamer().emitDirectiveCpLocal(NewReg); + return false; +} + bool MipsAsmParser::parseDirectiveCpRestore(SMLoc Loc) { MCAsmParser &Parser = getParser(); @@ -7897,6 +8128,10 @@ bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) { parseDirectiveCpRestore(DirectiveID.getLoc()); return false; } + if (IDVal == ".cplocal") { + parseDirectiveCpLocal(DirectiveID.getLoc()); + return false; + } if (IDVal == ".ent") { StringRef SymbolName; |